push 2cb3c55a66a85d63efe36907fa6cad8804808438
[wine/hacks.git] / dlls / wined3d / directx.c
blob9536b7165729f1b99746c8245dc8796f3cf3aaf6
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_minmax", EXT_BLEND_MINMAX, 0 },
87 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
88 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
89 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
90 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
91 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
92 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
93 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
94 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
95 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
96 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
97 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
98 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
99 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
100 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
101 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
102 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
103 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
104 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
105 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
107 /* NV */
108 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
109 {"GL_NV_fence", NV_FENCE, 0 },
110 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
111 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
112 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
113 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
114 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
115 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
116 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
117 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
118 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
119 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
120 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
121 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
122 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
123 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
124 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
125 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
127 /* SGI */
128 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
131 /**********************************************************
132 * Utility functions follow
133 **********************************************************/
135 /* Adapters */
136 static int numAdapters = 0;
137 static struct WineD3DAdapter Adapters[1];
139 /* lookup tables */
140 int minLookup[MAX_LOOKUPS];
141 int maxLookup[MAX_LOOKUPS];
142 DWORD *stateLookup[MAX_LOOKUPS];
144 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
146 /* drawStridedSlow attributes */
147 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
148 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
149 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
150 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
151 glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
154 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
155 * ie there is no GL Context - Get a default rendering context to enable the
156 * function query some info from GL
159 static int wined3d_fake_gl_context_ref = 0;
160 static BOOL wined3d_fake_gl_context_foreign;
161 static BOOL wined3d_fake_gl_context_available = FALSE;
162 static HDC wined3d_fake_gl_context_hdc = NULL;
163 static HWND wined3d_fake_gl_context_hwnd = NULL;
165 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
166 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
168 0, 0, &wined3d_fake_gl_context_cs,
169 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
170 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
171 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
173 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
175 static void WineD3D_ReleaseFakeGLContext(void) {
176 HGLRC glCtx;
178 EnterCriticalSection(&wined3d_fake_gl_context_cs);
180 if(!wined3d_fake_gl_context_available) {
181 TRACE_(d3d_caps)("context not available\n");
182 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
183 return;
186 glCtx = pwglGetCurrentContext();
188 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
189 if (0 == (--wined3d_fake_gl_context_ref) ) {
190 if(!wined3d_fake_gl_context_foreign && glCtx) {
191 TRACE_(d3d_caps)("destroying fake GL context\n");
192 pwglMakeCurrent(NULL, NULL);
193 pwglDeleteContext(glCtx);
195 if(wined3d_fake_gl_context_hdc)
196 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
197 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
198 if(wined3d_fake_gl_context_hwnd)
199 DestroyWindow(wined3d_fake_gl_context_hwnd);
200 wined3d_fake_gl_context_hwnd = NULL;
201 wined3d_fake_gl_context_available = FALSE;
203 assert(wined3d_fake_gl_context_ref >= 0);
205 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
208 static BOOL WineD3D_CreateFakeGLContext(void) {
209 HGLRC glCtx = NULL;
211 EnterCriticalSection(&wined3d_fake_gl_context_cs);
213 TRACE("getting context...\n");
214 if(wined3d_fake_gl_context_ref > 0) goto ret;
215 assert(0 == wined3d_fake_gl_context_ref);
217 wined3d_fake_gl_context_foreign = TRUE;
219 glCtx = pwglGetCurrentContext();
220 if (!glCtx) {
221 PIXELFORMATDESCRIPTOR pfd;
222 int iPixelFormat;
224 wined3d_fake_gl_context_foreign = FALSE;
226 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
227 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
228 if(!wined3d_fake_gl_context_hwnd) {
229 ERR("HWND creation failed!\n");
230 goto fail;
232 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
233 if(!wined3d_fake_gl_context_hdc) {
234 ERR("GetDC failed!\n");
235 goto fail;
238 /* PixelFormat selection */
239 ZeroMemory(&pfd, sizeof(pfd));
240 pfd.nSize = sizeof(pfd);
241 pfd.nVersion = 1;
242 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
243 pfd.iPixelType = PFD_TYPE_RGBA;
244 pfd.cColorBits = 32;
245 pfd.iLayerType = PFD_MAIN_PLANE;
247 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
248 if(!iPixelFormat) {
249 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
250 ERR("Can't find a suitable iPixelFormat\n");
251 goto fail;
253 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
254 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
256 /* Create a GL context */
257 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
258 if (!glCtx) {
259 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
260 goto fail;
263 /* Make it the current GL context */
264 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
265 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
266 goto fail;
270 ret:
271 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
272 wined3d_fake_gl_context_ref++;
273 wined3d_fake_gl_context_available = TRUE;
274 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
275 return TRUE;
276 fail:
277 if(wined3d_fake_gl_context_hdc)
278 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
279 wined3d_fake_gl_context_hdc = NULL;
280 if(wined3d_fake_gl_context_hwnd)
281 DestroyWindow(wined3d_fake_gl_context_hwnd);
282 wined3d_fake_gl_context_hwnd = NULL;
283 if(glCtx) pwglDeleteContext(glCtx);
284 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
285 return FALSE;
288 /* Adjust the amount of used texture memory */
289 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
290 UINT Adapter = D3DDevice->adapterNo;
292 Adapters[Adapter].UsedTextureRam += glram;
293 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
294 return Adapters[Adapter].UsedTextureRam;
297 /**********************************************************
298 * IUnknown parts follows
299 **********************************************************/
301 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
303 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
305 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
306 if (IsEqualGUID(riid, &IID_IUnknown)
307 || IsEqualGUID(riid, &IID_IWineD3DBase)
308 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
309 IUnknown_AddRef(iface);
310 *ppobj = This;
311 return S_OK;
313 *ppobj = NULL;
314 return E_NOINTERFACE;
317 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
318 IWineD3DImpl *This = (IWineD3DImpl *)iface;
319 ULONG refCount = InterlockedIncrement(&This->ref);
321 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
322 return refCount;
325 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
326 IWineD3DImpl *This = (IWineD3DImpl *)iface;
327 ULONG ref;
328 TRACE("(%p) : Releasing from %d\n", This, This->ref);
329 ref = InterlockedDecrement(&This->ref);
330 if (ref == 0) {
331 HeapFree(GetProcessHeap(), 0, This);
334 return ref;
337 /* Set the shader type for this device, depending on the given capabilities,
338 * the device type, and the user preferences in wined3d_settings */
340 static void select_shader_mode(
341 WineD3D_GL_Info *gl_info,
342 WINED3DDEVTYPE DeviceType,
343 int* ps_selected,
344 int* vs_selected) {
346 if (wined3d_settings.vs_mode == VS_NONE) {
347 *vs_selected = SHADER_NONE;
348 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
349 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
350 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
351 * shaders only on this card. */
352 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
353 *vs_selected = SHADER_ARB;
354 else
355 *vs_selected = SHADER_GLSL;
356 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
357 *vs_selected = SHADER_ARB;
358 } else {
359 *vs_selected = SHADER_NONE;
362 if (wined3d_settings.ps_mode == PS_NONE) {
363 *ps_selected = SHADER_NONE;
364 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
365 *ps_selected = SHADER_GLSL;
366 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
367 *ps_selected = SHADER_ARB;
368 } else {
369 *ps_selected = SHADER_NONE;
373 /** Select the number of report maximum shader constants based on the selected shader modes */
374 static void select_shader_max_constants(
375 int ps_selected_mode,
376 int vs_selected_mode,
377 WineD3D_GL_Info *gl_info) {
379 switch (vs_selected_mode) {
380 case SHADER_GLSL:
381 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
382 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
383 break;
384 case SHADER_ARB:
385 /* We have to subtract any other PARAMs that we might use in our shader programs.
386 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
387 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
388 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
389 break;
390 default:
391 gl_info->max_vshader_constantsF = 0;
392 break;
395 switch (ps_selected_mode) {
396 case SHADER_GLSL:
397 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
398 * In theory the texbem instruction may need one more shader constant too. But lets assume
399 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
400 * and lets not take away a uniform needlessly from all other shaders.
402 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
403 break;
404 case SHADER_ARB:
405 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
406 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
408 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
409 break;
410 default:
411 gl_info->max_pshader_constantsF = 0;
412 break;
416 /**********************************************************
417 * IWineD3D parts follows
418 **********************************************************/
420 #define GLINFO_LOCATION (*gl_info)
421 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
422 GLuint prog;
423 BOOL ret = FALSE;
424 const char *testcode =
425 "!!ARBvp1.0\n"
426 "PARAM C[66] = { program.env[0..65] };\n"
427 "ADDRESS A0;"
428 "ARL A0.x, 0.0;\n"
429 "MOV result.position, C[A0.x + 65];\n"
430 "END\n";
432 while(glGetError());
433 GL_EXTCALL(glGenProgramsARB(1, &prog));
434 if(!prog) {
435 ERR("Failed to create an ARB offset limit test program\n");
437 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
438 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
439 strlen(testcode), testcode));
440 if(glGetError() != 0) {
441 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
442 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
443 ret = TRUE;
444 } else TRACE("OpenGL implementation allows offsets > 63\n");
446 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
447 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
448 checkGLcall("ARB vp offset limit test cleanup\n");
450 return ret;
453 static DWORD ver_for_ext(GL_SupportedExt ext)
455 unsigned int i;
456 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
457 if(EXTENSION_MAP[i].extension == ext) {
458 return EXTENSION_MAP[i].version;
461 return 0;
464 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
465 const char *GL_Extensions = NULL;
466 const char *WGL_Extensions = NULL;
467 const char *gl_string = NULL;
468 const char *gl_string_cursor = NULL;
469 GLint gl_max;
470 GLfloat gl_floatv[2];
471 int major = 1, minor = 0;
472 BOOL return_value = TRUE;
473 unsigned i;
474 HDC hdc;
475 unsigned int vidmem=0;
477 TRACE_(d3d_caps)("(%p)\n", gl_info);
479 ENTER_GL();
481 gl_string = (const char *) glGetString(GL_RENDERER);
482 if (NULL == gl_string)
483 gl_string = "None";
484 strcpy(gl_info->gl_renderer, gl_string);
486 gl_string = (const char *) glGetString(GL_VENDOR);
487 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
488 if (gl_string != NULL) {
489 /* Fill in the GL vendor */
490 if (strstr(gl_string, "NVIDIA")) {
491 gl_info->gl_vendor = VENDOR_NVIDIA;
492 } else if (strstr(gl_string, "ATI")) {
493 gl_info->gl_vendor = VENDOR_ATI;
494 } else if (strstr(gl_string, "Intel(R)") ||
495 strstr(gl_info->gl_renderer, "Intel(R)") ||
496 strstr(gl_string, "Intel Inc.")) {
497 gl_info->gl_vendor = VENDOR_INTEL;
498 } else if (strstr(gl_string, "Mesa")) {
499 gl_info->gl_vendor = VENDOR_MESA;
500 } else {
501 gl_info->gl_vendor = VENDOR_WINE;
503 } else {
504 gl_info->gl_vendor = VENDOR_WINE;
508 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
510 /* Parse the GL_VERSION field into major and minor information */
511 gl_string = (const char *) glGetString(GL_VERSION);
512 if (gl_string != NULL) {
514 switch (gl_info->gl_vendor) {
515 case VENDOR_NVIDIA:
516 gl_string_cursor = strstr(gl_string, "NVIDIA");
517 if (!gl_string_cursor) {
518 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
519 break;
522 gl_string_cursor = strstr(gl_string_cursor, " ");
523 if (!gl_string_cursor) {
524 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
525 break;
528 while (*gl_string_cursor == ' ') {
529 ++gl_string_cursor;
532 if (!*gl_string_cursor) {
533 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
534 break;
537 major = atoi(gl_string_cursor);
538 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
539 ++gl_string_cursor;
542 if (*gl_string_cursor++ != '.') {
543 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
544 break;
547 minor = atoi(gl_string_cursor);
548 minor = major*100+minor;
549 major = 10;
551 break;
553 case VENDOR_ATI:
554 major = minor = 0;
555 gl_string_cursor = strchr(gl_string, '-');
556 if (gl_string_cursor) {
557 int error = 0;
558 gl_string_cursor++;
560 /* Check if version number is of the form x.y.z */
561 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
562 error = 1;
563 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
564 error = 1;
565 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
566 error = 1;
567 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
568 error = 1;
570 /* Mark version number as malformed */
571 if (error)
572 gl_string_cursor = 0;
575 if (!gl_string_cursor)
576 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
577 else {
578 major = *gl_string_cursor - '0';
579 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
581 break;
583 case VENDOR_INTEL:
584 /* Apple and Mesa version strings look differently, but both provide intel drivers */
585 if(strstr(gl_string, "APPLE")) {
586 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
587 * We only need the first part, and use the APPLE as identification
588 * "1.2 APPLE-1.4.56"
590 gl_string_cursor = gl_string;
591 major = atoi(gl_string_cursor);
592 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
593 ++gl_string_cursor;
596 if (*gl_string_cursor++ != '.') {
597 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
598 break;
601 minor = atoi(gl_string_cursor);
602 break;
605 case VENDOR_MESA:
606 gl_string_cursor = strstr(gl_string, "Mesa");
607 gl_string_cursor = strstr(gl_string_cursor, " ");
608 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
609 if (*gl_string_cursor) {
610 char tmp[16];
611 int cursor = 0;
613 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
614 tmp[cursor++] = *gl_string_cursor;
615 ++gl_string_cursor;
617 tmp[cursor] = 0;
618 major = atoi(tmp);
620 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
621 ++gl_string_cursor;
623 cursor = 0;
624 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
625 tmp[cursor++] = *gl_string_cursor;
626 ++gl_string_cursor;
628 tmp[cursor] = 0;
629 minor = atoi(tmp);
631 break;
633 default:
634 major = 0;
635 minor = 9;
637 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
638 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
641 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
644 * Initialize openGL extension related variables
645 * with Default values
647 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
648 gl_info->max_buffers = 1;
649 gl_info->max_textures = 1;
650 gl_info->max_texture_stages = 1;
651 gl_info->max_fragment_samplers = 1;
652 gl_info->max_vertex_samplers = 0;
653 gl_info->max_combined_samplers = 0;
654 gl_info->max_sampler_stages = 1;
655 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
656 gl_info->ps_arb_max_temps = 0;
657 gl_info->ps_arb_max_instructions = 0;
658 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
659 gl_info->vs_arb_max_temps = 0;
660 gl_info->vs_arb_max_instructions = 0;
661 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
662 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
663 gl_info->vs_glsl_constantsF = 0;
664 gl_info->ps_glsl_constantsF = 0;
665 gl_info->vs_arb_constantsF = 0;
666 gl_info->ps_arb_constantsF = 0;
668 /* Retrieve opengl defaults */
669 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
670 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
671 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
673 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
674 gl_info->max_lights = gl_max;
675 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
677 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
678 gl_info->max_texture_size = gl_max;
679 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
681 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
682 gl_info->max_pointsizemin = gl_floatv[0];
683 gl_info->max_pointsize = gl_floatv[1];
684 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
686 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
687 gl_info->max_aux_buffers = gl_max;
688 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
690 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
691 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
692 TRACE_(d3d_caps)("GL_Extensions reported:\n");
694 if (NULL == GL_Extensions) {
695 ERR(" GL_Extensions returns NULL\n");
696 } else {
697 while (*GL_Extensions != 0x00) {
698 const char *Start;
699 char ThisExtn[256];
700 size_t len;
702 while (isspace(*GL_Extensions)) GL_Extensions++;
703 Start = GL_Extensions;
704 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
705 GL_Extensions++;
708 len = GL_Extensions - Start;
709 if (len == 0 || len >= sizeof(ThisExtn))
710 continue;
712 memcpy(ThisExtn, Start, len);
713 ThisExtn[len] = '\0';
714 TRACE_(d3d_caps)("- %s\n", ThisExtn);
716 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
717 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
718 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
719 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
720 break;
724 /* Now work out what GL support this card really has */
725 #define USE_GL_FUNC(type, pfn, ext, replace) { \
726 DWORD ver = ver_for_ext(ext); \
727 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
728 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
729 else gl_info->pfn = NULL; \
731 GL_EXT_FUNCS_GEN;
732 #undef USE_GL_FUNC
734 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
735 WGL_EXT_FUNCS_GEN;
736 #undef USE_GL_FUNC
738 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
739 * loading the functions, otherwise the code above will load the extension entry points instead of the
740 * core functions, which may not work
742 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
743 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
744 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
745 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
746 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
750 if (gl_info->supported[APPLE_FENCE]) {
751 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
752 * The apple extension interacts with some other apple exts. Disable the NV
753 * extension if the apple one is support to prevent confusion in other parts
754 * of the code
756 gl_info->supported[NV_FENCE] = FALSE;
758 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
759 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
760 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
762 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
763 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
764 * Won't occur in any real world situation though
766 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
768 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
769 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
770 gl_info->max_buffers = gl_max;
771 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
773 if (gl_info->supported[ARB_MULTITEXTURE]) {
774 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
775 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
776 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
778 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
779 GLint tmp;
780 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
781 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
782 } else {
783 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
785 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
787 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
788 GLint tmp;
789 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
790 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
791 } else {
792 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
794 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
796 if (gl_info->supported[ARB_VERTEX_SHADER]) {
797 GLint tmp;
798 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
799 gl_info->max_vertex_samplers = tmp;
800 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
801 gl_info->max_combined_samplers = tmp;
803 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
804 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
805 * an issue because then the sampler setup only depends on the two shaders. If a pixel
806 * shader is used with fixed function vertex processing we're fine too because fixed function
807 * vertex processing doesn't use any samplers. If fixed function fragment processing is
808 * used we have to make sure that all vertex sampler setups are valid together with all
809 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
810 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
811 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
812 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
813 * a fixed function pipeline anymore.
815 * So this is just a check to check that our assumption holds true. If not, write a warning
816 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
818 if(gl_info->max_vertex_samplers &&
819 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
820 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
821 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
822 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
823 if( gl_info->max_combined_samplers > MAX_TEXTURES )
824 gl_info->max_vertex_samplers =
825 gl_info->max_combined_samplers - MAX_TEXTURES;
826 else
827 gl_info->max_vertex_samplers = 0;
829 } else {
830 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
832 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
833 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
835 if (gl_info->supported[ARB_VERTEX_BLEND]) {
836 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
837 gl_info->max_blends = gl_max;
838 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
840 if (gl_info->supported[EXT_TEXTURE3D]) {
841 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
842 gl_info->max_texture3d_size = gl_max;
843 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
845 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
846 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
847 gl_info->max_anisotropy = gl_max;
848 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
850 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
851 gl_info->ps_arb_version = PS_VERSION_11;
852 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
853 gl_info->ps_arb_constantsF = gl_max;
854 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
855 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
856 gl_info->ps_arb_max_temps = gl_max;
857 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
858 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
859 gl_info->ps_arb_max_instructions = gl_max;
860 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
862 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
863 gl_info->vs_arb_version = VS_VERSION_11;
864 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
865 gl_info->vs_arb_constantsF = gl_max;
866 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
867 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
868 gl_info->vs_arb_max_temps = gl_max;
869 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
870 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
871 gl_info->vs_arb_max_instructions = gl_max;
872 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
874 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
876 if (gl_info->supported[ARB_VERTEX_SHADER]) {
877 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
878 gl_info->vs_glsl_constantsF = gl_max / 4;
879 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
881 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
882 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
883 gl_info->ps_glsl_constantsF = gl_max / 4;
884 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
885 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
886 gl_info->max_glsl_varyings = gl_max;
887 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
889 if (gl_info->supported[EXT_VERTEX_SHADER]) {
890 gl_info->vs_ati_version = VS_VERSION_11;
892 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
893 gl_info->vs_nv_version = VS_VERSION_30;
894 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
895 gl_info->vs_nv_version = VS_VERSION_20;
896 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
897 gl_info->vs_nv_version = VS_VERSION_11;
898 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
899 gl_info->vs_nv_version = VS_VERSION_10;
901 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
902 gl_info->ps_nv_version = PS_VERSION_30;
903 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
904 gl_info->ps_nv_version = PS_VERSION_20;
906 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
907 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
908 * This saves a few redundant glDisable calls
910 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
914 checkGLcall("extension detection\n");
916 /* In some cases the number of texture stages can be larger than the number
917 * of samplers. The GF4 for example can use only 2 samplers (no fragment
918 * shaders), but 8 texture stages (register combiners). */
919 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
921 /* We can only use ORM_FBO when the hardware supports it. */
922 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
923 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
924 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
927 /* MRTs are currently only supported when FBOs are used. */
928 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
929 gl_info->max_buffers = 1;
932 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
933 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
934 * in case of the latest videocards in the number of pixel/vertex pipelines.
936 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
937 * rendering. Various games use this information to get a rough estimation of the features of the card
938 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
939 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
940 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
941 * not the PCI id.
943 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
944 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
945 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
946 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
947 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
948 * is used for rendering which is not always the case). This would work but it is not very portable. Second
949 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
950 * is limited.
952 * As said most games only use the PCI id to get an indication of the capabilities of the card.
953 * It doesn't really matter if the given id is the correct one if we return the id of a card with
954 * similar 3d features.
956 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
957 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
958 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
959 * won't pass we return a default card. This way is better than maintaining a full card database as even
960 * without a full database we can return a card with similar features. Second the size of the database
961 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
962 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
963 * to distinguishes between different models from that family.
965 * The code also selects a default amount of video memory which we will use for an estimation of the amount
966 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
967 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
968 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
969 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
970 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
971 * memory behind our backs if really needed.
972 * Note that the amout of video memory can be overruled using a registry setting.
974 switch (gl_info->gl_vendor) {
975 case VENDOR_NVIDIA:
976 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
977 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
979 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
980 /* Geforce8 - highend */
981 if (strstr(gl_info->gl_renderer, "8800")) {
982 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
983 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
985 /* Geforce8 - midend mobile */
986 else if(strstr(gl_info->gl_renderer, "8600 M")) {
987 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
988 vidmem = 512;
990 /* Geforce8 - midend */
991 else if(strstr(gl_info->gl_renderer, "8600") ||
992 strstr(gl_info->gl_renderer, "8700"))
994 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
995 vidmem = 256;
997 /* Geforce8 - lowend */
998 else if(strstr(gl_info->gl_renderer, "8300") ||
999 strstr(gl_info->gl_renderer, "8400") ||
1000 strstr(gl_info->gl_renderer, "8500"))
1002 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1003 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1005 /* Geforce7 - highend */
1006 else if(strstr(gl_info->gl_renderer, "7800") ||
1007 strstr(gl_info->gl_renderer, "7900") ||
1008 strstr(gl_info->gl_renderer, "7950") ||
1009 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1010 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1012 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1013 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1015 /* Geforce7 midend */
1016 else if(strstr(gl_info->gl_renderer, "7600") ||
1017 strstr(gl_info->gl_renderer, "7700")) {
1018 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1019 vidmem = 256; /* The 7600 uses 256-512MB */
1020 /* Geforce7 lower medium */
1021 } else if(strstr(gl_info->gl_renderer, "7400")) {
1022 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1023 vidmem = 256; /* The 7400 uses 256-512MB */
1025 /* Geforce6 highend */
1026 else if(strstr(gl_info->gl_renderer, "6800"))
1028 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1029 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1031 /* Geforce6 - midend */
1032 else if(strstr(gl_info->gl_renderer, "6600") ||
1033 strstr(gl_info->gl_renderer, "6610") ||
1034 strstr(gl_info->gl_renderer, "6700"))
1036 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1037 vidmem = 128; /* A 6600GT has 128-256MB */
1039 /* Geforce6/7 lowend */
1040 else {
1041 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1042 vidmem = 64; /* */
1044 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1045 /* GeforceFX - highend */
1046 if (strstr(gl_info->gl_renderer, "5800") ||
1047 strstr(gl_info->gl_renderer, "5900") ||
1048 strstr(gl_info->gl_renderer, "5950") ||
1049 strstr(gl_info->gl_renderer, "Quadro FX"))
1051 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1052 vidmem = 256; /* 5800-5900 cards use 256MB */
1054 /* GeforceFX - midend */
1055 else if(strstr(gl_info->gl_renderer, "5600") ||
1056 strstr(gl_info->gl_renderer, "5650") ||
1057 strstr(gl_info->gl_renderer, "5700") ||
1058 strstr(gl_info->gl_renderer, "5750"))
1060 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1061 vidmem = 128; /* A 5600 uses 128-256MB */
1063 /* GeforceFX - lowend */
1064 else {
1065 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1066 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1068 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1069 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1070 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1071 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1073 else {
1074 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1075 vidmem = 64; /* Geforce3 cards have 64-128MB */
1077 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1078 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1079 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1080 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1082 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1083 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1084 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1086 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1087 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1088 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1090 else {
1091 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1092 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1094 } else {
1095 if (strstr(gl_info->gl_renderer, "TNT2")) {
1096 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1097 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1099 else {
1100 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1101 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1104 break;
1105 case VENDOR_ATI:
1106 if(WINE_D3D9_CAPABLE(gl_info)) {
1107 /* Radeon R6xx HD2900 - highend */
1108 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1109 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1110 vidmem = 512; /* HD2900 uses 512-1024MB */
1112 /* Radeon R6xx HD2600- midend */
1113 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1114 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1115 vidmem = 256; /* HD2600 uses 256-512MB */
1117 /* Radeon R6xx HD2300/HD2400 - lowend */
1118 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1119 strstr(gl_info->gl_renderer, "HD 2400"))
1121 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1122 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1124 /* Radeon R5xx */
1125 else if (strstr(gl_info->gl_renderer, "X1600") ||
1126 strstr(gl_info->gl_renderer, "X1650") ||
1127 strstr(gl_info->gl_renderer, "X1800") ||
1128 strstr(gl_info->gl_renderer, "X1900") ||
1129 strstr(gl_info->gl_renderer, "X1950"))
1131 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1132 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1134 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1135 else if(strstr(gl_info->gl_renderer, "X700") ||
1136 strstr(gl_info->gl_renderer, "X800") ||
1137 strstr(gl_info->gl_renderer, "X850") ||
1138 strstr(gl_info->gl_renderer, "X1300") ||
1139 strstr(gl_info->gl_renderer, "X1400") ||
1140 strstr(gl_info->gl_renderer, "X1450") ||
1141 strstr(gl_info->gl_renderer, "X1550"))
1143 gl_info->gl_card = CARD_ATI_RADEON_X700;
1144 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1146 /* Radeon R3xx */
1147 else {
1148 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1149 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1151 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1152 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1153 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1154 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1155 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1156 vidmem = 32; /* There are models with up to 64MB */
1157 } else {
1158 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1159 vidmem = 16; /* There are 16-32MB models */
1161 break;
1162 case VENDOR_INTEL:
1163 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1164 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1165 gl_info->gl_card = CARD_INTEL_I945GM;
1166 vidmem = 64;
1167 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1168 gl_info->gl_card = CARD_INTEL_I915GM;
1169 } else if (strstr(gl_info->gl_renderer, "915G")) {
1170 gl_info->gl_card = CARD_INTEL_I915G;
1171 } else if (strstr(gl_info->gl_renderer, "865G")) {
1172 gl_info->gl_card = CARD_INTEL_I865G;
1173 } else if (strstr(gl_info->gl_renderer, "855G")) {
1174 gl_info->gl_card = CARD_INTEL_I855G;
1175 } else if (strstr(gl_info->gl_renderer, "830G")) {
1176 gl_info->gl_card = CARD_INTEL_I830G;
1177 } else {
1178 gl_info->gl_card = CARD_INTEL_I915G;
1180 break;
1181 case VENDOR_MESA:
1182 case VENDOR_WINE:
1183 default:
1184 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1185 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1186 * them a good generic choice.
1188 gl_info->gl_vendor = VENDOR_NVIDIA;
1189 if(WINE_D3D9_CAPABLE(gl_info))
1190 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1191 else if(WINE_D3D8_CAPABLE(gl_info))
1192 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1193 else if(WINE_D3D7_CAPABLE(gl_info))
1194 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1195 else if(WINE_D3D6_CAPABLE(gl_info))
1196 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1197 else
1198 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1200 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1202 /* If we have an estimate use it, else default to 64MB; */
1203 if(vidmem)
1204 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1205 else
1206 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1208 /* Load all the lookup tables
1209 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1210 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1211 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1213 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1214 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1217 for (i = 0; i < MAX_LOOKUPS; i++) {
1218 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1221 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1222 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1223 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1224 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1225 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1226 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1227 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1228 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1229 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1230 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1232 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1233 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1234 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1235 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1236 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1239 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1240 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1241 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1242 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1243 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1244 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1245 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1246 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1247 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1248 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1249 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1250 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1251 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1253 /* TODO: config lookups */
1255 /* Make sure there's an active HDC else the WGL extensions will fail */
1256 hdc = pwglGetCurrentDC();
1257 if (hdc) {
1258 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1259 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1261 if (NULL == WGL_Extensions) {
1262 ERR(" WGL_Extensions returns NULL\n");
1263 } else {
1264 while (*WGL_Extensions != 0x00) {
1265 const char *Start;
1266 char ThisExtn[256];
1267 size_t len;
1269 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1270 Start = WGL_Extensions;
1271 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1272 WGL_Extensions++;
1275 len = WGL_Extensions - Start;
1276 if (len == 0 || len >= sizeof(ThisExtn))
1277 continue;
1279 memcpy(ThisExtn, Start, len);
1280 ThisExtn[len] = '\0';
1281 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1283 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1284 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1285 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1290 LEAVE_GL();
1292 return return_value;
1294 #undef GLINFO_LOCATION
1296 /**********************************************************
1297 * IWineD3D implementation follows
1298 **********************************************************/
1300 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1301 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1303 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1304 return numAdapters;
1307 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1308 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1309 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1310 return WINED3D_OK;
1313 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1314 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1316 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1317 return NULL;
1320 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1321 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1324 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1325 of the same bpp but different resolutions */
1327 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1328 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1329 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1330 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1332 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1333 return 0;
1336 /* TODO: Store modes per adapter and read it from the adapter structure */
1337 if (Adapter == 0) { /* Display */
1338 int i = 0;
1339 int j = 0;
1341 if (!DEBUG_SINGLE_MODE) {
1342 DEVMODEW DevModeW;
1344 ZeroMemory(&DevModeW, sizeof(DevModeW));
1345 DevModeW.dmSize = sizeof(DevModeW);
1346 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1347 j++;
1348 switch (Format)
1350 case WINED3DFMT_UNKNOWN:
1351 /* This is for D3D8, do not enumerate P8 here */
1352 if (DevModeW.dmBitsPerPel == 32 ||
1353 DevModeW.dmBitsPerPel == 16) i++;
1354 break;
1355 case WINED3DFMT_X8R8G8B8:
1356 if (DevModeW.dmBitsPerPel == 32) i++;
1357 break;
1358 case WINED3DFMT_R5G6B5:
1359 if (DevModeW.dmBitsPerPel == 16) i++;
1360 break;
1361 case WINED3DFMT_P8:
1362 if (DevModeW.dmBitsPerPel == 8) i++;
1363 break;
1364 default:
1365 /* Skip other modes as they do not match the requested format */
1366 break;
1369 } else {
1370 i = 1;
1371 j = 1;
1374 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1375 return i;
1376 } else {
1377 FIXME_(d3d_caps)("Adapter not primary display\n");
1379 return 0;
1382 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1383 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1384 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1385 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1387 /* Validate the parameters as much as possible */
1388 if (NULL == pMode ||
1389 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1390 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1391 return WINED3DERR_INVALIDCALL;
1394 /* TODO: Store modes per adapter and read it from the adapter structure */
1395 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1396 DEVMODEW DevModeW;
1397 int ModeIdx = 0;
1398 int i = 0;
1399 int j = 0;
1401 ZeroMemory(&DevModeW, sizeof(DevModeW));
1402 DevModeW.dmSize = sizeof(DevModeW);
1404 /* If we are filtering to a specific format (D3D9), then need to skip
1405 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1406 just count through the ones with valid bit depths */
1407 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1408 switch (Format)
1410 case WINED3DFMT_UNKNOWN:
1411 /* This is D3D8. Do not enumerate P8 here */
1412 if (DevModeW.dmBitsPerPel == 32 ||
1413 DevModeW.dmBitsPerPel == 16) i++;
1414 break;
1415 case WINED3DFMT_X8R8G8B8:
1416 if (DevModeW.dmBitsPerPel == 32) i++;
1417 break;
1418 case WINED3DFMT_R5G6B5:
1419 if (DevModeW.dmBitsPerPel == 16) i++;
1420 break;
1421 case WINED3DFMT_P8:
1422 if (DevModeW.dmBitsPerPel == 8) i++;
1423 break;
1424 default:
1425 /* Modes that don't match what we support can get an early-out */
1426 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1427 return WINED3DERR_INVALIDCALL;
1431 if (i == 0) {
1432 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1433 return WINED3DERR_INVALIDCALL;
1435 ModeIdx = j - 1;
1437 /* Now get the display mode via the calculated index */
1438 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1439 pMode->Width = DevModeW.dmPelsWidth;
1440 pMode->Height = DevModeW.dmPelsHeight;
1441 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1442 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1443 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1445 if (Format == WINED3DFMT_UNKNOWN) {
1446 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1447 } else {
1448 pMode->Format = Format;
1450 } else {
1451 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1452 return WINED3DERR_INVALIDCALL;
1455 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1456 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1457 DevModeW.dmBitsPerPel);
1459 } else if (DEBUG_SINGLE_MODE) {
1460 /* Return one setting of the format requested */
1461 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1462 pMode->Width = 800;
1463 pMode->Height = 600;
1464 pMode->RefreshRate = 60;
1465 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1466 } else {
1467 FIXME_(d3d_caps)("Adapter not primary display\n");
1470 return WINED3D_OK;
1473 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1474 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1475 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1477 if (NULL == pMode ||
1478 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1479 return WINED3DERR_INVALIDCALL;
1482 if (Adapter == 0) { /* Display */
1483 int bpp = 0;
1484 DEVMODEW DevModeW;
1486 ZeroMemory(&DevModeW, sizeof(DevModeW));
1487 DevModeW.dmSize = sizeof(DevModeW);
1489 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1490 pMode->Width = DevModeW.dmPelsWidth;
1491 pMode->Height = DevModeW.dmPelsHeight;
1492 bpp = DevModeW.dmBitsPerPel;
1493 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1494 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1496 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1499 pMode->Format = pixelformat_for_depth(bpp);
1500 } else {
1501 FIXME_(d3d_caps)("Adapter not primary display\n");
1504 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1505 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1506 return WINED3D_OK;
1509 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1510 and fields being inserted in the middle, a new structure is used in place */
1511 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1512 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1513 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1515 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1517 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1518 return WINED3DERR_INVALIDCALL;
1521 /* Return the information requested */
1522 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1523 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1524 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1526 /* Note dx8 doesn't supply a DeviceName */
1527 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1528 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1529 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1530 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1531 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1532 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1533 *(pIdentifier->SubSysId) = 0;
1534 *(pIdentifier->Revision) = 0;
1536 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1537 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1538 *(pIdentifier->WHQLLevel) = 0;
1539 } else {
1540 *(pIdentifier->WHQLLevel) = 1;
1543 return WINED3D_OK;
1546 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1547 short redSize, greenSize, blueSize, alphaSize, colorBits;
1549 if(!cfg)
1550 return FALSE;
1552 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1553 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1554 return FALSE;
1557 if(cfg->redSize < redSize)
1558 return FALSE;
1560 if(cfg->greenSize < greenSize)
1561 return FALSE;
1563 if(cfg->blueSize < blueSize)
1564 return FALSE;
1566 if(cfg->alphaSize < alphaSize)
1567 return FALSE;
1569 return TRUE;
1572 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1573 short depthSize, stencilSize;
1575 if(!cfg)
1576 return FALSE;
1578 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1579 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1580 return FALSE;
1583 if(cfg->depthSize < depthSize)
1584 return FALSE;
1586 if(cfg->stencilSize < stencilSize)
1587 return FALSE;
1589 return TRUE;
1592 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1593 WINED3DFORMAT AdapterFormat,
1594 WINED3DFORMAT RenderTargetFormat,
1595 WINED3DFORMAT DepthStencilFormat) {
1596 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1597 int nCfgs;
1598 WineD3D_PixelFormat *cfgs;
1599 int it;
1601 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1602 This, Adapter,
1603 DeviceType, debug_d3ddevicetype(DeviceType),
1604 AdapterFormat, debug_d3dformat(AdapterFormat),
1605 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1606 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1608 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1609 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1610 return WINED3DERR_INVALIDCALL;
1613 cfgs = Adapters[Adapter].cfgs;
1614 nCfgs = Adapters[Adapter].nCfgs;
1615 for (it = 0; it < nCfgs; ++it) {
1616 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1617 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1618 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1619 return WINED3D_OK;
1623 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1625 return WINED3DERR_NOTAVAILABLE;
1628 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1629 WINED3DFORMAT SurfaceFormat,
1630 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1632 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1633 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1634 This,
1635 Adapter,
1636 DeviceType, debug_d3ddevicetype(DeviceType),
1637 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1638 Windowed,
1639 MultiSampleType,
1640 pQualityLevels);
1642 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1643 return WINED3DERR_INVALIDCALL;
1646 /* TODO: Store in Adapter structure */
1647 if (pQualityLevels != NULL) {
1648 static int s_single_shot = 0;
1649 if (!s_single_shot) {
1650 FIXME("Quality levels unsupported at present\n");
1651 s_single_shot = 1;
1653 *pQualityLevels = 1; /* Guess at a value! */
1656 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1657 return WINED3DERR_NOTAVAILABLE;
1660 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1661 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1663 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1664 int nCfgs = 0;
1665 WineD3D_PixelFormat *cfgs;
1666 int it;
1667 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1669 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1670 This,
1671 Adapter,
1672 CheckType, debug_d3ddevicetype(CheckType),
1673 DisplayFormat, debug_d3dformat(DisplayFormat),
1674 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1675 Windowed);
1677 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1678 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1679 return WINED3DERR_INVALIDCALL;
1682 cfgs = Adapters[Adapter].cfgs;
1683 nCfgs = Adapters[Adapter].nCfgs;
1684 for (it = 0; it < nCfgs; ++it) {
1685 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1686 hr = WINED3D_OK;
1687 TRACE_(d3d_caps)("OK\n");
1688 break ;
1692 if(hr != WINED3D_OK)
1693 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1695 if(hr != WINED3D_OK)
1696 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1698 return hr;
1701 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1702 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1703 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1704 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1705 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1706 This,
1707 Adapter,
1708 DeviceType, debug_d3ddevicetype(DeviceType),
1709 AdapterFormat, debug_d3dformat(AdapterFormat),
1710 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1711 RType, debug_d3dresourcetype(RType),
1712 CheckFormat, debug_d3dformat(CheckFormat));
1714 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1715 return WINED3DERR_INVALIDCALL;
1718 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1719 switch (CheckFormat) {
1720 /* Filtering not supported */
1721 case WINED3DFMT_R32F:
1722 case WINED3DFMT_A32B32G32R32F:
1723 TRACE_(d3d_caps)("[FAILED]\n");
1724 return WINED3DERR_NOTAVAILABLE;
1725 default:
1726 break;
1730 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1731 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1732 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1733 return WINED3DERR_NOTAVAILABLE;
1737 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1738 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1739 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1740 return WINED3DERR_NOTAVAILABLE;
1742 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1743 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1744 * app needing one of those formats, don't advertize them to avoid leading apps into
1745 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1746 * except of R32F.
1748 switch(CheckFormat) {
1749 case WINED3DFMT_P8:
1750 case WINED3DFMT_A4L4:
1751 case WINED3DFMT_R32F:
1752 case WINED3DFMT_R16F:
1753 case WINED3DFMT_X8L8V8U8:
1754 case WINED3DFMT_L6V5U5:
1755 case WINED3DFMT_G16R16:
1756 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1757 return WINED3DERR_NOTAVAILABLE;
1759 case WINED3DFMT_Q8W8V8U8:
1760 case WINED3DFMT_V16U16:
1761 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1762 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1763 return WINED3DERR_NOTAVAILABLE;
1765 break;
1767 case WINED3DFMT_V8U8:
1768 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1769 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1770 return WINED3DERR_NOTAVAILABLE;
1772 break;
1774 case WINED3DFMT_DXT1:
1775 case WINED3DFMT_DXT2:
1776 case WINED3DFMT_DXT3:
1777 case WINED3DFMT_DXT4:
1778 case WINED3DFMT_DXT5:
1779 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1780 * compressed texture results in an error. While the D3D refrast does
1781 * support s3tc volumes, at least the nvidia windows driver does not, so
1782 * we're free not to support this format.
1784 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1785 return WINED3DERR_NOTAVAILABLE;
1787 default:
1788 /* Do nothing, continue with checking the format below */
1789 break;
1792 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1793 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1794 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1795 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1796 if (!GL_LIMITS(vertex_samplers)) {
1797 TRACE_(d3d_caps)("[FAILED]\n");
1798 return WINED3DERR_NOTAVAILABLE;
1801 switch (CheckFormat) {
1802 case WINED3DFMT_A32B32G32R32F:
1803 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1804 TRACE_(d3d_caps)("[FAILED]\n");
1805 return WINED3DERR_NOTAVAILABLE;
1807 TRACE_(d3d_caps)("[OK]\n");
1808 return WINED3D_OK;
1810 default:
1811 TRACE_(d3d_caps)("[FAILED]\n");
1812 return WINED3DERR_NOTAVAILABLE;
1816 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1817 switch (CheckFormat) {
1818 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1819 * Windows supports only those 3, and enumerating the other formats confuses applications
1821 case WINED3DFMT_D24S8:
1822 case WINED3DFMT_D24X8:
1823 case WINED3DFMT_D16:
1824 TRACE_(d3d_caps)("[OK]\n");
1825 return WINED3D_OK;
1826 case WINED3DFMT_D16_LOCKABLE:
1827 case WINED3DFMT_D24FS8:
1828 case WINED3DFMT_D32F_LOCKABLE:
1829 case WINED3DFMT_D24X4S4:
1830 case WINED3DFMT_D15S1:
1831 case WINED3DFMT_D32:
1832 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1833 return WINED3DERR_NOTAVAILABLE;
1834 default:
1835 TRACE_(d3d_caps)("[FAILED]\n");
1836 return WINED3DERR_NOTAVAILABLE;
1838 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1839 switch (CheckFormat) {
1840 case WINED3DFMT_R8G8B8:
1841 case WINED3DFMT_A8R8G8B8:
1842 case WINED3DFMT_X8R8G8B8:
1843 case WINED3DFMT_R5G6B5:
1844 case WINED3DFMT_X1R5G5B5:
1845 case WINED3DFMT_A1R5G5B5:
1846 case WINED3DFMT_A4R4G4B4:
1847 case WINED3DFMT_R3G3B2:
1848 case WINED3DFMT_X4R4G4B4:
1849 case WINED3DFMT_A8B8G8R8:
1850 case WINED3DFMT_X8B8G8R8:
1851 case WINED3DFMT_P8:
1852 case WINED3DFMT_G16R16:
1853 TRACE_(d3d_caps)("[OK]\n");
1854 return WINED3D_OK;
1855 case WINED3DFMT_R16F:
1856 case WINED3DFMT_A16B16G16R16F:
1857 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1858 TRACE_(d3d_caps)("[FAILED]\n");
1859 return WINED3DERR_NOTAVAILABLE;
1861 TRACE_(d3d_caps)("[OK]\n");
1862 return WINED3D_OK;
1863 case WINED3DFMT_A32B32G32R32F:
1864 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1865 TRACE_(d3d_caps)("[FAILED]\n");
1866 return WINED3DERR_NOTAVAILABLE;
1868 TRACE_(d3d_caps)("[OK]\n");
1869 return WINED3D_OK;
1870 default:
1871 TRACE_(d3d_caps)("[FAILED]\n");
1872 return WINED3DERR_NOTAVAILABLE;
1874 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1875 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1876 switch (CheckFormat) {
1877 case WINED3DFMT_V8U8:
1878 TRACE_(d3d_caps)("[OK]\n");
1879 return WINED3D_OK;
1880 /* TODO: Other bump map formats */
1881 default:
1882 TRACE_(d3d_caps)("[FAILED]\n");
1883 return WINED3DERR_NOTAVAILABLE;
1886 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1887 switch (CheckFormat) {
1888 case WINED3DFMT_V8U8:
1889 TRACE_(d3d_caps)("[OK]\n");
1890 return WINED3D_OK;
1891 default:
1892 TRACE_(d3d_caps)("[FAILED]\n");
1893 return WINED3DERR_NOTAVAILABLE;
1896 TRACE_(d3d_caps)("[FAILED]\n");
1897 return WINED3DERR_NOTAVAILABLE;
1900 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1901 switch (CheckFormat) {
1902 case WINED3DFMT_DXT1:
1903 case WINED3DFMT_DXT2:
1904 case WINED3DFMT_DXT3:
1905 case WINED3DFMT_DXT4:
1906 case WINED3DFMT_DXT5:
1907 TRACE_(d3d_caps)("[OK]\n");
1908 return WINED3D_OK;
1909 default:
1910 break; /* Avoid compiler warnings */
1914 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1915 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1916 switch (CheckFormat) {
1917 case WINED3DFMT_A8R8G8B8:
1918 case WINED3DFMT_X8R8G8B8:
1919 case WINED3DFMT_A4R4G4B4:
1920 case WINED3DFMT_L8:
1921 case WINED3DFMT_A8L8:
1922 case WINED3DFMT_DXT1:
1923 case WINED3DFMT_DXT2:
1924 case WINED3DFMT_DXT3:
1925 case WINED3DFMT_DXT4:
1926 case WINED3DFMT_DXT5:
1927 TRACE_(d3d_caps)("[OK]\n");
1928 return WINED3D_OK;
1930 default:
1931 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1932 return WINED3DERR_NOTAVAILABLE;
1936 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1938 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1940 switch (CheckFormat) {
1941 case WINED3DFMT_R16F:
1942 case WINED3DFMT_A16B16G16R16F:
1943 if (!half_pixel_support) break;
1944 case WINED3DFMT_R32F:
1945 case WINED3DFMT_A32B32G32R32F:
1946 TRACE_(d3d_caps)("[OK]\n");
1947 return WINED3D_OK;
1948 default:
1949 break; /* Avoid compiler warnings */
1953 /* This format is nothing special and it is supported perfectly.
1954 * However, ati and nvidia driver on windows do not mark this format as
1955 * supported (tested with the dxCapsViewer) and pretending to
1956 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1957 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1958 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1960 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1961 TRACE_(d3d_caps)("[FAILED]\n");
1962 return WINED3DERR_NOTAVAILABLE;
1965 switch (CheckFormat) {
1967 /*****
1968 * supported: RGB(A) formats
1970 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1971 case WINED3DFMT_A8R8G8B8:
1972 case WINED3DFMT_X8R8G8B8:
1973 case WINED3DFMT_R5G6B5:
1974 case WINED3DFMT_X1R5G5B5:
1975 case WINED3DFMT_A1R5G5B5:
1976 case WINED3DFMT_A4R4G4B4:
1977 case WINED3DFMT_R3G3B2:
1978 case WINED3DFMT_A8:
1979 case WINED3DFMT_X4R4G4B4:
1980 case WINED3DFMT_A8B8G8R8:
1981 case WINED3DFMT_X8B8G8R8:
1982 case WINED3DFMT_A2R10G10B10:
1983 case WINED3DFMT_A2B10G10R10:
1984 case WINED3DFMT_G16R16:
1985 TRACE_(d3d_caps)("[OK]\n");
1986 return WINED3D_OK;
1988 /*****
1989 * supported: Palettized
1991 case WINED3DFMT_P8:
1992 TRACE_(d3d_caps)("[OK]\n");
1993 return WINED3D_OK;
1995 /*****
1996 * Supported: (Alpha)-Luminance
1998 case WINED3DFMT_L8:
1999 case WINED3DFMT_A8L8:
2000 case WINED3DFMT_A4L4:
2001 TRACE_(d3d_caps)("[OK]\n");
2002 return WINED3D_OK;
2004 /*****
2005 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2006 * GL_NV_texture_shader), but advertized to make apps happy.
2007 * Enable some because games often fail when they are not available
2008 * and are still playable even without bump mapping
2010 case WINED3DFMT_V8U8:
2011 case WINED3DFMT_V16U16:
2012 case WINED3DFMT_L6V5U5:
2013 case WINED3DFMT_X8L8V8U8:
2014 case WINED3DFMT_Q8W8V8U8:
2015 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
2016 return WINED3D_OK;
2018 /* Those are not advertized by the nvidia windows driver, and not
2019 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2020 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2021 * ARGB format if needed
2023 case WINED3DFMT_W11V11U10:
2024 case WINED3DFMT_A2W10V10U10:
2025 WARN_(d3d_caps)("[FAILED]\n");
2026 return WINED3DERR_NOTAVAILABLE;
2028 /*****
2029 * DXTN Formats: Handled above
2030 * WINED3DFMT_DXT1
2031 * WINED3DFMT_DXT2
2032 * WINED3DFMT_DXT3
2033 * WINED3DFMT_DXT4
2034 * WINED3DFMT_DXT5
2037 /*****
2038 * Odd formats - not supported
2040 case WINED3DFMT_VERTEXDATA:
2041 case WINED3DFMT_INDEX16:
2042 case WINED3DFMT_INDEX32:
2043 case WINED3DFMT_Q16W16V16U16:
2044 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2045 return WINED3DERR_NOTAVAILABLE;
2047 /*****
2048 * Float formats: Not supported right now
2050 case WINED3DFMT_G16R16F:
2051 case WINED3DFMT_G32R32F:
2052 case WINED3DFMT_CxV8U8:
2053 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2054 return WINED3DERR_NOTAVAILABLE;
2056 /* Not supported */
2057 case WINED3DFMT_A16B16G16R16:
2058 case WINED3DFMT_A8R3G3B2:
2059 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2060 return WINED3DERR_NOTAVAILABLE;
2062 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2063 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2064 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2065 * We can do instancing with all shader versions, but we need vertex shaders.
2067 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2068 * to enable instancing. WineD3D doesn't need that and just ignores it.
2070 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2072 case WINEMAKEFOURCC('I','N','S','T'):
2073 TRACE("ATI Instancing check hack\n");
2074 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2075 TRACE_(d3d_caps)("[OK]\n");
2076 return WINED3D_OK;
2077 } else {
2078 TRACE_(d3d_caps)("[FAILED]\n");
2079 return WINED3DERR_NOTAVAILABLE;
2082 default:
2083 break;
2086 TRACE_(d3d_caps)("[FAILED]\n");
2087 return WINED3DERR_NOTAVAILABLE;
2090 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2091 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2092 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2094 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2095 This,
2096 Adapter,
2097 DeviceType, debug_d3ddevicetype(DeviceType),
2098 SourceFormat, debug_d3dformat(SourceFormat),
2099 TargetFormat, debug_d3dformat(TargetFormat));
2100 return WINED3D_OK;
2103 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2104 subset of a D3DCAPS9 structure. However, it has to come via a void *
2105 as the d3d8 interface cannot import the d3d9 header */
2106 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2108 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2109 int vs_selected_mode;
2110 int ps_selected_mode;
2112 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2114 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2115 return WINED3DERR_INVALIDCALL;
2118 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2120 /* This function should *not* be modifying GL caps
2121 * TODO: move the functionality where it belongs */
2122 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2124 /* ------------------------------------------------
2125 The following fields apply to both d3d8 and d3d9
2126 ------------------------------------------------ */
2127 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2128 *pCaps->AdapterOrdinal = Adapter;
2130 *pCaps->Caps = 0;
2131 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2132 WINED3DCAPS2_FULLSCREENGAMMA |
2133 WINED3DCAPS2_DYNAMICTEXTURES;
2134 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2135 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2137 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2138 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2139 WINED3DPRESENT_INTERVAL_ONE;
2141 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2142 WINED3DCURSORCAPS_LOWRES;
2144 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2145 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2146 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2147 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2148 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2149 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2150 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2151 WINED3DDEVCAPS_PUREDEVICE |
2152 WINED3DDEVCAPS_HWRASTERIZATION |
2153 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2154 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2155 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2156 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2157 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2158 WINED3DDEVCAPS_RTPATCHES;
2160 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2161 WINED3DPMISCCAPS_CULLCCW |
2162 WINED3DPMISCCAPS_CULLCW |
2163 WINED3DPMISCCAPS_COLORWRITEENABLE |
2164 WINED3DPMISCCAPS_CLIPTLVERTS |
2165 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2166 WINED3DPMISCCAPS_MASKZ |
2167 WINED3DPMISCCAPS_BLENDOP;
2168 /* TODO:
2169 WINED3DPMISCCAPS_NULLREFERENCE
2170 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2171 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2172 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2173 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2174 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2175 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2177 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2178 #if 0
2179 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2180 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2181 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2182 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2183 #endif
2185 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2186 WINED3DPRASTERCAPS_PAT |
2187 WINED3DPRASTERCAPS_WFOG |
2188 WINED3DPRASTERCAPS_ZFOG |
2189 WINED3DPRASTERCAPS_FOGVERTEX |
2190 WINED3DPRASTERCAPS_FOGTABLE |
2191 WINED3DPRASTERCAPS_STIPPLE |
2192 WINED3DPRASTERCAPS_SUBPIXEL |
2193 WINED3DPRASTERCAPS_ZTEST |
2194 WINED3DPRASTERCAPS_SCISSORTEST |
2195 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2196 WINED3DPRASTERCAPS_DEPTHBIAS;
2198 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2199 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2200 WINED3DPRASTERCAPS_ZBIAS |
2201 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2203 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2204 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2206 /* FIXME Add:
2207 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2208 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2209 WINED3DPRASTERCAPS_ANTIALIASEDGES
2210 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2211 WINED3DPRASTERCAPS_WBUFFER */
2213 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2214 WINED3DPCMPCAPS_EQUAL |
2215 WINED3DPCMPCAPS_GREATER |
2216 WINED3DPCMPCAPS_GREATEREQUAL |
2217 WINED3DPCMPCAPS_LESS |
2218 WINED3DPCMPCAPS_LESSEQUAL |
2219 WINED3DPCMPCAPS_NEVER |
2220 WINED3DPCMPCAPS_NOTEQUAL;
2222 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2223 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_BLENDFACTOR |
2238 WINED3DPBLENDCAPS_DESTALPHA |
2239 WINED3DPBLENDCAPS_DESTCOLOR |
2240 WINED3DPBLENDCAPS_INVDESTALPHA |
2241 WINED3DPBLENDCAPS_INVDESTCOLOR |
2242 WINED3DPBLENDCAPS_INVSRCALPHA |
2243 WINED3DPBLENDCAPS_INVSRCCOLOR |
2244 WINED3DPBLENDCAPS_ONE |
2245 WINED3DPBLENDCAPS_SRCALPHA |
2246 WINED3DPBLENDCAPS_SRCCOLOR |
2247 WINED3DPBLENDCAPS_ZERO;
2248 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2249 * according to the glBlendFunc manpage
2251 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2252 * legacy settings for srcblend only
2255 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2256 WINED3DPCMPCAPS_EQUAL |
2257 WINED3DPCMPCAPS_GREATER |
2258 WINED3DPCMPCAPS_GREATEREQUAL |
2259 WINED3DPCMPCAPS_LESS |
2260 WINED3DPCMPCAPS_LESSEQUAL |
2261 WINED3DPCMPCAPS_NEVER |
2262 WINED3DPCMPCAPS_NOTEQUAL;
2264 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2265 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2266 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2267 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2268 WINED3DPSHADECAPS_COLORFLATRGB |
2269 WINED3DPSHADECAPS_FOGFLAT |
2270 WINED3DPSHADECAPS_FOGGOURAUD |
2271 WINED3DPSHADECAPS_SPECULARFLATRGB;
2273 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2274 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2275 WINED3DPTEXTURECAPS_BORDER |
2276 WINED3DPTEXTURECAPS_MIPMAP |
2277 WINED3DPTEXTURECAPS_PROJECTED |
2278 WINED3DPTEXTURECAPS_PERSPECTIVE;
2280 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2281 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2282 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2285 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2286 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2287 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2288 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2291 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2292 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2293 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2294 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2298 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2299 WINED3DPTFILTERCAPS_MAGFPOINT |
2300 WINED3DPTFILTERCAPS_MINFLINEAR |
2301 WINED3DPTFILTERCAPS_MINFPOINT |
2302 WINED3DPTFILTERCAPS_MIPFLINEAR |
2303 WINED3DPTFILTERCAPS_MIPFPOINT |
2304 WINED3DPTFILTERCAPS_LINEAR |
2305 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2306 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2307 WINED3DPTFILTERCAPS_MIPLINEAR |
2308 WINED3DPTFILTERCAPS_MIPNEAREST |
2309 WINED3DPTFILTERCAPS_NEAREST;
2311 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2312 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2313 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2316 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2317 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2318 WINED3DPTFILTERCAPS_MAGFPOINT |
2319 WINED3DPTFILTERCAPS_MINFLINEAR |
2320 WINED3DPTFILTERCAPS_MINFPOINT |
2321 WINED3DPTFILTERCAPS_MIPFLINEAR |
2322 WINED3DPTFILTERCAPS_MIPFPOINT |
2323 WINED3DPTFILTERCAPS_LINEAR |
2324 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2325 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2326 WINED3DPTFILTERCAPS_MIPLINEAR |
2327 WINED3DPTFILTERCAPS_MIPNEAREST |
2328 WINED3DPTFILTERCAPS_NEAREST;
2330 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2331 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2332 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2334 } else
2335 *pCaps->CubeTextureFilterCaps = 0;
2337 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2338 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2339 WINED3DPTFILTERCAPS_MAGFPOINT |
2340 WINED3DPTFILTERCAPS_MINFLINEAR |
2341 WINED3DPTFILTERCAPS_MINFPOINT |
2342 WINED3DPTFILTERCAPS_MIPFLINEAR |
2343 WINED3DPTFILTERCAPS_MIPFPOINT |
2344 WINED3DPTFILTERCAPS_LINEAR |
2345 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2346 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2347 WINED3DPTFILTERCAPS_MIPLINEAR |
2348 WINED3DPTFILTERCAPS_MIPNEAREST |
2349 WINED3DPTFILTERCAPS_NEAREST;
2350 } else
2351 *pCaps->VolumeTextureFilterCaps = 0;
2353 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2354 WINED3DPTADDRESSCAPS_CLAMP |
2355 WINED3DPTADDRESSCAPS_WRAP;
2357 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2358 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2360 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2361 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2363 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2364 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2367 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2368 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2369 WINED3DPTADDRESSCAPS_CLAMP |
2370 WINED3DPTADDRESSCAPS_WRAP;
2371 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2372 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2374 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2375 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2377 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2378 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2380 } else
2381 *pCaps->VolumeTextureAddressCaps = 0;
2383 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2384 WINED3DLINECAPS_ZTEST;
2385 /* FIXME: Add
2386 WINED3DLINECAPS_BLEND
2387 WINED3DLINECAPS_ALPHACMP
2388 WINED3DLINECAPS_FOG */
2390 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2391 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2393 if(GL_SUPPORT(EXT_TEXTURE3D))
2394 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2395 else
2396 *pCaps->MaxVolumeExtent = 0;
2398 *pCaps->MaxTextureRepeat = 32768;
2399 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2400 *pCaps->MaxVertexW = 1.0;
2402 *pCaps->GuardBandLeft = 0;
2403 *pCaps->GuardBandTop = 0;
2404 *pCaps->GuardBandRight = 0;
2405 *pCaps->GuardBandBottom = 0;
2407 *pCaps->ExtentsAdjust = 0;
2409 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2410 WINED3DSTENCILCAPS_INCRSAT |
2411 WINED3DSTENCILCAPS_INVERT |
2412 WINED3DSTENCILCAPS_KEEP |
2413 WINED3DSTENCILCAPS_REPLACE |
2414 WINED3DSTENCILCAPS_ZERO;
2415 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2416 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2417 WINED3DSTENCILCAPS_INCR;
2419 if ( This->dxVersion > 8 &&
2420 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2421 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2422 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2425 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2427 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2428 WINED3DTEXOPCAPS_ADDSIGNED |
2429 WINED3DTEXOPCAPS_ADDSIGNED2X |
2430 WINED3DTEXOPCAPS_MODULATE |
2431 WINED3DTEXOPCAPS_MODULATE2X |
2432 WINED3DTEXOPCAPS_MODULATE4X |
2433 WINED3DTEXOPCAPS_SELECTARG1 |
2434 WINED3DTEXOPCAPS_SELECTARG2 |
2435 WINED3DTEXOPCAPS_DISABLE;
2437 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2438 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2439 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2440 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2441 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2442 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2443 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2444 WINED3DTEXOPCAPS_LERP |
2445 WINED3DTEXOPCAPS_SUBTRACT;
2447 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2448 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2449 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2450 WINED3DTEXOPCAPS_MULTIPLYADD |
2451 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2452 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2453 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2455 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2456 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2458 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2459 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2460 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2463 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2464 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2465 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2466 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2467 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2468 * and 3D textures. It also allows us to keep the code simpler by having texture
2469 * shaders constantly enabled.
2471 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2472 /* TODO: Luminance bump map? */
2474 #if 0
2475 /* FIXME: Add
2476 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2477 WINED3DTEXOPCAPS_PREMODULATE */
2478 #endif
2480 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2481 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2482 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2483 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2485 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2486 *pCaps->MaxVertexBlendMatrixIndex = 0;
2488 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2489 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2492 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2493 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2494 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2495 WINED3DVTXPCAPS_LOCALVIEWER |
2496 WINED3DVTXPCAPS_VERTEXFOG |
2497 WINED3DVTXPCAPS_TEXGEN;
2498 /* FIXME: Add
2499 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2501 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2502 *pCaps->MaxVertexIndex = 0xFFFFF;
2503 *pCaps->MaxStreams = MAX_STREAMS;
2504 *pCaps->MaxStreamStride = 1024;
2506 if (vs_selected_mode == SHADER_GLSL) {
2507 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2508 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2509 * vs_nv_version which is based on NV_vertex_program.
2510 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2511 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2512 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2513 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2514 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2515 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2516 else
2517 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2518 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2519 } else if (vs_selected_mode == SHADER_ARB) {
2520 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2521 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2522 } else {
2523 *pCaps->VertexShaderVersion = 0;
2524 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2527 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2529 if (ps_selected_mode == SHADER_GLSL) {
2530 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2531 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2532 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2533 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2534 * in max native instructions. Intel and others also offer the info in this extension but they
2535 * don't support GLSL (at least on Windows).
2537 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number
2538 * of instructions is 512 or less we have to do with ps2.0 hardware.
2539 * 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.
2541 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2542 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2543 else
2544 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2545 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2546 * Direct3D minimum requirement.
2548 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2549 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2551 * The problem is that the refrast clamps temporary results in the shader to
2552 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2553 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2554 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2555 * offer a way to query this.
2557 *pCaps->PixelShader1xMaxValue = 8.0;
2558 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2559 } else if (ps_selected_mode == SHADER_ARB) {
2560 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2561 *pCaps->PixelShader1xMaxValue = 8.0;
2562 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2563 } else {
2564 *pCaps->PixelShaderVersion = 0;
2565 *pCaps->PixelShader1xMaxValue = 0.0;
2566 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2569 /* ------------------------------------------------
2570 The following fields apply to d3d9 only
2571 ------------------------------------------------ */
2572 if (This->dxVersion > 8) {
2573 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2574 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2575 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2576 *pCaps->MaxNpatchTessellationLevel = 0;
2577 *pCaps->MasterAdapterOrdinal = 0;
2578 *pCaps->AdapterOrdinalInGroup = 0;
2579 *pCaps->NumberOfAdaptersInGroup = 1;
2581 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2582 /* OpenGL supports all the formats below, perhaps not always
2583 * without conversion, but it supports them.
2584 * Further GLSL doesn't seem to have an official unsigned type so
2585 * don't advertise it yet as I'm not sure how we handle it.
2586 * We might need to add some clamping in the shader engine to
2587 * support it.
2588 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2589 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2590 WINED3DDTCAPS_UBYTE4N |
2591 WINED3DDTCAPS_SHORT2N |
2592 WINED3DDTCAPS_SHORT4N;
2593 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2594 *pCaps->DeclTypes |=
2595 WINED3DDTCAPS_FLOAT16_2 |
2596 WINED3DDTCAPS_FLOAT16_4;
2598 } else
2599 *pCaps->DeclTypes = 0;
2601 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2604 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2605 WINED3DPTFILTERCAPS_MAGFPOINT |
2606 WINED3DPTFILTERCAPS_MINFLINEAR |
2607 WINED3DPTFILTERCAPS_MAGFLINEAR;
2608 *pCaps->VertexTextureFilterCaps = 0;
2610 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2611 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2612 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2613 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2614 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2615 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2616 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2618 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2619 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2620 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2621 *pCaps->VS20Caps.Caps = 0;
2622 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2623 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2624 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2626 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2627 *pCaps->MaxVertexShader30InstructionSlots = 0;
2628 } else { /* VS 1.x */
2629 *pCaps->VS20Caps.Caps = 0;
2630 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2631 *pCaps->VS20Caps.NumTemps = 0;
2632 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2634 *pCaps->MaxVShaderInstructionsExecuted = 0;
2635 *pCaps->MaxVertexShader30InstructionSlots = 0;
2638 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2639 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2640 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2642 /* 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 */
2643 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2644 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2645 WINED3DPS20CAPS_PREDICATION |
2646 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2647 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2648 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2649 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2650 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2651 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2653 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2654 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2655 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2656 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2657 *pCaps->PS20Caps.Caps = 0;
2658 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2659 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2660 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2661 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2663 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2664 *pCaps->MaxPixelShader30InstructionSlots = 0;
2665 } else { /* PS 1.x */
2666 *pCaps->PS20Caps.Caps = 0;
2667 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2668 *pCaps->PS20Caps.NumTemps = 0;
2669 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2670 *pCaps->PS20Caps.NumInstructionSlots = 0;
2672 *pCaps->MaxPShaderInstructionsExecuted = 0;
2673 *pCaps->MaxPixelShader30InstructionSlots = 0;
2677 return WINED3D_OK;
2680 static unsigned int glsl_program_key_hash(void *key) {
2681 glsl_program_key_t *k = (glsl_program_key_t *)key;
2683 unsigned int hash = k->vshader | k->pshader << 16;
2684 hash += ~(hash << 15);
2685 hash ^= (hash >> 10);
2686 hash += (hash << 3);
2687 hash ^= (hash >> 6);
2688 hash += ~(hash << 11);
2689 hash ^= (hash >> 16);
2691 return hash;
2694 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2695 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2696 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2698 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2701 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2702 and fields being inserted in the middle, a new structure is used in place */
2703 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2704 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2705 IUnknown *parent) {
2707 IWineD3DDeviceImpl *object = NULL;
2708 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2709 WINED3DDISPLAYMODE mode;
2710 int i;
2712 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2713 * number and create a device without a 3D adapter for 2D only operation.
2715 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2716 return WINED3DERR_INVALIDCALL;
2719 /* Create a WineD3DDevice object */
2720 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2721 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2722 TRACE("Created WineD3DDevice object @ %p\n", object);
2723 if (NULL == object) {
2724 return WINED3DERR_OUTOFVIDEOMEMORY;
2727 /* Set up initial COM information */
2728 object->lpVtbl = &IWineD3DDevice_Vtbl;
2729 object->ref = 1;
2730 object->wineD3D = iface;
2731 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2732 IWineD3D_AddRef(object->wineD3D);
2733 object->parent = parent;
2734 list_init(&object->resources);
2736 if(This->dxVersion == 7) {
2737 object->surface_alignment = 8;
2738 } else {
2739 object->surface_alignment = 4;
2741 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2743 /* Set the state up as invalid until the device is fully created */
2744 object->state = WINED3DERR_DRIVERINTERNALERROR;
2746 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2747 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2749 /* Save the creation parameters */
2750 object->createParms.AdapterOrdinal = Adapter;
2751 object->createParms.DeviceType = DeviceType;
2752 object->createParms.hFocusWindow = hFocusWindow;
2753 object->createParms.BehaviorFlags = BehaviourFlags;
2755 /* Initialize other useful values */
2756 object->adapterNo = Adapter;
2757 object->devType = DeviceType;
2759 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2760 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2761 object->shader_backend = &glsl_shader_backend;
2762 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2763 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2764 object->shader_backend = &arb_program_shader_backend;
2765 } else {
2766 object->shader_backend = &none_shader_backend;
2769 /* set the state of the device to valid */
2770 object->state = WINED3D_OK;
2772 /* Get the initial screen setup for ddraw */
2773 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
2775 object->ddraw_width = mode.Width;
2776 object->ddraw_height = mode.Height;
2777 object->ddraw_format = mode.Format;
2779 for(i = 0; i < PATCHMAP_SIZE; i++) {
2780 list_init(&object->patches[i]);
2782 return WINED3D_OK;
2784 #undef GLINFO_LOCATION
2786 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2787 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2788 IUnknown_AddRef(This->parent);
2789 *pParent = This->parent;
2790 return WINED3D_OK;
2793 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2794 IUnknown* surfaceParent;
2795 TRACE("(%p) call back\n", pSurface);
2797 /* Now, release the parent, which will take care of cleaning up the surface for us */
2798 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2799 IUnknown_Release(surfaceParent);
2800 return IUnknown_Release(surfaceParent);
2803 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2804 IUnknown* volumeParent;
2805 TRACE("(%p) call back\n", pVolume);
2807 /* Now, release the parent, which will take care of cleaning up the volume for us */
2808 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2809 IUnknown_Release(volumeParent);
2810 return IUnknown_Release(volumeParent);
2813 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2814 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2815 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2816 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2818 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2819 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2820 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2821 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2822 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
2823 * the chance that other implementations support them is rather small since Win32 QuickTime uses
2824 * DirectDraw, not OpenGL.
2826 if(gl_info->supported[APPLE_FENCE] &&
2827 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2828 gl_info->supported[APPLE_FLUSH_RENDER] &&
2829 gl_info->supported[APPLE_YCBCR_422]) {
2830 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2831 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2832 return TRUE;
2833 } else {
2834 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2835 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2836 return FALSE;
2840 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2841 if(implementation_is_apple(gl_info)) {
2842 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
2843 * used it falls back to software. While the compiler can detect if the shader uses all declared
2844 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2845 * using relative addressing falls back to software.
2847 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2849 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2850 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2851 } else {
2852 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2853 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2854 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2857 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2858 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2859 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2860 * flag for this extension
2862 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2863 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2864 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2865 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2866 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2867 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2868 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2872 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
2873 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
2874 * and opengl feedback mode, but some GL implementations(MacOS ATI at least, propably all macos ones)
2875 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
2876 * according to the spec.
2878 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
2879 * makes the shader slower and eats instruction slots which should be available to the d3d app.
2881 if(gl_info->gl_vendor == VENDOR_INTEL) {
2882 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
2883 gl_info->set_texcoord_w = TRUE;
2888 void invalid_func(void *data) {
2889 ERR("Invalid vertex attribute function called\n");
2890 DebugBreak();
2893 #define GLINFO_LOCATION (Adapters[0].gl_info)
2895 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
2896 * the extension detection and are used in drawStridedSlow
2898 static void position_d3dcolor(void *data) {
2899 DWORD pos = *((DWORD *) data);
2901 FIXME("Add a test for fixed function position from d3dcolor type\n");
2902 glVertex4s(D3DCOLOR_B_R(pos),
2903 D3DCOLOR_B_G(pos),
2904 D3DCOLOR_B_B(pos),
2905 D3DCOLOR_B_A(pos));
2907 static void position_float4(void *data) {
2908 GLfloat *pos = (float *) data;
2910 if (pos[3] < eps && pos[3] > -eps)
2911 glVertex3fv(pos);
2912 else {
2913 float w = 1.0 / pos[3];
2915 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
2919 static void diffuse_d3dcolor(void *data) {
2920 DWORD diffuseColor = *((DWORD *) data);
2922 glColor4ub(D3DCOLOR_B_R(diffuseColor),
2923 D3DCOLOR_B_G(diffuseColor),
2924 D3DCOLOR_B_B(diffuseColor),
2925 D3DCOLOR_B_A(diffuseColor));
2928 static void specular_d3dcolor(void *data) {
2929 DWORD specularColor = *((DWORD *) data);
2931 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
2932 D3DCOLOR_B_G(specularColor),
2933 D3DCOLOR_B_B(specularColor));
2935 static void warn_no_specular_func(void *data) {
2936 WARN("GL_EXT_secondary_color not supported\n");
2939 void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
2940 position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2941 position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2942 position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv;
2943 position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4;
2944 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor;
2945 position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2946 position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2947 position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv;
2948 position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
2949 position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2950 position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
2951 position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2952 position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
2953 position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2954 position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2955 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2956 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2958 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2959 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2960 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv;
2961 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv;
2962 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor;
2963 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2964 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2965 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
2966 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv;
2967 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2968 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv;
2969 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2970 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv;
2971 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2972 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
2973 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
2974 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
2976 /* No 4 component entry points here */
2977 specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
2978 specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
2979 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2980 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT);
2981 } else {
2982 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
2984 specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func;
2985 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2986 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor;
2987 } else {
2988 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
2990 specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
2991 specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
2992 specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
2993 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
2994 specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
2995 specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
2996 specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
2997 specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
2998 specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
2999 specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3000 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3001 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3003 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
3004 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
3006 normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3007 normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3008 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv;
3009 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */
3010 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func;
3011 normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3012 normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3013 normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3014 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3015 normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3016 normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3017 normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3018 normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3019 normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3020 normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3021 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3022 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3025 #define PUSH1(att) attribs[nAttribs++] = (att);
3026 BOOL InitAdapters(void) {
3027 static HMODULE mod_gl;
3028 BOOL ret;
3029 int ps_selected_mode, vs_selected_mode;
3031 /* No need to hold any lock. The calling library makes sure only one thread calls
3032 * wined3d simultaneously
3034 if(numAdapters > 0) return TRUE;
3036 TRACE("Initializing adapters\n");
3038 if(!mod_gl) {
3039 #ifdef USE_WIN32_OPENGL
3040 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
3041 mod_gl = LoadLibraryA("opengl32.dll");
3042 if(!mod_gl) {
3043 ERR("Can't load opengl32.dll!\n");
3044 return FALSE;
3046 #else
3047 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
3048 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
3049 mod_gl = GetModuleHandleA("gdi32.dll");
3050 #endif
3053 /* Load WGL core functions from opengl32.dll */
3054 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
3055 WGL_FUNCS_GEN;
3056 #undef USE_WGL_FUNC
3058 if(!pwglGetProcAddress) {
3059 ERR("Unable to load wglGetProcAddress!\n");
3060 return FALSE;
3063 /* Dynamically load all GL core functions */
3064 GL_FUNCS_GEN;
3065 #undef USE_GL_FUNC
3067 /* For now only one default adapter */
3069 int iPixelFormat;
3070 int attribs[8];
3071 int values[8];
3072 int nAttribs = 0;
3073 int res;
3074 WineD3D_PixelFormat *cfgs;
3075 int attribute;
3076 DISPLAY_DEVICEW DisplayDevice;
3077 HDC hdc;
3079 TRACE("Initializing default adapter\n");
3080 Adapters[0].num = 0;
3081 Adapters[0].monitorPoint.x = -1;
3082 Adapters[0].monitorPoint.y = -1;
3084 if (!WineD3D_CreateFakeGLContext()) {
3085 ERR("Failed to get a gl context for default adapter\n");
3086 HeapFree(GetProcessHeap(), 0, Adapters);
3087 WineD3D_ReleaseFakeGLContext();
3088 return FALSE;
3091 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
3092 if(!ret) {
3093 ERR("Failed to initialize gl caps for default adapter\n");
3094 HeapFree(GetProcessHeap(), 0, Adapters);
3095 WineD3D_ReleaseFakeGLContext();
3096 return FALSE;
3098 ret = initPixelFormats(&Adapters[0].gl_info);
3099 if(!ret) {
3100 ERR("Failed to init gl formats\n");
3101 HeapFree(GetProcessHeap(), 0, Adapters);
3102 WineD3D_ReleaseFakeGLContext();
3103 return FALSE;
3106 hdc = pwglGetCurrentDC();
3107 if(!hdc) {
3108 ERR("Failed to get gl HDC\n");
3109 HeapFree(GetProcessHeap(), 0, Adapters);
3110 WineD3D_ReleaseFakeGLContext();
3111 return FALSE;
3114 Adapters[0].driver = "Display";
3115 Adapters[0].description = "Direct3D HAL";
3117 /* Use the VideoRamSize registry setting when set */
3118 if(wined3d_settings.emulated_textureram)
3119 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
3120 else
3121 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
3122 Adapters[0].UsedTextureRam = 0;
3123 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
3125 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
3126 DisplayDevice.cb = sizeof(DisplayDevice);
3127 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
3128 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
3129 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
3131 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
3132 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
3134 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
3135 cfgs = Adapters[0].cfgs;
3136 PUSH1(WGL_RED_BITS_ARB)
3137 PUSH1(WGL_GREEN_BITS_ARB)
3138 PUSH1(WGL_BLUE_BITS_ARB)
3139 PUSH1(WGL_ALPHA_BITS_ARB)
3140 PUSH1(WGL_DEPTH_BITS_ARB)
3141 PUSH1(WGL_STENCIL_BITS_ARB)
3143 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
3144 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
3146 if(!res)
3147 continue;
3149 /* Cache the pixel format */
3150 cfgs->iPixelFormat = iPixelFormat;
3151 cfgs->redSize = values[0];
3152 cfgs->greenSize = values[1];
3153 cfgs->blueSize = values[2];
3154 cfgs->alphaSize = values[3];
3155 cfgs->depthSize = values[4];
3156 cfgs->stencilSize = values[5];
3158 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);
3159 cfgs++;
3161 WineD3D_ReleaseFakeGLContext();
3163 fixup_extensions(&Adapters[0].gl_info);
3165 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
3166 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3167 fillGLAttribFuncs(&Adapters[0].gl_info);
3168 init_type_lookup(&Adapters[0].gl_info);
3170 numAdapters = 1;
3171 TRACE("%d adapters successfully initialized\n", numAdapters);
3173 return TRUE;
3175 #undef PUSH1
3176 #undef GLINFO_LOCATION
3178 /**********************************************************
3179 * IWineD3D VTbl follows
3180 **********************************************************/
3182 const IWineD3DVtbl IWineD3D_Vtbl =
3184 /* IUnknown */
3185 IWineD3DImpl_QueryInterface,
3186 IWineD3DImpl_AddRef,
3187 IWineD3DImpl_Release,
3188 /* IWineD3D */
3189 IWineD3DImpl_GetParent,
3190 IWineD3DImpl_GetAdapterCount,
3191 IWineD3DImpl_RegisterSoftwareDevice,
3192 IWineD3DImpl_GetAdapterMonitor,
3193 IWineD3DImpl_GetAdapterModeCount,
3194 IWineD3DImpl_EnumAdapterModes,
3195 IWineD3DImpl_GetAdapterDisplayMode,
3196 IWineD3DImpl_GetAdapterIdentifier,
3197 IWineD3DImpl_CheckDeviceMultiSampleType,
3198 IWineD3DImpl_CheckDepthStencilMatch,
3199 IWineD3DImpl_CheckDeviceType,
3200 IWineD3DImpl_CheckDeviceFormat,
3201 IWineD3DImpl_CheckDeviceFormatConversion,
3202 IWineD3DImpl_GetDeviceCaps,
3203 IWineD3DImpl_CreateDevice