push c718ce09c2ff12a5f254019f4a72fa896c170c07
[wine/hacks.git] / dlls / wined3d / directx.c
blob36d7ebcfe8b2df835bf4a38e3faf46ae961f82e2
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 DWORD version;
44 } EXTENSION_MAP[] = {
45 /* APPLE */
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
51 /* ATI */
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
57 /* ARB */
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
78 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
79 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
80 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
81 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
82 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
84 /* EXT */
85 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
86 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
87 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
88 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
89 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
90 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
91 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
92 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
93 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
94 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
95 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
96 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
97 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
98 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
99 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
100 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
101 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
102 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
103 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
104 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
106 /* NV */
107 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
108 {"GL_NV_fence", NV_FENCE, 0 },
109 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
110 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
111 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
112 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
113 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
114 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
115 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
116 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
117 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
118 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
119 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
120 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
121 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
122 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
123 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
124 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
126 /* SGI */
127 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
130 /**********************************************************
131 * Utility functions follow
132 **********************************************************/
134 /* Adapters */
135 static int numAdapters = 0;
136 static struct WineD3DAdapter Adapters[1];
138 /* lookup tables */
139 int minLookup[MAX_LOOKUPS];
140 int maxLookup[MAX_LOOKUPS];
141 DWORD *stateLookup[MAX_LOOKUPS];
143 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
147 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
148 * ie there is no GL Context - Get a default rendering context to enable the
149 * function query some info from GL
152 static int wined3d_fake_gl_context_ref = 0;
153 static BOOL wined3d_fake_gl_context_foreign;
154 static BOOL wined3d_fake_gl_context_available = FALSE;
155 static HDC wined3d_fake_gl_context_hdc = NULL;
156 static HWND wined3d_fake_gl_context_hwnd = NULL;
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
159 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
161 0, 0, &wined3d_fake_gl_context_cs,
162 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
163 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
164 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
166 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
168 static void WineD3D_ReleaseFakeGLContext(void) {
169 HGLRC glCtx;
171 EnterCriticalSection(&wined3d_fake_gl_context_cs);
173 if(!wined3d_fake_gl_context_available) {
174 TRACE_(d3d_caps)("context not available\n");
175 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
176 return;
179 glCtx = pwglGetCurrentContext();
181 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
182 if (0 == (--wined3d_fake_gl_context_ref) ) {
183 if(!wined3d_fake_gl_context_foreign && glCtx) {
184 TRACE_(d3d_caps)("destroying fake GL context\n");
185 pwglMakeCurrent(NULL, NULL);
186 pwglDeleteContext(glCtx);
188 if(wined3d_fake_gl_context_hdc)
189 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
190 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
191 if(wined3d_fake_gl_context_hwnd)
192 DestroyWindow(wined3d_fake_gl_context_hwnd);
193 wined3d_fake_gl_context_hwnd = NULL;
194 wined3d_fake_gl_context_available = FALSE;
196 assert(wined3d_fake_gl_context_ref >= 0);
198 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
201 static BOOL WineD3D_CreateFakeGLContext(void) {
202 HGLRC glCtx = NULL;
204 EnterCriticalSection(&wined3d_fake_gl_context_cs);
206 TRACE("getting context...\n");
207 if(wined3d_fake_gl_context_ref > 0) goto ret;
208 assert(0 == wined3d_fake_gl_context_ref);
210 wined3d_fake_gl_context_foreign = TRUE;
212 glCtx = pwglGetCurrentContext();
213 if (!glCtx) {
214 PIXELFORMATDESCRIPTOR pfd;
215 int iPixelFormat;
217 wined3d_fake_gl_context_foreign = FALSE;
219 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
220 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
221 if(!wined3d_fake_gl_context_hwnd) {
222 ERR("HWND creation failed!\n");
223 goto fail;
225 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
226 if(!wined3d_fake_gl_context_hdc) {
227 ERR("GetDC failed!\n");
228 goto fail;
231 /* PixelFormat selection */
232 ZeroMemory(&pfd, sizeof(pfd));
233 pfd.nSize = sizeof(pfd);
234 pfd.nVersion = 1;
235 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
236 pfd.iPixelType = PFD_TYPE_RGBA;
237 pfd.cColorBits = 32;
238 pfd.iLayerType = PFD_MAIN_PLANE;
240 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
241 if(!iPixelFormat) {
242 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
243 ERR("Can't find a suitable iPixelFormat\n");
244 goto fail;
246 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
247 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
249 /* Create a GL context */
250 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
251 if (!glCtx) {
252 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
253 goto fail;
256 /* Make it the current GL context */
257 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
258 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
259 goto fail;
263 ret:
264 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
265 wined3d_fake_gl_context_ref++;
266 wined3d_fake_gl_context_available = TRUE;
267 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
268 return TRUE;
269 fail:
270 if(wined3d_fake_gl_context_hdc)
271 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
272 wined3d_fake_gl_context_hdc = NULL;
273 if(wined3d_fake_gl_context_hwnd)
274 DestroyWindow(wined3d_fake_gl_context_hwnd);
275 wined3d_fake_gl_context_hwnd = NULL;
276 if(glCtx) pwglDeleteContext(glCtx);
277 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
278 return FALSE;
281 /* Adjust the amount of used texture memory */
282 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
283 UINT Adapter = D3DDevice->adapterNo;
285 Adapters[Adapter].UsedTextureRam += glram;
286 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
287 return Adapters[Adapter].UsedTextureRam;
290 /**********************************************************
291 * IUnknown parts follows
292 **********************************************************/
294 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
298 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
299 if (IsEqualGUID(riid, &IID_IUnknown)
300 || IsEqualGUID(riid, &IID_IWineD3DBase)
301 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
302 IUnknown_AddRef(iface);
303 *ppobj = This;
304 return S_OK;
306 *ppobj = NULL;
307 return E_NOINTERFACE;
310 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
311 IWineD3DImpl *This = (IWineD3DImpl *)iface;
312 ULONG refCount = InterlockedIncrement(&This->ref);
314 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
315 return refCount;
318 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
319 IWineD3DImpl *This = (IWineD3DImpl *)iface;
320 ULONG ref;
321 TRACE("(%p) : Releasing from %d\n", This, This->ref);
322 ref = InterlockedDecrement(&This->ref);
323 if (ref == 0) {
324 HeapFree(GetProcessHeap(), 0, This);
327 return ref;
330 /* Set the shader type for this device, depending on the given capabilities,
331 * the device type, and the user preferences in wined3d_settings */
333 static void select_shader_mode(
334 WineD3D_GL_Info *gl_info,
335 WINED3DDEVTYPE DeviceType,
336 int* ps_selected,
337 int* vs_selected) {
339 if (wined3d_settings.vs_mode == VS_NONE) {
340 *vs_selected = SHADER_NONE;
341 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
342 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
343 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
344 * shaders only on this card. */
345 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
346 *vs_selected = SHADER_ARB;
347 else
348 *vs_selected = SHADER_GLSL;
349 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
350 *vs_selected = SHADER_ARB;
351 } else {
352 *vs_selected = SHADER_NONE;
355 if (wined3d_settings.ps_mode == PS_NONE) {
356 *ps_selected = SHADER_NONE;
357 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
358 *ps_selected = SHADER_GLSL;
359 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
360 *ps_selected = SHADER_ARB;
361 } else {
362 *ps_selected = SHADER_NONE;
366 /** Select the number of report maximum shader constants based on the selected shader modes */
367 static void select_shader_max_constants(
368 int ps_selected_mode,
369 int vs_selected_mode,
370 WineD3D_GL_Info *gl_info) {
372 switch (vs_selected_mode) {
373 case SHADER_GLSL:
374 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
375 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
376 break;
377 case SHADER_ARB:
378 /* We have to subtract any other PARAMs that we might use in our shader programs.
379 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
380 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
381 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
382 break;
383 default:
384 gl_info->max_vshader_constantsF = 0;
385 break;
388 switch (ps_selected_mode) {
389 case SHADER_GLSL:
390 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
391 * In theory the texbem instruction may need one more shader constant too. But lets assume
392 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
393 * and lets not take away a uniform needlessly from all other shaders.
395 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
396 break;
397 case SHADER_ARB:
398 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
399 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
401 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
402 break;
403 default:
404 gl_info->max_pshader_constantsF = 0;
405 break;
409 /**********************************************************
410 * IWineD3D parts follows
411 **********************************************************/
413 #define GLINFO_LOCATION (*gl_info)
414 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
415 GLuint prog;
416 BOOL ret = FALSE;
417 const char *testcode =
418 "!!ARBvp1.0\n"
419 "PARAM C[66] = { program.env[0..65] };\n"
420 "ADDRESS A0;"
421 "ARL A0.x, 0.0;\n"
422 "MOV result.position, C[A0.x + 65];\n"
423 "END\n";
425 while(glGetError());
426 GL_EXTCALL(glGenProgramsARB(1, &prog));
427 if(!prog) {
428 ERR("Failed to create an ARB offset limit test program\n");
430 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
431 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
432 strlen(testcode), testcode));
433 if(glGetError() != 0) {
434 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
435 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
436 ret = TRUE;
437 } else TRACE("OpenGL implementation allows offsets > 63\n");
439 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
440 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
441 checkGLcall("ARB vp offset limit test cleanup\n");
443 return ret;
446 static DWORD ver_for_ext(GL_SupportedExt ext)
448 unsigned int i;
449 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
450 if(EXTENSION_MAP[i].extension == ext) {
451 return EXTENSION_MAP[i].version;
454 return 0;
457 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
458 const char *GL_Extensions = NULL;
459 const char *WGL_Extensions = NULL;
460 const char *gl_string = NULL;
461 const char *gl_string_cursor = NULL;
462 GLint gl_max;
463 GLfloat gl_floatv[2];
464 int major = 1, minor = 0;
465 BOOL return_value = TRUE;
466 int i;
467 HDC hdc;
468 unsigned int vidmem=0;
470 TRACE_(d3d_caps)("(%p)\n", gl_info);
472 ENTER_GL();
474 gl_string = (const char *) glGetString(GL_RENDERER);
475 if (NULL == gl_string)
476 gl_string = "None";
477 strcpy(gl_info->gl_renderer, gl_string);
479 gl_string = (const char *) glGetString(GL_VENDOR);
480 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
481 if (gl_string != NULL) {
482 /* Fill in the GL vendor */
483 if (strstr(gl_string, "NVIDIA")) {
484 gl_info->gl_vendor = VENDOR_NVIDIA;
485 } else if (strstr(gl_string, "ATI")) {
486 gl_info->gl_vendor = VENDOR_ATI;
487 } else if (strstr(gl_string, "Intel(R)") ||
488 strstr(gl_info->gl_renderer, "Intel(R)")) {
489 gl_info->gl_vendor = VENDOR_INTEL;
490 } else if (strstr(gl_string, "Mesa")) {
491 gl_info->gl_vendor = VENDOR_MESA;
492 } else {
493 gl_info->gl_vendor = VENDOR_WINE;
495 } else {
496 gl_info->gl_vendor = VENDOR_WINE;
500 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
502 /* Parse the GL_VERSION field into major and minor information */
503 gl_string = (const char *) glGetString(GL_VERSION);
504 if (gl_string != NULL) {
506 switch (gl_info->gl_vendor) {
507 case VENDOR_NVIDIA:
508 gl_string_cursor = strstr(gl_string, "NVIDIA");
509 if (!gl_string_cursor) {
510 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
511 break;
514 gl_string_cursor = strstr(gl_string_cursor, " ");
515 if (!gl_string_cursor) {
516 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
517 break;
520 while (*gl_string_cursor == ' ') {
521 ++gl_string_cursor;
524 if (!*gl_string_cursor) {
525 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
526 break;
529 major = atoi(gl_string_cursor);
530 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
531 ++gl_string_cursor;
534 if (*gl_string_cursor++ != '.') {
535 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
536 break;
539 minor = atoi(gl_string_cursor);
540 minor = major*100+minor;
541 major = 10;
543 break;
545 case VENDOR_ATI:
546 major = minor = 0;
547 gl_string_cursor = strchr(gl_string, '-');
548 if (gl_string_cursor) {
549 int error = 0;
550 gl_string_cursor++;
552 /* Check if version number is of the form x.y.z */
553 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
554 error = 1;
555 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
556 error = 1;
557 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
558 error = 1;
559 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
560 error = 1;
562 /* Mark version number as malformed */
563 if (error)
564 gl_string_cursor = 0;
567 if (!gl_string_cursor)
568 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
569 else {
570 major = *gl_string_cursor - '0';
571 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
573 break;
575 case VENDOR_INTEL:
576 case VENDOR_MESA:
577 gl_string_cursor = strstr(gl_string, "Mesa");
578 gl_string_cursor = strstr(gl_string_cursor, " ");
579 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
580 if (*gl_string_cursor) {
581 char tmp[16];
582 int cursor = 0;
584 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
585 tmp[cursor++] = *gl_string_cursor;
586 ++gl_string_cursor;
588 tmp[cursor] = 0;
589 major = atoi(tmp);
591 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
592 ++gl_string_cursor;
594 cursor = 0;
595 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
596 tmp[cursor++] = *gl_string_cursor;
597 ++gl_string_cursor;
599 tmp[cursor] = 0;
600 minor = atoi(tmp);
602 break;
604 default:
605 major = 0;
606 minor = 9;
608 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
609 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
612 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
615 * Initialize openGL extension related variables
616 * with Default values
618 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
619 gl_info->max_buffers = 1;
620 gl_info->max_textures = 1;
621 gl_info->max_texture_stages = 1;
622 gl_info->max_fragment_samplers = 1;
623 gl_info->max_vertex_samplers = 0;
624 gl_info->max_combined_samplers = 0;
625 gl_info->max_sampler_stages = 1;
626 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
627 gl_info->ps_arb_max_temps = 0;
628 gl_info->ps_arb_max_instructions = 0;
629 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
630 gl_info->vs_arb_max_temps = 0;
631 gl_info->vs_arb_max_instructions = 0;
632 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
633 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
634 gl_info->vs_glsl_constantsF = 0;
635 gl_info->ps_glsl_constantsF = 0;
636 gl_info->vs_arb_constantsF = 0;
637 gl_info->ps_arb_constantsF = 0;
639 /* Retrieve opengl defaults */
640 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
641 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
642 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
644 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
645 gl_info->max_lights = gl_max;
646 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
648 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
649 gl_info->max_texture_size = gl_max;
650 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
652 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
653 gl_info->max_pointsizemin = gl_floatv[0];
654 gl_info->max_pointsize = gl_floatv[1];
655 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
657 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
658 gl_info->max_aux_buffers = gl_max;
659 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
661 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
662 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
663 TRACE_(d3d_caps)("GL_Extensions reported:\n");
665 if (NULL == GL_Extensions) {
666 ERR(" GL_Extensions returns NULL\n");
667 } else {
668 while (*GL_Extensions != 0x00) {
669 const char *Start;
670 char ThisExtn[256];
671 size_t len;
673 while (isspace(*GL_Extensions)) GL_Extensions++;
674 Start = GL_Extensions;
675 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
676 GL_Extensions++;
679 len = GL_Extensions - Start;
680 if (len == 0 || len >= sizeof(ThisExtn))
681 continue;
683 memcpy(ThisExtn, Start, len);
684 ThisExtn[len] = '\0';
685 TRACE_(d3d_caps)("- %s\n", ThisExtn);
687 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
688 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
689 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
690 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
691 break;
695 /* Now work out what GL support this card really has */
696 #define USE_GL_FUNC(type, pfn, ext, replace) { \
697 DWORD ver = ver_for_ext(ext); \
698 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
699 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
700 else gl_info->pfn = NULL; \
702 GL_EXT_FUNCS_GEN;
703 #undef USE_GL_FUNC
705 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
706 WGL_EXT_FUNCS_GEN;
707 #undef USE_GL_FUNC
709 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
710 * loading the functions, otherwise the code above will load the extension entry points instead of the
711 * core functions, which may not work
713 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
714 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
715 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
716 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
717 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
721 if (gl_info->supported[APPLE_FENCE]) {
722 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
723 * The apple extension interacts with some other apple exts. Disable the NV
724 * extension if the apple one is support to prevent confusion in other parts
725 * of the code
727 gl_info->supported[NV_FENCE] = FALSE;
729 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
730 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
731 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
733 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
734 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
735 * Won't occur in any real world situation though
737 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
739 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
740 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
741 gl_info->max_buffers = gl_max;
742 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
744 if (gl_info->supported[ARB_MULTITEXTURE]) {
745 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
746 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
747 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
749 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
750 GLint tmp;
751 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
752 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
753 } else {
754 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
756 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
758 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
759 GLint tmp;
760 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
761 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
762 } else {
763 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
765 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
767 if (gl_info->supported[ARB_VERTEX_SHADER]) {
768 GLint tmp;
769 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
770 gl_info->max_vertex_samplers = tmp;
771 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
772 gl_info->max_combined_samplers = tmp;
774 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
775 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
776 * an issue because then the sampler setup only depends on the two shaders. If a pixel
777 * shader is used with fixed function vertex processing we're fine too because fixed function
778 * vertex processing doesn't use any samplers. If fixed function fragment processing is
779 * used we have to make sure that all vertex sampler setups are valid together with all
780 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
781 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
782 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
783 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
784 * a fixed function pipeline anymore.
786 * So this is just a check to check that our assumption holds true. If not, write a warning
787 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
789 if(gl_info->max_vertex_samplers &&
790 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
791 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
792 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
793 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
794 gl_info->max_vertex_samplers = max(0, gl_info->max_combined_samplers - MAX_TEXTURES);
796 } else {
797 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
799 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
800 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
802 if (gl_info->supported[ARB_VERTEX_BLEND]) {
803 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
804 gl_info->max_blends = gl_max;
805 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
807 if (gl_info->supported[EXT_TEXTURE3D]) {
808 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
809 gl_info->max_texture3d_size = gl_max;
810 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
812 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
813 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
814 gl_info->max_anisotropy = gl_max;
815 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
817 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
818 gl_info->ps_arb_version = PS_VERSION_11;
819 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
820 gl_info->ps_arb_constantsF = gl_max;
821 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
822 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
823 gl_info->ps_arb_max_temps = gl_max;
824 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
825 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
826 gl_info->ps_arb_max_instructions = gl_max;
827 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
829 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
830 gl_info->vs_arb_version = VS_VERSION_11;
831 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
832 gl_info->vs_arb_constantsF = gl_max;
833 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
834 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
835 gl_info->vs_arb_max_temps = gl_max;
836 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
837 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
838 gl_info->vs_arb_max_instructions = gl_max;
839 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
841 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
843 if (gl_info->supported[ARB_VERTEX_SHADER]) {
844 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
845 gl_info->vs_glsl_constantsF = gl_max / 4;
846 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
848 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
849 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
850 gl_info->ps_glsl_constantsF = gl_max / 4;
851 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
852 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
853 gl_info->max_glsl_varyings = gl_max;
854 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
856 if (gl_info->supported[EXT_VERTEX_SHADER]) {
857 gl_info->vs_ati_version = VS_VERSION_11;
859 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
860 gl_info->vs_nv_version = VS_VERSION_30;
861 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
862 gl_info->vs_nv_version = VS_VERSION_20;
863 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
864 gl_info->vs_nv_version = VS_VERSION_11;
865 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
866 gl_info->vs_nv_version = VS_VERSION_10;
868 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
869 gl_info->ps_nv_version = PS_VERSION_30;
870 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
871 gl_info->ps_nv_version = PS_VERSION_20;
875 checkGLcall("extension detection\n");
877 /* In some cases the number of texture stages can be larger than the number
878 * of samplers. The GF4 for example can use only 2 samplers (no fragment
879 * shaders), but 8 texture stages (register combiners). */
880 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
882 /* We can only use ORM_FBO when the hardware supports it. */
883 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
884 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
885 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
888 /* MRTs are currently only supported when FBOs are used. */
889 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
890 gl_info->max_buffers = 1;
893 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
894 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
895 * in case of the latest videocards in the number of pixel/vertex pipelines.
897 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
898 * rendering. Various games use this information to get a rough estimation of the features of the card
899 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
900 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
901 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
902 * not the PCI id.
904 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
905 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
906 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
907 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
908 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
909 * is used for rendering which is not always the case). This would work but it is not very portable. Second
910 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
911 * is limited.
913 * As said most games only use the PCI id to get an indication of the capabilities of the card.
914 * It doesn't really matter if the given id is the correct one if we return the id of a card with
915 * similar 3d features.
917 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
918 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
919 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
920 * won't pass we return a default card. This way is better than maintaining a full card database as even
921 * without a full database we can return a card with similar features. Second the size of the database
922 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
923 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
924 * to distinguishes between different models from that family.
926 * The code also selects a default amount of video memory which we will use for an estimation of the amount
927 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
928 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
929 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
930 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
931 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
932 * memory behind our backs if really needed.
933 * Note that the amout of video memory can be overruled using a registry setting.
935 switch (gl_info->gl_vendor) {
936 case VENDOR_NVIDIA:
937 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
938 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
940 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
941 /* Geforce8 - highend */
942 if (strstr(gl_info->gl_renderer, "8800")) {
943 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
944 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
946 /* Geforce8 - midend */
947 else if(strstr(gl_info->gl_renderer, "8600") ||
948 strstr(gl_info->gl_renderer, "8700"))
950 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
951 vidmem = 256;
953 /* Geforce8 - lowend */
954 else if(strstr(gl_info->gl_renderer, "8300") ||
955 strstr(gl_info->gl_renderer, "8400") ||
956 strstr(gl_info->gl_renderer, "8500"))
958 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
959 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
961 /* Geforce7 - highend */
962 else if(strstr(gl_info->gl_renderer, "7800") ||
963 strstr(gl_info->gl_renderer, "7900") ||
964 strstr(gl_info->gl_renderer, "7950") ||
965 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
966 strstr(gl_info->gl_renderer, "Quadro FX 5"))
968 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
969 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
971 /* Geforce7 midend / Geforce6 highend */
972 else if(strstr(gl_info->gl_renderer, "6800") ||
973 strstr(gl_info->gl_renderer, "7600") ||
974 strstr(gl_info->gl_renderer, "7700"))
976 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
977 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
979 /* Geforce6 - midend */
980 else if(strstr(gl_info->gl_renderer, "6600") ||
981 strstr(gl_info->gl_renderer, "6610") ||
982 strstr(gl_info->gl_renderer, "6700"))
984 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
985 vidmem = 128; /* A 6600GT has 128-256MB */
987 /* Geforce6/7 lowend */
988 else {
989 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
990 vidmem = 64; /* */
992 } else if(WINE_D3D9_CAPABLE(gl_info)) {
993 /* GeforceFX - highend */
994 if (strstr(gl_info->gl_renderer, "5800") ||
995 strstr(gl_info->gl_renderer, "5900") ||
996 strstr(gl_info->gl_renderer, "5950") ||
997 strstr(gl_info->gl_renderer, "Quadro FX"))
999 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1000 vidmem = 256; /* 5800-5900 cards use 256MB */
1002 /* GeforceFX - midend */
1003 else if(strstr(gl_info->gl_renderer, "5600") ||
1004 strstr(gl_info->gl_renderer, "5650") ||
1005 strstr(gl_info->gl_renderer, "5700") ||
1006 strstr(gl_info->gl_renderer, "5750"))
1008 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1009 vidmem = 128; /* A 5600 uses 128-256MB */
1011 /* GeforceFX - lowend */
1012 else {
1013 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1014 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1016 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1017 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1018 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1019 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1021 else {
1022 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1023 vidmem = 64; /* Geforce3 cards have 64-128MB */
1025 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1026 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1027 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1028 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1030 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1031 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1032 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1034 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1035 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1036 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1038 else {
1039 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1040 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1042 } else {
1043 if (strstr(gl_info->gl_renderer, "TNT2")) {
1044 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1045 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1047 else {
1048 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1049 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1052 break;
1053 case VENDOR_ATI:
1054 if(WINE_D3D9_CAPABLE(gl_info)) {
1055 /* Radeon R6xx HD2900 - highend */
1056 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1057 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1058 vidmem = 512; /* HD2900 uses 512-1024MB */
1060 /* Radeon R6xx HD2600- midend */
1061 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1062 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1063 vidmem = 256; /* HD2600 uses 256-512MB */
1065 /* Radeon R6xx HD2300/HD2400 - lowend */
1066 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1067 strstr(gl_info->gl_renderer, "HD 2400"))
1069 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1070 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1072 /* Radeon R5xx */
1073 else if (strstr(gl_info->gl_renderer, "X1600") ||
1074 strstr(gl_info->gl_renderer, "X1650") ||
1075 strstr(gl_info->gl_renderer, "X1800") ||
1076 strstr(gl_info->gl_renderer, "X1900") ||
1077 strstr(gl_info->gl_renderer, "X1950"))
1079 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1080 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1082 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1083 else if(strstr(gl_info->gl_renderer, "X700") ||
1084 strstr(gl_info->gl_renderer, "X800") ||
1085 strstr(gl_info->gl_renderer, "X850") ||
1086 strstr(gl_info->gl_renderer, "X1300") ||
1087 strstr(gl_info->gl_renderer, "X1400") ||
1088 strstr(gl_info->gl_renderer, "X1450") ||
1089 strstr(gl_info->gl_renderer, "X1550"))
1091 gl_info->gl_card = CARD_ATI_RADEON_X700;
1092 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1094 /* Radeon R3xx */
1095 else {
1096 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1097 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1099 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1100 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1101 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1102 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1103 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1104 vidmem = 32; /* There are models with up to 64MB */
1105 } else {
1106 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1107 vidmem = 16; /* There are 16-32MB models */
1109 break;
1110 case VENDOR_INTEL:
1111 if (strstr(gl_info->gl_renderer, "915GM")) {
1112 gl_info->gl_card = CARD_INTEL_I915GM;
1113 } else if (strstr(gl_info->gl_renderer, "915G")) {
1114 gl_info->gl_card = CARD_INTEL_I915G;
1115 } else if (strstr(gl_info->gl_renderer, "865G")) {
1116 gl_info->gl_card = CARD_INTEL_I865G;
1117 } else if (strstr(gl_info->gl_renderer, "855G")) {
1118 gl_info->gl_card = CARD_INTEL_I855G;
1119 } else if (strstr(gl_info->gl_renderer, "830G")) {
1120 gl_info->gl_card = CARD_INTEL_I830G;
1121 } else {
1122 gl_info->gl_card = CARD_INTEL_I915G;
1124 break;
1125 case VENDOR_MESA:
1126 case VENDOR_WINE:
1127 default:
1128 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1129 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1130 * them a good generic choice.
1132 gl_info->gl_vendor = VENDOR_NVIDIA;
1133 if(WINE_D3D9_CAPABLE(gl_info))
1134 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1135 else if(WINE_D3D8_CAPABLE(gl_info))
1136 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1137 else if(WINE_D3D7_CAPABLE(gl_info))
1138 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1139 else if(WINE_D3D6_CAPABLE(gl_info))
1140 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1141 else
1142 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1144 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1146 /* If we have an estimate use it, else default to 64MB; */
1147 if(vidmem)
1148 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1149 else
1150 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1152 /* Load all the lookup tables
1153 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1154 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1155 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1157 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1158 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1161 for (i = 0; i < MAX_LOOKUPS; i++) {
1162 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1165 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1166 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1167 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1168 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1169 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1170 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1171 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1172 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1173 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1174 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1176 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1177 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1178 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1179 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1180 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1183 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1184 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1185 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1186 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1187 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1188 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1189 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1190 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1191 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1192 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1193 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1194 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1195 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1197 /* TODO: config lookups */
1199 /* Make sure there's an active HDC else the WGL extensions will fail */
1200 hdc = pwglGetCurrentDC();
1201 if (hdc) {
1202 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1203 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1205 if (NULL == WGL_Extensions) {
1206 ERR(" WGL_Extensions returns NULL\n");
1207 } else {
1208 while (*WGL_Extensions != 0x00) {
1209 const char *Start;
1210 char ThisExtn[256];
1211 size_t len;
1213 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1214 Start = WGL_Extensions;
1215 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1216 WGL_Extensions++;
1219 len = WGL_Extensions - Start;
1220 if (len == 0 || len >= sizeof(ThisExtn))
1221 continue;
1223 memcpy(ThisExtn, Start, len);
1224 ThisExtn[len] = '\0';
1225 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1227 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1228 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1229 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1234 LEAVE_GL();
1236 return return_value;
1238 #undef GLINFO_LOCATION
1240 /**********************************************************
1241 * IWineD3D implementation follows
1242 **********************************************************/
1244 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1245 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1247 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1248 return numAdapters;
1251 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1252 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1253 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1254 return WINED3D_OK;
1257 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1258 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1260 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1261 return NULL;
1264 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1265 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1268 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1269 of the same bpp but different resolutions */
1271 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1272 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1273 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1274 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1276 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1277 return 0;
1280 /* TODO: Store modes per adapter and read it from the adapter structure */
1281 if (Adapter == 0) { /* Display */
1282 int i = 0;
1283 int j = 0;
1285 if (!DEBUG_SINGLE_MODE) {
1286 DEVMODEW DevModeW;
1288 ZeroMemory(&DevModeW, sizeof(DevModeW));
1289 DevModeW.dmSize = sizeof(DevModeW);
1290 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1291 j++;
1292 switch (Format)
1294 case WINED3DFMT_UNKNOWN:
1295 /* This is for D3D8, do not enumerate P8 here */
1296 if (DevModeW.dmBitsPerPel == 32 ||
1297 DevModeW.dmBitsPerPel == 16) i++;
1298 break;
1299 case WINED3DFMT_X8R8G8B8:
1300 if (DevModeW.dmBitsPerPel == 32) i++;
1301 break;
1302 case WINED3DFMT_R5G6B5:
1303 if (DevModeW.dmBitsPerPel == 16) i++;
1304 break;
1305 case WINED3DFMT_P8:
1306 if (DevModeW.dmBitsPerPel == 8) i++;
1307 break;
1308 default:
1309 /* Skip other modes as they do not match the requested format */
1310 break;
1313 } else {
1314 i = 1;
1315 j = 1;
1318 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1319 return i;
1320 } else {
1321 FIXME_(d3d_caps)("Adapter not primary display\n");
1323 return 0;
1326 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1327 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1328 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1329 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1331 /* Validate the parameters as much as possible */
1332 if (NULL == pMode ||
1333 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1334 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1335 return WINED3DERR_INVALIDCALL;
1338 /* TODO: Store modes per adapter and read it from the adapter structure */
1339 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1340 DEVMODEW DevModeW;
1341 int ModeIdx = 0;
1342 int i = 0;
1343 int j = 0;
1345 ZeroMemory(&DevModeW, sizeof(DevModeW));
1346 DevModeW.dmSize = sizeof(DevModeW);
1348 /* If we are filtering to a specific format (D3D9), then need to skip
1349 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1350 just count through the ones with valid bit depths */
1351 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1352 switch (Format)
1354 case WINED3DFMT_UNKNOWN:
1355 /* This is D3D8. Do not enumerate P8 here */
1356 if (DevModeW.dmBitsPerPel == 32 ||
1357 DevModeW.dmBitsPerPel == 16) i++;
1358 break;
1359 case WINED3DFMT_X8R8G8B8:
1360 if (DevModeW.dmBitsPerPel == 32) i++;
1361 break;
1362 case WINED3DFMT_R5G6B5:
1363 if (DevModeW.dmBitsPerPel == 16) i++;
1364 break;
1365 case WINED3DFMT_P8:
1366 if (DevModeW.dmBitsPerPel == 8) i++;
1367 break;
1368 default:
1369 /* Modes that don't match what we support can get an early-out */
1370 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1371 return WINED3DERR_INVALIDCALL;
1375 if (i == 0) {
1376 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1377 return WINED3DERR_INVALIDCALL;
1379 ModeIdx = j - 1;
1381 /* Now get the display mode via the calculated index */
1382 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1383 pMode->Width = DevModeW.dmPelsWidth;
1384 pMode->Height = DevModeW.dmPelsHeight;
1385 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1386 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1387 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1389 if (Format == WINED3DFMT_UNKNOWN)
1391 switch (DevModeW.dmBitsPerPel)
1393 case 8:
1394 pMode->Format = WINED3DFMT_P8;
1395 break;
1396 case 16:
1397 pMode->Format = WINED3DFMT_R5G6B5;
1398 break;
1399 case 32:
1400 pMode->Format = WINED3DFMT_X8R8G8B8;
1401 break;
1402 default:
1403 pMode->Format = WINED3DFMT_UNKNOWN;
1404 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1406 } else {
1407 pMode->Format = Format;
1409 } else {
1410 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1411 return WINED3DERR_INVALIDCALL;
1414 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1415 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1416 DevModeW.dmBitsPerPel);
1418 } else if (DEBUG_SINGLE_MODE) {
1419 /* Return one setting of the format requested */
1420 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1421 pMode->Width = 800;
1422 pMode->Height = 600;
1423 pMode->RefreshRate = 60;
1424 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1425 } else {
1426 FIXME_(d3d_caps)("Adapter not primary display\n");
1429 return WINED3D_OK;
1432 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1433 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1434 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1436 if (NULL == pMode ||
1437 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1438 return WINED3DERR_INVALIDCALL;
1441 if (Adapter == 0) { /* Display */
1442 int bpp = 0;
1443 DEVMODEW DevModeW;
1445 ZeroMemory(&DevModeW, sizeof(DevModeW));
1446 DevModeW.dmSize = sizeof(DevModeW);
1448 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1449 pMode->Width = DevModeW.dmPelsWidth;
1450 pMode->Height = DevModeW.dmPelsHeight;
1451 bpp = DevModeW.dmBitsPerPel;
1452 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1453 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1455 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1458 switch (bpp) {
1459 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1460 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1461 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1462 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1463 default: pMode->Format = WINED3DFMT_UNKNOWN;
1466 } else {
1467 FIXME_(d3d_caps)("Adapter not primary display\n");
1470 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1471 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1472 return WINED3D_OK;
1475 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1476 and fields being inserted in the middle, a new structure is used in place */
1477 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1478 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1479 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1481 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1483 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1484 return WINED3DERR_INVALIDCALL;
1487 /* Return the information requested */
1488 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1489 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1490 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1492 /* Note dx8 doesn't supply a DeviceName */
1493 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1494 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1495 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1496 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1497 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1498 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1499 *(pIdentifier->SubSysId) = 0;
1500 *(pIdentifier->Revision) = 0;
1502 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1503 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1504 *(pIdentifier->WHQLLevel) = 0;
1505 } else {
1506 *(pIdentifier->WHQLLevel) = 1;
1509 return WINED3D_OK;
1512 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1513 short redSize, greenSize, blueSize, alphaSize, colorBits;
1515 if(!cfg)
1516 return FALSE;
1518 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1519 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1520 return FALSE;
1523 if(cfg->redSize < redSize)
1524 return FALSE;
1526 if(cfg->greenSize < greenSize)
1527 return FALSE;
1529 if(cfg->blueSize < blueSize)
1530 return FALSE;
1532 if(cfg->alphaSize < alphaSize)
1533 return FALSE;
1535 return TRUE;
1538 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1539 short depthSize, stencilSize;
1541 if(!cfg)
1542 return FALSE;
1544 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1545 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1546 return FALSE;
1549 if(cfg->depthSize < depthSize)
1550 return FALSE;
1552 if(cfg->stencilSize < stencilSize)
1553 return FALSE;
1555 return TRUE;
1558 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1559 WINED3DFORMAT AdapterFormat,
1560 WINED3DFORMAT RenderTargetFormat,
1561 WINED3DFORMAT DepthStencilFormat) {
1562 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1563 int nCfgs;
1564 WineD3D_PixelFormat *cfgs;
1565 int it;
1567 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1568 This, Adapter,
1569 DeviceType, debug_d3ddevicetype(DeviceType),
1570 AdapterFormat, debug_d3dformat(AdapterFormat),
1571 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1572 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1574 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1575 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1576 return WINED3DERR_INVALIDCALL;
1579 cfgs = Adapters[Adapter].cfgs;
1580 nCfgs = Adapters[Adapter].nCfgs;
1581 for (it = 0; it < nCfgs; ++it) {
1582 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1583 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1584 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1585 return WINED3D_OK;
1589 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1591 return WINED3DERR_NOTAVAILABLE;
1594 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1595 WINED3DFORMAT SurfaceFormat,
1596 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1598 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1599 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1600 This,
1601 Adapter,
1602 DeviceType, debug_d3ddevicetype(DeviceType),
1603 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1604 Windowed,
1605 MultiSampleType,
1606 pQualityLevels);
1608 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1609 return WINED3DERR_INVALIDCALL;
1612 /* TODO: Store in Adapter structure */
1613 if (pQualityLevels != NULL) {
1614 static int s_single_shot = 0;
1615 if (!s_single_shot) {
1616 FIXME("Quality levels unsupported at present\n");
1617 s_single_shot = 1;
1619 *pQualityLevels = 1; /* Guess at a value! */
1622 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1623 return WINED3DERR_NOTAVAILABLE;
1626 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1627 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1629 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1630 int nCfgs = 0;
1631 WineD3D_PixelFormat *cfgs;
1632 int it;
1633 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1635 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1636 This,
1637 Adapter,
1638 CheckType, debug_d3ddevicetype(CheckType),
1639 DisplayFormat, debug_d3dformat(DisplayFormat),
1640 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1641 Windowed);
1643 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1644 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1645 return WINED3DERR_INVALIDCALL;
1648 cfgs = Adapters[Adapter].cfgs;
1649 nCfgs = Adapters[Adapter].nCfgs;
1650 for (it = 0; it < nCfgs; ++it) {
1651 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1652 hr = WINED3D_OK;
1653 TRACE_(d3d_caps)("OK\n");
1654 break ;
1658 if(hr != WINED3D_OK)
1659 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1661 if(hr != WINED3D_OK)
1662 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1664 return hr;
1667 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1668 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1669 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1670 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1671 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1672 This,
1673 Adapter,
1674 DeviceType, debug_d3ddevicetype(DeviceType),
1675 AdapterFormat, debug_d3dformat(AdapterFormat),
1676 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1677 RType, debug_d3dresourcetype(RType),
1678 CheckFormat, debug_d3dformat(CheckFormat));
1680 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1681 return WINED3DERR_INVALIDCALL;
1684 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1685 switch (CheckFormat) {
1686 /* Filtering not supported */
1687 case WINED3DFMT_R32F:
1688 case WINED3DFMT_A32B32G32R32F:
1689 TRACE_(d3d_caps)("[FAILED]\n");
1690 return WINED3DERR_NOTAVAILABLE;
1691 default:
1692 break;
1696 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1697 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1698 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1699 return WINED3DERR_NOTAVAILABLE;
1703 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1704 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1705 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1706 return WINED3DERR_NOTAVAILABLE;
1708 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1709 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1710 * app needing one of those formats, don't advertize them to avoid leading apps into
1711 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1712 * except of R32F.
1714 switch(CheckFormat) {
1715 case WINED3DFMT_P8:
1716 case WINED3DFMT_A4L4:
1717 case WINED3DFMT_R32F:
1718 case WINED3DFMT_R16F:
1719 case WINED3DFMT_X8L8V8U8:
1720 case WINED3DFMT_L6V5U5:
1721 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1722 return WINED3DERR_NOTAVAILABLE;
1724 case WINED3DFMT_Q8W8V8U8:
1725 case WINED3DFMT_V16U16:
1726 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1727 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1728 return WINED3DERR_NOTAVAILABLE;
1730 break;
1732 case WINED3DFMT_V8U8:
1733 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1734 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1735 return WINED3DERR_NOTAVAILABLE;
1737 break;
1739 case WINED3DFMT_DXT1:
1740 case WINED3DFMT_DXT2:
1741 case WINED3DFMT_DXT3:
1742 case WINED3DFMT_DXT4:
1743 case WINED3DFMT_DXT5:
1744 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1745 * compressed texture results in an error. While the D3D refrast does
1746 * support s3tc volumes, at least the nvidia windows driver does not, so
1747 * we're free not to support this format.
1749 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1750 return WINED3DERR_NOTAVAILABLE;
1752 default:
1753 /* Do nothing, continue with checking the format below */
1754 break;
1757 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1758 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1759 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1760 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1761 if (!GL_LIMITS(vertex_samplers)) {
1762 TRACE_(d3d_caps)("[FAILED]\n");
1763 return WINED3DERR_NOTAVAILABLE;
1766 switch (CheckFormat) {
1767 case WINED3DFMT_A32B32G32R32F:
1768 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1769 TRACE_(d3d_caps)("[FAILED]\n");
1770 return WINED3DERR_NOTAVAILABLE;
1772 TRACE_(d3d_caps)("[OK]\n");
1773 return WINED3D_OK;
1775 default:
1776 TRACE_(d3d_caps)("[FAILED]\n");
1777 return WINED3DERR_NOTAVAILABLE;
1781 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1782 switch (CheckFormat) {
1783 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1784 * Windows supports only those 3, and enumerating the other formats confuses applications
1786 case WINED3DFMT_D24S8:
1787 case WINED3DFMT_D24X8:
1788 case WINED3DFMT_D16:
1789 TRACE_(d3d_caps)("[OK]\n");
1790 return WINED3D_OK;
1791 case WINED3DFMT_D16_LOCKABLE:
1792 case WINED3DFMT_D24FS8:
1793 case WINED3DFMT_D32F_LOCKABLE:
1794 case WINED3DFMT_D24X4S4:
1795 case WINED3DFMT_D15S1:
1796 case WINED3DFMT_D32:
1797 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1798 return WINED3DERR_NOTAVAILABLE;
1799 default:
1800 TRACE_(d3d_caps)("[FAILED]\n");
1801 return WINED3DERR_NOTAVAILABLE;
1803 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1804 switch (CheckFormat) {
1805 case WINED3DFMT_R8G8B8:
1806 case WINED3DFMT_A8R8G8B8:
1807 case WINED3DFMT_X8R8G8B8:
1808 case WINED3DFMT_R5G6B5:
1809 case WINED3DFMT_X1R5G5B5:
1810 case WINED3DFMT_A1R5G5B5:
1811 case WINED3DFMT_A4R4G4B4:
1812 case WINED3DFMT_R3G3B2:
1813 case WINED3DFMT_X4R4G4B4:
1814 case WINED3DFMT_A8B8G8R8:
1815 case WINED3DFMT_X8B8G8R8:
1816 case WINED3DFMT_P8:
1817 TRACE_(d3d_caps)("[OK]\n");
1818 return WINED3D_OK;
1819 case WINED3DFMT_R16F:
1820 case WINED3DFMT_A16B16G16R16F:
1821 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1822 TRACE_(d3d_caps)("[FAILED]\n");
1823 return WINED3DERR_NOTAVAILABLE;
1825 TRACE_(d3d_caps)("[OK]\n");
1826 return WINED3D_OK;
1827 case WINED3DFMT_A32B32G32R32F:
1828 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1829 TRACE_(d3d_caps)("[FAILED]\n");
1830 return WINED3DERR_NOTAVAILABLE;
1832 TRACE_(d3d_caps)("[OK]\n");
1833 return WINED3D_OK;
1834 default:
1835 TRACE_(d3d_caps)("[FAILED]\n");
1836 return WINED3DERR_NOTAVAILABLE;
1838 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1839 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1840 switch (CheckFormat) {
1841 case WINED3DFMT_V8U8:
1842 TRACE_(d3d_caps)("[OK]\n");
1843 return WINED3D_OK;
1844 /* TODO: Other bump map formats */
1845 default:
1846 TRACE_(d3d_caps)("[FAILED]\n");
1847 return WINED3DERR_NOTAVAILABLE;
1850 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1851 switch (CheckFormat) {
1852 case WINED3DFMT_V8U8:
1853 TRACE_(d3d_caps)("[OK]\n");
1854 return WINED3D_OK;
1855 default:
1856 TRACE_(d3d_caps)("[FAILED]\n");
1857 return WINED3DERR_NOTAVAILABLE;
1860 TRACE_(d3d_caps)("[FAILED]\n");
1861 return WINED3DERR_NOTAVAILABLE;
1864 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1865 switch (CheckFormat) {
1866 case WINED3DFMT_DXT1:
1867 case WINED3DFMT_DXT2:
1868 case WINED3DFMT_DXT3:
1869 case WINED3DFMT_DXT4:
1870 case WINED3DFMT_DXT5:
1871 TRACE_(d3d_caps)("[OK]\n");
1872 return WINED3D_OK;
1873 default:
1874 break; /* Avoid compiler warnings */
1878 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1879 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1880 switch (CheckFormat) {
1881 case WINED3DFMT_A8R8G8B8:
1882 case WINED3DFMT_X8R8G8B8:
1883 case WINED3DFMT_A4R4G4B4:
1884 case WINED3DFMT_L8:
1885 case WINED3DFMT_A8L8:
1886 case WINED3DFMT_DXT1:
1887 case WINED3DFMT_DXT2:
1888 case WINED3DFMT_DXT3:
1889 case WINED3DFMT_DXT4:
1890 case WINED3DFMT_DXT5:
1891 TRACE_(d3d_caps)("[OK]\n");
1892 return WINED3D_OK;
1894 default:
1895 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1896 return WINED3DERR_NOTAVAILABLE;
1900 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1902 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1904 switch (CheckFormat) {
1905 case WINED3DFMT_R16F:
1906 case WINED3DFMT_A16B16G16R16F:
1907 if (!half_pixel_support) break;
1908 case WINED3DFMT_R32F:
1909 case WINED3DFMT_A32B32G32R32F:
1910 TRACE_(d3d_caps)("[OK]\n");
1911 return WINED3D_OK;
1912 default:
1913 break; /* Avoid compiler warnings */
1917 /* This format is nothing special and it is supported perfectly.
1918 * However, ati and nvidia driver on windows do not mark this format as
1919 * supported (tested with the dxCapsViewer) and pretending to
1920 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1921 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1922 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1924 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1925 TRACE_(d3d_caps)("[FAILED]\n");
1926 return WINED3DERR_NOTAVAILABLE;
1929 switch (CheckFormat) {
1931 /*****
1932 * supported: RGB(A) formats
1934 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1935 case WINED3DFMT_A8R8G8B8:
1936 case WINED3DFMT_X8R8G8B8:
1937 case WINED3DFMT_R5G6B5:
1938 case WINED3DFMT_X1R5G5B5:
1939 case WINED3DFMT_A1R5G5B5:
1940 case WINED3DFMT_A4R4G4B4:
1941 case WINED3DFMT_R3G3B2:
1942 case WINED3DFMT_A8:
1943 case WINED3DFMT_X4R4G4B4:
1944 case WINED3DFMT_A8B8G8R8:
1945 case WINED3DFMT_X8B8G8R8:
1946 case WINED3DFMT_A2R10G10B10:
1947 case WINED3DFMT_A2B10G10R10:
1948 TRACE_(d3d_caps)("[OK]\n");
1949 return WINED3D_OK;
1951 /*****
1952 * supported: Palettized
1954 case WINED3DFMT_P8:
1955 TRACE_(d3d_caps)("[OK]\n");
1956 return WINED3D_OK;
1958 /*****
1959 * Supported: (Alpha)-Luminance
1961 case WINED3DFMT_L8:
1962 case WINED3DFMT_A8L8:
1963 case WINED3DFMT_A4L4:
1964 TRACE_(d3d_caps)("[OK]\n");
1965 return WINED3D_OK;
1967 /*****
1968 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1969 * GL_NV_texture_shader), but advertized to make apps happy.
1970 * Enable some because games often fail when they are not available
1971 * and are still playable even without bump mapping
1973 case WINED3DFMT_V8U8:
1974 case WINED3DFMT_V16U16:
1975 case WINED3DFMT_L6V5U5:
1976 case WINED3DFMT_X8L8V8U8:
1977 case WINED3DFMT_Q8W8V8U8:
1978 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1979 return WINED3D_OK;
1981 /* Those are not advertized by the nvidia windows driver, and not
1982 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1983 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1984 * ARGB format if needed
1986 case WINED3DFMT_W11V11U10:
1987 case WINED3DFMT_A2W10V10U10:
1988 WARN_(d3d_caps)("[FAILED]\n");
1989 return WINED3DERR_NOTAVAILABLE;
1991 /*****
1992 * DXTN Formats: Handled above
1993 * WINED3DFMT_DXT1
1994 * WINED3DFMT_DXT2
1995 * WINED3DFMT_DXT3
1996 * WINED3DFMT_DXT4
1997 * WINED3DFMT_DXT5
2000 /*****
2001 * Odd formats - not supported
2003 case WINED3DFMT_VERTEXDATA:
2004 case WINED3DFMT_INDEX16:
2005 case WINED3DFMT_INDEX32:
2006 case WINED3DFMT_Q16W16V16U16:
2007 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2008 return WINED3DERR_NOTAVAILABLE;
2010 /*****
2011 * Float formats: Not supported right now
2013 case WINED3DFMT_G16R16F:
2014 case WINED3DFMT_G32R32F:
2015 case WINED3DFMT_CxV8U8:
2016 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2017 return WINED3DERR_NOTAVAILABLE;
2019 /* Not supported */
2020 case WINED3DFMT_G16R16:
2021 case WINED3DFMT_A16B16G16R16:
2022 case WINED3DFMT_A8R3G3B2:
2023 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2024 return WINED3DERR_NOTAVAILABLE;
2026 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2027 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2028 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2029 * We can do instancing with all shader versions, but we need vertex shaders.
2031 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2032 * to enable instancing. WineD3D doesn't need that and just ignores it.
2034 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2036 case WINEMAKEFOURCC('I','N','S','T'):
2037 TRACE("ATI Instancing check hack\n");
2038 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2039 TRACE_(d3d_caps)("[OK]\n");
2040 return WINED3D_OK;
2041 } else {
2042 TRACE_(d3d_caps)("[FAILED]\n");
2043 return WINED3DERR_NOTAVAILABLE;
2046 default:
2047 break;
2050 TRACE_(d3d_caps)("[FAILED]\n");
2051 return WINED3DERR_NOTAVAILABLE;
2054 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2055 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2056 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2058 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2059 This,
2060 Adapter,
2061 DeviceType, debug_d3ddevicetype(DeviceType),
2062 SourceFormat, debug_d3dformat(SourceFormat),
2063 TargetFormat, debug_d3dformat(TargetFormat));
2064 return WINED3D_OK;
2067 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2068 subset of a D3DCAPS9 structure. However, it has to come via a void *
2069 as the d3d8 interface cannot import the d3d9 header */
2070 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2072 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2073 int vs_selected_mode;
2074 int ps_selected_mode;
2076 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2078 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2079 return WINED3DERR_INVALIDCALL;
2082 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2084 /* This function should *not* be modifying GL caps
2085 * TODO: move the functionality where it belongs */
2086 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2088 /* ------------------------------------------------
2089 The following fields apply to both d3d8 and d3d9
2090 ------------------------------------------------ */
2091 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2092 *pCaps->AdapterOrdinal = Adapter;
2094 *pCaps->Caps = 0;
2095 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2096 WINED3DCAPS2_FULLSCREENGAMMA |
2097 WINED3DCAPS2_DYNAMICTEXTURES;
2098 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2099 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2101 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2102 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2103 WINED3DPRESENT_INTERVAL_ONE;
2105 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2106 WINED3DCURSORCAPS_LOWRES;
2108 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2109 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2110 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2111 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2112 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2113 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2114 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2115 WINED3DDEVCAPS_PUREDEVICE |
2116 WINED3DDEVCAPS_HWRASTERIZATION |
2117 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2118 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2119 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2120 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2121 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2122 WINED3DDEVCAPS_RTPATCHES;
2124 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2125 WINED3DPMISCCAPS_CULLCCW |
2126 WINED3DPMISCCAPS_CULLCW |
2127 WINED3DPMISCCAPS_COLORWRITEENABLE |
2128 WINED3DPMISCCAPS_CLIPTLVERTS |
2129 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2130 WINED3DPMISCCAPS_MASKZ |
2131 WINED3DPMISCCAPS_BLENDOP;
2132 /* TODO:
2133 WINED3DPMISCCAPS_NULLREFERENCE
2134 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2135 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2136 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2137 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2138 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2139 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2141 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2142 #if 0
2143 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2144 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2145 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2146 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2147 #endif
2149 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2150 WINED3DPRASTERCAPS_PAT |
2151 WINED3DPRASTERCAPS_WFOG |
2152 WINED3DPRASTERCAPS_ZFOG |
2153 WINED3DPRASTERCAPS_FOGVERTEX |
2154 WINED3DPRASTERCAPS_FOGTABLE |
2155 WINED3DPRASTERCAPS_STIPPLE |
2156 WINED3DPRASTERCAPS_SUBPIXEL |
2157 WINED3DPRASTERCAPS_ZTEST |
2158 WINED3DPRASTERCAPS_SCISSORTEST |
2159 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2160 WINED3DPRASTERCAPS_DEPTHBIAS;
2162 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2163 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2164 WINED3DPRASTERCAPS_ZBIAS |
2165 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2167 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2168 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2170 /* FIXME Add:
2171 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2172 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2173 WINED3DPRASTERCAPS_ANTIALIASEDGES
2174 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2175 WINED3DPRASTERCAPS_WBUFFER */
2177 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2178 WINED3DPCMPCAPS_EQUAL |
2179 WINED3DPCMPCAPS_GREATER |
2180 WINED3DPCMPCAPS_GREATEREQUAL |
2181 WINED3DPCMPCAPS_LESS |
2182 WINED3DPCMPCAPS_LESSEQUAL |
2183 WINED3DPCMPCAPS_NEVER |
2184 WINED3DPCMPCAPS_NOTEQUAL;
2186 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2187 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2188 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2189 WINED3DPBLENDCAPS_DESTALPHA |
2190 WINED3DPBLENDCAPS_DESTCOLOR |
2191 WINED3DPBLENDCAPS_INVDESTALPHA |
2192 WINED3DPBLENDCAPS_INVDESTCOLOR |
2193 WINED3DPBLENDCAPS_INVSRCALPHA |
2194 WINED3DPBLENDCAPS_INVSRCCOLOR |
2195 WINED3DPBLENDCAPS_ONE |
2196 WINED3DPBLENDCAPS_SRCALPHA |
2197 WINED3DPBLENDCAPS_SRCALPHASAT |
2198 WINED3DPBLENDCAPS_SRCCOLOR |
2199 WINED3DPBLENDCAPS_ZERO;
2201 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2202 WINED3DPBLENDCAPS_DESTALPHA |
2203 WINED3DPBLENDCAPS_DESTCOLOR |
2204 WINED3DPBLENDCAPS_INVDESTALPHA |
2205 WINED3DPBLENDCAPS_INVDESTCOLOR |
2206 WINED3DPBLENDCAPS_INVSRCALPHA |
2207 WINED3DPBLENDCAPS_INVSRCCOLOR |
2208 WINED3DPBLENDCAPS_ONE |
2209 WINED3DPBLENDCAPS_SRCALPHA |
2210 WINED3DPBLENDCAPS_SRCCOLOR |
2211 WINED3DPBLENDCAPS_ZERO;
2212 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2213 * according to the glBlendFunc manpage
2215 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2216 * legacy settings for srcblend only
2219 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2220 WINED3DPCMPCAPS_EQUAL |
2221 WINED3DPCMPCAPS_GREATER |
2222 WINED3DPCMPCAPS_GREATEREQUAL |
2223 WINED3DPCMPCAPS_LESS |
2224 WINED3DPCMPCAPS_LESSEQUAL |
2225 WINED3DPCMPCAPS_NEVER |
2226 WINED3DPCMPCAPS_NOTEQUAL;
2228 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2229 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2230 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2231 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2232 WINED3DPSHADECAPS_COLORFLATRGB |
2233 WINED3DPSHADECAPS_FOGFLAT |
2234 WINED3DPSHADECAPS_FOGGOURAUD |
2235 WINED3DPSHADECAPS_SPECULARFLATRGB;
2237 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2238 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2239 WINED3DPTEXTURECAPS_BORDER |
2240 WINED3DPTEXTURECAPS_MIPMAP |
2241 WINED3DPTEXTURECAPS_PROJECTED |
2242 WINED3DPTEXTURECAPS_PERSPECTIVE;
2244 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2245 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2246 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2249 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2250 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2251 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2252 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2255 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2256 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2257 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2258 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2262 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2263 WINED3DPTFILTERCAPS_MAGFPOINT |
2264 WINED3DPTFILTERCAPS_MINFLINEAR |
2265 WINED3DPTFILTERCAPS_MINFPOINT |
2266 WINED3DPTFILTERCAPS_MIPFLINEAR |
2267 WINED3DPTFILTERCAPS_MIPFPOINT |
2268 WINED3DPTFILTERCAPS_LINEAR |
2269 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2270 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2271 WINED3DPTFILTERCAPS_MIPLINEAR |
2272 WINED3DPTFILTERCAPS_MIPNEAREST |
2273 WINED3DPTFILTERCAPS_NEAREST;
2275 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2276 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2277 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2280 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2281 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2282 WINED3DPTFILTERCAPS_MAGFPOINT |
2283 WINED3DPTFILTERCAPS_MINFLINEAR |
2284 WINED3DPTFILTERCAPS_MINFPOINT |
2285 WINED3DPTFILTERCAPS_MIPFLINEAR |
2286 WINED3DPTFILTERCAPS_MIPFPOINT |
2287 WINED3DPTFILTERCAPS_LINEAR |
2288 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2289 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2290 WINED3DPTFILTERCAPS_MIPLINEAR |
2291 WINED3DPTFILTERCAPS_MIPNEAREST |
2292 WINED3DPTFILTERCAPS_NEAREST;
2294 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2295 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2296 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2298 } else
2299 *pCaps->CubeTextureFilterCaps = 0;
2301 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2302 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2303 WINED3DPTFILTERCAPS_MAGFPOINT |
2304 WINED3DPTFILTERCAPS_MINFLINEAR |
2305 WINED3DPTFILTERCAPS_MINFPOINT |
2306 WINED3DPTFILTERCAPS_MIPFLINEAR |
2307 WINED3DPTFILTERCAPS_MIPFPOINT |
2308 WINED3DPTFILTERCAPS_LINEAR |
2309 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2310 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2311 WINED3DPTFILTERCAPS_MIPLINEAR |
2312 WINED3DPTFILTERCAPS_MIPNEAREST |
2313 WINED3DPTFILTERCAPS_NEAREST;
2314 } else
2315 *pCaps->VolumeTextureFilterCaps = 0;
2317 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2318 WINED3DPTADDRESSCAPS_CLAMP |
2319 WINED3DPTADDRESSCAPS_WRAP;
2321 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2322 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2324 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2325 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2327 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2328 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2331 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2332 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2333 WINED3DPTADDRESSCAPS_CLAMP |
2334 WINED3DPTADDRESSCAPS_WRAP;
2335 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2336 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2338 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2339 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2341 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2342 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2344 } else
2345 *pCaps->VolumeTextureAddressCaps = 0;
2347 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2348 WINED3DLINECAPS_ZTEST;
2349 /* FIXME: Add
2350 WINED3DLINECAPS_BLEND
2351 WINED3DLINECAPS_ALPHACMP
2352 WINED3DLINECAPS_FOG */
2354 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2355 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2357 if(GL_SUPPORT(EXT_TEXTURE3D))
2358 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2359 else
2360 *pCaps->MaxVolumeExtent = 0;
2362 *pCaps->MaxTextureRepeat = 32768;
2363 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2364 *pCaps->MaxVertexW = 1.0;
2366 *pCaps->GuardBandLeft = 0;
2367 *pCaps->GuardBandTop = 0;
2368 *pCaps->GuardBandRight = 0;
2369 *pCaps->GuardBandBottom = 0;
2371 *pCaps->ExtentsAdjust = 0;
2373 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2374 WINED3DSTENCILCAPS_INCRSAT |
2375 WINED3DSTENCILCAPS_INVERT |
2376 WINED3DSTENCILCAPS_KEEP |
2377 WINED3DSTENCILCAPS_REPLACE |
2378 WINED3DSTENCILCAPS_ZERO;
2379 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2380 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2381 WINED3DSTENCILCAPS_INCR;
2383 if ( This->dxVersion > 8 &&
2384 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2385 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2386 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2389 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2391 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2392 WINED3DTEXOPCAPS_ADDSIGNED |
2393 WINED3DTEXOPCAPS_ADDSIGNED2X |
2394 WINED3DTEXOPCAPS_MODULATE |
2395 WINED3DTEXOPCAPS_MODULATE2X |
2396 WINED3DTEXOPCAPS_MODULATE4X |
2397 WINED3DTEXOPCAPS_SELECTARG1 |
2398 WINED3DTEXOPCAPS_SELECTARG2 |
2399 WINED3DTEXOPCAPS_DISABLE;
2401 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2402 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2403 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2404 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2405 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2406 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2407 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2408 WINED3DTEXOPCAPS_LERP |
2409 WINED3DTEXOPCAPS_SUBTRACT;
2411 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2412 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2413 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2414 WINED3DTEXOPCAPS_MULTIPLYADD |
2415 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2416 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2417 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2419 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2420 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2422 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2423 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2424 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2427 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2428 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2429 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2430 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2431 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2432 * and 3D textures. It also allows us to keep the code simpler by having texture
2433 * shaders constantly enabled.
2435 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2436 /* TODO: Luminance bump map? */
2438 #if 0
2439 /* FIXME: Add
2440 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2441 WINED3DTEXOPCAPS_PREMODULATE */
2442 #endif
2444 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2445 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2446 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2447 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2449 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2450 *pCaps->MaxVertexBlendMatrixIndex = 0;
2452 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2453 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2456 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2457 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2458 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2459 WINED3DVTXPCAPS_LOCALVIEWER |
2460 WINED3DVTXPCAPS_VERTEXFOG |
2461 WINED3DVTXPCAPS_TEXGEN;
2462 /* FIXME: Add
2463 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2465 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2466 *pCaps->MaxVertexIndex = 0xFFFFF;
2467 *pCaps->MaxStreams = MAX_STREAMS;
2468 *pCaps->MaxStreamStride = 1024;
2470 if (vs_selected_mode == SHADER_GLSL) {
2471 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2472 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2473 * vs_nv_version which is based on NV_vertex_program.
2474 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2475 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2476 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2477 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2478 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2479 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2480 else
2481 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2482 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2483 } else if (vs_selected_mode == SHADER_ARB) {
2484 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2485 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2486 } else {
2487 *pCaps->VertexShaderVersion = 0;
2488 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2491 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2493 if (ps_selected_mode == SHADER_GLSL) {
2494 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2495 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2496 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2497 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2498 * in max native instructions. Intel and others also offer the info in this extension but they
2499 * don't support GLSL (at least on Windows).
2501 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2502 * of instructions is 512 or less we have to do with ps2.0 hardware.
2503 * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware.
2505 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2506 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2507 else
2508 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2509 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2510 * Direct3D minimum requirement.
2512 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2513 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2515 * The problem is that the refrast clamps temporary results in the shader to
2516 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2517 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2518 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2519 * offer a way to query this.
2521 *pCaps->PixelShader1xMaxValue = 8.0;
2522 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2523 } else if (ps_selected_mode == SHADER_ARB) {
2524 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2525 *pCaps->PixelShader1xMaxValue = 8.0;
2526 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2527 } else {
2528 *pCaps->PixelShaderVersion = 0;
2529 *pCaps->PixelShader1xMaxValue = 0.0;
2530 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2533 /* ------------------------------------------------
2534 The following fields apply to d3d9 only
2535 ------------------------------------------------ */
2536 if (This->dxVersion > 8) {
2537 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2538 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2539 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2540 *pCaps->MaxNpatchTessellationLevel = 0;
2541 *pCaps->MasterAdapterOrdinal = 0;
2542 *pCaps->AdapterOrdinalInGroup = 0;
2543 *pCaps->NumberOfAdaptersInGroup = 1;
2545 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2546 /* OpenGL supports all the formats below, perhaps not always
2547 * without conversion, but it supports them.
2548 * Further GLSL doesn't seem to have an official unsigned type so
2549 * don't advertise it yet as I'm not sure how we handle it.
2550 * We might need to add some clamping in the shader engine to
2551 * support it.
2552 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2553 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2554 WINED3DDTCAPS_UBYTE4N |
2555 WINED3DDTCAPS_SHORT2N |
2556 WINED3DDTCAPS_SHORT4N;
2557 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2558 *pCaps->DeclTypes |=
2559 WINED3DDTCAPS_FLOAT16_2 |
2560 WINED3DDTCAPS_FLOAT16_4;
2562 } else
2563 *pCaps->DeclTypes = 0;
2565 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2568 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2569 WINED3DPTFILTERCAPS_MAGFPOINT |
2570 WINED3DPTFILTERCAPS_MINFLINEAR |
2571 WINED3DPTFILTERCAPS_MAGFLINEAR;
2572 *pCaps->VertexTextureFilterCaps = 0;
2574 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2575 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2576 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2577 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2578 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2579 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2580 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2582 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2583 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2584 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2585 *pCaps->VS20Caps.Caps = 0;
2586 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2587 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2588 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2590 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2591 *pCaps->MaxVertexShader30InstructionSlots = 0;
2592 } else { /* VS 1.x */
2593 *pCaps->VS20Caps.Caps = 0;
2594 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2595 *pCaps->VS20Caps.NumTemps = 0;
2596 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2598 *pCaps->MaxVShaderInstructionsExecuted = 0;
2599 *pCaps->MaxVertexShader30InstructionSlots = 0;
2602 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2603 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2604 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2606 /* 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 */
2607 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2608 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2609 WINED3DPS20CAPS_PREDICATION |
2610 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2611 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2612 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2613 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2614 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2615 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2617 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2618 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2619 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2620 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2621 *pCaps->PS20Caps.Caps = 0;
2622 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2623 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2624 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2625 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2627 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2628 *pCaps->MaxPixelShader30InstructionSlots = 0;
2629 } else { /* PS 1.x */
2630 *pCaps->PS20Caps.Caps = 0;
2631 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2632 *pCaps->PS20Caps.NumTemps = 0;
2633 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2634 *pCaps->PS20Caps.NumInstructionSlots = 0;
2636 *pCaps->MaxPShaderInstructionsExecuted = 0;
2637 *pCaps->MaxPixelShader30InstructionSlots = 0;
2641 return WINED3D_OK;
2644 static unsigned int glsl_program_key_hash(void *key) {
2645 glsl_program_key_t *k = (glsl_program_key_t *)key;
2647 unsigned int hash = k->vshader | k->pshader << 16;
2648 hash += ~(hash << 15);
2649 hash ^= (hash >> 10);
2650 hash += (hash << 3);
2651 hash ^= (hash >> 6);
2652 hash += ~(hash << 11);
2653 hash ^= (hash >> 16);
2655 return hash;
2658 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2659 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2660 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2662 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2665 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2666 and fields being inserted in the middle, a new structure is used in place */
2667 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2668 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2669 IUnknown *parent) {
2671 IWineD3DDeviceImpl *object = NULL;
2672 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2673 HDC hDC;
2674 int i;
2676 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2677 * number and create a device without a 3D adapter for 2D only operation.
2679 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2680 return WINED3DERR_INVALIDCALL;
2683 /* Create a WineD3DDevice object */
2684 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2685 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2686 TRACE("Created WineD3DDevice object @ %p\n", object);
2687 if (NULL == object) {
2688 return WINED3DERR_OUTOFVIDEOMEMORY;
2691 /* Set up initial COM information */
2692 object->lpVtbl = &IWineD3DDevice_Vtbl;
2693 object->ref = 1;
2694 object->wineD3D = iface;
2695 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2696 IWineD3D_AddRef(object->wineD3D);
2697 object->parent = parent;
2698 list_init(&object->resources);
2700 if(This->dxVersion == 7) {
2701 object->surface_alignment = 8;
2702 } else {
2703 object->surface_alignment = 4;
2705 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2707 /* Set the state up as invalid until the device is fully created */
2708 object->state = WINED3DERR_DRIVERINTERNALERROR;
2710 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2711 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2713 /* Save the creation parameters */
2714 object->createParms.AdapterOrdinal = Adapter;
2715 object->createParms.DeviceType = DeviceType;
2716 object->createParms.hFocusWindow = hFocusWindow;
2717 object->createParms.BehaviorFlags = BehaviourFlags;
2719 /* Initialize other useful values */
2720 object->adapterNo = Adapter;
2721 object->devType = DeviceType;
2723 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2724 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2725 object->shader_backend = &glsl_shader_backend;
2726 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2727 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2728 object->shader_backend = &arb_program_shader_backend;
2729 } else {
2730 object->shader_backend = &none_shader_backend;
2733 /* set the state of the device to valid */
2734 object->state = WINED3D_OK;
2736 /* Get the initial screen setup for ddraw */
2737 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2738 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2739 hDC = GetDC(0);
2740 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2741 ReleaseDC(0, hDC);
2743 for(i = 0; i < PATCHMAP_SIZE; i++) {
2744 list_init(&object->patches[i]);
2746 return WINED3D_OK;
2748 #undef GLINFO_LOCATION
2750 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2751 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2752 IUnknown_AddRef(This->parent);
2753 *pParent = This->parent;
2754 return WINED3D_OK;
2757 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2758 IUnknown* surfaceParent;
2759 TRACE("(%p) call back\n", pSurface);
2761 /* Now, release the parent, which will take care of cleaning up the surface for us */
2762 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2763 IUnknown_Release(surfaceParent);
2764 return IUnknown_Release(surfaceParent);
2767 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2768 IUnknown* volumeParent;
2769 TRACE("(%p) call back\n", pVolume);
2771 /* Now, release the parent, which will take care of cleaning up the volume for us */
2772 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2773 IUnknown_Release(volumeParent);
2774 return IUnknown_Release(volumeParent);
2777 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2778 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2779 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2780 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2782 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2783 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2784 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2785 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2786 * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
2787 * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
2788 * DirectDraw, not OpenGL.
2790 if(gl_info->supported[APPLE_FENCE] &&
2791 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2792 gl_info->supported[APPLE_FLUSH_RENDER] &&
2793 gl_info->supported[APPLE_YCBCR_422]) {
2794 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2795 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2796 return TRUE;
2797 } else {
2798 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2799 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2800 return FALSE;
2804 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2805 if(implementation_is_apple(gl_info)) {
2806 /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
2807 * used it falls back to software. While the compiler can detect if the shader uses all declared
2808 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2809 * using relative addressing falls back to software.
2811 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2813 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2814 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2815 } else {
2816 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2817 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2818 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2821 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2822 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2823 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2824 * flag for this extension
2826 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2827 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2828 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2829 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2830 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2831 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2837 #define PUSH1(att) attribs[nAttribs++] = (att);
2838 #define GLINFO_LOCATION (Adapters[0].gl_info)
2839 BOOL InitAdapters(void) {
2840 static HMODULE mod_gl;
2841 BOOL ret;
2842 int ps_selected_mode, vs_selected_mode;
2844 /* No need to hold any lock. The calling library makes sure only one thread calls
2845 * wined3d simultaneously
2847 if(numAdapters > 0) return TRUE;
2849 TRACE("Initializing adapters\n");
2851 if(!mod_gl) {
2852 #ifdef USE_WIN32_OPENGL
2853 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2854 mod_gl = LoadLibraryA("opengl32.dll");
2855 if(!mod_gl) {
2856 ERR("Can't load opengl32.dll!\n");
2857 return FALSE;
2859 #else
2860 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2861 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2862 mod_gl = GetModuleHandleA("gdi32.dll");
2863 #endif
2866 /* Load WGL core functions from opengl32.dll */
2867 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2868 WGL_FUNCS_GEN;
2869 #undef USE_WGL_FUNC
2871 if(!pwglGetProcAddress) {
2872 ERR("Unable to load wglGetProcAddress!\n");
2873 return FALSE;
2876 /* Dynamically load all GL core functions */
2877 GL_FUNCS_GEN;
2878 #undef USE_GL_FUNC
2880 /* For now only one default adapter */
2882 int iPixelFormat;
2883 int attribs[8];
2884 int values[8];
2885 int nAttribs = 0;
2886 int res;
2887 WineD3D_PixelFormat *cfgs;
2888 int attribute;
2889 DISPLAY_DEVICEW DisplayDevice;
2890 HDC hdc;
2892 TRACE("Initializing default adapter\n");
2893 Adapters[0].monitorPoint.x = -1;
2894 Adapters[0].monitorPoint.y = -1;
2896 if (!WineD3D_CreateFakeGLContext()) {
2897 ERR("Failed to get a gl context for default adapter\n");
2898 HeapFree(GetProcessHeap(), 0, Adapters);
2899 WineD3D_ReleaseFakeGLContext();
2900 return FALSE;
2903 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2904 if(!ret) {
2905 ERR("Failed to initialize gl caps for default adapter\n");
2906 HeapFree(GetProcessHeap(), 0, Adapters);
2907 WineD3D_ReleaseFakeGLContext();
2908 return FALSE;
2910 ret = initPixelFormats(&Adapters[0].gl_info);
2911 if(!ret) {
2912 ERR("Failed to init gl formats\n");
2913 HeapFree(GetProcessHeap(), 0, Adapters);
2914 WineD3D_ReleaseFakeGLContext();
2915 return FALSE;
2918 hdc = pwglGetCurrentDC();
2919 if(!hdc) {
2920 ERR("Failed to get gl HDC\n");
2921 HeapFree(GetProcessHeap(), 0, Adapters);
2922 WineD3D_ReleaseFakeGLContext();
2923 return FALSE;
2926 Adapters[0].driver = "Display";
2927 Adapters[0].description = "Direct3D HAL";
2929 /* Use the VideoRamSize registry setting when set */
2930 if(wined3d_settings.emulated_textureram)
2931 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2932 else
2933 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2934 Adapters[0].UsedTextureRam = 0;
2935 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2937 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2938 DisplayDevice.cb = sizeof(DisplayDevice);
2939 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2940 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2941 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2943 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2944 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2946 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2947 cfgs = Adapters[0].cfgs;
2948 PUSH1(WGL_RED_BITS_ARB)
2949 PUSH1(WGL_GREEN_BITS_ARB)
2950 PUSH1(WGL_BLUE_BITS_ARB)
2951 PUSH1(WGL_ALPHA_BITS_ARB)
2952 PUSH1(WGL_DEPTH_BITS_ARB)
2953 PUSH1(WGL_STENCIL_BITS_ARB)
2955 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2956 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2958 if(!res)
2959 continue;
2961 /* Cache the pixel format */
2962 cfgs->iPixelFormat = iPixelFormat;
2963 cfgs->redSize = values[0];
2964 cfgs->greenSize = values[1];
2965 cfgs->blueSize = values[2];
2966 cfgs->alphaSize = values[3];
2967 cfgs->depthSize = values[4];
2968 cfgs->stencilSize = values[5];
2970 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);
2971 cfgs++;
2973 WineD3D_ReleaseFakeGLContext();
2975 fixup_extensions(&Adapters[0].gl_info);
2977 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2978 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2981 numAdapters = 1;
2982 TRACE("%d adapters successfully initialized\n", numAdapters);
2984 return TRUE;
2986 #undef PUSH1
2987 #undef GLINFO_LOCATION
2989 /**********************************************************
2990 * IWineD3D VTbl follows
2991 **********************************************************/
2993 const IWineD3DVtbl IWineD3D_Vtbl =
2995 /* IUnknown */
2996 IWineD3DImpl_QueryInterface,
2997 IWineD3DImpl_AddRef,
2998 IWineD3DImpl_Release,
2999 /* IWineD3D */
3000 IWineD3DImpl_GetParent,
3001 IWineD3DImpl_GetAdapterCount,
3002 IWineD3DImpl_RegisterSoftwareDevice,
3003 IWineD3DImpl_GetAdapterMonitor,
3004 IWineD3DImpl_GetAdapterModeCount,
3005 IWineD3DImpl_EnumAdapterModes,
3006 IWineD3DImpl_GetAdapterDisplayMode,
3007 IWineD3DImpl_GetAdapterIdentifier,
3008 IWineD3DImpl_CheckDeviceMultiSampleType,
3009 IWineD3DImpl_CheckDepthStencilMatch,
3010 IWineD3DImpl_CheckDeviceType,
3011 IWineD3DImpl_CheckDeviceFormat,
3012 IWineD3DImpl_CheckDeviceFormatConversion,
3013 IWineD3DImpl_GetDeviceCaps,
3014 IWineD3DImpl_CreateDevice