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