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
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
41 const char *extension_string;
42 GL_SupportedExt extension;
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
78 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
79 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
80 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
81 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
82 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
83 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
86 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
87 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
88 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
89 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
90 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
91 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
92 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
93 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
94 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
95 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
96 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
97 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
98 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
99 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
100 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
101 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
102 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
103 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
104 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
105 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
108 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
109 {"GL_NV_fence", NV_FENCE, 0 },
110 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
111 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
112 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
113 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
114 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
115 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
116 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
117 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
118 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
119 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
120 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
121 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
122 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
123 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
124 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
125 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
128 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
131 /**********************************************************
132 * Utility functions follow
133 **********************************************************/
136 static int numAdapters = 0;
137 static struct WineD3DAdapter Adapters[1];
140 int minLookup[MAX_LOOKUPS];
141 int maxLookup[MAX_LOOKUPS];
142 DWORD *stateLookup[MAX_LOOKUPS];
144 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
148 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
149 * ie there is no GL Context - Get a default rendering context to enable the
150 * function query some info from GL
153 static int wined3d_fake_gl_context_ref = 0;
154 static BOOL wined3d_fake_gl_context_foreign;
155 static BOOL wined3d_fake_gl_context_available = FALSE;
156 static HDC wined3d_fake_gl_context_hdc = NULL;
157 static HWND wined3d_fake_gl_context_hwnd = NULL;
159 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
160 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
162 0, 0, &wined3d_fake_gl_context_cs,
163 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
164 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
165 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
167 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
169 static void WineD3D_ReleaseFakeGLContext(void) {
172 EnterCriticalSection(&wined3d_fake_gl_context_cs);
174 if(!wined3d_fake_gl_context_available) {
175 TRACE_(d3d_caps)("context not available\n");
176 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
180 glCtx = pwglGetCurrentContext();
182 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
183 if (0 == (--wined3d_fake_gl_context_ref) ) {
184 if(!wined3d_fake_gl_context_foreign && glCtx) {
185 TRACE_(d3d_caps)("destroying fake GL context\n");
186 pwglMakeCurrent(NULL, NULL);
187 pwglDeleteContext(glCtx);
189 if(wined3d_fake_gl_context_hdc)
190 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
191 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
192 if(wined3d_fake_gl_context_hwnd)
193 DestroyWindow(wined3d_fake_gl_context_hwnd);
194 wined3d_fake_gl_context_hwnd = NULL;
195 wined3d_fake_gl_context_available = FALSE;
197 assert(wined3d_fake_gl_context_ref >= 0);
199 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
202 static BOOL WineD3D_CreateFakeGLContext(void) {
205 EnterCriticalSection(&wined3d_fake_gl_context_cs);
207 TRACE("getting context...\n");
208 if(wined3d_fake_gl_context_ref > 0) goto ret;
209 assert(0 == wined3d_fake_gl_context_ref);
211 wined3d_fake_gl_context_foreign = TRUE;
213 glCtx = pwglGetCurrentContext();
215 PIXELFORMATDESCRIPTOR pfd;
218 wined3d_fake_gl_context_foreign = FALSE;
220 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
221 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
222 if(!wined3d_fake_gl_context_hwnd) {
223 ERR("HWND creation failed!\n");
226 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
227 if(!wined3d_fake_gl_context_hdc) {
228 ERR("GetDC failed!\n");
232 /* PixelFormat selection */
233 ZeroMemory(&pfd, sizeof(pfd));
234 pfd.nSize = sizeof(pfd);
236 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
237 pfd.iPixelType = PFD_TYPE_RGBA;
239 pfd.iLayerType = PFD_MAIN_PLANE;
241 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
243 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
244 ERR("Can't find a suitable iPixelFormat\n");
247 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
248 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
250 /* Create a GL context */
251 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
253 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
257 /* Make it the current GL context */
258 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
259 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
265 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
266 wined3d_fake_gl_context_ref++;
267 wined3d_fake_gl_context_available = TRUE;
268 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
271 if(wined3d_fake_gl_context_hdc)
272 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
273 wined3d_fake_gl_context_hdc = NULL;
274 if(wined3d_fake_gl_context_hwnd)
275 DestroyWindow(wined3d_fake_gl_context_hwnd);
276 wined3d_fake_gl_context_hwnd = NULL;
277 if(glCtx) pwglDeleteContext(glCtx);
278 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
282 /* Adjust the amount of used texture memory */
283 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
284 UINT Adapter = D3DDevice->adapterNo;
286 Adapters[Adapter].UsedTextureRam += glram;
287 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
288 return Adapters[Adapter].UsedTextureRam;
291 /**********************************************************
292 * IUnknown parts follows
293 **********************************************************/
295 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
299 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
300 if (IsEqualGUID(riid, &IID_IUnknown)
301 || IsEqualGUID(riid, &IID_IWineD3DBase)
302 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
303 IUnknown_AddRef(iface);
308 return E_NOINTERFACE;
311 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
312 IWineD3DImpl *This = (IWineD3DImpl *)iface;
313 ULONG refCount = InterlockedIncrement(&This->ref);
315 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
319 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
320 IWineD3DImpl *This = (IWineD3DImpl *)iface;
322 TRACE("(%p) : Releasing from %d\n", This, This->ref);
323 ref = InterlockedDecrement(&This->ref);
325 HeapFree(GetProcessHeap(), 0, This);
331 /* Set the shader type for this device, depending on the given capabilities,
332 * the device type, and the user preferences in wined3d_settings */
334 static void select_shader_mode(
335 WineD3D_GL_Info *gl_info,
336 WINED3DDEVTYPE DeviceType,
340 if (wined3d_settings.vs_mode == VS_NONE) {
341 *vs_selected = SHADER_NONE;
342 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
343 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
344 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
345 * shaders only on this card. */
346 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
347 *vs_selected = SHADER_ARB;
349 *vs_selected = SHADER_GLSL;
350 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
351 *vs_selected = SHADER_ARB;
353 *vs_selected = SHADER_NONE;
356 if (wined3d_settings.ps_mode == PS_NONE) {
357 *ps_selected = SHADER_NONE;
358 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
359 *ps_selected = SHADER_GLSL;
360 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
361 *ps_selected = SHADER_ARB;
363 *ps_selected = SHADER_NONE;
367 /** Select the number of report maximum shader constants based on the selected shader modes */
368 static void select_shader_max_constants(
369 int ps_selected_mode,
370 int vs_selected_mode,
371 WineD3D_GL_Info *gl_info) {
373 switch (vs_selected_mode) {
375 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
376 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
379 /* We have to subtract any other PARAMs that we might use in our shader programs.
380 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
381 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
382 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
385 gl_info->max_vshader_constantsF = 0;
389 switch (ps_selected_mode) {
391 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
392 * In theory the texbem instruction may need one more shader constant too. But lets assume
393 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
394 * and lets not take away a uniform needlessly from all other shaders.
396 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
399 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
400 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
402 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
405 gl_info->max_pshader_constantsF = 0;
410 /**********************************************************
411 * IWineD3D parts follows
412 **********************************************************/
414 #define GLINFO_LOCATION (*gl_info)
415 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
418 const char *testcode =
420 "PARAM C[66] = { program.env[0..65] };\n"
423 "MOV result.position, C[A0.x + 65];\n"
427 GL_EXTCALL(glGenProgramsARB(1, &prog));
429 ERR("Failed to create an ARB offset limit test program\n");
431 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
432 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
433 strlen(testcode), testcode));
434 if(glGetError() != 0) {
435 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
436 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
438 } else TRACE("OpenGL implementation allows offsets > 63\n");
440 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
441 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
442 checkGLcall("ARB vp offset limit test cleanup\n");
447 static DWORD ver_for_ext(GL_SupportedExt ext)
450 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
451 if(EXTENSION_MAP[i].extension == ext) {
452 return EXTENSION_MAP[i].version;
458 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
459 const char *GL_Extensions = NULL;
460 const char *WGL_Extensions = NULL;
461 const char *gl_string = NULL;
462 const char *gl_string_cursor = NULL;
464 GLfloat gl_floatv[2];
465 int major = 1, minor = 0;
466 BOOL return_value = TRUE;
469 unsigned int vidmem=0;
471 TRACE_(d3d_caps)("(%p)\n", gl_info);
475 gl_string = (const char *) glGetString(GL_RENDERER);
476 if (NULL == gl_string)
478 strcpy(gl_info->gl_renderer, gl_string);
480 gl_string = (const char *) glGetString(GL_VENDOR);
481 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
482 if (gl_string != NULL) {
483 /* Fill in the GL vendor */
484 if (strstr(gl_string, "NVIDIA")) {
485 gl_info->gl_vendor = VENDOR_NVIDIA;
486 } else if (strstr(gl_string, "ATI")) {
487 gl_info->gl_vendor = VENDOR_ATI;
488 } else if (strstr(gl_string, "Intel(R)") ||
489 strstr(gl_info->gl_renderer, "Intel(R)")) {
490 gl_info->gl_vendor = VENDOR_INTEL;
491 } else if (strstr(gl_string, "Mesa")) {
492 gl_info->gl_vendor = VENDOR_MESA;
494 gl_info->gl_vendor = VENDOR_WINE;
497 gl_info->gl_vendor = VENDOR_WINE;
501 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
503 /* Parse the GL_VERSION field into major and minor information */
504 gl_string = (const char *) glGetString(GL_VERSION);
505 if (gl_string != NULL) {
507 switch (gl_info->gl_vendor) {
509 gl_string_cursor = strstr(gl_string, "NVIDIA");
510 if (!gl_string_cursor) {
511 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
515 gl_string_cursor = strstr(gl_string_cursor, " ");
516 if (!gl_string_cursor) {
517 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
521 while (*gl_string_cursor == ' ') {
525 if (!*gl_string_cursor) {
526 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
530 major = atoi(gl_string_cursor);
531 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
535 if (*gl_string_cursor++ != '.') {
536 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
540 minor = atoi(gl_string_cursor);
541 minor = major*100+minor;
548 gl_string_cursor = strchr(gl_string, '-');
549 if (gl_string_cursor) {
553 /* Check if version number is of the form x.y.z */
554 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
556 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
558 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
560 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
563 /* Mark version number as malformed */
565 gl_string_cursor = 0;
568 if (!gl_string_cursor)
569 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
571 major = *gl_string_cursor - '0';
572 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
578 gl_string_cursor = strstr(gl_string, "Mesa");
579 gl_string_cursor = strstr(gl_string_cursor, " ");
580 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
581 if (*gl_string_cursor) {
585 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
586 tmp[cursor++] = *gl_string_cursor;
592 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
596 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
597 tmp[cursor++] = *gl_string_cursor;
609 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
610 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
613 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
616 * Initialize openGL extension related variables
617 * with Default values
619 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
620 gl_info->max_buffers = 1;
621 gl_info->max_textures = 1;
622 gl_info->max_texture_stages = 1;
623 gl_info->max_fragment_samplers = 1;
624 gl_info->max_vertex_samplers = 0;
625 gl_info->max_combined_samplers = 0;
626 gl_info->max_sampler_stages = 1;
627 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
628 gl_info->ps_arb_max_temps = 0;
629 gl_info->ps_arb_max_instructions = 0;
630 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
631 gl_info->vs_arb_max_temps = 0;
632 gl_info->vs_arb_max_instructions = 0;
633 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
634 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
635 gl_info->vs_glsl_constantsF = 0;
636 gl_info->ps_glsl_constantsF = 0;
637 gl_info->vs_arb_constantsF = 0;
638 gl_info->ps_arb_constantsF = 0;
640 /* Retrieve opengl defaults */
641 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
642 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
643 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
645 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
646 gl_info->max_lights = gl_max;
647 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
649 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
650 gl_info->max_texture_size = gl_max;
651 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
653 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
654 gl_info->max_pointsizemin = gl_floatv[0];
655 gl_info->max_pointsize = gl_floatv[1];
656 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
658 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
659 gl_info->max_aux_buffers = gl_max;
660 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
662 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
663 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
664 TRACE_(d3d_caps)("GL_Extensions reported:\n");
666 if (NULL == GL_Extensions) {
667 ERR(" GL_Extensions returns NULL\n");
669 while (*GL_Extensions != 0x00) {
674 while (isspace(*GL_Extensions)) GL_Extensions++;
675 Start = GL_Extensions;
676 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
680 len = GL_Extensions - Start;
681 if (len == 0 || len >= sizeof(ThisExtn))
684 memcpy(ThisExtn, Start, len);
685 ThisExtn[len] = '\0';
686 TRACE_(d3d_caps)("- %s\n", ThisExtn);
688 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
689 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
690 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
691 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
696 /* Now work out what GL support this card really has */
697 #define USE_GL_FUNC(type, pfn, ext, replace) { \
698 DWORD ver = ver_for_ext(ext); \
699 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
700 else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
701 else gl_info->pfn = NULL; \
706 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
710 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
711 * loading the functions, otherwise the code above will load the extension entry points instead of the
712 * core functions, which may not work
714 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
715 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
716 EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
717 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
718 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
722 if (gl_info->supported[APPLE_FENCE]) {
723 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
724 * The apple extension interacts with some other apple exts. Disable the NV
725 * extension if the apple one is support to prevent confusion in other parts
728 gl_info->supported[NV_FENCE] = FALSE;
730 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
731 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
732 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
734 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
735 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
736 * Won't occur in any real world situation though
738 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
740 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
741 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
742 gl_info->max_buffers = gl_max;
743 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
745 if (gl_info->supported[ARB_MULTITEXTURE]) {
746 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
747 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
748 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
750 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
752 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
753 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
755 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
757 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
759 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
761 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
762 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
764 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
766 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
768 if (gl_info->supported[ARB_VERTEX_SHADER]) {
770 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
771 gl_info->max_vertex_samplers = tmp;
772 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
773 gl_info->max_combined_samplers = tmp;
775 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
776 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
777 * an issue because then the sampler setup only depends on the two shaders. If a pixel
778 * shader is used with fixed function vertex processing we're fine too because fixed function
779 * vertex processing doesn't use any samplers. If fixed function fragment processing is
780 * used we have to make sure that all vertex sampler setups are valid together with all
781 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
782 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
783 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
784 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
785 * a fixed function pipeline anymore.
787 * So this is just a check to check that our assumption holds true. If not, write a warning
788 * and reduce the number of vertex samplers or propably disable vertex texture fetch.
790 if(gl_info->max_vertex_samplers &&
791 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
792 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
793 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
794 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
795 if( gl_info->max_combined_samplers > MAX_TEXTURES )
796 gl_info->max_vertex_samplers =
797 gl_info->max_combined_samplers - MAX_TEXTURES;
799 gl_info->max_vertex_samplers = 0;
802 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
804 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
805 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
807 if (gl_info->supported[ARB_VERTEX_BLEND]) {
808 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
809 gl_info->max_blends = gl_max;
810 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
812 if (gl_info->supported[EXT_TEXTURE3D]) {
813 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
814 gl_info->max_texture3d_size = gl_max;
815 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
817 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
818 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
819 gl_info->max_anisotropy = gl_max;
820 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
822 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
823 gl_info->ps_arb_version = PS_VERSION_11;
824 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
825 gl_info->ps_arb_constantsF = gl_max;
826 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
827 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
828 gl_info->ps_arb_max_temps = gl_max;
829 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
830 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
831 gl_info->ps_arb_max_instructions = gl_max;
832 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
834 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
835 gl_info->vs_arb_version = VS_VERSION_11;
836 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
837 gl_info->vs_arb_constantsF = gl_max;
838 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
839 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
840 gl_info->vs_arb_max_temps = gl_max;
841 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
842 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
843 gl_info->vs_arb_max_instructions = gl_max;
844 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
846 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
848 if (gl_info->supported[ARB_VERTEX_SHADER]) {
849 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
850 gl_info->vs_glsl_constantsF = gl_max / 4;
851 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
853 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
854 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
855 gl_info->ps_glsl_constantsF = gl_max / 4;
856 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
857 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
858 gl_info->max_glsl_varyings = gl_max;
859 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
861 if (gl_info->supported[EXT_VERTEX_SHADER]) {
862 gl_info->vs_ati_version = VS_VERSION_11;
864 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
865 gl_info->vs_nv_version = VS_VERSION_30;
866 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
867 gl_info->vs_nv_version = VS_VERSION_20;
868 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
869 gl_info->vs_nv_version = VS_VERSION_11;
870 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
871 gl_info->vs_nv_version = VS_VERSION_10;
873 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
874 gl_info->ps_nv_version = PS_VERSION_30;
875 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
876 gl_info->ps_nv_version = PS_VERSION_20;
878 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
879 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
880 * This saves a few redundant glDisable calls
882 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
886 checkGLcall("extension detection\n");
888 /* In some cases the number of texture stages can be larger than the number
889 * of samplers. The GF4 for example can use only 2 samplers (no fragment
890 * shaders), but 8 texture stages (register combiners). */
891 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
893 /* We can only use ORM_FBO when the hardware supports it. */
894 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
895 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
896 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
899 /* MRTs are currently only supported when FBOs are used. */
900 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
901 gl_info->max_buffers = 1;
904 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
905 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
906 * in case of the latest videocards in the number of pixel/vertex pipelines.
908 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
909 * rendering. Various games use this information to get a rough estimation of the features of the card
910 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
911 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
912 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
915 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
916 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
917 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
918 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
919 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
920 * is used for rendering which is not always the case). This would work but it is not very portable. Second
921 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
924 * As said most games only use the PCI id to get an indication of the capabilities of the card.
925 * It doesn't really matter if the given id is the correct one if we return the id of a card with
926 * similar 3d features.
928 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
929 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
930 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
931 * won't pass we return a default card. This way is better than maintaining a full card database as even
932 * without a full database we can return a card with similar features. Second the size of the database
933 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
934 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
935 * to distinguishes between different models from that family.
937 * The code also selects a default amount of video memory which we will use for an estimation of the amount
938 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
939 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
940 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
941 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
942 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
943 * memory behind our backs if really needed.
944 * Note that the amout of video memory can be overruled using a registry setting.
946 switch (gl_info->gl_vendor) {
948 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
949 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
951 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
952 /* Geforce8 - highend */
953 if (strstr(gl_info->gl_renderer, "8800")) {
954 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
955 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
957 /* Geforce8 - midend */
958 else if(strstr(gl_info->gl_renderer, "8600") ||
959 strstr(gl_info->gl_renderer, "8700"))
961 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
964 /* Geforce8 - midend mobile */
965 else if(strstr(gl_info->gl_renderer, "8600 M")) {
966 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
969 /* Geforce8 - lowend */
970 else if(strstr(gl_info->gl_renderer, "8300") ||
971 strstr(gl_info->gl_renderer, "8400") ||
972 strstr(gl_info->gl_renderer, "8500"))
974 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
975 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
977 /* Geforce7 - highend */
978 else if(strstr(gl_info->gl_renderer, "7800") ||
979 strstr(gl_info->gl_renderer, "7900") ||
980 strstr(gl_info->gl_renderer, "7950") ||
981 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
982 strstr(gl_info->gl_renderer, "Quadro FX 5"))
984 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
985 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
987 /* Geforce7 midend */
988 else if(strstr(gl_info->gl_renderer, "7600") ||
989 strstr(gl_info->gl_renderer, "7700")) {
990 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
991 vidmem = 256; /* The 7600 uses 256-512MB */
992 /* Geforce7 lower medium */
993 } else if(strstr(gl_info->gl_renderer, "7400")) {
994 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
995 vidmem = 256; /* The 7400 uses 256-512MB */
997 /* Geforce6 highend */
998 else if(strstr(gl_info->gl_renderer, "6800"))
1000 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1001 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1003 /* Geforce6 - midend */
1004 else if(strstr(gl_info->gl_renderer, "6600") ||
1005 strstr(gl_info->gl_renderer, "6610") ||
1006 strstr(gl_info->gl_renderer, "6700"))
1008 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1009 vidmem = 128; /* A 6600GT has 128-256MB */
1011 /* Geforce6/7 lowend */
1013 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1016 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1017 /* GeforceFX - highend */
1018 if (strstr(gl_info->gl_renderer, "5800") ||
1019 strstr(gl_info->gl_renderer, "5900") ||
1020 strstr(gl_info->gl_renderer, "5950") ||
1021 strstr(gl_info->gl_renderer, "Quadro FX"))
1023 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1024 vidmem = 256; /* 5800-5900 cards use 256MB */
1026 /* GeforceFX - midend */
1027 else if(strstr(gl_info->gl_renderer, "5600") ||
1028 strstr(gl_info->gl_renderer, "5650") ||
1029 strstr(gl_info->gl_renderer, "5700") ||
1030 strstr(gl_info->gl_renderer, "5750"))
1032 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1033 vidmem = 128; /* A 5600 uses 128-256MB */
1035 /* GeforceFX - lowend */
1037 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1038 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1040 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1041 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1042 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1043 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1046 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1047 vidmem = 64; /* Geforce3 cards have 64-128MB */
1049 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1050 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1051 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1052 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1054 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1055 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1056 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1058 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1059 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1060 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1063 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1064 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1067 if (strstr(gl_info->gl_renderer, "TNT2")) {
1068 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1069 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1072 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1073 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1078 if(WINE_D3D9_CAPABLE(gl_info)) {
1079 /* Radeon R6xx HD2900 - highend */
1080 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1081 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1082 vidmem = 512; /* HD2900 uses 512-1024MB */
1084 /* Radeon R6xx HD2600- midend */
1085 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1086 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1087 vidmem = 256; /* HD2600 uses 256-512MB */
1089 /* Radeon R6xx HD2300/HD2400 - lowend */
1090 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1091 strstr(gl_info->gl_renderer, "HD 2400"))
1093 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1094 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1097 else if (strstr(gl_info->gl_renderer, "X1600") ||
1098 strstr(gl_info->gl_renderer, "X1650") ||
1099 strstr(gl_info->gl_renderer, "X1800") ||
1100 strstr(gl_info->gl_renderer, "X1900") ||
1101 strstr(gl_info->gl_renderer, "X1950"))
1103 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1104 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1106 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1107 else if(strstr(gl_info->gl_renderer, "X700") ||
1108 strstr(gl_info->gl_renderer, "X800") ||
1109 strstr(gl_info->gl_renderer, "X850") ||
1110 strstr(gl_info->gl_renderer, "X1300") ||
1111 strstr(gl_info->gl_renderer, "X1400") ||
1112 strstr(gl_info->gl_renderer, "X1450") ||
1113 strstr(gl_info->gl_renderer, "X1550"))
1115 gl_info->gl_card = CARD_ATI_RADEON_X700;
1116 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1120 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1121 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1123 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1124 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1125 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1126 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1127 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1128 vidmem = 32; /* There are models with up to 64MB */
1130 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1131 vidmem = 16; /* There are 16-32MB models */
1135 if (strstr(gl_info->gl_renderer, "915GM")) {
1136 gl_info->gl_card = CARD_INTEL_I915GM;
1137 } else if (strstr(gl_info->gl_renderer, "915G")) {
1138 gl_info->gl_card = CARD_INTEL_I915G;
1139 } else if (strstr(gl_info->gl_renderer, "865G")) {
1140 gl_info->gl_card = CARD_INTEL_I865G;
1141 } else if (strstr(gl_info->gl_renderer, "855G")) {
1142 gl_info->gl_card = CARD_INTEL_I855G;
1143 } else if (strstr(gl_info->gl_renderer, "830G")) {
1144 gl_info->gl_card = CARD_INTEL_I830G;
1146 gl_info->gl_card = CARD_INTEL_I915G;
1152 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1153 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1154 * them a good generic choice.
1156 gl_info->gl_vendor = VENDOR_NVIDIA;
1157 if(WINE_D3D9_CAPABLE(gl_info))
1158 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1159 else if(WINE_D3D8_CAPABLE(gl_info))
1160 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1161 else if(WINE_D3D7_CAPABLE(gl_info))
1162 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1163 else if(WINE_D3D6_CAPABLE(gl_info))
1164 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1166 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1168 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1170 /* If we have an estimate use it, else default to 64MB; */
1172 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1174 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1176 /* Load all the lookup tables
1177 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1178 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1179 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1181 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1182 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1185 for (i = 0; i < MAX_LOOKUPS; i++) {
1186 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1189 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1190 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1191 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1192 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1193 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1194 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1195 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1196 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1197 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1198 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1200 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1201 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1202 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1203 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1204 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1207 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1208 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1209 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1210 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1211 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1212 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1213 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1214 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1215 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1216 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1217 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1218 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1219 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1221 /* TODO: config lookups */
1223 /* Make sure there's an active HDC else the WGL extensions will fail */
1224 hdc = pwglGetCurrentDC();
1226 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1227 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1229 if (NULL == WGL_Extensions) {
1230 ERR(" WGL_Extensions returns NULL\n");
1232 while (*WGL_Extensions != 0x00) {
1237 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1238 Start = WGL_Extensions;
1239 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1243 len = WGL_Extensions - Start;
1244 if (len == 0 || len >= sizeof(ThisExtn))
1247 memcpy(ThisExtn, Start, len);
1248 ThisExtn[len] = '\0';
1249 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1251 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1252 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1253 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1260 return return_value;
1262 #undef GLINFO_LOCATION
1264 /**********************************************************
1265 * IWineD3D implementation follows
1266 **********************************************************/
1268 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1269 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1271 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1275 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1276 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1277 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1281 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1282 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1284 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1288 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1289 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1292 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1293 of the same bpp but different resolutions */
1295 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1296 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1297 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1298 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1300 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1304 /* TODO: Store modes per adapter and read it from the adapter structure */
1305 if (Adapter == 0) { /* Display */
1309 if (!DEBUG_SINGLE_MODE) {
1312 ZeroMemory(&DevModeW, sizeof(DevModeW));
1313 DevModeW.dmSize = sizeof(DevModeW);
1314 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1318 case WINED3DFMT_UNKNOWN:
1319 /* This is for D3D8, do not enumerate P8 here */
1320 if (DevModeW.dmBitsPerPel == 32 ||
1321 DevModeW.dmBitsPerPel == 16) i++;
1323 case WINED3DFMT_X8R8G8B8:
1324 if (DevModeW.dmBitsPerPel == 32) i++;
1326 case WINED3DFMT_R5G6B5:
1327 if (DevModeW.dmBitsPerPel == 16) i++;
1330 if (DevModeW.dmBitsPerPel == 8) i++;
1333 /* Skip other modes as they do not match the requested format */
1342 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1345 FIXME_(d3d_caps)("Adapter not primary display\n");
1350 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1351 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1352 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1353 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1355 /* Validate the parameters as much as possible */
1356 if (NULL == pMode ||
1357 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1358 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1359 return WINED3DERR_INVALIDCALL;
1362 /* TODO: Store modes per adapter and read it from the adapter structure */
1363 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1369 ZeroMemory(&DevModeW, sizeof(DevModeW));
1370 DevModeW.dmSize = sizeof(DevModeW);
1372 /* If we are filtering to a specific format (D3D9), then need to skip
1373 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1374 just count through the ones with valid bit depths */
1375 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1378 case WINED3DFMT_UNKNOWN:
1379 /* This is D3D8. Do not enumerate P8 here */
1380 if (DevModeW.dmBitsPerPel == 32 ||
1381 DevModeW.dmBitsPerPel == 16) i++;
1383 case WINED3DFMT_X8R8G8B8:
1384 if (DevModeW.dmBitsPerPel == 32) i++;
1386 case WINED3DFMT_R5G6B5:
1387 if (DevModeW.dmBitsPerPel == 16) i++;
1390 if (DevModeW.dmBitsPerPel == 8) i++;
1393 /* Modes that don't match what we support can get an early-out */
1394 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1395 return WINED3DERR_INVALIDCALL;
1400 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1401 return WINED3DERR_INVALIDCALL;
1405 /* Now get the display mode via the calculated index */
1406 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1407 pMode->Width = DevModeW.dmPelsWidth;
1408 pMode->Height = DevModeW.dmPelsHeight;
1409 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1410 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1411 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1413 if (Format == WINED3DFMT_UNKNOWN) {
1414 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1416 pMode->Format = Format;
1419 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1420 return WINED3DERR_INVALIDCALL;
1423 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1424 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1425 DevModeW.dmBitsPerPel);
1427 } else if (DEBUG_SINGLE_MODE) {
1428 /* Return one setting of the format requested */
1429 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1431 pMode->Height = 600;
1432 pMode->RefreshRate = 60;
1433 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1435 FIXME_(d3d_caps)("Adapter not primary display\n");
1441 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1442 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1443 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1445 if (NULL == pMode ||
1446 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1447 return WINED3DERR_INVALIDCALL;
1450 if (Adapter == 0) { /* Display */
1454 ZeroMemory(&DevModeW, sizeof(DevModeW));
1455 DevModeW.dmSize = sizeof(DevModeW);
1457 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1458 pMode->Width = DevModeW.dmPelsWidth;
1459 pMode->Height = DevModeW.dmPelsHeight;
1460 bpp = DevModeW.dmBitsPerPel;
1461 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1462 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1464 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1467 pMode->Format = pixelformat_for_depth(bpp);
1469 FIXME_(d3d_caps)("Adapter not primary display\n");
1472 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1473 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1477 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1478 and fields being inserted in the middle, a new structure is used in place */
1479 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1480 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1481 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1483 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1485 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1486 return WINED3DERR_INVALIDCALL;
1489 /* Return the information requested */
1490 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1491 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1492 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1494 /* Note dx8 doesn't supply a DeviceName */
1495 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1496 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1497 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1498 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1499 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1500 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1501 *(pIdentifier->SubSysId) = 0;
1502 *(pIdentifier->Revision) = 0;
1504 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1505 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1506 *(pIdentifier->WHQLLevel) = 0;
1508 *(pIdentifier->WHQLLevel) = 1;
1514 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1515 short redSize, greenSize, blueSize, alphaSize, colorBits;
1520 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1521 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1525 if(cfg->redSize < redSize)
1528 if(cfg->greenSize < greenSize)
1531 if(cfg->blueSize < blueSize)
1534 if(cfg->alphaSize < alphaSize)
1540 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1541 short depthSize, stencilSize;
1546 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1547 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1551 if(cfg->depthSize < depthSize)
1554 if(cfg->stencilSize < stencilSize)
1560 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1561 WINED3DFORMAT AdapterFormat,
1562 WINED3DFORMAT RenderTargetFormat,
1563 WINED3DFORMAT DepthStencilFormat) {
1564 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1566 WineD3D_PixelFormat *cfgs;
1569 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1571 DeviceType, debug_d3ddevicetype(DeviceType),
1572 AdapterFormat, debug_d3dformat(AdapterFormat),
1573 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1574 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1576 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1577 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1578 return WINED3DERR_INVALIDCALL;
1581 cfgs = Adapters[Adapter].cfgs;
1582 nCfgs = Adapters[Adapter].nCfgs;
1583 for (it = 0; it < nCfgs; ++it) {
1584 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1585 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1586 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1591 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1593 return WINED3DERR_NOTAVAILABLE;
1596 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1597 WINED3DFORMAT SurfaceFormat,
1598 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1600 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1601 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1604 DeviceType, debug_d3ddevicetype(DeviceType),
1605 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1610 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1611 return WINED3DERR_INVALIDCALL;
1614 /* TODO: Store in Adapter structure */
1615 if (pQualityLevels != NULL) {
1616 static int s_single_shot = 0;
1617 if (!s_single_shot) {
1618 FIXME("Quality levels unsupported at present\n");
1621 *pQualityLevels = 1; /* Guess at a value! */
1624 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1625 return WINED3DERR_NOTAVAILABLE;
1628 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1629 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1631 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1633 WineD3D_PixelFormat *cfgs;
1635 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1637 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1640 CheckType, debug_d3ddevicetype(CheckType),
1641 DisplayFormat, debug_d3dformat(DisplayFormat),
1642 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1645 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1646 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1647 return WINED3DERR_INVALIDCALL;
1650 cfgs = Adapters[Adapter].cfgs;
1651 nCfgs = Adapters[Adapter].nCfgs;
1652 for (it = 0; it < nCfgs; ++it) {
1653 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1655 TRACE_(d3d_caps)("OK\n");
1660 if(hr != WINED3D_OK)
1661 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1663 if(hr != WINED3D_OK)
1664 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1669 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1670 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1671 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1672 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1673 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1676 DeviceType, debug_d3ddevicetype(DeviceType),
1677 AdapterFormat, debug_d3dformat(AdapterFormat),
1678 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1679 RType, debug_d3dresourcetype(RType),
1680 CheckFormat, debug_d3dformat(CheckFormat));
1682 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1683 return WINED3DERR_INVALIDCALL;
1686 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1687 switch (CheckFormat) {
1688 /* Filtering not supported */
1689 case WINED3DFMT_R32F:
1690 case WINED3DFMT_A32B32G32R32F:
1691 TRACE_(d3d_caps)("[FAILED]\n");
1692 return WINED3DERR_NOTAVAILABLE;
1698 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1699 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1700 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1701 return WINED3DERR_NOTAVAILABLE;
1705 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1706 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1707 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1708 return WINED3DERR_NOTAVAILABLE;
1710 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1711 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1712 * app needing one of those formats, don't advertize them to avoid leading apps into
1713 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1716 switch(CheckFormat) {
1718 case WINED3DFMT_A4L4:
1719 case WINED3DFMT_R32F:
1720 case WINED3DFMT_R16F:
1721 case WINED3DFMT_X8L8V8U8:
1722 case WINED3DFMT_L6V5U5:
1723 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1724 return WINED3DERR_NOTAVAILABLE;
1726 case WINED3DFMT_Q8W8V8U8:
1727 case WINED3DFMT_V16U16:
1728 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1729 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1730 return WINED3DERR_NOTAVAILABLE;
1734 case WINED3DFMT_V8U8:
1735 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1736 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1737 return WINED3DERR_NOTAVAILABLE;
1741 case WINED3DFMT_DXT1:
1742 case WINED3DFMT_DXT2:
1743 case WINED3DFMT_DXT3:
1744 case WINED3DFMT_DXT4:
1745 case WINED3DFMT_DXT5:
1746 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1747 * compressed texture results in an error. While the D3D refrast does
1748 * support s3tc volumes, at least the nvidia windows driver does not, so
1749 * we're free not to support this format.
1751 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1752 return WINED3DERR_NOTAVAILABLE;
1755 /* Do nothing, continue with checking the format below */
1759 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1760 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1761 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1762 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1763 if (!GL_LIMITS(vertex_samplers)) {
1764 TRACE_(d3d_caps)("[FAILED]\n");
1765 return WINED3DERR_NOTAVAILABLE;
1768 switch (CheckFormat) {
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");
1778 TRACE_(d3d_caps)("[FAILED]\n");
1779 return WINED3DERR_NOTAVAILABLE;
1783 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1784 switch (CheckFormat) {
1785 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1786 * Windows supports only those 3, and enumerating the other formats confuses applications
1788 case WINED3DFMT_D24S8:
1789 case WINED3DFMT_D24X8:
1790 case WINED3DFMT_D16:
1791 TRACE_(d3d_caps)("[OK]\n");
1793 case WINED3DFMT_D16_LOCKABLE:
1794 case WINED3DFMT_D24FS8:
1795 case WINED3DFMT_D32F_LOCKABLE:
1796 case WINED3DFMT_D24X4S4:
1797 case WINED3DFMT_D15S1:
1798 case WINED3DFMT_D32:
1799 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1800 return WINED3DERR_NOTAVAILABLE;
1802 TRACE_(d3d_caps)("[FAILED]\n");
1803 return WINED3DERR_NOTAVAILABLE;
1805 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1806 switch (CheckFormat) {
1807 case WINED3DFMT_R8G8B8:
1808 case WINED3DFMT_A8R8G8B8:
1809 case WINED3DFMT_X8R8G8B8:
1810 case WINED3DFMT_R5G6B5:
1811 case WINED3DFMT_X1R5G5B5:
1812 case WINED3DFMT_A1R5G5B5:
1813 case WINED3DFMT_A4R4G4B4:
1814 case WINED3DFMT_R3G3B2:
1815 case WINED3DFMT_X4R4G4B4:
1816 case WINED3DFMT_A8B8G8R8:
1817 case WINED3DFMT_X8B8G8R8:
1819 TRACE_(d3d_caps)("[OK]\n");
1821 case WINED3DFMT_R16F:
1822 case WINED3DFMT_A16B16G16R16F:
1823 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1824 TRACE_(d3d_caps)("[FAILED]\n");
1825 return WINED3DERR_NOTAVAILABLE;
1827 TRACE_(d3d_caps)("[OK]\n");
1829 case WINED3DFMT_A32B32G32R32F:
1830 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1831 TRACE_(d3d_caps)("[FAILED]\n");
1832 return WINED3DERR_NOTAVAILABLE;
1834 TRACE_(d3d_caps)("[OK]\n");
1837 TRACE_(d3d_caps)("[FAILED]\n");
1838 return WINED3DERR_NOTAVAILABLE;
1840 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1841 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1842 switch (CheckFormat) {
1843 case WINED3DFMT_V8U8:
1844 TRACE_(d3d_caps)("[OK]\n");
1846 /* TODO: Other bump map formats */
1848 TRACE_(d3d_caps)("[FAILED]\n");
1849 return WINED3DERR_NOTAVAILABLE;
1852 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1853 switch (CheckFormat) {
1854 case WINED3DFMT_V8U8:
1855 TRACE_(d3d_caps)("[OK]\n");
1858 TRACE_(d3d_caps)("[FAILED]\n");
1859 return WINED3DERR_NOTAVAILABLE;
1862 TRACE_(d3d_caps)("[FAILED]\n");
1863 return WINED3DERR_NOTAVAILABLE;
1866 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1867 switch (CheckFormat) {
1868 case WINED3DFMT_DXT1:
1869 case WINED3DFMT_DXT2:
1870 case WINED3DFMT_DXT3:
1871 case WINED3DFMT_DXT4:
1872 case WINED3DFMT_DXT5:
1873 TRACE_(d3d_caps)("[OK]\n");
1876 break; /* Avoid compiler warnings */
1880 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1881 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1882 switch (CheckFormat) {
1883 case WINED3DFMT_A8R8G8B8:
1884 case WINED3DFMT_X8R8G8B8:
1885 case WINED3DFMT_A4R4G4B4:
1887 case WINED3DFMT_A8L8:
1888 case WINED3DFMT_DXT1:
1889 case WINED3DFMT_DXT2:
1890 case WINED3DFMT_DXT3:
1891 case WINED3DFMT_DXT4:
1892 case WINED3DFMT_DXT5:
1893 TRACE_(d3d_caps)("[OK]\n");
1897 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1898 return WINED3DERR_NOTAVAILABLE;
1902 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1904 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1906 switch (CheckFormat) {
1907 case WINED3DFMT_R16F:
1908 case WINED3DFMT_A16B16G16R16F:
1909 if (!half_pixel_support) break;
1910 case WINED3DFMT_R32F:
1911 case WINED3DFMT_A32B32G32R32F:
1912 TRACE_(d3d_caps)("[OK]\n");
1915 break; /* Avoid compiler warnings */
1919 /* This format is nothing special and it is supported perfectly.
1920 * However, ati and nvidia driver on windows do not mark this format as
1921 * supported (tested with the dxCapsViewer) and pretending to
1922 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1923 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1924 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1926 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1927 TRACE_(d3d_caps)("[FAILED]\n");
1928 return WINED3DERR_NOTAVAILABLE;
1931 switch (CheckFormat) {
1934 * supported: RGB(A) formats
1936 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1937 case WINED3DFMT_A8R8G8B8:
1938 case WINED3DFMT_X8R8G8B8:
1939 case WINED3DFMT_R5G6B5:
1940 case WINED3DFMT_X1R5G5B5:
1941 case WINED3DFMT_A1R5G5B5:
1942 case WINED3DFMT_A4R4G4B4:
1943 case WINED3DFMT_R3G3B2:
1945 case WINED3DFMT_X4R4G4B4:
1946 case WINED3DFMT_A8B8G8R8:
1947 case WINED3DFMT_X8B8G8R8:
1948 case WINED3DFMT_A2R10G10B10:
1949 case WINED3DFMT_A2B10G10R10:
1950 TRACE_(d3d_caps)("[OK]\n");
1954 * supported: Palettized
1957 TRACE_(d3d_caps)("[OK]\n");
1961 * Supported: (Alpha)-Luminance
1964 case WINED3DFMT_A8L8:
1965 case WINED3DFMT_A4L4:
1966 TRACE_(d3d_caps)("[OK]\n");
1970 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
1971 * GL_NV_texture_shader), but advertized to make apps happy.
1972 * Enable some because games often fail when they are not available
1973 * and are still playable even without bump mapping
1975 case WINED3DFMT_V8U8:
1976 case WINED3DFMT_V16U16:
1977 case WINED3DFMT_L6V5U5:
1978 case WINED3DFMT_X8L8V8U8:
1979 case WINED3DFMT_Q8W8V8U8:
1980 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1983 /* Those are not advertized by the nvidia windows driver, and not
1984 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
1985 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
1986 * ARGB format if needed
1988 case WINED3DFMT_W11V11U10:
1989 case WINED3DFMT_A2W10V10U10:
1990 WARN_(d3d_caps)("[FAILED]\n");
1991 return WINED3DERR_NOTAVAILABLE;
1994 * DXTN Formats: Handled above
2003 * Odd formats - not supported
2005 case WINED3DFMT_VERTEXDATA:
2006 case WINED3DFMT_INDEX16:
2007 case WINED3DFMT_INDEX32:
2008 case WINED3DFMT_Q16W16V16U16:
2009 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2010 return WINED3DERR_NOTAVAILABLE;
2013 * Float formats: Not supported right now
2015 case WINED3DFMT_G16R16F:
2016 case WINED3DFMT_G32R32F:
2017 case WINED3DFMT_CxV8U8:
2018 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2019 return WINED3DERR_NOTAVAILABLE;
2022 case WINED3DFMT_G16R16:
2023 case WINED3DFMT_A16B16G16R16:
2024 case WINED3DFMT_A8R3G3B2:
2025 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2026 return WINED3DERR_NOTAVAILABLE;
2028 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2029 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2030 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2031 * We can do instancing with all shader versions, but we need vertex shaders.
2033 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2034 * to enable instancing. WineD3D doesn't need that and just ignores it.
2036 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2038 case WINEMAKEFOURCC('I','N','S','T'):
2039 TRACE("ATI Instancing check hack\n");
2040 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2041 TRACE_(d3d_caps)("[OK]\n");
2044 TRACE_(d3d_caps)("[FAILED]\n");
2045 return WINED3DERR_NOTAVAILABLE;
2052 TRACE_(d3d_caps)("[FAILED]\n");
2053 return WINED3DERR_NOTAVAILABLE;
2056 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2057 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2058 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2060 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2063 DeviceType, debug_d3ddevicetype(DeviceType),
2064 SourceFormat, debug_d3dformat(SourceFormat),
2065 TargetFormat, debug_d3dformat(TargetFormat));
2069 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2070 subset of a D3DCAPS9 structure. However, it has to come via a void *
2071 as the d3d8 interface cannot import the d3d9 header */
2072 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2074 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2075 int vs_selected_mode;
2076 int ps_selected_mode;
2078 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2080 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2081 return WINED3DERR_INVALIDCALL;
2084 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2086 /* This function should *not* be modifying GL caps
2087 * TODO: move the functionality where it belongs */
2088 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2090 /* ------------------------------------------------
2091 The following fields apply to both d3d8 and d3d9
2092 ------------------------------------------------ */
2093 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2094 *pCaps->AdapterOrdinal = Adapter;
2097 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2098 WINED3DCAPS2_FULLSCREENGAMMA |
2099 WINED3DCAPS2_DYNAMICTEXTURES;
2100 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2101 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2103 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2104 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2105 WINED3DPRESENT_INTERVAL_ONE;
2107 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2108 WINED3DCURSORCAPS_LOWRES;
2110 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2111 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2112 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2113 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2114 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2115 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2116 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2117 WINED3DDEVCAPS_PUREDEVICE |
2118 WINED3DDEVCAPS_HWRASTERIZATION |
2119 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2120 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2121 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2122 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2123 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2124 WINED3DDEVCAPS_RTPATCHES;
2126 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2127 WINED3DPMISCCAPS_CULLCCW |
2128 WINED3DPMISCCAPS_CULLCW |
2129 WINED3DPMISCCAPS_COLORWRITEENABLE |
2130 WINED3DPMISCCAPS_CLIPTLVERTS |
2131 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2132 WINED3DPMISCCAPS_MASKZ |
2133 WINED3DPMISCCAPS_BLENDOP;
2135 WINED3DPMISCCAPS_NULLREFERENCE
2136 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2137 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2138 WINED3DPMISCCAPS_SEPARATEALPHABLEND
2139 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2140 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2141 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2143 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2145 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2146 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2147 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2148 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2151 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2152 WINED3DPRASTERCAPS_PAT |
2153 WINED3DPRASTERCAPS_WFOG |
2154 WINED3DPRASTERCAPS_ZFOG |
2155 WINED3DPRASTERCAPS_FOGVERTEX |
2156 WINED3DPRASTERCAPS_FOGTABLE |
2157 WINED3DPRASTERCAPS_STIPPLE |
2158 WINED3DPRASTERCAPS_SUBPIXEL |
2159 WINED3DPRASTERCAPS_ZTEST |
2160 WINED3DPRASTERCAPS_SCISSORTEST |
2161 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2162 WINED3DPRASTERCAPS_DEPTHBIAS;
2164 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2165 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2166 WINED3DPRASTERCAPS_ZBIAS |
2167 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2169 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2170 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2173 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2174 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2175 WINED3DPRASTERCAPS_ANTIALIASEDGES
2176 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2177 WINED3DPRASTERCAPS_WBUFFER */
2179 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2180 WINED3DPCMPCAPS_EQUAL |
2181 WINED3DPCMPCAPS_GREATER |
2182 WINED3DPCMPCAPS_GREATEREQUAL |
2183 WINED3DPCMPCAPS_LESS |
2184 WINED3DPCMPCAPS_LESSEQUAL |
2185 WINED3DPCMPCAPS_NEVER |
2186 WINED3DPCMPCAPS_NOTEQUAL;
2188 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2189 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2190 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2191 WINED3DPBLENDCAPS_DESTALPHA |
2192 WINED3DPBLENDCAPS_DESTCOLOR |
2193 WINED3DPBLENDCAPS_INVDESTALPHA |
2194 WINED3DPBLENDCAPS_INVDESTCOLOR |
2195 WINED3DPBLENDCAPS_INVSRCALPHA |
2196 WINED3DPBLENDCAPS_INVSRCCOLOR |
2197 WINED3DPBLENDCAPS_ONE |
2198 WINED3DPBLENDCAPS_SRCALPHA |
2199 WINED3DPBLENDCAPS_SRCALPHASAT |
2200 WINED3DPBLENDCAPS_SRCCOLOR |
2201 WINED3DPBLENDCAPS_ZERO;
2203 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
2204 WINED3DPBLENDCAPS_DESTALPHA |
2205 WINED3DPBLENDCAPS_DESTCOLOR |
2206 WINED3DPBLENDCAPS_INVDESTALPHA |
2207 WINED3DPBLENDCAPS_INVDESTCOLOR |
2208 WINED3DPBLENDCAPS_INVSRCALPHA |
2209 WINED3DPBLENDCAPS_INVSRCCOLOR |
2210 WINED3DPBLENDCAPS_ONE |
2211 WINED3DPBLENDCAPS_SRCALPHA |
2212 WINED3DPBLENDCAPS_SRCCOLOR |
2213 WINED3DPBLENDCAPS_ZERO;
2214 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2215 * according to the glBlendFunc manpage
2217 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2218 * legacy settings for srcblend only
2221 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2222 WINED3DPCMPCAPS_EQUAL |
2223 WINED3DPCMPCAPS_GREATER |
2224 WINED3DPCMPCAPS_GREATEREQUAL |
2225 WINED3DPCMPCAPS_LESS |
2226 WINED3DPCMPCAPS_LESSEQUAL |
2227 WINED3DPCMPCAPS_NEVER |
2228 WINED3DPCMPCAPS_NOTEQUAL;
2230 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2231 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2232 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2233 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2234 WINED3DPSHADECAPS_COLORFLATRGB |
2235 WINED3DPSHADECAPS_FOGFLAT |
2236 WINED3DPSHADECAPS_FOGGOURAUD |
2237 WINED3DPSHADECAPS_SPECULARFLATRGB;
2239 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2240 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2241 WINED3DPTEXTURECAPS_BORDER |
2242 WINED3DPTEXTURECAPS_MIPMAP |
2243 WINED3DPTEXTURECAPS_PROJECTED |
2244 WINED3DPTEXTURECAPS_PERSPECTIVE;
2246 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2247 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2248 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2251 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2252 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2253 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2254 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2257 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2258 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2259 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2260 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2264 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2265 WINED3DPTFILTERCAPS_MAGFPOINT |
2266 WINED3DPTFILTERCAPS_MINFLINEAR |
2267 WINED3DPTFILTERCAPS_MINFPOINT |
2268 WINED3DPTFILTERCAPS_MIPFLINEAR |
2269 WINED3DPTFILTERCAPS_MIPFPOINT |
2270 WINED3DPTFILTERCAPS_LINEAR |
2271 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2272 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2273 WINED3DPTFILTERCAPS_MIPLINEAR |
2274 WINED3DPTFILTERCAPS_MIPNEAREST |
2275 WINED3DPTFILTERCAPS_NEAREST;
2277 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2278 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2279 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2282 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2283 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2284 WINED3DPTFILTERCAPS_MAGFPOINT |
2285 WINED3DPTFILTERCAPS_MINFLINEAR |
2286 WINED3DPTFILTERCAPS_MINFPOINT |
2287 WINED3DPTFILTERCAPS_MIPFLINEAR |
2288 WINED3DPTFILTERCAPS_MIPFPOINT |
2289 WINED3DPTFILTERCAPS_LINEAR |
2290 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2291 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2292 WINED3DPTFILTERCAPS_MIPLINEAR |
2293 WINED3DPTFILTERCAPS_MIPNEAREST |
2294 WINED3DPTFILTERCAPS_NEAREST;
2296 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2297 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2298 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2301 *pCaps->CubeTextureFilterCaps = 0;
2303 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2304 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2305 WINED3DPTFILTERCAPS_MAGFPOINT |
2306 WINED3DPTFILTERCAPS_MINFLINEAR |
2307 WINED3DPTFILTERCAPS_MINFPOINT |
2308 WINED3DPTFILTERCAPS_MIPFLINEAR |
2309 WINED3DPTFILTERCAPS_MIPFPOINT |
2310 WINED3DPTFILTERCAPS_LINEAR |
2311 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2312 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2313 WINED3DPTFILTERCAPS_MIPLINEAR |
2314 WINED3DPTFILTERCAPS_MIPNEAREST |
2315 WINED3DPTFILTERCAPS_NEAREST;
2317 *pCaps->VolumeTextureFilterCaps = 0;
2319 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2320 WINED3DPTADDRESSCAPS_CLAMP |
2321 WINED3DPTADDRESSCAPS_WRAP;
2323 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2324 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2326 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2327 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2329 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2330 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2333 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2334 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2335 WINED3DPTADDRESSCAPS_CLAMP |
2336 WINED3DPTADDRESSCAPS_WRAP;
2337 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2338 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2340 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2341 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2343 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2344 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2347 *pCaps->VolumeTextureAddressCaps = 0;
2349 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2350 WINED3DLINECAPS_ZTEST;
2352 WINED3DLINECAPS_BLEND
2353 WINED3DLINECAPS_ALPHACMP
2354 WINED3DLINECAPS_FOG */
2356 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2357 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2359 if(GL_SUPPORT(EXT_TEXTURE3D))
2360 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2362 *pCaps->MaxVolumeExtent = 0;
2364 *pCaps->MaxTextureRepeat = 32768;
2365 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2366 *pCaps->MaxVertexW = 1.0;
2368 *pCaps->GuardBandLeft = 0;
2369 *pCaps->GuardBandTop = 0;
2370 *pCaps->GuardBandRight = 0;
2371 *pCaps->GuardBandBottom = 0;
2373 *pCaps->ExtentsAdjust = 0;
2375 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2376 WINED3DSTENCILCAPS_INCRSAT |
2377 WINED3DSTENCILCAPS_INVERT |
2378 WINED3DSTENCILCAPS_KEEP |
2379 WINED3DSTENCILCAPS_REPLACE |
2380 WINED3DSTENCILCAPS_ZERO;
2381 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2382 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2383 WINED3DSTENCILCAPS_INCR;
2385 if ( This->dxVersion > 8 &&
2386 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2387 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2388 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2391 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2393 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2394 WINED3DTEXOPCAPS_ADDSIGNED |
2395 WINED3DTEXOPCAPS_ADDSIGNED2X |
2396 WINED3DTEXOPCAPS_MODULATE |
2397 WINED3DTEXOPCAPS_MODULATE2X |
2398 WINED3DTEXOPCAPS_MODULATE4X |
2399 WINED3DTEXOPCAPS_SELECTARG1 |
2400 WINED3DTEXOPCAPS_SELECTARG2 |
2401 WINED3DTEXOPCAPS_DISABLE;
2403 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2404 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2405 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2406 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2407 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2408 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2409 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2410 WINED3DTEXOPCAPS_LERP |
2411 WINED3DTEXOPCAPS_SUBTRACT;
2413 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2414 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2415 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2416 WINED3DTEXOPCAPS_MULTIPLYADD |
2417 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2418 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2419 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2421 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2422 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2424 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2425 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2426 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2429 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2430 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2431 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2432 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2433 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2434 * and 3D textures. It also allows us to keep the code simpler by having texture
2435 * shaders constantly enabled.
2437 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2438 /* TODO: Luminance bump map? */
2442 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2443 WINED3DTEXOPCAPS_PREMODULATE */
2446 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2447 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2448 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2449 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2451 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2452 *pCaps->MaxVertexBlendMatrixIndex = 0;
2454 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2455 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2458 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2459 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2460 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2461 WINED3DVTXPCAPS_LOCALVIEWER |
2462 WINED3DVTXPCAPS_VERTEXFOG |
2463 WINED3DVTXPCAPS_TEXGEN;
2465 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2467 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2468 *pCaps->MaxVertexIndex = 0xFFFFF;
2469 *pCaps->MaxStreams = MAX_STREAMS;
2470 *pCaps->MaxStreamStride = 1024;
2472 if (vs_selected_mode == SHADER_GLSL) {
2473 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2474 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2475 * vs_nv_version which is based on NV_vertex_program.
2476 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2477 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2478 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2479 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2480 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2481 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2483 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2484 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2485 } else if (vs_selected_mode == SHADER_ARB) {
2486 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2487 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2489 *pCaps->VertexShaderVersion = 0;
2490 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2493 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2495 if (ps_selected_mode == SHADER_GLSL) {
2496 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2497 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2498 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2499 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2500 * in max native instructions. Intel and others also offer the info in this extension but they
2501 * don't support GLSL (at least on Windows).
2503 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
2504 * of instructions is 512 or less we have to do with ps2.0 hardware.
2505 * 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.
2507 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2508 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2510 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2511 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2512 * Direct3D minimum requirement.
2514 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2515 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2517 * The problem is that the refrast clamps temporary results in the shader to
2518 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2519 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2520 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2521 * offer a way to query this.
2523 *pCaps->PixelShader1xMaxValue = 8.0;
2524 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2525 } else if (ps_selected_mode == SHADER_ARB) {
2526 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2527 *pCaps->PixelShader1xMaxValue = 8.0;
2528 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2530 *pCaps->PixelShaderVersion = 0;
2531 *pCaps->PixelShader1xMaxValue = 0.0;
2532 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2535 /* ------------------------------------------------
2536 The following fields apply to d3d9 only
2537 ------------------------------------------------ */
2538 if (This->dxVersion > 8) {
2539 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2540 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2541 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2542 *pCaps->MaxNpatchTessellationLevel = 0;
2543 *pCaps->MasterAdapterOrdinal = 0;
2544 *pCaps->AdapterOrdinalInGroup = 0;
2545 *pCaps->NumberOfAdaptersInGroup = 1;
2547 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2548 /* OpenGL supports all the formats below, perhaps not always
2549 * without conversion, but it supports them.
2550 * Further GLSL doesn't seem to have an official unsigned type so
2551 * don't advertise it yet as I'm not sure how we handle it.
2552 * We might need to add some clamping in the shader engine to
2554 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2555 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2556 WINED3DDTCAPS_UBYTE4N |
2557 WINED3DDTCAPS_SHORT2N |
2558 WINED3DDTCAPS_SHORT4N;
2559 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2560 *pCaps->DeclTypes |=
2561 WINED3DDTCAPS_FLOAT16_2 |
2562 WINED3DDTCAPS_FLOAT16_4;
2565 *pCaps->DeclTypes = 0;
2567 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2570 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2571 WINED3DPTFILTERCAPS_MAGFPOINT |
2572 WINED3DPTFILTERCAPS_MINFLINEAR |
2573 WINED3DPTFILTERCAPS_MAGFLINEAR;
2574 *pCaps->VertexTextureFilterCaps = 0;
2576 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2577 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2578 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2579 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2580 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2581 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2582 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2584 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2585 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2586 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2587 *pCaps->VS20Caps.Caps = 0;
2588 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2589 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2590 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2592 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2593 *pCaps->MaxVertexShader30InstructionSlots = 0;
2594 } else { /* VS 1.x */
2595 *pCaps->VS20Caps.Caps = 0;
2596 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2597 *pCaps->VS20Caps.NumTemps = 0;
2598 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2600 *pCaps->MaxVShaderInstructionsExecuted = 0;
2601 *pCaps->MaxVertexShader30InstructionSlots = 0;
2604 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2605 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2606 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2608 /* 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 */
2609 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2610 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2611 WINED3DPS20CAPS_PREDICATION |
2612 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2613 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2614 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2615 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2616 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2617 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2619 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2620 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2621 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2622 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2623 *pCaps->PS20Caps.Caps = 0;
2624 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2625 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2626 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2627 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2629 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2630 *pCaps->MaxPixelShader30InstructionSlots = 0;
2631 } else { /* PS 1.x */
2632 *pCaps->PS20Caps.Caps = 0;
2633 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2634 *pCaps->PS20Caps.NumTemps = 0;
2635 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2636 *pCaps->PS20Caps.NumInstructionSlots = 0;
2638 *pCaps->MaxPShaderInstructionsExecuted = 0;
2639 *pCaps->MaxPixelShader30InstructionSlots = 0;
2646 static unsigned int glsl_program_key_hash(void *key) {
2647 glsl_program_key_t *k = (glsl_program_key_t *)key;
2649 unsigned int hash = k->vshader | k->pshader << 16;
2650 hash += ~(hash << 15);
2651 hash ^= (hash >> 10);
2652 hash += (hash << 3);
2653 hash ^= (hash >> 6);
2654 hash += ~(hash << 11);
2655 hash ^= (hash >> 16);
2660 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2661 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2662 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2664 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2667 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2668 and fields being inserted in the middle, a new structure is used in place */
2669 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2670 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2673 IWineD3DDeviceImpl *object = NULL;
2674 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2678 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2679 * number and create a device without a 3D adapter for 2D only operation.
2681 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2682 return WINED3DERR_INVALIDCALL;
2685 /* Create a WineD3DDevice object */
2686 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2687 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2688 TRACE("Created WineD3DDevice object @ %p\n", object);
2689 if (NULL == object) {
2690 return WINED3DERR_OUTOFVIDEOMEMORY;
2693 /* Set up initial COM information */
2694 object->lpVtbl = &IWineD3DDevice_Vtbl;
2696 object->wineD3D = iface;
2697 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2698 IWineD3D_AddRef(object->wineD3D);
2699 object->parent = parent;
2700 list_init(&object->resources);
2702 if(This->dxVersion == 7) {
2703 object->surface_alignment = 8;
2705 object->surface_alignment = 4;
2707 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2709 /* Set the state up as invalid until the device is fully created */
2710 object->state = WINED3DERR_DRIVERINTERNALERROR;
2712 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2713 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2715 /* Save the creation parameters */
2716 object->createParms.AdapterOrdinal = Adapter;
2717 object->createParms.DeviceType = DeviceType;
2718 object->createParms.hFocusWindow = hFocusWindow;
2719 object->createParms.BehaviorFlags = BehaviourFlags;
2721 /* Initialize other useful values */
2722 object->adapterNo = Adapter;
2723 object->devType = DeviceType;
2725 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2726 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2727 object->shader_backend = &glsl_shader_backend;
2728 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2729 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2730 object->shader_backend = &arb_program_shader_backend;
2732 object->shader_backend = &none_shader_backend;
2735 /* set the state of the device to valid */
2736 object->state = WINED3D_OK;
2738 /* Get the initial screen setup for ddraw */
2739 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2740 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2742 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2745 for(i = 0; i < PATCHMAP_SIZE; i++) {
2746 list_init(&object->patches[i]);
2750 #undef GLINFO_LOCATION
2752 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2753 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2754 IUnknown_AddRef(This->parent);
2755 *pParent = This->parent;
2759 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2760 IUnknown* surfaceParent;
2761 TRACE("(%p) call back\n", pSurface);
2763 /* Now, release the parent, which will take care of cleaning up the surface for us */
2764 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2765 IUnknown_Release(surfaceParent);
2766 return IUnknown_Release(surfaceParent);
2769 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2770 IUnknown* volumeParent;
2771 TRACE("(%p) call back\n", pVolume);
2773 /* Now, release the parent, which will take care of cleaning up the volume for us */
2774 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2775 IUnknown_Release(volumeParent);
2776 return IUnknown_Release(volumeParent);
2779 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2780 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2781 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2782 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2784 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2785 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2786 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2787 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2788 * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
2789 * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
2790 * DirectDraw, not OpenGL.
2792 if(gl_info->supported[APPLE_FENCE] &&
2793 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2794 gl_info->supported[APPLE_FLUSH_RENDER] &&
2795 gl_info->supported[APPLE_YCBCR_422]) {
2796 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2797 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2800 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2801 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2806 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2807 if(implementation_is_apple(gl_info)) {
2808 /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
2809 * used it falls back to software. While the compiler can detect if the shader uses all declared
2810 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2811 * using relative addressing falls back to software.
2813 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2815 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2816 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2818 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
2819 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
2820 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
2823 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
2824 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
2825 * If real NP2 textures are used, the driver falls back to software. So remove the supported
2826 * flag for this extension
2828 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
2829 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
2830 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
2831 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
2832 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
2833 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
2834 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
2840 #define PUSH1(att) attribs[nAttribs++] = (att);
2841 #define GLINFO_LOCATION (Adapters[0].gl_info)
2842 BOOL InitAdapters(void) {
2843 static HMODULE mod_gl;
2845 int ps_selected_mode, vs_selected_mode;
2847 /* No need to hold any lock. The calling library makes sure only one thread calls
2848 * wined3d simultaneously
2850 if(numAdapters > 0) return TRUE;
2852 TRACE("Initializing adapters\n");
2855 #ifdef USE_WIN32_OPENGL
2856 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
2857 mod_gl = LoadLibraryA("opengl32.dll");
2859 ERR("Can't load opengl32.dll!\n");
2863 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
2864 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
2865 mod_gl = GetModuleHandleA("gdi32.dll");
2869 /* Load WGL core functions from opengl32.dll */
2870 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
2874 if(!pwglGetProcAddress) {
2875 ERR("Unable to load wglGetProcAddress!\n");
2879 /* Dynamically load all GL core functions */
2883 /* For now only one default adapter */
2890 WineD3D_PixelFormat *cfgs;
2892 DISPLAY_DEVICEW DisplayDevice;
2895 TRACE("Initializing default adapter\n");
2896 Adapters[0].monitorPoint.x = -1;
2897 Adapters[0].monitorPoint.y = -1;
2899 if (!WineD3D_CreateFakeGLContext()) {
2900 ERR("Failed to get a gl context for default adapter\n");
2901 HeapFree(GetProcessHeap(), 0, Adapters);
2902 WineD3D_ReleaseFakeGLContext();
2906 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2908 ERR("Failed to initialize gl caps for default adapter\n");
2909 HeapFree(GetProcessHeap(), 0, Adapters);
2910 WineD3D_ReleaseFakeGLContext();
2913 ret = initPixelFormats(&Adapters[0].gl_info);
2915 ERR("Failed to init gl formats\n");
2916 HeapFree(GetProcessHeap(), 0, Adapters);
2917 WineD3D_ReleaseFakeGLContext();
2921 hdc = pwglGetCurrentDC();
2923 ERR("Failed to get gl HDC\n");
2924 HeapFree(GetProcessHeap(), 0, Adapters);
2925 WineD3D_ReleaseFakeGLContext();
2929 Adapters[0].driver = "Display";
2930 Adapters[0].description = "Direct3D HAL";
2932 /* Use the VideoRamSize registry setting when set */
2933 if(wined3d_settings.emulated_textureram)
2934 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
2936 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
2937 Adapters[0].UsedTextureRam = 0;
2938 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
2940 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2941 DisplayDevice.cb = sizeof(DisplayDevice);
2942 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2943 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2944 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2946 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2947 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2949 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2950 cfgs = Adapters[0].cfgs;
2951 PUSH1(WGL_RED_BITS_ARB)
2952 PUSH1(WGL_GREEN_BITS_ARB)
2953 PUSH1(WGL_BLUE_BITS_ARB)
2954 PUSH1(WGL_ALPHA_BITS_ARB)
2955 PUSH1(WGL_DEPTH_BITS_ARB)
2956 PUSH1(WGL_STENCIL_BITS_ARB)
2958 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2959 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
2964 /* Cache the pixel format */
2965 cfgs->iPixelFormat = iPixelFormat;
2966 cfgs->redSize = values[0];
2967 cfgs->greenSize = values[1];
2968 cfgs->blueSize = values[2];
2969 cfgs->alphaSize = values[3];
2970 cfgs->depthSize = values[4];
2971 cfgs->stencilSize = values[5];
2973 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);
2976 WineD3D_ReleaseFakeGLContext();
2978 fixup_extensions(&Adapters[0].gl_info);
2980 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2981 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2985 TRACE("%d adapters successfully initialized\n", numAdapters);
2990 #undef GLINFO_LOCATION
2992 /**********************************************************
2993 * IWineD3D VTbl follows
2994 **********************************************************/
2996 const IWineD3DVtbl IWineD3D_Vtbl =
2999 IWineD3DImpl_QueryInterface,
3000 IWineD3DImpl_AddRef,
3001 IWineD3DImpl_Release,
3003 IWineD3DImpl_GetParent,
3004 IWineD3DImpl_GetAdapterCount,
3005 IWineD3DImpl_RegisterSoftwareDevice,
3006 IWineD3DImpl_GetAdapterMonitor,
3007 IWineD3DImpl_GetAdapterModeCount,
3008 IWineD3DImpl_EnumAdapterModes,
3009 IWineD3DImpl_GetAdapterDisplayMode,
3010 IWineD3DImpl_GetAdapterIdentifier,
3011 IWineD3DImpl_CheckDeviceMultiSampleType,
3012 IWineD3DImpl_CheckDepthStencilMatch,
3013 IWineD3DImpl_CheckDeviceType,
3014 IWineD3DImpl_CheckDeviceFormat,
3015 IWineD3DImpl_CheckDeviceFormatConversion,
3016 IWineD3DImpl_GetDeviceCaps,
3017 IWineD3DImpl_CreateDevice