wined3d: Honor the driver's min point size.
[wine/multimedia.git] / dlls / wined3d / directx.c
blobcff6550f22f70d2d64d63469ed9df4c46aa29205
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 } EXTENSION_MAP[] = {
44 /* APPLE */
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
48 /* ATI */
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP},
54 /* ARB */
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL},
59 {"GL_ARB_imaging", ARB_IMAGING},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER},
80 /* EXT */
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING},
102 /* NV */
103 {"GL_NV_half_float", NV_HALF_FLOAT},
104 {"GL_NV_fence", NV_FENCE},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
120 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP},
122 /* SGI */
123 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP},
126 /**********************************************************
127 * Utility functions follow
128 **********************************************************/
130 /* Adapters */
131 static int numAdapters = 0;
132 static struct WineD3DAdapter Adapters[1];
134 /* lookup tables */
135 int minLookup[MAX_LOOKUPS];
136 int maxLookup[MAX_LOOKUPS];
137 DWORD *stateLookup[MAX_LOOKUPS];
139 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
143 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
144 * ie there is no GL Context - Get a default rendering context to enable the
145 * function query some info from GL
148 static int wined3d_fake_gl_context_ref = 0;
149 static BOOL wined3d_fake_gl_context_foreign;
150 static BOOL wined3d_fake_gl_context_available = FALSE;
151 static HDC wined3d_fake_gl_context_hdc = NULL;
152 static HWND wined3d_fake_gl_context_hwnd = NULL;
154 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
155 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
157 0, 0, &wined3d_fake_gl_context_cs,
158 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
159 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
160 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
162 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
164 static void WineD3D_ReleaseFakeGLContext(void) {
165 HGLRC glCtx;
167 EnterCriticalSection(&wined3d_fake_gl_context_cs);
169 if(!wined3d_fake_gl_context_available) {
170 TRACE_(d3d_caps)("context not available\n");
171 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
172 return;
175 glCtx = pwglGetCurrentContext();
177 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
178 if (0 == (--wined3d_fake_gl_context_ref) ) {
179 if(!wined3d_fake_gl_context_foreign && glCtx) {
180 TRACE_(d3d_caps)("destroying fake GL context\n");
181 pwglMakeCurrent(NULL, NULL);
182 pwglDeleteContext(glCtx);
184 if(wined3d_fake_gl_context_hdc)
185 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
186 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
187 if(wined3d_fake_gl_context_hwnd)
188 DestroyWindow(wined3d_fake_gl_context_hwnd);
189 wined3d_fake_gl_context_hwnd = NULL;
190 wined3d_fake_gl_context_available = FALSE;
192 assert(wined3d_fake_gl_context_ref >= 0);
194 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
197 static BOOL WineD3D_CreateFakeGLContext(void) {
198 HGLRC glCtx = NULL;
200 EnterCriticalSection(&wined3d_fake_gl_context_cs);
202 TRACE("getting context...\n");
203 if(wined3d_fake_gl_context_ref > 0) goto ret;
204 assert(0 == wined3d_fake_gl_context_ref);
206 wined3d_fake_gl_context_foreign = TRUE;
208 glCtx = pwglGetCurrentContext();
209 if (!glCtx) {
210 PIXELFORMATDESCRIPTOR pfd;
211 int iPixelFormat;
213 wined3d_fake_gl_context_foreign = FALSE;
215 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
216 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
217 if(!wined3d_fake_gl_context_hwnd) {
218 ERR("HWND creation failed!\n");
219 goto fail;
221 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
222 if(!wined3d_fake_gl_context_hdc) {
223 ERR("GetDC failed!\n");
224 goto fail;
227 /* PixelFormat selection */
228 ZeroMemory(&pfd, sizeof(pfd));
229 pfd.nSize = sizeof(pfd);
230 pfd.nVersion = 1;
231 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
232 pfd.iPixelType = PFD_TYPE_RGBA;
233 pfd.cColorBits = 32;
234 pfd.iLayerType = PFD_MAIN_PLANE;
236 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
237 if(!iPixelFormat) {
238 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
239 ERR("Can't find a suitable iPixelFormat\n");
240 goto fail;
242 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
243 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
245 /* Create a GL context */
246 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
247 if (!glCtx) {
248 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
249 goto fail;
252 /* Make it the current GL context */
253 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
254 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
255 goto fail;
259 ret:
260 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
261 wined3d_fake_gl_context_ref++;
262 wined3d_fake_gl_context_available = TRUE;
263 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
264 return TRUE;
265 fail:
266 if(wined3d_fake_gl_context_hdc)
267 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
268 wined3d_fake_gl_context_hdc = NULL;
269 if(wined3d_fake_gl_context_hwnd)
270 DestroyWindow(wined3d_fake_gl_context_hwnd);
271 wined3d_fake_gl_context_hwnd = NULL;
272 if(glCtx) pwglDeleteContext(glCtx);
273 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
274 return FALSE;
277 /* Adjust the amount of used texture memory */
278 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
279 UINT Adapter = D3DDevice->adapterNo;
281 Adapters[Adapter].UsedTextureRam += glram;
282 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
283 return Adapters[Adapter].UsedTextureRam;
286 /**********************************************************
287 * IUnknown parts follows
288 **********************************************************/
290 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
294 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
295 if (IsEqualGUID(riid, &IID_IUnknown)
296 || IsEqualGUID(riid, &IID_IWineD3DBase)
297 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
298 IUnknown_AddRef(iface);
299 *ppobj = This;
300 return S_OK;
302 *ppobj = NULL;
303 return E_NOINTERFACE;
306 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
307 IWineD3DImpl *This = (IWineD3DImpl *)iface;
308 ULONG refCount = InterlockedIncrement(&This->ref);
310 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
311 return refCount;
314 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
315 IWineD3DImpl *This = (IWineD3DImpl *)iface;
316 ULONG ref;
317 TRACE("(%p) : Releasing from %d\n", This, This->ref);
318 ref = InterlockedDecrement(&This->ref);
319 if (ref == 0) {
320 HeapFree(GetProcessHeap(), 0, This);
323 return ref;
326 /* Set the shader type for this device, depending on the given capabilities,
327 * the device type, and the user preferences in wined3d_settings */
329 static void select_shader_mode(
330 WineD3D_GL_Info *gl_info,
331 WINED3DDEVTYPE DeviceType,
332 int* ps_selected,
333 int* vs_selected) {
335 if (wined3d_settings.vs_mode == VS_NONE) {
336 *vs_selected = SHADER_NONE;
337 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
338 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
339 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
340 * shaders only on this card. */
341 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
342 *vs_selected = SHADER_ARB;
343 else
344 *vs_selected = SHADER_GLSL;
345 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
346 *vs_selected = SHADER_ARB;
347 } else {
348 *vs_selected = SHADER_NONE;
351 if (wined3d_settings.ps_mode == PS_NONE) {
352 *ps_selected = SHADER_NONE;
353 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
354 *ps_selected = SHADER_GLSL;
355 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
356 *ps_selected = SHADER_ARB;
357 } else {
358 *ps_selected = SHADER_NONE;
362 /** Select the number of report maximum shader constants based on the selected shader modes */
363 static void select_shader_max_constants(
364 int ps_selected_mode,
365 int vs_selected_mode,
366 WineD3D_GL_Info *gl_info) {
368 switch (vs_selected_mode) {
369 case SHADER_GLSL:
370 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
371 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
372 break;
373 case SHADER_ARB:
374 /* We have to subtract any other PARAMs that we might use in our shader programs.
375 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
376 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
377 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
378 break;
379 default:
380 gl_info->max_vshader_constantsF = 0;
381 break;
384 switch (ps_selected_mode) {
385 case SHADER_GLSL:
386 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
387 * In theory the texbem instruction may need one more shader constant too. But lets assume
388 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
389 * and lets not take away a uniform needlessly from all other shaders.
391 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
392 break;
393 case SHADER_ARB:
394 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
395 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
397 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
398 break;
399 default:
400 gl_info->max_pshader_constantsF = 0;
401 break;
405 /**********************************************************
406 * IWineD3D parts follows
407 **********************************************************/
409 #define GLINFO_LOCATION (*gl_info)
410 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
411 GLuint prog;
412 BOOL ret = FALSE;
413 const char *testcode =
414 "!!ARBvp1.0\n"
415 "PARAM C[66] = { program.env[0..65] };\n"
416 "ADDRESS A0;"
417 "ARL A0.x, 0.0;\n"
418 "MOV result.position, C[A0.x + 65];\n"
419 "END\n";
421 while(glGetError());
422 GL_EXTCALL(glGenProgramsARB(1, &prog));
423 if(!prog) {
424 ERR("Failed to create an ARB offset limit test program\n");
426 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
427 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
428 strlen(testcode), testcode));
429 if(glGetError() != 0) {
430 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
431 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
432 ret = TRUE;
433 } else TRACE("OpenGL implementation allows offsets > 63\n");
435 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
436 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
437 checkGLcall("ARB vp offset limit test cleanup\n");
439 return ret;
442 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
443 const char *GL_Extensions = NULL;
444 const char *WGL_Extensions = NULL;
445 const char *gl_string = NULL;
446 const char *gl_string_cursor = NULL;
447 GLint gl_max;
448 GLfloat gl_floatv[2];
449 int major = 1, minor = 0;
450 BOOL return_value = TRUE;
451 int i;
452 HDC hdc;
453 unsigned int vidmem=0;
455 TRACE_(d3d_caps)("(%p)\n", gl_info);
457 ENTER_GL();
459 gl_string = (const char *) glGetString(GL_RENDERER);
460 if (NULL == gl_string)
461 gl_string = "None";
462 strcpy(gl_info->gl_renderer, gl_string);
464 gl_string = (const char *) glGetString(GL_VENDOR);
465 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
466 if (gl_string != NULL) {
467 /* Fill in the GL vendor */
468 if (strstr(gl_string, "NVIDIA")) {
469 gl_info->gl_vendor = VENDOR_NVIDIA;
470 } else if (strstr(gl_string, "ATI")) {
471 gl_info->gl_vendor = VENDOR_ATI;
472 } else if (strstr(gl_string, "Intel(R)") ||
473 strstr(gl_info->gl_renderer, "Intel(R)")) {
474 gl_info->gl_vendor = VENDOR_INTEL;
475 } else if (strstr(gl_string, "Mesa")) {
476 gl_info->gl_vendor = VENDOR_MESA;
477 } else {
478 gl_info->gl_vendor = VENDOR_WINE;
480 } else {
481 gl_info->gl_vendor = VENDOR_WINE;
485 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
487 /* Parse the GL_VERSION field into major and minor information */
488 gl_string = (const char *) glGetString(GL_VERSION);
489 if (gl_string != NULL) {
491 switch (gl_info->gl_vendor) {
492 case VENDOR_NVIDIA:
493 gl_string_cursor = strstr(gl_string, "NVIDIA");
494 if (!gl_string_cursor) {
495 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
496 break;
499 gl_string_cursor = strstr(gl_string_cursor, " ");
500 if (!gl_string_cursor) {
501 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
502 break;
505 while (*gl_string_cursor == ' ') {
506 ++gl_string_cursor;
509 if (!*gl_string_cursor) {
510 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
511 break;
514 major = atoi(gl_string_cursor);
515 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
516 ++gl_string_cursor;
519 if (*gl_string_cursor++ != '.') {
520 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
521 break;
524 minor = atoi(gl_string_cursor);
525 minor = major*100+minor;
526 major = 10;
528 break;
530 case VENDOR_ATI:
531 major = minor = 0;
532 gl_string_cursor = strchr(gl_string, '-');
533 if (gl_string_cursor) {
534 int error = 0;
535 gl_string_cursor++;
537 /* Check if version number is of the form x.y.z */
538 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
539 error = 1;
540 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
541 error = 1;
542 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
543 error = 1;
544 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
545 error = 1;
547 /* Mark version number as malformed */
548 if (error)
549 gl_string_cursor = 0;
552 if (!gl_string_cursor)
553 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
554 else {
555 major = *gl_string_cursor - '0';
556 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
558 break;
560 case VENDOR_INTEL:
561 case VENDOR_MESA:
562 gl_string_cursor = strstr(gl_string, "Mesa");
563 gl_string_cursor = strstr(gl_string_cursor, " ");
564 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
565 if (*gl_string_cursor) {
566 char tmp[16];
567 int cursor = 0;
569 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
570 tmp[cursor++] = *gl_string_cursor;
571 ++gl_string_cursor;
573 tmp[cursor] = 0;
574 major = atoi(tmp);
576 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
577 ++gl_string_cursor;
579 cursor = 0;
580 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
581 tmp[cursor++] = *gl_string_cursor;
582 ++gl_string_cursor;
584 tmp[cursor] = 0;
585 minor = atoi(tmp);
587 break;
589 default:
590 major = 0;
591 minor = 9;
593 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
594 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
597 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
600 * Initialize openGL extension related variables
601 * with Default values
603 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
604 gl_info->max_buffers = 1;
605 gl_info->max_textures = 1;
606 gl_info->max_texture_stages = 1;
607 gl_info->max_fragment_samplers = 1;
608 gl_info->max_vertex_samplers = 0;
609 gl_info->max_combined_samplers = 0;
610 gl_info->max_sampler_stages = 1;
611 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
612 gl_info->ps_arb_max_temps = 0;
613 gl_info->ps_arb_max_instructions = 0;
614 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
615 gl_info->vs_arb_max_temps = 0;
616 gl_info->vs_arb_max_instructions = 0;
617 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
618 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
619 gl_info->vs_glsl_constantsF = 0;
620 gl_info->ps_glsl_constantsF = 0;
621 gl_info->vs_arb_constantsF = 0;
622 gl_info->ps_arb_constantsF = 0;
624 /* Now work out what GL support this card really has */
625 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
626 GL_EXT_FUNCS_GEN;
627 WGL_EXT_FUNCS_GEN;
628 #undef USE_GL_FUNC
630 /* Retrieve opengl defaults */
631 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
632 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
633 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
635 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
636 gl_info->max_lights = gl_max;
637 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
639 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
640 gl_info->max_texture_size = gl_max;
641 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
643 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
644 gl_info->max_pointsizemin = gl_floatv[0];
645 gl_info->max_pointsize = gl_floatv[1];
646 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
648 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
649 gl_info->max_aux_buffers = gl_max;
650 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
652 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
653 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
654 TRACE_(d3d_caps)("GL_Extensions reported:\n");
656 if (NULL == GL_Extensions) {
657 ERR(" GL_Extensions returns NULL\n");
658 } else {
659 while (*GL_Extensions != 0x00) {
660 const char *Start;
661 char ThisExtn[256];
662 size_t len;
664 while (isspace(*GL_Extensions)) GL_Extensions++;
665 Start = GL_Extensions;
666 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
667 GL_Extensions++;
670 len = GL_Extensions - Start;
671 if (len == 0 || len >= sizeof(ThisExtn))
672 continue;
674 memcpy(ThisExtn, Start, len);
675 ThisExtn[len] = '\0';
676 TRACE_(d3d_caps)("- %s\n", ThisExtn);
678 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
679 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
680 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
681 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
682 break;
687 if (gl_info->supported[APPLE_FENCE]) {
688 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
689 * The apple extension interacts with some other apple exts. Disable the NV
690 * extension if the apple one is support to prevent confusion in other parts
691 * of the code
693 gl_info->supported[NV_FENCE] = FALSE;
695 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
696 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
697 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
699 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
700 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
701 * Won't occur in any real world situation though
703 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
705 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
706 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
707 gl_info->max_buffers = gl_max;
708 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
710 if (gl_info->supported[ARB_MULTITEXTURE]) {
711 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
712 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
713 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
715 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
716 GLint tmp;
717 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
718 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
719 } else {
720 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
722 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
724 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
725 GLint tmp;
726 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
727 gl_info->max_fragment_samplers = min(8, tmp);
728 } else {
729 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
731 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
733 if (gl_info->supported[ARB_VERTEX_SHADER]) {
734 GLint tmp;
735 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
736 gl_info->max_vertex_samplers = tmp;
737 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
738 gl_info->max_combined_samplers = tmp;
739 } else {
740 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
742 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
743 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
745 if (gl_info->supported[ARB_VERTEX_BLEND]) {
746 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
747 gl_info->max_blends = gl_max;
748 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
750 if (gl_info->supported[EXT_TEXTURE3D]) {
751 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
752 gl_info->max_texture3d_size = gl_max;
753 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
755 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
756 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
757 gl_info->max_anisotropy = gl_max;
758 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
760 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
761 gl_info->ps_arb_version = PS_VERSION_11;
762 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
763 gl_info->ps_arb_constantsF = gl_max;
764 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
765 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
766 gl_info->ps_arb_max_temps = gl_max;
767 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
768 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
769 gl_info->ps_arb_max_instructions = gl_max;
770 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
772 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
773 gl_info->vs_arb_version = VS_VERSION_11;
774 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
775 gl_info->vs_arb_constantsF = gl_max;
776 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
777 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
778 gl_info->vs_arb_max_temps = gl_max;
779 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
780 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
781 gl_info->vs_arb_max_instructions = gl_max;
782 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
784 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
786 if (gl_info->supported[ARB_VERTEX_SHADER]) {
787 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
788 gl_info->vs_glsl_constantsF = gl_max / 4;
789 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
791 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
792 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
793 gl_info->ps_glsl_constantsF = gl_max / 4;
794 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
795 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
796 gl_info->max_glsl_varyings = gl_max;
797 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
799 if (gl_info->supported[EXT_VERTEX_SHADER]) {
800 gl_info->vs_ati_version = VS_VERSION_11;
802 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
803 gl_info->vs_nv_version = VS_VERSION_30;
804 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
805 gl_info->vs_nv_version = VS_VERSION_20;
806 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
807 gl_info->vs_nv_version = VS_VERSION_11;
808 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
809 gl_info->vs_nv_version = VS_VERSION_10;
811 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
812 gl_info->ps_nv_version = PS_VERSION_30;
813 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
814 gl_info->ps_nv_version = PS_VERSION_20;
818 checkGLcall("extension detection\n");
820 /* In some cases the number of texture stages can be larger than the number
821 * of samplers. The GF4 for example can use only 2 samplers (no fragment
822 * shaders), but 8 texture stages (register combiners). */
823 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
825 /* We can only use ORM_FBO when the hardware supports it. */
826 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
827 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
828 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
831 /* MRTs are currently only supported when FBOs are used. */
832 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
833 gl_info->max_buffers = 1;
836 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
837 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
838 * in case of the latest videocards in the number of pixel/vertex pipelines.
840 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
841 * rendering. Various games use this information to get a rough estimation of the features of the card
842 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
843 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
844 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
845 * not the PCI id.
847 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
848 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
849 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
850 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
851 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
852 * is used for rendering which is not always the case). This would work but it is not very portable. Second
853 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
854 * is limited.
856 * As said most games only use the PCI id to get an indication of the capabilities of the card.
857 * It doesn't really matter if the given id is the correct one if we return the id of a card with
858 * similar 3d features.
860 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
861 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
862 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
863 * won't pass we return a default card. This way is better than maintaining a full card database as even
864 * without a full database we can return a card with similar features. Second the size of the database
865 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
866 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
867 * to distinguishes between different models from that family.
869 * The code also selects a default amount of video memory which we will use for an estimation of the amount
870 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
871 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
872 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
873 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
874 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
875 * memory behind our backs if really needed.
876 * Note that the amout of video memory can be overruled using a registry setting.
878 switch (gl_info->gl_vendor) {
879 case VENDOR_NVIDIA:
880 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
881 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
883 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
884 /* Geforce8 - highend */
885 if (strstr(gl_info->gl_renderer, "8800")) {
886 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
887 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
889 /* Geforce8 - midend */
890 else if(strstr(gl_info->gl_renderer, "8600") ||
891 strstr(gl_info->gl_renderer, "8700"))
893 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
894 vidmem = 256;
896 /* Geforce8 - lowend */
897 else if(strstr(gl_info->gl_renderer, "8300") ||
898 strstr(gl_info->gl_renderer, "8400") ||
899 strstr(gl_info->gl_renderer, "8500"))
901 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
902 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
904 /* Geforce7 - highend */
905 else if(strstr(gl_info->gl_renderer, "7800") ||
906 strstr(gl_info->gl_renderer, "7900") ||
907 strstr(gl_info->gl_renderer, "7950") ||
908 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
909 strstr(gl_info->gl_renderer, "Quadro FX 5"))
911 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
912 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
914 /* Geforce7 midend / Geforce6 highend */
915 else if(strstr(gl_info->gl_renderer, "6800") ||
916 strstr(gl_info->gl_renderer, "7600") ||
917 strstr(gl_info->gl_renderer, "7700"))
919 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
920 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
922 /* Geforce6 - midend */
923 else if(strstr(gl_info->gl_renderer, "6600") ||
924 strstr(gl_info->gl_renderer, "6610") ||
925 strstr(gl_info->gl_renderer, "6700"))
927 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
928 vidmem = 128; /* A 6600GT has 128-256MB */
930 /* Geforce6/7 lowend */
931 else {
932 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
933 vidmem = 64; /* */
935 } else if(WINE_D3D9_CAPABLE(gl_info)) {
936 /* GeforceFX - highend */
937 if (strstr(gl_info->gl_renderer, "5800") ||
938 strstr(gl_info->gl_renderer, "5900") ||
939 strstr(gl_info->gl_renderer, "5950") ||
940 strstr(gl_info->gl_renderer, "Quadro FX"))
942 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
943 vidmem = 256; /* 5800-5900 cards use 256MB */
945 /* GeforceFX - midend */
946 else if(strstr(gl_info->gl_renderer, "5600") ||
947 strstr(gl_info->gl_renderer, "5650") ||
948 strstr(gl_info->gl_renderer, "5700") ||
949 strstr(gl_info->gl_renderer, "5750"))
951 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
952 vidmem = 128; /* A 5600 uses 128-256MB */
954 /* GeforceFX - lowend */
955 else {
956 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
957 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
959 } else if(WINE_D3D8_CAPABLE(gl_info)) {
960 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
961 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
962 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
964 else {
965 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
966 vidmem = 64; /* Geforce3 cards have 64-128MB */
968 } else if(WINE_D3D7_CAPABLE(gl_info)) {
969 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
970 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
971 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
973 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
974 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
975 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
977 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
978 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
979 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
981 else {
982 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
983 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
985 } else {
986 if (strstr(gl_info->gl_renderer, "TNT2")) {
987 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
988 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
990 else {
991 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
992 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
995 break;
996 case VENDOR_ATI:
997 if(WINE_D3D9_CAPABLE(gl_info)) {
998 /* Radeon R6xx HD2900 - highend */
999 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1000 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1001 vidmem = 512; /* HD2900 uses 512-1024MB */
1003 /* Radeon R6xx HD2600- midend */
1004 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1005 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1006 vidmem = 256; /* HD2600 uses 256-512MB */
1008 /* Radeon R6xx HD2300/HD2400 - lowend */
1009 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1010 strstr(gl_info->gl_renderer, "HD 2400"))
1012 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1013 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1015 /* Radeon R5xx */
1016 else if (strstr(gl_info->gl_renderer, "X1600") ||
1017 strstr(gl_info->gl_renderer, "X1650") ||
1018 strstr(gl_info->gl_renderer, "X1800") ||
1019 strstr(gl_info->gl_renderer, "X1900") ||
1020 strstr(gl_info->gl_renderer, "X1950"))
1022 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1023 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1025 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1026 else if(strstr(gl_info->gl_renderer, "X700") ||
1027 strstr(gl_info->gl_renderer, "X800") ||
1028 strstr(gl_info->gl_renderer, "X850") ||
1029 strstr(gl_info->gl_renderer, "X1300") ||
1030 strstr(gl_info->gl_renderer, "X1400") ||
1031 strstr(gl_info->gl_renderer, "X1450") ||
1032 strstr(gl_info->gl_renderer, "X1550"))
1034 gl_info->gl_card = CARD_ATI_RADEON_X700;
1035 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1037 /* Radeon R3xx */
1038 else {
1039 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1040 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1042 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1043 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1044 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1045 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1046 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1047 vidmem = 32; /* There are models with up to 64MB */
1048 } else
1049 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1050 vidmem = 16; /* There are 16-32MB models */
1051 break;
1052 case VENDOR_INTEL:
1053 if (strstr(gl_info->gl_renderer, "915GM")) {
1054 gl_info->gl_card = CARD_INTEL_I915GM;
1055 } else if (strstr(gl_info->gl_renderer, "915G")) {
1056 gl_info->gl_card = CARD_INTEL_I915G;
1057 } else if (strstr(gl_info->gl_renderer, "865G")) {
1058 gl_info->gl_card = CARD_INTEL_I865G;
1059 } else if (strstr(gl_info->gl_renderer, "855G")) {
1060 gl_info->gl_card = CARD_INTEL_I855G;
1061 } else if (strstr(gl_info->gl_renderer, "830G")) {
1062 gl_info->gl_card = CARD_INTEL_I830G;
1063 } else {
1064 gl_info->gl_card = CARD_INTEL_I915G;
1066 break;
1067 case VENDOR_MESA:
1068 case VENDOR_WINE:
1069 default:
1070 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1071 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1072 * them a good generic choice.
1074 gl_info->gl_vendor = VENDOR_NVIDIA;
1075 if(WINE_D3D9_CAPABLE(gl_info))
1076 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1077 else if(WINE_D3D8_CAPABLE(gl_info))
1078 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1079 else if(WINE_D3D7_CAPABLE(gl_info))
1080 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1081 else if(WINE_D3D6_CAPABLE(gl_info))
1082 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1083 else
1084 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1086 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1088 /* If we have an estimate use it, else default to 64MB; */
1089 if(vidmem)
1090 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1091 else
1092 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1094 /* Load all the lookup tables
1095 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1096 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1097 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1099 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1100 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1103 for (i = 0; i < MAX_LOOKUPS; i++) {
1104 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1107 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1108 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1109 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1110 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1111 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1112 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1113 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1114 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1115 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1116 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1118 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1119 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1120 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1121 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1122 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1125 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1126 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1127 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1128 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1129 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1130 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1131 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1132 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1133 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1134 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1135 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1136 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1137 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1139 /* TODO: config lookups */
1141 /* Make sure there's an active HDC else the WGL extensions will fail */
1142 hdc = pwglGetCurrentDC();
1143 if (hdc) {
1144 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1145 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1147 if (NULL == WGL_Extensions) {
1148 ERR(" WGL_Extensions returns NULL\n");
1149 } else {
1150 while (*WGL_Extensions != 0x00) {
1151 const char *Start;
1152 char ThisExtn[256];
1153 size_t len;
1155 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1156 Start = WGL_Extensions;
1157 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1158 WGL_Extensions++;
1161 len = WGL_Extensions - Start;
1162 if (len == 0 || len >= sizeof(ThisExtn))
1163 continue;
1165 memcpy(ThisExtn, Start, len);
1166 ThisExtn[len] = '\0';
1167 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1169 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1170 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1171 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1176 LEAVE_GL();
1178 return return_value;
1180 #undef GLINFO_LOCATION
1182 /**********************************************************
1183 * IWineD3D implementation follows
1184 **********************************************************/
1186 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1187 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1189 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1190 return numAdapters;
1193 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1194 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1195 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1196 return WINED3D_OK;
1199 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1200 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1202 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1203 return NULL;
1206 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1207 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1210 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1211 of the same bpp but different resolutions */
1213 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1214 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1215 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1216 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1218 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1219 return 0;
1222 /* TODO: Store modes per adapter and read it from the adapter structure */
1223 if (Adapter == 0) { /* Display */
1224 int i = 0;
1225 int j = 0;
1227 if (!DEBUG_SINGLE_MODE) {
1228 DEVMODEW DevModeW;
1230 ZeroMemory(&DevModeW, sizeof(DevModeW));
1231 DevModeW.dmSize = sizeof(DevModeW);
1232 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1233 j++;
1234 switch (Format)
1236 case WINED3DFMT_UNKNOWN:
1237 /* This is for D3D8, do not enumerate P8 here */
1238 if (DevModeW.dmBitsPerPel == 32 ||
1239 DevModeW.dmBitsPerPel == 16) i++;
1240 break;
1241 case WINED3DFMT_X8R8G8B8:
1242 if (DevModeW.dmBitsPerPel == 32) i++;
1243 break;
1244 case WINED3DFMT_R5G6B5:
1245 if (DevModeW.dmBitsPerPel == 16) i++;
1246 break;
1247 case WINED3DFMT_P8:
1248 if (DevModeW.dmBitsPerPel == 8) i++;
1249 break;
1250 default:
1251 /* Skip other modes as they do not match the requested format */
1252 break;
1255 } else {
1256 i = 1;
1257 j = 1;
1260 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1261 return i;
1262 } else {
1263 FIXME_(d3d_caps)("Adapter not primary display\n");
1265 return 0;
1268 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1269 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1270 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1271 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1273 /* Validate the parameters as much as possible */
1274 if (NULL == pMode ||
1275 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1276 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1277 return WINED3DERR_INVALIDCALL;
1280 /* TODO: Store modes per adapter and read it from the adapter structure */
1281 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1282 DEVMODEW DevModeW;
1283 int ModeIdx = 0;
1284 int i = 0;
1285 int j = 0;
1287 ZeroMemory(&DevModeW, sizeof(DevModeW));
1288 DevModeW.dmSize = sizeof(DevModeW);
1290 /* If we are filtering to a specific format (D3D9), then need to skip
1291 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1292 just count through the ones with valid bit depths */
1293 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1294 switch (Format)
1296 case WINED3DFMT_UNKNOWN:
1297 /* This is D3D8. Do not enumerate P8 here */
1298 if (DevModeW.dmBitsPerPel == 32 ||
1299 DevModeW.dmBitsPerPel == 16) i++;
1300 break;
1301 case WINED3DFMT_X8R8G8B8:
1302 if (DevModeW.dmBitsPerPel == 32) i++;
1303 break;
1304 case WINED3DFMT_R5G6B5:
1305 if (DevModeW.dmBitsPerPel == 16) i++;
1306 break;
1307 case WINED3DFMT_P8:
1308 if (DevModeW.dmBitsPerPel == 8) i++;
1309 break;
1310 default:
1311 /* Modes that don't match what we support can get an early-out */
1312 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1313 return WINED3DERR_INVALIDCALL;
1317 if (i == 0) {
1318 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1319 return WINED3DERR_INVALIDCALL;
1321 ModeIdx = j - 1;
1323 /* Now get the display mode via the calculated index */
1324 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1325 pMode->Width = DevModeW.dmPelsWidth;
1326 pMode->Height = DevModeW.dmPelsHeight;
1327 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1328 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1329 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1331 if (Format == WINED3DFMT_UNKNOWN)
1333 switch (DevModeW.dmBitsPerPel)
1335 case 8:
1336 pMode->Format = WINED3DFMT_P8;
1337 break;
1338 case 16:
1339 pMode->Format = WINED3DFMT_R5G6B5;
1340 break;
1341 case 32:
1342 pMode->Format = WINED3DFMT_X8R8G8B8;
1343 break;
1344 default:
1345 pMode->Format = WINED3DFMT_UNKNOWN;
1346 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1348 } else {
1349 pMode->Format = Format;
1351 } else {
1352 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1353 return WINED3DERR_INVALIDCALL;
1356 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1357 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1358 DevModeW.dmBitsPerPel);
1360 } else if (DEBUG_SINGLE_MODE) {
1361 /* Return one setting of the format requested */
1362 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1363 pMode->Width = 800;
1364 pMode->Height = 600;
1365 pMode->RefreshRate = 60;
1366 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1367 } else {
1368 FIXME_(d3d_caps)("Adapter not primary display\n");
1371 return WINED3D_OK;
1374 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1375 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1376 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1378 if (NULL == pMode ||
1379 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1380 return WINED3DERR_INVALIDCALL;
1383 if (Adapter == 0) { /* Display */
1384 int bpp = 0;
1385 DEVMODEW DevModeW;
1387 ZeroMemory(&DevModeW, sizeof(DevModeW));
1388 DevModeW.dmSize = sizeof(DevModeW);
1390 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1391 pMode->Width = DevModeW.dmPelsWidth;
1392 pMode->Height = DevModeW.dmPelsHeight;
1393 bpp = DevModeW.dmBitsPerPel;
1394 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1395 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1397 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1400 switch (bpp) {
1401 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1402 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1403 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1404 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1405 default: pMode->Format = WINED3DFMT_UNKNOWN;
1408 } else {
1409 FIXME_(d3d_caps)("Adapter not primary display\n");
1412 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1413 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1414 return WINED3D_OK;
1417 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1418 and fields being inserted in the middle, a new structure is used in place */
1419 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1420 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1421 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1423 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1425 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1426 return WINED3DERR_INVALIDCALL;
1429 /* Return the information requested */
1430 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1431 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1432 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1434 /* Note dx8 doesn't supply a DeviceName */
1435 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1436 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1437 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1438 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1439 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1440 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1441 *(pIdentifier->SubSysId) = 0;
1442 *(pIdentifier->Revision) = 0;
1444 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1445 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1446 *(pIdentifier->WHQLLevel) = 0;
1447 } else {
1448 *(pIdentifier->WHQLLevel) = 1;
1451 return WINED3D_OK;
1454 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1455 short redSize, greenSize, blueSize, alphaSize, colorBits;
1457 if(!cfg)
1458 return FALSE;
1460 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1461 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1462 return FALSE;
1465 if(cfg->redSize < redSize)
1466 return FALSE;
1468 if(cfg->greenSize < greenSize)
1469 return FALSE;
1471 if(cfg->blueSize < blueSize)
1472 return FALSE;
1474 if(cfg->alphaSize < alphaSize)
1475 return FALSE;
1477 return TRUE;
1480 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1481 short depthSize, stencilSize;
1483 if(!cfg)
1484 return FALSE;
1486 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1487 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1488 return FALSE;
1491 if(cfg->depthSize < depthSize)
1492 return FALSE;
1494 if(cfg->stencilSize < stencilSize)
1495 return FALSE;
1497 return TRUE;
1500 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1501 WINED3DFORMAT AdapterFormat,
1502 WINED3DFORMAT RenderTargetFormat,
1503 WINED3DFORMAT DepthStencilFormat) {
1504 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1505 int nCfgs;
1506 WineD3D_PixelFormat *cfgs;
1507 int it;
1509 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1510 This, Adapter,
1511 DeviceType, debug_d3ddevicetype(DeviceType),
1512 AdapterFormat, debug_d3dformat(AdapterFormat),
1513 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1514 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1516 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1517 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1518 return WINED3DERR_INVALIDCALL;
1521 cfgs = Adapters[Adapter].cfgs;
1522 nCfgs = Adapters[Adapter].nCfgs;
1523 for (it = 0; it < nCfgs; ++it) {
1524 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1525 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1526 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1527 return WINED3D_OK;
1531 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1533 return WINED3DERR_NOTAVAILABLE;
1536 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1537 WINED3DFORMAT SurfaceFormat,
1538 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1540 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1541 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1542 This,
1543 Adapter,
1544 DeviceType, debug_d3ddevicetype(DeviceType),
1545 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1546 Windowed,
1547 MultiSampleType,
1548 pQualityLevels);
1550 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1551 return WINED3DERR_INVALIDCALL;
1554 /* TODO: Store in Adapter structure */
1555 if (pQualityLevels != NULL) {
1556 static int s_single_shot = 0;
1557 if (!s_single_shot) {
1558 FIXME("Quality levels unsupported at present\n");
1559 s_single_shot = 1;
1561 *pQualityLevels = 1; /* Guess at a value! */
1564 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1565 return WINED3DERR_NOTAVAILABLE;
1568 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1569 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1571 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1572 int nCfgs = 0;
1573 WineD3D_PixelFormat *cfgs;
1574 int it;
1575 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1577 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1578 This,
1579 Adapter,
1580 CheckType, debug_d3ddevicetype(CheckType),
1581 DisplayFormat, debug_d3dformat(DisplayFormat),
1582 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1583 Windowed);
1585 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1586 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1587 return WINED3DERR_INVALIDCALL;
1590 cfgs = Adapters[Adapter].cfgs;
1591 nCfgs = Adapters[Adapter].nCfgs;
1592 for (it = 0; it < nCfgs; ++it) {
1593 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1594 hr = WINED3D_OK;
1595 TRACE_(d3d_caps)("OK\n");
1596 break ;
1600 if(hr != WINED3D_OK)
1601 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1603 if(hr != WINED3D_OK)
1604 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1606 return hr;
1609 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1610 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1611 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1612 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1613 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1614 This,
1615 Adapter,
1616 DeviceType, debug_d3ddevicetype(DeviceType),
1617 AdapterFormat, debug_d3dformat(AdapterFormat),
1618 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1619 RType, debug_d3dresourcetype(RType),
1620 CheckFormat, debug_d3dformat(CheckFormat));
1622 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1623 return WINED3DERR_INVALIDCALL;
1626 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1627 switch (CheckFormat) {
1628 /* Filtering not supported */
1629 case WINED3DFMT_R32F:
1630 case WINED3DFMT_A32B32G32R32F:
1631 TRACE_(d3d_caps)("[FAILED]\n");
1632 return WINED3DERR_NOTAVAILABLE;
1633 default:
1634 break;
1638 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1639 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1640 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1641 return WINED3DERR_NOTAVAILABLE;
1645 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1646 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1647 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1648 return WINED3DERR_NOTAVAILABLE;
1650 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1651 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1652 * app needing one of those formats, don't advertize them to avoid leading apps into
1653 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1654 * except of R32F.
1656 switch(CheckFormat) {
1657 case WINED3DFMT_P8:
1658 case WINED3DFMT_A4L4:
1659 case WINED3DFMT_R32F:
1660 case WINED3DFMT_R16F:
1661 case WINED3DFMT_X8L8V8U8:
1662 case WINED3DFMT_L6V5U5:
1663 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1664 return WINED3DERR_NOTAVAILABLE;
1666 case WINED3DFMT_Q8W8V8U8:
1667 case WINED3DFMT_V16U16:
1668 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1669 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1670 return WINED3DERR_NOTAVAILABLE;
1672 break;
1674 case WINED3DFMT_V8U8:
1675 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1676 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1677 return WINED3DERR_NOTAVAILABLE;
1679 break;
1681 case WINED3DFMT_DXT1:
1682 case WINED3DFMT_DXT2:
1683 case WINED3DFMT_DXT3:
1684 case WINED3DFMT_DXT4:
1685 case WINED3DFMT_DXT5:
1686 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1687 * compressed texture results in an error. While the D3D refrast does
1688 * support s3tc volumes, at least the nvidia windows driver does not, so
1689 * we're free not to support this format.
1691 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1692 return WINED3DERR_NOTAVAILABLE;
1694 default:
1695 /* Do nothing, continue with checking the format below */
1696 break;
1699 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1700 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1701 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1702 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1703 if (!GL_LIMITS(vertex_samplers)) {
1704 TRACE_(d3d_caps)("[FAILED]\n");
1705 return WINED3DERR_NOTAVAILABLE;
1708 switch (CheckFormat) {
1709 case WINED3DFMT_A32B32G32R32F:
1710 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1711 TRACE_(d3d_caps)("[FAILED]\n");
1712 return WINED3DERR_NOTAVAILABLE;
1714 TRACE_(d3d_caps)("[OK]\n");
1715 return WINED3D_OK;
1717 default:
1718 TRACE_(d3d_caps)("[FAILED]\n");
1719 return WINED3DERR_NOTAVAILABLE;
1723 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1724 switch (CheckFormat) {
1725 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1726 * Windows supports only those 3, and enumerating the other formats confuses applications
1728 case WINED3DFMT_D24S8:
1729 case WINED3DFMT_D24X8:
1730 case WINED3DFMT_D16:
1731 TRACE_(d3d_caps)("[OK]\n");
1732 return WINED3D_OK;
1733 case WINED3DFMT_D16_LOCKABLE:
1734 case WINED3DFMT_D24FS8:
1735 case WINED3DFMT_D32F_LOCKABLE:
1736 case WINED3DFMT_D24X4S4:
1737 case WINED3DFMT_D15S1:
1738 case WINED3DFMT_D32:
1739 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1740 return WINED3DERR_NOTAVAILABLE;
1741 default:
1742 TRACE_(d3d_caps)("[FAILED]\n");
1743 return WINED3DERR_NOTAVAILABLE;
1745 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1746 switch (CheckFormat) {
1747 case WINED3DFMT_R8G8B8:
1748 case WINED3DFMT_A8R8G8B8:
1749 case WINED3DFMT_X8R8G8B8:
1750 case WINED3DFMT_R5G6B5:
1751 case WINED3DFMT_X1R5G5B5:
1752 case WINED3DFMT_A1R5G5B5:
1753 case WINED3DFMT_A4R4G4B4:
1754 case WINED3DFMT_R3G3B2:
1755 case WINED3DFMT_X4R4G4B4:
1756 case WINED3DFMT_A8B8G8R8:
1757 case WINED3DFMT_X8B8G8R8:
1758 case WINED3DFMT_P8:
1759 TRACE_(d3d_caps)("[OK]\n");
1760 return WINED3D_OK;
1761 case WINED3DFMT_R16F:
1762 case WINED3DFMT_A16B16G16R16F:
1763 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1764 TRACE_(d3d_caps)("[FAILED]\n");
1765 return WINED3DERR_NOTAVAILABLE;
1767 TRACE_(d3d_caps)("[OK]\n");
1768 return WINED3D_OK;
1769 case WINED3DFMT_A32B32G32R32F:
1770 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1771 TRACE_(d3d_caps)("[FAILED]\n");
1772 return WINED3DERR_NOTAVAILABLE;
1774 TRACE_(d3d_caps)("[OK]\n");
1775 return WINED3D_OK;
1776 default:
1777 TRACE_(d3d_caps)("[FAILED]\n");
1778 return WINED3DERR_NOTAVAILABLE;
1780 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1781 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1782 switch (CheckFormat) {
1783 case WINED3DFMT_V8U8:
1784 TRACE_(d3d_caps)("[OK]\n");
1785 return WINED3D_OK;
1786 /* TODO: Other bump map formats */
1787 default:
1788 TRACE_(d3d_caps)("[FAILED]\n");
1789 return WINED3DERR_NOTAVAILABLE;
1792 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1793 switch (CheckFormat) {
1794 case WINED3DFMT_V8U8:
1795 TRACE_(d3d_caps)("[OK]\n");
1796 return WINED3D_OK;
1797 default:
1798 TRACE_(d3d_caps)("[FAILED]\n");
1799 return WINED3DERR_NOTAVAILABLE;
1802 TRACE_(d3d_caps)("[FAILED]\n");
1803 return WINED3DERR_NOTAVAILABLE;
1806 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1807 switch (CheckFormat) {
1808 case WINED3DFMT_DXT1:
1809 case WINED3DFMT_DXT2:
1810 case WINED3DFMT_DXT3:
1811 case WINED3DFMT_DXT4:
1812 case WINED3DFMT_DXT5:
1813 TRACE_(d3d_caps)("[OK]\n");
1814 return WINED3D_OK;
1815 default:
1816 break; /* Avoid compiler warnings */
1820 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1821 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1822 switch (CheckFormat) {
1823 case WINED3DFMT_A8R8G8B8:
1824 case WINED3DFMT_X8R8G8B8:
1825 case WINED3DFMT_A4R4G4B4:
1826 case WINED3DFMT_L8:
1827 case WINED3DFMT_A8L8:
1828 case WINED3DFMT_DXT1:
1829 case WINED3DFMT_DXT2:
1830 case WINED3DFMT_DXT3:
1831 case WINED3DFMT_DXT4:
1832 case WINED3DFMT_DXT5:
1833 TRACE_(d3d_caps)("[OK]\n");
1834 return WINED3D_OK;
1836 default:
1837 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1838 return WINED3DERR_NOTAVAILABLE;
1842 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1844 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1846 switch (CheckFormat) {
1847 case WINED3DFMT_R16F:
1848 case WINED3DFMT_A16B16G16R16F:
1849 if (!half_pixel_support) break;
1850 case WINED3DFMT_R32F:
1851 case WINED3DFMT_A32B32G32R32F:
1852 TRACE_(d3d_caps)("[OK]\n");
1853 return WINED3D_OK;
1854 default:
1855 break; /* Avoid compiler warnings */
1859 /* This format is nothing special and it is supported perfectly.
1860 * However, ati and nvidia driver on windows do not mark this format as
1861 * supported (tested with the dxCapsViewer) and pretending to
1862 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1863 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1864 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1866 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1867 TRACE_(d3d_caps)("[FAILED]\n");
1868 return WINED3DERR_NOTAVAILABLE;
1871 switch (CheckFormat) {
1873 /*****
1874 * supported: RGB(A) formats
1876 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1877 case WINED3DFMT_A8R8G8B8:
1878 case WINED3DFMT_X8R8G8B8:
1879 case WINED3DFMT_R5G6B5:
1880 case WINED3DFMT_X1R5G5B5:
1881 case WINED3DFMT_A1R5G5B5:
1882 case WINED3DFMT_A4R4G4B4:
1883 case WINED3DFMT_R3G3B2:
1884 case WINED3DFMT_A8:
1885 case WINED3DFMT_X4R4G4B4:
1886 case WINED3DFMT_A8B8G8R8:
1887 case WINED3DFMT_X8B8G8R8:
1888 case WINED3DFMT_A2R10G10B10:
1889 case WINED3DFMT_A2B10G10R10:
1890 TRACE_(d3d_caps)("[OK]\n");
1891 return WINED3D_OK;
1893 /*****
1894 * supported: Palettized
1896 case WINED3DFMT_P8:
1897 TRACE_(d3d_caps)("[OK]\n");
1898 return WINED3D_OK;
1900 /*****
1901 * Supported: (Alpha)-Luminance
1903 case WINED3DFMT_L8:
1904 case WINED3DFMT_A8L8:
1905 case WINED3DFMT_A4L4:
1906 TRACE_(d3d_caps)("[OK]\n");
1907 return WINED3D_OK;
1909 /*****
1910 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1911 * GL_NV_texture_shader), but advertized to make apps happy.
1912 * Enable some because games often fail when they are not available
1913 * and are still playable even without bump mapping
1915 case WINED3DFMT_V8U8:
1916 case WINED3DFMT_V16U16:
1917 case WINED3DFMT_L6V5U5:
1918 case WINED3DFMT_X8L8V8U8:
1919 case WINED3DFMT_Q8W8V8U8:
1920 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1921 return WINED3D_OK;
1923 /* Those are not advertized by the nvidia windows driver, and not
1924 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1925 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1926 * ARGB format if needed
1928 case WINED3DFMT_W11V11U10:
1929 case WINED3DFMT_A2W10V10U10:
1930 WARN_(d3d_caps)("[FAILED]\n");
1931 return WINED3DERR_NOTAVAILABLE;
1933 /*****
1934 * DXTN Formats: Handled above
1935 * WINED3DFMT_DXT1
1936 * WINED3DFMT_DXT2
1937 * WINED3DFMT_DXT3
1938 * WINED3DFMT_DXT4
1939 * WINED3DFMT_DXT5
1942 /*****
1943 * Odd formats - not supported
1945 case WINED3DFMT_VERTEXDATA:
1946 case WINED3DFMT_INDEX16:
1947 case WINED3DFMT_INDEX32:
1948 case WINED3DFMT_Q16W16V16U16:
1949 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1950 return WINED3DERR_NOTAVAILABLE;
1952 /*****
1953 * Float formats: Not supported right now
1955 case WINED3DFMT_G16R16F:
1956 case WINED3DFMT_G32R32F:
1957 case WINED3DFMT_CxV8U8:
1958 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1959 return WINED3DERR_NOTAVAILABLE;
1961 /* Not supported */
1962 case WINED3DFMT_G16R16:
1963 case WINED3DFMT_A16B16G16R16:
1964 case WINED3DFMT_A8R3G3B2:
1965 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1966 return WINED3DERR_NOTAVAILABLE;
1968 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1969 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1970 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1971 * We can do instancing with all shader versions, but we need vertex shaders.
1973 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1974 * to enable instancing. WineD3D doesn't need that and just ignores it.
1976 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1978 case WINEMAKEFOURCC('I','N','S','T'):
1979 TRACE("ATI Instancing check hack\n");
1980 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1981 TRACE_(d3d_caps)("[OK]\n");
1982 return WINED3D_OK;
1983 } else {
1984 TRACE_(d3d_caps)("[FAILED]\n");
1985 return WINED3DERR_NOTAVAILABLE;
1988 default:
1989 break;
1992 TRACE_(d3d_caps)("[FAILED]\n");
1993 return WINED3DERR_NOTAVAILABLE;
1996 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1997 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1998 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2000 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2001 This,
2002 Adapter,
2003 DeviceType, debug_d3ddevicetype(DeviceType),
2004 SourceFormat, debug_d3dformat(SourceFormat),
2005 TargetFormat, debug_d3dformat(TargetFormat));
2006 return WINED3D_OK;
2009 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2010 subset of a D3DCAPS9 structure. However, it has to come via a void *
2011 as the d3d8 interface cannot import the d3d9 header */
2012 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2014 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2015 int vs_selected_mode;
2016 int ps_selected_mode;
2018 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2020 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2021 return WINED3DERR_INVALIDCALL;
2024 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2026 /* This function should *not* be modifying GL caps
2027 * TODO: move the functionality where it belongs */
2028 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2030 /* ------------------------------------------------
2031 The following fields apply to both d3d8 and d3d9
2032 ------------------------------------------------ */
2033 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2034 *pCaps->AdapterOrdinal = Adapter;
2036 *pCaps->Caps = 0;
2037 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2038 WINED3DCAPS2_FULLSCREENGAMMA |
2039 WINED3DCAPS2_DYNAMICTEXTURES;
2040 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2041 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2043 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2044 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2045 WINED3DPRESENT_INTERVAL_ONE;
2047 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2048 WINED3DCURSORCAPS_LOWRES;
2050 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2051 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2052 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2053 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2054 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2055 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2056 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2057 WINED3DDEVCAPS_PUREDEVICE |
2058 WINED3DDEVCAPS_HWRASTERIZATION |
2059 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2060 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2061 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2062 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2063 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2064 WINED3DDEVCAPS_RTPATCHES;
2066 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2067 WINED3DPMISCCAPS_CULLCCW |
2068 WINED3DPMISCCAPS_CULLCW |
2069 WINED3DPMISCCAPS_COLORWRITEENABLE |
2070 WINED3DPMISCCAPS_CLIPTLVERTS |
2071 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2072 WINED3DPMISCCAPS_MASKZ |
2073 WINED3DPMISCCAPS_BLENDOP;
2074 /* TODO:
2075 WINED3DPMISCCAPS_NULLREFERENCE
2076 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2077 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2078 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2079 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2080 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2081 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2083 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2084 #if 0
2085 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2086 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2087 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2088 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2089 #endif
2091 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2092 WINED3DPRASTERCAPS_PAT |
2093 WINED3DPRASTERCAPS_WFOG |
2094 WINED3DPRASTERCAPS_ZFOG |
2095 WINED3DPRASTERCAPS_FOGVERTEX |
2096 WINED3DPRASTERCAPS_FOGTABLE |
2097 WINED3DPRASTERCAPS_STIPPLE |
2098 WINED3DPRASTERCAPS_SUBPIXEL |
2099 WINED3DPRASTERCAPS_ZTEST |
2100 WINED3DPRASTERCAPS_SCISSORTEST |
2101 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2102 WINED3DPRASTERCAPS_DEPTHBIAS;
2104 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2105 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2106 WINED3DPRASTERCAPS_ZBIAS |
2107 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2109 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2110 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2112 /* FIXME Add:
2113 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2114 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2115 WINED3DPRASTERCAPS_ANTIALIASEDGES
2116 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2117 WINED3DPRASTERCAPS_WBUFFER */
2119 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2120 WINED3DPCMPCAPS_EQUAL |
2121 WINED3DPCMPCAPS_GREATER |
2122 WINED3DPCMPCAPS_GREATEREQUAL |
2123 WINED3DPCMPCAPS_LESS |
2124 WINED3DPCMPCAPS_LESSEQUAL |
2125 WINED3DPCMPCAPS_NEVER |
2126 WINED3DPCMPCAPS_NOTEQUAL;
2128 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2129 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2130 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2131 WINED3DPBLENDCAPS_DESTALPHA |
2132 WINED3DPBLENDCAPS_DESTCOLOR |
2133 WINED3DPBLENDCAPS_INVDESTALPHA |
2134 WINED3DPBLENDCAPS_INVDESTCOLOR |
2135 WINED3DPBLENDCAPS_INVSRCALPHA |
2136 WINED3DPBLENDCAPS_INVSRCCOLOR |
2137 WINED3DPBLENDCAPS_ONE |
2138 WINED3DPBLENDCAPS_SRCALPHA |
2139 WINED3DPBLENDCAPS_SRCALPHASAT |
2140 WINED3DPBLENDCAPS_SRCCOLOR |
2141 WINED3DPBLENDCAPS_ZERO;
2143 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2144 WINED3DPBLENDCAPS_DESTALPHA |
2145 WINED3DPBLENDCAPS_DESTCOLOR |
2146 WINED3DPBLENDCAPS_INVDESTALPHA |
2147 WINED3DPBLENDCAPS_INVDESTCOLOR |
2148 WINED3DPBLENDCAPS_INVSRCALPHA |
2149 WINED3DPBLENDCAPS_INVSRCCOLOR |
2150 WINED3DPBLENDCAPS_ONE |
2151 WINED3DPBLENDCAPS_SRCALPHA |
2152 WINED3DPBLENDCAPS_SRCCOLOR |
2153 WINED3DPBLENDCAPS_ZERO;
2154 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2155 * according to the glBlendFunc manpage
2157 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2158 * legacy settings for srcblend only
2161 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2162 WINED3DPCMPCAPS_EQUAL |
2163 WINED3DPCMPCAPS_GREATER |
2164 WINED3DPCMPCAPS_GREATEREQUAL |
2165 WINED3DPCMPCAPS_LESS |
2166 WINED3DPCMPCAPS_LESSEQUAL |
2167 WINED3DPCMPCAPS_NEVER |
2168 WINED3DPCMPCAPS_NOTEQUAL;
2170 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2171 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2172 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2173 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2174 WINED3DPSHADECAPS_COLORFLATRGB |
2175 WINED3DPSHADECAPS_FOGFLAT |
2176 WINED3DPSHADECAPS_FOGGOURAUD |
2177 WINED3DPSHADECAPS_SPECULARFLATRGB;
2179 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2180 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2181 WINED3DPTEXTURECAPS_BORDER |
2182 WINED3DPTEXTURECAPS_MIPMAP |
2183 WINED3DPTEXTURECAPS_PROJECTED |
2184 WINED3DPTEXTURECAPS_PERSPECTIVE;
2186 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2187 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2188 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2191 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2192 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2193 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2194 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2197 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2198 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2199 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2200 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2204 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2205 WINED3DPTFILTERCAPS_MAGFPOINT |
2206 WINED3DPTFILTERCAPS_MINFLINEAR |
2207 WINED3DPTFILTERCAPS_MINFPOINT |
2208 WINED3DPTFILTERCAPS_MIPFLINEAR |
2209 WINED3DPTFILTERCAPS_MIPFPOINT |
2210 WINED3DPTFILTERCAPS_LINEAR |
2211 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2212 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2213 WINED3DPTFILTERCAPS_MIPLINEAR |
2214 WINED3DPTFILTERCAPS_MIPNEAREST |
2215 WINED3DPTFILTERCAPS_NEAREST;
2217 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2218 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2219 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2222 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2223 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2224 WINED3DPTFILTERCAPS_MAGFPOINT |
2225 WINED3DPTFILTERCAPS_MINFLINEAR |
2226 WINED3DPTFILTERCAPS_MINFPOINT |
2227 WINED3DPTFILTERCAPS_MIPFLINEAR |
2228 WINED3DPTFILTERCAPS_MIPFPOINT |
2229 WINED3DPTFILTERCAPS_LINEAR |
2230 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2231 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2232 WINED3DPTFILTERCAPS_MIPLINEAR |
2233 WINED3DPTFILTERCAPS_MIPNEAREST |
2234 WINED3DPTFILTERCAPS_NEAREST;
2236 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2237 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2238 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2240 } else
2241 *pCaps->CubeTextureFilterCaps = 0;
2243 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2244 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2245 WINED3DPTFILTERCAPS_MAGFPOINT |
2246 WINED3DPTFILTERCAPS_MINFLINEAR |
2247 WINED3DPTFILTERCAPS_MINFPOINT |
2248 WINED3DPTFILTERCAPS_MIPFLINEAR |
2249 WINED3DPTFILTERCAPS_MIPFPOINT |
2250 WINED3DPTFILTERCAPS_LINEAR |
2251 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2252 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2253 WINED3DPTFILTERCAPS_MIPLINEAR |
2254 WINED3DPTFILTERCAPS_MIPNEAREST |
2255 WINED3DPTFILTERCAPS_NEAREST;
2256 } else
2257 *pCaps->VolumeTextureFilterCaps = 0;
2259 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2260 WINED3DPTADDRESSCAPS_CLAMP |
2261 WINED3DPTADDRESSCAPS_WRAP;
2263 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2264 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2266 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2267 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2269 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2270 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2273 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2274 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2275 WINED3DPTADDRESSCAPS_CLAMP |
2276 WINED3DPTADDRESSCAPS_WRAP;
2277 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2278 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2280 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2281 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2283 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2284 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2286 } else
2287 *pCaps->VolumeTextureAddressCaps = 0;
2289 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2290 WINED3DLINECAPS_ZTEST;
2291 /* FIXME: Add
2292 WINED3DLINECAPS_BLEND
2293 WINED3DLINECAPS_ALPHACMP
2294 WINED3DLINECAPS_FOG */
2296 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2297 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2299 if(GL_SUPPORT(EXT_TEXTURE3D))
2300 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2301 else
2302 *pCaps->MaxVolumeExtent = 0;
2304 *pCaps->MaxTextureRepeat = 32768;
2305 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2306 *pCaps->MaxVertexW = 1.0;
2308 *pCaps->GuardBandLeft = 0;
2309 *pCaps->GuardBandTop = 0;
2310 *pCaps->GuardBandRight = 0;
2311 *pCaps->GuardBandBottom = 0;
2313 *pCaps->ExtentsAdjust = 0;
2315 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2316 WINED3DSTENCILCAPS_INCRSAT |
2317 WINED3DSTENCILCAPS_INVERT |
2318 WINED3DSTENCILCAPS_KEEP |
2319 WINED3DSTENCILCAPS_REPLACE |
2320 WINED3DSTENCILCAPS_ZERO;
2321 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2322 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2323 WINED3DSTENCILCAPS_INCR;
2325 if ( This->dxVersion > 8 &&
2326 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2327 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2328 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2331 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2333 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2334 WINED3DTEXOPCAPS_ADDSIGNED |
2335 WINED3DTEXOPCAPS_ADDSIGNED2X |
2336 WINED3DTEXOPCAPS_MODULATE |
2337 WINED3DTEXOPCAPS_MODULATE2X |
2338 WINED3DTEXOPCAPS_MODULATE4X |
2339 WINED3DTEXOPCAPS_SELECTARG1 |
2340 WINED3DTEXOPCAPS_SELECTARG2 |
2341 WINED3DTEXOPCAPS_DISABLE;
2343 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2344 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2345 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2346 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2347 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2348 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2349 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2350 WINED3DTEXOPCAPS_LERP |
2351 WINED3DTEXOPCAPS_SUBTRACT;
2353 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2354 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2355 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2356 WINED3DTEXOPCAPS_MULTIPLYADD |
2357 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2358 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2359 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2361 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2362 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2364 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2365 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2366 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2369 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2370 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2371 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2372 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2373 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2374 * and 3D textures. It also allows us to keep the code simpler by having texture
2375 * shaders constantly enabled.
2377 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2378 /* TODO: Luminance bump map? */
2380 #if 0
2381 /* FIXME: Add
2382 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2383 WINED3DTEXOPCAPS_PREMODULATE */
2384 #endif
2386 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2387 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2388 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2389 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2391 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2392 *pCaps->MaxVertexBlendMatrixIndex = 0;
2394 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2395 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2398 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2399 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2400 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2401 WINED3DVTXPCAPS_LOCALVIEWER |
2402 WINED3DVTXPCAPS_VERTEXFOG |
2403 WINED3DVTXPCAPS_TEXGEN;
2404 /* FIXME: Add
2405 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2407 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2408 *pCaps->MaxVertexIndex = 0xFFFFF;
2409 *pCaps->MaxStreams = MAX_STREAMS;
2410 *pCaps->MaxStreamStride = 1024;
2412 if (vs_selected_mode == SHADER_GLSL) {
2413 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2414 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2415 * vs_nv_version which is based on NV_vertex_program.
2416 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2417 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2418 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2419 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2420 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2421 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2422 else
2423 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2424 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2425 } else if (vs_selected_mode == SHADER_ARB) {
2426 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2427 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2428 } else {
2429 *pCaps->VertexShaderVersion = 0;
2430 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2433 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2435 if (ps_selected_mode == SHADER_GLSL) {
2436 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2437 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2438 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2439 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2440 * in max native instructions. Intel and others also offer the info in this extension but they
2441 * don't support GLSL (at least on Windows).
2443 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2444 * of instructions is 512 or less we have to do with ps2.0 hardware.
2445 * 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.
2447 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2448 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2449 else
2450 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2451 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2452 * Direct3D minimum requirement.
2454 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2455 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2457 * The problem is that the refrast clamps temporary results in the shader to
2458 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2459 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2460 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2461 * offer a way to query this.
2463 *pCaps->PixelShader1xMaxValue = 8.0;
2464 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2465 } else if (ps_selected_mode == SHADER_ARB) {
2466 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2467 *pCaps->PixelShader1xMaxValue = 8.0;
2468 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2469 } else {
2470 *pCaps->PixelShaderVersion = 0;
2471 *pCaps->PixelShader1xMaxValue = 0.0;
2472 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2475 /* ------------------------------------------------
2476 The following fields apply to d3d9 only
2477 ------------------------------------------------ */
2478 if (This->dxVersion > 8) {
2479 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2480 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2481 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2482 *pCaps->MaxNpatchTessellationLevel = 0;
2483 *pCaps->MasterAdapterOrdinal = 0;
2484 *pCaps->AdapterOrdinalInGroup = 0;
2485 *pCaps->NumberOfAdaptersInGroup = 1;
2487 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2488 /* OpenGL supports all the formats below, perhaps not always
2489 * without conversion, but it supports them.
2490 * Further GLSL doesn't seem to have an official unsigned type so
2491 * don't advertise it yet as I'm not sure how we handle it.
2492 * We might need to add some clamping in the shader engine to
2493 * support it.
2494 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2495 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2496 WINED3DDTCAPS_UBYTE4N |
2497 WINED3DDTCAPS_SHORT2N |
2498 WINED3DDTCAPS_SHORT4N;
2499 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2500 *pCaps->DeclTypes |=
2501 WINED3DDTCAPS_FLOAT16_2 |
2502 WINED3DDTCAPS_FLOAT16_4;
2504 } else
2505 *pCaps->DeclTypes = 0;
2507 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2510 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2511 WINED3DPTFILTERCAPS_MAGFPOINT |
2512 WINED3DPTFILTERCAPS_MINFLINEAR |
2513 WINED3DPTFILTERCAPS_MAGFLINEAR;
2514 *pCaps->VertexTextureFilterCaps = 0;
2516 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2517 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2518 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2519 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2520 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2521 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2522 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2524 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2525 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2526 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2527 *pCaps->VS20Caps.Caps = 0;
2528 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2529 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2530 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2532 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2533 *pCaps->MaxVertexShader30InstructionSlots = 0;
2534 } else { /* VS 1.x */
2535 *pCaps->VS20Caps.Caps = 0;
2536 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2537 *pCaps->VS20Caps.NumTemps = 0;
2538 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2540 *pCaps->MaxVShaderInstructionsExecuted = 0;
2541 *pCaps->MaxVertexShader30InstructionSlots = 0;
2544 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2545 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2546 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2548 /* 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 */
2549 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2550 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2551 WINED3DPS20CAPS_PREDICATION |
2552 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2553 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2554 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2555 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2556 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2557 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2559 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2560 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2561 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2562 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2563 *pCaps->PS20Caps.Caps = 0;
2564 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2565 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2566 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2567 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2569 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2570 *pCaps->MaxPixelShader30InstructionSlots = 0;
2571 } else { /* PS 1.x */
2572 *pCaps->PS20Caps.Caps = 0;
2573 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2574 *pCaps->PS20Caps.NumTemps = 0;
2575 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2576 *pCaps->PS20Caps.NumInstructionSlots = 0;
2578 *pCaps->MaxPShaderInstructionsExecuted = 0;
2579 *pCaps->MaxPixelShader30InstructionSlots = 0;
2583 return WINED3D_OK;
2586 static unsigned int glsl_program_key_hash(void *key) {
2587 glsl_program_key_t *k = (glsl_program_key_t *)key;
2589 unsigned int hash = k->vshader | k->pshader << 16;
2590 hash += ~(hash << 15);
2591 hash ^= (hash >> 10);
2592 hash += (hash << 3);
2593 hash ^= (hash >> 6);
2594 hash += ~(hash << 11);
2595 hash ^= (hash >> 16);
2597 return hash;
2600 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2601 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2602 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2604 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2607 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2608 and fields being inserted in the middle, a new structure is used in place */
2609 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2610 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2611 IUnknown *parent) {
2613 IWineD3DDeviceImpl *object = NULL;
2614 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2615 HDC hDC;
2616 int i;
2618 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2619 * number and create a device without a 3D adapter for 2D only operation.
2621 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2622 return WINED3DERR_INVALIDCALL;
2625 /* Create a WineD3DDevice object */
2626 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2627 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2628 TRACE("Created WineD3DDevice object @ %p\n", object);
2629 if (NULL == object) {
2630 return WINED3DERR_OUTOFVIDEOMEMORY;
2633 /* Set up initial COM information */
2634 object->lpVtbl = &IWineD3DDevice_Vtbl;
2635 object->ref = 1;
2636 object->wineD3D = iface;
2637 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2638 IWineD3D_AddRef(object->wineD3D);
2639 object->parent = parent;
2641 if(This->dxVersion == 7) {
2642 object->surface_alignment = 8;
2643 } else {
2644 object->surface_alignment = 4;
2646 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2648 /* Set the state up as invalid until the device is fully created */
2649 object->state = WINED3DERR_DRIVERINTERNALERROR;
2651 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2652 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2654 /* Save the creation parameters */
2655 object->createParms.AdapterOrdinal = Adapter;
2656 object->createParms.DeviceType = DeviceType;
2657 object->createParms.hFocusWindow = hFocusWindow;
2658 object->createParms.BehaviorFlags = BehaviourFlags;
2660 /* Initialize other useful values */
2661 object->adapterNo = Adapter;
2662 object->devType = DeviceType;
2664 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2665 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2666 object->shader_backend = &glsl_shader_backend;
2667 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2668 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2669 object->shader_backend = &arb_program_shader_backend;
2670 } else {
2671 object->shader_backend = &none_shader_backend;
2674 /* set the state of the device to valid */
2675 object->state = WINED3D_OK;
2677 /* Get the initial screen setup for ddraw */
2678 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2679 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2680 hDC = GetDC(0);
2681 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2682 ReleaseDC(0, hDC);
2684 for(i = 0; i < PATCHMAP_SIZE; i++) {
2685 list_init(&object->patches[i]);
2687 return WINED3D_OK;
2689 #undef GLINFO_LOCATION
2691 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2692 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2693 IUnknown_AddRef(This->parent);
2694 *pParent = This->parent;
2695 return WINED3D_OK;
2698 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2699 IUnknown* surfaceParent;
2700 TRACE("(%p) call back\n", pSurface);
2702 /* Now, release the parent, which will take care of cleaning up the surface for us */
2703 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2704 IUnknown_Release(surfaceParent);
2705 return IUnknown_Release(surfaceParent);
2708 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2709 IUnknown* volumeParent;
2710 TRACE("(%p) call back\n", pVolume);
2712 /* Now, release the parent, which will take care of cleaning up the volume for us */
2713 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2714 IUnknown_Release(volumeParent);
2715 return IUnknown_Release(volumeParent);
2718 #define PUSH1(att) attribs[nAttribs++] = (att);
2719 #define GLINFO_LOCATION (Adapters[0].gl_info)
2720 BOOL InitAdapters(void) {
2721 static HMODULE mod_gl;
2722 BOOL ret;
2723 int ps_selected_mode, vs_selected_mode;
2725 /* No need to hold any lock. The calling library makes sure only one thread calls
2726 * wined3d simultaneously
2728 if(numAdapters > 0) return TRUE;
2730 TRACE("Initializing adapters\n");
2732 if(!mod_gl) {
2733 #ifdef USE_WIN32_OPENGL
2734 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2735 mod_gl = LoadLibraryA("opengl32.dll");
2736 if(!mod_gl) {
2737 ERR("Can't load opengl32.dll!\n");
2738 return FALSE;
2740 #else
2741 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2742 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2743 mod_gl = GetModuleHandleA("gdi32.dll");
2744 #endif
2747 /* Load WGL core functions from opengl32.dll */
2748 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2749 WGL_FUNCS_GEN;
2750 #undef USE_WGL_FUNC
2752 if(!pwglGetProcAddress) {
2753 ERR("Unable to load wglGetProcAddress!\n");
2754 return FALSE;
2757 /* Dynamically load all GL core functions */
2758 GL_FUNCS_GEN;
2759 #undef USE_GL_FUNC
2761 /* For now only one default adapter */
2763 int iPixelFormat;
2764 int attribs[8];
2765 int values[8];
2766 int nAttribs = 0;
2767 int res;
2768 WineD3D_PixelFormat *cfgs;
2769 int attribute;
2770 DISPLAY_DEVICEW DisplayDevice;
2771 HDC hdc;
2773 TRACE("Initializing default adapter\n");
2774 Adapters[0].monitorPoint.x = -1;
2775 Adapters[0].monitorPoint.y = -1;
2777 if (!WineD3D_CreateFakeGLContext()) {
2778 ERR("Failed to get a gl context for default adapter\n");
2779 HeapFree(GetProcessHeap(), 0, Adapters);
2780 WineD3D_ReleaseFakeGLContext();
2781 return FALSE;
2784 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2785 if(!ret) {
2786 ERR("Failed to initialize gl caps for default adapter\n");
2787 HeapFree(GetProcessHeap(), 0, Adapters);
2788 WineD3D_ReleaseFakeGLContext();
2789 return FALSE;
2791 ret = initPixelFormats(&Adapters[0].gl_info);
2792 if(!ret) {
2793 ERR("Failed to init gl formats\n");
2794 HeapFree(GetProcessHeap(), 0, Adapters);
2795 WineD3D_ReleaseFakeGLContext();
2796 return FALSE;
2799 hdc = pwglGetCurrentDC();
2800 if(!hdc) {
2801 ERR("Failed to get gl HDC\n");
2802 HeapFree(GetProcessHeap(), 0, Adapters);
2803 WineD3D_ReleaseFakeGLContext();
2804 return FALSE;
2807 Adapters[0].driver = "Display";
2808 Adapters[0].description = "Direct3D HAL";
2810 /* Use the VideoRamSize registry setting when set */
2811 if(wined3d_settings.emulated_textureram)
2812 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2813 else
2814 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2815 Adapters[0].UsedTextureRam = 0;
2816 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2818 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2819 DisplayDevice.cb = sizeof(DisplayDevice);
2820 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2821 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2822 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2824 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2825 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2827 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2828 cfgs = Adapters[0].cfgs;
2829 PUSH1(WGL_RED_BITS_ARB)
2830 PUSH1(WGL_GREEN_BITS_ARB)
2831 PUSH1(WGL_BLUE_BITS_ARB)
2832 PUSH1(WGL_ALPHA_BITS_ARB)
2833 PUSH1(WGL_DEPTH_BITS_ARB)
2834 PUSH1(WGL_STENCIL_BITS_ARB)
2836 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2837 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2839 if(!res)
2840 continue;
2842 /* Cache the pixel format */
2843 cfgs->iPixelFormat = iPixelFormat;
2844 cfgs->redSize = values[0];
2845 cfgs->greenSize = values[1];
2846 cfgs->blueSize = values[2];
2847 cfgs->alphaSize = values[3];
2848 cfgs->depthSize = values[4];
2849 cfgs->stencilSize = values[5];
2851 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);
2852 cfgs++;
2854 WineD3D_ReleaseFakeGLContext();
2856 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2857 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2860 numAdapters = 1;
2861 TRACE("%d adapters successfully initialized\n", numAdapters);
2863 return TRUE;
2865 #undef PUSH1
2866 #undef GLINFO_LOCATION
2868 /**********************************************************
2869 * IWineD3D VTbl follows
2870 **********************************************************/
2872 const IWineD3DVtbl IWineD3D_Vtbl =
2874 /* IUnknown */
2875 IWineD3DImpl_QueryInterface,
2876 IWineD3DImpl_AddRef,
2877 IWineD3DImpl_Release,
2878 /* IWineD3D */
2879 IWineD3DImpl_GetParent,
2880 IWineD3DImpl_GetAdapterCount,
2881 IWineD3DImpl_RegisterSoftwareDevice,
2882 IWineD3DImpl_GetAdapterMonitor,
2883 IWineD3DImpl_GetAdapterModeCount,
2884 IWineD3DImpl_EnumAdapterModes,
2885 IWineD3DImpl_GetAdapterDisplayMode,
2886 IWineD3DImpl_GetAdapterIdentifier,
2887 IWineD3DImpl_CheckDeviceMultiSampleType,
2888 IWineD3DImpl_CheckDepthStencilMatch,
2889 IWineD3DImpl_CheckDeviceType,
2890 IWineD3DImpl_CheckDeviceFormat,
2891 IWineD3DImpl_CheckDeviceFormatConversion,
2892 IWineD3DImpl_GetDeviceCaps,
2893 IWineD3DImpl_CreateDevice