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 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
38 #define GLINFO_LOCATION This->gl_info
40 /**********************************************************
41 * Utility functions follow
42 **********************************************************/
44 /* x11drv GDI escapes */
45 #define X11DRV_ESCAPE 6789
46 enum x11drv_escape_codes
48 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
49 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
50 X11DRV_GET_FONT, /* get current X font for a DC */
53 /* retrieve the X display to use on a given DC */
54 inline static Display *get_display( HDC hdc )
57 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
59 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
60 sizeof(display), (LPSTR)&display )) display = NULL;
65 int minLookup[MAX_LOOKUPS];
66 int maxLookup[MAX_LOOKUPS];
67 DWORD *stateLookup[MAX_LOOKUPS];
69 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
73 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
74 * ie there is no GL Context - Get a default rendering context to enable the
75 * function query some info from GL
78 static int wined3d_fake_gl_context_ref = 0;
79 static BOOL wined3d_fake_gl_context_foreign;
80 static BOOL wined3d_fake_gl_context_available = FALSE;
81 static Display* wined3d_fake_gl_context_display = NULL;
83 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
84 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
86 0, 0, &wined3d_fake_gl_context_cs,
87 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
88 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
89 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
91 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
93 static void WineD3D_ReleaseFakeGLContext(void) {
96 EnterCriticalSection(&wined3d_fake_gl_context_cs);
98 if(!wined3d_fake_gl_context_available) {
99 TRACE_(d3d_caps)("context not available\n");
100 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
104 glCtx = glXGetCurrentContext();
106 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
107 if (0 == (--wined3d_fake_gl_context_ref) ) {
108 if(!wined3d_fake_gl_context_foreign && glCtx) {
109 TRACE_(d3d_caps)("destroying fake GL context\n");
110 glXMakeCurrent(wined3d_fake_gl_context_display, None, NULL);
111 glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
113 wined3d_fake_gl_context_available = FALSE;
115 assert(wined3d_fake_gl_context_ref >= 0);
117 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
121 static BOOL WineD3D_CreateFakeGLContext(void) {
122 XVisualInfo* visInfo;
126 EnterCriticalSection(&wined3d_fake_gl_context_cs);
128 TRACE_(d3d_caps)("getting context...\n");
129 if(wined3d_fake_gl_context_ref > 0) goto ret;
130 assert(0 == wined3d_fake_gl_context_ref);
132 wined3d_fake_gl_context_foreign = TRUE;
134 if(!wined3d_fake_gl_context_display) {
135 HDC device_context = GetDC(0);
137 wined3d_fake_gl_context_display = get_display(device_context);
138 ReleaseDC(0, device_context);
142 glCtx = glXGetCurrentContext();
146 XVisualInfo template;
149 XWindowAttributes win_attr;
151 wined3d_fake_gl_context_foreign = FALSE;
152 drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
154 TRACE_(d3d_caps)("Creating Fake GL Context\n");
156 /* Get the X visual */
157 if (XGetWindowAttributes(wined3d_fake_gl_context_display, drawable, &win_attr)) {
158 visual = win_attr.visual;
160 visual = DefaultVisual(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display));
162 template.visualid = XVisualIDFromVisual(visual);
163 visInfo = XGetVisualInfo(wined3d_fake_gl_context_display, VisualIDMask, &template, &num);
165 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
169 /* Create a GL context */
170 glCtx = glXCreateContext(wined3d_fake_gl_context_display, visInfo, NULL, GL_TRUE);
172 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
176 /* Make it the current GL context */
177 if (!glXMakeCurrent(wined3d_fake_gl_context_display, drawable, glCtx)) {
178 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
187 TRACE_(d3d_caps)("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
188 wined3d_fake_gl_context_ref++;
189 wined3d_fake_gl_context_available = TRUE;
190 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
193 if(visInfo) XFree(visInfo);
194 if(glCtx) glXDestroyContext(wined3d_fake_gl_context_display, glCtx);
195 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
200 /**********************************************************
201 * IUnknown parts follows
202 **********************************************************/
204 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
208 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
209 if (IsEqualGUID(riid, &IID_IUnknown)
210 || IsEqualGUID(riid, &IID_IWineD3DBase)
211 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
212 IUnknown_AddRef(iface);
217 return E_NOINTERFACE;
220 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
221 IWineD3DImpl *This = (IWineD3DImpl *)iface;
222 ULONG refCount = InterlockedIncrement(&This->ref);
224 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
228 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
229 IWineD3DImpl *This = (IWineD3DImpl *)iface;
231 TRACE("(%p) : Releasing from %d\n", This, This->ref);
232 ref = InterlockedDecrement(&This->ref);
234 HeapFree(GetProcessHeap(), 0, This);
240 /* Set the shader type for this device, depending on the given capabilities,
241 * the device type, and the user preferences in wined3d_settings */
243 static void select_shader_mode(
244 WineD3D_GL_Info *gl_info,
245 WINED3DDEVTYPE DeviceType,
249 if (wined3d_settings.vs_mode == VS_NONE) {
250 *vs_selected = SHADER_NONE;
251 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
252 *vs_selected = SHADER_GLSL;
253 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
254 *vs_selected = SHADER_ARB;
256 *vs_selected = SHADER_NONE;
259 if (wined3d_settings.ps_mode == PS_NONE) {
260 *ps_selected = SHADER_NONE;
261 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
262 *ps_selected = SHADER_GLSL;
263 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
264 *ps_selected = SHADER_ARB;
266 *ps_selected = SHADER_NONE;
270 /** Select the number of report maximum shader constants based on the selected shader modes */
271 static void select_shader_max_constants(
272 int ps_selected_mode,
273 int vs_selected_mode,
274 WineD3D_GL_Info *gl_info) {
276 switch (vs_selected_mode) {
278 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
279 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
282 /* We have to subtract any other PARAMs that we might use in our shader programs.
283 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
284 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
285 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
288 gl_info->max_vshader_constantsF = 0;
292 switch (ps_selected_mode) {
294 /* Subtract the other potential uniforms from the max available (bools & ints).
295 * In theory the texbem instruction may need one more shader constant too. But lets assume
296 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
297 * and lets not take away a uniform needlessly from all other shaders.
299 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I;
302 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
303 * a free constant to do that, so no need to reduce the number of available constants.
305 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
308 gl_info->max_pshader_constantsF = 0;
313 /**********************************************************
314 * IWineD3D parts follows
315 **********************************************************/
317 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
318 IWineD3DImpl *This = (IWineD3DImpl *)iface;
319 WineD3D_GL_Info *gl_info = &This->gl_info;
321 const char *GL_Extensions = NULL;
322 const char *GLX_Extensions = NULL;
323 const char *gl_string = NULL;
324 const char *gl_string_cursor = NULL;
326 GLfloat gl_floatv[2];
329 BOOL return_value = TRUE;
332 /* Make sure that we've got a context */
333 /* TODO: CreateFakeGLContext should really take a display as a parameter */
334 /* Only save the values obtained when a display is provided */
335 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
336 return_value = FALSE;
338 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
340 gl_string = (const char *) glGetString(GL_RENDERER);
341 if (NULL == gl_string)
343 strcpy(gl_info->gl_renderer, gl_string);
345 /* Fill in the GL info retrievable depending on the display */
346 if (NULL != display) {
347 test = glXQueryVersion(display, &major, &minor);
348 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
350 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
352 gl_string = (const char *) glGetString(GL_VENDOR);
354 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
355 if (gl_string != NULL) {
356 /* Fill in the GL vendor */
357 if (strstr(gl_string, "NVIDIA")) {
358 gl_info->gl_vendor = VENDOR_NVIDIA;
359 } else if (strstr(gl_string, "ATI")) {
360 gl_info->gl_vendor = VENDOR_ATI;
361 } else if (strstr(gl_string, "Intel(R)") ||
362 strstr(gl_info->gl_renderer, "Intel(R)")) {
363 gl_info->gl_vendor = VENDOR_INTEL;
364 } else if (strstr(gl_string, "Mesa")) {
365 gl_info->gl_vendor = VENDOR_MESA;
367 gl_info->gl_vendor = VENDOR_WINE;
370 gl_info->gl_vendor = VENDOR_WINE;
374 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
376 /* Parse the GL_VERSION field into major and minor information */
377 gl_string = (const char *) glGetString(GL_VERSION);
378 if (gl_string != NULL) {
380 switch (gl_info->gl_vendor) {
382 gl_string_cursor = strstr(gl_string, "NVIDIA");
383 if (!gl_string_cursor) {
384 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
388 gl_string_cursor = strstr(gl_string_cursor, " ");
389 if (!gl_string_cursor) {
390 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
394 while (*gl_string_cursor == ' ') {
398 if (!*gl_string_cursor) {
399 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
403 major = atoi(gl_string_cursor);
404 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
408 if (*gl_string_cursor++ != '.') {
409 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
413 minor = atoi(gl_string_cursor);
414 minor = major*100+minor;
421 gl_string_cursor = strchr(gl_string, '-');
422 if (gl_string_cursor) {
426 /* Check if version number is of the form x.y.z */
427 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
429 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
431 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
433 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
436 /* Mark version number as malformed */
438 gl_string_cursor = 0;
441 if (!gl_string_cursor)
442 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
444 major = *gl_string_cursor - '0';
445 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
451 gl_string_cursor = strstr(gl_string, "Mesa");
452 gl_string_cursor = strstr(gl_string_cursor, " ");
453 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
454 if (*gl_string_cursor) {
458 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
459 tmp[cursor++] = *gl_string_cursor;
465 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
469 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
470 tmp[cursor++] = *gl_string_cursor;
482 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
483 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
486 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
489 * Initialize openGL extension related variables
490 * with Default values
492 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
493 gl_info->max_buffers = 1;
494 gl_info->max_textures = 1;
495 gl_info->max_texture_stages = 1;
496 gl_info->max_samplers = 1;
497 gl_info->max_sampler_stages = 1;
498 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
499 gl_info->ps_arb_max_temps = 0;
500 gl_info->ps_arb_max_instructions = 0;
501 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
502 gl_info->vs_arb_max_temps = 0;
503 gl_info->vs_arb_max_instructions = 0;
504 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
505 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
506 gl_info->vs_glsl_constantsF = 0;
507 gl_info->ps_glsl_constantsF = 0;
508 gl_info->vs_arb_constantsF = 0;
509 gl_info->ps_arb_constantsF = 0;
511 /* Now work out what GL support this card really has */
512 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
517 /* Retrieve opengl defaults */
518 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
519 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
520 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
522 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
523 gl_info->max_lights = gl_max;
524 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
526 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
527 gl_info->max_texture_size = gl_max;
528 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
530 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
531 gl_info->max_pointsize = gl_floatv[1];
532 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
534 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
535 gl_info->max_aux_buffers = gl_max;
536 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
538 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
539 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
540 TRACE_(d3d_caps)("GL_Extensions reported:\n");
542 if (NULL == GL_Extensions) {
543 ERR(" GL_Extensions returns NULL\n");
545 while (*GL_Extensions != 0x00) {
546 const char *Start = GL_Extensions;
549 memset(ThisExtn, 0x00, sizeof(ThisExtn));
550 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
553 memcpy(ThisExtn, Start, (GL_Extensions - Start));
554 TRACE_(d3d_caps)("- %s\n", ThisExtn);
559 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
560 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
561 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
562 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
563 gl_info->max_buffers = gl_max;
564 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
565 gl_info->ps_arb_version = PS_VERSION_11;
566 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
567 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
568 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
569 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
570 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
571 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
572 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
573 gl_info->ps_arb_constantsF = gl_max;
574 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
575 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
576 gl_info->ps_arb_max_temps = gl_max;
577 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
578 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
579 gl_info->ps_arb_max_instructions = gl_max;
580 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
581 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
582 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
584 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
585 gl_info->ps_glsl_constantsF = gl_max;
586 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
587 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
588 gl_info->supported[ARB_IMAGING] = TRUE;
589 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
590 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
591 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
592 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
593 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
594 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
595 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
596 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
597 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
598 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
599 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
600 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
601 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
602 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
603 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
604 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
605 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
606 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
607 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
608 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
609 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
610 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
611 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
612 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
613 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
614 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
615 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
616 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
617 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
618 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
619 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
620 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
621 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
622 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
623 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
624 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
625 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
626 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
627 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
628 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
629 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
630 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
631 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
632 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
633 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
634 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
635 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
636 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
637 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
638 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
639 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
640 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
641 gl_info->vs_arb_version = VS_VERSION_11;
642 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
643 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
644 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
645 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
646 gl_info->vs_arb_constantsF = gl_max;
647 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
648 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
649 gl_info->vs_arb_max_temps = gl_max;
650 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
651 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
652 gl_info->vs_arb_max_instructions = gl_max;
653 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
654 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
655 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
657 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
658 gl_info->vs_glsl_constantsF = gl_max;
659 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
660 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
661 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
662 gl_info->max_blends = gl_max;
663 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
664 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
665 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
666 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
667 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
668 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
669 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
670 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
671 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
672 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
676 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
678 gl_info->supported[EXT_FOG_COORD] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
681 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
683 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
684 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
686 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
687 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
688 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
689 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
690 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
691 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
692 TRACE_(d3d_caps)(" FOUND: EXT Secondary color support\n");
693 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
694 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
695 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
696 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
698 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
699 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
701 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
702 gl_info->supported[EXT_TEXTURE3D] = TRUE;
703 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
704 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
705 gl_info->max_texture3d_size = gl_max;
706 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
707 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
708 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
709 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
710 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
711 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
713 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
714 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
716 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
717 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
718 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
719 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
720 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
721 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
722 gl_info->max_anisotropy = gl_max;
723 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
724 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
725 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
726 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
727 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
728 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
729 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
730 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
731 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
736 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
737 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
738 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
739 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
740 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
741 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
742 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
743 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
744 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
745 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
746 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
747 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
748 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
749 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
750 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
751 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
752 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
753 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
754 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
755 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
756 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
757 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
758 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
759 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
760 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
761 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
762 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
763 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
764 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
765 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
766 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
767 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
768 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
769 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
770 gl_info->vs_nv_version = VS_VERSION_30;
771 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
772 gl_info->vs_nv_version = VS_VERSION_20;
773 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
774 gl_info->vs_nv_version = VS_VERSION_11;
776 gl_info->vs_nv_version = VS_VERSION_10;
777 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
778 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
779 } else if (strstr(ThisExtn, "GL_NV_fence")) {
780 if(!gl_info->supported[APPLE_FENCE]) {
781 gl_info->supported[NV_FENCE] = TRUE;
788 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
789 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
790 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
791 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
792 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
793 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
794 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
795 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
796 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
797 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
798 gl_info->vs_ati_version = VS_VERSION_11;
799 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
800 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
804 } else if (strstr(ThisExtn, "GL_APPLE_fence")) {
805 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
806 * The apple extension interacts with some other apple exts. Disable the NV
807 * extension if the apple one is support to prevent confusion in other parts
810 gl_info->supported[NV_FENCE] = FALSE;
811 gl_info->supported[APPLE_FENCE] = TRUE;
814 if (*GL_Extensions == ' ') GL_Extensions++;
817 checkGLcall("extension detection\n");
819 /* In some cases the number of texture stages can be larger than the number
820 * of samplers. The GF4 for example can use only 2 samplers (no fragment
821 * shaders), but 8 texture stages (register combiners). */
822 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
824 /* We can only use ORM_FBO when the hardware supports it. */
825 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
826 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
827 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
830 /* MRTs are currently only supported when FBOs are used. */
831 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
832 gl_info->max_buffers = 1;
835 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
836 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
837 * in case of the latest videocards in the number of pixel/vertex pipelines.
839 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
840 * rendering. Various games use this information to get a rough estimation of the features of the card
841 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
842 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
843 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
846 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
847 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
848 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
849 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
850 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
851 * is used for rendering which is not always the case). This would work but it is not very portable. Second
852 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
855 * As said most games only use the PCI id to get an indication of the capabilities of the card.
856 * It doesn't really matter if the given id is the correct one if we return the id of a card with
857 * similar 3d features.
859 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
860 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
861 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
862 * won't pass we return a default card. This way is better than maintaining a full card database as even
863 * without a full database we can return a card with similar features. Second the size of the database
864 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
865 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
866 * to distinguishes between different models from that family.
868 switch (gl_info->gl_vendor) {
870 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
871 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
873 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
874 if (strstr(gl_info->gl_renderer, "7800") ||
875 strstr(gl_info->gl_renderer, "7900") ||
876 strstr(gl_info->gl_renderer, "7950") ||
877 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
878 strstr(gl_info->gl_renderer, "Quadro FX 5"))
879 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
880 else if(strstr(gl_info->gl_renderer, "6800") ||
881 strstr(gl_info->gl_renderer, "7600"))
882 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
883 else if(strstr(gl_info->gl_renderer, "6600") ||
884 strstr(gl_info->gl_renderer, "6610") ||
885 strstr(gl_info->gl_renderer, "6700"))
886 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
888 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
889 } else if(WINE_D3D9_CAPABLE(gl_info)) {
890 if (strstr(gl_info->gl_renderer, "5800") ||
891 strstr(gl_info->gl_renderer, "5900") ||
892 strstr(gl_info->gl_renderer, "5950") ||
893 strstr(gl_info->gl_renderer, "Quadro FX"))
894 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
895 else if(strstr(gl_info->gl_renderer, "5600") ||
896 strstr(gl_info->gl_renderer, "5650") ||
897 strstr(gl_info->gl_renderer, "5700") ||
898 strstr(gl_info->gl_renderer, "5750"))
899 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
901 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
902 } else if(WINE_D3D8_CAPABLE(gl_info)) {
903 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
904 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
906 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
907 } else if(WINE_D3D7_CAPABLE(gl_info)) {
908 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
909 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
910 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
911 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
912 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
913 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
915 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
917 if (strstr(gl_info->gl_renderer, "TNT2"))
918 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
920 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
924 if(WINE_D3D9_CAPABLE(gl_info)) {
926 if (strstr(gl_info->gl_renderer, "X1600") ||
927 strstr(gl_info->gl_renderer, "X1800") ||
928 strstr(gl_info->gl_renderer, "X1900") ||
929 strstr(gl_info->gl_renderer, "X1950"))
930 gl_info->gl_card = CARD_ATI_RADEON_X1600;
931 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
932 else if(strstr(gl_info->gl_renderer, "X700") ||
933 strstr(gl_info->gl_renderer, "X800") ||
934 strstr(gl_info->gl_renderer, "X850") ||
935 strstr(gl_info->gl_renderer, "X1300") ||
936 strstr(gl_info->gl_renderer, "X1400"))
937 gl_info->gl_card = CARD_ATI_RADEON_X700;
940 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
941 } else if(WINE_D3D8_CAPABLE(gl_info)) {
942 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
943 } else if(WINE_D3D7_CAPABLE(gl_info)) {
944 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
946 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
949 if (strstr(gl_info->gl_renderer, "915GM")) {
950 gl_info->gl_card = CARD_INTEL_I915GM;
951 } else if (strstr(gl_info->gl_renderer, "915G")) {
952 gl_info->gl_card = CARD_INTEL_I915G;
953 } else if (strstr(gl_info->gl_renderer, "865G")) {
954 gl_info->gl_card = CARD_INTEL_I865G;
955 } else if (strstr(gl_info->gl_renderer, "855G")) {
956 gl_info->gl_card = CARD_INTEL_I855G;
957 } else if (strstr(gl_info->gl_renderer, "830G")) {
958 gl_info->gl_card = CARD_INTEL_I830G;
960 gl_info->gl_card = CARD_INTEL_I915G;
966 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
967 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
968 * them a good generic choice.
970 gl_info->gl_vendor = VENDOR_NVIDIA;
971 if(WINE_D3D9_CAPABLE(gl_info))
972 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
973 else if(WINE_D3D8_CAPABLE(gl_info))
974 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
975 else if(WINE_D3D7_CAPABLE(gl_info))
976 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
977 else if(WINE_D3D6_CAPABLE(gl_info))
978 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
980 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
982 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
984 /* Load all the lookup tables
985 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
986 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
987 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
989 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
990 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
993 for (i = 0; i < MAX_LOOKUPS; i++) {
994 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
997 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
998 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
999 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1000 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1001 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1002 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1003 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1004 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1005 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1006 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1008 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1009 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1010 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1011 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1012 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1015 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1016 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1017 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1018 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1019 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1020 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1021 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1022 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1023 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1024 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1025 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1026 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1027 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1029 /* TODO: config lookups */
1031 if (display != NULL) {
1032 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
1033 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
1035 if (NULL == GLX_Extensions) {
1036 ERR(" GLX_Extensions returns NULL\n");
1038 while (*GLX_Extensions != 0x00) {
1039 const char *Start = GLX_Extensions;
1042 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1043 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
1046 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
1047 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1048 if (*GLX_Extensions == ' ') GLX_Extensions++;
1054 WineD3D_ReleaseFakeGLContext();
1055 return return_value;
1058 /**********************************************************
1059 * IWineD3D implementation follows
1060 **********************************************************/
1062 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1063 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1065 /* FIXME: Set to one for now to imply the display */
1066 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1070 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1071 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1072 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1076 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1077 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1078 POINT pt = { -1, -1 };
1080 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1084 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1085 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1088 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1089 of the same bpp but different resolutions */
1091 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1092 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1093 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1094 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1096 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1100 if (Adapter == 0) { /* Display */
1104 if (!DEBUG_SINGLE_MODE) {
1107 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1111 case WINED3DFMT_UNKNOWN:
1112 if (DevModeW.dmBitsPerPel == 32 ||
1113 DevModeW.dmBitsPerPel == 16) i++;
1115 case WINED3DFMT_X8R8G8B8:
1116 if (DevModeW.dmBitsPerPel == 32) i++;
1118 case WINED3DFMT_R5G6B5:
1119 if (DevModeW.dmBitsPerPel == 16) i++;
1122 /* Skip other modes as they do not match the requested format */
1131 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1134 FIXME_(d3d_caps)("Adapter not primary display\n");
1139 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1140 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1141 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1142 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1144 /* Validate the parameters as much as possible */
1145 if (NULL == pMode ||
1146 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1147 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1148 return WINED3DERR_INVALIDCALL;
1151 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1157 /* If we are filtering to a specific format (D3D9), then need to skip
1158 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1159 just count through the ones with valid bit depths */
1160 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1163 case WINED3DFMT_UNKNOWN:
1164 if (DevModeW.dmBitsPerPel == 32 ||
1165 DevModeW.dmBitsPerPel == 16) i++;
1167 case WINED3DFMT_X8R8G8B8:
1168 if (DevModeW.dmBitsPerPel == 32) i++;
1170 case WINED3DFMT_R5G6B5:
1171 if (DevModeW.dmBitsPerPel == 16) i++;
1174 /* Modes that don't match what we support can get an early-out */
1175 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1176 return WINED3DERR_INVALIDCALL;
1181 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1182 return WINED3DERR_INVALIDCALL;
1186 /* Now get the display mode via the calculated index */
1187 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1188 pMode->Width = DevModeW.dmPelsWidth;
1189 pMode->Height = DevModeW.dmPelsHeight;
1190 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1191 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1192 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1194 if (Format == WINED3DFMT_UNKNOWN)
1196 switch (DevModeW.dmBitsPerPel)
1199 pMode->Format = WINED3DFMT_R5G6B5;
1202 pMode->Format = WINED3DFMT_X8R8G8B8;
1205 pMode->Format = WINED3DFMT_UNKNOWN;
1206 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1209 pMode->Format = Format;
1212 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1213 return WINED3DERR_INVALIDCALL;
1216 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1217 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1218 DevModeW.dmBitsPerPel);
1220 } else if (DEBUG_SINGLE_MODE) {
1221 /* Return one setting of the format requested */
1222 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1224 pMode->Height = 600;
1225 pMode->RefreshRate = 60;
1226 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1228 FIXME_(d3d_caps)("Adapter not primary display\n");
1234 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1235 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1236 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1238 if (NULL == pMode ||
1239 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1240 return WINED3DERR_INVALIDCALL;
1243 if (Adapter == 0) { /* Display */
1247 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1248 pMode->Width = DevModeW.dmPelsWidth;
1249 pMode->Height = DevModeW.dmPelsHeight;
1250 bpp = DevModeW.dmBitsPerPel;
1251 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1252 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1254 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1258 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1259 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1260 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1261 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1262 default: pMode->Format = WINED3DFMT_UNKNOWN;
1266 FIXME_(d3d_caps)("Adapter not primary display\n");
1269 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1270 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1274 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1277 /* only works with one adapter at the moment... */
1279 /* Get the display */
1280 device_context = GetDC(0);
1281 display = get_display(device_context);
1282 ReleaseDC(0, device_context);
1286 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1287 and fields being inserted in the middle, a new structure is used in place */
1288 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1289 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1290 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1292 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1294 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1295 return WINED3DERR_INVALIDCALL;
1298 if (Adapter == 0) { /* Display - only device supported for now */
1300 BOOL isGLInfoValid = This->isGLInfoValid;
1302 /* FillGLCaps updates gl_info, but we only want to store and
1303 reuse the values once we have a context which is valid. Values from
1304 a temporary context may differ from the final ones */
1305 if (!isGLInfoValid) {
1306 /* If we don't know the device settings, go query them now */
1307 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1310 /* If it worked, return the information requested */
1311 if (isGLInfoValid) {
1312 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1313 strcpy(pIdentifier->Driver, "Display");
1314 strcpy(pIdentifier->Description, "Direct3D HAL");
1316 /* Note dx8 doesn't supply a DeviceName */
1317 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1318 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1319 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1320 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1321 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1322 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1323 *(pIdentifier->SubSysId) = 0;
1324 *(pIdentifier->Revision) = 0;
1328 /* If it failed, return dummy values from an NVidia driver */
1329 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1330 strcpy(pIdentifier->Driver, "Display");
1331 strcpy(pIdentifier->Description, "Direct3D HAL");
1332 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1333 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1334 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1335 /* 71.74 is a current Linux Nvidia driver version */
1336 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1337 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1338 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1339 *(pIdentifier->SubSysId) = 0;
1340 *(pIdentifier->Revision) = 0;
1343 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1344 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1345 *(pIdentifier->WHQLLevel) = 0;
1347 *(pIdentifier->WHQLLevel) = 1;
1351 FIXME_(d3d_caps)("Adapter not primary display\n");
1357 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1358 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1360 int rb, gb, bb, ab, type, buf_sz;
1362 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1363 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1364 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1365 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1366 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1367 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1370 case WINED3DFMT_X8R8G8B8:
1371 case WINED3DFMT_R8G8B8:
1372 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1374 case WINED3DFMT_A8R8G8B8:
1375 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1377 case WINED3DFMT_A2R10G10B10:
1378 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1380 case WINED3DFMT_X1R5G5B5:
1381 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1383 case WINED3DFMT_A1R5G5B5:
1384 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1386 case WINED3DFMT_X4R4G4B4:
1387 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1389 case WINED3DFMT_R5G6B5:
1390 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1392 case WINED3DFMT_R3G3B2:
1393 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1395 case WINED3DFMT_A8P8:
1396 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1399 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1405 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1407 case WINED3DFMT_X8R8G8B8:
1408 case WINED3DFMT_R8G8B8:
1409 case WINED3DFMT_A8R8G8B8:
1410 case WINED3DFMT_A2R10G10B10:
1411 case WINED3DFMT_X1R5G5B5:
1412 case WINED3DFMT_A1R5G5B5:
1413 case WINED3DFMT_R5G6B5:
1414 case WINED3DFMT_R3G3B2:
1415 case WINED3DFMT_A8P8:
1425 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display *display, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1426 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1430 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1431 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1434 case WINED3DFMT_D16:
1435 case WINED3DFMT_D16_LOCKABLE:
1436 if (16 == db) return TRUE;
1438 case WINED3DFMT_D32:
1439 if (32 == db) return TRUE;
1441 case WINED3DFMT_D15S1:
1442 if (15 == db) return TRUE;
1444 case WINED3DFMT_D24S8:
1445 if (24 == db && 8 == sb) return TRUE;
1447 case WINED3DFMT_D24FS8:
1448 if (24 == db && 8 == sb) return TRUE;
1450 case WINED3DFMT_D24X8:
1451 if (24 == db) return TRUE;
1453 case WINED3DFMT_D24X4S4:
1454 if (24 == db && 4 == sb) return TRUE;
1456 case WINED3DFMT_D32F_LOCKABLE:
1457 if (32 == db) return TRUE;
1463 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1465 case WINED3DFMT_D16:
1466 case WINED3DFMT_D16_LOCKABLE:
1467 case WINED3DFMT_D32:
1468 case WINED3DFMT_D15S1:
1469 case WINED3DFMT_D24S8:
1470 case WINED3DFMT_D24FS8:
1471 case WINED3DFMT_D24X8:
1472 case WINED3DFMT_D24X4S4:
1473 case WINED3DFMT_D32F_LOCKABLE:
1482 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1483 WINED3DFORMAT AdapterFormat,
1484 WINED3DFORMAT RenderTargetFormat,
1485 WINED3DFORMAT DepthStencilFormat) {
1486 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1487 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1488 GLXFBConfig* cfgs = NULL;
1492 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1494 DeviceType, debug_d3ddevicetype(DeviceType),
1495 AdapterFormat, debug_d3dformat(AdapterFormat),
1496 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1497 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1499 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1500 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1501 return WINED3DERR_INVALIDCALL;
1504 if(WineD3D_CreateFakeGLContext())
1505 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1508 for (it = 0; it < nCfgs; ++it) {
1509 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], RenderTargetFormat)) {
1510 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(wined3d_fake_gl_context_display, cfgs[it], DepthStencilFormat)) {
1517 if(hr != WINED3D_OK)
1518 ERR("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1520 ERR_(d3d_caps)("returning WINED3D_OK even so CreateFakeGLContext or glXGetFBConfigs failed\n");
1524 WineD3D_ReleaseFakeGLContext();
1526 if (hr != WINED3D_OK)
1527 TRACE_(d3d_caps)("Failed to match stencil format to device\n");
1529 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1533 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1534 WINED3DFORMAT SurfaceFormat,
1535 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1537 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1538 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1541 DeviceType, debug_d3ddevicetype(DeviceType),
1542 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1547 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1548 return WINED3DERR_INVALIDCALL;
1551 if (pQualityLevels != NULL) {
1552 static int s_single_shot = 0;
1553 if (!s_single_shot) {
1554 FIXME("Quality levels unsupported at present\n");
1557 *pQualityLevels = 1; /* Guess at a value! */
1560 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1561 return WINED3DERR_NOTAVAILABLE;
1564 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1565 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1567 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1568 GLXFBConfig* cfgs = NULL;
1571 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1573 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1576 CheckType, debug_d3ddevicetype(CheckType),
1577 DisplayFormat, debug_d3dformat(DisplayFormat),
1578 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1581 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1582 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1583 return WINED3DERR_INVALIDCALL;
1586 if (WineD3D_CreateFakeGLContext()) {
1587 cfgs = glXGetFBConfigs(wined3d_fake_gl_context_display, DefaultScreen(wined3d_fake_gl_context_display), &nCfgs);
1588 for (it = 0; it < nCfgs; ++it) {
1589 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display, cfgs[it], DisplayFormat)) {
1591 TRACE_(d3d_caps)("OK\n");
1595 if(cfgs) XFree(cfgs);
1596 if(hr != WINED3D_OK)
1597 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1598 WineD3D_ReleaseFakeGLContext();
1601 if(hr != WINED3D_OK)
1602 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1607 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1608 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1609 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1610 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1613 DeviceType, debug_d3ddevicetype(DeviceType),
1614 AdapterFormat, debug_d3dformat(AdapterFormat),
1615 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1616 RType, debug_d3dresourcetype(RType),
1617 CheckFormat, debug_d3dformat(CheckFormat));
1619 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1620 return WINED3DERR_INVALIDCALL;
1623 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1624 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1625 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1626 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1627 TRACE_(d3d_caps)("[FAILED]\n");
1628 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1631 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1632 switch (CheckFormat) {
1633 case WINED3DFMT_D16_LOCKABLE:
1634 case WINED3DFMT_D32:
1635 case WINED3DFMT_D15S1:
1636 case WINED3DFMT_D24S8:
1637 case WINED3DFMT_D24X8:
1638 case WINED3DFMT_D24X4S4:
1639 case WINED3DFMT_D16:
1640 case WINED3DFMT_L16:
1641 case WINED3DFMT_D32F_LOCKABLE:
1642 case WINED3DFMT_D24FS8:
1643 TRACE_(d3d_caps)("[OK]\n");
1646 TRACE_(d3d_caps)("[FAILED]\n");
1647 return WINED3DERR_NOTAVAILABLE;
1649 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1650 switch (CheckFormat) {
1651 case WINED3DFMT_R8G8B8:
1652 case WINED3DFMT_A8R8G8B8:
1653 case WINED3DFMT_X8R8G8B8:
1654 case WINED3DFMT_R5G6B5:
1655 case WINED3DFMT_X1R5G5B5:
1656 case WINED3DFMT_A1R5G5B5:
1657 case WINED3DFMT_A4R4G4B4:
1658 case WINED3DFMT_R3G3B2:
1659 case WINED3DFMT_X4R4G4B4:
1660 case WINED3DFMT_A8B8G8R8:
1661 case WINED3DFMT_X8B8G8R8:
1663 TRACE_(d3d_caps)("[OK]\n");
1666 TRACE_(d3d_caps)("[FAILED]\n");
1667 return WINED3DERR_NOTAVAILABLE;
1671 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1672 switch (CheckFormat) {
1673 case WINED3DFMT_DXT1:
1674 case WINED3DFMT_DXT2:
1675 case WINED3DFMT_DXT3:
1676 case WINED3DFMT_DXT4:
1677 case WINED3DFMT_DXT5:
1678 TRACE_(d3d_caps)("[OK]\n");
1681 break; /* Avoid compiler warnings */
1685 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1687 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1689 switch (CheckFormat) {
1690 case WINED3DFMT_R16F:
1691 case WINED3DFMT_A16B16G16R16F:
1692 if (!half_pixel_support) break;
1693 case WINED3DFMT_R32F:
1694 case WINED3DFMT_A32B32G32R32F:
1695 TRACE_(d3d_caps)("[OK]\n");
1698 break; /* Avoid compiler warnings */
1702 /* This format is nothing special and it is supported perfectly.
1703 * However, ati and nvidia driver on windows do not mark this format as
1704 * supported (tested with the dxCapsViewer) and pretending to
1705 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1706 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1707 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1709 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1710 TRACE_(d3d_caps)("[FAILED]\n");
1711 return WINED3DERR_NOTAVAILABLE;
1714 switch (CheckFormat) {
1717 * supported: RGB(A) formats
1719 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1720 case WINED3DFMT_A8R8G8B8:
1721 case WINED3DFMT_X8R8G8B8:
1722 case WINED3DFMT_R5G6B5:
1723 case WINED3DFMT_X1R5G5B5:
1724 case WINED3DFMT_A1R5G5B5:
1725 case WINED3DFMT_A4R4G4B4:
1726 case WINED3DFMT_R3G3B2:
1728 case WINED3DFMT_A8R3G3B2:
1729 case WINED3DFMT_X4R4G4B4:
1730 case WINED3DFMT_A8B8G8R8:
1731 case WINED3DFMT_X8B8G8R8:
1732 case WINED3DFMT_A2R10G10B10:
1733 case WINED3DFMT_A2B10G10R10:
1734 TRACE_(d3d_caps)("[OK]\n");
1738 * supported: Palettized
1741 TRACE_(d3d_caps)("[OK]\n");
1745 * Supported: (Alpha)-Luminance
1748 case WINED3DFMT_A8L8:
1749 case WINED3DFMT_A4L4:
1750 TRACE_(d3d_caps)("[OK]\n");
1754 * Not supported for now: Bump mapping formats
1755 * Enable some because games often fail when they are not available
1756 * and are still playable even without bump mapping
1758 case WINED3DFMT_V8U8:
1759 case WINED3DFMT_V16U16:
1760 case WINED3DFMT_L6V5U5:
1761 case WINED3DFMT_X8L8V8U8:
1762 case WINED3DFMT_Q8W8V8U8:
1763 case WINED3DFMT_W11V11U10:
1764 case WINED3DFMT_A2W10V10U10:
1765 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1769 * DXTN Formats: Handled above
1778 * Odd formats - not supported
1780 case WINED3DFMT_VERTEXDATA:
1781 case WINED3DFMT_INDEX16:
1782 case WINED3DFMT_INDEX32:
1783 case WINED3DFMT_Q16W16V16U16:
1784 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1785 return WINED3DERR_NOTAVAILABLE;
1788 * Float formats: Not supported right now
1790 case WINED3DFMT_G16R16F:
1791 case WINED3DFMT_G32R32F:
1792 case WINED3DFMT_CxV8U8:
1793 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1794 return WINED3DERR_NOTAVAILABLE;
1797 case WINED3DFMT_G16R16:
1798 case WINED3DFMT_A16B16G16R16:
1799 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1800 return WINED3DERR_NOTAVAILABLE;
1802 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1803 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1804 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1805 * We can do instancing with all shader versions, but we need vertex shaders.
1807 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1808 * to enable instancing. WineD3D doesn't need that and just ignores it.
1810 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1812 case MAKEFOURCC('I','N','S','T'):
1813 TRACE("ATI Instancing check hack\n");
1814 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1815 TRACE_(d3d_caps)("[OK]\n");
1818 TRACE_(d3d_caps)("[FAILED]\n");
1819 return WINED3DERR_NOTAVAILABLE;
1826 TRACE_(d3d_caps)("[FAILED]\n");
1827 return WINED3DERR_NOTAVAILABLE;
1830 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1831 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1832 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1834 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1837 DeviceType, debug_d3ddevicetype(DeviceType),
1838 SourceFormat, debug_d3dformat(SourceFormat),
1839 TargetFormat, debug_d3dformat(TargetFormat));
1843 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1844 subset of a D3DCAPS9 structure. However, it has to come via a void *
1845 as the d3d8 interface cannot import the d3d9 header */
1846 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1848 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1849 int vs_selected_mode;
1850 int ps_selected_mode;
1852 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1854 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1855 return WINED3DERR_INVALIDCALL;
1858 /* FIXME: GL info should be per adapter */
1860 /* If we don't know the device settings, go query them now */
1861 if (!This->isGLInfoValid) {
1862 /* use the desktop window to fill gl caps */
1863 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1865 /* We are running off a real context, save the values */
1866 if (rc) This->isGLInfoValid = TRUE;
1868 select_shader_mode(&This->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1870 /* This function should *not* be modifying GL caps
1871 * TODO: move the functionality where it belongs */
1872 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &This->gl_info);
1874 /* ------------------------------------------------
1875 The following fields apply to both d3d8 and d3d9
1876 ------------------------------------------------ */
1877 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1878 *pCaps->AdapterOrdinal = Adapter;
1881 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1882 WINED3DCAPS2_FULLSCREENGAMMA |
1883 WINED3DCAPS2_DYNAMICTEXTURES;
1885 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1887 *pCaps->CursorCaps = 0;
1890 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1891 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1892 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1893 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1894 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1895 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1896 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1897 WINED3DDEVCAPS_PUREDEVICE |
1898 WINED3DDEVCAPS_HWRASTERIZATION |
1899 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1900 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1901 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1902 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1903 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1905 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1906 WINED3DPMISCCAPS_CULLCCW |
1907 WINED3DPMISCCAPS_CULLCW |
1908 WINED3DPMISCCAPS_COLORWRITEENABLE |
1909 WINED3DPMISCCAPS_CLIPTLVERTS |
1910 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1911 WINED3DPMISCCAPS_MASKZ |
1912 WINED3DPMISCCAPS_BLENDOP;
1914 WINED3DPMISCCAPS_NULLREFERENCE
1915 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1916 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1917 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1918 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1919 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1920 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1922 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1924 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1925 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1926 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1927 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1930 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1931 WINED3DPRASTERCAPS_PAT |
1932 WINED3DPRASTERCAPS_WFOG |
1933 WINED3DPRASTERCAPS_ZFOG |
1934 WINED3DPRASTERCAPS_FOGVERTEX |
1935 WINED3DPRASTERCAPS_FOGTABLE |
1936 WINED3DPRASTERCAPS_FOGRANGE |
1937 WINED3DPRASTERCAPS_STIPPLE |
1938 WINED3DPRASTERCAPS_SUBPIXEL |
1939 WINED3DPRASTERCAPS_ZTEST |
1940 WINED3DPRASTERCAPS_SCISSORTEST |
1941 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1942 WINED3DPRASTERCAPS_DEPTHBIAS;
1944 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1945 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1946 WINED3DPRASTERCAPS_ZBIAS |
1947 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1950 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1951 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1952 WINED3DPRASTERCAPS_ANTIALIASEDGES
1953 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1954 WINED3DPRASTERCAPS_WBUFFER */
1956 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1957 WINED3DPCMPCAPS_EQUAL |
1958 WINED3DPCMPCAPS_GREATER |
1959 WINED3DPCMPCAPS_GREATEREQUAL |
1960 WINED3DPCMPCAPS_LESS |
1961 WINED3DPCMPCAPS_LESSEQUAL |
1962 WINED3DPCMPCAPS_NEVER |
1963 WINED3DPCMPCAPS_NOTEQUAL;
1965 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1966 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1967 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1968 WINED3DPBLENDCAPS_DESTALPHA |
1969 WINED3DPBLENDCAPS_DESTCOLOR |
1970 WINED3DPBLENDCAPS_INVDESTALPHA |
1971 WINED3DPBLENDCAPS_INVDESTCOLOR |
1972 WINED3DPBLENDCAPS_INVSRCALPHA |
1973 WINED3DPBLENDCAPS_INVSRCCOLOR |
1974 WINED3DPBLENDCAPS_ONE |
1975 WINED3DPBLENDCAPS_SRCALPHA |
1976 WINED3DPBLENDCAPS_SRCALPHASAT |
1977 WINED3DPBLENDCAPS_SRCCOLOR |
1978 WINED3DPBLENDCAPS_ZERO;
1980 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1981 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1982 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1983 WINED3DPBLENDCAPS_DESTALPHA |
1984 WINED3DPBLENDCAPS_DESTCOLOR |
1985 WINED3DPBLENDCAPS_INVDESTALPHA |
1986 WINED3DPBLENDCAPS_INVDESTCOLOR |
1987 WINED3DPBLENDCAPS_INVSRCALPHA |
1988 WINED3DPBLENDCAPS_INVSRCCOLOR |
1989 WINED3DPBLENDCAPS_ONE |
1990 WINED3DPBLENDCAPS_SRCALPHA |
1991 WINED3DPBLENDCAPS_SRCALPHASAT |
1992 WINED3DPBLENDCAPS_SRCCOLOR |
1993 WINED3DPBLENDCAPS_ZERO;
1995 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1996 WINED3DPCMPCAPS_EQUAL |
1997 WINED3DPCMPCAPS_GREATER |
1998 WINED3DPCMPCAPS_GREATEREQUAL |
1999 WINED3DPCMPCAPS_LESS |
2000 WINED3DPCMPCAPS_LESSEQUAL |
2001 WINED3DPCMPCAPS_NEVER |
2002 WINED3DPCMPCAPS_NOTEQUAL;
2004 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2005 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2006 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2007 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2008 WINED3DPSHADECAPS_COLORFLATRGB |
2009 WINED3DPSHADECAPS_FOGFLAT |
2010 WINED3DPSHADECAPS_FOGGOURAUD |
2011 WINED3DPSHADECAPS_SPECULARFLATRGB;
2013 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2014 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2015 WINED3DPTEXTURECAPS_BORDER |
2016 WINED3DPTEXTURECAPS_MIPMAP |
2017 WINED3DPTEXTURECAPS_PROJECTED |
2018 WINED3DPTEXTURECAPS_PERSPECTIVE |
2019 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2021 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2022 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2023 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2024 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2027 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2028 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2029 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2030 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2034 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2035 WINED3DPTFILTERCAPS_MAGFPOINT |
2036 WINED3DPTFILTERCAPS_MINFLINEAR |
2037 WINED3DPTFILTERCAPS_MINFPOINT |
2038 WINED3DPTFILTERCAPS_MIPFLINEAR |
2039 WINED3DPTFILTERCAPS_MIPFPOINT |
2040 WINED3DPTFILTERCAPS_LINEAR |
2041 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2042 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2043 WINED3DPTFILTERCAPS_MIPLINEAR |
2044 WINED3DPTFILTERCAPS_MIPNEAREST |
2045 WINED3DPTFILTERCAPS_NEAREST;
2047 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2048 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2049 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2052 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2053 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2054 WINED3DPTFILTERCAPS_MAGFPOINT |
2055 WINED3DPTFILTERCAPS_MINFLINEAR |
2056 WINED3DPTFILTERCAPS_MINFPOINT |
2057 WINED3DPTFILTERCAPS_MIPFLINEAR |
2058 WINED3DPTFILTERCAPS_MIPFPOINT |
2059 WINED3DPTFILTERCAPS_LINEAR |
2060 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2061 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2062 WINED3DPTFILTERCAPS_MIPLINEAR |
2063 WINED3DPTFILTERCAPS_MIPNEAREST |
2064 WINED3DPTFILTERCAPS_NEAREST;
2066 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2067 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2068 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2071 *pCaps->CubeTextureFilterCaps = 0;
2073 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2074 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2075 WINED3DPTFILTERCAPS_MAGFPOINT |
2076 WINED3DPTFILTERCAPS_MINFLINEAR |
2077 WINED3DPTFILTERCAPS_MINFPOINT |
2078 WINED3DPTFILTERCAPS_MIPFLINEAR |
2079 WINED3DPTFILTERCAPS_MIPFPOINT |
2080 WINED3DPTFILTERCAPS_LINEAR |
2081 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2082 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2083 WINED3DPTFILTERCAPS_MIPLINEAR |
2084 WINED3DPTFILTERCAPS_MIPNEAREST |
2085 WINED3DPTFILTERCAPS_NEAREST;
2087 *pCaps->VolumeTextureFilterCaps = 0;
2089 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2090 WINED3DPTADDRESSCAPS_CLAMP |
2091 WINED3DPTADDRESSCAPS_WRAP;
2093 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2094 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2096 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2097 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2099 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2100 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2103 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2104 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2105 WINED3DPTADDRESSCAPS_CLAMP |
2106 WINED3DPTADDRESSCAPS_WRAP;
2107 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2108 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2110 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2111 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2113 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2114 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2117 *pCaps->VolumeTextureAddressCaps = 0;
2119 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2120 WINED3DLINECAPS_ZTEST;
2122 WINED3DLINECAPS_BLEND
2123 WINED3DLINECAPS_ALPHACMP
2124 WINED3DLINECAPS_FOG */
2126 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2127 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2129 if(GL_SUPPORT(EXT_TEXTURE3D))
2130 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2132 *pCaps->MaxVolumeExtent = 0;
2134 *pCaps->MaxTextureRepeat = 32768;
2135 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2136 *pCaps->MaxVertexW = 1.0;
2138 *pCaps->GuardBandLeft = 0;
2139 *pCaps->GuardBandTop = 0;
2140 *pCaps->GuardBandRight = 0;
2141 *pCaps->GuardBandBottom = 0;
2143 *pCaps->ExtentsAdjust = 0;
2145 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2146 WINED3DSTENCILCAPS_INCRSAT |
2147 WINED3DSTENCILCAPS_INVERT |
2148 WINED3DSTENCILCAPS_KEEP |
2149 WINED3DSTENCILCAPS_REPLACE |
2150 WINED3DSTENCILCAPS_ZERO;
2151 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2152 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2153 WINED3DSTENCILCAPS_INCR;
2155 if ( This->dxVersion > 8 &&
2156 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2157 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2158 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2161 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2163 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2164 WINED3DTEXOPCAPS_ADDSIGNED |
2165 WINED3DTEXOPCAPS_ADDSIGNED2X |
2166 WINED3DTEXOPCAPS_MODULATE |
2167 WINED3DTEXOPCAPS_MODULATE2X |
2168 WINED3DTEXOPCAPS_MODULATE4X |
2169 WINED3DTEXOPCAPS_SELECTARG1 |
2170 WINED3DTEXOPCAPS_SELECTARG2 |
2171 WINED3DTEXOPCAPS_DISABLE;
2173 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2174 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2175 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2176 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2177 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2178 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2179 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2180 WINED3DTEXOPCAPS_LERP |
2181 WINED3DTEXOPCAPS_SUBTRACT;
2183 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2184 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2185 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2186 WINED3DTEXOPCAPS_MULTIPLYADD |
2187 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2188 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2189 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2191 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2192 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2194 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2195 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2196 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2201 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2203 WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2204 WINED3DTEXOPCAPS_PREMODULATE */
2207 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2208 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2209 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2210 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2214 #if 0 /* TODO: Blends support in drawprim */
2215 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2217 *pCaps->MaxVertexBlendMatrices = 0;
2219 *pCaps->MaxVertexBlendMatrixIndex = 1;
2221 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2222 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2225 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2226 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2227 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2228 WINED3DVTXPCAPS_LOCALVIEWER |
2229 WINED3DVTXPCAPS_VERTEXFOG |
2230 WINED3DVTXPCAPS_TEXGEN;
2232 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2234 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2235 *pCaps->MaxVertexIndex = 0xFFFFF;
2236 *pCaps->MaxStreams = MAX_STREAMS;
2237 *pCaps->MaxStreamStride = 1024;
2239 if (vs_selected_mode == SHADER_GLSL) {
2240 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2241 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2242 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2243 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2244 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2245 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2247 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2248 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2249 } else if (vs_selected_mode == SHADER_ARB) {
2250 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2251 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2253 *pCaps->VertexShaderVersion = 0;
2254 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2257 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2259 if (ps_selected_mode == SHADER_GLSL) {
2260 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2261 in case of GeforceFX cards. */
2262 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2263 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2265 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2266 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2267 *pCaps->PixelShader1xMaxValue = 1.0;
2268 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2269 } else if (ps_selected_mode == SHADER_ARB) {
2270 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2271 *pCaps->PixelShader1xMaxValue = 1.0;
2272 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2274 *pCaps->PixelShaderVersion = 0;
2275 *pCaps->PixelShader1xMaxValue = 0.0;
2276 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2279 /* ------------------------------------------------
2280 The following fields apply to d3d9 only
2281 ------------------------------------------------ */
2282 if (This->dxVersion > 8) {
2283 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2284 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2285 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2286 *pCaps->MaxNpatchTessellationLevel = 0;
2287 *pCaps->MasterAdapterOrdinal = 0;
2288 *pCaps->AdapterOrdinalInGroup = 0;
2289 *pCaps->NumberOfAdaptersInGroup = 1;
2291 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2292 /* OpenGL supports all the formats below, perhaps not always
2293 * without conversion, but it supports them.
2294 * Further GLSL doesn't seem to have an official unsigned type so
2295 * don't advertise it yet as I'm not sure how we handle it.
2296 * We might need to add some clamping in the shader engine to
2298 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2299 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2300 WINED3DDTCAPS_UBYTE4N |
2301 WINED3DDTCAPS_SHORT2N |
2302 WINED3DDTCAPS_SHORT4N |
2303 WINED3DDTCAPS_FLOAT16_2 |
2304 WINED3DDTCAPS_FLOAT16_4;
2307 *pCaps->DeclTypes = 0;
2309 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2312 *pCaps->StretchRectFilterCaps = 0;
2313 *pCaps->VertexTextureFilterCaps = 0;
2315 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2316 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2317 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2318 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2319 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2320 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2321 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2323 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2324 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2325 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2326 *pCaps->VS20Caps.Caps = 0;
2327 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2328 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2329 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2331 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2332 *pCaps->MaxVertexShader30InstructionSlots = 0;
2333 } else { /* VS 1.x */
2334 *pCaps->VS20Caps.Caps = 0;
2335 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2336 *pCaps->VS20Caps.NumTemps = 0;
2337 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2339 *pCaps->MaxVShaderInstructionsExecuted = 0;
2340 *pCaps->MaxVertexShader30InstructionSlots = 0;
2343 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2344 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2345 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2347 /* 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 */
2348 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2349 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2350 WINED3DPS20CAPS_PREDICATION |
2351 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2352 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2353 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2354 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2355 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2356 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2358 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2359 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2360 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2361 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2362 *pCaps->PS20Caps.Caps = 0;
2363 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2364 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2365 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2366 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2368 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2369 *pCaps->MaxPixelShader30InstructionSlots = 0;
2370 } else { /* PS 1.x */
2371 *pCaps->PS20Caps.Caps = 0;
2372 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2373 *pCaps->PS20Caps.NumTemps = 0;
2374 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2375 *pCaps->PS20Caps.NumInstructionSlots = 0;
2377 *pCaps->MaxPShaderInstructionsExecuted = 0;
2378 *pCaps->MaxPixelShader30InstructionSlots = 0;
2385 static unsigned int glsl_program_key_hash(void *key) {
2386 glsl_program_key_t *k = (glsl_program_key_t *)key;
2388 unsigned int hash = k->vshader | k->pshader << 16;
2389 hash += ~(hash << 15);
2390 hash ^= (hash >> 10);
2391 hash += (hash << 3);
2392 hash ^= (hash >> 6);
2393 hash += ~(hash << 11);
2394 hash ^= (hash >> 16);
2399 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2400 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2401 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2403 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2406 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2407 and fields being inserted in the middle, a new structure is used in place */
2408 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2409 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2412 IWineD3DDeviceImpl *object = NULL;
2413 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2415 HRESULT temp_result;
2417 /* Validate the adapter number */
2418 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2419 return WINED3DERR_INVALIDCALL;
2422 /* Create a WineD3DDevice object */
2423 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2424 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2425 TRACE("Created WineD3DDevice object @ %p\n", object);
2426 if (NULL == object) {
2427 return WINED3DERR_OUTOFVIDEOMEMORY;
2430 /* Set up initial COM information */
2431 object->lpVtbl = &IWineD3DDevice_Vtbl;
2433 object->wineD3D = iface;
2434 IWineD3D_AddRef(object->wineD3D);
2435 object->parent = parent;
2437 /* Set the state up as invalid until the device is fully created */
2438 object->state = WINED3DERR_DRIVERINTERNALERROR;
2440 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2441 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2443 /* Save the creation parameters */
2444 object->createParms.AdapterOrdinal = Adapter;
2445 object->createParms.DeviceType = DeviceType;
2446 object->createParms.hFocusWindow = hFocusWindow;
2447 object->createParms.BehaviorFlags = BehaviourFlags;
2449 /* Initialize other useful values */
2450 object->adapterNo = Adapter;
2451 object->devType = DeviceType;
2453 TRACE("(%p) : Creating stateblock\n", This);
2454 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2455 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2457 (IWineD3DStateBlock **)&object->stateBlock,
2458 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2459 WARN("Failed to create stateblock\n");
2460 goto create_device_error;
2462 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2463 object->updateStateBlock = object->stateBlock;
2464 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2465 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2467 /* Setup some defaults for creating the implicit swapchain */
2469 /* FIXME: GL info should be per adapter */
2470 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2472 select_shader_mode(&This->gl_info, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2473 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2474 object->shader_backend = &glsl_shader_backend;
2475 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2476 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2477 object->shader_backend = &arb_program_shader_backend;
2479 object->shader_backend = &none_shader_backend;
2482 /* This function should *not* be modifying GL caps
2483 * TODO: move the functionality where it belongs */
2484 select_shader_max_constants(object->ps_selected_mode, object->vs_selected_mode, &This->gl_info);
2486 temp_result = allocate_shader_constants(object->updateStateBlock);
2487 if (WINED3D_OK != temp_result)
2490 object->render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *) * GL_LIMITS(buffers));
2492 object->draw_buffers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLenum) * GL_LIMITS(buffers));
2494 /* set the state of the device to valid */
2495 object->state = WINED3D_OK;
2497 /* Get the initial screen setup for ddraw */
2498 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2499 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2501 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2505 create_device_error:
2507 /* Set the device state to error */
2508 object->state = WINED3DERR_DRIVERINTERNALERROR;
2510 if (object->updateStateBlock != NULL) {
2511 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2512 object->updateStateBlock = NULL;
2514 if (object->stateBlock != NULL) {
2515 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2516 object->stateBlock = NULL;
2518 if (object->render_targets[0] != NULL) {
2519 IWineD3DSurface_Release(object->render_targets[0]);
2520 object->render_targets[0] = NULL;
2522 if (object->stencilBufferTarget != NULL) {
2523 IWineD3DSurface_Release(object->stencilBufferTarget);
2524 object->stencilBufferTarget = NULL;
2526 HeapFree(GetProcessHeap(), 0, object);
2527 *ppReturnedDeviceInterface = NULL;
2528 return WINED3DERR_INVALIDCALL;
2532 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2533 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2534 IUnknown_AddRef(This->parent);
2535 *pParent = This->parent;
2539 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2540 IUnknown* surfaceParent;
2541 TRACE("(%p) call back\n", pSurface);
2543 /* Now, release the parent, which will take care of cleaning up the surface for us */
2544 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2545 IUnknown_Release(surfaceParent);
2546 return IUnknown_Release(surfaceParent);
2549 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2550 IUnknown* volumeParent;
2551 TRACE("(%p) call back\n", pVolume);
2553 /* Now, release the parent, which will take care of cleaning up the volume for us */
2554 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2555 IUnknown_Release(volumeParent);
2556 return IUnknown_Release(volumeParent);
2559 /**********************************************************
2560 * IWineD3D VTbl follows
2561 **********************************************************/
2563 const IWineD3DVtbl IWineD3D_Vtbl =
2566 IWineD3DImpl_QueryInterface,
2567 IWineD3DImpl_AddRef,
2568 IWineD3DImpl_Release,
2570 IWineD3DImpl_GetParent,
2571 IWineD3DImpl_GetAdapterCount,
2572 IWineD3DImpl_RegisterSoftwareDevice,
2573 IWineD3DImpl_GetAdapterMonitor,
2574 IWineD3DImpl_GetAdapterModeCount,
2575 IWineD3DImpl_EnumAdapterModes,
2576 IWineD3DImpl_GetAdapterDisplayMode,
2577 IWineD3DImpl_GetAdapterIdentifier,
2578 IWineD3DImpl_CheckDeviceMultiSampleType,
2579 IWineD3DImpl_CheckDepthStencilMatch,
2580 IWineD3DImpl_CheckDeviceType,
2581 IWineD3DImpl_CheckDeviceFormat,
2582 IWineD3DImpl_CheckDeviceFormatConversion,
2583 IWineD3DImpl_GetDeviceCaps,
2584 IWineD3DImpl_CreateDevice