wined3d: Disable W11V11U10 and A2W10V10U10.
[wine.git] / dlls / wined3d / directx.c
blobce2c6cfe1a3de76b8936bf94ddeca6a9e5771219
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 } EXTENSION_MAP[] = {
44 /* APPLE */
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
48 /* ATI */
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP},
54 /* ARB */
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL},
59 {"GL_ARB_imaging", ARB_IMAGING},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER},
80 /* EXT */
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING},
102 /* NV */
103 {"GL_NV_half_float", NV_HALF_FLOAT},
104 {"GL_NV_fence", NV_FENCE},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
122 /**********************************************************
123 * Utility functions follow
124 **********************************************************/
126 /* Adapters */
127 static int numAdapters = 0;
128 static struct WineD3DAdapter Adapters[1];
130 /* lookup tables */
131 int minLookup[MAX_LOOKUPS];
132 int maxLookup[MAX_LOOKUPS];
133 DWORD *stateLookup[MAX_LOOKUPS];
135 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
139 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
140 * ie there is no GL Context - Get a default rendering context to enable the
141 * function query some info from GL
144 static int wined3d_fake_gl_context_ref = 0;
145 static BOOL wined3d_fake_gl_context_foreign;
146 static BOOL wined3d_fake_gl_context_available = FALSE;
147 static HDC wined3d_fake_gl_context_hdc = NULL;
148 static HWND wined3d_fake_gl_context_hwnd = NULL;
150 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
151 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
153 0, 0, &wined3d_fake_gl_context_cs,
154 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
155 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
156 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
160 static void WineD3D_ReleaseFakeGLContext(void) {
161 HGLRC glCtx;
163 EnterCriticalSection(&wined3d_fake_gl_context_cs);
165 if(!wined3d_fake_gl_context_available) {
166 TRACE_(d3d_caps)("context not available\n");
167 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
168 return;
171 glCtx = pwglGetCurrentContext();
173 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
174 if (0 == (--wined3d_fake_gl_context_ref) ) {
175 if(!wined3d_fake_gl_context_foreign && glCtx) {
176 TRACE_(d3d_caps)("destroying fake GL context\n");
177 pwglMakeCurrent(NULL, NULL);
178 pwglDeleteContext(glCtx);
180 if(wined3d_fake_gl_context_hdc)
181 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
182 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
183 if(wined3d_fake_gl_context_hwnd)
184 DestroyWindow(wined3d_fake_gl_context_hwnd);
185 wined3d_fake_gl_context_hwnd = NULL;
186 wined3d_fake_gl_context_available = FALSE;
188 assert(wined3d_fake_gl_context_ref >= 0);
190 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
191 LEAVE_GL();
194 static BOOL WineD3D_CreateFakeGLContext(void) {
195 HGLRC glCtx = NULL;
197 ENTER_GL();
198 EnterCriticalSection(&wined3d_fake_gl_context_cs);
200 TRACE("getting context...\n");
201 if(wined3d_fake_gl_context_ref > 0) goto ret;
202 assert(0 == wined3d_fake_gl_context_ref);
204 wined3d_fake_gl_context_foreign = TRUE;
206 glCtx = pwglGetCurrentContext();
207 if (!glCtx) {
208 PIXELFORMATDESCRIPTOR pfd;
209 int iPixelFormat;
211 wined3d_fake_gl_context_foreign = FALSE;
213 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
214 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
215 if(!wined3d_fake_gl_context_hwnd) {
216 ERR("HWND creation failed!\n");
217 goto fail;
219 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
220 if(!wined3d_fake_gl_context_hdc) {
221 ERR("GetDC failed!\n");
222 goto fail;
225 /* PixelFormat selection */
226 ZeroMemory(&pfd, sizeof(pfd));
227 pfd.nSize = sizeof(pfd);
228 pfd.nVersion = 1;
229 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
230 pfd.iPixelType = PFD_TYPE_RGBA;
231 pfd.cColorBits = 32;
232 pfd.iLayerType = PFD_MAIN_PLANE;
234 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
235 if(!iPixelFormat) {
236 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
237 ERR("Can't find a suitable iPixelFormat\n");
238 goto fail;
240 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
241 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
243 /* Create a GL context */
244 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
245 if (!glCtx) {
246 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
247 goto fail;
250 /* Make it the current GL context */
251 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
252 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
253 goto fail;
257 ret:
258 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
259 wined3d_fake_gl_context_ref++;
260 wined3d_fake_gl_context_available = TRUE;
261 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
262 return TRUE;
263 fail:
264 if(wined3d_fake_gl_context_hdc)
265 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
266 wined3d_fake_gl_context_hdc = NULL;
267 if(wined3d_fake_gl_context_hwnd)
268 DestroyWindow(wined3d_fake_gl_context_hwnd);
269 wined3d_fake_gl_context_hwnd = NULL;
270 if(glCtx) pwglDeleteContext(glCtx);
271 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
272 LEAVE_GL();
273 return FALSE;
277 /**********************************************************
278 * IUnknown parts follows
279 **********************************************************/
281 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
285 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
286 if (IsEqualGUID(riid, &IID_IUnknown)
287 || IsEqualGUID(riid, &IID_IWineD3DBase)
288 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
289 IUnknown_AddRef(iface);
290 *ppobj = This;
291 return S_OK;
293 *ppobj = NULL;
294 return E_NOINTERFACE;
297 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
298 IWineD3DImpl *This = (IWineD3DImpl *)iface;
299 ULONG refCount = InterlockedIncrement(&This->ref);
301 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
302 return refCount;
305 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
307 ULONG ref;
308 TRACE("(%p) : Releasing from %d\n", This, This->ref);
309 ref = InterlockedDecrement(&This->ref);
310 if (ref == 0) {
311 HeapFree(GetProcessHeap(), 0, This);
314 return ref;
317 /* Set the shader type for this device, depending on the given capabilities,
318 * the device type, and the user preferences in wined3d_settings */
320 static void select_shader_mode(
321 WineD3D_GL_Info *gl_info,
322 WINED3DDEVTYPE DeviceType,
323 int* ps_selected,
324 int* vs_selected) {
326 if (wined3d_settings.vs_mode == VS_NONE) {
327 *vs_selected = SHADER_NONE;
328 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
329 *vs_selected = SHADER_GLSL;
330 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
331 *vs_selected = SHADER_ARB;
332 } else {
333 *vs_selected = SHADER_NONE;
336 if (wined3d_settings.ps_mode == PS_NONE) {
337 *ps_selected = SHADER_NONE;
338 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
339 *ps_selected = SHADER_GLSL;
340 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
341 *ps_selected = SHADER_ARB;
342 } else {
343 *ps_selected = SHADER_NONE;
347 /** Select the number of report maximum shader constants based on the selected shader modes */
348 static void select_shader_max_constants(
349 int ps_selected_mode,
350 int vs_selected_mode,
351 WineD3D_GL_Info *gl_info) {
353 switch (vs_selected_mode) {
354 case SHADER_GLSL:
355 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
356 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
357 break;
358 case SHADER_ARB:
359 /* We have to subtract any other PARAMs that we might use in our shader programs.
360 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
361 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
362 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
363 break;
364 default:
365 gl_info->max_vshader_constantsF = 0;
366 break;
369 switch (ps_selected_mode) {
370 case SHADER_GLSL:
371 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
372 * In theory the texbem instruction may need one more shader constant too. But lets assume
373 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
374 * and lets not take away a uniform needlessly from all other shaders.
376 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
377 break;
378 case SHADER_ARB:
379 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
380 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
382 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
383 break;
384 default:
385 gl_info->max_pshader_constantsF = 0;
386 break;
390 /**********************************************************
391 * IWineD3D parts follows
392 **********************************************************/
394 #define GLINFO_LOCATION (*gl_info)
395 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
396 const char *GL_Extensions = NULL;
397 const char *WGL_Extensions = NULL;
398 const char *gl_string = NULL;
399 const char *gl_string_cursor = NULL;
400 GLint gl_max;
401 GLfloat gl_floatv[2];
402 int major = 1, minor = 0;
403 BOOL return_value = TRUE;
404 int i;
405 HDC hdc;
407 TRACE_(d3d_caps)("(%p)\n", gl_info);
409 gl_string = (const char *) glGetString(GL_RENDERER);
410 if (NULL == gl_string)
411 gl_string = "None";
412 strcpy(gl_info->gl_renderer, gl_string);
414 gl_string = (const char *) glGetString(GL_VENDOR);
415 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
416 if (gl_string != NULL) {
417 /* Fill in the GL vendor */
418 if (strstr(gl_string, "NVIDIA")) {
419 gl_info->gl_vendor = VENDOR_NVIDIA;
420 } else if (strstr(gl_string, "ATI")) {
421 gl_info->gl_vendor = VENDOR_ATI;
422 } else if (strstr(gl_string, "Intel(R)") ||
423 strstr(gl_info->gl_renderer, "Intel(R)")) {
424 gl_info->gl_vendor = VENDOR_INTEL;
425 } else if (strstr(gl_string, "Mesa")) {
426 gl_info->gl_vendor = VENDOR_MESA;
427 } else {
428 gl_info->gl_vendor = VENDOR_WINE;
430 } else {
431 gl_info->gl_vendor = VENDOR_WINE;
435 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
437 /* Parse the GL_VERSION field into major and minor information */
438 gl_string = (const char *) glGetString(GL_VERSION);
439 if (gl_string != NULL) {
441 switch (gl_info->gl_vendor) {
442 case VENDOR_NVIDIA:
443 gl_string_cursor = strstr(gl_string, "NVIDIA");
444 if (!gl_string_cursor) {
445 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
446 break;
449 gl_string_cursor = strstr(gl_string_cursor, " ");
450 if (!gl_string_cursor) {
451 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
452 break;
455 while (*gl_string_cursor == ' ') {
456 ++gl_string_cursor;
459 if (!*gl_string_cursor) {
460 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
461 break;
464 major = atoi(gl_string_cursor);
465 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
466 ++gl_string_cursor;
469 if (*gl_string_cursor++ != '.') {
470 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
471 break;
474 minor = atoi(gl_string_cursor);
475 minor = major*100+minor;
476 major = 10;
478 break;
480 case VENDOR_ATI:
481 major = minor = 0;
482 gl_string_cursor = strchr(gl_string, '-');
483 if (gl_string_cursor) {
484 int error = 0;
485 gl_string_cursor++;
487 /* Check if version number is of the form x.y.z */
488 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
489 error = 1;
490 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
491 error = 1;
492 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
493 error = 1;
494 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
495 error = 1;
497 /* Mark version number as malformed */
498 if (error)
499 gl_string_cursor = 0;
502 if (!gl_string_cursor)
503 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
504 else {
505 major = *gl_string_cursor - '0';
506 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
508 break;
510 case VENDOR_INTEL:
511 case VENDOR_MESA:
512 gl_string_cursor = strstr(gl_string, "Mesa");
513 gl_string_cursor = strstr(gl_string_cursor, " ");
514 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
515 if (*gl_string_cursor) {
516 char tmp[16];
517 int cursor = 0;
519 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
520 tmp[cursor++] = *gl_string_cursor;
521 ++gl_string_cursor;
523 tmp[cursor] = 0;
524 major = atoi(tmp);
526 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
527 ++gl_string_cursor;
529 cursor = 0;
530 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
531 tmp[cursor++] = *gl_string_cursor;
532 ++gl_string_cursor;
534 tmp[cursor] = 0;
535 minor = atoi(tmp);
537 break;
539 default:
540 major = 0;
541 minor = 9;
543 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
544 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
547 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
550 * Initialize openGL extension related variables
551 * with Default values
553 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
554 gl_info->max_buffers = 1;
555 gl_info->max_textures = 1;
556 gl_info->max_texture_stages = 1;
557 gl_info->max_fragment_samplers = 1;
558 gl_info->max_vertex_samplers = 0;
559 gl_info->max_combined_samplers = 0;
560 gl_info->max_sampler_stages = 1;
561 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
562 gl_info->ps_arb_max_temps = 0;
563 gl_info->ps_arb_max_instructions = 0;
564 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
565 gl_info->vs_arb_max_temps = 0;
566 gl_info->vs_arb_max_instructions = 0;
567 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
568 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
569 gl_info->vs_glsl_constantsF = 0;
570 gl_info->ps_glsl_constantsF = 0;
571 gl_info->vs_arb_constantsF = 0;
572 gl_info->ps_arb_constantsF = 0;
574 /* Now work out what GL support this card really has */
575 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
576 GL_EXT_FUNCS_GEN;
577 WGL_EXT_FUNCS_GEN;
578 #undef USE_GL_FUNC
580 /* Retrieve opengl defaults */
581 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
582 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
583 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
585 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
586 gl_info->max_lights = gl_max;
587 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
589 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
590 gl_info->max_texture_size = gl_max;
591 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
593 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
594 gl_info->max_pointsize = gl_floatv[1];
595 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
597 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
598 gl_info->max_aux_buffers = gl_max;
599 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
601 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
602 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
603 TRACE_(d3d_caps)("GL_Extensions reported:\n");
605 if (NULL == GL_Extensions) {
606 ERR(" GL_Extensions returns NULL\n");
607 } else {
608 while (*GL_Extensions != 0x00) {
609 const char *Start;
610 char ThisExtn[256];
611 size_t len;
613 while (isspace(*GL_Extensions)) GL_Extensions++;
614 Start = GL_Extensions;
615 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
616 GL_Extensions++;
619 len = GL_Extensions - Start;
620 if (len == 0 || len >= sizeof(ThisExtn))
621 continue;
623 memcpy(ThisExtn, Start, len);
624 ThisExtn[len] = '\0';
625 TRACE_(d3d_caps)("- %s\n", ThisExtn);
627 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
628 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
629 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
630 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
631 break;
636 if (gl_info->supported[APPLE_FENCE]) {
637 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
638 * The apple extension interacts with some other apple exts. Disable the NV
639 * extension if the apple one is support to prevent confusion in other parts
640 * of the code
642 gl_info->supported[NV_FENCE] = FALSE;
644 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
645 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
646 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
648 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
649 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
650 * Won't occur in any real world situation though
652 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
654 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
655 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
656 gl_info->max_buffers = gl_max;
657 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
659 if (gl_info->supported[ARB_MULTITEXTURE]) {
660 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
661 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
662 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
664 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
665 GLint tmp;
666 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
667 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
668 } else {
669 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
671 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
673 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
674 GLint tmp;
675 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
676 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
677 } else {
678 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
680 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
682 if (gl_info->supported[ARB_VERTEX_SHADER]) {
683 GLint tmp;
684 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
685 gl_info->max_vertex_samplers = tmp;
686 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
687 gl_info->max_combined_samplers = tmp;
688 } else {
689 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
691 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
692 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
694 if (gl_info->supported[ARB_VERTEX_BLEND]) {
695 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
696 gl_info->max_blends = gl_max;
697 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
699 if (gl_info->supported[EXT_TEXTURE3D]) {
700 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
701 gl_info->max_texture3d_size = gl_max;
702 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
704 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
705 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
706 gl_info->max_anisotropy = gl_max;
707 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
709 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
710 gl_info->ps_arb_version = PS_VERSION_11;
711 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
712 gl_info->ps_arb_constantsF = gl_max;
713 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
714 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
715 gl_info->ps_arb_max_temps = gl_max;
716 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
717 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
718 gl_info->ps_arb_max_instructions = gl_max;
719 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
721 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
722 gl_info->vs_arb_version = VS_VERSION_11;
723 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
724 gl_info->vs_arb_constantsF = gl_max;
725 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
726 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
727 gl_info->vs_arb_max_temps = gl_max;
728 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
729 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
730 gl_info->vs_arb_max_instructions = gl_max;
731 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
733 if (gl_info->supported[ARB_VERTEX_SHADER]) {
734 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
735 gl_info->vs_glsl_constantsF = gl_max / 4;
736 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
738 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
739 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
740 gl_info->ps_glsl_constantsF = gl_max / 4;
741 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
743 if (gl_info->supported[EXT_VERTEX_SHADER]) {
744 gl_info->vs_ati_version = VS_VERSION_11;
746 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
747 gl_info->vs_nv_version = VS_VERSION_30;
748 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
749 gl_info->vs_nv_version = VS_VERSION_20;
750 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
751 gl_info->vs_nv_version = VS_VERSION_11;
752 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
753 gl_info->vs_nv_version = VS_VERSION_10;
755 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
756 gl_info->ps_nv_version = PS_VERSION_30;
757 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
758 gl_info->ps_nv_version = PS_VERSION_20;
762 checkGLcall("extension detection\n");
764 /* In some cases the number of texture stages can be larger than the number
765 * of samplers. The GF4 for example can use only 2 samplers (no fragment
766 * shaders), but 8 texture stages (register combiners). */
767 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
769 /* We can only use ORM_FBO when the hardware supports it. */
770 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
771 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
772 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
775 /* MRTs are currently only supported when FBOs are used. */
776 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
777 gl_info->max_buffers = 1;
780 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
781 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
782 * in case of the latest videocards in the number of pixel/vertex pipelines.
784 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
785 * rendering. Various games use this information to get a rough estimation of the features of the card
786 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
787 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
788 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
789 * not the PCI id.
791 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
792 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
793 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
794 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
795 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
796 * is used for rendering which is not always the case). This would work but it is not very portable. Second
797 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
798 * is limited.
800 * As said most games only use the PCI id to get an indication of the capabilities of the card.
801 * It doesn't really matter if the given id is the correct one if we return the id of a card with
802 * similar 3d features.
804 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
805 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
806 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
807 * won't pass we return a default card. This way is better than maintaining a full card database as even
808 * without a full database we can return a card with similar features. Second the size of the database
809 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
810 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
811 * to distinguishes between different models from that family.
813 switch (gl_info->gl_vendor) {
814 case VENDOR_NVIDIA:
815 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
816 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
818 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
819 if (strstr(gl_info->gl_renderer, "8800"))
820 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
821 else if(strstr(gl_info->gl_renderer, "8600") ||
822 strstr(gl_info->gl_renderer, "8700"))
823 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
824 else if(strstr(gl_info->gl_renderer, "8300") ||
825 strstr(gl_info->gl_renderer, "8400") ||
826 strstr(gl_info->gl_renderer, "8500"))
827 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
828 else if(strstr(gl_info->gl_renderer, "7800") ||
829 strstr(gl_info->gl_renderer, "7900") ||
830 strstr(gl_info->gl_renderer, "7950") ||
831 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
832 strstr(gl_info->gl_renderer, "Quadro FX 5"))
833 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
834 else if(strstr(gl_info->gl_renderer, "6800") ||
835 strstr(gl_info->gl_renderer, "7600"))
836 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
837 else if(strstr(gl_info->gl_renderer, "6600") ||
838 strstr(gl_info->gl_renderer, "6610") ||
839 strstr(gl_info->gl_renderer, "6700"))
840 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
841 else
842 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
843 } else if(WINE_D3D9_CAPABLE(gl_info)) {
844 if (strstr(gl_info->gl_renderer, "5800") ||
845 strstr(gl_info->gl_renderer, "5900") ||
846 strstr(gl_info->gl_renderer, "5950") ||
847 strstr(gl_info->gl_renderer, "Quadro FX"))
848 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
849 else if(strstr(gl_info->gl_renderer, "5600") ||
850 strstr(gl_info->gl_renderer, "5650") ||
851 strstr(gl_info->gl_renderer, "5700") ||
852 strstr(gl_info->gl_renderer, "5750"))
853 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
854 else
855 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
856 } else if(WINE_D3D8_CAPABLE(gl_info)) {
857 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
858 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
859 else
860 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
861 } else if(WINE_D3D7_CAPABLE(gl_info)) {
862 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
863 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
864 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
865 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
866 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
867 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
868 else
869 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
870 } else {
871 if (strstr(gl_info->gl_renderer, "TNT2"))
872 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
873 else
874 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
876 break;
877 case VENDOR_ATI:
878 if(WINE_D3D9_CAPABLE(gl_info)) {
879 /* Radeon R5xx */
880 if (strstr(gl_info->gl_renderer, "X1600") ||
881 strstr(gl_info->gl_renderer, "X1800") ||
882 strstr(gl_info->gl_renderer, "X1900") ||
883 strstr(gl_info->gl_renderer, "X1950"))
884 gl_info->gl_card = CARD_ATI_RADEON_X1600;
885 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
886 else if(strstr(gl_info->gl_renderer, "X700") ||
887 strstr(gl_info->gl_renderer, "X800") ||
888 strstr(gl_info->gl_renderer, "X850") ||
889 strstr(gl_info->gl_renderer, "X1300") ||
890 strstr(gl_info->gl_renderer, "X1400"))
891 gl_info->gl_card = CARD_ATI_RADEON_X700;
892 /* Radeon R3xx */
893 else
894 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
895 } else if(WINE_D3D8_CAPABLE(gl_info)) {
896 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
897 } else if(WINE_D3D7_CAPABLE(gl_info)) {
898 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
899 } else
900 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
901 break;
902 case VENDOR_INTEL:
903 if (strstr(gl_info->gl_renderer, "915GM")) {
904 gl_info->gl_card = CARD_INTEL_I915GM;
905 } else if (strstr(gl_info->gl_renderer, "915G")) {
906 gl_info->gl_card = CARD_INTEL_I915G;
907 } else if (strstr(gl_info->gl_renderer, "865G")) {
908 gl_info->gl_card = CARD_INTEL_I865G;
909 } else if (strstr(gl_info->gl_renderer, "855G")) {
910 gl_info->gl_card = CARD_INTEL_I855G;
911 } else if (strstr(gl_info->gl_renderer, "830G")) {
912 gl_info->gl_card = CARD_INTEL_I830G;
913 } else {
914 gl_info->gl_card = CARD_INTEL_I915G;
916 break;
917 case VENDOR_MESA:
918 case VENDOR_WINE:
919 default:
920 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
921 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
922 * them a good generic choice.
924 gl_info->gl_vendor = VENDOR_NVIDIA;
925 if(WINE_D3D9_CAPABLE(gl_info))
926 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
927 else if(WINE_D3D8_CAPABLE(gl_info))
928 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
929 else if(WINE_D3D7_CAPABLE(gl_info))
930 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
931 else if(WINE_D3D6_CAPABLE(gl_info))
932 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
933 else
934 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
936 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
938 /* Load all the lookup tables
939 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
940 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
941 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
943 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
944 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
947 for (i = 0; i < MAX_LOOKUPS; i++) {
948 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
951 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
952 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
953 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
954 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
955 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
956 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
957 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
958 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
959 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
960 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
962 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
963 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
964 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
965 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
966 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
969 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
970 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
971 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
972 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
973 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
974 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
975 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
976 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
977 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
978 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
979 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
980 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
981 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
983 /* TODO: config lookups */
985 /* Make sure there's an active HDC else the WGL extensions will fail */
986 hdc = pwglGetCurrentDC();
987 if (hdc) {
988 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
989 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
991 if (NULL == WGL_Extensions) {
992 ERR(" WGL_Extensions returns NULL\n");
993 } else {
994 while (*WGL_Extensions != 0x00) {
995 const char *Start;
996 char ThisExtn[256];
997 size_t len;
999 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1000 Start = WGL_Extensions;
1001 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1002 WGL_Extensions++;
1005 len = WGL_Extensions - Start;
1006 if (len == 0 || len >= sizeof(ThisExtn))
1007 continue;
1009 memcpy(ThisExtn, Start, len);
1010 ThisExtn[len] = '\0';
1011 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1013 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1014 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1015 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1021 return return_value;
1023 #undef GLINFO_LOCATION
1025 /**********************************************************
1026 * IWineD3D implementation follows
1027 **********************************************************/
1029 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1030 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1032 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1033 return numAdapters;
1036 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1037 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1038 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1039 return WINED3D_OK;
1042 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1043 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1045 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1046 return NULL;
1049 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1050 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1053 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1054 of the same bpp but different resolutions */
1056 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1057 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1058 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1059 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1061 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1062 return 0;
1065 /* TODO: Store modes per adapter and read it from the adapter structure */
1066 if (Adapter == 0) { /* Display */
1067 int i = 0;
1068 int j = 0;
1070 if (!DEBUG_SINGLE_MODE) {
1071 DEVMODEW DevModeW;
1073 ZeroMemory(&DevModeW, sizeof(DevModeW));
1074 DevModeW.dmSize = sizeof(DevModeW);
1075 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1076 j++;
1077 switch (Format)
1079 case WINED3DFMT_UNKNOWN:
1080 /* This is for D3D8, do not enumerate P8 here */
1081 if (DevModeW.dmBitsPerPel == 32 ||
1082 DevModeW.dmBitsPerPel == 16) i++;
1083 break;
1084 case WINED3DFMT_X8R8G8B8:
1085 if (DevModeW.dmBitsPerPel == 32) i++;
1086 break;
1087 case WINED3DFMT_R5G6B5:
1088 if (DevModeW.dmBitsPerPel == 16) i++;
1089 break;
1090 case WINED3DFMT_P8:
1091 if (DevModeW.dmBitsPerPel == 8) i++;
1092 break;
1093 default:
1094 /* Skip other modes as they do not match the requested format */
1095 break;
1098 } else {
1099 i = 1;
1100 j = 1;
1103 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1104 return i;
1105 } else {
1106 FIXME_(d3d_caps)("Adapter not primary display\n");
1108 return 0;
1111 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1112 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1113 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1114 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1116 /* Validate the parameters as much as possible */
1117 if (NULL == pMode ||
1118 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1119 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1120 return WINED3DERR_INVALIDCALL;
1123 /* TODO: Store modes per adapter and read it from the adapter structure */
1124 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1125 DEVMODEW DevModeW;
1126 int ModeIdx = 0;
1127 int i = 0;
1128 int j = 0;
1130 ZeroMemory(&DevModeW, sizeof(DevModeW));
1131 DevModeW.dmSize = sizeof(DevModeW);
1133 /* If we are filtering to a specific format (D3D9), then need to skip
1134 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1135 just count through the ones with valid bit depths */
1136 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1137 switch (Format)
1139 case WINED3DFMT_UNKNOWN:
1140 /* This is D3D8. Do not enumerate P8 here */
1141 if (DevModeW.dmBitsPerPel == 32 ||
1142 DevModeW.dmBitsPerPel == 16) i++;
1143 break;
1144 case WINED3DFMT_X8R8G8B8:
1145 if (DevModeW.dmBitsPerPel == 32) i++;
1146 break;
1147 case WINED3DFMT_R5G6B5:
1148 if (DevModeW.dmBitsPerPel == 16) i++;
1149 break;
1150 case WINED3DFMT_P8:
1151 if (DevModeW.dmBitsPerPel == 8) i++;
1152 break;
1153 default:
1154 /* Modes that don't match what we support can get an early-out */
1155 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1156 return WINED3DERR_INVALIDCALL;
1160 if (i == 0) {
1161 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1162 return WINED3DERR_INVALIDCALL;
1164 ModeIdx = j - 1;
1166 /* Now get the display mode via the calculated index */
1167 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1168 pMode->Width = DevModeW.dmPelsWidth;
1169 pMode->Height = DevModeW.dmPelsHeight;
1170 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1171 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1172 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1174 if (Format == WINED3DFMT_UNKNOWN)
1176 switch (DevModeW.dmBitsPerPel)
1178 case 8:
1179 pMode->Format = WINED3DFMT_P8;
1180 break;
1181 case 16:
1182 pMode->Format = WINED3DFMT_R5G6B5;
1183 break;
1184 case 32:
1185 pMode->Format = WINED3DFMT_X8R8G8B8;
1186 break;
1187 default:
1188 pMode->Format = WINED3DFMT_UNKNOWN;
1189 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1191 } else {
1192 pMode->Format = Format;
1194 } else {
1195 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1196 return WINED3DERR_INVALIDCALL;
1199 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1200 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1201 DevModeW.dmBitsPerPel);
1203 } else if (DEBUG_SINGLE_MODE) {
1204 /* Return one setting of the format requested */
1205 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1206 pMode->Width = 800;
1207 pMode->Height = 600;
1208 pMode->RefreshRate = 60;
1209 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1210 } else {
1211 FIXME_(d3d_caps)("Adapter not primary display\n");
1214 return WINED3D_OK;
1217 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1218 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1219 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1221 if (NULL == pMode ||
1222 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1223 return WINED3DERR_INVALIDCALL;
1226 if (Adapter == 0) { /* Display */
1227 int bpp = 0;
1228 DEVMODEW DevModeW;
1230 ZeroMemory(&DevModeW, sizeof(DevModeW));
1231 DevModeW.dmSize = sizeof(DevModeW);
1233 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1234 pMode->Width = DevModeW.dmPelsWidth;
1235 pMode->Height = DevModeW.dmPelsHeight;
1236 bpp = DevModeW.dmBitsPerPel;
1237 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1238 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1240 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1243 switch (bpp) {
1244 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1245 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1246 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1247 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1248 default: pMode->Format = WINED3DFMT_UNKNOWN;
1251 } else {
1252 FIXME_(d3d_caps)("Adapter not primary display\n");
1255 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1256 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1257 return WINED3D_OK;
1260 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1261 and fields being inserted in the middle, a new structure is used in place */
1262 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1263 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1264 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1266 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1268 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1269 return WINED3DERR_INVALIDCALL;
1272 /* Return the information requested */
1273 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1274 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1275 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1277 /* Note dx8 doesn't supply a DeviceName */
1278 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1279 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1280 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1281 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1282 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1283 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1284 *(pIdentifier->SubSysId) = 0;
1285 *(pIdentifier->Revision) = 0;
1287 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1288 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1289 *(pIdentifier->WHQLLevel) = 0;
1290 } else {
1291 *(pIdentifier->WHQLLevel) = 1;
1294 return WINED3D_OK;
1297 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1298 short redSize, greenSize, blueSize, alphaSize, colorBits;
1300 if(!cfg)
1301 return FALSE;
1303 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1304 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1305 return FALSE;
1308 if(cfg->redSize < redSize)
1309 return FALSE;
1311 if(cfg->greenSize < greenSize)
1312 return FALSE;
1314 if(cfg->blueSize < blueSize)
1315 return FALSE;
1317 if(cfg->alphaSize < alphaSize)
1318 return FALSE;
1320 return TRUE;
1323 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1324 short depthSize, stencilSize;
1326 if(!cfg)
1327 return FALSE;
1329 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1330 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1331 return FALSE;
1334 if(cfg->depthSize < depthSize)
1335 return FALSE;
1337 if(cfg->stencilSize < stencilSize)
1338 return FALSE;
1340 return TRUE;
1343 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1344 WINED3DFORMAT AdapterFormat,
1345 WINED3DFORMAT RenderTargetFormat,
1346 WINED3DFORMAT DepthStencilFormat) {
1347 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1348 int nCfgs;
1349 WineD3D_PixelFormat *cfgs;
1350 int it;
1352 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1353 This, Adapter,
1354 DeviceType, debug_d3ddevicetype(DeviceType),
1355 AdapterFormat, debug_d3dformat(AdapterFormat),
1356 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1357 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1359 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1360 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1361 return WINED3DERR_INVALIDCALL;
1364 cfgs = Adapters[Adapter].cfgs;
1365 nCfgs = Adapters[Adapter].nCfgs;
1366 for (it = 0; it < nCfgs; ++it) {
1367 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1368 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1369 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1370 return WINED3D_OK;
1374 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1376 return WINED3DERR_NOTAVAILABLE;
1379 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1380 WINED3DFORMAT SurfaceFormat,
1381 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1383 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1384 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1385 This,
1386 Adapter,
1387 DeviceType, debug_d3ddevicetype(DeviceType),
1388 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1389 Windowed,
1390 MultiSampleType,
1391 pQualityLevels);
1393 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1394 return WINED3DERR_INVALIDCALL;
1397 /* TODO: Store in Adapter structure */
1398 if (pQualityLevels != NULL) {
1399 static int s_single_shot = 0;
1400 if (!s_single_shot) {
1401 FIXME("Quality levels unsupported at present\n");
1402 s_single_shot = 1;
1404 *pQualityLevels = 1; /* Guess at a value! */
1407 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1408 return WINED3DERR_NOTAVAILABLE;
1411 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1412 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1414 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1415 int nCfgs = 0;
1416 WineD3D_PixelFormat *cfgs;
1417 int it;
1418 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1420 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1421 This,
1422 Adapter,
1423 CheckType, debug_d3ddevicetype(CheckType),
1424 DisplayFormat, debug_d3dformat(DisplayFormat),
1425 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1426 Windowed);
1428 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1429 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1430 return WINED3DERR_INVALIDCALL;
1433 cfgs = Adapters[Adapter].cfgs;
1434 nCfgs = Adapters[Adapter].nCfgs;
1435 for (it = 0; it < nCfgs; ++it) {
1436 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1437 hr = WINED3D_OK;
1438 TRACE_(d3d_caps)("OK\n");
1439 break ;
1443 if(hr != WINED3D_OK)
1444 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1446 if(hr != WINED3D_OK)
1447 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1449 return hr;
1452 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1453 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1454 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1455 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1456 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1457 This,
1458 Adapter,
1459 DeviceType, debug_d3ddevicetype(DeviceType),
1460 AdapterFormat, debug_d3dformat(AdapterFormat),
1461 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1462 RType, debug_d3dresourcetype(RType),
1463 CheckFormat, debug_d3dformat(CheckFormat));
1465 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1466 return WINED3DERR_INVALIDCALL;
1469 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1470 switch (CheckFormat) {
1471 /* Filtering not supported */
1472 case WINED3DFMT_A32B32G32R32F:
1473 TRACE_(d3d_caps)("[FAILED]\n");
1474 return WINED3DERR_NOTAVAILABLE;
1475 default:
1476 break;
1480 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1481 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1482 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1483 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1484 if (!GL_LIMITS(vertex_samplers)) {
1485 TRACE_(d3d_caps)("[FAILED]\n");
1486 return WINED3DERR_NOTAVAILABLE;
1489 switch (CheckFormat) {
1490 case WINED3DFMT_A32B32G32R32F:
1491 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1492 TRACE_(d3d_caps)("[FAILED]\n");
1493 return WINED3DERR_NOTAVAILABLE;
1495 TRACE_(d3d_caps)("[OK]\n");
1496 return WINED3D_OK;
1498 default:
1499 TRACE_(d3d_caps)("[FAILED]\n");
1500 return WINED3DERR_NOTAVAILABLE;
1504 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1505 switch (CheckFormat) {
1506 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1507 * Windows supports only those 3, and enumerating the other formats confuses applications
1509 case WINED3DFMT_D24S8:
1510 case WINED3DFMT_D24X8:
1511 case WINED3DFMT_D16:
1512 TRACE_(d3d_caps)("[OK]\n");
1513 return WINED3D_OK;
1514 case WINED3DFMT_D16_LOCKABLE:
1515 case WINED3DFMT_D24FS8:
1516 case WINED3DFMT_D32F_LOCKABLE:
1517 case WINED3DFMT_D24X4S4:
1518 case WINED3DFMT_D15S1:
1519 case WINED3DFMT_D32:
1520 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1521 return WINED3DERR_NOTAVAILABLE;
1522 default:
1523 TRACE_(d3d_caps)("[FAILED]\n");
1524 return WINED3DERR_NOTAVAILABLE;
1526 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1527 switch (CheckFormat) {
1528 case WINED3DFMT_R8G8B8:
1529 case WINED3DFMT_A8R8G8B8:
1530 case WINED3DFMT_X8R8G8B8:
1531 case WINED3DFMT_R5G6B5:
1532 case WINED3DFMT_X1R5G5B5:
1533 case WINED3DFMT_A1R5G5B5:
1534 case WINED3DFMT_A4R4G4B4:
1535 case WINED3DFMT_R3G3B2:
1536 case WINED3DFMT_X4R4G4B4:
1537 case WINED3DFMT_A8B8G8R8:
1538 case WINED3DFMT_X8B8G8R8:
1539 case WINED3DFMT_P8:
1540 TRACE_(d3d_caps)("[OK]\n");
1541 return WINED3D_OK;
1542 case WINED3DFMT_R16F:
1543 case WINED3DFMT_A16B16G16R16F:
1544 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1545 TRACE_(d3d_caps)("[FAILED]\n");
1546 return WINED3DERR_NOTAVAILABLE;
1548 TRACE_(d3d_caps)("[OK]\n");
1549 return WINED3D_OK;
1550 case WINED3DFMT_A32B32G32R32F:
1551 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1552 TRACE_(d3d_caps)("[FAILED]\n");
1553 return WINED3DERR_NOTAVAILABLE;
1555 TRACE_(d3d_caps)("[OK]\n");
1556 return WINED3D_OK;
1557 default:
1558 TRACE_(d3d_caps)("[FAILED]\n");
1559 return WINED3DERR_NOTAVAILABLE;
1561 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1562 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1563 switch (CheckFormat) {
1564 case WINED3DFMT_V8U8:
1565 TRACE_(d3d_caps)("[OK]\n");
1566 return WINED3D_OK;
1567 /* TODO: Other bump map formats */
1568 default:
1569 TRACE_(d3d_caps)("[FAILED]\n");
1570 return WINED3DERR_NOTAVAILABLE;
1573 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1574 switch (CheckFormat) {
1575 case WINED3DFMT_V8U8:
1576 TRACE_(d3d_caps)("[OK]\n");
1577 return WINED3D_OK;
1578 default:
1579 TRACE_(d3d_caps)("[FAILED]\n");
1580 return WINED3DERR_NOTAVAILABLE;
1583 TRACE_(d3d_caps)("[FAILED]\n");
1584 return WINED3DERR_NOTAVAILABLE;
1587 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1588 switch (CheckFormat) {
1589 case WINED3DFMT_DXT1:
1590 case WINED3DFMT_DXT2:
1591 case WINED3DFMT_DXT3:
1592 case WINED3DFMT_DXT4:
1593 case WINED3DFMT_DXT5:
1594 TRACE_(d3d_caps)("[OK]\n");
1595 return WINED3D_OK;
1596 default:
1597 break; /* Avoid compiler warnings */
1601 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1602 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1603 switch (CheckFormat) {
1604 case WINED3DFMT_A8R8G8B8:
1605 case WINED3DFMT_X8R8G8B8:
1606 case WINED3DFMT_A4R4G4B4:
1607 case WINED3DFMT_L8:
1608 case WINED3DFMT_A8L8:
1609 case WINED3DFMT_DXT1:
1610 case WINED3DFMT_DXT2:
1611 case WINED3DFMT_DXT3:
1612 case WINED3DFMT_DXT4:
1613 case WINED3DFMT_DXT5:
1614 TRACE_(d3d_caps)("[OK]\n");
1615 return WINED3D_OK;
1617 default:
1618 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1619 return WINED3DERR_NOTAVAILABLE;
1623 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1625 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1627 switch (CheckFormat) {
1628 case WINED3DFMT_R16F:
1629 case WINED3DFMT_A16B16G16R16F:
1630 if (!half_pixel_support) break;
1631 case WINED3DFMT_R32F:
1632 case WINED3DFMT_A32B32G32R32F:
1633 TRACE_(d3d_caps)("[OK]\n");
1634 return WINED3D_OK;
1635 default:
1636 break; /* Avoid compiler warnings */
1640 /* This format is nothing special and it is supported perfectly.
1641 * However, ati and nvidia driver on windows do not mark this format as
1642 * supported (tested with the dxCapsViewer) and pretending to
1643 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1644 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1645 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1647 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1648 TRACE_(d3d_caps)("[FAILED]\n");
1649 return WINED3DERR_NOTAVAILABLE;
1652 switch (CheckFormat) {
1654 /*****
1655 * supported: RGB(A) formats
1657 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1658 case WINED3DFMT_A8R8G8B8:
1659 case WINED3DFMT_X8R8G8B8:
1660 case WINED3DFMT_R5G6B5:
1661 case WINED3DFMT_X1R5G5B5:
1662 case WINED3DFMT_A1R5G5B5:
1663 case WINED3DFMT_A4R4G4B4:
1664 case WINED3DFMT_R3G3B2:
1665 case WINED3DFMT_A8:
1666 case WINED3DFMT_X4R4G4B4:
1667 case WINED3DFMT_A8B8G8R8:
1668 case WINED3DFMT_X8B8G8R8:
1669 case WINED3DFMT_A2R10G10B10:
1670 case WINED3DFMT_A2B10G10R10:
1671 TRACE_(d3d_caps)("[OK]\n");
1672 return WINED3D_OK;
1674 /*****
1675 * supported: Palettized
1677 case WINED3DFMT_P8:
1678 TRACE_(d3d_caps)("[OK]\n");
1679 return WINED3D_OK;
1681 /*****
1682 * Supported: (Alpha)-Luminance
1684 case WINED3DFMT_L8:
1685 case WINED3DFMT_A8L8:
1686 case WINED3DFMT_A4L4:
1687 TRACE_(d3d_caps)("[OK]\n");
1688 return WINED3D_OK;
1690 /*****
1691 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1692 * GL_NV_texture_shader), but advertized to make apps happy.
1693 * Enable some because games often fail when they are not available
1694 * and are still playable even without bump mapping
1696 case WINED3DFMT_V8U8:
1697 case WINED3DFMT_V16U16:
1698 case WINED3DFMT_L6V5U5:
1699 case WINED3DFMT_X8L8V8U8:
1700 case WINED3DFMT_Q8W8V8U8:
1701 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1702 return WINED3D_OK;
1704 /* Those are not advertized by the nvidia windows driver, and not
1705 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1706 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1707 * ARGB format if needed
1709 case WINED3DFMT_W11V11U10:
1710 case WINED3DFMT_A2W10V10U10:
1711 WARN_(d3d_caps)("[FAILED]\n");
1712 return WINED3DERR_NOTAVAILABLE;
1714 /*****
1715 * DXTN Formats: Handled above
1716 * WINED3DFMT_DXT1
1717 * WINED3DFMT_DXT2
1718 * WINED3DFMT_DXT3
1719 * WINED3DFMT_DXT4
1720 * WINED3DFMT_DXT5
1723 /*****
1724 * Odd formats - not supported
1726 case WINED3DFMT_VERTEXDATA:
1727 case WINED3DFMT_INDEX16:
1728 case WINED3DFMT_INDEX32:
1729 case WINED3DFMT_Q16W16V16U16:
1730 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1731 return WINED3DERR_NOTAVAILABLE;
1733 /*****
1734 * Float formats: Not supported right now
1736 case WINED3DFMT_G16R16F:
1737 case WINED3DFMT_G32R32F:
1738 case WINED3DFMT_CxV8U8:
1739 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1740 return WINED3DERR_NOTAVAILABLE;
1742 /* Not supported */
1743 case WINED3DFMT_G16R16:
1744 case WINED3DFMT_A16B16G16R16:
1745 case WINED3DFMT_A8R3G3B2:
1746 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1747 return WINED3DERR_NOTAVAILABLE;
1749 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1750 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1751 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1752 * We can do instancing with all shader versions, but we need vertex shaders.
1754 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1755 * to enable instancing. WineD3D doesn't need that and just ignores it.
1757 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1759 case WINEMAKEFOURCC('I','N','S','T'):
1760 TRACE("ATI Instancing check hack\n");
1761 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1762 TRACE_(d3d_caps)("[OK]\n");
1763 return WINED3D_OK;
1764 } else {
1765 TRACE_(d3d_caps)("[FAILED]\n");
1766 return WINED3DERR_NOTAVAILABLE;
1769 default:
1770 break;
1773 TRACE_(d3d_caps)("[FAILED]\n");
1774 return WINED3DERR_NOTAVAILABLE;
1777 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1778 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1779 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1781 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1782 This,
1783 Adapter,
1784 DeviceType, debug_d3ddevicetype(DeviceType),
1785 SourceFormat, debug_d3dformat(SourceFormat),
1786 TargetFormat, debug_d3dformat(TargetFormat));
1787 return WINED3D_OK;
1790 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1791 subset of a D3DCAPS9 structure. However, it has to come via a void *
1792 as the d3d8 interface cannot import the d3d9 header */
1793 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1795 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1796 int vs_selected_mode;
1797 int ps_selected_mode;
1799 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1801 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1802 return WINED3DERR_INVALIDCALL;
1805 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1807 /* This function should *not* be modifying GL caps
1808 * TODO: move the functionality where it belongs */
1809 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1811 /* ------------------------------------------------
1812 The following fields apply to both d3d8 and d3d9
1813 ------------------------------------------------ */
1814 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1815 *pCaps->AdapterOrdinal = Adapter;
1817 *pCaps->Caps = 0;
1818 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1819 WINED3DCAPS2_FULLSCREENGAMMA |
1820 WINED3DCAPS2_DYNAMICTEXTURES;
1821 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1822 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
1823 WINED3DPRESENT_INTERVAL_ONE;
1825 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1826 WINED3DCURSORCAPS_LOWRES;
1828 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1829 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1830 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1831 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1832 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1833 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1834 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1835 WINED3DDEVCAPS_PUREDEVICE |
1836 WINED3DDEVCAPS_HWRASTERIZATION |
1837 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1838 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1839 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1840 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1841 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1842 WINED3DDEVCAPS_RTPATCHES;
1844 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1845 WINED3DPMISCCAPS_CULLCCW |
1846 WINED3DPMISCCAPS_CULLCW |
1847 WINED3DPMISCCAPS_COLORWRITEENABLE |
1848 WINED3DPMISCCAPS_CLIPTLVERTS |
1849 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1850 WINED3DPMISCCAPS_MASKZ |
1851 WINED3DPMISCCAPS_BLENDOP;
1852 /* TODO:
1853 WINED3DPMISCCAPS_NULLREFERENCE
1854 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1855 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1856 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1857 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1858 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1859 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1861 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1862 #if 0
1863 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1864 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1865 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1866 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1867 #endif
1869 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1870 WINED3DPRASTERCAPS_PAT |
1871 WINED3DPRASTERCAPS_WFOG |
1872 WINED3DPRASTERCAPS_ZFOG |
1873 WINED3DPRASTERCAPS_FOGVERTEX |
1874 WINED3DPRASTERCAPS_FOGTABLE |
1875 WINED3DPRASTERCAPS_STIPPLE |
1876 WINED3DPRASTERCAPS_SUBPIXEL |
1877 WINED3DPRASTERCAPS_ZTEST |
1878 WINED3DPRASTERCAPS_SCISSORTEST |
1879 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1880 WINED3DPRASTERCAPS_DEPTHBIAS;
1882 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1883 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1884 WINED3DPRASTERCAPS_ZBIAS |
1885 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1887 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
1888 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
1890 /* FIXME Add:
1891 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1892 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1893 WINED3DPRASTERCAPS_ANTIALIASEDGES
1894 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1895 WINED3DPRASTERCAPS_WBUFFER */
1897 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1898 WINED3DPCMPCAPS_EQUAL |
1899 WINED3DPCMPCAPS_GREATER |
1900 WINED3DPCMPCAPS_GREATEREQUAL |
1901 WINED3DPCMPCAPS_LESS |
1902 WINED3DPCMPCAPS_LESSEQUAL |
1903 WINED3DPCMPCAPS_NEVER |
1904 WINED3DPCMPCAPS_NOTEQUAL;
1906 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1907 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1908 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1909 WINED3DPBLENDCAPS_DESTALPHA |
1910 WINED3DPBLENDCAPS_DESTCOLOR |
1911 WINED3DPBLENDCAPS_INVDESTALPHA |
1912 WINED3DPBLENDCAPS_INVDESTCOLOR |
1913 WINED3DPBLENDCAPS_INVSRCALPHA |
1914 WINED3DPBLENDCAPS_INVSRCCOLOR |
1915 WINED3DPBLENDCAPS_ONE |
1916 WINED3DPBLENDCAPS_SRCALPHA |
1917 WINED3DPBLENDCAPS_SRCALPHASAT |
1918 WINED3DPBLENDCAPS_SRCCOLOR |
1919 WINED3DPBLENDCAPS_ZERO;
1921 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1922 WINED3DPBLENDCAPS_DESTALPHA |
1923 WINED3DPBLENDCAPS_DESTCOLOR |
1924 WINED3DPBLENDCAPS_INVDESTALPHA |
1925 WINED3DPBLENDCAPS_INVDESTCOLOR |
1926 WINED3DPBLENDCAPS_INVSRCALPHA |
1927 WINED3DPBLENDCAPS_INVSRCCOLOR |
1928 WINED3DPBLENDCAPS_ONE |
1929 WINED3DPBLENDCAPS_SRCALPHA |
1930 WINED3DPBLENDCAPS_SRCCOLOR |
1931 WINED3DPBLENDCAPS_ZERO;
1932 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
1933 * according to the glBlendFunc manpage
1935 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
1936 * legacy settings for srcblend only
1939 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1940 WINED3DPCMPCAPS_EQUAL |
1941 WINED3DPCMPCAPS_GREATER |
1942 WINED3DPCMPCAPS_GREATEREQUAL |
1943 WINED3DPCMPCAPS_LESS |
1944 WINED3DPCMPCAPS_LESSEQUAL |
1945 WINED3DPCMPCAPS_NEVER |
1946 WINED3DPCMPCAPS_NOTEQUAL;
1948 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1949 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1950 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1951 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1952 WINED3DPSHADECAPS_COLORFLATRGB |
1953 WINED3DPSHADECAPS_FOGFLAT |
1954 WINED3DPSHADECAPS_FOGGOURAUD |
1955 WINED3DPSHADECAPS_SPECULARFLATRGB;
1957 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1958 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1959 WINED3DPTEXTURECAPS_BORDER |
1960 WINED3DPTEXTURECAPS_MIPMAP |
1961 WINED3DPTEXTURECAPS_PROJECTED |
1962 WINED3DPTEXTURECAPS_PERSPECTIVE;
1964 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
1965 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
1966 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1969 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1970 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1971 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1972 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1975 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1976 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1977 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1978 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1982 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1983 WINED3DPTFILTERCAPS_MAGFPOINT |
1984 WINED3DPTFILTERCAPS_MINFLINEAR |
1985 WINED3DPTFILTERCAPS_MINFPOINT |
1986 WINED3DPTFILTERCAPS_MIPFLINEAR |
1987 WINED3DPTFILTERCAPS_MIPFPOINT |
1988 WINED3DPTFILTERCAPS_LINEAR |
1989 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1990 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1991 WINED3DPTFILTERCAPS_MIPLINEAR |
1992 WINED3DPTFILTERCAPS_MIPNEAREST |
1993 WINED3DPTFILTERCAPS_NEAREST;
1995 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1996 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1997 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2000 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2001 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2002 WINED3DPTFILTERCAPS_MAGFPOINT |
2003 WINED3DPTFILTERCAPS_MINFLINEAR |
2004 WINED3DPTFILTERCAPS_MINFPOINT |
2005 WINED3DPTFILTERCAPS_MIPFLINEAR |
2006 WINED3DPTFILTERCAPS_MIPFPOINT |
2007 WINED3DPTFILTERCAPS_LINEAR |
2008 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2009 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2010 WINED3DPTFILTERCAPS_MIPLINEAR |
2011 WINED3DPTFILTERCAPS_MIPNEAREST |
2012 WINED3DPTFILTERCAPS_NEAREST;
2014 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2015 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2016 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2018 } else
2019 *pCaps->CubeTextureFilterCaps = 0;
2021 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2022 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2023 WINED3DPTFILTERCAPS_MAGFPOINT |
2024 WINED3DPTFILTERCAPS_MINFLINEAR |
2025 WINED3DPTFILTERCAPS_MINFPOINT |
2026 WINED3DPTFILTERCAPS_MIPFLINEAR |
2027 WINED3DPTFILTERCAPS_MIPFPOINT |
2028 WINED3DPTFILTERCAPS_LINEAR |
2029 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2030 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2031 WINED3DPTFILTERCAPS_MIPLINEAR |
2032 WINED3DPTFILTERCAPS_MIPNEAREST |
2033 WINED3DPTFILTERCAPS_NEAREST;
2034 } else
2035 *pCaps->VolumeTextureFilterCaps = 0;
2037 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2038 WINED3DPTADDRESSCAPS_CLAMP |
2039 WINED3DPTADDRESSCAPS_WRAP;
2041 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2042 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2044 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2045 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2047 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2048 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2051 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2052 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2053 WINED3DPTADDRESSCAPS_CLAMP |
2054 WINED3DPTADDRESSCAPS_WRAP;
2055 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2056 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2058 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2059 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2061 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2062 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2064 } else
2065 *pCaps->VolumeTextureAddressCaps = 0;
2067 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2068 WINED3DLINECAPS_ZTEST;
2069 /* FIXME: Add
2070 WINED3DLINECAPS_BLEND
2071 WINED3DLINECAPS_ALPHACMP
2072 WINED3DLINECAPS_FOG */
2074 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2075 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2077 if(GL_SUPPORT(EXT_TEXTURE3D))
2078 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2079 else
2080 *pCaps->MaxVolumeExtent = 0;
2082 *pCaps->MaxTextureRepeat = 32768;
2083 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2084 *pCaps->MaxVertexW = 1.0;
2086 *pCaps->GuardBandLeft = 0;
2087 *pCaps->GuardBandTop = 0;
2088 *pCaps->GuardBandRight = 0;
2089 *pCaps->GuardBandBottom = 0;
2091 *pCaps->ExtentsAdjust = 0;
2093 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2094 WINED3DSTENCILCAPS_INCRSAT |
2095 WINED3DSTENCILCAPS_INVERT |
2096 WINED3DSTENCILCAPS_KEEP |
2097 WINED3DSTENCILCAPS_REPLACE |
2098 WINED3DSTENCILCAPS_ZERO;
2099 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2100 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2101 WINED3DSTENCILCAPS_INCR;
2103 if ( This->dxVersion > 8 &&
2104 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2105 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2106 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2109 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2111 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2112 WINED3DTEXOPCAPS_ADDSIGNED |
2113 WINED3DTEXOPCAPS_ADDSIGNED2X |
2114 WINED3DTEXOPCAPS_MODULATE |
2115 WINED3DTEXOPCAPS_MODULATE2X |
2116 WINED3DTEXOPCAPS_MODULATE4X |
2117 WINED3DTEXOPCAPS_SELECTARG1 |
2118 WINED3DTEXOPCAPS_SELECTARG2 |
2119 WINED3DTEXOPCAPS_DISABLE;
2121 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2122 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2123 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2124 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2125 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2126 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2127 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2128 WINED3DTEXOPCAPS_LERP |
2129 WINED3DTEXOPCAPS_SUBTRACT;
2131 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2132 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2133 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2134 WINED3DTEXOPCAPS_MULTIPLYADD |
2135 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2136 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2137 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2139 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2140 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2142 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2143 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2144 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2147 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2148 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2149 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2150 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2151 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2152 * and 3D textures. It also allows us to keep the code simpler by having texture
2153 * shaders constantly enabled.
2155 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2156 /* TODO: Luminance bump map? */
2158 #if 0
2159 /* FIXME: Add
2160 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2161 WINED3DTEXOPCAPS_PREMODULATE */
2162 #endif
2164 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2165 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2166 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2167 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2169 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2170 *pCaps->MaxVertexBlendMatrixIndex = 0;
2172 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2173 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2176 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2177 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2178 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2179 WINED3DVTXPCAPS_LOCALVIEWER |
2180 WINED3DVTXPCAPS_VERTEXFOG |
2181 WINED3DVTXPCAPS_TEXGEN;
2182 /* FIXME: Add
2183 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2185 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2186 *pCaps->MaxVertexIndex = 0xFFFFF;
2187 *pCaps->MaxStreams = MAX_STREAMS;
2188 *pCaps->MaxStreamStride = 1024;
2190 if (vs_selected_mode == SHADER_GLSL) {
2191 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2192 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2193 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2194 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2195 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2196 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2197 else
2198 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2199 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2200 } else if (vs_selected_mode == SHADER_ARB) {
2201 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2202 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2203 } else {
2204 *pCaps->VertexShaderVersion = 0;
2205 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2208 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2210 if (ps_selected_mode == SHADER_GLSL) {
2211 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2212 in case of GeforceFX cards. */
2213 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2214 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2215 else
2216 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2217 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2218 * Direct3D minimum requirement.
2220 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2221 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2223 * The problem is that the refrast clamps temporary results in the shader to
2224 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2225 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2226 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2227 * offer a way to query this.
2229 *pCaps->PixelShader1xMaxValue = 8.0;
2230 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2231 } else if (ps_selected_mode == SHADER_ARB) {
2232 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2233 *pCaps->PixelShader1xMaxValue = 8.0;
2234 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2235 } else {
2236 *pCaps->PixelShaderVersion = 0;
2237 *pCaps->PixelShader1xMaxValue = 0.0;
2238 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2241 /* ------------------------------------------------
2242 The following fields apply to d3d9 only
2243 ------------------------------------------------ */
2244 if (This->dxVersion > 8) {
2245 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2246 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2247 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2248 *pCaps->MaxNpatchTessellationLevel = 0;
2249 *pCaps->MasterAdapterOrdinal = 0;
2250 *pCaps->AdapterOrdinalInGroup = 0;
2251 *pCaps->NumberOfAdaptersInGroup = 1;
2253 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2254 /* OpenGL supports all the formats below, perhaps not always
2255 * without conversion, but it supports them.
2256 * Further GLSL doesn't seem to have an official unsigned type so
2257 * don't advertise it yet as I'm not sure how we handle it.
2258 * We might need to add some clamping in the shader engine to
2259 * support it.
2260 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2261 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2262 WINED3DDTCAPS_UBYTE4N |
2263 WINED3DDTCAPS_SHORT2N |
2264 WINED3DDTCAPS_SHORT4N;
2265 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2266 *pCaps->DeclTypes |=
2267 WINED3DDTCAPS_FLOAT16_2 |
2268 WINED3DDTCAPS_FLOAT16_4;
2270 } else
2271 *pCaps->DeclTypes = 0;
2273 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2276 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2277 WINED3DPTFILTERCAPS_MAGFPOINT |
2278 WINED3DPTFILTERCAPS_MINFLINEAR |
2279 WINED3DPTFILTERCAPS_MAGFLINEAR;
2280 *pCaps->VertexTextureFilterCaps = 0;
2282 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2283 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2284 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2285 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2286 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2287 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2288 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2290 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2291 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2292 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2293 *pCaps->VS20Caps.Caps = 0;
2294 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2295 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2296 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2298 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2299 *pCaps->MaxVertexShader30InstructionSlots = 0;
2300 } else { /* VS 1.x */
2301 *pCaps->VS20Caps.Caps = 0;
2302 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2303 *pCaps->VS20Caps.NumTemps = 0;
2304 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2306 *pCaps->MaxVShaderInstructionsExecuted = 0;
2307 *pCaps->MaxVertexShader30InstructionSlots = 0;
2310 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2311 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2312 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2314 /* 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 */
2315 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2316 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2317 WINED3DPS20CAPS_PREDICATION |
2318 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2319 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2320 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2321 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2322 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2323 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2325 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2326 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2327 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2328 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2329 *pCaps->PS20Caps.Caps = 0;
2330 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2331 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2332 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2333 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2335 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2336 *pCaps->MaxPixelShader30InstructionSlots = 0;
2337 } else { /* PS 1.x */
2338 *pCaps->PS20Caps.Caps = 0;
2339 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2340 *pCaps->PS20Caps.NumTemps = 0;
2341 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2342 *pCaps->PS20Caps.NumInstructionSlots = 0;
2344 *pCaps->MaxPShaderInstructionsExecuted = 0;
2345 *pCaps->MaxPixelShader30InstructionSlots = 0;
2349 return WINED3D_OK;
2352 static unsigned int glsl_program_key_hash(void *key) {
2353 glsl_program_key_t *k = (glsl_program_key_t *)key;
2355 unsigned int hash = k->vshader | k->pshader << 16;
2356 hash += ~(hash << 15);
2357 hash ^= (hash >> 10);
2358 hash += (hash << 3);
2359 hash ^= (hash >> 6);
2360 hash += ~(hash << 11);
2361 hash ^= (hash >> 16);
2363 return hash;
2366 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2367 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2368 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2370 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2373 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2374 and fields being inserted in the middle, a new structure is used in place */
2375 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2376 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2377 IUnknown *parent) {
2379 IWineD3DDeviceImpl *object = NULL;
2380 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2381 HDC hDC;
2382 int i;
2384 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2385 * number and create a device without a 3D adapter for 2D only operation.
2387 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2388 return WINED3DERR_INVALIDCALL;
2391 /* Create a WineD3DDevice object */
2392 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2393 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2394 TRACE("Created WineD3DDevice object @ %p\n", object);
2395 if (NULL == object) {
2396 return WINED3DERR_OUTOFVIDEOMEMORY;
2399 /* Set up initial COM information */
2400 object->lpVtbl = &IWineD3DDevice_Vtbl;
2401 object->ref = 1;
2402 object->wineD3D = iface;
2403 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2404 IWineD3D_AddRef(object->wineD3D);
2405 object->parent = parent;
2407 if(This->dxVersion == 7) {
2408 object->surface_alignment = 8;
2409 } else {
2410 object->surface_alignment = 4;
2413 /* Set the state up as invalid until the device is fully created */
2414 object->state = WINED3DERR_DRIVERINTERNALERROR;
2416 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2417 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2419 /* Save the creation parameters */
2420 object->createParms.AdapterOrdinal = Adapter;
2421 object->createParms.DeviceType = DeviceType;
2422 object->createParms.hFocusWindow = hFocusWindow;
2423 object->createParms.BehaviorFlags = BehaviourFlags;
2425 /* Initialize other useful values */
2426 object->adapterNo = Adapter;
2427 object->devType = DeviceType;
2429 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2430 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2431 object->shader_backend = &glsl_shader_backend;
2432 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2433 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2434 object->shader_backend = &arb_program_shader_backend;
2435 } else {
2436 object->shader_backend = &none_shader_backend;
2439 /* set the state of the device to valid */
2440 object->state = WINED3D_OK;
2442 /* Get the initial screen setup for ddraw */
2443 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2444 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2445 hDC = GetDC(0);
2446 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2447 ReleaseDC(0, hDC);
2449 for(i = 0; i < PATCHMAP_SIZE; i++) {
2450 list_init(&object->patches[i]);
2452 return WINED3D_OK;
2454 #undef GLINFO_LOCATION
2456 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2457 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2458 IUnknown_AddRef(This->parent);
2459 *pParent = This->parent;
2460 return WINED3D_OK;
2463 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2464 IUnknown* surfaceParent;
2465 TRACE("(%p) call back\n", pSurface);
2467 /* Now, release the parent, which will take care of cleaning up the surface for us */
2468 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2469 IUnknown_Release(surfaceParent);
2470 return IUnknown_Release(surfaceParent);
2473 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2474 IUnknown* volumeParent;
2475 TRACE("(%p) call back\n", pVolume);
2477 /* Now, release the parent, which will take care of cleaning up the volume for us */
2478 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2479 IUnknown_Release(volumeParent);
2480 return IUnknown_Release(volumeParent);
2483 #define PUSH1(att) attribs[nAttribs++] = (att);
2484 #define GLINFO_LOCATION (Adapters[0].gl_info)
2485 BOOL InitAdapters(void) {
2486 static HMODULE mod_gl;
2487 BOOL ret;
2488 int ps_selected_mode, vs_selected_mode;
2490 /* No need to hold any lock. The calling library makes sure only one thread calls
2491 * wined3d simultaneously
2493 if(numAdapters > 0) return TRUE;
2495 TRACE("Initializing adapters\n");
2497 if(!mod_gl) {
2498 #ifdef USE_WIN32_OPENGL
2499 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2500 mod_gl = LoadLibraryA("opengl32.dll");
2501 if(!mod_gl) {
2502 ERR("Can't load opengl32.dll!\n");
2503 return FALSE;
2505 #else
2506 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2507 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2508 mod_gl = GetModuleHandleA("gdi32.dll");
2509 #endif
2512 /* Load WGL core functions from opengl32.dll */
2513 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2514 WGL_FUNCS_GEN;
2515 #undef USE_WGL_FUNC
2517 if(!pwglGetProcAddress) {
2518 ERR("Unable to load wglGetProcAddress!\n");
2519 return FALSE;
2522 /* Dynamically load all GL core functions */
2523 GL_FUNCS_GEN;
2524 #undef USE_GL_FUNC
2526 /* For now only one default adapter */
2528 int iPixelFormat;
2529 int attribs[8];
2530 int values[8];
2531 int nAttribs = 0;
2532 int res;
2533 WineD3D_PixelFormat *cfgs;
2534 int attribute;
2535 DISPLAY_DEVICEW DisplayDevice;
2536 HDC hdc;
2538 TRACE("Initializing default adapter\n");
2539 Adapters[0].monitorPoint.x = -1;
2540 Adapters[0].monitorPoint.y = -1;
2542 if (!WineD3D_CreateFakeGLContext()) {
2543 ERR("Failed to get a gl context for default adapter\n");
2544 HeapFree(GetProcessHeap(), 0, Adapters);
2545 WineD3D_ReleaseFakeGLContext();
2546 return FALSE;
2549 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2550 if(!ret) {
2551 ERR("Failed to initialize gl caps for default adapter\n");
2552 HeapFree(GetProcessHeap(), 0, Adapters);
2553 WineD3D_ReleaseFakeGLContext();
2554 return FALSE;
2556 ret = initPixelFormats(&Adapters[0].gl_info);
2557 if(!ret) {
2558 ERR("Failed to init gl formats\n");
2559 HeapFree(GetProcessHeap(), 0, Adapters);
2560 WineD3D_ReleaseFakeGLContext();
2561 return FALSE;
2564 hdc = pwglGetCurrentDC();
2565 if(!hdc) {
2566 ERR("Failed to get gl HDC\n");
2567 HeapFree(GetProcessHeap(), 0, Adapters);
2568 WineD3D_ReleaseFakeGLContext();
2569 return FALSE;
2572 Adapters[0].driver = "Display";
2573 Adapters[0].description = "Direct3D HAL";
2575 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2576 DisplayDevice.cb = sizeof(DisplayDevice);
2577 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2578 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2579 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2581 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2582 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2584 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2585 cfgs = Adapters[0].cfgs;
2586 PUSH1(WGL_RED_BITS_ARB)
2587 PUSH1(WGL_GREEN_BITS_ARB)
2588 PUSH1(WGL_BLUE_BITS_ARB)
2589 PUSH1(WGL_ALPHA_BITS_ARB)
2590 PUSH1(WGL_DEPTH_BITS_ARB)
2591 PUSH1(WGL_STENCIL_BITS_ARB)
2593 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2594 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2596 if(!res)
2597 continue;
2599 /* Cache the pixel format */
2600 cfgs->iPixelFormat = iPixelFormat;
2601 cfgs->redSize = values[0];
2602 cfgs->greenSize = values[1];
2603 cfgs->blueSize = values[2];
2604 cfgs->alphaSize = values[3];
2605 cfgs->depthSize = values[4];
2606 cfgs->stencilSize = values[5];
2608 TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize);
2609 cfgs++;
2611 WineD3D_ReleaseFakeGLContext();
2613 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2614 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2617 numAdapters = 1;
2618 TRACE("%d adapters successfully initialized\n", numAdapters);
2620 return TRUE;
2622 #undef PUSH1
2623 #undef GLINFO_LOCATION
2625 /**********************************************************
2626 * IWineD3D VTbl follows
2627 **********************************************************/
2629 const IWineD3DVtbl IWineD3D_Vtbl =
2631 /* IUnknown */
2632 IWineD3DImpl_QueryInterface,
2633 IWineD3DImpl_AddRef,
2634 IWineD3DImpl_Release,
2635 /* IWineD3D */
2636 IWineD3DImpl_GetParent,
2637 IWineD3DImpl_GetAdapterCount,
2638 IWineD3DImpl_RegisterSoftwareDevice,
2639 IWineD3DImpl_GetAdapterMonitor,
2640 IWineD3DImpl_GetAdapterModeCount,
2641 IWineD3DImpl_EnumAdapterModes,
2642 IWineD3DImpl_GetAdapterDisplayMode,
2643 IWineD3DImpl_GetAdapterIdentifier,
2644 IWineD3DImpl_CheckDeviceMultiSampleType,
2645 IWineD3DImpl_CheckDepthStencilMatch,
2646 IWineD3DImpl_CheckDeviceType,
2647 IWineD3DImpl_CheckDeviceFormat,
2648 IWineD3DImpl_CheckDeviceFormatConversion,
2649 IWineD3DImpl_GetDeviceCaps,
2650 IWineD3DImpl_CreateDevice