wined3d: Check real depth/stencil capabilities based on WGL pixel formats.
[wine/gsoc_dplay.git] / dlls / wined3d / directx.c
blob58a278151851f65225818974ce71c70a4f1d4321
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
29 #endif
32 #include "config.h"
33 #include <assert.h>
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
40 static const struct {
41 const char *extension_string;
42 GL_SupportedExt extension;
43 DWORD version;
44 } EXTENSION_MAP[] = {
45 /* APPLE */
46 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
47 {"GL_APPLE_fence", APPLE_FENCE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
51 /* ATI */
52 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
53 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
54 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
55 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
57 /* ARB */
58 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
59 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
60 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_imaging", ARB_IMAGING, 0 },
63 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
64 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
65 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
66 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
67 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
68 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
69 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
70 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
71 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
72 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
73 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
74 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
75 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
76 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
77 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
78 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
79 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
80 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
81 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
82 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
83 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
85 /* EXT */
86 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
87 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
88 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
89 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
90 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
91 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
92 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
93 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
94 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
95 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
96 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
97 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
98 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
99 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
100 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
101 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
102 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
103 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
104 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
105 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
106 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
107 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
108 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
110 /* NV */
111 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
112 {"GL_NV_fence", NV_FENCE, 0 },
113 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
114 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
115 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
116 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
117 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
118 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
119 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
120 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
121 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
122 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
123 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
124 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
125 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
126 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
127 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
128 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
130 /* SGI */
131 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
134 /**********************************************************
135 * Utility functions follow
136 **********************************************************/
138 /* Adapters */
139 static int numAdapters = 0;
140 static struct WineD3DAdapter Adapters[1];
142 /* lookup tables */
143 int minLookup[MAX_LOOKUPS];
144 int maxLookup[MAX_LOOKUPS];
145 DWORD *stateLookup[MAX_LOOKUPS];
147 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
149 /* drawStridedSlow attributes */
150 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
151 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
152 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
153 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
154 glTexAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
157 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
158 * ie there is no GL Context - Get a default rendering context to enable the
159 * function query some info from GL
162 static int wined3d_fake_gl_context_ref = 0;
163 static BOOL wined3d_fake_gl_context_foreign;
164 static BOOL wined3d_fake_gl_context_available = FALSE;
165 static HDC wined3d_fake_gl_context_hdc = NULL;
166 static HWND wined3d_fake_gl_context_hwnd = NULL;
168 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
169 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
171 0, 0, &wined3d_fake_gl_context_cs,
172 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
173 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
174 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
176 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
178 static void WineD3D_ReleaseFakeGLContext(void) {
179 HGLRC glCtx;
181 EnterCriticalSection(&wined3d_fake_gl_context_cs);
183 if(!wined3d_fake_gl_context_available) {
184 TRACE_(d3d_caps)("context not available\n");
185 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
186 return;
189 glCtx = pwglGetCurrentContext();
191 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
192 if (0 == (--wined3d_fake_gl_context_ref) ) {
193 if(!wined3d_fake_gl_context_foreign && glCtx) {
194 TRACE_(d3d_caps)("destroying fake GL context\n");
195 pwglMakeCurrent(NULL, NULL);
196 pwglDeleteContext(glCtx);
198 if(wined3d_fake_gl_context_hdc)
199 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
200 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
201 if(wined3d_fake_gl_context_hwnd)
202 DestroyWindow(wined3d_fake_gl_context_hwnd);
203 wined3d_fake_gl_context_hwnd = NULL;
204 wined3d_fake_gl_context_available = FALSE;
206 assert(wined3d_fake_gl_context_ref >= 0);
208 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
211 static BOOL WineD3D_CreateFakeGLContext(void) {
212 HGLRC glCtx = NULL;
214 EnterCriticalSection(&wined3d_fake_gl_context_cs);
216 TRACE("getting context...\n");
217 if(wined3d_fake_gl_context_ref > 0) goto ret;
218 assert(0 == wined3d_fake_gl_context_ref);
220 wined3d_fake_gl_context_foreign = TRUE;
222 glCtx = pwglGetCurrentContext();
223 if (!glCtx) {
224 PIXELFORMATDESCRIPTOR pfd;
225 int iPixelFormat;
227 wined3d_fake_gl_context_foreign = FALSE;
229 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
230 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
231 if(!wined3d_fake_gl_context_hwnd) {
232 ERR("HWND creation failed!\n");
233 goto fail;
235 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
236 if(!wined3d_fake_gl_context_hdc) {
237 ERR("GetDC failed!\n");
238 goto fail;
241 /* PixelFormat selection */
242 ZeroMemory(&pfd, sizeof(pfd));
243 pfd.nSize = sizeof(pfd);
244 pfd.nVersion = 1;
245 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
246 pfd.iPixelType = PFD_TYPE_RGBA;
247 pfd.cColorBits = 32;
248 pfd.iLayerType = PFD_MAIN_PLANE;
250 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
251 if(!iPixelFormat) {
252 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
253 ERR("Can't find a suitable iPixelFormat\n");
254 goto fail;
256 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
257 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
259 /* Create a GL context */
260 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
261 if (!glCtx) {
262 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
263 goto fail;
266 /* Make it the current GL context */
267 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
268 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
269 goto fail;
273 ret:
274 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
275 wined3d_fake_gl_context_ref++;
276 wined3d_fake_gl_context_available = TRUE;
277 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
278 return TRUE;
279 fail:
280 if(wined3d_fake_gl_context_hdc)
281 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
282 wined3d_fake_gl_context_hdc = NULL;
283 if(wined3d_fake_gl_context_hwnd)
284 DestroyWindow(wined3d_fake_gl_context_hwnd);
285 wined3d_fake_gl_context_hwnd = NULL;
286 if(glCtx) pwglDeleteContext(glCtx);
287 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
288 return FALSE;
291 /* Adjust the amount of used texture memory */
292 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
293 UINT Adapter = D3DDevice->adapterNo;
295 Adapters[Adapter].UsedTextureRam += glram;
296 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
297 return Adapters[Adapter].UsedTextureRam;
300 /**********************************************************
301 * IUnknown parts follows
302 **********************************************************/
304 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
308 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
309 if (IsEqualGUID(riid, &IID_IUnknown)
310 || IsEqualGUID(riid, &IID_IWineD3DBase)
311 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
312 IUnknown_AddRef(iface);
313 *ppobj = This;
314 return S_OK;
316 *ppobj = NULL;
317 return E_NOINTERFACE;
320 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
321 IWineD3DImpl *This = (IWineD3DImpl *)iface;
322 ULONG refCount = InterlockedIncrement(&This->ref);
324 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
325 return refCount;
328 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
329 IWineD3DImpl *This = (IWineD3DImpl *)iface;
330 ULONG ref;
331 TRACE("(%p) : Releasing from %d\n", This, This->ref);
332 ref = InterlockedDecrement(&This->ref);
333 if (ref == 0) {
334 HeapFree(GetProcessHeap(), 0, This);
337 return ref;
340 /* Set the shader type for this device, depending on the given capabilities,
341 * the device type, and the user preferences in wined3d_settings */
343 static void select_shader_mode(
344 WineD3D_GL_Info *gl_info,
345 WINED3DDEVTYPE DeviceType,
346 int* ps_selected,
347 int* vs_selected) {
349 if (wined3d_settings.vs_mode == VS_NONE) {
350 *vs_selected = SHADER_NONE;
351 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
352 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
353 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
354 * shaders only on this card. */
355 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
356 *vs_selected = SHADER_ARB;
357 else
358 *vs_selected = SHADER_GLSL;
359 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
360 *vs_selected = SHADER_ARB;
361 } else {
362 *vs_selected = SHADER_NONE;
365 if (wined3d_settings.ps_mode == PS_NONE) {
366 *ps_selected = SHADER_NONE;
367 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
368 *ps_selected = SHADER_GLSL;
369 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
370 *ps_selected = SHADER_ARB;
371 } else {
372 *ps_selected = SHADER_NONE;
376 /** Select the number of report maximum shader constants based on the selected shader modes */
377 static void select_shader_max_constants(
378 int ps_selected_mode,
379 int vs_selected_mode,
380 WineD3D_GL_Info *gl_info) {
382 switch (vs_selected_mode) {
383 case SHADER_GLSL:
384 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
385 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
386 break;
387 case SHADER_ARB:
388 /* We have to subtract any other PARAMs that we might use in our shader programs.
389 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
390 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
391 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
392 break;
393 default:
394 gl_info->max_vshader_constantsF = 0;
395 break;
398 switch (ps_selected_mode) {
399 case SHADER_GLSL:
400 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
401 * In theory the texbem instruction may need one more shader constant too. But lets assume
402 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
403 * and lets not take away a uniform needlessly from all other shaders.
405 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
406 break;
407 case SHADER_ARB:
408 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
409 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
411 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
412 break;
413 default:
414 gl_info->max_pshader_constantsF = 0;
415 break;
419 /**********************************************************
420 * IWineD3D parts follows
421 **********************************************************/
423 #define GLINFO_LOCATION (*gl_info)
424 static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
425 GLuint prog;
426 BOOL ret = FALSE;
427 const char *testcode =
428 "!!ARBvp1.0\n"
429 "PARAM C[66] = { program.env[0..65] };\n"
430 "ADDRESS A0;"
431 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
432 "ARL A0.x, zero.x;\n"
433 "MOV result.position, C[A0.x + 65];\n"
434 "END\n";
436 while(glGetError());
437 GL_EXTCALL(glGenProgramsARB(1, &prog));
438 if(!prog) {
439 ERR("Failed to create an ARB offset limit test program\n");
441 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
442 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
443 strlen(testcode), testcode));
444 if(glGetError() != 0) {
445 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
446 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
447 ret = TRUE;
448 } else TRACE("OpenGL implementation allows offsets > 63\n");
450 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
451 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
452 checkGLcall("ARB vp offset limit test cleanup\n");
454 return ret;
457 static DWORD ver_for_ext(GL_SupportedExt ext)
459 unsigned int i;
460 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
461 if(EXTENSION_MAP[i].extension == ext) {
462 return EXTENSION_MAP[i].version;
465 return 0;
468 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
469 const char *GL_Extensions = NULL;
470 const char *WGL_Extensions = NULL;
471 const char *gl_string = NULL;
472 const char *gl_string_cursor = NULL;
473 GLint gl_max;
474 GLfloat gl_floatv[2];
475 int major = 1, minor = 0;
476 BOOL return_value = TRUE;
477 unsigned i;
478 HDC hdc;
479 unsigned int vidmem=0;
481 TRACE_(d3d_caps)("(%p)\n", gl_info);
483 ENTER_GL();
485 gl_string = (const char *) glGetString(GL_RENDERER);
486 if (NULL == gl_string)
487 gl_string = "None";
488 strcpy(gl_info->gl_renderer, gl_string);
490 gl_string = (const char *) glGetString(GL_VENDOR);
491 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
492 if (gl_string != NULL) {
493 /* Fill in the GL vendor */
494 if (strstr(gl_string, "NVIDIA")) {
495 gl_info->gl_vendor = VENDOR_NVIDIA;
496 } else if (strstr(gl_string, "ATI")) {
497 gl_info->gl_vendor = VENDOR_ATI;
498 } else if (strstr(gl_string, "Intel(R)") ||
499 strstr(gl_info->gl_renderer, "Intel(R)") ||
500 strstr(gl_string, "Intel Inc.")) {
501 gl_info->gl_vendor = VENDOR_INTEL;
502 } else if (strstr(gl_string, "Mesa")) {
503 gl_info->gl_vendor = VENDOR_MESA;
504 } else {
505 gl_info->gl_vendor = VENDOR_WINE;
507 } else {
508 gl_info->gl_vendor = VENDOR_WINE;
512 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
514 /* Parse the GL_VERSION field into major and minor information */
515 gl_string = (const char *) glGetString(GL_VERSION);
516 if (gl_string != NULL) {
518 /* First, parse the generic opengl version. This is supposed not to be convoluted with
519 * driver specific information
521 gl_string_cursor = gl_string;
522 major = atoi(gl_string_cursor);
523 if(major <= 0) {
524 ERR("Invalid opengl major version: %d\n", major);
526 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
527 ++gl_string_cursor;
529 if (*gl_string_cursor++ != '.') {
530 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
532 minor = atoi(gl_string_cursor);
533 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
534 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
536 /* Now parse the driver specific string which we'll report to the app */
537 switch (gl_info->gl_vendor) {
538 case VENDOR_NVIDIA:
539 gl_string_cursor = strstr(gl_string, "NVIDIA");
540 if (!gl_string_cursor) {
541 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
542 break;
545 gl_string_cursor = strstr(gl_string_cursor, " ");
546 if (!gl_string_cursor) {
547 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
548 break;
551 while (*gl_string_cursor == ' ') {
552 ++gl_string_cursor;
555 if (!*gl_string_cursor) {
556 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
557 break;
560 major = atoi(gl_string_cursor);
561 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
562 ++gl_string_cursor;
565 if (*gl_string_cursor++ != '.') {
566 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
567 break;
570 minor = atoi(gl_string_cursor);
571 minor = major*100+minor;
572 major = 10;
574 break;
576 case VENDOR_ATI:
577 major = minor = 0;
578 gl_string_cursor = strchr(gl_string, '-');
579 if (gl_string_cursor) {
580 int error = 0;
581 gl_string_cursor++;
583 /* Check if version number is of the form x.y.z */
584 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
585 error = 1;
586 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
587 error = 1;
588 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
589 error = 1;
590 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
591 error = 1;
593 /* Mark version number as malformed */
594 if (error)
595 gl_string_cursor = 0;
598 if (!gl_string_cursor)
599 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
600 else {
601 major = *gl_string_cursor - '0';
602 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
604 break;
606 case VENDOR_INTEL:
607 /* Apple and Mesa version strings look differently, but both provide intel drivers */
608 if(strstr(gl_string, "APPLE")) {
609 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
610 * We only need the first part, and use the APPLE as identification
611 * "1.2 APPLE-1.4.56"
613 gl_string_cursor = gl_string;
614 major = atoi(gl_string_cursor);
615 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
616 ++gl_string_cursor;
619 if (*gl_string_cursor++ != '.') {
620 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
621 break;
624 minor = atoi(gl_string_cursor);
625 break;
628 case VENDOR_MESA:
629 gl_string_cursor = strstr(gl_string, "Mesa");
630 gl_string_cursor = strstr(gl_string_cursor, " ");
631 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
632 if (*gl_string_cursor) {
633 char tmp[16];
634 int cursor = 0;
636 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
637 tmp[cursor++] = *gl_string_cursor;
638 ++gl_string_cursor;
640 tmp[cursor] = 0;
641 major = atoi(tmp);
643 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
644 ++gl_string_cursor;
646 cursor = 0;
647 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
648 tmp[cursor++] = *gl_string_cursor;
649 ++gl_string_cursor;
651 tmp[cursor] = 0;
652 minor = atoi(tmp);
654 break;
656 default:
657 major = 0;
658 minor = 9;
660 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
661 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
662 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
663 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
664 } else {
665 FIXME("OpenGL driver did not return version information\n");
666 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
667 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
670 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
673 * Initialize openGL extension related variables
674 * with Default values
676 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
677 gl_info->max_buffers = 1;
678 gl_info->max_textures = 1;
679 gl_info->max_texture_stages = 1;
680 gl_info->max_fragment_samplers = 1;
681 gl_info->max_vertex_samplers = 0;
682 gl_info->max_combined_samplers = 0;
683 gl_info->max_sampler_stages = 1;
684 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
685 gl_info->ps_arb_max_temps = 0;
686 gl_info->ps_arb_max_instructions = 0;
687 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
688 gl_info->vs_arb_max_temps = 0;
689 gl_info->vs_arb_max_instructions = 0;
690 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
691 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
692 gl_info->vs_glsl_constantsF = 0;
693 gl_info->ps_glsl_constantsF = 0;
694 gl_info->vs_arb_constantsF = 0;
695 gl_info->ps_arb_constantsF = 0;
697 /* Retrieve opengl defaults */
698 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
699 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
700 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
702 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
703 gl_info->max_lights = gl_max;
704 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
706 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
707 gl_info->max_texture_size = gl_max;
708 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
710 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
711 gl_info->max_pointsizemin = gl_floatv[0];
712 gl_info->max_pointsize = gl_floatv[1];
713 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
715 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
716 gl_info->max_aux_buffers = gl_max;
717 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
719 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
720 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
721 TRACE_(d3d_caps)("GL_Extensions reported:\n");
723 if (NULL == GL_Extensions) {
724 ERR(" GL_Extensions returns NULL\n");
725 } else {
726 while (*GL_Extensions != 0x00) {
727 const char *Start;
728 char ThisExtn[256];
729 size_t len;
731 while (isspace(*GL_Extensions)) GL_Extensions++;
732 Start = GL_Extensions;
733 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
734 GL_Extensions++;
737 len = GL_Extensions - Start;
738 if (len == 0 || len >= sizeof(ThisExtn))
739 continue;
741 memcpy(ThisExtn, Start, len);
742 ThisExtn[len] = '\0';
743 TRACE_(d3d_caps)("- %s\n", ThisExtn);
745 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
746 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
747 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
748 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
749 break;
753 /* Now work out what GL support this card really has */
754 #define USE_GL_FUNC(type, pfn, ext, replace) { \
755 DWORD ver = ver_for_ext(ext); \
756 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
757 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
758 else gl_info->pfn = NULL; \
760 GL_EXT_FUNCS_GEN;
761 #undef USE_GL_FUNC
763 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
764 WGL_EXT_FUNCS_GEN;
765 #undef USE_GL_FUNC
767 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
768 * loading the functions, otherwise the code above will load the extension entry points instead of the
769 * core functions, which may not work
771 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
772 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
773 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
774 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
775 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
779 if (gl_info->supported[APPLE_FENCE]) {
780 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
781 * The apple extension interacts with some other apple exts. Disable the NV
782 * extension if the apple one is support to prevent confusion in other parts
783 * of the code
785 gl_info->supported[NV_FENCE] = FALSE;
787 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
788 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
789 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
791 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
792 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
793 * Won't occur in any real world situation though
795 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
797 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
798 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
799 gl_info->max_buffers = gl_max;
800 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
802 if (gl_info->supported[ARB_MULTITEXTURE]) {
803 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
804 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
805 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
807 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
808 GLint tmp;
809 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
810 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
811 } else {
812 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
814 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
816 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
817 GLint tmp;
818 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
819 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
820 } else {
821 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
823 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
825 if (gl_info->supported[ARB_VERTEX_SHADER]) {
826 GLint tmp;
827 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
828 gl_info->max_vertex_samplers = tmp;
829 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
830 gl_info->max_combined_samplers = tmp;
832 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
833 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
834 * an issue because then the sampler setup only depends on the two shaders. If a pixel
835 * shader is used with fixed function vertex processing we're fine too because fixed function
836 * vertex processing doesn't use any samplers. If fixed function fragment processing is
837 * used we have to make sure that all vertex sampler setups are valid together with all
838 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
839 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
840 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
841 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
842 * a fixed function pipeline anymore.
844 * So this is just a check to check that our assumption holds true. If not, write a warning
845 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
847 if(gl_info->max_vertex_samplers &&
848 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
849 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
850 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
851 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
852 if( gl_info->max_combined_samplers > MAX_TEXTURES )
853 gl_info->max_vertex_samplers =
854 gl_info->max_combined_samplers - MAX_TEXTURES;
855 else
856 gl_info->max_vertex_samplers = 0;
858 } else {
859 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
861 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
862 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
864 if (gl_info->supported[ARB_VERTEX_BLEND]) {
865 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
866 gl_info->max_blends = gl_max;
867 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
869 if (gl_info->supported[EXT_TEXTURE3D]) {
870 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
871 gl_info->max_texture3d_size = gl_max;
872 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
874 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
875 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
876 gl_info->max_anisotropy = gl_max;
877 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
879 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
880 gl_info->ps_arb_version = PS_VERSION_11;
881 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
882 gl_info->ps_arb_constantsF = gl_max;
883 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
884 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
885 gl_info->ps_arb_max_temps = gl_max;
886 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
887 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
888 gl_info->ps_arb_max_instructions = gl_max;
889 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
891 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
892 gl_info->vs_arb_version = VS_VERSION_11;
893 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
894 gl_info->vs_arb_constantsF = gl_max;
895 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
896 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
897 gl_info->vs_arb_max_temps = gl_max;
898 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
899 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
900 gl_info->vs_arb_max_instructions = gl_max;
901 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
903 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
905 if (gl_info->supported[ARB_VERTEX_SHADER]) {
906 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
907 gl_info->vs_glsl_constantsF = gl_max / 4;
908 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
910 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
911 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
912 gl_info->ps_glsl_constantsF = gl_max / 4;
913 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
914 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
915 gl_info->max_glsl_varyings = gl_max;
916 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
918 if (gl_info->supported[EXT_VERTEX_SHADER]) {
919 gl_info->vs_ati_version = VS_VERSION_11;
921 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
922 gl_info->vs_nv_version = VS_VERSION_30;
923 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
924 gl_info->vs_nv_version = VS_VERSION_20;
925 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
926 gl_info->vs_nv_version = VS_VERSION_11;
927 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
928 gl_info->vs_nv_version = VS_VERSION_10;
930 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
931 gl_info->ps_nv_version = PS_VERSION_30;
932 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
933 gl_info->ps_nv_version = PS_VERSION_20;
935 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
936 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
937 * This saves a few redundant glDisable calls
939 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
943 checkGLcall("extension detection\n");
945 /* In some cases the number of texture stages can be larger than the number
946 * of samplers. The GF4 for example can use only 2 samplers (no fragment
947 * shaders), but 8 texture stages (register combiners). */
948 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
950 /* We can only use ORM_FBO when the hardware supports it. */
951 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
952 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
953 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
956 /* MRTs are currently only supported when FBOs are used. */
957 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
958 gl_info->max_buffers = 1;
961 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
962 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
963 * in case of the latest videocards in the number of pixel/vertex pipelines.
965 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
966 * rendering. Various games use this information to get a rough estimation of the features of the card
967 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
968 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
969 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
970 * not the PCI id.
972 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
973 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
974 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
975 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
976 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
977 * is used for rendering which is not always the case). This would work but it is not very portable. Second
978 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
979 * is limited.
981 * As said most games only use the PCI id to get an indication of the capabilities of the card.
982 * It doesn't really matter if the given id is the correct one if we return the id of a card with
983 * similar 3d features.
985 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
986 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
987 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
988 * won't pass we return a default card. This way is better than maintaining a full card database as even
989 * without a full database we can return a card with similar features. Second the size of the database
990 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
991 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
992 * to distinguishes between different models from that family.
994 * The code also selects a default amount of video memory which we will use for an estimation of the amount
995 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
996 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
997 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
998 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
999 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1000 * memory behind our backs if really needed.
1001 * Note that the amount of video memory can be overruled using a registry setting.
1003 switch (gl_info->gl_vendor) {
1004 case VENDOR_NVIDIA:
1005 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1006 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1008 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1009 /* Geforce8 - highend */
1010 if (strstr(gl_info->gl_renderer, "8800")) {
1011 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1012 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1014 /* Geforce8 - midend mobile */
1015 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1016 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1017 vidmem = 512;
1019 /* Geforce8 - midend */
1020 else if(strstr(gl_info->gl_renderer, "8600") ||
1021 strstr(gl_info->gl_renderer, "8700"))
1023 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1024 vidmem = 256;
1026 /* Geforce8 - lowend */
1027 else if(strstr(gl_info->gl_renderer, "8300") ||
1028 strstr(gl_info->gl_renderer, "8400") ||
1029 strstr(gl_info->gl_renderer, "8500"))
1031 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1032 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1034 /* Geforce7 - highend */
1035 else if(strstr(gl_info->gl_renderer, "7800") ||
1036 strstr(gl_info->gl_renderer, "7900") ||
1037 strstr(gl_info->gl_renderer, "7950") ||
1038 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1039 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1041 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1042 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1044 /* Geforce7 midend */
1045 else if(strstr(gl_info->gl_renderer, "7600") ||
1046 strstr(gl_info->gl_renderer, "7700")) {
1047 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1048 vidmem = 256; /* The 7600 uses 256-512MB */
1049 /* Geforce7 lower medium */
1050 } else if(strstr(gl_info->gl_renderer, "7400")) {
1051 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1052 vidmem = 256; /* The 7400 uses 256-512MB */
1054 /* Geforce7 lowend */
1055 else if(strstr(gl_info->gl_renderer, "7300")) {
1056 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1057 vidmem = 256; /* Mac Pros with this card have 256 MB */
1059 /* Geforce6 highend */
1060 else if(strstr(gl_info->gl_renderer, "6800"))
1062 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1063 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1065 /* Geforce6 - midend */
1066 else if(strstr(gl_info->gl_renderer, "6600") ||
1067 strstr(gl_info->gl_renderer, "6610") ||
1068 strstr(gl_info->gl_renderer, "6700"))
1070 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1071 vidmem = 128; /* A 6600GT has 128-256MB */
1073 /* Geforce6/7 lowend */
1074 else {
1075 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1076 vidmem = 64; /* */
1078 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1079 /* GeforceFX - highend */
1080 if (strstr(gl_info->gl_renderer, "5800") ||
1081 strstr(gl_info->gl_renderer, "5900") ||
1082 strstr(gl_info->gl_renderer, "5950") ||
1083 strstr(gl_info->gl_renderer, "Quadro FX"))
1085 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1086 vidmem = 256; /* 5800-5900 cards use 256MB */
1088 /* GeforceFX - midend */
1089 else if(strstr(gl_info->gl_renderer, "5600") ||
1090 strstr(gl_info->gl_renderer, "5650") ||
1091 strstr(gl_info->gl_renderer, "5700") ||
1092 strstr(gl_info->gl_renderer, "5750"))
1094 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1095 vidmem = 128; /* A 5600 uses 128-256MB */
1097 /* GeforceFX - lowend */
1098 else {
1099 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1100 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1102 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1103 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1104 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1105 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1107 else {
1108 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1109 vidmem = 64; /* Geforce3 cards have 64-128MB */
1111 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1112 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1113 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1114 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1116 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1117 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1118 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1120 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1121 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1122 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1124 else {
1125 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1126 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1128 } else {
1129 if (strstr(gl_info->gl_renderer, "TNT2")) {
1130 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1131 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1133 else {
1134 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1135 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1138 break;
1139 case VENDOR_ATI:
1140 if(WINE_D3D9_CAPABLE(gl_info)) {
1141 /* Radeon R6xx HD2900 - highend */
1142 if (strstr(gl_info->gl_renderer, "HD 2900")) {
1143 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1144 vidmem = 512; /* HD2900 uses 512-1024MB */
1146 /* Radeon R6xx HD2600- midend */
1147 else if (strstr(gl_info->gl_renderer, "HD 2600")) {
1148 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1149 vidmem = 256; /* HD2600 uses 256-512MB */
1151 /* Radeon R6xx HD2300/HD2400 - lowend */
1152 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1153 strstr(gl_info->gl_renderer, "HD 2400"))
1155 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1156 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1158 /* Radeon R5xx */
1159 else if (strstr(gl_info->gl_renderer, "X1600") ||
1160 strstr(gl_info->gl_renderer, "X1650") ||
1161 strstr(gl_info->gl_renderer, "X1800") ||
1162 strstr(gl_info->gl_renderer, "X1900") ||
1163 strstr(gl_info->gl_renderer, "X1950"))
1165 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1166 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1168 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1169 else if(strstr(gl_info->gl_renderer, "X700") ||
1170 strstr(gl_info->gl_renderer, "X800") ||
1171 strstr(gl_info->gl_renderer, "X850") ||
1172 strstr(gl_info->gl_renderer, "X1300") ||
1173 strstr(gl_info->gl_renderer, "X1400") ||
1174 strstr(gl_info->gl_renderer, "X1450") ||
1175 strstr(gl_info->gl_renderer, "X1550"))
1177 gl_info->gl_card = CARD_ATI_RADEON_X700;
1178 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1180 /* Radeon R3xx */
1181 else {
1182 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1183 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1185 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1186 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1187 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1188 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1189 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1190 vidmem = 32; /* There are models with up to 64MB */
1191 } else {
1192 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1193 vidmem = 16; /* There are 16-32MB models */
1195 break;
1196 case VENDOR_INTEL:
1197 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1198 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1199 gl_info->gl_card = CARD_INTEL_I945GM;
1200 vidmem = 64;
1201 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1202 gl_info->gl_card = CARD_INTEL_I915GM;
1203 } else if (strstr(gl_info->gl_renderer, "915G")) {
1204 gl_info->gl_card = CARD_INTEL_I915G;
1205 } else if (strstr(gl_info->gl_renderer, "865G")) {
1206 gl_info->gl_card = CARD_INTEL_I865G;
1207 } else if (strstr(gl_info->gl_renderer, "855G")) {
1208 gl_info->gl_card = CARD_INTEL_I855G;
1209 } else if (strstr(gl_info->gl_renderer, "830G")) {
1210 gl_info->gl_card = CARD_INTEL_I830G;
1211 } else {
1212 gl_info->gl_card = CARD_INTEL_I915G;
1214 break;
1215 case VENDOR_MESA:
1216 case VENDOR_WINE:
1217 default:
1218 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1219 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1220 * them a good generic choice.
1222 gl_info->gl_vendor = VENDOR_NVIDIA;
1223 if(WINE_D3D9_CAPABLE(gl_info))
1224 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1225 else if(WINE_D3D8_CAPABLE(gl_info))
1226 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1227 else if(WINE_D3D7_CAPABLE(gl_info))
1228 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1229 else if(WINE_D3D6_CAPABLE(gl_info))
1230 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1231 else
1232 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1234 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1236 /* If we have an estimate use it, else default to 64MB; */
1237 if(vidmem)
1238 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1239 else
1240 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1242 /* Load all the lookup tables
1243 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1244 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
1245 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
1247 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
1248 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
1251 for (i = 0; i < MAX_LOOKUPS; i++) {
1252 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1255 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1256 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1257 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1258 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1259 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1260 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1261 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1262 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1263 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1264 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1266 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1267 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
1268 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
1269 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
1270 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1273 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
1274 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
1275 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
1276 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
1277 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1278 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1279 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
1280 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1281 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1282 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
1283 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1284 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1285 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1287 /* TODO: config lookups */
1289 /* Make sure there's an active HDC else the WGL extensions will fail */
1290 hdc = pwglGetCurrentDC();
1291 if (hdc) {
1292 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1293 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1295 if (NULL == WGL_Extensions) {
1296 ERR(" WGL_Extensions returns NULL\n");
1297 } else {
1298 while (*WGL_Extensions != 0x00) {
1299 const char *Start;
1300 char ThisExtn[256];
1301 size_t len;
1303 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1304 Start = WGL_Extensions;
1305 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1306 WGL_Extensions++;
1309 len = WGL_Extensions - Start;
1310 if (len == 0 || len >= sizeof(ThisExtn))
1311 continue;
1313 memcpy(ThisExtn, Start, len);
1314 ThisExtn[len] = '\0';
1315 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1317 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1318 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1319 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1324 LEAVE_GL();
1326 return return_value;
1328 #undef GLINFO_LOCATION
1330 /**********************************************************
1331 * IWineD3D implementation follows
1332 **********************************************************/
1334 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1335 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1337 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1338 return numAdapters;
1341 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1342 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1343 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1344 return WINED3D_OK;
1347 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1348 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1350 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1351 return NULL;
1354 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1355 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1358 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1359 of the same bpp but different resolutions */
1361 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1362 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1363 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1364 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1366 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1367 return 0;
1370 /* TODO: Store modes per adapter and read it from the adapter structure */
1371 if (Adapter == 0) { /* Display */
1372 int i = 0;
1373 int j = 0;
1375 if (!DEBUG_SINGLE_MODE) {
1376 DEVMODEW DevModeW;
1378 ZeroMemory(&DevModeW, sizeof(DevModeW));
1379 DevModeW.dmSize = sizeof(DevModeW);
1380 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1381 j++;
1382 switch (Format)
1384 case WINED3DFMT_UNKNOWN:
1385 /* This is for D3D8, do not enumerate P8 here */
1386 if (DevModeW.dmBitsPerPel == 32 ||
1387 DevModeW.dmBitsPerPel == 16) i++;
1388 break;
1389 case WINED3DFMT_X8R8G8B8:
1390 if (DevModeW.dmBitsPerPel == 32) i++;
1391 break;
1392 case WINED3DFMT_R5G6B5:
1393 if (DevModeW.dmBitsPerPel == 16) i++;
1394 break;
1395 case WINED3DFMT_P8:
1396 if (DevModeW.dmBitsPerPel == 8) i++;
1397 break;
1398 default:
1399 /* Skip other modes as they do not match the requested format */
1400 break;
1403 } else {
1404 i = 1;
1405 j = 1;
1408 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1409 return i;
1410 } else {
1411 FIXME_(d3d_caps)("Adapter not primary display\n");
1413 return 0;
1416 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1417 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1418 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1419 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1421 /* Validate the parameters as much as possible */
1422 if (NULL == pMode ||
1423 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1424 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1425 return WINED3DERR_INVALIDCALL;
1428 /* TODO: Store modes per adapter and read it from the adapter structure */
1429 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1430 DEVMODEW DevModeW;
1431 int ModeIdx = 0;
1432 int i = 0;
1433 int j = 0;
1435 ZeroMemory(&DevModeW, sizeof(DevModeW));
1436 DevModeW.dmSize = sizeof(DevModeW);
1438 /* If we are filtering to a specific format (D3D9), then need to skip
1439 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1440 just count through the ones with valid bit depths */
1441 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1442 switch (Format)
1444 case WINED3DFMT_UNKNOWN:
1445 /* This is D3D8. Do not enumerate P8 here */
1446 if (DevModeW.dmBitsPerPel == 32 ||
1447 DevModeW.dmBitsPerPel == 16) i++;
1448 break;
1449 case WINED3DFMT_X8R8G8B8:
1450 if (DevModeW.dmBitsPerPel == 32) i++;
1451 break;
1452 case WINED3DFMT_R5G6B5:
1453 if (DevModeW.dmBitsPerPel == 16) i++;
1454 break;
1455 case WINED3DFMT_P8:
1456 if (DevModeW.dmBitsPerPel == 8) i++;
1457 break;
1458 default:
1459 /* Modes that don't match what we support can get an early-out */
1460 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1461 return WINED3DERR_INVALIDCALL;
1465 if (i == 0) {
1466 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1467 return WINED3DERR_INVALIDCALL;
1469 ModeIdx = j - 1;
1471 /* Now get the display mode via the calculated index */
1472 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1473 pMode->Width = DevModeW.dmPelsWidth;
1474 pMode->Height = DevModeW.dmPelsHeight;
1475 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1476 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1477 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1479 if (Format == WINED3DFMT_UNKNOWN) {
1480 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1481 } else {
1482 pMode->Format = Format;
1484 } else {
1485 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1486 return WINED3DERR_INVALIDCALL;
1489 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1490 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1491 DevModeW.dmBitsPerPel);
1493 } else if (DEBUG_SINGLE_MODE) {
1494 /* Return one setting of the format requested */
1495 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1496 pMode->Width = 800;
1497 pMode->Height = 600;
1498 pMode->RefreshRate = 60;
1499 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1500 } else {
1501 FIXME_(d3d_caps)("Adapter not primary display\n");
1504 return WINED3D_OK;
1507 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1508 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1509 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1511 if (NULL == pMode ||
1512 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1513 return WINED3DERR_INVALIDCALL;
1516 if (Adapter == 0) { /* Display */
1517 int bpp = 0;
1518 DEVMODEW DevModeW;
1520 ZeroMemory(&DevModeW, sizeof(DevModeW));
1521 DevModeW.dmSize = sizeof(DevModeW);
1523 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1524 pMode->Width = DevModeW.dmPelsWidth;
1525 pMode->Height = DevModeW.dmPelsHeight;
1526 bpp = DevModeW.dmBitsPerPel;
1527 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1528 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1530 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1533 pMode->Format = pixelformat_for_depth(bpp);
1534 } else {
1535 FIXME_(d3d_caps)("Adapter not primary display\n");
1538 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1539 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1540 return WINED3D_OK;
1543 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1544 and fields being inserted in the middle, a new structure is used in place */
1545 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1546 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1547 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1549 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1551 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1552 return WINED3DERR_INVALIDCALL;
1555 /* Return the information requested */
1556 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1557 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1558 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1560 /* Note dx8 doesn't supply a DeviceName */
1561 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1562 pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart;
1563 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version;
1564 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1565 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1566 *(pIdentifier->SubSysId) = 0;
1567 *(pIdentifier->Revision) = 0;
1569 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1570 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1571 *(pIdentifier->WHQLLevel) = 0;
1572 } else {
1573 *(pIdentifier->WHQLLevel) = 1;
1576 return WINED3D_OK;
1579 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1580 short redSize, greenSize, blueSize, alphaSize, colorBits;
1582 if(!cfg)
1583 return FALSE;
1585 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1586 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1587 return FALSE;
1590 if(cfg->redSize < redSize)
1591 return FALSE;
1593 if(cfg->greenSize < greenSize)
1594 return FALSE;
1596 if(cfg->blueSize < blueSize)
1597 return FALSE;
1599 if(cfg->alphaSize < alphaSize)
1600 return FALSE;
1602 return TRUE;
1605 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1606 short depthSize, stencilSize;
1608 if(!cfg)
1609 return FALSE;
1611 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1612 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1613 return FALSE;
1616 if(cfg->depthSize != depthSize)
1617 return FALSE;
1619 if(cfg->stencilSize != stencilSize)
1620 return FALSE;
1622 return TRUE;
1625 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1626 WINED3DFORMAT AdapterFormat,
1627 WINED3DFORMAT RenderTargetFormat,
1628 WINED3DFORMAT DepthStencilFormat) {
1629 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1630 int nCfgs;
1631 WineD3D_PixelFormat *cfgs;
1632 int it;
1634 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1635 This, Adapter,
1636 DeviceType, debug_d3ddevicetype(DeviceType),
1637 AdapterFormat, debug_d3dformat(AdapterFormat),
1638 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1639 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1641 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1642 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1643 return WINED3DERR_INVALIDCALL;
1646 cfgs = Adapters[Adapter].cfgs;
1647 nCfgs = Adapters[Adapter].nCfgs;
1648 for (it = 0; it < nCfgs; ++it) {
1649 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1650 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1651 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1652 return WINED3D_OK;
1656 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1658 return WINED3DERR_NOTAVAILABLE;
1661 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1662 WINED3DFORMAT SurfaceFormat,
1663 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1665 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1666 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1667 This,
1668 Adapter,
1669 DeviceType, debug_d3ddevicetype(DeviceType),
1670 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1671 Windowed,
1672 MultiSampleType,
1673 pQualityLevels);
1675 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1676 return WINED3DERR_INVALIDCALL;
1679 /* TODO: Store in Adapter structure */
1680 if (pQualityLevels != NULL) {
1681 static int s_single_shot = 0;
1682 if (!s_single_shot) {
1683 FIXME("Quality levels unsupported at present\n");
1684 s_single_shot = 1;
1686 *pQualityLevels = 1; /* Guess at a value! */
1689 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1690 return WINED3DERR_NOTAVAILABLE;
1693 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1694 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1696 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1697 int nCfgs = 0;
1698 WineD3D_PixelFormat *cfgs;
1699 int it;
1700 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1702 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1703 This,
1704 Adapter,
1705 CheckType, debug_d3ddevicetype(CheckType),
1706 DisplayFormat, debug_d3dformat(DisplayFormat),
1707 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1708 Windowed);
1710 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1711 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1712 return WINED3DERR_INVALIDCALL;
1715 cfgs = Adapters[Adapter].cfgs;
1716 nCfgs = Adapters[Adapter].nCfgs;
1717 for (it = 0; it < nCfgs; ++it) {
1718 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1719 hr = WINED3D_OK;
1720 TRACE_(d3d_caps)("OK\n");
1721 break ;
1725 if(hr != WINED3D_OK)
1726 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1728 if(hr != WINED3D_OK)
1729 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1731 return hr;
1734 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1735 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1736 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1737 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1738 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1739 This,
1740 Adapter,
1741 DeviceType, debug_d3ddevicetype(DeviceType),
1742 AdapterFormat, debug_d3dformat(AdapterFormat),
1743 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1744 RType, debug_d3dresourcetype(RType),
1745 CheckFormat, debug_d3dformat(CheckFormat));
1747 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1748 return WINED3DERR_INVALIDCALL;
1751 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1752 switch (CheckFormat) {
1753 /* Filtering not supported */
1754 case WINED3DFMT_R32F:
1755 case WINED3DFMT_A32B32G32R32F:
1756 TRACE_(d3d_caps)("[FAILED]\n");
1757 return WINED3DERR_NOTAVAILABLE;
1758 default:
1759 break;
1763 if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
1764 if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
1765 TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
1766 return WINED3DERR_NOTAVAILABLE;
1770 if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
1771 if(!GL_SUPPORT(EXT_TEXTURE3D)) {
1772 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
1773 return WINED3DERR_NOTAVAILABLE;
1775 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
1776 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
1777 * app needing one of those formats, don't advertize them to avoid leading apps into
1778 * temptation. The windows drivers don't support most of those formats on volumes anyway,
1779 * except of R32F.
1781 switch(CheckFormat) {
1782 case WINED3DFMT_P8:
1783 case WINED3DFMT_A4L4:
1784 case WINED3DFMT_R32F:
1785 case WINED3DFMT_R16F:
1786 case WINED3DFMT_X8L8V8U8:
1787 case WINED3DFMT_L6V5U5:
1788 case WINED3DFMT_G16R16:
1789 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1790 return WINED3DERR_NOTAVAILABLE;
1792 case WINED3DFMT_Q8W8V8U8:
1793 case WINED3DFMT_V16U16:
1794 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
1795 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1796 return WINED3DERR_NOTAVAILABLE;
1798 break;
1800 case WINED3DFMT_V8U8:
1801 if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1802 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
1803 return WINED3DERR_NOTAVAILABLE;
1805 break;
1807 case WINED3DFMT_DXT1:
1808 case WINED3DFMT_DXT2:
1809 case WINED3DFMT_DXT3:
1810 case WINED3DFMT_DXT4:
1811 case WINED3DFMT_DXT5:
1812 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
1813 * compressed texture results in an error. While the D3D refrast does
1814 * support s3tc volumes, at least the nvidia windows driver does not, so
1815 * we're free not to support this format.
1817 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
1818 return WINED3DERR_NOTAVAILABLE;
1820 default:
1821 /* Do nothing, continue with checking the format below */
1822 break;
1825 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1826 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1827 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1828 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1829 if (!GL_LIMITS(vertex_samplers)) {
1830 TRACE_(d3d_caps)("[FAILED]\n");
1831 return WINED3DERR_NOTAVAILABLE;
1834 switch (CheckFormat) {
1835 case WINED3DFMT_A32B32G32R32F:
1836 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1837 TRACE_(d3d_caps)("[FAILED]\n");
1838 return WINED3DERR_NOTAVAILABLE;
1840 TRACE_(d3d_caps)("[OK]\n");
1841 return WINED3D_OK;
1843 default:
1844 TRACE_(d3d_caps)("[FAILED]\n");
1845 return WINED3DERR_NOTAVAILABLE;
1849 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1850 switch (CheckFormat) {
1851 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1852 * Windows supports only those 3, and enumerating the other formats confuses applications
1854 case WINED3DFMT_D24S8:
1855 case WINED3DFMT_D24X8:
1856 case WINED3DFMT_D16:
1857 TRACE_(d3d_caps)("[OK]\n");
1858 return WINED3D_OK;
1859 case WINED3DFMT_D16_LOCKABLE:
1860 case WINED3DFMT_D24FS8:
1861 case WINED3DFMT_D32F_LOCKABLE:
1862 case WINED3DFMT_D24X4S4:
1863 case WINED3DFMT_D15S1:
1864 case WINED3DFMT_D32:
1865 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1866 return WINED3DERR_NOTAVAILABLE;
1867 default:
1868 TRACE_(d3d_caps)("[FAILED]\n");
1869 return WINED3DERR_NOTAVAILABLE;
1871 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1872 switch (CheckFormat) {
1873 case WINED3DFMT_R8G8B8:
1874 case WINED3DFMT_A8R8G8B8:
1875 case WINED3DFMT_X8R8G8B8:
1876 case WINED3DFMT_R5G6B5:
1877 case WINED3DFMT_X1R5G5B5:
1878 case WINED3DFMT_A1R5G5B5:
1879 case WINED3DFMT_A4R4G4B4:
1880 case WINED3DFMT_R3G3B2:
1881 case WINED3DFMT_X4R4G4B4:
1882 case WINED3DFMT_A8B8G8R8:
1883 case WINED3DFMT_X8B8G8R8:
1884 case WINED3DFMT_P8:
1885 case WINED3DFMT_G16R16:
1886 TRACE_(d3d_caps)("[OK]\n");
1887 return WINED3D_OK;
1888 case WINED3DFMT_R16F:
1889 case WINED3DFMT_A16B16G16R16F:
1890 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1891 TRACE_(d3d_caps)("[FAILED]\n");
1892 return WINED3DERR_NOTAVAILABLE;
1894 TRACE_(d3d_caps)("[OK]\n");
1895 return WINED3D_OK;
1896 case WINED3DFMT_A32B32G32R32F:
1897 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1898 TRACE_(d3d_caps)("[FAILED]\n");
1899 return WINED3DERR_NOTAVAILABLE;
1901 TRACE_(d3d_caps)("[OK]\n");
1902 return WINED3D_OK;
1903 default:
1904 TRACE_(d3d_caps)("[FAILED]\n");
1905 return WINED3DERR_NOTAVAILABLE;
1907 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1908 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1909 switch (CheckFormat) {
1910 case WINED3DFMT_V8U8:
1911 TRACE_(d3d_caps)("[OK]\n");
1912 return WINED3D_OK;
1913 /* TODO: Other bump map formats */
1914 default:
1915 TRACE_(d3d_caps)("[FAILED]\n");
1916 return WINED3DERR_NOTAVAILABLE;
1919 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1920 switch (CheckFormat) {
1921 case WINED3DFMT_V8U8:
1922 TRACE_(d3d_caps)("[OK]\n");
1923 return WINED3D_OK;
1924 default:
1925 TRACE_(d3d_caps)("[FAILED]\n");
1926 return WINED3DERR_NOTAVAILABLE;
1929 TRACE_(d3d_caps)("[FAILED]\n");
1930 return WINED3DERR_NOTAVAILABLE;
1933 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1934 if (Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
1935 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
1936 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
1939 switch (CheckFormat) {
1940 case WINED3DFMT_A8R8G8B8:
1941 case WINED3DFMT_X8R8G8B8:
1942 case WINED3DFMT_A4R4G4B4:
1943 case WINED3DFMT_L8:
1944 case WINED3DFMT_A8L8:
1945 case WINED3DFMT_DXT1:
1946 case WINED3DFMT_DXT2:
1947 case WINED3DFMT_DXT3:
1948 case WINED3DFMT_DXT4:
1949 case WINED3DFMT_DXT5:
1950 TRACE_(d3d_caps)("[OK]\n");
1951 break; /* Continue with checking other flags */
1953 default:
1954 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1955 return WINED3DERR_NOTAVAILABLE;
1959 /* This format is nothing special and it is supported perfectly.
1960 * However, ati and nvidia driver on windows do not mark this format as
1961 * supported (tested with the dxCapsViewer) and pretending to
1962 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1963 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1964 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1966 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1967 TRACE_(d3d_caps)("[FAILED]\n");
1968 return WINED3DERR_NOTAVAILABLE;
1971 switch (CheckFormat) {
1973 /*****
1974 * supported: RGB(A) formats
1976 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1977 case WINED3DFMT_A8R8G8B8:
1978 case WINED3DFMT_X8R8G8B8:
1979 case WINED3DFMT_R5G6B5:
1980 case WINED3DFMT_X1R5G5B5:
1981 case WINED3DFMT_A1R5G5B5:
1982 case WINED3DFMT_A4R4G4B4:
1983 case WINED3DFMT_R3G3B2:
1984 case WINED3DFMT_A8:
1985 case WINED3DFMT_X4R4G4B4:
1986 case WINED3DFMT_A8B8G8R8:
1987 case WINED3DFMT_X8B8G8R8:
1988 case WINED3DFMT_A2R10G10B10:
1989 case WINED3DFMT_A2B10G10R10:
1990 case WINED3DFMT_G16R16:
1991 TRACE_(d3d_caps)("[OK]\n");
1992 return WINED3D_OK;
1994 /*****
1995 * supported: Palettized
1997 case WINED3DFMT_P8:
1998 TRACE_(d3d_caps)("[OK]\n");
1999 return WINED3D_OK;
2001 /*****
2002 * Supported: (Alpha)-Luminance
2004 case WINED3DFMT_L8:
2005 case WINED3DFMT_A8L8:
2006 case WINED3DFMT_A4L4:
2007 TRACE_(d3d_caps)("[OK]\n");
2008 return WINED3D_OK;
2010 /*****
2011 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2012 * GL_NV_texture_shader), but advertized to make apps happy.
2013 * Enable some because games often fail when they are not available
2014 * and are still playable even without bump mapping
2016 case WINED3DFMT_V8U8:
2017 case WINED3DFMT_V16U16:
2018 case WINED3DFMT_L6V5U5:
2019 case WINED3DFMT_X8L8V8U8:
2020 case WINED3DFMT_Q8W8V8U8:
2021 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
2022 return WINED3D_OK;
2024 /* Those are not advertized by the nvidia windows driver, and not
2025 * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
2026 * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
2027 * ARGB format if needed
2029 case WINED3DFMT_W11V11U10:
2030 case WINED3DFMT_A2W10V10U10:
2031 WARN_(d3d_caps)("[FAILED]\n");
2032 return WINED3DERR_NOTAVAILABLE;
2034 case WINED3DFMT_DXT1:
2035 case WINED3DFMT_DXT2:
2036 case WINED3DFMT_DXT3:
2037 case WINED3DFMT_DXT4:
2038 case WINED3DFMT_DXT5:
2039 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2040 TRACE_(d3d_caps)("[OK]\n");
2041 return WINED3D_OK;
2042 } else {
2043 TRACE_(d3d_caps)("[FAILED]\n");
2044 return WINED3DERR_NOTAVAILABLE;
2048 /*****
2049 * Odd formats - not supported
2051 case WINED3DFMT_VERTEXDATA:
2052 case WINED3DFMT_INDEX16:
2053 case WINED3DFMT_INDEX32:
2054 case WINED3DFMT_Q16W16V16U16:
2055 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2056 return WINED3DERR_NOTAVAILABLE;
2058 /*****
2059 * WINED3DFMT_CxV8U8: Not supported right now
2061 case WINED3DFMT_CxV8U8:
2062 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2063 return WINED3DERR_NOTAVAILABLE;
2065 /* Not supported */
2066 case WINED3DFMT_A16B16G16R16:
2067 case WINED3DFMT_A8R3G3B2:
2068 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2069 return WINED3DERR_NOTAVAILABLE;
2071 /* Floating point formats */
2072 case WINED3DFMT_R16F:
2073 case WINED3DFMT_A16B16G16R16F:
2074 if(GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2075 TRACE_(d3d_caps)("[OK]\n");
2076 return WINED3D_OK;
2077 } else {
2078 TRACE_(d3d_caps)("[FAILED]\n");
2079 return WINED3DERR_NOTAVAILABLE;
2081 case WINED3DFMT_R32F:
2082 case WINED3DFMT_A32B32G32R32F:
2083 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2084 TRACE_(d3d_caps)("[OK]\n");
2085 return WINED3D_OK;
2086 } else {
2087 TRACE_(d3d_caps)("[FAILED]\n");
2088 return WINED3DERR_NOTAVAILABLE;
2091 case WINED3DFMT_G16R16F:
2092 case WINED3DFMT_G32R32F:
2093 TRACE_(d3d_caps)("[FAILED]\n");
2094 return WINED3DERR_NOTAVAILABLE;
2096 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2097 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2098 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2099 * We can do instancing with all shader versions, but we need vertex shaders.
2101 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2102 * to enable instancing. WineD3D doesn't need that and just ignores it.
2104 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2106 case WINEMAKEFOURCC('I','N','S','T'):
2107 TRACE("ATI Instancing check hack\n");
2108 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2109 TRACE_(d3d_caps)("[OK]\n");
2110 return WINED3D_OK;
2111 } else {
2112 TRACE_(d3d_caps)("[FAILED]\n");
2113 return WINED3DERR_NOTAVAILABLE;
2116 default:
2117 break;
2120 TRACE_(d3d_caps)("[FAILED]\n");
2121 return WINED3DERR_NOTAVAILABLE;
2124 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2125 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2126 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2128 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2129 This,
2130 Adapter,
2131 DeviceType, debug_d3ddevicetype(DeviceType),
2132 SourceFormat, debug_d3dformat(SourceFormat),
2133 TargetFormat, debug_d3dformat(TargetFormat));
2134 return WINED3D_OK;
2137 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
2138 subset of a D3DCAPS9 structure. However, it has to come via a void *
2139 as the d3d8 interface cannot import the d3d9 header */
2140 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
2142 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2143 int vs_selected_mode;
2144 int ps_selected_mode;
2146 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
2148 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2149 return WINED3DERR_INVALIDCALL;
2152 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2154 /* This function should *not* be modifying GL caps
2155 * TODO: move the functionality where it belongs */
2156 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
2158 /* ------------------------------------------------
2159 The following fields apply to both d3d8 and d3d9
2160 ------------------------------------------------ */
2161 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
2162 *pCaps->AdapterOrdinal = Adapter;
2164 *pCaps->Caps = 0;
2165 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
2166 WINED3DCAPS2_FULLSCREENGAMMA |
2167 WINED3DCAPS2_DYNAMICTEXTURES;
2168 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2169 *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
2171 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
2172 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
2173 WINED3DPRESENT_INTERVAL_ONE;
2175 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
2176 WINED3DCURSORCAPS_LOWRES;
2178 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
2179 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
2180 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
2181 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
2182 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
2183 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
2184 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
2185 WINED3DDEVCAPS_PUREDEVICE |
2186 WINED3DDEVCAPS_HWRASTERIZATION |
2187 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
2188 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
2189 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
2190 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
2191 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
2192 WINED3DDEVCAPS_RTPATCHES;
2194 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
2195 WINED3DPMISCCAPS_CULLCCW |
2196 WINED3DPMISCCAPS_CULLCW |
2197 WINED3DPMISCCAPS_COLORWRITEENABLE |
2198 WINED3DPMISCCAPS_CLIPTLVERTS |
2199 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
2200 WINED3DPMISCCAPS_MASKZ |
2201 WINED3DPMISCCAPS_BLENDOP;
2202 /* TODO:
2203 WINED3DPMISCCAPS_NULLREFERENCE
2204 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
2205 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
2206 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
2207 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
2208 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
2210 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
2211 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
2213 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
2214 #if 0
2215 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
2216 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
2217 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
2218 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
2219 #endif
2221 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
2222 WINED3DPRASTERCAPS_PAT |
2223 WINED3DPRASTERCAPS_WFOG |
2224 WINED3DPRASTERCAPS_ZFOG |
2225 WINED3DPRASTERCAPS_FOGVERTEX |
2226 WINED3DPRASTERCAPS_FOGTABLE |
2227 WINED3DPRASTERCAPS_STIPPLE |
2228 WINED3DPRASTERCAPS_SUBPIXEL |
2229 WINED3DPRASTERCAPS_ZTEST |
2230 WINED3DPRASTERCAPS_SCISSORTEST |
2231 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
2232 WINED3DPRASTERCAPS_DEPTHBIAS;
2234 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2235 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
2236 WINED3DPRASTERCAPS_ZBIAS |
2237 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
2239 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
2240 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
2242 /* FIXME Add:
2243 WINED3DPRASTERCAPS_COLORPERSPECTIVE
2244 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
2245 WINED3DPRASTERCAPS_ANTIALIASEDGES
2246 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
2247 WINED3DPRASTERCAPS_WBUFFER */
2249 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2250 WINED3DPCMPCAPS_EQUAL |
2251 WINED3DPCMPCAPS_GREATER |
2252 WINED3DPCMPCAPS_GREATEREQUAL |
2253 WINED3DPCMPCAPS_LESS |
2254 WINED3DPCMPCAPS_LESSEQUAL |
2255 WINED3DPCMPCAPS_NEVER |
2256 WINED3DPCMPCAPS_NOTEQUAL;
2258 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
2259 WINED3DPBLENDCAPS_BOTHSRCALPHA |
2260 WINED3DPBLENDCAPS_DESTALPHA |
2261 WINED3DPBLENDCAPS_DESTCOLOR |
2262 WINED3DPBLENDCAPS_INVDESTALPHA |
2263 WINED3DPBLENDCAPS_INVDESTCOLOR |
2264 WINED3DPBLENDCAPS_INVSRCALPHA |
2265 WINED3DPBLENDCAPS_INVSRCCOLOR |
2266 WINED3DPBLENDCAPS_ONE |
2267 WINED3DPBLENDCAPS_SRCALPHA |
2268 WINED3DPBLENDCAPS_SRCALPHASAT |
2269 WINED3DPBLENDCAPS_SRCCOLOR |
2270 WINED3DPBLENDCAPS_ZERO;
2272 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
2273 WINED3DPBLENDCAPS_DESTCOLOR |
2274 WINED3DPBLENDCAPS_INVDESTALPHA |
2275 WINED3DPBLENDCAPS_INVDESTCOLOR |
2276 WINED3DPBLENDCAPS_INVSRCALPHA |
2277 WINED3DPBLENDCAPS_INVSRCCOLOR |
2278 WINED3DPBLENDCAPS_ONE |
2279 WINED3DPBLENDCAPS_SRCALPHA |
2280 WINED3DPBLENDCAPS_SRCCOLOR |
2281 WINED3DPBLENDCAPS_ZERO;
2282 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
2283 * according to the glBlendFunc manpage
2285 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
2286 * legacy settings for srcblend only
2289 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
2290 *pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2291 *pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
2295 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2296 WINED3DPCMPCAPS_EQUAL |
2297 WINED3DPCMPCAPS_GREATER |
2298 WINED3DPCMPCAPS_GREATEREQUAL |
2299 WINED3DPCMPCAPS_LESS |
2300 WINED3DPCMPCAPS_LESSEQUAL |
2301 WINED3DPCMPCAPS_NEVER |
2302 WINED3DPCMPCAPS_NOTEQUAL;
2304 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2305 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2306 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2307 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2308 WINED3DPSHADECAPS_COLORFLATRGB |
2309 WINED3DPSHADECAPS_FOGFLAT |
2310 WINED3DPSHADECAPS_FOGGOURAUD |
2311 WINED3DPSHADECAPS_SPECULARFLATRGB;
2313 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2314 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2315 WINED3DPTEXTURECAPS_BORDER |
2316 WINED3DPTEXTURECAPS_MIPMAP |
2317 WINED3DPTEXTURECAPS_PROJECTED |
2318 WINED3DPTEXTURECAPS_PERSPECTIVE;
2320 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
2321 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
2322 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2325 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2326 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2327 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2328 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2331 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2332 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2333 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2334 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2338 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2339 WINED3DPTFILTERCAPS_MAGFPOINT |
2340 WINED3DPTFILTERCAPS_MINFLINEAR |
2341 WINED3DPTFILTERCAPS_MINFPOINT |
2342 WINED3DPTFILTERCAPS_MIPFLINEAR |
2343 WINED3DPTFILTERCAPS_MIPFPOINT |
2344 WINED3DPTFILTERCAPS_LINEAR |
2345 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2346 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2347 WINED3DPTFILTERCAPS_MIPLINEAR |
2348 WINED3DPTFILTERCAPS_MIPNEAREST |
2349 WINED3DPTFILTERCAPS_NEAREST;
2351 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2352 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2353 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2356 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2357 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2358 WINED3DPTFILTERCAPS_MAGFPOINT |
2359 WINED3DPTFILTERCAPS_MINFLINEAR |
2360 WINED3DPTFILTERCAPS_MINFPOINT |
2361 WINED3DPTFILTERCAPS_MIPFLINEAR |
2362 WINED3DPTFILTERCAPS_MIPFPOINT |
2363 WINED3DPTFILTERCAPS_LINEAR |
2364 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2365 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2366 WINED3DPTFILTERCAPS_MIPLINEAR |
2367 WINED3DPTFILTERCAPS_MIPNEAREST |
2368 WINED3DPTFILTERCAPS_NEAREST;
2370 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2371 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2372 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2374 } else
2375 *pCaps->CubeTextureFilterCaps = 0;
2377 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2378 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2379 WINED3DPTFILTERCAPS_MAGFPOINT |
2380 WINED3DPTFILTERCAPS_MINFLINEAR |
2381 WINED3DPTFILTERCAPS_MINFPOINT |
2382 WINED3DPTFILTERCAPS_MIPFLINEAR |
2383 WINED3DPTFILTERCAPS_MIPFPOINT |
2384 WINED3DPTFILTERCAPS_LINEAR |
2385 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2386 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2387 WINED3DPTFILTERCAPS_MIPLINEAR |
2388 WINED3DPTFILTERCAPS_MIPNEAREST |
2389 WINED3DPTFILTERCAPS_NEAREST;
2390 } else
2391 *pCaps->VolumeTextureFilterCaps = 0;
2393 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2394 WINED3DPTADDRESSCAPS_CLAMP |
2395 WINED3DPTADDRESSCAPS_WRAP;
2397 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2398 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2400 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2401 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2403 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2404 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2407 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2408 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2409 WINED3DPTADDRESSCAPS_CLAMP |
2410 WINED3DPTADDRESSCAPS_WRAP;
2411 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2412 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2414 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2415 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2417 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2418 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2420 } else
2421 *pCaps->VolumeTextureAddressCaps = 0;
2423 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2424 WINED3DLINECAPS_ZTEST;
2425 /* FIXME: Add
2426 WINED3DLINECAPS_BLEND
2427 WINED3DLINECAPS_ALPHACMP
2428 WINED3DLINECAPS_FOG */
2430 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2431 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2433 if(GL_SUPPORT(EXT_TEXTURE3D))
2434 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2435 else
2436 *pCaps->MaxVolumeExtent = 0;
2438 *pCaps->MaxTextureRepeat = 32768;
2439 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2440 *pCaps->MaxVertexW = 1.0;
2442 *pCaps->GuardBandLeft = 0;
2443 *pCaps->GuardBandTop = 0;
2444 *pCaps->GuardBandRight = 0;
2445 *pCaps->GuardBandBottom = 0;
2447 *pCaps->ExtentsAdjust = 0;
2449 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2450 WINED3DSTENCILCAPS_INCRSAT |
2451 WINED3DSTENCILCAPS_INVERT |
2452 WINED3DSTENCILCAPS_KEEP |
2453 WINED3DSTENCILCAPS_REPLACE |
2454 WINED3DSTENCILCAPS_ZERO;
2455 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2456 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2457 WINED3DSTENCILCAPS_INCR;
2459 if ( This->dxVersion > 8 &&
2460 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2461 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2462 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2465 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2467 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2468 WINED3DTEXOPCAPS_ADDSIGNED |
2469 WINED3DTEXOPCAPS_ADDSIGNED2X |
2470 WINED3DTEXOPCAPS_MODULATE |
2471 WINED3DTEXOPCAPS_MODULATE2X |
2472 WINED3DTEXOPCAPS_MODULATE4X |
2473 WINED3DTEXOPCAPS_SELECTARG1 |
2474 WINED3DTEXOPCAPS_SELECTARG2 |
2475 WINED3DTEXOPCAPS_DISABLE;
2477 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2478 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2479 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2480 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2481 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2482 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2483 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2484 WINED3DTEXOPCAPS_LERP |
2485 WINED3DTEXOPCAPS_SUBTRACT;
2487 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2488 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2489 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2490 WINED3DTEXOPCAPS_MULTIPLYADD |
2491 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2492 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2493 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2495 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2496 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2498 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2499 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2500 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2503 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2504 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2505 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2506 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2507 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2508 * and 3D textures. It also allows us to keep the code simpler by having texture
2509 * shaders constantly enabled.
2511 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2512 /* TODO: Luminance bump map? */
2514 #if 0
2515 /* FIXME: Add
2516 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2517 WINED3DTEXOPCAPS_PREMODULATE */
2518 #endif
2520 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2521 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2522 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2523 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2525 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2526 *pCaps->MaxVertexBlendMatrixIndex = 0;
2528 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2529 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2532 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2533 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2534 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2535 WINED3DVTXPCAPS_LOCALVIEWER |
2536 WINED3DVTXPCAPS_VERTEXFOG |
2537 WINED3DVTXPCAPS_TEXGEN;
2538 /* FIXME: Add
2539 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2541 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2542 *pCaps->MaxVertexIndex = 0xFFFFF;
2543 *pCaps->MaxStreams = MAX_STREAMS;
2544 *pCaps->MaxStreamStride = 1024;
2546 if (vs_selected_mode == SHADER_GLSL) {
2547 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2548 * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2549 * vs_nv_version which is based on NV_vertex_program.
2550 * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
2551 * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
2552 * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
2553 * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
2554 if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2555 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2556 else
2557 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2558 TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
2559 } else if (vs_selected_mode == SHADER_ARB) {
2560 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2561 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2562 } else {
2563 *pCaps->VertexShaderVersion = 0;
2564 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2567 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2569 if (ps_selected_mode == SHADER_GLSL) {
2570 /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
2571 * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
2572 * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
2573 * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
2574 * in max native instructions. Intel and others also offer the info in this extension but they
2575 * don't support GLSL (at least on Windows).
2577 * PS2.0 requires at least 96 instructions, 2.0a/2.0b go up to 512. Assume that if the number
2578 * of instructions is 512 or less we have to do with ps2.0 hardware.
2579 * 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.
2581 if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
2582 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2583 else
2584 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2585 /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
2586 * Direct3D minimum requirement.
2588 * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
2589 * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
2591 * The problem is that the refrast clamps temporary results in the shader to
2592 * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
2593 * then applications may miss the clamping behavior. On the other hand, if it is smaller,
2594 * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
2595 * offer a way to query this.
2597 *pCaps->PixelShader1xMaxValue = 8.0;
2598 TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
2599 } else if (ps_selected_mode == SHADER_ARB) {
2600 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2601 *pCaps->PixelShader1xMaxValue = 8.0;
2602 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2603 } else {
2604 *pCaps->PixelShaderVersion = 0;
2605 *pCaps->PixelShader1xMaxValue = 0.0;
2606 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2609 /* ------------------------------------------------
2610 The following fields apply to d3d9 only
2611 ------------------------------------------------ */
2612 if (This->dxVersion > 8) {
2613 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2614 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2615 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2616 *pCaps->MaxNpatchTessellationLevel = 0;
2617 *pCaps->MasterAdapterOrdinal = 0;
2618 *pCaps->AdapterOrdinalInGroup = 0;
2619 *pCaps->NumberOfAdaptersInGroup = 1;
2621 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2622 /* OpenGL supports all the formats below, perhaps not always
2623 * without conversion, but it supports them.
2624 * Further GLSL doesn't seem to have an official unsigned type so
2625 * don't advertise it yet as I'm not sure how we handle it.
2626 * We might need to add some clamping in the shader engine to
2627 * support it.
2628 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2629 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2630 WINED3DDTCAPS_UBYTE4N |
2631 WINED3DDTCAPS_SHORT2N |
2632 WINED3DDTCAPS_SHORT4N;
2633 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2634 *pCaps->DeclTypes |=
2635 WINED3DDTCAPS_FLOAT16_2 |
2636 WINED3DDTCAPS_FLOAT16_4;
2638 } else
2639 *pCaps->DeclTypes = 0;
2641 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2644 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2645 WINED3DPTFILTERCAPS_MAGFPOINT |
2646 WINED3DPTFILTERCAPS_MINFLINEAR |
2647 WINED3DPTFILTERCAPS_MAGFLINEAR;
2648 *pCaps->VertexTextureFilterCaps = 0;
2650 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2651 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2652 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2653 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2654 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2655 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2656 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2658 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2659 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2660 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2661 *pCaps->VS20Caps.Caps = 0;
2662 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2663 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2664 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2666 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2667 *pCaps->MaxVertexShader30InstructionSlots = 0;
2668 } else { /* VS 1.x */
2669 *pCaps->VS20Caps.Caps = 0;
2670 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2671 *pCaps->VS20Caps.NumTemps = 0;
2672 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2674 *pCaps->MaxVShaderInstructionsExecuted = 0;
2675 *pCaps->MaxVertexShader30InstructionSlots = 0;
2678 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2679 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2680 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2682 /* 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 */
2683 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2684 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2685 WINED3DPS20CAPS_PREDICATION |
2686 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2687 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2688 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2689 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2690 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2691 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2693 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2694 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2695 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2696 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2697 *pCaps->PS20Caps.Caps = 0;
2698 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2699 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2700 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
2701 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2703 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2704 *pCaps->MaxPixelShader30InstructionSlots = 0;
2705 } else { /* PS 1.x */
2706 *pCaps->PS20Caps.Caps = 0;
2707 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2708 *pCaps->PS20Caps.NumTemps = 0;
2709 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2710 *pCaps->PS20Caps.NumInstructionSlots = 0;
2712 *pCaps->MaxPShaderInstructionsExecuted = 0;
2713 *pCaps->MaxPixelShader30InstructionSlots = 0;
2717 return WINED3D_OK;
2720 static unsigned int glsl_program_key_hash(void *key) {
2721 glsl_program_key_t *k = (glsl_program_key_t *)key;
2723 unsigned int hash = k->vshader | k->pshader << 16;
2724 hash += ~(hash << 15);
2725 hash ^= (hash >> 10);
2726 hash += (hash << 3);
2727 hash ^= (hash >> 6);
2728 hash += ~(hash << 11);
2729 hash ^= (hash >> 16);
2731 return hash;
2734 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2735 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2736 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2738 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2741 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2742 and fields being inserted in the middle, a new structure is used in place */
2743 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2744 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2745 IUnknown *parent) {
2747 IWineD3DDeviceImpl *object = NULL;
2748 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2749 WINED3DDISPLAYMODE mode;
2750 int i;
2752 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2753 * number and create a device without a 3D adapter for 2D only operation.
2755 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2756 return WINED3DERR_INVALIDCALL;
2759 /* Create a WineD3DDevice object */
2760 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2761 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2762 TRACE("Created WineD3DDevice object @ %p\n", object);
2763 if (NULL == object) {
2764 return WINED3DERR_OUTOFVIDEOMEMORY;
2767 /* Set up initial COM information */
2768 object->lpVtbl = &IWineD3DDevice_Vtbl;
2769 object->ref = 1;
2770 object->wineD3D = iface;
2771 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2772 IWineD3D_AddRef(object->wineD3D);
2773 object->parent = parent;
2774 list_init(&object->resources);
2775 list_init(&object->shaders);
2777 if(This->dxVersion == 7) {
2778 object->surface_alignment = 8;
2779 } else {
2780 object->surface_alignment = 4;
2782 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
2784 /* Set the state up as invalid until the device is fully created */
2785 object->state = WINED3DERR_DRIVERINTERNALERROR;
2787 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2788 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2790 /* Save the creation parameters */
2791 object->createParms.AdapterOrdinal = Adapter;
2792 object->createParms.DeviceType = DeviceType;
2793 object->createParms.hFocusWindow = hFocusWindow;
2794 object->createParms.BehaviorFlags = BehaviourFlags;
2796 /* Initialize other useful values */
2797 object->adapterNo = Adapter;
2798 object->devType = DeviceType;
2800 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2801 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2802 object->shader_backend = &glsl_shader_backend;
2803 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2804 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2805 object->shader_backend = &arb_program_shader_backend;
2806 } else {
2807 object->shader_backend = &none_shader_backend;
2810 /* set the state of the device to valid */
2811 object->state = WINED3D_OK;
2813 /* Get the initial screen setup for ddraw */
2814 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
2816 object->ddraw_width = mode.Width;
2817 object->ddraw_height = mode.Height;
2818 object->ddraw_format = mode.Format;
2820 for(i = 0; i < PATCHMAP_SIZE; i++) {
2821 list_init(&object->patches[i]);
2823 return WINED3D_OK;
2825 #undef GLINFO_LOCATION
2827 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2828 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2829 IUnknown_AddRef(This->parent);
2830 *pParent = This->parent;
2831 return WINED3D_OK;
2834 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2835 IUnknown* surfaceParent;
2836 TRACE("(%p) call back\n", pSurface);
2838 /* Now, release the parent, which will take care of cleaning up the surface for us */
2839 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2840 IUnknown_Release(surfaceParent);
2841 return IUnknown_Release(surfaceParent);
2844 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2845 IUnknown* volumeParent;
2846 TRACE("(%p) call back\n", pVolume);
2848 /* Now, release the parent, which will take care of cleaning up the volume for us */
2849 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2850 IUnknown_Release(volumeParent);
2851 return IUnknown_Release(volumeParent);
2854 static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
2855 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
2856 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
2857 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
2859 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
2860 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
2861 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
2862 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
2863 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
2864 * the chance that other implementations support them is rather small since Win32 QuickTime uses
2865 * DirectDraw, not OpenGL.
2867 if(gl_info->supported[APPLE_FENCE] &&
2868 gl_info->supported[APPLE_CLIENT_STORAGE] &&
2869 gl_info->supported[APPLE_FLUSH_RENDER] &&
2870 gl_info->supported[APPLE_YCBCR_422]) {
2871 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
2872 TRACE_(d3d_caps)("Activating MacOS fixups\n");
2873 return TRUE;
2874 } else {
2875 TRACE_(d3d_caps)("Apple extensions are not supported\n");
2876 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
2877 return FALSE;
2881 #define GLINFO_LOCATION (*gl_info)
2882 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
2883 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
2884 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
2885 * all the texture. This function detects this bug by its symptom and disables PBOs
2886 * if the test fails.
2888 * The test uplaods a 4x4 texture via the PBO in the "native" format GL_BGRA,
2889 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
2890 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
2891 * read back is compared to the original. If they are equal PBOs are assumed to work,
2892 * otherwise the PBO extension is disabled.
2894 GLuint texture, pbo;
2895 static const unsigned int pattern[] = {
2896 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
2897 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
2898 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
2899 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
2901 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
2903 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
2904 /* No PBO -> No point in testing them */
2905 return;
2908 while(glGetError());
2909 glGenTextures(1, &texture);
2910 glBindTexture(GL_TEXTURE_2D, texture);
2911 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
2912 checkGLcall("Specifying the PBO test texture\n");
2914 GL_EXTCALL(glGenBuffersARB(1, &pbo));
2915 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
2916 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
2917 checkGLcall("Specifying the PBO test pbo\n");
2919 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
2920 checkGLcall("Loading the PBO test texture\n");
2922 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
2923 glFinish(); /* just to be sure */
2925 memset(check, 0, sizeof(check));
2926 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
2927 checkGLcall("Reading back the PBO test texture\n");
2929 glDeleteTextures(1, &texture);
2930 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
2931 checkGLcall("PBO test cleanup\n");
2933 if(memcmp(check, pattern, sizeof(check)) != 0) {
2934 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
2935 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
2936 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
2937 } else {
2938 TRACE_(d3d_caps)("PBO test successfull\n");
2941 #undef GLINFO_LOCATION
2943 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
2944 * reporting a driver version is moot because we are not the Windows driver, and we have different
2945 * bugs, features, etc.
2947 * If a card is not found in this table, the gl driver version is reported
2949 struct driver_version_information {
2950 WORD vendor; /* reported PCI card vendor ID */
2951 WORD card; /* reported PCI card device ID */
2952 WORD hipart_hi, hipart_lo; /* driver hiword to report */
2953 WORD lopart_hi, lopart_lo; /* driver loword to report */
2956 static const struct driver_version_information driver_version_table[] = {
2957 /* Nvidia drivers. Geforce FX and newer cards are supported by the current driver */
2958 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 10, 16921 },
2959 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 10, 16921 },
2960 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 10, 16921 },
2961 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 10, 16921 },
2962 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 10, 16921 },
2963 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 10, 16921 },
2964 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 10, 16921 },
2965 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 10, 16921 },
2966 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 10, 16921 },
2967 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 10, 16921 },
2968 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 10, 16921 },
2969 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 10, 16921 },
2970 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 10, 16921 },
2971 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 10, 16921 },
2973 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
2974 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
2975 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
2976 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
2977 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
2978 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
2979 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
2981 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
2984 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
2985 unsigned int i;
2986 BOOL apple = implementation_is_apple(gl_info);
2988 if(apple) {
2989 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
2990 * used it falls back to software. While the compiler can detect if the shader uses all declared
2991 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
2992 * using relative addressing falls back to software.
2994 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
2996 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
2997 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
2998 } else {
2999 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3000 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3001 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3004 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
3005 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
3006 * If real NP2 textures are used, the driver falls back to software. So remove the supported
3007 * flag for this extension
3009 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
3010 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
3011 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
3012 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
3013 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
3014 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3015 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
3019 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3020 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3021 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3022 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3023 * according to the spec.
3025 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3026 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3028 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards blacklist
3029 * all radeon cards on Macs but whitelist the good ones, that way we're prepared for the future. If
3030 * this workaround is activated on cards that do not need it it won't break things, just affect
3031 * performance negatively
3033 if(gl_info->gl_vendor == VENDOR_INTEL ||
3034 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
3035 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
3036 gl_info->set_texcoord_w = TRUE;
3040 /* Find out if PBOs work as they are supposed to */
3041 test_pbo_functionality(gl_info);
3043 /* Fixup the driver version */
3044 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
3045 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
3046 gl_info->gl_card == driver_version_table[i].card) {
3047 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
3049 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
3050 driver_version_table[i].lopart_lo);
3051 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
3052 driver_version_table[i].hipart_lo);
3053 break;
3058 void invalid_func(void *data) {
3059 ERR("Invalid vertex attribute function called\n");
3060 DebugBreak();
3063 #define GLINFO_LOCATION (Adapters[0].gl_info)
3065 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
3066 * the extension detection and are used in drawStridedSlow
3068 static void position_d3dcolor(void *data) {
3069 DWORD pos = *((DWORD *) data);
3071 FIXME("Add a test for fixed function position from d3dcolor type\n");
3072 glVertex4s(D3DCOLOR_B_R(pos),
3073 D3DCOLOR_B_G(pos),
3074 D3DCOLOR_B_B(pos),
3075 D3DCOLOR_B_A(pos));
3077 static void position_float4(void *data) {
3078 GLfloat *pos = (float *) data;
3080 if (pos[3] < eps && pos[3] > -eps)
3081 glVertex3fv(pos);
3082 else {
3083 float w = 1.0 / pos[3];
3085 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
3089 static void diffuse_d3dcolor(void *data) {
3090 DWORD diffuseColor = *((DWORD *) data);
3092 glColor4ub(D3DCOLOR_B_R(diffuseColor),
3093 D3DCOLOR_B_G(diffuseColor),
3094 D3DCOLOR_B_B(diffuseColor),
3095 D3DCOLOR_B_A(diffuseColor));
3098 static void specular_d3dcolor(void *data) {
3099 DWORD specularColor = *((DWORD *) data);
3101 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
3102 D3DCOLOR_B_G(specularColor),
3103 D3DCOLOR_B_B(specularColor));
3105 static void warn_no_specular_func(void *data) {
3106 WARN("GL_EXT_secondary_color not supported\n");
3109 void fillGLAttribFuncs(WineD3D_GL_Info *gl_info) {
3110 position_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3111 position_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3112 position_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glVertex3fv;
3113 position_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) position_float4;
3114 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) position_d3dcolor;
3115 position_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3116 position_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3117 position_funcs[WINED3DDECLTYPE_SHORT4] = (void *) glVertex2sv;
3118 position_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3119 position_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3120 position_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3121 position_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3122 position_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3123 position_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3124 position_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3125 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3126 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3128 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3129 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3130 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glColor3fv;
3131 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glColor4fv;
3132 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) diffuse_d3dcolor;
3133 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3134 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3135 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3136 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) glColor4ubv;
3137 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3138 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) glColor4sv;
3139 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3140 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) glColor4usv;
3141 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3142 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3143 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3144 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3146 /* No 4 component entry points here */
3147 specular_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3148 specular_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3149 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3150 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) GL_EXTCALL(glSecondaryColor3fvEXT);
3151 } else {
3152 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
3154 specular_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) invalid_func;
3155 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3156 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) specular_d3dcolor;
3157 } else {
3158 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) warn_no_specular_func;
3160 specular_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3161 specular_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3162 specular_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3163 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3164 specular_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3165 specular_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3166 specular_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3167 specular_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3168 specular_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3169 specular_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3170 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3171 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3173 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
3174 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
3176 normal_funcs[WINED3DDECLTYPE_FLOAT1] = (void *) invalid_func;
3177 normal_funcs[WINED3DDECLTYPE_FLOAT2] = (void *) invalid_func;
3178 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (void *) glNormal3fv;
3179 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (void *) glNormal3fv; /* Just ignore the 4th value */
3180 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = (void *) invalid_func;
3181 normal_funcs[WINED3DDECLTYPE_UBYTE4] = (void *) invalid_func;
3182 normal_funcs[WINED3DDECLTYPE_SHORT2] = (void *) invalid_func;
3183 normal_funcs[WINED3DDECLTYPE_SHORT4] = (void *) invalid_func;
3184 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = (void *) invalid_func;
3185 normal_funcs[WINED3DDECLTYPE_SHORT2N] = (void *) invalid_func;
3186 normal_funcs[WINED3DDECLTYPE_SHORT4N] = (void *) invalid_func;
3187 normal_funcs[WINED3DDECLTYPE_USHORT2N] = (void *) invalid_func;
3188 normal_funcs[WINED3DDECLTYPE_USHORT4N] = (void *) invalid_func;
3189 normal_funcs[WINED3DDECLTYPE_UDEC3] = (void *) invalid_func;
3190 normal_funcs[WINED3DDECLTYPE_DEC3N] = (void *) invalid_func;
3191 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = (void *) invalid_func;
3192 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = (void *) invalid_func;
3195 #define PUSH1(att) attribs[nAttribs++] = (att);
3196 BOOL InitAdapters(void) {
3197 static HMODULE mod_gl;
3198 BOOL ret;
3199 int ps_selected_mode, vs_selected_mode;
3201 /* No need to hold any lock. The calling library makes sure only one thread calls
3202 * wined3d simultaneously
3204 if(numAdapters > 0) return TRUE;
3206 TRACE("Initializing adapters\n");
3208 if(!mod_gl) {
3209 #ifdef USE_WIN32_OPENGL
3210 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
3211 mod_gl = LoadLibraryA("opengl32.dll");
3212 if(!mod_gl) {
3213 ERR("Can't load opengl32.dll!\n");
3214 return FALSE;
3216 #else
3217 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
3218 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
3219 mod_gl = GetModuleHandleA("gdi32.dll");
3220 #endif
3223 /* Load WGL core functions from opengl32.dll */
3224 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
3225 WGL_FUNCS_GEN;
3226 #undef USE_WGL_FUNC
3228 if(!pwglGetProcAddress) {
3229 ERR("Unable to load wglGetProcAddress!\n");
3230 return FALSE;
3233 /* Dynamically load all GL core functions */
3234 GL_FUNCS_GEN;
3235 #undef USE_GL_FUNC
3237 /* For now only one default adapter */
3239 int iPixelFormat;
3240 int attribs[8];
3241 int values[8];
3242 int nAttribs = 0;
3243 int res;
3244 WineD3D_PixelFormat *cfgs;
3245 int attribute;
3246 DISPLAY_DEVICEW DisplayDevice;
3247 HDC hdc;
3249 TRACE("Initializing default adapter\n");
3250 Adapters[0].num = 0;
3251 Adapters[0].monitorPoint.x = -1;
3252 Adapters[0].monitorPoint.y = -1;
3254 if (!WineD3D_CreateFakeGLContext()) {
3255 ERR("Failed to get a gl context for default adapter\n");
3256 HeapFree(GetProcessHeap(), 0, Adapters);
3257 WineD3D_ReleaseFakeGLContext();
3258 return FALSE;
3261 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
3262 if(!ret) {
3263 ERR("Failed to initialize gl caps for default adapter\n");
3264 HeapFree(GetProcessHeap(), 0, Adapters);
3265 WineD3D_ReleaseFakeGLContext();
3266 return FALSE;
3268 ret = initPixelFormats(&Adapters[0].gl_info);
3269 if(!ret) {
3270 ERR("Failed to init gl formats\n");
3271 HeapFree(GetProcessHeap(), 0, Adapters);
3272 WineD3D_ReleaseFakeGLContext();
3273 return FALSE;
3276 hdc = pwglGetCurrentDC();
3277 if(!hdc) {
3278 ERR("Failed to get gl HDC\n");
3279 HeapFree(GetProcessHeap(), 0, Adapters);
3280 WineD3D_ReleaseFakeGLContext();
3281 return FALSE;
3284 Adapters[0].driver = "Display";
3285 Adapters[0].description = "Direct3D HAL";
3287 /* Use the VideoRamSize registry setting when set */
3288 if(wined3d_settings.emulated_textureram)
3289 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
3290 else
3291 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
3292 Adapters[0].UsedTextureRam = 0;
3293 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
3295 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
3296 DisplayDevice.cb = sizeof(DisplayDevice);
3297 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
3298 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
3299 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
3301 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
3302 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
3304 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
3305 cfgs = Adapters[0].cfgs;
3306 PUSH1(WGL_RED_BITS_ARB)
3307 PUSH1(WGL_GREEN_BITS_ARB)
3308 PUSH1(WGL_BLUE_BITS_ARB)
3309 PUSH1(WGL_ALPHA_BITS_ARB)
3310 PUSH1(WGL_DEPTH_BITS_ARB)
3311 PUSH1(WGL_STENCIL_BITS_ARB)
3313 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
3314 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
3316 if(!res)
3317 continue;
3319 /* Cache the pixel format */
3320 cfgs->iPixelFormat = iPixelFormat;
3321 cfgs->redSize = values[0];
3322 cfgs->greenSize = values[1];
3323 cfgs->blueSize = values[2];
3324 cfgs->alphaSize = values[3];
3325 cfgs->depthSize = values[4];
3326 cfgs->stencilSize = values[5];
3328 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);
3329 cfgs++;
3331 WineD3D_ReleaseFakeGLContext();
3333 fixup_extensions(&Adapters[0].gl_info);
3335 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
3336 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
3337 fillGLAttribFuncs(&Adapters[0].gl_info);
3338 init_type_lookup(&Adapters[0].gl_info);
3340 numAdapters = 1;
3341 TRACE("%d adapters successfully initialized\n", numAdapters);
3343 return TRUE;
3345 #undef PUSH1
3346 #undef GLINFO_LOCATION
3348 /**********************************************************
3349 * IWineD3D VTbl follows
3350 **********************************************************/
3352 const IWineD3DVtbl IWineD3D_Vtbl =
3354 /* IUnknown */
3355 IWineD3DImpl_QueryInterface,
3356 IWineD3DImpl_AddRef,
3357 IWineD3DImpl_Release,
3358 /* IWineD3D */
3359 IWineD3DImpl_GetParent,
3360 IWineD3DImpl_GetAdapterCount,
3361 IWineD3DImpl_RegisterSoftwareDevice,
3362 IWineD3DImpl_GetAdapterMonitor,
3363 IWineD3DImpl_GetAdapterModeCount,
3364 IWineD3DImpl_EnumAdapterModes,
3365 IWineD3DImpl_GetAdapterDisplayMode,
3366 IWineD3DImpl_GetAdapterIdentifier,
3367 IWineD3DImpl_CheckDeviceMultiSampleType,
3368 IWineD3DImpl_CheckDepthStencilMatch,
3369 IWineD3DImpl_CheckDeviceType,
3370 IWineD3DImpl_CheckDeviceFormat,
3371 IWineD3DImpl_CheckDeviceFormatConversion,
3372 IWineD3DImpl_GetDeviceCaps,
3373 IWineD3DImpl_CreateDevice