wined3d: Fix dxtn format check.
[wine.git] / dlls / wined3d / directx.c
blobe4d8da2ad51884d3402811215abbe87190f37ba2
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_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
79 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
80 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
81 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
82 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
83 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
85 /* EXT */
86 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
87 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
88 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
89 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
90 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
91 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
92 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
93 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
94 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
95 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
96 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
97 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
98 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
99 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
100 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
101 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
102 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
103 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
104 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
105 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
106 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
108 /* NV */
109 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
110 {"GL_NV_fence", NV_FENCE, 0 },
111 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
112 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
113 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
114 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
115 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
116 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
117 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
118 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
119 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
120 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
121 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
122 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
123 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
124 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
125 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
126 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
128 /* SGI */
129 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
132 /**********************************************************
133 * Utility functions follow
134 **********************************************************/
136 /* Adapters */
137 static int numAdapters = 0;
138 static struct WineD3DAdapter Adapters[1];
140 /* lookup tables */
141 int minLookup[MAX_LOOKUPS];
142 int maxLookup[MAX_LOOKUPS];
143 DWORD *stateLookup[MAX_LOOKUPS];
145 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
147 /* drawStridedSlow attributes */
148 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
149 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
150 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
151 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
152 glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
155 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
156 * ie there is no GL Context - Get a default rendering context to enable the
157 * function query some info from GL
160 static int wined3d_fake_gl_context_ref = 0;
161 static BOOL wined3d_fake_gl_context_foreign;
162 static BOOL wined3d_fake_gl_context_available = FALSE;
163 static HDC wined3d_fake_gl_context_hdc = NULL;
164 static HWND wined3d_fake_gl_context_hwnd = NULL;
166 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
167 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
169 0, 0, &wined3d_fake_gl_context_cs,
170 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
171 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
172 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
174 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
176 static void WineD3D_ReleaseFakeGLContext(void) {
177 HGLRC glCtx;
179 EnterCriticalSection(&wined3d_fake_gl_context_cs);
181 if(!wined3d_fake_gl_context_available) {
182 TRACE_(d3d_caps)("context not available\n");
183 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
184 return;
187 glCtx = pwglGetCurrentContext();
189 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
190 if (0 == (--wined3d_fake_gl_context_ref) ) {
191 if(!wined3d_fake_gl_context_foreign && glCtx) {
192 TRACE_(d3d_caps)("destroying fake GL context\n");
193 pwglMakeCurrent(NULL, NULL);
194 pwglDeleteContext(glCtx);
196 if(wined3d_fake_gl_context_hdc)
197 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
198 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
199 if(wined3d_fake_gl_context_hwnd)
200 DestroyWindow(wined3d_fake_gl_context_hwnd);
201 wined3d_fake_gl_context_hwnd = NULL;
202 wined3d_fake_gl_context_available = FALSE;
204 assert(wined3d_fake_gl_context_ref >= 0);
206 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
209 static BOOL WineD3D_CreateFakeGLContext(void) {
210 HGLRC glCtx = NULL;
212 EnterCriticalSection(&wined3d_fake_gl_context_cs);
214 TRACE("getting context...\n");
215 if(wined3d_fake_gl_context_ref > 0) goto ret;
216 assert(0 == wined3d_fake_gl_context_ref);
218 wined3d_fake_gl_context_foreign = TRUE;
220 glCtx = pwglGetCurrentContext();
221 if (!glCtx) {
222 PIXELFORMATDESCRIPTOR pfd;
223 int iPixelFormat;
225 wined3d_fake_gl_context_foreign = FALSE;
227 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
228 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
229 if(!wined3d_fake_gl_context_hwnd) {
230 ERR("HWND creation failed!\n");
231 goto fail;
233 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
234 if(!wined3d_fake_gl_context_hdc) {
235 ERR("GetDC failed!\n");
236 goto fail;
239 /* PixelFormat selection */
240 ZeroMemory(&pfd, sizeof(pfd));
241 pfd.nSize = sizeof(pfd);
242 pfd.nVersion = 1;
243 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
244 pfd.iPixelType = PFD_TYPE_RGBA;
245 pfd.cColorBits = 32;
246 pfd.iLayerType = PFD_MAIN_PLANE;
248 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
249 if(!iPixelFormat) {
250 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
251 ERR("Can't find a suitable iPixelFormat\n");
252 goto fail;
254 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
255 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
257 /* Create a GL context */
258 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
259 if (!glCtx) {
260 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
261 goto fail;
264 /* Make it the current GL context */
265 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
266 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
267 goto fail;
271 ret:
272 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
273 wined3d_fake_gl_context_ref++;
274 wined3d_fake_gl_context_available = TRUE;
275 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
276 return TRUE;
277 fail:
278 if(wined3d_fake_gl_context_hdc)
279 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
280 wined3d_fake_gl_context_hdc = NULL;
281 if(wined3d_fake_gl_context_hwnd)
282 DestroyWindow(wined3d_fake_gl_context_hwnd);
283 wined3d_fake_gl_context_hwnd = NULL;
284 if(glCtx) pwglDeleteContext(glCtx);
285 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
286 return FALSE;
289 /* Adjust the amount of used texture memory */
290 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
291 UINT Adapter = D3DDevice->adapterNo;
293 Adapters[Adapter].UsedTextureRam += glram;
294 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
295 return Adapters[Adapter].UsedTextureRam;
298 /**********************************************************
299 * IUnknown parts follows
300 **********************************************************/
302 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
304 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
306 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
307 if (IsEqualGUID(riid, &IID_IUnknown)
308 || IsEqualGUID(riid, &IID_IWineD3DBase)
309 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
310 IUnknown_AddRef(iface);
311 *ppobj = This;
312 return S_OK;
314 *ppobj = NULL;
315 return E_NOINTERFACE;
318 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
319 IWineD3DImpl *This = (IWineD3DImpl *)iface;
320 ULONG refCount = InterlockedIncrement(&This->ref);
322 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
323 return refCount;
326 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
327 IWineD3DImpl *This = (IWineD3DImpl *)iface;
328 ULONG ref;
329 TRACE("(%p) : Releasing from %d\n", This, This->ref);
330 ref = InterlockedDecrement(&This->ref);
331 if (ref == 0) {
332 HeapFree(GetProcessHeap(), 0, This);
335 return ref;
338 /* Set the shader type for this device, depending on the given capabilities,
339 * the device type, and the user preferences in wined3d_settings */
341 static void select_shader_mode(
342 WineD3D_GL_Info *gl_info,
343 WINED3DDEVTYPE DeviceType,
344 int* ps_selected,
345 int* vs_selected) {
347 if (wined3d_settings.vs_mode == VS_NONE) {
348 *vs_selected = SHADER_NONE;
349 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
350 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
351 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
352 * shaders only on this card. */
353 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
354 *vs_selected = SHADER_ARB;
355 else
356 *vs_selected = SHADER_GLSL;
357 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
358 *vs_selected = SHADER_ARB;
359 } else {
360 *vs_selected = SHADER_NONE;
363 if (wined3d_settings.ps_mode == PS_NONE) {
364 *ps_selected = SHADER_NONE;
365 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
366 *ps_selected = SHADER_GLSL;
367 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
368 *ps_selected = SHADER_ARB;
369 } else {
370 *ps_selected = SHADER_NONE;
374 /** Select the number of report maximum shader constants based on the selected shader modes */
375 static void select_shader_max_constants(
376 int ps_selected_mode,
377 int vs_selected_mode,
378 WineD3D_GL_Info *gl_info) {
380 switch (vs_selected_mode) {
381 case SHADER_GLSL:
382 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
383 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
384 break;
385 case SHADER_ARB:
386 /* We have to subtract any other PARAMs that we might use in our shader programs.
387 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
388 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
389 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
390 break;
391 default:
392 gl_info->max_vshader_constantsF = 0;
393 break;
396 switch (ps_selected_mode) {
397 case SHADER_GLSL:
398 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
399 * In theory the texbem instruction may need one more shader constant too. But lets assume
400 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
401 * and lets not take away a uniform needlessly from all other shaders.
403 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
404 break;
405 case SHADER_ARB:
406 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
407 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
409 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
410 break;
411 default:
412 gl_info->max_pshader_constantsF = 0;
413 break;
417 /**********************************************************
418 * IWineD3D parts follows
419 **********************************************************/
421 #define GLINFO_LOCATION (*gl_info)
422 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
423 GLuint prog;
424 BOOL ret = FALSE;
425 const char *testcode =
426 "!!ARBvp1.0\n"
427 "PARAM C[66] = { program.env[0..65] };\n"
428 "ADDRESS A0;"
429 "ARL A0.x, 0.0;\n"
430 "MOV result.position, C[A0.x + 65];\n"
431 "END\n";
433 while(glGetError());
434 GL_EXTCALL(glGenProgramsARB(1, &prog));
435 if(!prog) {
436 ERR("Failed to create an ARB offset limit test program\n");
438 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
439 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
440 strlen(testcode), testcode));
441 if(glGetError() != 0) {
442 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
443 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
444 ret = TRUE;
445 } else TRACE("OpenGL implementation allows offsets > 63\n");
447 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
448 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
449 checkGLcall("ARB vp offset limit test cleanup\n");
451 return ret;
454 static DWORD ver_for_ext(GL_SupportedExt ext)
456 unsigned int i;
457 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
458 if(EXTENSION_MAP[i].extension == ext) {
459 return EXTENSION_MAP[i].version;
462 return 0;
465 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
466 const char *GL_Extensions = NULL;
467 const char *WGL_Extensions = NULL;
468 const char *gl_string = NULL;
469 const char *gl_string_cursor = NULL;
470 GLint gl_max;
471 GLfloat gl_floatv[2];
472 int major = 1, minor = 0;
473 BOOL return_value = TRUE;
474 unsigned i;
475 HDC hdc;
476 unsigned int vidmem=0;
478 TRACE_(d3d_caps)("(%p)\n", gl_info);
480 ENTER_GL();
482 gl_string = (const char *) glGetString(GL_RENDERER);
483 if (NULL == gl_string)
484 gl_string = "None";
485 strcpy(gl_info->gl_renderer, gl_string);
487 gl_string = (const char *) glGetString(GL_VENDOR);
488 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
489 if (gl_string != NULL) {
490 /* Fill in the GL vendor */
491 if (strstr(gl_string, "NVIDIA")) {
492 gl_info->gl_vendor = VENDOR_NVIDIA;
493 } else if (strstr(gl_string, "ATI")) {
494 gl_info->gl_vendor = VENDOR_ATI;
495 } else if (strstr(gl_string, "Intel(R)") ||
496 strstr(gl_info->gl_renderer, "Intel(R)") ||
497 strstr(gl_string, "Intel Inc.")) {
498 gl_info->gl_vendor = VENDOR_INTEL;
499 } else if (strstr(gl_string, "Mesa")) {
500 gl_info->gl_vendor = VENDOR_MESA;
501 } else {
502 gl_info->gl_vendor = VENDOR_WINE;
504 } else {
505 gl_info->gl_vendor = VENDOR_WINE;
509 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
511 /* Parse the GL_VERSION field into major and minor information */
512 gl_string = (const char *) glGetString(GL_VERSION);
513 if (gl_string != NULL) {
515 switch (gl_info->gl_vendor) {
516 case VENDOR_NVIDIA:
517 gl_string_cursor = strstr(gl_string, "NVIDIA");
518 if (!gl_string_cursor) {
519 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
520 break;
523 gl_string_cursor = strstr(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 while (*gl_string_cursor == ' ') {
530 ++gl_string_cursor;
533 if (!*gl_string_cursor) {
534 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
535 break;
538 major = atoi(gl_string_cursor);
539 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
540 ++gl_string_cursor;
543 if (*gl_string_cursor++ != '.') {
544 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
545 break;
548 minor = atoi(gl_string_cursor);
549 minor = major*100+minor;
550 major = 10;
552 break;
554 case VENDOR_ATI:
555 major = minor = 0;
556 gl_string_cursor = strchr(gl_string, '-');
557 if (gl_string_cursor) {
558 int error = 0;
559 gl_string_cursor++;
561 /* Check if version number is of the form x.y.z */
562 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
563 error = 1;
564 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
565 error = 1;
566 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
567 error = 1;
568 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
569 error = 1;
571 /* Mark version number as malformed */
572 if (error)
573 gl_string_cursor = 0;
576 if (!gl_string_cursor)
577 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
578 else {
579 major = *gl_string_cursor - '0';
580 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
582 break;
584 case VENDOR_INTEL:
585 /* Apple and Mesa version strings look differently, but both provide intel drivers */
586 if(strstr(gl_string, "APPLE")) {
587 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
588 * We only need the first part, and use the APPLE as identification
589 * "1.2 APPLE-1.4.56"
591 gl_string_cursor = gl_string;
592 major = atoi(gl_string_cursor);
593 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
594 ++gl_string_cursor;
597 if (*gl_string_cursor++ != '.') {
598 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
599 break;
602 minor = atoi(gl_string_cursor);
603 break;
606 case VENDOR_MESA:
607 gl_string_cursor = strstr(gl_string, "Mesa");
608 gl_string_cursor = strstr(gl_string_cursor, " ");
609 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
610 if (*gl_string_cursor) {
611 char tmp[16];
612 int cursor = 0;
614 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
615 tmp[cursor++] = *gl_string_cursor;
616 ++gl_string_cursor;
618 tmp[cursor] = 0;
619 major = atoi(tmp);
621 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
622 ++gl_string_cursor;
624 cursor = 0;
625 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
626 tmp[cursor++] = *gl_string_cursor;
627 ++gl_string_cursor;
629 tmp[cursor] = 0;
630 minor = atoi(tmp);
632 break;
634 default:
635 major = 0;
636 minor = 9;
638 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
639 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
642 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
645 * Initialize openGL extension related variables
646 * with Default values
648 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
649 gl_info->max_buffers = 1;
650 gl_info->max_textures = 1;
651 gl_info->max_texture_stages = 1;
652 gl_info->max_fragment_samplers = 1;
653 gl_info->max_vertex_samplers = 0;
654 gl_info->max_combined_samplers = 0;
655 gl_info->max_sampler_stages = 1;
656 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
657 gl_info->ps_arb_max_temps = 0;
658 gl_info->ps_arb_max_instructions = 0;
659 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
660 gl_info->vs_arb_max_temps = 0;
661 gl_info->vs_arb_max_instructions = 0;
662 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
663 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
664 gl_info->vs_glsl_constantsF = 0;
665 gl_info->ps_glsl_constantsF = 0;
666 gl_info->vs_arb_constantsF = 0;
667 gl_info->ps_arb_constantsF = 0;
669 /* Retrieve opengl defaults */
670 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
671 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
672 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
674 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
675 gl_info->max_lights = gl_max;
676 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
678 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
679 gl_info->max_texture_size = gl_max;
680 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
682 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
683 gl_info->max_pointsizemin = gl_floatv[0];
684 gl_info->max_pointsize = gl_floatv[1];
685 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
687 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
688 gl_info->max_aux_buffers = gl_max;
689 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
691 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
692 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
693 TRACE_(d3d_caps)("GL_Extensions reported:\n");
695 if (NULL == GL_Extensions) {
696 ERR(" GL_Extensions returns NULL\n");
697 } else {
698 while (*GL_Extensions != 0x00) {
699 const char *Start;
700 char ThisExtn[256];
701 size_t len;
703 while (isspace(*GL_Extensions)) GL_Extensions++;
704 Start = GL_Extensions;
705 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
706 GL_Extensions++;
709 len = GL_Extensions - Start;
710 if (len == 0 || len >= sizeof(ThisExtn))
711 continue;
713 memcpy(ThisExtn, Start, len);
714 ThisExtn[len] = '\0';
715 TRACE_(d3d_caps)("- %s\n", ThisExtn);
717 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
718 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
719 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
720 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
721 break;
725 /* Now work out what GL support this card really has */
726 #define USE_GL_FUNC(type, pfn, ext, replace) { \
727 DWORD ver = ver_for_ext(ext); \
728 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
729 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
730 else gl_info->pfn = NULL; \
732 GL_EXT_FUNCS_GEN;
733 #undef USE_GL_FUNC
735 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
736 WGL_EXT_FUNCS_GEN;
737 #undef USE_GL_FUNC
739 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
740 * loading the functions, otherwise the code above will load the extension entry points instead of the
741 * core functions, which may not work
743 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
744 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
745 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
746 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
747 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
751 if (gl_info->supported[APPLE_FENCE]) {
752 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
753 * The apple extension interacts with some other apple exts. Disable the NV
754 * extension if the apple one is support to prevent confusion in other parts
755 * of the code
757 gl_info->supported[NV_FENCE] = FALSE;
759 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
760 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
761 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
763 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
764 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
765 * Won't occur in any real world situation though
767 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
769 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
770 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
771 gl_info->max_buffers = gl_max;
772 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
774 if (gl_info->supported[ARB_MULTITEXTURE]) {
775 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
776 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
777 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
779 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
780 GLint tmp;
781 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
782 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
783 } else {
784 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
786 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
788 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
789 GLint tmp;
790 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
791 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
792 } else {
793 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
795 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
797 if (gl_info->supported[ARB_VERTEX_SHADER]) {
798 GLint tmp;
799 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
800 gl_info->max_vertex_samplers = tmp;
801 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
802 gl_info->max_combined_samplers = tmp;
804 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
805 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
806 * an issue because then the sampler setup only depends on the two shaders. If a pixel
807 * shader is used with fixed function vertex processing we're fine too because fixed function
808 * vertex processing doesn't use any samplers. If fixed function fragment processing is
809 * used we have to make sure that all vertex sampler setups are valid together with all
810 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
811 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
812 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
813 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
814 * a fixed function pipeline anymore.
816 * So this is just a check to check that our assumption holds true. If not, write a warning
817 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
819 if(gl_info->max_vertex_samplers &&
820 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
821 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
822 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
823 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
824 if( gl_info->max_combined_samplers > MAX_TEXTURES )
825 gl_info->max_vertex_samplers =
826 gl_info->max_combined_samplers - MAX_TEXTURES;
827 else
828 gl_info->max_vertex_samplers = 0;
830 } else {
831 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
833 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
834 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
836 if (gl_info->supported[ARB_VERTEX_BLEND]) {
837 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
838 gl_info->max_blends = gl_max;
839 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
841 if (gl_info->supported[EXT_TEXTURE3D]) {
842 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
843 gl_info->max_texture3d_size = gl_max;
844 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
846 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
847 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
848 gl_info->max_anisotropy = gl_max;
849 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
851 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
852 gl_info->ps_arb_version = PS_VERSION_11;
853 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
854 gl_info->ps_arb_constantsF = gl_max;
855 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
856 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
857 gl_info->ps_arb_max_temps = gl_max;
858 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
859 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
860 gl_info->ps_arb_max_instructions = gl_max;
861 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
863 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
864 gl_info->vs_arb_version = VS_VERSION_11;
865 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
866 gl_info->vs_arb_constantsF = gl_max;
867 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
868 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
869 gl_info->vs_arb_max_temps = gl_max;
870 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
871 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
872 gl_info->vs_arb_max_instructions = gl_max;
873 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
875 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
877 if (gl_info->supported[ARB_VERTEX_SHADER]) {
878 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
879 gl_info->vs_glsl_constantsF = gl_max / 4;
880 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
882 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
883 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
884 gl_info->ps_glsl_constantsF = gl_max / 4;
885 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
886 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
887 gl_info->max_glsl_varyings = gl_max;
888 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
890 if (gl_info->supported[EXT_VERTEX_SHADER]) {
891 gl_info->vs_ati_version = VS_VERSION_11;
893 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
894 gl_info->vs_nv_version = VS_VERSION_30;
895 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
896 gl_info->vs_nv_version = VS_VERSION_20;
897 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
898 gl_info->vs_nv_version = VS_VERSION_11;
899 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
900 gl_info->vs_nv_version = VS_VERSION_10;
902 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
903 gl_info->ps_nv_version = PS_VERSION_30;
904 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
905 gl_info->ps_nv_version = PS_VERSION_20;
907 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
908 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
909 * This saves a few redundant glDisable calls
911 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
915 checkGLcall("extension detection\n");
917 /* In some cases the number of texture stages can be larger than the number
918 * of samplers. The GF4 for example can use only 2 samplers (no fragment
919 * shaders), but 8 texture stages (register combiners). */
920 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
922 /* We can only use ORM_FBO when the hardware supports it. */
923 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
924 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
925 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
928 /* MRTs are currently only supported when FBOs are used. */
929 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
930 gl_info->max_buffers = 1;
933 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
934 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
935 * in case of the latest videocards in the number of pixel/vertex pipelines.
937 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
938 * rendering. Various games use this information to get a rough estimation of the features of the card
939 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
940 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
941 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
942 * not the PCI id.
944 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
945 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
946 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
947 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
948 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
949 * is used for rendering which is not always the case). This would work but it is not very portable. Second
950 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
951 * is limited.
953 * As said most games only use the PCI id to get an indication of the capabilities of the card.
954 * It doesn't really matter if the given id is the correct one if we return the id of a card with
955 * similar 3d features.
957 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
958 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
959 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
960 * won't pass we return a default card. This way is better than maintaining a full card database as even
961 * without a full database we can return a card with similar features. Second the size of the database
962 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
963 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
964 * to distinguishes between different models from that family.
966 * The code also selects a default amount of video memory which we will use for an estimation of the amount
967 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
968 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
969 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
970 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
971 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
972 * memory behind our backs if really needed.
973 * Note that the amount of video memory can be overruled using a registry setting.
975 switch (gl_info->gl_vendor) {
976 case VENDOR_NVIDIA:
977 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
978 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
980 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
981 /* Geforce8 - highend */
982 if (strstr(gl_info->gl_renderer, "8800")) {
983 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
984 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
986 /* Geforce8 - midend mobile */
987 else if(strstr(gl_info->gl_renderer, "8600 M")) {
988 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
989 vidmem = 512;
991 /* Geforce8 - midend */
992 else if(strstr(gl_info->gl_renderer, "8600") ||
993 strstr(gl_info->gl_renderer, "8700"))
995 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
996 vidmem = 256;
998 /* Geforce8 - lowend */
999 else if(strstr(gl_info->gl_renderer, "8300") ||
1000 strstr(gl_info->gl_renderer, "8400") ||
1001 strstr(gl_info->gl_renderer, "8500"))
1003 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1004 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1006 /* Geforce7 - highend */
1007 else if(strstr(gl_info->gl_renderer, "7800") ||
1008 strstr(gl_info->gl_renderer, "7900") ||
1009 strstr(gl_info->gl_renderer, "7950") ||
1010 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1011 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1013 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1014 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1016 /* Geforce7 midend */
1017 else if(strstr(gl_info->gl_renderer, "7600") ||
1018 strstr(gl_info->gl_renderer, "7700")) {
1019 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1020 vidmem = 256; /* The 7600 uses 256-512MB */
1021 /* Geforce7 lower medium */
1022 } else if(strstr(gl_info->gl_renderer, "7400")) {
1023 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1024 vidmem = 256; /* The 7400 uses 256-512MB */
1026 /* Geforce7 lowend */
1027 else if(strstr(gl_info->gl_renderer, "7300")) {
1028 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1029 vidmem = 256; /* Mac Pros with this card have 256 MB */
1031 /* Geforce6 highend */
1032 else if(strstr(gl_info->gl_renderer, "6800"))
1034 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1035 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1037 /* Geforce6 - midend */
1038 else if(strstr(gl_info->gl_renderer, "6600") ||
1039 strstr(gl_info->gl_renderer, "6610") ||
1040 strstr(gl_info->gl_renderer, "6700"))
1042 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1043 vidmem = 128; /* A 6600GT has 128-256MB */
1045 /* Geforce6/7 lowend */
1046 else {
1047 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1048 vidmem = 64; /* */
1050 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1051 /* GeforceFX - highend */
1052 if (strstr(gl_info->gl_renderer, "5800") ||
1053 strstr(gl_info->gl_renderer, "5900") ||
1054 strstr(gl_info->gl_renderer, "5950") ||
1055 strstr(gl_info->gl_renderer, "Quadro FX"))
1057 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1058 vidmem = 256; /* 5800-5900 cards use 256MB */
1060 /* GeforceFX - midend */
1061 else if(strstr(gl_info->gl_renderer, "5600") ||
1062 strstr(gl_info->gl_renderer, "5650") ||
1063 strstr(gl_info->gl_renderer, "5700") ||
1064 strstr(gl_info->gl_renderer, "5750"))
1066 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1067 vidmem = 128; /* A 5600 uses 128-256MB */
1069 /* GeforceFX - lowend */
1070 else {
1071 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1072 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1074 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1075 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1076 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1077 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1079 else {
1080 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1081 vidmem = 64; /* Geforce3 cards have 64-128MB */
1083 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1084 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1085 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1086 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1088 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1089 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1090 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1092 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1093 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1094 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1096 else {
1097 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1098 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1100 } else {
1101 if (strstr(gl_info->gl_renderer, "TNT2")) {
1102 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1103 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1105 else {
1106 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1107 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1110 break;
1111 case VENDOR_ATI:
1112 if(WINE_D3D9_CAPABLE(gl_info)) {
1113 /* Radeon R6xx HD2900 - highend */
1114 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1115 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1116 vidmem = 512; /* HD2900 uses 512-1024MB */
1118 /* Radeon R6xx HD2600- midend */
1119 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1120 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1121 vidmem = 256; /* HD2600 uses 256-512MB */
1123 /* Radeon R6xx HD2300/HD2400 - lowend */
1124 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1125 strstr(gl_info->gl_renderer, "HD 2400"))
1127 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1128 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1130 /* Radeon R5xx */
1131 else if (strstr(gl_info->gl_renderer, "X1600") ||
1132 strstr(gl_info->gl_renderer, "X1650") ||
1133 strstr(gl_info->gl_renderer, "X1800") ||
1134 strstr(gl_info->gl_renderer, "X1900") ||
1135 strstr(gl_info->gl_renderer, "X1950"))
1137 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1138 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1140 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1141 else if(strstr(gl_info->gl_renderer, "X700") ||
1142 strstr(gl_info->gl_renderer, "X800") ||
1143 strstr(gl_info->gl_renderer, "X850") ||
1144 strstr(gl_info->gl_renderer, "X1300") ||
1145 strstr(gl_info->gl_renderer, "X1400") ||
1146 strstr(gl_info->gl_renderer, "X1450") ||
1147 strstr(gl_info->gl_renderer, "X1550"))
1149 gl_info->gl_card = CARD_ATI_RADEON_X700;
1150 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1152 /* Radeon R3xx */
1153 else {
1154 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1155 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1157 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1158 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1159 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1160 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1161 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1162 vidmem = 32; /* There are models with up to 64MB */
1163 } else {
1164 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1165 vidmem = 16; /* There are 16-32MB models */
1167 break;
1168 case VENDOR_INTEL:
1169 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1170 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1171 gl_info->gl_card = CARD_INTEL_I945GM;
1172 vidmem = 64;
1173 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1174 gl_info->gl_card = CARD_INTEL_I915GM;
1175 } else if (strstr(gl_info->gl_renderer, "915G")) {
1176 gl_info->gl_card = CARD_INTEL_I915G;
1177 } else if (strstr(gl_info->gl_renderer, "865G")) {
1178 gl_info->gl_card = CARD_INTEL_I865G;
1179 } else if (strstr(gl_info->gl_renderer, "855G")) {
1180 gl_info->gl_card = CARD_INTEL_I855G;
1181 } else if (strstr(gl_info->gl_renderer, "830G")) {
1182 gl_info->gl_card = CARD_INTEL_I830G;
1183 } else {
1184 gl_info->gl_card = CARD_INTEL_I915G;
1186 break;
1187 case VENDOR_MESA:
1188 case VENDOR_WINE:
1189 default:
1190 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1191 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1192 * them a good generic choice.
1194 gl_info->gl_vendor = VENDOR_NVIDIA;
1195 if(WINE_D3D9_CAPABLE(gl_info))
1196 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1197 else if(WINE_D3D8_CAPABLE(gl_info))
1198 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1199 else if(WINE_D3D7_CAPABLE(gl_info))
1200 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1201 else if(WINE_D3D6_CAPABLE(gl_info))
1202 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1203 else
1204 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1206 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1208 /* If we have an estimate use it, else default to 64MB; */
1209 if(vidmem)
1210 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1211 else
1212 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1214 /* Load all the lookup tables
1215 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1216 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1217 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1219 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1220 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1223 for (i = 0; i < MAX_LOOKUPS; i++) {
1224 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1227 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1228 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1229 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1230 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1231 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1232 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1233 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1234 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1235 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1236 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1238 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1239 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1240 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1241 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1242 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1245 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1246 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1247 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1248 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1249 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1250 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1251 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1252 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1253 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1254 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1255 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1256 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1257 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1259 /* TODO: config lookups */
1261 /* Make sure there's an active HDC else the WGL extensions will fail */
1262 hdc = pwglGetCurrentDC();
1263 if (hdc) {
1264 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1265 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1267 if (NULL == WGL_Extensions) {
1268 ERR(" WGL_Extensions returns NULL\n");
1269 } else {
1270 while (*WGL_Extensions != 0x00) {
1271 const char *Start;
1272 char ThisExtn[256];
1273 size_t len;
1275 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1276 Start = WGL_Extensions;
1277 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1278 WGL_Extensions++;
1281 len = WGL_Extensions - Start;
1282 if (len == 0 || len >= sizeof(ThisExtn))
1283 continue;
1285 memcpy(ThisExtn, Start, len);
1286 ThisExtn[len] = '\0';
1287 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1289 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1290 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1291 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1296 LEAVE_GL();
1298 return return_value;
1300 #undef GLINFO_LOCATION
1302 /**********************************************************
1303 * IWineD3D implementation follows
1304 **********************************************************/
1306 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1307 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1309 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1310 return numAdapters;
1313 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1314 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1315 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1316 return WINED3D_OK;
1319 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1320 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1322 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1323 return NULL;
1326 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1327 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1330 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1331 of the same bpp but different resolutions */
1333 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1334 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1335 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1336 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1338 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1339 return 0;
1342 /* TODO: Store modes per adapter and read it from the adapter structure */
1343 if (Adapter == 0) { /* Display */
1344 int i = 0;
1345 int j = 0;
1347 if (!DEBUG_SINGLE_MODE) {
1348 DEVMODEW DevModeW;
1350 ZeroMemory(&DevModeW, sizeof(DevModeW));
1351 DevModeW.dmSize = sizeof(DevModeW);
1352 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1353 j++;
1354 switch (Format)
1356 case WINED3DFMT_UNKNOWN:
1357 /* This is for D3D8, do not enumerate P8 here */
1358 if (DevModeW.dmBitsPerPel == 32 ||
1359 DevModeW.dmBitsPerPel == 16) i++;
1360 break;
1361 case WINED3DFMT_X8R8G8B8:
1362 if (DevModeW.dmBitsPerPel == 32) i++;
1363 break;
1364 case WINED3DFMT_R5G6B5:
1365 if (DevModeW.dmBitsPerPel == 16) i++;
1366 break;
1367 case WINED3DFMT_P8:
1368 if (DevModeW.dmBitsPerPel == 8) i++;
1369 break;
1370 default:
1371 /* Skip other modes as they do not match the requested format */
1372 break;
1375 } else {
1376 i = 1;
1377 j = 1;
1380 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1381 return i;
1382 } else {
1383 FIXME_(d3d_caps)("Adapter not primary display\n");
1385 return 0;
1388 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1389 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1390 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1391 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1393 /* Validate the parameters as much as possible */
1394 if (NULL == pMode ||
1395 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1396 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1397 return WINED3DERR_INVALIDCALL;
1400 /* TODO: Store modes per adapter and read it from the adapter structure */
1401 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1402 DEVMODEW DevModeW;
1403 int ModeIdx = 0;
1404 int i = 0;
1405 int j = 0;
1407 ZeroMemory(&DevModeW, sizeof(DevModeW));
1408 DevModeW.dmSize = sizeof(DevModeW);
1410 /* If we are filtering to a specific format (D3D9), then need to skip
1411 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1412 just count through the ones with valid bit depths */
1413 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1414 switch (Format)
1416 case WINED3DFMT_UNKNOWN:
1417 /* This is D3D8. Do not enumerate P8 here */
1418 if (DevModeW.dmBitsPerPel == 32 ||
1419 DevModeW.dmBitsPerPel == 16) i++;
1420 break;
1421 case WINED3DFMT_X8R8G8B8:
1422 if (DevModeW.dmBitsPerPel == 32) i++;
1423 break;
1424 case WINED3DFMT_R5G6B5:
1425 if (DevModeW.dmBitsPerPel == 16) i++;
1426 break;
1427 case WINED3DFMT_P8:
1428 if (DevModeW.dmBitsPerPel == 8) i++;
1429 break;
1430 default:
1431 /* Modes that don't match what we support can get an early-out */
1432 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1433 return WINED3DERR_INVALIDCALL;
1437 if (i == 0) {
1438 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1439 return WINED3DERR_INVALIDCALL;
1441 ModeIdx = j - 1;
1443 /* Now get the display mode via the calculated index */
1444 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1445 pMode->Width = DevModeW.dmPelsWidth;
1446 pMode->Height = DevModeW.dmPelsHeight;
1447 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1448 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1449 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1451 if (Format == WINED3DFMT_UNKNOWN) {
1452 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1453 } else {
1454 pMode->Format = Format;
1456 } else {
1457 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1458 return WINED3DERR_INVALIDCALL;
1461 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1462 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1463 DevModeW.dmBitsPerPel);
1465 } else if (DEBUG_SINGLE_MODE) {
1466 /* Return one setting of the format requested */
1467 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1468 pMode->Width = 800;
1469 pMode->Height = 600;
1470 pMode->RefreshRate = 60;
1471 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1472 } else {
1473 FIXME_(d3d_caps)("Adapter not primary display\n");
1476 return WINED3D_OK;
1479 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1480 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1481 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1483 if (NULL == pMode ||
1484 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1485 return WINED3DERR_INVALIDCALL;
1488 if (Adapter == 0) { /* Display */
1489 int bpp = 0;
1490 DEVMODEW DevModeW;
1492 ZeroMemory(&DevModeW, sizeof(DevModeW));
1493 DevModeW.dmSize = sizeof(DevModeW);
1495 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1496 pMode->Width = DevModeW.dmPelsWidth;
1497 pMode->Height = DevModeW.dmPelsHeight;
1498 bpp = DevModeW.dmBitsPerPel;
1499 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1500 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1502 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1505 pMode->Format = pixelformat_for_depth(bpp);
1506 } else {
1507 FIXME_(d3d_caps)("Adapter not primary display\n");
1510 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1511 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1512 return WINED3D_OK;
1515 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1516 and fields being inserted in the middle, a new structure is used in place */
1517 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1518 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1519 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1521 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1523 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1524 return WINED3DERR_INVALIDCALL;
1527 /* Return the information requested */
1528 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1529 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1530 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1532 /* Note dx8 doesn't supply a DeviceName */
1533 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1534 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1535 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1536 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1537 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1538 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1539 *(pIdentifier->SubSysId) = 0;
1540 *(pIdentifier->Revision) = 0;
1542 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1543 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1544 *(pIdentifier->WHQLLevel) = 0;
1545 } else {
1546 *(pIdentifier->WHQLLevel) = 1;
1549 return WINED3D_OK;
1552 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1553 short redSize, greenSize, blueSize, alphaSize, colorBits;
1555 if(!cfg)
1556 return FALSE;
1558 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1559 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1560 return FALSE;
1563 if(cfg->redSize < redSize)
1564 return FALSE;
1566 if(cfg->greenSize < greenSize)
1567 return FALSE;
1569 if(cfg->blueSize < blueSize)
1570 return FALSE;
1572 if(cfg->alphaSize < alphaSize)
1573 return FALSE;
1575 return TRUE;
1578 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1579 short depthSize, stencilSize;
1581 if(!cfg)
1582 return FALSE;
1584 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1585 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1586 return FALSE;
1589 if(cfg->depthSize < depthSize)
1590 return FALSE;
1592 if(cfg->stencilSize < stencilSize)
1593 return FALSE;
1595 return TRUE;
1598 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1599 WINED3DFORMAT AdapterFormat,
1600 WINED3DFORMAT RenderTargetFormat,
1601 WINED3DFORMAT DepthStencilFormat) {
1602 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1603 int nCfgs;
1604 WineD3D_PixelFormat *cfgs;
1605 int it;
1607 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1608 This, Adapter,
1609 DeviceType, debug_d3ddevicetype(DeviceType),
1610 AdapterFormat, debug_d3dformat(AdapterFormat),
1611 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1612 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1614 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1615 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1616 return WINED3DERR_INVALIDCALL;
1619 cfgs = Adapters[Adapter].cfgs;
1620 nCfgs = Adapters[Adapter].nCfgs;
1621 for (it = 0; it < nCfgs; ++it) {
1622 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1623 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1624 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1625 return WINED3D_OK;
1629 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1631 return WINED3DERR_NOTAVAILABLE;
1634 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1635 WINED3DFORMAT SurfaceFormat,
1636 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1638 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1639 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1640 This,
1641 Adapter,
1642 DeviceType, debug_d3ddevicetype(DeviceType),
1643 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1644 Windowed,
1645 MultiSampleType,
1646 pQualityLevels);
1648 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1649 return WINED3DERR_INVALIDCALL;
1652 /* TODO: Store in Adapter structure */
1653 if (pQualityLevels != NULL) {
1654 static int s_single_shot = 0;
1655 if (!s_single_shot) {
1656 FIXME("Quality levels unsupported at present\n");
1657 s_single_shot = 1;
1659 *pQualityLevels = 1; /* Guess at a value! */
1662 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1663 return WINED3DERR_NOTAVAILABLE;
1666 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1667 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1669 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1670 int nCfgs = 0;
1671 WineD3D_PixelFormat *cfgs;
1672 int it;
1673 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1675 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1676 This,
1677 Adapter,
1678 CheckType, debug_d3ddevicetype(CheckType),
1679 DisplayFormat, debug_d3dformat(DisplayFormat),
1680 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1681 Windowed);
1683 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1684 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1685 return WINED3DERR_INVALIDCALL;
1688 cfgs = Adapters[Adapter].cfgs;
1689 nCfgs = Adapters[Adapter].nCfgs;
1690 for (it = 0; it < nCfgs; ++it) {
1691 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1692 hr = WINED3D_OK;
1693 TRACE_(d3d_caps)("OK\n");
1694 break ;
1698 if(hr != WINED3D_OK)
1699 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1701 if(hr != WINED3D_OK)
1702 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1704 return hr;
1707 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1708 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1709 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1710 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1711 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1712 This,
1713 Adapter,
1714 DeviceType, debug_d3ddevicetype(DeviceType),
1715 AdapterFormat, debug_d3dformat(AdapterFormat),
1716 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1717 RType, debug_d3dresourcetype(RType),
1718 CheckFormat, debug_d3dformat(CheckFormat));
1720 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1721 return WINED3DERR_INVALIDCALL;
1724 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1725 switch (CheckFormat) {
1726 /* Filtering not supported */
1727 case WINED3DFMT_R32F:
1728 case WINED3DFMT_A32B32G32R32F:
1729 TRACE_(d3d_caps)("[FAILED]\n");
1730 return WINED3DERR_NOTAVAILABLE;
1731 default:
1732 break;
1736 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1737 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1738 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1739 return WINED3DERR_NOTAVAILABLE;
1743 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1744 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1745 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1746 return WINED3DERR_NOTAVAILABLE;
1748 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1749 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1750 * app needing one of those formats, don't advertize them to avoid leading apps into
1751 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1752 * except of R32F.
1754 switch(CheckFormat) {
1755 case WINED3DFMT_P8:
1756 case WINED3DFMT_A4L4:
1757 case WINED3DFMT_R32F:
1758 case WINED3DFMT_R16F:
1759 case WINED3DFMT_X8L8V8U8:
1760 case WINED3DFMT_L6V5U5:
1761 case WINED3DFMT_G16R16:
1762 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1763 return WINED3DERR_NOTAVAILABLE;
1765 case WINED3DFMT_Q8W8V8U8:
1766 case WINED3DFMT_V16U16:
1767 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1768 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1769 return WINED3DERR_NOTAVAILABLE;
1771 break;
1773 case WINED3DFMT_V8U8:
1774 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1775 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1776 return WINED3DERR_NOTAVAILABLE;
1778 break;
1780 case WINED3DFMT_DXT1:
1781 case WINED3DFMT_DXT2:
1782 case WINED3DFMT_DXT3:
1783 case WINED3DFMT_DXT4:
1784 case WINED3DFMT_DXT5:
1785 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1786 * compressed texture results in an error. While the D3D refrast does
1787 * support s3tc volumes, at least the nvidia windows driver does not, so
1788 * we're free not to support this format.
1790 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1791 return WINED3DERR_NOTAVAILABLE;
1793 default:
1794 /* Do nothing, continue with checking the format below */
1795 break;
1798 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1799 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1800 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1801 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1802 if (!GL_LIMITS(vertex_samplers)) {
1803 TRACE_(d3d_caps)("[FAILED]\n");
1804 return WINED3DERR_NOTAVAILABLE;
1807 switch (CheckFormat) {
1808 case WINED3DFMT_A32B32G32R32F:
1809 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1810 TRACE_(d3d_caps)("[FAILED]\n");
1811 return WINED3DERR_NOTAVAILABLE;
1813 TRACE_(d3d_caps)("[OK]\n");
1814 return WINED3D_OK;
1816 default:
1817 TRACE_(d3d_caps)("[FAILED]\n");
1818 return WINED3DERR_NOTAVAILABLE;
1822 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1823 switch (CheckFormat) {
1824 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1825 * Windows supports only those 3, and enumerating the other formats confuses applications
1827 case WINED3DFMT_D24S8:
1828 case WINED3DFMT_D24X8:
1829 case WINED3DFMT_D16:
1830 TRACE_(d3d_caps)("[OK]\n");
1831 return WINED3D_OK;
1832 case WINED3DFMT_D16_LOCKABLE:
1833 case WINED3DFMT_D24FS8:
1834 case WINED3DFMT_D32F_LOCKABLE:
1835 case WINED3DFMT_D24X4S4:
1836 case WINED3DFMT_D15S1:
1837 case WINED3DFMT_D32:
1838 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1839 return WINED3DERR_NOTAVAILABLE;
1840 default:
1841 TRACE_(d3d_caps)("[FAILED]\n");
1842 return WINED3DERR_NOTAVAILABLE;
1844 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1845 switch (CheckFormat) {
1846 case WINED3DFMT_R8G8B8:
1847 case WINED3DFMT_A8R8G8B8:
1848 case WINED3DFMT_X8R8G8B8:
1849 case WINED3DFMT_R5G6B5:
1850 case WINED3DFMT_X1R5G5B5:
1851 case WINED3DFMT_A1R5G5B5:
1852 case WINED3DFMT_A4R4G4B4:
1853 case WINED3DFMT_R3G3B2:
1854 case WINED3DFMT_X4R4G4B4:
1855 case WINED3DFMT_A8B8G8R8:
1856 case WINED3DFMT_X8B8G8R8:
1857 case WINED3DFMT_P8:
1858 case WINED3DFMT_G16R16:
1859 TRACE_(d3d_caps)("[OK]\n");
1860 return WINED3D_OK;
1861 case WINED3DFMT_R16F:
1862 case WINED3DFMT_A16B16G16R16F:
1863 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1864 TRACE_(d3d_caps)("[FAILED]\n");
1865 return WINED3DERR_NOTAVAILABLE;
1867 TRACE_(d3d_caps)("[OK]\n");
1868 return WINED3D_OK;
1869 case WINED3DFMT_A32B32G32R32F:
1870 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1871 TRACE_(d3d_caps)("[FAILED]\n");
1872 return WINED3DERR_NOTAVAILABLE;
1874 TRACE_(d3d_caps)("[OK]\n");
1875 return WINED3D_OK;
1876 default:
1877 TRACE_(d3d_caps)("[FAILED]\n");
1878 return WINED3DERR_NOTAVAILABLE;
1880 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1881 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1882 switch (CheckFormat) {
1883 case WINED3DFMT_V8U8:
1884 TRACE_(d3d_caps)("[OK]\n");
1885 return WINED3D_OK;
1886 /* TODO: Other bump map formats */
1887 default:
1888 TRACE_(d3d_caps)("[FAILED]\n");
1889 return WINED3DERR_NOTAVAILABLE;
1892 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1893 switch (CheckFormat) {
1894 case WINED3DFMT_V8U8:
1895 TRACE_(d3d_caps)("[OK]\n");
1896 return WINED3D_OK;
1897 default:
1898 TRACE_(d3d_caps)("[FAILED]\n");
1899 return WINED3DERR_NOTAVAILABLE;
1902 TRACE_(d3d_caps)("[FAILED]\n");
1903 return WINED3DERR_NOTAVAILABLE;
1906 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1907 if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
1908 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
1909 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
1912 switch (CheckFormat) {
1913 case WINED3DFMT_A8R8G8B8:
1914 case WINED3DFMT_X8R8G8B8:
1915 case WINED3DFMT_A4R4G4B4:
1916 case WINED3DFMT_L8:
1917 case WINED3DFMT_A8L8:
1918 case WINED3DFMT_DXT1:
1919 case WINED3DFMT_DXT2:
1920 case WINED3DFMT_DXT3:
1921 case WINED3DFMT_DXT4:
1922 case WINED3DFMT_DXT5:
1923 TRACE_(d3d_caps)("[OK]\n");
1924 break; /* Continue with checking other flags */
1926 default:
1927 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1928 return WINED3DERR_NOTAVAILABLE;
1932 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1934 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1936 switch (CheckFormat) {
1937 case WINED3DFMT_R16F:
1938 case WINED3DFMT_A16B16G16R16F:
1939 if (!half_pixel_support) break;
1940 case WINED3DFMT_R32F:
1941 case WINED3DFMT_A32B32G32R32F:
1942 TRACE_(d3d_caps)("[OK]\n");
1943 return WINED3D_OK;
1944 default:
1945 break; /* Avoid compiler warnings */
1949 /* This format is nothing special and it is supported perfectly.
1950 * However, ati and nvidia driver on windows do not mark this format as
1951 * supported (tested with the dxCapsViewer) and pretending to
1952 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1953 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1954 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1956 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1957 TRACE_(d3d_caps)("[FAILED]\n");
1958 return WINED3DERR_NOTAVAILABLE;
1961 switch (CheckFormat) {
1963 /*****
1964 * supported: RGB(A) formats
1966 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1967 case WINED3DFMT_A8R8G8B8:
1968 case WINED3DFMT_X8R8G8B8:
1969 case WINED3DFMT_R5G6B5:
1970 case WINED3DFMT_X1R5G5B5:
1971 case WINED3DFMT_A1R5G5B5:
1972 case WINED3DFMT_A4R4G4B4:
1973 case WINED3DFMT_R3G3B2:
1974 case WINED3DFMT_A8:
1975 case WINED3DFMT_X4R4G4B4:
1976 case WINED3DFMT_A8B8G8R8:
1977 case WINED3DFMT_X8B8G8R8:
1978 case WINED3DFMT_A2R10G10B10:
1979 case WINED3DFMT_A2B10G10R10:
1980 case WINED3DFMT_G16R16:
1981 TRACE_(d3d_caps)("[OK]\n");
1982 return WINED3D_OK;
1984 /*****
1985 * supported: Palettized
1987 case WINED3DFMT_P8:
1988 TRACE_(d3d_caps)("[OK]\n");
1989 return WINED3D_OK;
1991 /*****
1992 * Supported: (Alpha)-Luminance
1994 case WINED3DFMT_L8:
1995 case WINED3DFMT_A8L8:
1996 case WINED3DFMT_A4L4:
1997 TRACE_(d3d_caps)("[OK]\n");
1998 return WINED3D_OK;
2000 /*****
2001 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2002 * GL_NV_texture_shader), but advertized to make apps happy.
2003 * Enable some because games often fail when they are not available
2004 * and are still playable even without bump mapping
2006 case WINED3DFMT_V8U8:
2007 case WINED3DFMT_V16U16:
2008 case WINED3DFMT_L6V5U5:
2009 case WINED3DFMT_X8L8V8U8:
2010 case WINED3DFMT_Q8W8V8U8:
2011 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
2012 return WINED3D_OK;
2014 /* Those are not advertized by the nvidia windows driver, and not
2015 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2016 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2017 * ARGB format if needed
2019 case WINED3DFMT_W11V11U10:
2020 case WINED3DFMT_A2W10V10U10:
2021 WARN_(d3d_caps)("[FAILED]\n");
2022 return WINED3DERR_NOTAVAILABLE;
2024 case WINED3DFMT_DXT1:
2025 case WINED3DFMT_DXT2:
2026 case WINED3DFMT_DXT3:
2027 case WINED3DFMT_DXT4:
2028 case WINED3DFMT_DXT5:
2029 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2030 TRACE_(d3d_caps)("[OK]\n");
2031 return WINED3D_OK;
2032 } else {
2033 TRACE_(d3d_caps)("[FAILED]\n");
2034 return WINED3DERR_NOTAVAILABLE;
2038 /*****
2039 * Odd formats - not supported
2041 case WINED3DFMT_VERTEXDATA:
2042 case WINED3DFMT_INDEX16:
2043 case WINED3DFMT_INDEX32:
2044 case WINED3DFMT_Q16W16V16U16:
2045 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2046 return WINED3DERR_NOTAVAILABLE;
2048 /*****
2049 * Float formats: Not supported right now
2051 case WINED3DFMT_G16R16F:
2052 case WINED3DFMT_G32R32F:
2053 case WINED3DFMT_CxV8U8:
2054 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2055 return WINED3DERR_NOTAVAILABLE;
2057 /* Not supported */
2058 case WINED3DFMT_A16B16G16R16:
2059 case WINED3DFMT_A8R3G3B2:
2060 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2061 return WINED3DERR_NOTAVAILABLE;
2063 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2064 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2065 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2066 * We can do instancing with all shader versions, but we need vertex shaders.
2068 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2069 * to enable instancing. WineD3D doesn't need that and just ignores it.
2071 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2073 case WINEMAKEFOURCC('I','N','S','T'):
2074 TRACE("ATI Instancing check hack\n");
2075 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2076 TRACE_(d3d_caps)("[OK]\n");
2077 return WINED3D_OK;
2078 } else {
2079 TRACE_(d3d_caps)("[FAILED]\n");
2080 return WINED3DERR_NOTAVAILABLE;
2083 default:
2084 break;
2087 TRACE_(d3d_caps)("[FAILED]\n");
2088 return WINED3DERR_NOTAVAILABLE;
2091 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2092 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2093 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2095 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2096 This,
2097 Adapter,
2098 DeviceType, debug_d3ddevicetype(DeviceType),
2099 SourceFormat, debug_d3dformat(SourceFormat),
2100 TargetFormat, debug_d3dformat(TargetFormat));
2101 return WINED3D_OK;
2104 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2105 subset of a D3DCAPS9 structure. However, it has to come via a void *
2106 as the d3d8 interface cannot import the d3d9 header */
2107 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2109 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2110 int vs_selected_mode;
2111 int ps_selected_mode;
2113 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2115 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2116 return WINED3DERR_INVALIDCALL;
2119 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2121 /* This function should *not* be modifying GL caps
2122 * TODO: move the functionality where it belongs */
2123 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2125 /* ------------------------------------------------
2126 The following fields apply to both d3d8 and d3d9
2127 ------------------------------------------------ */
2128 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2129 *pCaps->AdapterOrdinal = Adapter;
2131 *pCaps->Caps = 0;
2132 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2133 WINED3DCAPS2_FULLSCREENGAMMA |
2134 WINED3DCAPS2_DYNAMICTEXTURES;
2135 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2136 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2138 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2139 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2140 WINED3DPRESENT_INTERVAL_ONE;
2142 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2143 WINED3DCURSORCAPS_LOWRES;
2145 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2146 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2147 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2148 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2149 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2150 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2151 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2152 WINED3DDEVCAPS_PUREDEVICE |
2153 WINED3DDEVCAPS_HWRASTERIZATION |
2154 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2155 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2156 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2157 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2158 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2159 WINED3DDEVCAPS_RTPATCHES;
2161 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2162 WINED3DPMISCCAPS_CULLCCW |
2163 WINED3DPMISCCAPS_CULLCW |
2164 WINED3DPMISCCAPS_COLORWRITEENABLE |
2165 WINED3DPMISCCAPS_CLIPTLVERTS |
2166 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2167 WINED3DPMISCCAPS_MASKZ |
2168 WINED3DPMISCCAPS_BLENDOP;
2169 /* TODO:
2170 WINED3DPMISCCAPS_NULLREFERENCE
2171 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2172 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2173 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2174 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2175 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2176 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2178 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2179 #if 0
2180 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2181 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2182 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2183 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2184 #endif
2186 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2187 WINED3DPRASTERCAPS_PAT |
2188 WINED3DPRASTERCAPS_WFOG |
2189 WINED3DPRASTERCAPS_ZFOG |
2190 WINED3DPRASTERCAPS_FOGVERTEX |
2191 WINED3DPRASTERCAPS_FOGTABLE |
2192 WINED3DPRASTERCAPS_STIPPLE |
2193 WINED3DPRASTERCAPS_SUBPIXEL |
2194 WINED3DPRASTERCAPS_ZTEST |
2195 WINED3DPRASTERCAPS_SCISSORTEST |
2196 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2197 WINED3DPRASTERCAPS_DEPTHBIAS;
2199 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2200 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2201 WINED3DPRASTERCAPS_ZBIAS |
2202 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2204 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2205 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2207 /* FIXME Add:
2208 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2209 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2210 WINED3DPRASTERCAPS_ANTIALIASEDGES
2211 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2212 WINED3DPRASTERCAPS_WBUFFER */
2214 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2215 WINED3DPCMPCAPS_EQUAL |
2216 WINED3DPCMPCAPS_GREATER |
2217 WINED3DPCMPCAPS_GREATEREQUAL |
2218 WINED3DPCMPCAPS_LESS |
2219 WINED3DPCMPCAPS_LESSEQUAL |
2220 WINED3DPCMPCAPS_NEVER |
2221 WINED3DPCMPCAPS_NOTEQUAL;
2223 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2224 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2225 WINED3DPBLENDCAPS_DESTALPHA |
2226 WINED3DPBLENDCAPS_DESTCOLOR |
2227 WINED3DPBLENDCAPS_INVDESTALPHA |
2228 WINED3DPBLENDCAPS_INVDESTCOLOR |
2229 WINED3DPBLENDCAPS_INVSRCALPHA |
2230 WINED3DPBLENDCAPS_INVSRCCOLOR |
2231 WINED3DPBLENDCAPS_ONE |
2232 WINED3DPBLENDCAPS_SRCALPHA |
2233 WINED3DPBLENDCAPS_SRCALPHASAT |
2234 WINED3DPBLENDCAPS_SRCCOLOR |
2235 WINED3DPBLENDCAPS_ZERO;
2237 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
2238 WINED3DPBLENDCAPS_DESTCOLOR |
2239 WINED3DPBLENDCAPS_INVDESTALPHA |
2240 WINED3DPBLENDCAPS_INVDESTCOLOR |
2241 WINED3DPBLENDCAPS_INVSRCALPHA |
2242 WINED3DPBLENDCAPS_INVSRCCOLOR |
2243 WINED3DPBLENDCAPS_ONE |
2244 WINED3DPBLENDCAPS_SRCALPHA |
2245 WINED3DPBLENDCAPS_SRCCOLOR |
2246 WINED3DPBLENDCAPS_ZERO;
2247 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2248 * according to the glBlendFunc manpage
2250 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2251 * legacy settings for srcblend only
2254 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
2255 *pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2256 *pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2260 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2261 WINED3DPCMPCAPS_EQUAL |
2262 WINED3DPCMPCAPS_GREATER |
2263 WINED3DPCMPCAPS_GREATEREQUAL |
2264 WINED3DPCMPCAPS_LESS |
2265 WINED3DPCMPCAPS_LESSEQUAL |
2266 WINED3DPCMPCAPS_NEVER |
2267 WINED3DPCMPCAPS_NOTEQUAL;
2269 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2270 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2271 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2272 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2273 WINED3DPSHADECAPS_COLORFLATRGB |
2274 WINED3DPSHADECAPS_FOGFLAT |
2275 WINED3DPSHADECAPS_FOGGOURAUD |
2276 WINED3DPSHADECAPS_SPECULARFLATRGB;
2278 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2279 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2280 WINED3DPTEXTURECAPS_BORDER |
2281 WINED3DPTEXTURECAPS_MIPMAP |
2282 WINED3DPTEXTURECAPS_PROJECTED |
2283 WINED3DPTEXTURECAPS_PERSPECTIVE;
2285 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2286 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2287 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2290 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2291 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2292 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2293 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2296 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2297 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2298 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2299 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2303 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2304 WINED3DPTFILTERCAPS_MAGFPOINT |
2305 WINED3DPTFILTERCAPS_MINFLINEAR |
2306 WINED3DPTFILTERCAPS_MINFPOINT |
2307 WINED3DPTFILTERCAPS_MIPFLINEAR |
2308 WINED3DPTFILTERCAPS_MIPFPOINT |
2309 WINED3DPTFILTERCAPS_LINEAR |
2310 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2311 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2312 WINED3DPTFILTERCAPS_MIPLINEAR |
2313 WINED3DPTFILTERCAPS_MIPNEAREST |
2314 WINED3DPTFILTERCAPS_NEAREST;
2316 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2317 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2318 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2321 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2322 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2323 WINED3DPTFILTERCAPS_MAGFPOINT |
2324 WINED3DPTFILTERCAPS_MINFLINEAR |
2325 WINED3DPTFILTERCAPS_MINFPOINT |
2326 WINED3DPTFILTERCAPS_MIPFLINEAR |
2327 WINED3DPTFILTERCAPS_MIPFPOINT |
2328 WINED3DPTFILTERCAPS_LINEAR |
2329 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2330 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2331 WINED3DPTFILTERCAPS_MIPLINEAR |
2332 WINED3DPTFILTERCAPS_MIPNEAREST |
2333 WINED3DPTFILTERCAPS_NEAREST;
2335 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2336 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2337 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2339 } else
2340 *pCaps->CubeTextureFilterCaps = 0;
2342 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2343 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2344 WINED3DPTFILTERCAPS_MAGFPOINT |
2345 WINED3DPTFILTERCAPS_MINFLINEAR |
2346 WINED3DPTFILTERCAPS_MINFPOINT |
2347 WINED3DPTFILTERCAPS_MIPFLINEAR |
2348 WINED3DPTFILTERCAPS_MIPFPOINT |
2349 WINED3DPTFILTERCAPS_LINEAR |
2350 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2351 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2352 WINED3DPTFILTERCAPS_MIPLINEAR |
2353 WINED3DPTFILTERCAPS_MIPNEAREST |
2354 WINED3DPTFILTERCAPS_NEAREST;
2355 } else
2356 *pCaps->VolumeTextureFilterCaps = 0;
2358 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2359 WINED3DPTADDRESSCAPS_CLAMP |
2360 WINED3DPTADDRESSCAPS_WRAP;
2362 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2363 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2365 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2366 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2368 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2369 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2372 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2373 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2374 WINED3DPTADDRESSCAPS_CLAMP |
2375 WINED3DPTADDRESSCAPS_WRAP;
2376 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2377 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2379 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2380 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2382 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2383 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2385 } else
2386 *pCaps->VolumeTextureAddressCaps = 0;
2388 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2389 WINED3DLINECAPS_ZTEST;
2390 /* FIXME: Add
2391 WINED3DLINECAPS_BLEND
2392 WINED3DLINECAPS_ALPHACMP
2393 WINED3DLINECAPS_FOG */
2395 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2396 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2398 if(GL_SUPPORT(EXT_TEXTURE3D))
2399 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2400 else
2401 *pCaps->MaxVolumeExtent = 0;
2403 *pCaps->MaxTextureRepeat = 32768;
2404 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2405 *pCaps->MaxVertexW = 1.0;
2407 *pCaps->GuardBandLeft = 0;
2408 *pCaps->GuardBandTop = 0;
2409 *pCaps->GuardBandRight = 0;
2410 *pCaps->GuardBandBottom = 0;
2412 *pCaps->ExtentsAdjust = 0;
2414 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2415 WINED3DSTENCILCAPS_INCRSAT |
2416 WINED3DSTENCILCAPS_INVERT |
2417 WINED3DSTENCILCAPS_KEEP |
2418 WINED3DSTENCILCAPS_REPLACE |
2419 WINED3DSTENCILCAPS_ZERO;
2420 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2421 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2422 WINED3DSTENCILCAPS_INCR;
2424 if ( This->dxVersion > 8 &&
2425 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2426 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2427 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2430 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2432 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2433 WINED3DTEXOPCAPS_ADDSIGNED |
2434 WINED3DTEXOPCAPS_ADDSIGNED2X |
2435 WINED3DTEXOPCAPS_MODULATE |
2436 WINED3DTEXOPCAPS_MODULATE2X |
2437 WINED3DTEXOPCAPS_MODULATE4X |
2438 WINED3DTEXOPCAPS_SELECTARG1 |
2439 WINED3DTEXOPCAPS_SELECTARG2 |
2440 WINED3DTEXOPCAPS_DISABLE;
2442 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2443 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2444 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2445 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2446 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2447 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2448 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2449 WINED3DTEXOPCAPS_LERP |
2450 WINED3DTEXOPCAPS_SUBTRACT;
2452 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2453 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2454 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2455 WINED3DTEXOPCAPS_MULTIPLYADD |
2456 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2457 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2458 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2460 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2461 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2463 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2464 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2465 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2468 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2469 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2470 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2471 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2472 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2473 * and 3D textures. It also allows us to keep the code simpler by having texture
2474 * shaders constantly enabled.
2476 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2477 /* TODO: Luminance bump map? */
2479 #if 0
2480 /* FIXME: Add
2481 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2482 WINED3DTEXOPCAPS_PREMODULATE */
2483 #endif
2485 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2486 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2487 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2488 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2490 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2491 *pCaps->MaxVertexBlendMatrixIndex = 0;
2493 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2494 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2497 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2498 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2499 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2500 WINED3DVTXPCAPS_LOCALVIEWER |
2501 WINED3DVTXPCAPS_VERTEXFOG |
2502 WINED3DVTXPCAPS_TEXGEN;
2503 /* FIXME: Add
2504 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2506 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2507 *pCaps->MaxVertexIndex = 0xFFFFF;
2508 *pCaps->MaxStreams = MAX_STREAMS;
2509 *pCaps->MaxStreamStride = 1024;
2511 if (vs_selected_mode == SHADER_GLSL) {
2512 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2513 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2514 * vs_nv_version which is based on NV_vertex_program.
2515 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2516 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2517 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2518 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2519 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2520 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2521 else
2522 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2523 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2524 } else if (vs_selected_mode == SHADER_ARB) {
2525 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2526 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2527 } else {
2528 *pCaps->VertexShaderVersion = 0;
2529 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2532 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2534 if (ps_selected_mode == SHADER_GLSL) {
2535 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2536 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2537 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2538 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2539 * in max native instructions. Intel and others also offer the info in this extension but they
2540 * don't support GLSL (at least on Windows).
2542 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number
2543 * of instructions is 512 or less we have to do with ps2.0 hardware.
2544 * 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.
2546 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2547 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2548 else
2549 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2550 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2551 * Direct3D minimum requirement.
2553 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2554 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2556 * The problem is that the refrast clamps temporary results in the shader to
2557 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2558 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2559 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2560 * offer a way to query this.
2562 *pCaps->PixelShader1xMaxValue = 8.0;
2563 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2564 } else if (ps_selected_mode == SHADER_ARB) {
2565 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2566 *pCaps->PixelShader1xMaxValue = 8.0;
2567 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2568 } else {
2569 *pCaps->PixelShaderVersion = 0;
2570 *pCaps->PixelShader1xMaxValue = 0.0;
2571 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2574 /* ------------------------------------------------
2575 The following fields apply to d3d9 only
2576 ------------------------------------------------ */
2577 if (This->dxVersion > 8) {
2578 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2579 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2580 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2581 *pCaps->MaxNpatchTessellationLevel = 0;
2582 *pCaps->MasterAdapterOrdinal = 0;
2583 *pCaps->AdapterOrdinalInGroup = 0;
2584 *pCaps->NumberOfAdaptersInGroup = 1;
2586 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2587 /* OpenGL supports all the formats below, perhaps not always
2588 * without conversion, but it supports them.
2589 * Further GLSL doesn't seem to have an official unsigned type so
2590 * don't advertise it yet as I'm not sure how we handle it.
2591 * We might need to add some clamping in the shader engine to
2592 * support it.
2593 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2594 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2595 WINED3DDTCAPS_UBYTE4N |
2596 WINED3DDTCAPS_SHORT2N |
2597 WINED3DDTCAPS_SHORT4N;
2598 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2599 *pCaps->DeclTypes |=
2600 WINED3DDTCAPS_FLOAT16_2 |
2601 WINED3DDTCAPS_FLOAT16_4;
2603 } else
2604 *pCaps->DeclTypes = 0;
2606 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2609 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2610 WINED3DPTFILTERCAPS_MAGFPOINT |
2611 WINED3DPTFILTERCAPS_MINFLINEAR |
2612 WINED3DPTFILTERCAPS_MAGFLINEAR;
2613 *pCaps->VertexTextureFilterCaps = 0;
2615 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2616 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2617 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2618 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2619 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2620 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2621 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2623 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2624 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2625 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2626 *pCaps->VS20Caps.Caps = 0;
2627 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2628 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2629 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2631 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2632 *pCaps->MaxVertexShader30InstructionSlots = 0;
2633 } else { /* VS 1.x */
2634 *pCaps->VS20Caps.Caps = 0;
2635 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2636 *pCaps->VS20Caps.NumTemps = 0;
2637 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2639 *pCaps->MaxVShaderInstructionsExecuted = 0;
2640 *pCaps->MaxVertexShader30InstructionSlots = 0;
2643 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2644 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2645 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2647 /* 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 */
2648 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2649 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2650 WINED3DPS20CAPS_PREDICATION |
2651 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2652 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2653 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2654 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2655 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2656 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2658 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2659 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2660 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2661 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2662 *pCaps->PS20Caps.Caps = 0;
2663 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2664 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2665 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
2666 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2668 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2669 *pCaps->MaxPixelShader30InstructionSlots = 0;
2670 } else { /* PS 1.x */
2671 *pCaps->PS20Caps.Caps = 0;
2672 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2673 *pCaps->PS20Caps.NumTemps = 0;
2674 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2675 *pCaps->PS20Caps.NumInstructionSlots = 0;
2677 *pCaps->MaxPShaderInstructionsExecuted = 0;
2678 *pCaps->MaxPixelShader30InstructionSlots = 0;
2682 return WINED3D_OK;
2685 static unsigned int glsl_program_key_hash(void *key) {
2686 glsl_program_key_t *k = (glsl_program_key_t *)key;
2688 unsigned int hash = k->vshader | k->pshader << 16;
2689 hash += ~(hash << 15);
2690 hash ^= (hash >> 10);
2691 hash += (hash << 3);
2692 hash ^= (hash >> 6);
2693 hash += ~(hash << 11);
2694 hash ^= (hash >> 16);
2696 return hash;
2699 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2700 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2701 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2703 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2706 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2707 and fields being inserted in the middle, a new structure is used in place */
2708 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2709 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2710 IUnknown *parent) {
2712 IWineD3DDeviceImpl *object = NULL;
2713 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2714 WINED3DDISPLAYMODE mode;
2715 int i;
2717 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2718 * number and create a device without a 3D adapter for 2D only operation.
2720 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2721 return WINED3DERR_INVALIDCALL;
2724 /* Create a WineD3DDevice object */
2725 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2726 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2727 TRACE("Created WineD3DDevice object @ %p\n", object);
2728 if (NULL == object) {
2729 return WINED3DERR_OUTOFVIDEOMEMORY;
2732 /* Set up initial COM information */
2733 object->lpVtbl = &IWineD3DDevice_Vtbl;
2734 object->ref = 1;
2735 object->wineD3D = iface;
2736 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2737 IWineD3D_AddRef(object->wineD3D);
2738 object->parent = parent;
2739 list_init(&object->resources);
2740 list_init(&object->shaders);
2742 if(This->dxVersion == 7) {
2743 object->surface_alignment = 8;
2744 } else {
2745 object->surface_alignment = 4;
2747 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2749 /* Set the state up as invalid until the device is fully created */
2750 object->state = WINED3DERR_DRIVERINTERNALERROR;
2752 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2753 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2755 /* Save the creation parameters */
2756 object->createParms.AdapterOrdinal = Adapter;
2757 object->createParms.DeviceType = DeviceType;
2758 object->createParms.hFocusWindow = hFocusWindow;
2759 object->createParms.BehaviorFlags = BehaviourFlags;
2761 /* Initialize other useful values */
2762 object->adapterNo = Adapter;
2763 object->devType = DeviceType;
2765 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2766 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2767 object->shader_backend = &glsl_shader_backend;
2768 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2769 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2770 object->shader_backend = &arb_program_shader_backend;
2771 } else {
2772 object->shader_backend = &none_shader_backend;
2775 /* set the state of the device to valid */
2776 object->state = WINED3D_OK;
2778 /* Get the initial screen setup for ddraw */
2779 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
2781 object->ddraw_width = mode.Width;
2782 object->ddraw_height = mode.Height;
2783 object->ddraw_format = mode.Format;
2785 for(i = 0; i < PATCHMAP_SIZE; i++) {
2786 list_init(&object->patches[i]);
2788 return WINED3D_OK;
2790 #undef GLINFO_LOCATION
2792 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2793 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2794 IUnknown_AddRef(This->parent);
2795 *pParent = This->parent;
2796 return WINED3D_OK;
2799 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2800 IUnknown* surfaceParent;
2801 TRACE("(%p) call back\n", pSurface);
2803 /* Now, release the parent, which will take care of cleaning up the surface for us */
2804 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2805 IUnknown_Release(surfaceParent);
2806 return IUnknown_Release(surfaceParent);
2809 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2810 IUnknown* volumeParent;
2811 TRACE("(%p) call back\n", pVolume);
2813 /* Now, release the parent, which will take care of cleaning up the volume for us */
2814 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2815 IUnknown_Release(volumeParent);
2816 return IUnknown_Release(volumeParent);
2819 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2820 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2821 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2822 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2824 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2825 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2826 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2827 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2828 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
2829 * the chance that other implementations support them is rather small since Win32 QuickTime uses
2830 * DirectDraw, not OpenGL.
2832 if(gl_info->supported[APPLE_FENCE] &&
2833 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2834 gl_info->supported[APPLE_FLUSH_RENDER] &&
2835 gl_info->supported[APPLE_YCBCR_422]) {
2836 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2837 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2838 return TRUE;
2839 } else {
2840 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2841 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2842 return FALSE;
2846 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2847 if(implementation_is_apple(gl_info)) {
2848 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
2849 * used it falls back to software. While the compiler can detect if the shader uses all declared
2850 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2851 * using relative addressing falls back to software.
2853 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2855 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2856 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2857 } else {
2858 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2859 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2860 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2863 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2864 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2865 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2866 * flag for this extension
2868 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2869 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2870 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2871 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2872 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2873 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2874 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2878 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
2879 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
2880 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
2881 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
2882 * according to the spec.
2884 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
2885 * makes the shader slower and eats instruction slots which should be available to the d3d app.
2887 if(gl_info->gl_vendor == VENDOR_INTEL) {
2888 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
2889 gl_info->set_texcoord_w = TRUE;
2894 void invalid_func(void *data) {
2895 ERR("Invalid vertex attribute function called\n");
2896 DebugBreak();
2899 #define GLINFO_LOCATION (Adapters[0].gl_info)
2901 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
2902 * the extension detection and are used in drawStridedSlow
2904 static void position_d3dcolor(void *data) {
2905 DWORD pos = *((DWORD *) data);
2907 FIXME("Add a test for fixed function position from d3dcolor type\n");
2908 glVertex4s(D3DCOLOR_B_R(pos),
2909 D3DCOLOR_B_G(pos),
2910 D3DCOLOR_B_B(pos),
2911 D3DCOLOR_B_A(pos));
2913 static void position_float4(void *data) {
2914 GLfloat *pos = (float *) data;
2916 if (pos[3] < eps && pos[3] > -eps)
2917 glVertex3fv(pos);
2918 else {
2919 float w = 1.0 / pos[3];
2921 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
2925 static void diffuse_d3dcolor(void *data) {
2926 DWORD diffuseColor = *((DWORD *) data);
2928 glColor4ub(D3DCOLOR_B_R(diffuseColor),
2929 D3DCOLOR_B_G(diffuseColor),
2930 D3DCOLOR_B_B(diffuseColor),
2931 D3DCOLOR_B_A(diffuseColor));
2934 static void specular_d3dcolor(void *data) {
2935 DWORD specularColor = *((DWORD *) data);
2937 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
2938 D3DCOLOR_B_G(specularColor),
2939 D3DCOLOR_B_B(specularColor));
2941 static void warn_no_specular_func(void *data) {
2942 WARN("GL_EXT_secondary_color not supported\n");
2945 void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
2946 position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2947 position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2948 position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv;
2949 position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4;
2950 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor;
2951 position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2952 position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2953 position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv;
2954 position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
2955 position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2956 position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
2957 position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2958 position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
2959 position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2960 position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2961 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2962 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2964 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2965 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2966 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv;
2967 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv;
2968 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor;
2969 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2970 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2971 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
2972 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv;
2973 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2974 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv;
2975 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2976 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv;
2977 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2978 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2979 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2980 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2982 /* No 4 component entry points here */
2983 specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2984 specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2985 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2986 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT);
2987 } else {
2988 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
2990 specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func;
2991 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2992 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor;
2993 } else {
2994 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
2996 specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2997 specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2998 specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
2999 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3000 specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3001 specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3002 specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3003 specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3004 specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3005 specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3006 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3007 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3009 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
3010 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
3012 normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3013 normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3014 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv;
3015 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */
3016 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func;
3017 normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3018 normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3019 normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3020 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3021 normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3022 normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3023 normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3024 normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3025 normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3026 normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3027 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3028 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3031 #define PUSH1(att) attribs[nAttribs++] = (att);
3032 BOOL InitAdapters(void) {
3033 static HMODULE mod_gl;
3034 BOOL ret;
3035 int ps_selected_mode, vs_selected_mode;
3037 /* No need to hold any lock. The calling library makes sure only one thread calls
3038 * wined3d simultaneously
3040 if(numAdapters > 0) return TRUE;
3042 TRACE("Initializing adapters\n");
3044 if(!mod_gl) {
3045 #ifdef USE_WIN32_OPENGL
3046 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
3047 mod_gl = LoadLibraryA("opengl32.dll");
3048 if(!mod_gl) {
3049 ERR("Can't load opengl32.dll!\n");
3050 return FALSE;
3052 #else
3053 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
3054 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
3055 mod_gl = GetModuleHandleA("gdi32.dll");
3056 #endif
3059 /* Load WGL core functions from opengl32.dll */
3060 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
3061 WGL_FUNCS_GEN;
3062 #undef USE_WGL_FUNC
3064 if(!pwglGetProcAddress) {
3065 ERR("Unable to load wglGetProcAddress!\n");
3066 return FALSE;
3069 /* Dynamically load all GL core functions */
3070 GL_FUNCS_GEN;
3071 #undef USE_GL_FUNC
3073 /* For now only one default adapter */
3075 int iPixelFormat;
3076 int attribs[8];
3077 int values[8];
3078 int nAttribs = 0;
3079 int res;
3080 WineD3D_PixelFormat *cfgs;
3081 int attribute;
3082 DISPLAY_DEVICEW DisplayDevice;
3083 HDC hdc;
3085 TRACE("Initializing default adapter\n");
3086 Adapters[0].num = 0;
3087 Adapters[0].monitorPoint.x = -1;
3088 Adapters[0].monitorPoint.y = -1;
3090 if (!WineD3D_CreateFakeGLContext()) {
3091 ERR("Failed to get a gl context for default adapter\n");
3092 HeapFree(GetProcessHeap(), 0, Adapters);
3093 WineD3D_ReleaseFakeGLContext();
3094 return FALSE;
3097 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
3098 if(!ret) {
3099 ERR("Failed to initialize gl caps for default adapter\n");
3100 HeapFree(GetProcessHeap(), 0, Adapters);
3101 WineD3D_ReleaseFakeGLContext();
3102 return FALSE;
3104 ret = initPixelFormats(&Adapters[0].gl_info);
3105 if(!ret) {
3106 ERR("Failed to init gl formats\n");
3107 HeapFree(GetProcessHeap(), 0, Adapters);
3108 WineD3D_ReleaseFakeGLContext();
3109 return FALSE;
3112 hdc = pwglGetCurrentDC();
3113 if(!hdc) {
3114 ERR("Failed to get gl HDC\n");
3115 HeapFree(GetProcessHeap(), 0, Adapters);
3116 WineD3D_ReleaseFakeGLContext();
3117 return FALSE;
3120 Adapters[0].driver = "Display";
3121 Adapters[0].description = "Direct3D HAL";
3123 /* Use the VideoRamSize registry setting when set */
3124 if(wined3d_settings.emulated_textureram)
3125 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
3126 else
3127 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
3128 Adapters[0].UsedTextureRam = 0;
3129 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
3131 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
3132 DisplayDevice.cb = sizeof(DisplayDevice);
3133 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
3134 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
3135 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
3137 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
3138 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
3140 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
3141 cfgs = Adapters[0].cfgs;
3142 PUSH1(WGL_RED_BITS_ARB)
3143 PUSH1(WGL_GREEN_BITS_ARB)
3144 PUSH1(WGL_BLUE_BITS_ARB)
3145 PUSH1(WGL_ALPHA_BITS_ARB)
3146 PUSH1(WGL_DEPTH_BITS_ARB)
3147 PUSH1(WGL_STENCIL_BITS_ARB)
3149 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
3150 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
3152 if(!res)
3153 continue;
3155 /* Cache the pixel format */
3156 cfgs->iPixelFormat = iPixelFormat;
3157 cfgs->redSize = values[0];
3158 cfgs->greenSize = values[1];
3159 cfgs->blueSize = values[2];
3160 cfgs->alphaSize = values[3];
3161 cfgs->depthSize = values[4];
3162 cfgs->stencilSize = values[5];
3164 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);
3165 cfgs++;
3167 WineD3D_ReleaseFakeGLContext();
3169 fixup_extensions(&Adapters[0].gl_info);
3171 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
3172 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3173 fillGLAttribFuncs(&Adapters[0].gl_info);
3174 init_type_lookup(&Adapters[0].gl_info);
3176 numAdapters = 1;
3177 TRACE("%d adapters successfully initialized\n", numAdapters);
3179 return TRUE;
3181 #undef PUSH1
3182 #undef GLINFO_LOCATION
3184 /**********************************************************
3185 * IWineD3D VTbl follows
3186 **********************************************************/
3188 const IWineD3DVtbl IWineD3D_Vtbl =
3190 /* IUnknown */
3191 IWineD3DImpl_QueryInterface,
3192 IWineD3DImpl_AddRef,
3193 IWineD3DImpl_Release,
3194 /* IWineD3D */
3195 IWineD3DImpl_GetParent,
3196 IWineD3DImpl_GetAdapterCount,
3197 IWineD3DImpl_RegisterSoftwareDevice,
3198 IWineD3DImpl_GetAdapterMonitor,
3199 IWineD3DImpl_GetAdapterModeCount,
3200 IWineD3DImpl_EnumAdapterModes,
3201 IWineD3DImpl_GetAdapterDisplayMode,
3202 IWineD3DImpl_GetAdapterIdentifier,
3203 IWineD3DImpl_CheckDeviceMultiSampleType,
3204 IWineD3DImpl_CheckDepthStencilMatch,
3205 IWineD3DImpl_CheckDeviceType,
3206 IWineD3DImpl_CheckDeviceFormat,
3207 IWineD3DImpl_CheckDeviceFormatConversion,
3208 IWineD3DImpl_GetDeviceCaps,
3209 IWineD3DImpl_CreateDevice