wined3d: Only use one fake context when building adapter info.
[wine/multimedia.git] / dlls / wined3d / directx.c
blob29d54eeb66ebf934c1a952dc179d39d4a4486d28
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 for now: Bump mapping formats
1692 * Enable some because games often fail when they are not available
1693 * and are still playable even without bump mapping
1695 case WINED3DFMT_V8U8:
1696 case WINED3DFMT_V16U16:
1697 case WINED3DFMT_L6V5U5:
1698 case WINED3DFMT_X8L8V8U8:
1699 case WINED3DFMT_Q8W8V8U8:
1700 case WINED3DFMT_W11V11U10:
1701 case WINED3DFMT_A2W10V10U10:
1702 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1703 return WINED3D_OK;
1705 /*****
1706 * DXTN Formats: Handled above
1707 * WINED3DFMT_DXT1
1708 * WINED3DFMT_DXT2
1709 * WINED3DFMT_DXT3
1710 * WINED3DFMT_DXT4
1711 * WINED3DFMT_DXT5
1714 /*****
1715 * Odd formats - not supported
1717 case WINED3DFMT_VERTEXDATA:
1718 case WINED3DFMT_INDEX16:
1719 case WINED3DFMT_INDEX32:
1720 case WINED3DFMT_Q16W16V16U16:
1721 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1722 return WINED3DERR_NOTAVAILABLE;
1724 /*****
1725 * Float formats: Not supported right now
1727 case WINED3DFMT_G16R16F:
1728 case WINED3DFMT_G32R32F:
1729 case WINED3DFMT_CxV8U8:
1730 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1731 return WINED3DERR_NOTAVAILABLE;
1733 /* Not supported */
1734 case WINED3DFMT_G16R16:
1735 case WINED3DFMT_A16B16G16R16:
1736 case WINED3DFMT_A8R3G3B2:
1737 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1738 return WINED3DERR_NOTAVAILABLE;
1740 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1741 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1742 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1743 * We can do instancing with all shader versions, but we need vertex shaders.
1745 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1746 * to enable instancing. WineD3D doesn't need that and just ignores it.
1748 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1750 case WINEMAKEFOURCC('I','N','S','T'):
1751 TRACE("ATI Instancing check hack\n");
1752 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1753 TRACE_(d3d_caps)("[OK]\n");
1754 return WINED3D_OK;
1755 } else {
1756 TRACE_(d3d_caps)("[FAILED]\n");
1757 return WINED3DERR_NOTAVAILABLE;
1760 default:
1761 break;
1764 TRACE_(d3d_caps)("[FAILED]\n");
1765 return WINED3DERR_NOTAVAILABLE;
1768 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1769 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1770 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1772 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1773 This,
1774 Adapter,
1775 DeviceType, debug_d3ddevicetype(DeviceType),
1776 SourceFormat, debug_d3dformat(SourceFormat),
1777 TargetFormat, debug_d3dformat(TargetFormat));
1778 return WINED3D_OK;
1781 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1782 subset of a D3DCAPS9 structure. However, it has to come via a void *
1783 as the d3d8 interface cannot import the d3d9 header */
1784 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1786 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1787 int vs_selected_mode;
1788 int ps_selected_mode;
1790 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1792 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1793 return WINED3DERR_INVALIDCALL;
1796 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1798 /* This function should *not* be modifying GL caps
1799 * TODO: move the functionality where it belongs */
1800 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1802 /* ------------------------------------------------
1803 The following fields apply to both d3d8 and d3d9
1804 ------------------------------------------------ */
1805 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1806 *pCaps->AdapterOrdinal = Adapter;
1808 *pCaps->Caps = 0;
1809 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1810 WINED3DCAPS2_FULLSCREENGAMMA |
1811 WINED3DCAPS2_DYNAMICTEXTURES;
1812 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1813 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1815 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1816 WINED3DCURSORCAPS_LOWRES;
1818 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1819 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1820 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1821 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1822 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1823 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1824 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1825 WINED3DDEVCAPS_PUREDEVICE |
1826 WINED3DDEVCAPS_HWRASTERIZATION |
1827 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1828 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1829 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1830 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1831 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1832 WINED3DDEVCAPS_RTPATCHES;
1834 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1835 WINED3DPMISCCAPS_CULLCCW |
1836 WINED3DPMISCCAPS_CULLCW |
1837 WINED3DPMISCCAPS_COLORWRITEENABLE |
1838 WINED3DPMISCCAPS_CLIPTLVERTS |
1839 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1840 WINED3DPMISCCAPS_MASKZ |
1841 WINED3DPMISCCAPS_BLENDOP;
1842 /* TODO:
1843 WINED3DPMISCCAPS_NULLREFERENCE
1844 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1845 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1846 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1847 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1848 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1849 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1851 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1852 #if 0
1853 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1854 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1855 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1856 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1857 #endif
1859 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1860 WINED3DPRASTERCAPS_PAT |
1861 WINED3DPRASTERCAPS_WFOG |
1862 WINED3DPRASTERCAPS_ZFOG |
1863 WINED3DPRASTERCAPS_FOGVERTEX |
1864 WINED3DPRASTERCAPS_FOGTABLE |
1865 WINED3DPRASTERCAPS_STIPPLE |
1866 WINED3DPRASTERCAPS_SUBPIXEL |
1867 WINED3DPRASTERCAPS_ZTEST |
1868 WINED3DPRASTERCAPS_SCISSORTEST |
1869 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1870 WINED3DPRASTERCAPS_DEPTHBIAS;
1872 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1873 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1874 WINED3DPRASTERCAPS_ZBIAS |
1875 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1877 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
1878 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
1880 /* FIXME Add:
1881 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1882 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1883 WINED3DPRASTERCAPS_ANTIALIASEDGES
1884 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1885 WINED3DPRASTERCAPS_WBUFFER */
1887 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1888 WINED3DPCMPCAPS_EQUAL |
1889 WINED3DPCMPCAPS_GREATER |
1890 WINED3DPCMPCAPS_GREATEREQUAL |
1891 WINED3DPCMPCAPS_LESS |
1892 WINED3DPCMPCAPS_LESSEQUAL |
1893 WINED3DPCMPCAPS_NEVER |
1894 WINED3DPCMPCAPS_NOTEQUAL;
1896 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1897 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1898 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1899 WINED3DPBLENDCAPS_DESTALPHA |
1900 WINED3DPBLENDCAPS_DESTCOLOR |
1901 WINED3DPBLENDCAPS_INVDESTALPHA |
1902 WINED3DPBLENDCAPS_INVDESTCOLOR |
1903 WINED3DPBLENDCAPS_INVSRCALPHA |
1904 WINED3DPBLENDCAPS_INVSRCCOLOR |
1905 WINED3DPBLENDCAPS_ONE |
1906 WINED3DPBLENDCAPS_SRCALPHA |
1907 WINED3DPBLENDCAPS_SRCALPHASAT |
1908 WINED3DPBLENDCAPS_SRCCOLOR |
1909 WINED3DPBLENDCAPS_ZERO;
1911 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1912 WINED3DPBLENDCAPS_DESTALPHA |
1913 WINED3DPBLENDCAPS_DESTCOLOR |
1914 WINED3DPBLENDCAPS_INVDESTALPHA |
1915 WINED3DPBLENDCAPS_INVDESTCOLOR |
1916 WINED3DPBLENDCAPS_INVSRCALPHA |
1917 WINED3DPBLENDCAPS_INVSRCCOLOR |
1918 WINED3DPBLENDCAPS_ONE |
1919 WINED3DPBLENDCAPS_SRCALPHA |
1920 WINED3DPBLENDCAPS_SRCCOLOR |
1921 WINED3DPBLENDCAPS_ZERO;
1922 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
1923 * according to the glBlendFunc manpage
1925 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
1926 * legacy settings for srcblend only
1929 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1930 WINED3DPCMPCAPS_EQUAL |
1931 WINED3DPCMPCAPS_GREATER |
1932 WINED3DPCMPCAPS_GREATEREQUAL |
1933 WINED3DPCMPCAPS_LESS |
1934 WINED3DPCMPCAPS_LESSEQUAL |
1935 WINED3DPCMPCAPS_NEVER |
1936 WINED3DPCMPCAPS_NOTEQUAL;
1938 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1939 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1940 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1941 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1942 WINED3DPSHADECAPS_COLORFLATRGB |
1943 WINED3DPSHADECAPS_FOGFLAT |
1944 WINED3DPSHADECAPS_FOGGOURAUD |
1945 WINED3DPSHADECAPS_SPECULARFLATRGB;
1947 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1948 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1949 WINED3DPTEXTURECAPS_BORDER |
1950 WINED3DPTEXTURECAPS_MIPMAP |
1951 WINED3DPTEXTURECAPS_PROJECTED |
1952 WINED3DPTEXTURECAPS_PERSPECTIVE;
1954 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
1955 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
1956 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1959 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1960 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1961 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1962 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1965 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1966 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1967 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1968 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1972 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1973 WINED3DPTFILTERCAPS_MAGFPOINT |
1974 WINED3DPTFILTERCAPS_MINFLINEAR |
1975 WINED3DPTFILTERCAPS_MINFPOINT |
1976 WINED3DPTFILTERCAPS_MIPFLINEAR |
1977 WINED3DPTFILTERCAPS_MIPFPOINT |
1978 WINED3DPTFILTERCAPS_LINEAR |
1979 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1980 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1981 WINED3DPTFILTERCAPS_MIPLINEAR |
1982 WINED3DPTFILTERCAPS_MIPNEAREST |
1983 WINED3DPTFILTERCAPS_NEAREST;
1985 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1986 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1987 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1990 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1991 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1992 WINED3DPTFILTERCAPS_MAGFPOINT |
1993 WINED3DPTFILTERCAPS_MINFLINEAR |
1994 WINED3DPTFILTERCAPS_MINFPOINT |
1995 WINED3DPTFILTERCAPS_MIPFLINEAR |
1996 WINED3DPTFILTERCAPS_MIPFPOINT |
1997 WINED3DPTFILTERCAPS_LINEAR |
1998 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1999 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2000 WINED3DPTFILTERCAPS_MIPLINEAR |
2001 WINED3DPTFILTERCAPS_MIPNEAREST |
2002 WINED3DPTFILTERCAPS_NEAREST;
2004 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2005 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2006 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2008 } else
2009 *pCaps->CubeTextureFilterCaps = 0;
2011 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2012 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2013 WINED3DPTFILTERCAPS_MAGFPOINT |
2014 WINED3DPTFILTERCAPS_MINFLINEAR |
2015 WINED3DPTFILTERCAPS_MINFPOINT |
2016 WINED3DPTFILTERCAPS_MIPFLINEAR |
2017 WINED3DPTFILTERCAPS_MIPFPOINT |
2018 WINED3DPTFILTERCAPS_LINEAR |
2019 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2020 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2021 WINED3DPTFILTERCAPS_MIPLINEAR |
2022 WINED3DPTFILTERCAPS_MIPNEAREST |
2023 WINED3DPTFILTERCAPS_NEAREST;
2024 } else
2025 *pCaps->VolumeTextureFilterCaps = 0;
2027 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2028 WINED3DPTADDRESSCAPS_CLAMP |
2029 WINED3DPTADDRESSCAPS_WRAP;
2031 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2032 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2034 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2035 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2037 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2038 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2041 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2042 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2043 WINED3DPTADDRESSCAPS_CLAMP |
2044 WINED3DPTADDRESSCAPS_WRAP;
2045 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2046 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2048 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2049 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2051 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2052 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2054 } else
2055 *pCaps->VolumeTextureAddressCaps = 0;
2057 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2058 WINED3DLINECAPS_ZTEST;
2059 /* FIXME: Add
2060 WINED3DLINECAPS_BLEND
2061 WINED3DLINECAPS_ALPHACMP
2062 WINED3DLINECAPS_FOG */
2064 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2065 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2067 if(GL_SUPPORT(EXT_TEXTURE3D))
2068 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2069 else
2070 *pCaps->MaxVolumeExtent = 0;
2072 *pCaps->MaxTextureRepeat = 32768;
2073 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2074 *pCaps->MaxVertexW = 1.0;
2076 *pCaps->GuardBandLeft = 0;
2077 *pCaps->GuardBandTop = 0;
2078 *pCaps->GuardBandRight = 0;
2079 *pCaps->GuardBandBottom = 0;
2081 *pCaps->ExtentsAdjust = 0;
2083 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2084 WINED3DSTENCILCAPS_INCRSAT |
2085 WINED3DSTENCILCAPS_INVERT |
2086 WINED3DSTENCILCAPS_KEEP |
2087 WINED3DSTENCILCAPS_REPLACE |
2088 WINED3DSTENCILCAPS_ZERO;
2089 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2090 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2091 WINED3DSTENCILCAPS_INCR;
2093 if ( This->dxVersion > 8 &&
2094 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2095 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2096 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2099 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2101 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2102 WINED3DTEXOPCAPS_ADDSIGNED |
2103 WINED3DTEXOPCAPS_ADDSIGNED2X |
2104 WINED3DTEXOPCAPS_MODULATE |
2105 WINED3DTEXOPCAPS_MODULATE2X |
2106 WINED3DTEXOPCAPS_MODULATE4X |
2107 WINED3DTEXOPCAPS_SELECTARG1 |
2108 WINED3DTEXOPCAPS_SELECTARG2 |
2109 WINED3DTEXOPCAPS_DISABLE;
2111 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2112 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2113 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2114 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2115 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2116 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2117 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2118 WINED3DTEXOPCAPS_LERP |
2119 WINED3DTEXOPCAPS_SUBTRACT;
2121 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2122 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2123 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2124 WINED3DTEXOPCAPS_MULTIPLYADD |
2125 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2126 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2127 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2129 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2130 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2132 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2133 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2134 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2137 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2138 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2139 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2140 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2141 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2142 * and 3D textures. It also allows us to keep the code simpler by having texture
2143 * shaders constantly enabled.
2145 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2146 /* TODO: Luminance bump map? */
2148 #if 0
2149 /* FIXME: Add
2150 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2151 WINED3DTEXOPCAPS_PREMODULATE */
2152 #endif
2154 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2155 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2156 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2157 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2159 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2160 *pCaps->MaxVertexBlendMatrixIndex = 0;
2162 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2163 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2166 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2167 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2168 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2169 WINED3DVTXPCAPS_LOCALVIEWER |
2170 WINED3DVTXPCAPS_VERTEXFOG |
2171 WINED3DVTXPCAPS_TEXGEN;
2172 /* FIXME: Add
2173 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2175 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2176 *pCaps->MaxVertexIndex = 0xFFFFF;
2177 *pCaps->MaxStreams = MAX_STREAMS;
2178 *pCaps->MaxStreamStride = 1024;
2180 if (vs_selected_mode == SHADER_GLSL) {
2181 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2182 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2183 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2184 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2185 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2186 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2187 else
2188 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2189 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2190 } else if (vs_selected_mode == SHADER_ARB) {
2191 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2192 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2193 } else {
2194 *pCaps->VertexShaderVersion = 0;
2195 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2198 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2200 if (ps_selected_mode == SHADER_GLSL) {
2201 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2202 in case of GeforceFX cards. */
2203 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2204 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2205 else
2206 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2207 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2208 *pCaps->PixelShader1xMaxValue = 1.0;
2209 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2210 } else if (ps_selected_mode == SHADER_ARB) {
2211 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2212 *pCaps->PixelShader1xMaxValue = 1.0;
2213 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2214 } else {
2215 *pCaps->PixelShaderVersion = 0;
2216 *pCaps->PixelShader1xMaxValue = 0.0;
2217 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2220 /* ------------------------------------------------
2221 The following fields apply to d3d9 only
2222 ------------------------------------------------ */
2223 if (This->dxVersion > 8) {
2224 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2225 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2226 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2227 *pCaps->MaxNpatchTessellationLevel = 0;
2228 *pCaps->MasterAdapterOrdinal = 0;
2229 *pCaps->AdapterOrdinalInGroup = 0;
2230 *pCaps->NumberOfAdaptersInGroup = 1;
2232 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2233 /* OpenGL supports all the formats below, perhaps not always
2234 * without conversion, but it supports them.
2235 * Further GLSL doesn't seem to have an official unsigned type so
2236 * don't advertise it yet as I'm not sure how we handle it.
2237 * We might need to add some clamping in the shader engine to
2238 * support it.
2239 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2240 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2241 WINED3DDTCAPS_UBYTE4N |
2242 WINED3DDTCAPS_SHORT2N |
2243 WINED3DDTCAPS_SHORT4N;
2244 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2245 *pCaps->DeclTypes |=
2246 WINED3DDTCAPS_FLOAT16_2 |
2247 WINED3DDTCAPS_FLOAT16_4;
2249 } else
2250 *pCaps->DeclTypes = 0;
2252 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2255 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2256 WINED3DPTFILTERCAPS_MAGFPOINT |
2257 WINED3DPTFILTERCAPS_MINFLINEAR |
2258 WINED3DPTFILTERCAPS_MAGFLINEAR;
2259 *pCaps->VertexTextureFilterCaps = 0;
2261 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2262 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2263 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2264 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2265 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2266 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2267 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2269 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2270 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2271 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2272 *pCaps->VS20Caps.Caps = 0;
2273 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2274 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2275 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2277 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2278 *pCaps->MaxVertexShader30InstructionSlots = 0;
2279 } else { /* VS 1.x */
2280 *pCaps->VS20Caps.Caps = 0;
2281 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2282 *pCaps->VS20Caps.NumTemps = 0;
2283 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2285 *pCaps->MaxVShaderInstructionsExecuted = 0;
2286 *pCaps->MaxVertexShader30InstructionSlots = 0;
2289 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2290 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2291 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2293 /* 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 */
2294 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2295 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2296 WINED3DPS20CAPS_PREDICATION |
2297 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2298 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2299 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2300 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2301 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2302 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2304 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2305 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2306 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2307 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2308 *pCaps->PS20Caps.Caps = 0;
2309 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2310 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2311 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2312 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2314 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2315 *pCaps->MaxPixelShader30InstructionSlots = 0;
2316 } else { /* PS 1.x */
2317 *pCaps->PS20Caps.Caps = 0;
2318 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2319 *pCaps->PS20Caps.NumTemps = 0;
2320 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2321 *pCaps->PS20Caps.NumInstructionSlots = 0;
2323 *pCaps->MaxPShaderInstructionsExecuted = 0;
2324 *pCaps->MaxPixelShader30InstructionSlots = 0;
2328 return WINED3D_OK;
2331 static unsigned int glsl_program_key_hash(void *key) {
2332 glsl_program_key_t *k = (glsl_program_key_t *)key;
2334 unsigned int hash = k->vshader | k->pshader << 16;
2335 hash += ~(hash << 15);
2336 hash ^= (hash >> 10);
2337 hash += (hash << 3);
2338 hash ^= (hash >> 6);
2339 hash += ~(hash << 11);
2340 hash ^= (hash >> 16);
2342 return hash;
2345 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2346 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2347 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2349 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2352 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2353 and fields being inserted in the middle, a new structure is used in place */
2354 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2355 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2356 IUnknown *parent) {
2358 IWineD3DDeviceImpl *object = NULL;
2359 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2360 HDC hDC;
2361 int i;
2363 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2364 * number and create a device without a 3D adapter for 2D only operation.
2366 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2367 return WINED3DERR_INVALIDCALL;
2370 /* Create a WineD3DDevice object */
2371 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2372 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2373 TRACE("Created WineD3DDevice object @ %p\n", object);
2374 if (NULL == object) {
2375 return WINED3DERR_OUTOFVIDEOMEMORY;
2378 /* Set up initial COM information */
2379 object->lpVtbl = &IWineD3DDevice_Vtbl;
2380 object->ref = 1;
2381 object->wineD3D = iface;
2382 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2383 IWineD3D_AddRef(object->wineD3D);
2384 object->parent = parent;
2386 if(This->dxVersion == 7) {
2387 object->surface_alignment = 8;
2388 } else {
2389 object->surface_alignment = 4;
2392 /* Set the state up as invalid until the device is fully created */
2393 object->state = WINED3DERR_DRIVERINTERNALERROR;
2395 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2396 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2398 /* Save the creation parameters */
2399 object->createParms.AdapterOrdinal = Adapter;
2400 object->createParms.DeviceType = DeviceType;
2401 object->createParms.hFocusWindow = hFocusWindow;
2402 object->createParms.BehaviorFlags = BehaviourFlags;
2404 /* Initialize other useful values */
2405 object->adapterNo = Adapter;
2406 object->devType = DeviceType;
2408 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2409 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2410 object->shader_backend = &glsl_shader_backend;
2411 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2412 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2413 object->shader_backend = &arb_program_shader_backend;
2414 } else {
2415 object->shader_backend = &none_shader_backend;
2418 /* set the state of the device to valid */
2419 object->state = WINED3D_OK;
2421 /* Get the initial screen setup for ddraw */
2422 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2423 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2424 hDC = GetDC(0);
2425 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2426 ReleaseDC(0, hDC);
2428 for(i = 0; i < PATCHMAP_SIZE; i++) {
2429 list_init(&object->patches[i]);
2431 return WINED3D_OK;
2433 #undef GLINFO_LOCATION
2435 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2436 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2437 IUnknown_AddRef(This->parent);
2438 *pParent = This->parent;
2439 return WINED3D_OK;
2442 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2443 IUnknown* surfaceParent;
2444 TRACE("(%p) call back\n", pSurface);
2446 /* Now, release the parent, which will take care of cleaning up the surface for us */
2447 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2448 IUnknown_Release(surfaceParent);
2449 return IUnknown_Release(surfaceParent);
2452 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2453 IUnknown* volumeParent;
2454 TRACE("(%p) call back\n", pVolume);
2456 /* Now, release the parent, which will take care of cleaning up the volume for us */
2457 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2458 IUnknown_Release(volumeParent);
2459 return IUnknown_Release(volumeParent);
2462 #define PUSH1(att) attribs[nAttribs++] = (att);
2463 #define GLINFO_LOCATION (Adapters[0].gl_info)
2464 BOOL InitAdapters(void) {
2465 static HMODULE mod_gl;
2466 BOOL ret;
2467 int ps_selected_mode, vs_selected_mode;
2469 /* No need to hold any lock. The calling library makes sure only one thread calls
2470 * wined3d simultaneously
2472 if(numAdapters > 0) return TRUE;
2474 TRACE("Initializing adapters\n");
2476 if(!mod_gl) {
2477 #ifdef USE_WIN32_OPENGL
2478 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2479 mod_gl = LoadLibraryA("opengl32.dll");
2480 if(!mod_gl) {
2481 ERR("Can't load opengl32.dll!\n");
2482 return FALSE;
2484 #else
2485 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2486 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2487 mod_gl = GetModuleHandleA("gdi32.dll");
2488 #endif
2491 /* Load WGL core functions from opengl32.dll */
2492 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2493 WGL_FUNCS_GEN;
2494 #undef USE_WGL_FUNC
2496 if(!pwglGetProcAddress) {
2497 ERR("Unable to load wglGetProcAddress!\n");
2498 return FALSE;
2501 /* Dynamicly load all GL core functions */
2502 GL_FUNCS_GEN;
2503 #undef USE_GL_FUNC
2505 /* For now only one default adapter */
2507 int iPixelFormat;
2508 int attribs[8];
2509 int values[8];
2510 int nAttribs = 0;
2511 int res;
2512 WineD3D_PixelFormat *cfgs;
2513 int attribute;
2514 DISPLAY_DEVICEW DisplayDevice;
2516 TRACE("Initializing default adapter\n");
2517 Adapters[0].monitorPoint.x = -1;
2518 Adapters[0].monitorPoint.y = -1;
2520 if (!WineD3D_CreateFakeGLContext()) {
2521 ERR("Failed to get a gl context for default adapter\n");
2522 HeapFree(GetProcessHeap(), 0, Adapters);
2523 WineD3D_ReleaseFakeGLContext();
2524 return FALSE;
2527 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2528 if(!ret) {
2529 ERR("Failed to initialize gl caps for default adapter\n");
2530 HeapFree(GetProcessHeap(), 0, Adapters);
2531 WineD3D_ReleaseFakeGLContext();
2532 return FALSE;
2534 ret = initPixelFormats(&Adapters[0].gl_info);
2535 if(!ret) {
2536 ERR("Failed to init gl formats\n");
2537 HeapFree(GetProcessHeap(), 0, Adapters);
2538 WineD3D_ReleaseFakeGLContext();
2539 return FALSE;
2542 Adapters[0].driver = "Display";
2543 Adapters[0].description = "Direct3D HAL";
2545 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2546 DisplayDevice.cb = sizeof(DisplayDevice);
2547 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2548 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2549 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2551 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2552 GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2554 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2555 cfgs = Adapters[0].cfgs;
2556 PUSH1(WGL_RED_BITS_ARB)
2557 PUSH1(WGL_GREEN_BITS_ARB)
2558 PUSH1(WGL_BLUE_BITS_ARB)
2559 PUSH1(WGL_ALPHA_BITS_ARB)
2560 PUSH1(WGL_DEPTH_BITS_ARB)
2561 PUSH1(WGL_STENCIL_BITS_ARB)
2563 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2564 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, iPixelFormat, 0, nAttribs, attribs, values));
2566 if(!res)
2567 continue;
2569 /* Cache the pixel format */
2570 cfgs->iPixelFormat = iPixelFormat;
2571 cfgs->redSize = values[0];
2572 cfgs->greenSize = values[1];
2573 cfgs->blueSize = values[2];
2574 cfgs->alphaSize = values[3];
2575 cfgs->depthSize = values[4];
2576 cfgs->stencilSize = values[5];
2578 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);
2579 cfgs++;
2581 WineD3D_ReleaseFakeGLContext();
2583 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2584 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2587 numAdapters = 1;
2588 TRACE("%d adapters successfully initialized\n", numAdapters);
2590 return TRUE;
2592 #undef PUSH1
2593 #undef GLINFO_LOCATION
2595 /**********************************************************
2596 * IWineD3D VTbl follows
2597 **********************************************************/
2599 const IWineD3DVtbl IWineD3D_Vtbl =
2601 /* IUnknown */
2602 IWineD3DImpl_QueryInterface,
2603 IWineD3DImpl_AddRef,
2604 IWineD3DImpl_Release,
2605 /* IWineD3D */
2606 IWineD3DImpl_GetParent,
2607 IWineD3DImpl_GetAdapterCount,
2608 IWineD3DImpl_RegisterSoftwareDevice,
2609 IWineD3DImpl_GetAdapterMonitor,
2610 IWineD3DImpl_GetAdapterModeCount,
2611 IWineD3DImpl_EnumAdapterModes,
2612 IWineD3DImpl_GetAdapterDisplayMode,
2613 IWineD3DImpl_GetAdapterIdentifier,
2614 IWineD3DImpl_CheckDeviceMultiSampleType,
2615 IWineD3DImpl_CheckDepthStencilMatch,
2616 IWineD3DImpl_CheckDeviceType,
2617 IWineD3DImpl_CheckDeviceFormat,
2618 IWineD3DImpl_CheckDeviceFormatConversion,
2619 IWineD3DImpl_GetDeviceCaps,
2620 IWineD3DImpl_CreateDevice