msvcrt/tests: Remove a space before a '\n'.
[wine/gsoc-2012-control.git] / dlls / wined3d / directx.c
blob478c21643ed7297a9b7342101086a06d892da5b9
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
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 /* Compile time diagnostics: */
27 #ifndef DEBUG_SINGLE_MODE
28 /* Set to 1 to force only a single display mode to be exposed: */
29 #define DEBUG_SINGLE_MODE 0
30 #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 /* The d3d device ID */
40 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
42 /* Extension detection */
43 static const struct {
44 const char *extension_string;
45 GL_SupportedExt extension;
46 DWORD version;
47 } EXTENSION_MAP[] = {
48 /* APPLE */
49 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
50 {"GL_APPLE_fence", APPLE_FENCE, 0 },
51 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
52 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
53 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
55 /* ATI */
56 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
57 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
58 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
59 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
60 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
62 /* ARB */
63 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
64 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
65 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
66 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
67 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
68 {"GL_ARB_imaging", ARB_IMAGING, 0 },
69 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
70 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
71 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
72 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
73 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
74 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
75 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
76 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
77 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
78 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
79 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
80 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
81 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
82 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
83 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
84 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
85 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
86 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
87 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
88 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
89 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
90 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
92 /* EXT */
93 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
94 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
95 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
96 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
97 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
98 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
99 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
100 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
101 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
102 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
103 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
104 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
105 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
106 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
107 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
108 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
109 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
110 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
111 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
112 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
113 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
114 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
115 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
116 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
117 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
118 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
119 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
121 /* NV */
122 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
123 {"GL_NV_fence", NV_FENCE, 0 },
124 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
125 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
126 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
127 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
128 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
129 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
130 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
131 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
132 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
133 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
134 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
135 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
136 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
137 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
138 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
139 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
140 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
142 /* SGI */
143 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
146 /**********************************************************
147 * Utility functions follow
148 **********************************************************/
150 /* Adapters */
151 static int numAdapters = 0;
152 static struct WineD3DAdapter Adapters[1];
154 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
155 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
156 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType);
157 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
159 /* lookup tables */
160 const int minLookup[MAX_LOOKUPS] =
162 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
165 const int maxLookup[MAX_LOOKUPS] =
167 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
170 DWORD *stateLookup[MAX_LOOKUPS];
172 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
173 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
178 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
181 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
182 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
184 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
187 /* drawStridedSlow attributes */
188 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
189 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
190 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
191 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
192 glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
195 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
196 * i.e., there is no GL Context - Get a default rendering context to enable the
197 * function query some info from GL.
200 static int wined3d_fake_gl_context_ref = 0;
201 static BOOL wined3d_fake_gl_context_foreign;
202 static BOOL wined3d_fake_gl_context_available = FALSE;
203 static HDC wined3d_fake_gl_context_hdc = NULL;
204 static HWND wined3d_fake_gl_context_hwnd = NULL;
206 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
207 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
209 0, 0, &wined3d_fake_gl_context_cs,
210 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
211 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
212 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
214 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
216 static void WineD3D_ReleaseFakeGLContext(void) {
217 HGLRC glCtx;
219 EnterCriticalSection(&wined3d_fake_gl_context_cs);
221 if(!wined3d_fake_gl_context_available) {
222 TRACE_(d3d_caps)("context not available\n");
223 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
224 return;
227 glCtx = pwglGetCurrentContext();
229 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
230 if (0 == (--wined3d_fake_gl_context_ref) ) {
231 if(!wined3d_fake_gl_context_foreign && glCtx) {
232 TRACE_(d3d_caps)("destroying fake GL context\n");
233 pwglMakeCurrent(NULL, NULL);
234 pwglDeleteContext(glCtx);
236 if(wined3d_fake_gl_context_hdc)
237 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
238 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
239 if(wined3d_fake_gl_context_hwnd)
240 DestroyWindow(wined3d_fake_gl_context_hwnd);
241 wined3d_fake_gl_context_hwnd = NULL;
242 wined3d_fake_gl_context_available = FALSE;
244 assert(wined3d_fake_gl_context_ref >= 0);
246 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
249 static BOOL WineD3D_CreateFakeGLContext(void) {
250 HGLRC glCtx = NULL;
252 EnterCriticalSection(&wined3d_fake_gl_context_cs);
254 TRACE("getting context...\n");
255 if(wined3d_fake_gl_context_ref > 0) goto ret;
256 assert(0 == wined3d_fake_gl_context_ref);
258 wined3d_fake_gl_context_foreign = TRUE;
260 glCtx = pwglGetCurrentContext();
261 if (!glCtx) {
262 PIXELFORMATDESCRIPTOR pfd;
263 int iPixelFormat;
265 wined3d_fake_gl_context_foreign = FALSE;
267 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
268 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
269 if(!wined3d_fake_gl_context_hwnd) {
270 ERR("HWND creation failed!\n");
271 goto fail;
273 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
274 if(!wined3d_fake_gl_context_hdc) {
275 ERR("GetDC failed!\n");
276 goto fail;
279 /* PixelFormat selection */
280 ZeroMemory(&pfd, sizeof(pfd));
281 pfd.nSize = sizeof(pfd);
282 pfd.nVersion = 1;
283 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
284 pfd.iPixelType = PFD_TYPE_RGBA;
285 pfd.cColorBits = 32;
286 pfd.iLayerType = PFD_MAIN_PLANE;
288 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
289 if(!iPixelFormat) {
290 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
291 ERR("Can't find a suitable iPixelFormat\n");
292 goto fail;
294 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
295 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
297 /* Create a GL context */
298 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
299 if (!glCtx) {
300 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
301 goto fail;
304 /* Make it the current GL context */
305 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
306 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
307 goto fail;
311 ret:
312 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
313 wined3d_fake_gl_context_ref++;
314 wined3d_fake_gl_context_available = TRUE;
315 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
316 return TRUE;
317 fail:
318 if(wined3d_fake_gl_context_hdc)
319 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
320 wined3d_fake_gl_context_hdc = NULL;
321 if(wined3d_fake_gl_context_hwnd)
322 DestroyWindow(wined3d_fake_gl_context_hwnd);
323 wined3d_fake_gl_context_hwnd = NULL;
324 if(glCtx) pwglDeleteContext(glCtx);
325 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
326 return FALSE;
329 /* Adjust the amount of used texture memory */
330 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
331 UINT Adapter = D3DDevice->adapterNo;
333 Adapters[Adapter].UsedTextureRam += glram;
334 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
335 return Adapters[Adapter].UsedTextureRam;
338 /**********************************************************
339 * IUnknown parts follows
340 **********************************************************/
342 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
346 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
347 if (IsEqualGUID(riid, &IID_IUnknown)
348 || IsEqualGUID(riid, &IID_IWineD3DBase)
349 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
350 IUnknown_AddRef(iface);
351 *ppobj = This;
352 return S_OK;
354 *ppobj = NULL;
355 return E_NOINTERFACE;
358 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
359 IWineD3DImpl *This = (IWineD3DImpl *)iface;
360 ULONG refCount = InterlockedIncrement(&This->ref);
362 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
363 return refCount;
366 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
367 IWineD3DImpl *This = (IWineD3DImpl *)iface;
368 ULONG ref;
369 TRACE("(%p) : Releasing from %d\n", This, This->ref);
370 ref = InterlockedDecrement(&This->ref);
371 if (ref == 0) {
372 HeapFree(GetProcessHeap(), 0, This);
375 return ref;
378 /* Set the shader type for this device, depending on the given capabilities,
379 * the device type, and the user preferences in wined3d_settings */
381 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
383 if (wined3d_settings.vs_mode == VS_NONE) {
384 *vs_selected = SHADER_NONE;
385 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
386 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
387 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
388 * shaders only on this card. */
389 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
390 *vs_selected = SHADER_ARB;
391 else
392 *vs_selected = SHADER_GLSL;
393 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
394 *vs_selected = SHADER_ARB;
395 } else {
396 *vs_selected = SHADER_NONE;
399 if (wined3d_settings.ps_mode == PS_NONE) {
400 *ps_selected = SHADER_NONE;
401 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
402 *ps_selected = SHADER_GLSL;
403 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
404 *ps_selected = SHADER_ARB;
405 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
406 *ps_selected = SHADER_ATI;
407 } else {
408 *ps_selected = SHADER_NONE;
412 /** Select the number of report maximum shader constants based on the selected shader modes */
413 static void select_shader_max_constants(
414 int ps_selected_mode,
415 int vs_selected_mode,
416 WineD3D_GL_Info *gl_info) {
418 switch (vs_selected_mode) {
419 case SHADER_GLSL:
420 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
421 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
422 break;
423 case SHADER_ARB:
424 /* We have to subtract any other PARAMs that we might use in our shader programs.
425 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
426 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
427 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
428 break;
429 default:
430 gl_info->max_vshader_constantsF = 0;
431 break;
434 switch (ps_selected_mode) {
435 case SHADER_GLSL:
436 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
437 * In theory the texbem instruction may need one more shader constant too. But lets assume
438 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
439 * and lets not take away a uniform needlessly from all other shaders.
441 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
442 break;
443 case SHADER_ARB:
444 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
445 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
447 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
448 break;
449 default:
450 gl_info->max_pshader_constantsF = 0;
451 break;
455 /**********************************************************
456 * IWineD3D parts follows
457 **********************************************************/
459 #define GLINFO_LOCATION (*gl_info)
460 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
462 GLuint prog;
463 BOOL ret = FALSE;
464 const char *testcode =
465 "!!ARBvp1.0\n"
466 "PARAM C[66] = { program.env[0..65] };\n"
467 "ADDRESS A0;"
468 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
469 "ARL A0.x, zero.x;\n"
470 "MOV result.position, C[A0.x + 65];\n"
471 "END\n";
473 while(glGetError());
474 GL_EXTCALL(glGenProgramsARB(1, &prog));
475 if(!prog) {
476 ERR("Failed to create an ARB offset limit test program\n");
478 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
479 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
480 strlen(testcode), testcode));
481 if(glGetError() != 0) {
482 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
483 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
484 ret = TRUE;
485 } else TRACE("OpenGL implementation allows offsets > 63\n");
487 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
488 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
489 checkGLcall("ARB vp offset limit test cleanup\n");
491 return ret;
494 static DWORD ver_for_ext(GL_SupportedExt ext)
496 unsigned int i;
497 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
498 if(EXTENSION_MAP[i].extension == ext) {
499 return EXTENSION_MAP[i].version;
502 return 0;
505 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
506 const char *GL_Extensions = NULL;
507 const char *WGL_Extensions = NULL;
508 const char *gl_string = NULL;
509 const char *gl_string_cursor = NULL;
510 GLint gl_max;
511 GLfloat gl_floatv[2];
512 int major = 1, minor = 0;
513 BOOL return_value = TRUE;
514 unsigned i;
515 HDC hdc;
516 unsigned int vidmem=0;
518 TRACE_(d3d_caps)("(%p)\n", gl_info);
520 ENTER_GL();
522 gl_string = (const char *) glGetString(GL_RENDERER);
523 if (!gl_string) gl_string = "None";
524 strcpy(gl_info->gl_renderer, gl_string);
526 gl_string = (const char *) glGetString(GL_VENDOR);
527 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
528 if (gl_string != NULL) {
529 /* Fill in the GL vendor */
530 if (strstr(gl_string, "NVIDIA")) {
531 gl_info->gl_vendor = VENDOR_NVIDIA;
532 } else if (strstr(gl_string, "ATI")) {
533 gl_info->gl_vendor = VENDOR_ATI;
534 } else if (strstr(gl_string, "Intel(R)") ||
535 strstr(gl_info->gl_renderer, "Intel(R)") ||
536 strstr(gl_string, "Intel Inc.")) {
537 gl_info->gl_vendor = VENDOR_INTEL;
538 } else if (strstr(gl_string, "Mesa")) {
539 gl_info->gl_vendor = VENDOR_MESA;
540 } else {
541 gl_info->gl_vendor = VENDOR_WINE;
543 } else {
544 gl_info->gl_vendor = VENDOR_WINE;
548 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
550 /* Parse the GL_VERSION field into major and minor information */
551 gl_string = (const char *) glGetString(GL_VERSION);
552 if (gl_string != NULL) {
554 /* First, parse the generic opengl version. This is supposed not to be convoluted with
555 * driver specific information
557 gl_string_cursor = gl_string;
558 major = atoi(gl_string_cursor);
559 if(major <= 0) {
560 ERR("Invalid opengl major version: %d\n", major);
562 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
563 ++gl_string_cursor;
565 if (*gl_string_cursor++ != '.') {
566 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
568 minor = atoi(gl_string_cursor);
569 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
570 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
572 /* Now parse the driver specific string which we'll report to the app */
573 switch (gl_info->gl_vendor) {
574 case VENDOR_NVIDIA:
575 gl_string_cursor = strstr(gl_string, "NVIDIA");
576 if (!gl_string_cursor) {
577 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
578 break;
581 gl_string_cursor = strstr(gl_string_cursor, " ");
582 if (!gl_string_cursor) {
583 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
584 break;
587 while (*gl_string_cursor == ' ') {
588 ++gl_string_cursor;
591 if (!*gl_string_cursor) {
592 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
593 break;
596 major = atoi(gl_string_cursor);
597 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
598 ++gl_string_cursor;
601 if (*gl_string_cursor++ != '.') {
602 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
603 break;
606 minor = atoi(gl_string_cursor);
607 minor = major*100+minor;
608 major = 10;
610 break;
612 case VENDOR_ATI:
613 major = minor = 0;
614 gl_string_cursor = strchr(gl_string, '-');
615 if (gl_string_cursor) {
616 int error = 0;
617 gl_string_cursor++;
619 /* Check if version number is of the form x.y.z */
620 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
621 error = 1;
622 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
623 error = 1;
624 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
625 error = 1;
626 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
627 error = 1;
629 /* Mark version number as malformed */
630 if (error)
631 gl_string_cursor = 0;
634 if (!gl_string_cursor)
635 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
636 else {
637 major = *gl_string_cursor - '0';
638 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
640 break;
642 case VENDOR_INTEL:
643 /* Apple and Mesa version strings look differently, but both provide intel drivers */
644 if(strstr(gl_string, "APPLE")) {
645 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
646 * We only need the first part, and use the APPLE as identification
647 * "1.2 APPLE-1.4.56"
649 gl_string_cursor = gl_string;
650 major = atoi(gl_string_cursor);
651 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
652 ++gl_string_cursor;
655 if (*gl_string_cursor++ != '.') {
656 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
657 break;
660 minor = atoi(gl_string_cursor);
661 break;
664 case VENDOR_MESA:
665 gl_string_cursor = strstr(gl_string, "Mesa");
666 gl_string_cursor = strstr(gl_string_cursor, " ");
667 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
668 if (*gl_string_cursor) {
669 char tmp[16];
670 int cursor = 0;
672 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
673 tmp[cursor++] = *gl_string_cursor;
674 ++gl_string_cursor;
676 tmp[cursor] = 0;
677 major = atoi(tmp);
679 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
680 ++gl_string_cursor;
682 cursor = 0;
683 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
684 tmp[cursor++] = *gl_string_cursor;
685 ++gl_string_cursor;
687 tmp[cursor] = 0;
688 minor = atoi(tmp);
690 break;
692 default:
693 major = 0;
694 minor = 9;
696 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
697 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
698 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
699 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
700 } else {
701 FIXME("OpenGL driver did not return version information\n");
702 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
703 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
706 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
709 * Initialize openGL extension related variables
710 * with Default values
712 memset(gl_info->supported, 0, sizeof(gl_info->supported));
713 gl_info->max_buffers = 1;
714 gl_info->max_textures = 1;
715 gl_info->max_texture_stages = 1;
716 gl_info->max_fragment_samplers = 1;
717 gl_info->max_vertex_samplers = 0;
718 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
719 gl_info->max_sampler_stages = 1;
720 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
721 gl_info->ps_arb_max_temps = 0;
722 gl_info->ps_arb_max_instructions = 0;
723 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
724 gl_info->vs_arb_max_temps = 0;
725 gl_info->vs_arb_max_instructions = 0;
726 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
727 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
728 gl_info->vs_glsl_constantsF = 0;
729 gl_info->ps_glsl_constantsF = 0;
730 gl_info->vs_arb_constantsF = 0;
731 gl_info->ps_arb_constantsF = 0;
733 /* Retrieve opengl defaults */
734 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
735 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
736 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
738 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
739 gl_info->max_lights = gl_max;
740 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
742 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
743 gl_info->max_texture_size = gl_max;
744 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
746 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
747 gl_info->max_pointsizemin = gl_floatv[0];
748 gl_info->max_pointsize = gl_floatv[1];
749 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
751 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
752 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
753 TRACE_(d3d_caps)("GL_Extensions reported:\n");
755 if (NULL == GL_Extensions) {
756 ERR(" GL_Extensions returns NULL\n");
757 } else {
758 while (*GL_Extensions != 0x00) {
759 const char *Start;
760 char ThisExtn[256];
761 size_t len;
763 while (isspace(*GL_Extensions)) GL_Extensions++;
764 Start = GL_Extensions;
765 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
766 GL_Extensions++;
769 len = GL_Extensions - Start;
770 if (len == 0 || len >= sizeof(ThisExtn))
771 continue;
773 memcpy(ThisExtn, Start, len);
774 ThisExtn[len] = '\0';
775 TRACE_(d3d_caps)("- %s\n", ThisExtn);
777 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
778 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
779 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
780 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
781 break;
786 LEAVE_GL();
788 /* Now work out what GL support this card really has */
789 #define USE_GL_FUNC(type, pfn, ext, replace) { \
790 DWORD ver = ver_for_ext(ext); \
791 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
792 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
793 else gl_info->pfn = NULL; \
795 GL_EXT_FUNCS_GEN;
796 #undef USE_GL_FUNC
798 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
799 WGL_EXT_FUNCS_GEN;
800 #undef USE_GL_FUNC
802 ENTER_GL();
803 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
804 * loading the functions, otherwise the code above will load the extension entry points instead of the
805 * core functions, which may not work
807 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
808 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
809 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
810 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
811 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
815 if (gl_info->supported[APPLE_FENCE]) {
816 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
817 * The apple extension interacts with some other apple exts. Disable the NV
818 * extension if the apple one is support to prevent confusion in other parts
819 * of the code
821 gl_info->supported[NV_FENCE] = FALSE;
823 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
824 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
826 * The enums are the same:
827 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
828 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
829 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
830 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
831 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
833 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
834 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
835 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
837 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
838 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
839 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
842 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
843 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
844 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
846 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
847 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
848 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
849 * are supported. The nv extensions provide the same functionality as the
850 * ATI one, and a bit more(signed pixelformats)
852 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
855 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
856 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
857 gl_info->max_buffers = gl_max;
858 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
860 if (gl_info->supported[ARB_MULTITEXTURE]) {
861 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
862 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
863 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
865 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
866 GLint tmp;
867 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
868 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
869 } else {
870 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
872 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
874 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
875 GLint tmp;
876 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
877 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
878 } else {
879 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
881 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
883 if (gl_info->supported[ARB_VERTEX_SHADER]) {
884 GLint tmp;
885 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
886 gl_info->max_vertex_samplers = tmp;
887 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
888 gl_info->max_combined_samplers = tmp;
890 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
891 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
892 * an issue because then the sampler setup only depends on the two shaders. If a pixel
893 * shader is used with fixed function vertex processing we're fine too because fixed function
894 * vertex processing doesn't use any samplers. If fixed function fragment processing is
895 * used we have to make sure that all vertex sampler setups are valid together with all
896 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
897 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
898 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
899 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
900 * a fixed function pipeline anymore.
902 * So this is just a check to check that our assumption holds true. If not, write a warning
903 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
905 if(gl_info->max_vertex_samplers &&
906 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
907 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
908 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
909 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
910 if( gl_info->max_combined_samplers > MAX_TEXTURES )
911 gl_info->max_vertex_samplers =
912 gl_info->max_combined_samplers - MAX_TEXTURES;
913 else
914 gl_info->max_vertex_samplers = 0;
916 } else {
917 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
919 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
920 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
922 if (gl_info->supported[ARB_VERTEX_BLEND]) {
923 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
924 gl_info->max_blends = gl_max;
925 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
927 if (gl_info->supported[EXT_TEXTURE3D]) {
928 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
929 gl_info->max_texture3d_size = gl_max;
930 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
932 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
933 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
934 gl_info->max_anisotropy = gl_max;
935 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
937 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
938 gl_info->ps_arb_version = PS_VERSION_11;
939 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
940 gl_info->ps_arb_constantsF = gl_max;
941 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
942 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
943 gl_info->ps_arb_max_temps = gl_max;
944 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
945 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
946 gl_info->ps_arb_max_instructions = gl_max;
947 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
949 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
950 gl_info->vs_arb_version = VS_VERSION_11;
951 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
952 gl_info->vs_arb_constantsF = gl_max;
953 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
954 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
955 gl_info->vs_arb_max_temps = gl_max;
956 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
957 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
958 gl_info->vs_arb_max_instructions = gl_max;
959 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
961 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
963 if (gl_info->supported[ARB_VERTEX_SHADER]) {
964 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
965 gl_info->vs_glsl_constantsF = gl_max / 4;
966 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
968 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
969 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
970 gl_info->ps_glsl_constantsF = gl_max / 4;
971 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
972 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
973 gl_info->max_glsl_varyings = gl_max;
974 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
976 if (gl_info->supported[EXT_VERTEX_SHADER]) {
977 gl_info->vs_ati_version = VS_VERSION_11;
979 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
980 gl_info->vs_nv_version = VS_VERSION_30;
981 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
982 gl_info->vs_nv_version = VS_VERSION_20;
983 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
984 gl_info->vs_nv_version = VS_VERSION_11;
985 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
986 gl_info->vs_nv_version = VS_VERSION_10;
988 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
989 gl_info->ps_nv_version = PS_VERSION_30;
990 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
991 gl_info->ps_nv_version = PS_VERSION_20;
993 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
994 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
995 } else {
996 gl_info->max_shininess = 128.0;
998 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
999 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
1000 * This saves a few redundant glDisable calls
1002 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1004 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1005 /* Disable NV_register_combiners and fragment shader if this is supported.
1006 * generally the NV extensions are preferred over the ATI ones, and this
1007 * extension is disabled if register_combiners and texture_shader2 are both
1008 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1009 * fragment processing support
1011 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1012 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1013 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1014 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1015 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1019 checkGLcall("extension detection\n");
1021 /* In some cases the number of texture stages can be larger than the number
1022 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1023 * shaders), but 8 texture stages (register combiners). */
1024 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1026 /* We can only use ORM_FBO when the hardware supports it. */
1027 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1028 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
1029 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
1032 /* MRTs are currently only supported when FBOs are used. */
1033 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1034 gl_info->max_buffers = 1;
1037 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1038 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1039 * in case of the latest videocards in the number of pixel/vertex pipelines.
1041 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1042 * rendering. Various games use this information to get a rough estimation of the features of the card
1043 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1044 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1045 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1046 * not the PCI id.
1048 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1049 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1050 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1051 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1052 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1053 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1054 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1055 * is limited.
1057 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1058 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1059 * similar 3d features.
1061 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1062 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1063 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1064 * won't pass we return a default card. This way is better than maintaining a full card database as even
1065 * without a full database we can return a card with similar features. Second the size of the database
1066 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1067 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1068 * to distinguishes between different models from that family.
1070 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1071 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1072 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1073 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1074 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1075 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1076 * memory behind our backs if really needed.
1077 * Note that the amount of video memory can be overruled using a registry setting.
1079 switch (gl_info->gl_vendor) {
1080 case VENDOR_NVIDIA:
1081 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1082 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1084 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1085 /* Geforce GTX - highend */
1086 if(strstr(gl_info->gl_renderer, "GTX 280")) {
1087 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1088 vidmem = 1024;
1090 /* Geforce9 - highend */
1091 else if(strstr(gl_info->gl_renderer, "9800")) {
1092 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1093 vidmem = 512;
1095 /* Geforce9 - midend */
1096 else if(strstr(gl_info->gl_renderer, "9600")) {
1097 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1098 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1100 /* Geforce8 - highend */
1101 else if (strstr(gl_info->gl_renderer, "8800")) {
1102 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1103 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1105 /* Geforce8 - midend mobile */
1106 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1107 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1108 vidmem = 512;
1110 /* Geforce8 - midend */
1111 else if(strstr(gl_info->gl_renderer, "8600") ||
1112 strstr(gl_info->gl_renderer, "8700"))
1114 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1115 vidmem = 256;
1117 /* Geforce8 - lowend */
1118 else if(strstr(gl_info->gl_renderer, "8300") ||
1119 strstr(gl_info->gl_renderer, "8400") ||
1120 strstr(gl_info->gl_renderer, "8500"))
1122 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1123 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1125 /* Geforce7 - highend */
1126 else if(strstr(gl_info->gl_renderer, "7800") ||
1127 strstr(gl_info->gl_renderer, "7900") ||
1128 strstr(gl_info->gl_renderer, "7950") ||
1129 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1130 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1132 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1133 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1135 /* Geforce7 midend */
1136 else if(strstr(gl_info->gl_renderer, "7600") ||
1137 strstr(gl_info->gl_renderer, "7700")) {
1138 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1139 vidmem = 256; /* The 7600 uses 256-512MB */
1140 /* Geforce7 lower medium */
1141 } else if(strstr(gl_info->gl_renderer, "7400")) {
1142 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1143 vidmem = 256; /* The 7400 uses 256-512MB */
1145 /* Geforce7 lowend */
1146 else if(strstr(gl_info->gl_renderer, "7300")) {
1147 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1148 vidmem = 256; /* Mac Pros with this card have 256 MB */
1150 /* Geforce6 highend */
1151 else if(strstr(gl_info->gl_renderer, "6800"))
1153 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1154 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1156 /* Geforce6 - midend */
1157 else if(strstr(gl_info->gl_renderer, "6600") ||
1158 strstr(gl_info->gl_renderer, "6610") ||
1159 strstr(gl_info->gl_renderer, "6700"))
1161 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1162 vidmem = 128; /* A 6600GT has 128-256MB */
1164 /* Geforce6/7 lowend */
1165 else {
1166 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1167 vidmem = 64; /* */
1169 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1170 /* GeforceFX - highend */
1171 if (strstr(gl_info->gl_renderer, "5800") ||
1172 strstr(gl_info->gl_renderer, "5900") ||
1173 strstr(gl_info->gl_renderer, "5950") ||
1174 strstr(gl_info->gl_renderer, "Quadro FX"))
1176 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1177 vidmem = 256; /* 5800-5900 cards use 256MB */
1179 /* GeforceFX - midend */
1180 else if(strstr(gl_info->gl_renderer, "5600") ||
1181 strstr(gl_info->gl_renderer, "5650") ||
1182 strstr(gl_info->gl_renderer, "5700") ||
1183 strstr(gl_info->gl_renderer, "5750"))
1185 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1186 vidmem = 128; /* A 5600 uses 128-256MB */
1188 /* GeforceFX - lowend */
1189 else {
1190 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1191 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1193 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1194 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1195 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1196 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1198 else {
1199 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1200 vidmem = 64; /* Geforce3 cards have 64-128MB */
1202 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1203 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1204 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1205 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1207 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1208 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1209 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1211 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1212 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1213 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1215 else {
1216 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1217 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1219 } else {
1220 if (strstr(gl_info->gl_renderer, "TNT2")) {
1221 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1222 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1224 else {
1225 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1226 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1229 break;
1230 case VENDOR_ATI:
1231 if(WINE_D3D9_CAPABLE(gl_info)) {
1232 /* Radeon R6xx HD2900/HD3800 - highend */
1233 if (strstr(gl_info->gl_renderer, "HD 2900") ||
1234 strstr(gl_info->gl_renderer, "HD 3870") ||
1235 strstr(gl_info->gl_renderer, "HD 3850"))
1237 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1238 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1240 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1241 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1242 strstr(gl_info->gl_renderer, "HD 3830") ||
1243 strstr(gl_info->gl_renderer, "HD 3690") ||
1244 strstr(gl_info->gl_renderer, "HD 3650"))
1246 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1247 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1249 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1250 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1251 strstr(gl_info->gl_renderer, "HD 2400") ||
1252 strstr(gl_info->gl_renderer, "HD 3470") ||
1253 strstr(gl_info->gl_renderer, "HD 3450") ||
1254 strstr(gl_info->gl_renderer, "HD 3430"))
1256 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1257 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1259 /* Radeon R6xx/R7xx integrated */
1260 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1261 strstr(gl_info->gl_renderer, "HD 3200") ||
1262 strstr(gl_info->gl_renderer, "HD 3300"))
1264 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1265 vidmem = 128; /* 128MB */
1267 /* Radeon R5xx */
1268 else if (strstr(gl_info->gl_renderer, "X1600") ||
1269 strstr(gl_info->gl_renderer, "X1650") ||
1270 strstr(gl_info->gl_renderer, "X1800") ||
1271 strstr(gl_info->gl_renderer, "X1900") ||
1272 strstr(gl_info->gl_renderer, "X1950"))
1274 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1275 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1277 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1278 else if(strstr(gl_info->gl_renderer, "X700") ||
1279 strstr(gl_info->gl_renderer, "X800") ||
1280 strstr(gl_info->gl_renderer, "X850") ||
1281 strstr(gl_info->gl_renderer, "X1300") ||
1282 strstr(gl_info->gl_renderer, "X1400") ||
1283 strstr(gl_info->gl_renderer, "X1450") ||
1284 strstr(gl_info->gl_renderer, "X1550"))
1286 gl_info->gl_card = CARD_ATI_RADEON_X700;
1287 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1289 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1290 else if(strstr(gl_info->gl_renderer, "Radeon Xpress"))
1292 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1293 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1295 /* Radeon R3xx */
1296 else {
1297 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1298 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1300 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1301 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1302 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1303 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1304 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1305 vidmem = 32; /* There are models with up to 64MB */
1306 } else {
1307 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1308 vidmem = 16; /* There are 16-32MB models */
1310 break;
1311 case VENDOR_INTEL:
1312 if (strstr(gl_info->gl_renderer, "GMA 950") ||
1313 strstr(gl_info->gl_renderer, "945GM")) {
1314 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1315 gl_info->gl_card = CARD_INTEL_I945GM;
1316 vidmem = 64;
1317 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1318 gl_info->gl_card = CARD_INTEL_I915GM;
1319 } else if (strstr(gl_info->gl_renderer, "915G")) {
1320 gl_info->gl_card = CARD_INTEL_I915G;
1321 } else if (strstr(gl_info->gl_renderer, "865G")) {
1322 gl_info->gl_card = CARD_INTEL_I865G;
1323 } else if (strstr(gl_info->gl_renderer, "855G")) {
1324 gl_info->gl_card = CARD_INTEL_I855G;
1325 } else if (strstr(gl_info->gl_renderer, "830G")) {
1326 gl_info->gl_card = CARD_INTEL_I830G;
1327 } else {
1328 gl_info->gl_card = CARD_INTEL_I915G;
1330 break;
1331 case VENDOR_MESA:
1332 case VENDOR_WINE:
1333 default:
1334 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1335 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1336 * them a good generic choice.
1338 gl_info->gl_vendor = VENDOR_NVIDIA;
1339 if(WINE_D3D9_CAPABLE(gl_info))
1340 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1341 else if(WINE_D3D8_CAPABLE(gl_info))
1342 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1343 else if(WINE_D3D7_CAPABLE(gl_info))
1344 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1345 else if(WINE_D3D6_CAPABLE(gl_info))
1346 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1347 else
1348 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1350 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1352 /* If we have an estimate use it, else default to 64MB; */
1353 if(vidmem)
1354 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1355 else
1356 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1358 /* Load all the lookup tables */
1359 for (i = 0; i < MAX_LOOKUPS; i++) {
1360 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1363 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1364 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1365 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1366 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1367 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1368 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1369 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1370 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1371 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1372 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1374 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1375 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1376 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1377 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1378 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1381 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1382 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1383 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1384 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1385 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1386 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1387 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1388 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1389 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1390 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1391 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1392 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1393 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1394 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1395 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1397 /* TODO: config lookups */
1399 /* Make sure there's an active HDC else the WGL extensions will fail */
1400 hdc = pwglGetCurrentDC();
1401 if (hdc) {
1402 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1403 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1405 if (NULL == WGL_Extensions) {
1406 ERR(" WGL_Extensions returns NULL\n");
1407 } else {
1408 while (*WGL_Extensions != 0x00) {
1409 const char *Start;
1410 char ThisExtn[256];
1411 size_t len;
1413 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1414 Start = WGL_Extensions;
1415 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1416 WGL_Extensions++;
1419 len = WGL_Extensions - Start;
1420 if (len == 0 || len >= sizeof(ThisExtn))
1421 continue;
1423 memcpy(ThisExtn, Start, len);
1424 ThisExtn[len] = '\0';
1425 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1427 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1428 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1429 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1431 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1432 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1433 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1438 LEAVE_GL();
1440 return return_value;
1442 #undef GLINFO_LOCATION
1444 /**********************************************************
1445 * IWineD3D implementation follows
1446 **********************************************************/
1448 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1449 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1451 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1452 return numAdapters;
1455 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1456 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1457 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1458 return WINED3D_OK;
1461 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1462 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1464 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1466 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1467 return NULL;
1470 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1473 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1474 of the same bpp but different resolutions */
1476 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1477 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1478 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1479 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1481 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1482 return 0;
1485 /* TODO: Store modes per adapter and read it from the adapter structure */
1486 if (Adapter == 0) { /* Display */
1487 int i = 0;
1488 int j = 0;
1490 if (!DEBUG_SINGLE_MODE) {
1491 DEVMODEW DevModeW;
1493 ZeroMemory(&DevModeW, sizeof(DevModeW));
1494 DevModeW.dmSize = sizeof(DevModeW);
1495 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1496 j++;
1497 switch (Format)
1499 case WINED3DFMT_UNKNOWN:
1500 /* This is for D3D8, do not enumerate P8 here */
1501 if (DevModeW.dmBitsPerPel == 32 ||
1502 DevModeW.dmBitsPerPel == 16) i++;
1503 break;
1504 case WINED3DFMT_X8R8G8B8:
1505 if (DevModeW.dmBitsPerPel == 32) i++;
1506 break;
1507 case WINED3DFMT_R5G6B5:
1508 if (DevModeW.dmBitsPerPel == 16) i++;
1509 break;
1510 case WINED3DFMT_P8:
1511 if (DevModeW.dmBitsPerPel == 8) i++;
1512 break;
1513 default:
1514 /* Skip other modes as they do not match the requested format */
1515 break;
1518 } else {
1519 i = 1;
1520 j = 1;
1523 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1524 return i;
1525 } else {
1526 FIXME_(d3d_caps)("Adapter not primary display\n");
1528 return 0;
1531 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1532 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1533 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1534 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1536 /* Validate the parameters as much as possible */
1537 if (NULL == pMode ||
1538 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1539 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1540 return WINED3DERR_INVALIDCALL;
1543 /* TODO: Store modes per adapter and read it from the adapter structure */
1544 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1545 DEVMODEW DevModeW;
1546 int ModeIdx = 0;
1547 UINT i = 0;
1548 int j = 0;
1550 ZeroMemory(&DevModeW, sizeof(DevModeW));
1551 DevModeW.dmSize = sizeof(DevModeW);
1553 /* If we are filtering to a specific format (D3D9), then need to skip
1554 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1555 just count through the ones with valid bit depths */
1556 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1557 switch (Format)
1559 case WINED3DFMT_UNKNOWN:
1560 /* This is D3D8. Do not enumerate P8 here */
1561 if (DevModeW.dmBitsPerPel == 32 ||
1562 DevModeW.dmBitsPerPel == 16) i++;
1563 break;
1564 case WINED3DFMT_X8R8G8B8:
1565 if (DevModeW.dmBitsPerPel == 32) i++;
1566 break;
1567 case WINED3DFMT_R5G6B5:
1568 if (DevModeW.dmBitsPerPel == 16) i++;
1569 break;
1570 case WINED3DFMT_P8:
1571 if (DevModeW.dmBitsPerPel == 8) i++;
1572 break;
1573 default:
1574 /* Modes that don't match what we support can get an early-out */
1575 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1576 return WINED3DERR_INVALIDCALL;
1580 if (i == 0) {
1581 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1582 return WINED3DERR_INVALIDCALL;
1584 ModeIdx = j - 1;
1586 /* Now get the display mode via the calculated index */
1587 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1588 pMode->Width = DevModeW.dmPelsWidth;
1589 pMode->Height = DevModeW.dmPelsHeight;
1590 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1591 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1592 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1594 if (Format == WINED3DFMT_UNKNOWN) {
1595 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1596 } else {
1597 pMode->Format = Format;
1599 } else {
1600 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1601 return WINED3DERR_INVALIDCALL;
1604 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1605 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1606 DevModeW.dmBitsPerPel);
1608 } else if (DEBUG_SINGLE_MODE) {
1609 /* Return one setting of the format requested */
1610 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1611 pMode->Width = 800;
1612 pMode->Height = 600;
1613 pMode->RefreshRate = 60;
1614 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1615 } else {
1616 FIXME_(d3d_caps)("Adapter not primary display\n");
1619 return WINED3D_OK;
1622 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1623 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1624 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1626 if (NULL == pMode ||
1627 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1628 return WINED3DERR_INVALIDCALL;
1631 if (Adapter == 0) { /* Display */
1632 int bpp = 0;
1633 DEVMODEW DevModeW;
1635 ZeroMemory(&DevModeW, sizeof(DevModeW));
1636 DevModeW.dmSize = sizeof(DevModeW);
1638 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1639 pMode->Width = DevModeW.dmPelsWidth;
1640 pMode->Height = DevModeW.dmPelsHeight;
1641 bpp = DevModeW.dmBitsPerPel;
1642 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1643 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1645 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1648 pMode->Format = pixelformat_for_depth(bpp);
1649 } else {
1650 FIXME_(d3d_caps)("Adapter not primary display\n");
1653 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1654 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1655 return WINED3D_OK;
1658 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1659 and fields being inserted in the middle, a new structure is used in place */
1660 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1661 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1662 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1664 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1666 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1667 return WINED3DERR_INVALIDCALL;
1670 /* Return the information requested */
1671 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1672 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1673 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1675 /* Note dx8 doesn't supply a DeviceName */
1676 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1677 pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart;
1678 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version;
1679 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1680 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1681 *(pIdentifier->SubSysId) = 0;
1682 *(pIdentifier->Revision) = 0;
1683 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1685 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1687 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1688 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1691 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1693 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1694 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1697 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1698 *(pIdentifier->WHQLLevel) = 0;
1699 } else {
1700 *(pIdentifier->WHQLLevel) = 1;
1703 return WINED3D_OK;
1706 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1707 short redSize, greenSize, blueSize, alphaSize, colorBits;
1709 if(!cfg)
1710 return FALSE;
1712 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1713 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1714 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1715 return FALSE;
1718 if(cfg->redSize < redSize)
1719 return FALSE;
1721 if(cfg->greenSize < greenSize)
1722 return FALSE;
1724 if(cfg->blueSize < blueSize)
1725 return FALSE;
1727 if(cfg->alphaSize < alphaSize)
1728 return FALSE;
1730 return TRUE;
1731 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1732 if(Format == WINED3DFMT_R16F)
1733 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1734 if(Format == WINED3DFMT_G16R16F)
1735 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1736 if(Format == WINED3DFMT_A16B16G16R16F)
1737 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1738 if(Format == WINED3DFMT_R32F)
1739 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1740 if(Format == WINED3DFMT_G32R32F)
1741 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1742 if(Format == WINED3DFMT_A32B32G32R32F)
1743 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1744 } else {
1745 /* Probably a color index mode */
1746 return FALSE;
1749 return FALSE;
1752 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1753 short depthSize, stencilSize;
1754 BOOL lockable = FALSE;
1756 if(!cfg)
1757 return FALSE;
1759 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1760 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1761 return FALSE;
1764 if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE))
1765 lockable = TRUE;
1767 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1768 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1769 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1770 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1771 return FALSE;
1773 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1774 * allow more stencil bits than requested. */
1775 if(cfg->stencilSize < stencilSize)
1776 return FALSE;
1778 return TRUE;
1781 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1782 WINED3DFORMAT AdapterFormat,
1783 WINED3DFORMAT RenderTargetFormat,
1784 WINED3DFORMAT DepthStencilFormat) {
1785 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1786 int nCfgs;
1787 const WineD3D_PixelFormat *cfgs;
1788 int it;
1790 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1791 This, Adapter,
1792 DeviceType, debug_d3ddevicetype(DeviceType),
1793 AdapterFormat, debug_d3dformat(AdapterFormat),
1794 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1795 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1797 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1798 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1799 return WINED3DERR_INVALIDCALL;
1802 cfgs = Adapters[Adapter].cfgs;
1803 nCfgs = Adapters[Adapter].nCfgs;
1804 for (it = 0; it < nCfgs; ++it) {
1805 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1806 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1807 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1808 return WINED3D_OK;
1812 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1814 return WINED3DERR_NOTAVAILABLE;
1817 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1818 WINED3DFORMAT SurfaceFormat,
1819 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1821 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1822 const struct GlPixelFormatDesc *glDesc;
1823 const StaticPixelFormatDesc *desc;
1825 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1826 This,
1827 Adapter,
1828 DeviceType, debug_d3ddevicetype(DeviceType),
1829 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1830 Windowed,
1831 MultiSampleType,
1832 pQualityLevels);
1834 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1835 return WINED3DERR_INVALIDCALL;
1838 /* TODO: handle Windowed, add more quality levels */
1840 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1842 /* By default multisampling is disabled right now as it causes issues
1843 * on some Nvidia driver versions and it doesn't work well in combination
1844 * with FBOs yet. */
1845 if(!wined3d_settings.allow_multisampling)
1846 return WINED3DERR_NOTAVAILABLE;
1848 desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc);
1849 if(!desc || !glDesc) {
1850 return WINED3DERR_INVALIDCALL;
1853 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1854 int i, nCfgs;
1855 const WineD3D_PixelFormat *cfgs;
1857 cfgs = Adapters[Adapter].cfgs;
1858 nCfgs = Adapters[Adapter].nCfgs;
1859 for(i=0; i<nCfgs; i++) {
1860 if(cfgs[i].numSamples != MultiSampleType)
1861 continue;
1863 if(!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[i], SurfaceFormat))
1864 continue;
1866 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1868 if(pQualityLevels)
1869 *pQualityLevels = 1; /* Guess at a value! */
1870 return WINED3D_OK;
1873 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1874 short redSize, greenSize, blueSize, alphaSize, colorBits;
1875 int i, nCfgs;
1876 const WineD3D_PixelFormat *cfgs;
1878 if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1879 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1880 return WINED3DERR_NOTAVAILABLE;
1883 cfgs = Adapters[Adapter].cfgs;
1884 nCfgs = Adapters[Adapter].nCfgs;
1885 for(i=0; i<nCfgs; i++) {
1886 if(cfgs[i].numSamples != MultiSampleType)
1887 continue;
1888 if(cfgs[i].redSize != redSize)
1889 continue;
1890 if(cfgs[i].greenSize != greenSize)
1891 continue;
1892 if(cfgs[i].blueSize != blueSize)
1893 continue;
1894 if(cfgs[i].alphaSize != alphaSize)
1895 continue;
1897 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1899 if(pQualityLevels)
1900 *pQualityLevels = 1; /* Guess at a value! */
1901 return WINED3D_OK;
1904 return WINED3DERR_NOTAVAILABLE;
1907 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1908 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1910 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1911 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1912 UINT nmodes;
1914 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1915 This,
1916 Adapter,
1917 DeviceType, debug_d3ddevicetype(DeviceType),
1918 DisplayFormat, debug_d3dformat(DisplayFormat),
1919 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1920 Windowed);
1922 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1923 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1924 return WINED3DERR_INVALIDCALL;
1927 /* The task of this function is to check whether a certain display / backbuffer format
1928 * combination is available on the given adapter. In fullscreen mode microsoft specified
1929 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
1930 * and display format should match exactly.
1931 * In windowed mode format conversion can occur and this depends on the driver. When format
1932 * conversion is done, this function should nevertheless fail and applications need to use
1933 * CheckDeviceFormatConversion.
1934 * At the moment we assume that fullscreen and windowed have the same capabilities */
1936 /* There are only 4 display formats */
1937 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
1938 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
1939 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
1940 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
1942 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
1943 return WINED3DERR_NOTAVAILABLE;
1946 /* If the requested DisplayFormat is not available, don't continue */
1947 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
1948 if(!nmodes) {
1949 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
1950 return WINED3DERR_NOTAVAILABLE;
1953 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
1954 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
1955 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
1956 return WINED3DERR_NOTAVAILABLE;
1959 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
1960 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
1961 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1962 return WINED3DERR_NOTAVAILABLE;
1965 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
1966 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
1967 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1968 return WINED3DERR_NOTAVAILABLE;
1971 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
1972 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
1973 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1974 return WINED3DERR_NOTAVAILABLE;
1977 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
1978 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
1979 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1980 return WINED3DERR_NOTAVAILABLE;
1983 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
1984 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
1985 if(FAILED(hr))
1986 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1988 return hr;
1992 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1993 /* Check if we support bumpmapping for a format */
1994 static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
1996 const struct fragment_pipeline *fp;
1997 const struct GlPixelFormatDesc *glDesc;
1999 switch(CheckFormat) {
2000 case WINED3DFMT_V8U8:
2001 case WINED3DFMT_V16U16:
2002 case WINED3DFMT_L6V5U5:
2003 case WINED3DFMT_X8L8V8U8:
2004 case WINED3DFMT_Q8W8V8U8:
2005 /* Ask the fixed function pipeline implementation if it can deal
2006 * with the conversion. If we've got a GL extension giving native
2007 * support this will be an identity conversion. */
2008 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2009 fp = select_fragment_implementation(Adapter, DeviceType);
2010 if (fp->color_fixup_supported(glDesc->color_fixup))
2012 TRACE_(d3d_caps)("[OK]\n");
2013 return TRUE;
2015 TRACE_(d3d_caps)("[FAILED]\n");
2016 return FALSE;
2018 default:
2019 TRACE_(d3d_caps)("[FAILED]\n");
2020 return FALSE;
2024 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2025 static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
2027 int it=0;
2028 const struct GlPixelFormatDesc *glDesc;
2029 const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc);
2031 /* Fail if we weren't able to get a description of the format */
2032 if(!desc || !glDesc)
2033 return FALSE;
2035 /* Only allow depth/stencil formats */
2036 if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2037 return FALSE;
2039 /* Walk through all WGL pixel formats to find a match */
2040 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2041 WineD3D_PixelFormat *cfg = &Adapters[Adapter].cfgs[it];
2042 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(cfg, DisplayFormat)) {
2043 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(cfg, DepthStencilFormat)) {
2044 return TRUE;
2049 return FALSE;
2052 static BOOL CheckFilterCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2054 const struct GlPixelFormatDesc *glDesc;
2055 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2057 /* Fail if we weren't able to get a description of the format */
2058 if(!desc || !glDesc)
2059 return FALSE;
2061 /* The flags entry of a format contains the filtering capability */
2062 if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING)
2063 return TRUE;
2065 return FALSE;
2068 /* Check the render target capabilities of a format */
2069 static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat)
2071 UINT Adapter = 0;
2072 const struct GlPixelFormatDesc *glDesc;
2073 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2075 /* Fail if we weren't able to get a description of the format */
2076 if(!desc || !glDesc)
2077 return FALSE;
2079 /* Filter out non-RT formats */
2080 if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET))
2081 return FALSE;
2083 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2084 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2085 int it;
2086 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2087 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2089 getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2090 getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2092 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2093 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2094 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2095 TRACE_(d3d_caps)("[FAILED]\n");
2096 return FALSE;
2099 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2100 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2101 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2102 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2103 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2104 return TRUE;
2107 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2108 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2109 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2110 int it;
2112 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2113 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2114 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2115 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2116 return TRUE;
2119 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2120 /* For now return TRUE for FBOs until we have some proper checks.
2121 * Note that this function will only be called when the format is around for texturing. */
2122 return TRUE;
2124 return FALSE;
2127 static BOOL CheckSrgbReadCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2129 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2130 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2131 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2132 return FALSE;
2135 switch (CheckFormat) {
2136 case WINED3DFMT_A8R8G8B8:
2137 case WINED3DFMT_X8R8G8B8:
2138 case WINED3DFMT_A4R4G4B4:
2139 case WINED3DFMT_L8:
2140 case WINED3DFMT_A8L8:
2141 case WINED3DFMT_DXT1:
2142 case WINED3DFMT_DXT2:
2143 case WINED3DFMT_DXT3:
2144 case WINED3DFMT_DXT4:
2145 case WINED3DFMT_DXT5:
2146 TRACE_(d3d_caps)("[OK]\n");
2147 return TRUE;
2149 default:
2150 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
2151 return FALSE;
2153 return FALSE;
2156 static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2158 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2159 * doing the color fixup in shaders.
2160 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2161 if((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) {
2162 int vs_selected_mode;
2163 int ps_selected_mode;
2164 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
2166 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2167 TRACE_(d3d_caps)("[OK]\n");
2168 return TRUE;
2172 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
2173 return FALSE;
2176 /* Check if a format support blending in combination with pixel shaders */
2177 static BOOL CheckPostPixelShaderBlendingCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2179 const struct GlPixelFormatDesc *glDesc;
2180 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2182 /* Fail if we weren't able to get a description of the format */
2183 if(!desc || !glDesc)
2184 return FALSE;
2186 /* The flags entry of a format contains the post pixel shader blending capability */
2187 if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2188 return TRUE;
2190 return FALSE;
2193 static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
2194 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2195 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2196 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2197 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2198 * capability anyway.
2200 * For now lets report this on all formats, but in the future we may want to
2201 * restrict it to some should games need that
2203 return TRUE;
2206 /* Check if a texture format is supported on the given adapter */
2207 static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2209 const shader_backend_t *shader_backend;
2210 const struct fragment_pipeline *fp;
2211 const struct GlPixelFormatDesc *glDesc;
2213 switch (CheckFormat) {
2215 /*****
2216 * supported: RGB(A) formats
2218 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2219 case WINED3DFMT_A8R8G8B8:
2220 case WINED3DFMT_X8R8G8B8:
2221 case WINED3DFMT_R5G6B5:
2222 case WINED3DFMT_X1R5G5B5:
2223 case WINED3DFMT_A1R5G5B5:
2224 case WINED3DFMT_A4R4G4B4:
2225 case WINED3DFMT_A8:
2226 case WINED3DFMT_X4R4G4B4:
2227 case WINED3DFMT_A8B8G8R8:
2228 case WINED3DFMT_X8B8G8R8:
2229 case WINED3DFMT_A2R10G10B10:
2230 case WINED3DFMT_A2B10G10R10:
2231 case WINED3DFMT_G16R16:
2232 TRACE_(d3d_caps)("[OK]\n");
2233 return TRUE;
2235 case WINED3DFMT_R3G3B2:
2236 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2237 return FALSE;
2239 /*****
2240 * supported: Palettized
2242 case WINED3DFMT_P8:
2243 TRACE_(d3d_caps)("[OK]\n");
2244 return TRUE;
2245 /* No Windows driver offers A8P8, so don't offer it either */
2246 case WINED3DFMT_A8P8:
2247 return FALSE;
2249 /*****
2250 * Supported: (Alpha)-Luminance
2252 case WINED3DFMT_L8:
2253 case WINED3DFMT_A8L8:
2254 case WINED3DFMT_L16:
2255 TRACE_(d3d_caps)("[OK]\n");
2256 return TRUE;
2258 /* Not supported on Windows, thus disabled */
2259 case WINED3DFMT_A4L4:
2260 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2261 return FALSE;
2263 /*****
2264 * Supported: Depth/Stencil formats
2266 case WINED3DFMT_D16_LOCKABLE:
2267 case WINED3DFMT_D16:
2268 case WINED3DFMT_D15S1:
2269 case WINED3DFMT_D24X8:
2270 case WINED3DFMT_D24X4S4:
2271 case WINED3DFMT_D24S8:
2272 case WINED3DFMT_D24FS8:
2273 case WINED3DFMT_D32:
2274 case WINED3DFMT_D32F_LOCKABLE:
2275 return TRUE;
2277 /*****
2278 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2279 * GL_NV_texture_shader). Emulated by shaders
2281 case WINED3DFMT_V8U8:
2282 case WINED3DFMT_X8L8V8U8:
2283 case WINED3DFMT_L6V5U5:
2284 case WINED3DFMT_Q8W8V8U8:
2285 case WINED3DFMT_V16U16:
2286 /* Ask the shader backend if it can deal with the conversion. If
2287 * we've got a GL extension giving native support this will be an
2288 * identity conversion. */
2289 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2290 shader_backend = select_shader_backend(Adapter, DeviceType);
2291 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup))
2293 TRACE_(d3d_caps)("[OK]\n");
2294 return TRUE;
2296 TRACE_(d3d_caps)("[FAILED]\n");
2297 return FALSE;
2299 case WINED3DFMT_DXT1:
2300 case WINED3DFMT_DXT2:
2301 case WINED3DFMT_DXT3:
2302 case WINED3DFMT_DXT4:
2303 case WINED3DFMT_DXT5:
2304 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2305 TRACE_(d3d_caps)("[OK]\n");
2306 return TRUE;
2308 TRACE_(d3d_caps)("[FAILED]\n");
2309 return FALSE;
2312 /*****
2313 * Odd formats - not supported
2315 case WINED3DFMT_VERTEXDATA:
2316 case WINED3DFMT_INDEX16:
2317 case WINED3DFMT_INDEX32:
2318 case WINED3DFMT_Q16W16V16U16:
2319 case WINED3DFMT_A2W10V10U10:
2320 case WINED3DFMT_W11V11U10:
2321 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2322 return FALSE;
2324 /*****
2325 * WINED3DFMT_CxV8U8: Not supported right now
2327 case WINED3DFMT_CxV8U8:
2328 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2329 return FALSE;
2331 /* YUV formats */
2332 case WINED3DFMT_UYVY:
2333 case WINED3DFMT_YUY2:
2334 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2335 TRACE_(d3d_caps)("[OK]\n");
2336 return TRUE;
2338 TRACE_(d3d_caps)("[FAILED]\n");
2339 return FALSE;
2340 case WINED3DFMT_YV12:
2341 TRACE_(d3d_caps)("[FAILED]\n");
2342 return FALSE;
2344 /* Not supported */
2345 case WINED3DFMT_A16B16G16R16:
2346 case WINED3DFMT_A8R3G3B2:
2347 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2348 return FALSE;
2350 /* Floating point formats */
2351 case WINED3DFMT_R16F:
2352 case WINED3DFMT_A16B16G16R16F:
2353 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2354 TRACE_(d3d_caps)("[OK]\n");
2355 return TRUE;
2357 TRACE_(d3d_caps)("[FAILED]\n");
2358 return FALSE;
2360 case WINED3DFMT_R32F:
2361 case WINED3DFMT_A32B32G32R32F:
2362 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2363 TRACE_(d3d_caps)("[OK]\n");
2364 return TRUE;
2366 TRACE_(d3d_caps)("[FAILED]\n");
2367 return FALSE;
2369 case WINED3DFMT_G16R16F:
2370 case WINED3DFMT_G32R32F:
2371 if(GL_SUPPORT(ARB_TEXTURE_RG)) {
2372 TRACE_(d3d_caps)("[OK]\n");
2373 return TRUE;
2375 TRACE_(d3d_caps)("[FAILED]\n");
2376 return FALSE;
2378 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2379 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2380 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2381 * We can do instancing with all shader versions, but we need vertex shaders.
2383 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2384 * to enable instancing. WineD3D doesn't need that and just ignores it.
2386 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2388 case WINEMAKEFOURCC('I','N','S','T'):
2389 TRACE("ATI Instancing check hack\n");
2390 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2391 TRACE_(d3d_caps)("[OK]\n");
2392 return TRUE;
2394 TRACE_(d3d_caps)("[FAILED]\n");
2395 return FALSE;
2397 /* Some weird FOURCC formats */
2398 case WINED3DFMT_R8G8_B8G8:
2399 case WINED3DFMT_G8R8_G8B8:
2400 case WINED3DFMT_MULTI2_ARGB8:
2401 TRACE_(d3d_caps)("[FAILED]\n");
2402 return FALSE;
2404 /* Vendor specific formats */
2405 case WINED3DFMT_ATI2N:
2406 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2407 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2408 shader_backend = select_shader_backend(Adapter, DeviceType);
2409 fp = select_fragment_implementation(Adapter, DeviceType);
2410 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup)
2411 && fp->color_fixup_supported(glDesc->color_fixup))
2413 TRACE_(d3d_caps)("[OK]\n");
2414 return TRUE;
2417 TRACE_(d3d_caps)("[OK]\n");
2418 return TRUE;
2420 TRACE_(d3d_caps)("[FAILED]\n");
2421 return FALSE;
2423 case WINED3DFMT_NVHU:
2424 case WINED3DFMT_NVHS:
2425 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2426 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2427 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2428 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2429 * Applications have to deal with not having NVHS and NVHU.
2431 TRACE_(d3d_caps)("[FAILED]\n");
2432 return FALSE;
2434 case WINED3DFMT_UNKNOWN:
2435 return FALSE;
2437 default:
2438 ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat));
2439 break;
2441 return FALSE;
2444 static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) {
2445 const struct GlPixelFormatDesc *format_desc;
2446 const struct blit_shader *blitter;
2448 if(SurfaceType == SURFACE_GDI) {
2449 switch(CheckFormat) {
2450 case WINED3DFMT_R8G8B8:
2451 case WINED3DFMT_A8R8G8B8:
2452 case WINED3DFMT_X8R8G8B8:
2453 case WINED3DFMT_R5G6B5:
2454 case WINED3DFMT_X1R5G5B5:
2455 case WINED3DFMT_A1R5G5B5:
2456 case WINED3DFMT_A4R4G4B4:
2457 case WINED3DFMT_R3G3B2:
2458 case WINED3DFMT_A8:
2459 case WINED3DFMT_A8R3G3B2:
2460 case WINED3DFMT_X4R4G4B4:
2461 case WINED3DFMT_A2B10G10R10:
2462 case WINED3DFMT_A8B8G8R8:
2463 case WINED3DFMT_X8B8G8R8:
2464 case WINED3DFMT_G16R16:
2465 case WINED3DFMT_A2R10G10B10:
2466 case WINED3DFMT_A16B16G16R16:
2467 case WINED3DFMT_P8:
2468 TRACE_(d3d_caps)("[OK]\n");
2469 return TRUE;
2470 default:
2471 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2472 return FALSE;
2476 /* All format that are supported for textures are supported for surfaces as well */
2477 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE;
2478 /* All depth stencil formats are supported on surfaces */
2479 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) return TRUE;
2481 /* If opengl can't process the format natively, the blitter may be able to convert it */
2482 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &format_desc);
2483 blitter = select_blit_implementation(Adapter, DeviceType);
2484 if (blitter->color_fixup_supported(format_desc->color_fixup))
2486 TRACE_(d3d_caps)("[OK]\n");
2487 return TRUE;
2490 /* Reject other formats */
2491 TRACE_(d3d_caps)("[FAILED]\n");
2492 return FALSE;
2495 static BOOL CheckVertexTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2497 if (!GL_LIMITS(vertex_samplers)) {
2498 TRACE_(d3d_caps)("[FAILED]\n");
2499 return FALSE;
2502 switch (CheckFormat) {
2503 case WINED3DFMT_A32B32G32R32F:
2504 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2505 TRACE_(d3d_caps)("[FAILED]\n");
2506 return FALSE;
2508 TRACE_(d3d_caps)("[OK]\n");
2509 return TRUE;
2511 default:
2512 TRACE_(d3d_caps)("[FAILED]\n");
2513 return FALSE;
2515 return FALSE;
2518 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2519 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2520 WINED3DSURFTYPE SurfaceType) {
2521 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2522 DWORD UsageCaps = 0;
2524 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2525 This,
2526 Adapter,
2527 DeviceType, debug_d3ddevicetype(DeviceType),
2528 AdapterFormat, debug_d3dformat(AdapterFormat),
2529 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2530 RType, debug_d3dresourcetype(RType),
2531 CheckFormat, debug_d3dformat(CheckFormat));
2533 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2534 return WINED3DERR_INVALIDCALL;
2537 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2539 if(SurfaceType != SURFACE_OPENGL) {
2540 TRACE("[FAILED]\n");
2541 return WINED3DERR_NOTAVAILABLE;
2544 /* Cubetexture allows:
2545 * - D3DUSAGE_AUTOGENMIPMAP
2546 * - D3DUSAGE_DEPTHSTENCIL
2547 * - D3DUSAGE_DYNAMIC
2548 * - D3DUSAGE_NONSECURE (d3d9ex)
2549 * - D3DUSAGE_RENDERTARGET
2550 * - D3DUSAGE_SOFTWAREPROCESSING
2551 * - D3DUSAGE_QUERY_WRAPANDMIP
2553 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2554 /* Check if the texture format is around */
2555 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2556 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2557 /* Check for automatic mipmap generation support */
2558 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2559 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2560 } else {
2561 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2562 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2566 /* Always report dynamic locking */
2567 if(Usage & WINED3DUSAGE_DYNAMIC)
2568 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2570 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2571 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2572 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2573 } else {
2574 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2575 return WINED3DERR_NOTAVAILABLE;
2579 /* Always report software processing */
2580 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2581 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2583 /* Check QUERY_FILTER support */
2584 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2585 if(CheckFilterCapability(Adapter, CheckFormat)) {
2586 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2587 } else {
2588 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2589 return WINED3DERR_NOTAVAILABLE;
2593 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2594 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2595 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2596 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2597 } else {
2598 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2599 return WINED3DERR_NOTAVAILABLE;
2603 /* Check QUERY_SRGBREAD support */
2604 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2605 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2606 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2607 } else {
2608 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2609 return WINED3DERR_NOTAVAILABLE;
2613 /* Check QUERY_SRGBWRITE support */
2614 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2615 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2616 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2617 } else {
2618 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2619 return WINED3DERR_NOTAVAILABLE;
2623 /* Check QUERY_VERTEXTEXTURE support */
2624 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2625 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2626 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2627 } else {
2628 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2629 return WINED3DERR_NOTAVAILABLE;
2633 /* Check QUERY_WRAPANDMIP support */
2634 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2635 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2636 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2637 } else {
2638 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2639 return WINED3DERR_NOTAVAILABLE;
2642 } else {
2643 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2644 return WINED3DERR_NOTAVAILABLE;
2646 } else {
2647 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2648 return WINED3DERR_NOTAVAILABLE;
2650 } else if(RType == WINED3DRTYPE_SURFACE) {
2651 /* Surface allows:
2652 * - D3DUSAGE_DEPTHSTENCIL
2653 * - D3DUSAGE_NONSECURE (d3d9ex)
2654 * - D3DUSAGE_RENDERTARGET
2657 if(CheckSurfaceCapability(Adapter, AdapterFormat, DeviceType, CheckFormat, SurfaceType)) {
2658 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2659 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2660 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2661 } else {
2662 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2663 return WINED3DERR_NOTAVAILABLE;
2667 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2668 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2669 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2670 } else {
2671 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2672 return WINED3DERR_NOTAVAILABLE;
2676 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2677 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2678 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2679 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2680 } else {
2681 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2682 return WINED3DERR_NOTAVAILABLE;
2685 } else {
2686 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2687 return WINED3DERR_NOTAVAILABLE;
2690 } else if(RType == WINED3DRTYPE_TEXTURE) {
2691 /* Texture allows:
2692 * - D3DUSAGE_AUTOGENMIPMAP
2693 * - D3DUSAGE_DEPTHSTENCIL
2694 * - D3DUSAGE_DMAP
2695 * - D3DUSAGE_DYNAMIC
2696 * - D3DUSAGE_NONSECURE (d3d9ex)
2697 * - D3DUSAGE_RENDERTARGET
2698 * - D3DUSAGE_SOFTWAREPROCESSING
2699 * - D3DUSAGE_TEXTAPI (d3d9ex)
2700 * - D3DUSAGE_QUERY_WRAPANDMIP
2703 if(SurfaceType != SURFACE_OPENGL) {
2704 TRACE("[FAILED]\n");
2705 return WINED3DERR_NOTAVAILABLE;
2708 /* Check if the texture format is around */
2709 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2710 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2711 /* Check for automatic mipmap generation support */
2712 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2713 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2714 } else {
2715 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2716 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2720 /* Always report dynamic locking */
2721 if(Usage & WINED3DUSAGE_DYNAMIC)
2722 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2724 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2725 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2726 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2727 } else {
2728 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2729 return WINED3DERR_NOTAVAILABLE;
2733 /* Always report software processing */
2734 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2735 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2737 /* Check QUERY_FILTER support */
2738 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2739 if(CheckFilterCapability(Adapter, CheckFormat)) {
2740 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2741 } else {
2742 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2743 return WINED3DERR_NOTAVAILABLE;
2747 /* Check QUERY_LEGACYBUMPMAP support */
2748 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2749 if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) {
2750 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2751 } else {
2752 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2753 return WINED3DERR_NOTAVAILABLE;
2757 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2758 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2759 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2760 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2761 } else {
2762 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2763 return WINED3DERR_NOTAVAILABLE;
2767 /* Check QUERY_SRGBREAD support */
2768 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2769 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2770 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2771 } else {
2772 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2773 return WINED3DERR_NOTAVAILABLE;
2777 /* Check QUERY_SRGBWRITE support */
2778 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2779 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2780 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2781 } else {
2782 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2783 return WINED3DERR_NOTAVAILABLE;
2787 /* Check QUERY_VERTEXTEXTURE support */
2788 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2789 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2790 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2791 } else {
2792 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2793 return WINED3DERR_NOTAVAILABLE;
2797 /* Check QUERY_WRAPANDMIP support */
2798 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2799 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2800 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2801 } else {
2802 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2803 return WINED3DERR_NOTAVAILABLE;
2807 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2808 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2809 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2810 } else {
2811 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2812 return WINED3DERR_NOTAVAILABLE;
2815 } else {
2816 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2817 return WINED3DERR_NOTAVAILABLE;
2819 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2820 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2821 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2823 * Volumetexture allows:
2824 * - D3DUSAGE_DYNAMIC
2825 * - D3DUSAGE_NONSECURE (d3d9ex)
2826 * - D3DUSAGE_SOFTWAREPROCESSING
2827 * - D3DUSAGE_QUERY_WRAPANDMIP
2830 if(SurfaceType != SURFACE_OPENGL) {
2831 TRACE("[FAILED]\n");
2832 return WINED3DERR_NOTAVAILABLE;
2835 /* Check volume texture and volume usage caps */
2836 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2837 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) {
2838 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2839 return WINED3DERR_NOTAVAILABLE;
2842 /* Always report dynamic locking */
2843 if(Usage & WINED3DUSAGE_DYNAMIC)
2844 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2846 /* Always report software processing */
2847 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2848 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2850 /* Check QUERY_FILTER support */
2851 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2852 if(CheckFilterCapability(Adapter, CheckFormat)) {
2853 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2854 } else {
2855 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2856 return WINED3DERR_NOTAVAILABLE;
2860 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2861 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2862 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2863 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2864 } else {
2865 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2866 return WINED3DERR_NOTAVAILABLE;
2870 /* Check QUERY_SRGBREAD support */
2871 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2872 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2873 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2874 } else {
2875 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2876 return WINED3DERR_NOTAVAILABLE;
2880 /* Check QUERY_SRGBWRITE support */
2881 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2882 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2883 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2884 } else {
2885 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2886 return WINED3DERR_NOTAVAILABLE;
2890 /* Check QUERY_VERTEXTEXTURE support */
2891 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2892 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2893 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2894 } else {
2895 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2896 return WINED3DERR_NOTAVAILABLE;
2900 /* Check QUERY_WRAPANDMIP support */
2901 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2902 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2903 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2904 } else {
2905 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2906 return WINED3DERR_NOTAVAILABLE;
2909 } else {
2910 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
2911 return WINED3DERR_NOTAVAILABLE;
2914 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
2915 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
2916 * app needing one of those formats, don't advertize them to avoid leading apps into
2917 * temptation. The windows drivers don't support most of those formats on volumes anyway,
2918 * except of R32F.
2920 switch(CheckFormat) {
2921 case WINED3DFMT_P8:
2922 case WINED3DFMT_A4L4:
2923 case WINED3DFMT_R32F:
2924 case WINED3DFMT_R16F:
2925 case WINED3DFMT_X8L8V8U8:
2926 case WINED3DFMT_L6V5U5:
2927 case WINED3DFMT_G16R16:
2928 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2929 return WINED3DERR_NOTAVAILABLE;
2931 case WINED3DFMT_Q8W8V8U8:
2932 case WINED3DFMT_V16U16:
2933 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2934 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2935 return WINED3DERR_NOTAVAILABLE;
2937 break;
2939 case WINED3DFMT_V8U8:
2940 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2941 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2942 return WINED3DERR_NOTAVAILABLE;
2944 break;
2946 case WINED3DFMT_DXT1:
2947 case WINED3DFMT_DXT2:
2948 case WINED3DFMT_DXT3:
2949 case WINED3DFMT_DXT4:
2950 case WINED3DFMT_DXT5:
2951 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
2952 * compressed texture results in an error. While the D3D refrast does
2953 * support s3tc volumes, at least the nvidia windows driver does not, so
2954 * we're free not to support this format.
2956 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
2957 return WINED3DERR_NOTAVAILABLE;
2959 default:
2960 /* Do nothing, continue with checking the format below */
2961 break;
2963 } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){
2964 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
2965 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
2966 return WINED3DERR_NOTAVAILABLE;
2969 /* This format is nothing special and it is supported perfectly.
2970 * However, ati and nvidia driver on windows do not mark this format as
2971 * supported (tested with the dxCapsViewer) and pretending to
2972 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
2973 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
2974 * Enable it on dx7. It will need additional checking on dx10 when we support it.
2976 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
2977 TRACE_(d3d_caps)("[FAILED]\n");
2978 return WINED3DERR_NOTAVAILABLE;
2981 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
2982 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
2983 * usage flags match. */
2984 if(UsageCaps == Usage) {
2985 return WINED3D_OK;
2986 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
2987 return WINED3DOK_NOAUTOGEN;
2988 } else {
2989 TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
2990 return WINED3DERR_NOTAVAILABLE;
2994 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2995 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2996 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2998 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2999 This,
3000 Adapter,
3001 DeviceType, debug_d3ddevicetype(DeviceType),
3002 SourceFormat, debug_d3dformat(SourceFormat),
3003 TargetFormat, debug_d3dformat(TargetFormat));
3004 return WINED3D_OK;
3007 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3008 const shader_backend_t *ret;
3009 int vs_selected_mode;
3010 int ps_selected_mode;
3012 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3013 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3014 ret = &glsl_shader_backend;
3015 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3016 ret = &arb_program_shader_backend;
3017 } else {
3018 ret = &none_shader_backend;
3020 return ret;
3023 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3024 int vs_selected_mode;
3025 int ps_selected_mode;
3027 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3028 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3029 return &arbfp_fragment_pipeline;
3030 } else if(ps_selected_mode == SHADER_ATI) {
3031 return &atifs_fragment_pipeline;
3032 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3033 return &nvts_fragment_pipeline;
3034 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3035 return &nvrc_fragment_pipeline;
3036 } else {
3037 return &ffp_fragment_pipeline;
3041 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3042 int vs_selected_mode;
3043 int ps_selected_mode;
3045 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3046 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3047 return &arbfp_blit;
3048 } else {
3049 return &ffp_blit;
3053 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3054 subset of a D3DCAPS9 structure. However, it has to come via a void *
3055 as the d3d8 interface cannot import the d3d9 header */
3056 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3058 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3059 int vs_selected_mode;
3060 int ps_selected_mode;
3061 struct shader_caps shader_caps;
3062 struct fragment_caps fragment_caps;
3063 const shader_backend_t *shader_backend;
3064 const struct fragment_pipeline *frag_pipeline = NULL;
3065 DWORD ckey_caps, blit_caps, fx_caps;
3067 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3069 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3070 return WINED3DERR_INVALIDCALL;
3073 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3075 /* This function should *not* be modifying GL caps
3076 * TODO: move the functionality where it belongs */
3077 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
3079 /* ------------------------------------------------
3080 The following fields apply to both d3d8 and d3d9
3081 ------------------------------------------------ */
3082 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3083 pCaps->AdapterOrdinal = Adapter;
3085 pCaps->Caps = 0;
3086 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3087 WINED3DCAPS2_FULLSCREENGAMMA |
3088 WINED3DCAPS2_DYNAMICTEXTURES;
3089 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3090 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3093 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3094 WINED3DCAPS3_COPY_TO_VIDMEM |
3095 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3097 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3098 WINED3DPRESENT_INTERVAL_ONE;
3100 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3101 WINED3DCURSORCAPS_LOWRES;
3103 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3104 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3105 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3106 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3107 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3108 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3109 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3110 WINED3DDEVCAPS_PUREDEVICE |
3111 WINED3DDEVCAPS_HWRASTERIZATION |
3112 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3113 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3114 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3115 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3116 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3117 WINED3DDEVCAPS_RTPATCHES;
3119 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3120 WINED3DPMISCCAPS_CULLCCW |
3121 WINED3DPMISCCAPS_CULLCW |
3122 WINED3DPMISCCAPS_COLORWRITEENABLE |
3123 WINED3DPMISCCAPS_CLIPTLVERTS |
3124 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3125 WINED3DPMISCCAPS_MASKZ |
3126 WINED3DPMISCCAPS_BLENDOP |
3127 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3128 /* TODO:
3129 WINED3DPMISCCAPS_NULLREFERENCE
3130 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3131 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3132 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3133 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3135 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3136 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3138 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3139 WINED3DPRASTERCAPS_PAT |
3140 WINED3DPRASTERCAPS_WFOG |
3141 WINED3DPRASTERCAPS_ZFOG |
3142 WINED3DPRASTERCAPS_FOGVERTEX |
3143 WINED3DPRASTERCAPS_FOGTABLE |
3144 WINED3DPRASTERCAPS_STIPPLE |
3145 WINED3DPRASTERCAPS_SUBPIXEL |
3146 WINED3DPRASTERCAPS_ZTEST |
3147 WINED3DPRASTERCAPS_SCISSORTEST |
3148 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3149 WINED3DPRASTERCAPS_DEPTHBIAS;
3151 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3152 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3153 WINED3DPRASTERCAPS_ZBIAS |
3154 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3156 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3157 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3159 /* FIXME Add:
3160 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3161 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3162 WINED3DPRASTERCAPS_ANTIALIASEDGES
3163 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3164 WINED3DPRASTERCAPS_WBUFFER */
3166 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3167 WINED3DPCMPCAPS_EQUAL |
3168 WINED3DPCMPCAPS_GREATER |
3169 WINED3DPCMPCAPS_GREATEREQUAL |
3170 WINED3DPCMPCAPS_LESS |
3171 WINED3DPCMPCAPS_LESSEQUAL |
3172 WINED3DPCMPCAPS_NEVER |
3173 WINED3DPCMPCAPS_NOTEQUAL;
3175 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3176 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3177 WINED3DPBLENDCAPS_DESTALPHA |
3178 WINED3DPBLENDCAPS_DESTCOLOR |
3179 WINED3DPBLENDCAPS_INVDESTALPHA |
3180 WINED3DPBLENDCAPS_INVDESTCOLOR |
3181 WINED3DPBLENDCAPS_INVSRCALPHA |
3182 WINED3DPBLENDCAPS_INVSRCCOLOR |
3183 WINED3DPBLENDCAPS_ONE |
3184 WINED3DPBLENDCAPS_SRCALPHA |
3185 WINED3DPBLENDCAPS_SRCALPHASAT |
3186 WINED3DPBLENDCAPS_SRCCOLOR |
3187 WINED3DPBLENDCAPS_ZERO;
3189 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3190 WINED3DPBLENDCAPS_DESTCOLOR |
3191 WINED3DPBLENDCAPS_INVDESTALPHA |
3192 WINED3DPBLENDCAPS_INVDESTCOLOR |
3193 WINED3DPBLENDCAPS_INVSRCALPHA |
3194 WINED3DPBLENDCAPS_INVSRCCOLOR |
3195 WINED3DPBLENDCAPS_ONE |
3196 WINED3DPBLENDCAPS_SRCALPHA |
3197 WINED3DPBLENDCAPS_SRCCOLOR |
3198 WINED3DPBLENDCAPS_ZERO;
3199 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3200 * according to the glBlendFunc manpage
3202 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3203 * legacy settings for srcblend only
3206 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3207 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3208 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3212 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3213 WINED3DPCMPCAPS_EQUAL |
3214 WINED3DPCMPCAPS_GREATER |
3215 WINED3DPCMPCAPS_GREATEREQUAL |
3216 WINED3DPCMPCAPS_LESS |
3217 WINED3DPCMPCAPS_LESSEQUAL |
3218 WINED3DPCMPCAPS_NEVER |
3219 WINED3DPCMPCAPS_NOTEQUAL;
3221 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3222 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3223 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3224 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3225 WINED3DPSHADECAPS_COLORFLATRGB |
3226 WINED3DPSHADECAPS_FOGFLAT |
3227 WINED3DPSHADECAPS_FOGGOURAUD |
3228 WINED3DPSHADECAPS_SPECULARFLATRGB;
3230 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3231 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3232 WINED3DPTEXTURECAPS_TRANSPARENCY |
3233 WINED3DPTEXTURECAPS_BORDER |
3234 WINED3DPTEXTURECAPS_MIPMAP |
3235 WINED3DPTEXTURECAPS_PROJECTED |
3236 WINED3DPTEXTURECAPS_PERSPECTIVE;
3238 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3239 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3240 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3243 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3244 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3245 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3246 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3249 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3250 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3251 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3252 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3256 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3257 WINED3DPTFILTERCAPS_MAGFPOINT |
3258 WINED3DPTFILTERCAPS_MINFLINEAR |
3259 WINED3DPTFILTERCAPS_MINFPOINT |
3260 WINED3DPTFILTERCAPS_MIPFLINEAR |
3261 WINED3DPTFILTERCAPS_MIPFPOINT |
3262 WINED3DPTFILTERCAPS_LINEAR |
3263 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3264 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3265 WINED3DPTFILTERCAPS_MIPLINEAR |
3266 WINED3DPTFILTERCAPS_MIPNEAREST |
3267 WINED3DPTFILTERCAPS_NEAREST;
3269 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3270 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3271 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3274 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3275 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3276 WINED3DPTFILTERCAPS_MAGFPOINT |
3277 WINED3DPTFILTERCAPS_MINFLINEAR |
3278 WINED3DPTFILTERCAPS_MINFPOINT |
3279 WINED3DPTFILTERCAPS_MIPFLINEAR |
3280 WINED3DPTFILTERCAPS_MIPFPOINT |
3281 WINED3DPTFILTERCAPS_LINEAR |
3282 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3283 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3284 WINED3DPTFILTERCAPS_MIPLINEAR |
3285 WINED3DPTFILTERCAPS_MIPNEAREST |
3286 WINED3DPTFILTERCAPS_NEAREST;
3288 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3289 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3290 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3292 } else
3293 pCaps->CubeTextureFilterCaps = 0;
3295 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3296 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3297 WINED3DPTFILTERCAPS_MAGFPOINT |
3298 WINED3DPTFILTERCAPS_MINFLINEAR |
3299 WINED3DPTFILTERCAPS_MINFPOINT |
3300 WINED3DPTFILTERCAPS_MIPFLINEAR |
3301 WINED3DPTFILTERCAPS_MIPFPOINT |
3302 WINED3DPTFILTERCAPS_LINEAR |
3303 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3304 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3305 WINED3DPTFILTERCAPS_MIPLINEAR |
3306 WINED3DPTFILTERCAPS_MIPNEAREST |
3307 WINED3DPTFILTERCAPS_NEAREST;
3308 } else
3309 pCaps->VolumeTextureFilterCaps = 0;
3311 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3312 WINED3DPTADDRESSCAPS_CLAMP |
3313 WINED3DPTADDRESSCAPS_WRAP;
3315 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3316 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3318 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3319 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3321 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3322 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3325 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3326 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3327 WINED3DPTADDRESSCAPS_CLAMP |
3328 WINED3DPTADDRESSCAPS_WRAP;
3329 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3330 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3332 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3333 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3335 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3336 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3338 } else
3339 pCaps->VolumeTextureAddressCaps = 0;
3341 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3342 WINED3DLINECAPS_ZTEST |
3343 WINED3DLINECAPS_BLEND |
3344 WINED3DLINECAPS_ALPHACMP |
3345 WINED3DLINECAPS_FOG;
3346 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3347 * idea how generating the smoothing alpha values works; the result is different
3350 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3351 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3353 if(GL_SUPPORT(EXT_TEXTURE3D))
3354 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3355 else
3356 pCaps->MaxVolumeExtent = 0;
3358 pCaps->MaxTextureRepeat = 32768;
3359 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3360 pCaps->MaxVertexW = 1.0;
3362 pCaps->GuardBandLeft = 0;
3363 pCaps->GuardBandTop = 0;
3364 pCaps->GuardBandRight = 0;
3365 pCaps->GuardBandBottom = 0;
3367 pCaps->ExtentsAdjust = 0;
3369 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3370 WINED3DSTENCILCAPS_INCRSAT |
3371 WINED3DSTENCILCAPS_INVERT |
3372 WINED3DSTENCILCAPS_KEEP |
3373 WINED3DSTENCILCAPS_REPLACE |
3374 WINED3DSTENCILCAPS_ZERO;
3375 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3376 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3377 WINED3DSTENCILCAPS_INCR;
3379 if ( This->dxVersion > 8 &&
3380 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3381 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3382 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3385 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3387 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3388 pCaps->MaxActiveLights = GL_LIMITS(lights);
3390 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3391 pCaps->MaxVertexBlendMatrixIndex = 0;
3393 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3394 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3397 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3398 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3399 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3400 WINED3DVTXPCAPS_LOCALVIEWER |
3401 WINED3DVTXPCAPS_VERTEXFOG |
3402 WINED3DVTXPCAPS_TEXGEN;
3403 /* FIXME: Add
3404 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3406 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3407 pCaps->MaxVertexIndex = 0xFFFFF;
3408 pCaps->MaxStreams = MAX_STREAMS;
3409 pCaps->MaxStreamStride = 1024;
3411 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3412 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3413 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3414 pCaps->MaxNpatchTessellationLevel = 0;
3415 pCaps->MasterAdapterOrdinal = 0;
3416 pCaps->AdapterOrdinalInGroup = 0;
3417 pCaps->NumberOfAdaptersInGroup = 1;
3419 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3421 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3422 WINED3DPTFILTERCAPS_MAGFPOINT |
3423 WINED3DPTFILTERCAPS_MINFLINEAR |
3424 WINED3DPTFILTERCAPS_MAGFLINEAR;
3425 pCaps->VertexTextureFilterCaps = 0;
3427 memset(&shader_caps, 0, sizeof(shader_caps));
3428 shader_backend = select_shader_backend(Adapter, DeviceType);
3429 shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps);
3431 memset(&fragment_caps, 0, sizeof(fragment_caps));
3432 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3433 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &fragment_caps);
3435 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3436 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3438 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3439 * Ignore shader model capabilities if disabled in config
3441 if(vs_selected_mode == SHADER_NONE) {
3442 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3443 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3444 pCaps->MaxVertexShaderConst = 0;
3445 } else {
3446 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3447 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3450 if(ps_selected_mode == SHADER_NONE) {
3451 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3452 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3453 pCaps->PixelShader1xMaxValue = 0.0;
3454 } else {
3455 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3456 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3459 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3460 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3461 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3463 pCaps->VS20Caps = shader_caps.VS20Caps;
3464 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3465 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3466 pCaps->PS20Caps = shader_caps.PS20Caps;
3467 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3468 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3470 /* The following caps are shader specific, but they are things we cannot detect, or which
3471 * are the same among all shader models. So to avoid code duplication set the shader version
3472 * specific, but otherwise constant caps here
3474 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3475 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3476 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3477 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3478 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3479 pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
3480 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3482 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3483 pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
3484 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3485 pCaps->VS20Caps.Caps = 0;
3486 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3487 pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
3488 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3490 pCaps->MaxVShaderInstructionsExecuted = 65535;
3491 pCaps->MaxVertexShader30InstructionSlots = 0;
3492 } else { /* VS 1.x */
3493 pCaps->VS20Caps.Caps = 0;
3494 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3495 pCaps->VS20Caps.NumTemps = 0;
3496 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3498 pCaps->MaxVShaderInstructionsExecuted = 0;
3499 pCaps->MaxVertexShader30InstructionSlots = 0;
3502 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3503 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3504 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3506 /* 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 */
3507 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3508 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3509 WINED3DPS20CAPS_PREDICATION |
3510 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3511 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3512 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3513 pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
3514 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3515 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3517 pCaps->MaxPShaderInstructionsExecuted = 65535;
3518 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
3519 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3520 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3521 pCaps->PS20Caps.Caps = 0;
3522 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3523 pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
3524 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3525 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3527 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3528 pCaps->MaxPixelShader30InstructionSlots = 0;
3529 } else { /* PS 1.x */
3530 pCaps->PS20Caps.Caps = 0;
3531 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3532 pCaps->PS20Caps.NumTemps = 0;
3533 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3534 pCaps->PS20Caps.NumInstructionSlots = 0;
3536 pCaps->MaxPShaderInstructionsExecuted = 0;
3537 pCaps->MaxPixelShader30InstructionSlots = 0;
3540 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3541 /* OpenGL supports all the formats below, perhaps not always
3542 * without conversion, but it supports them.
3543 * Further GLSL doesn't seem to have an official unsigned type so
3544 * don't advertise it yet as I'm not sure how we handle it.
3545 * We might need to add some clamping in the shader engine to
3546 * support it.
3547 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3548 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3549 WINED3DDTCAPS_UBYTE4N |
3550 WINED3DDTCAPS_SHORT2N |
3551 WINED3DDTCAPS_SHORT4N;
3552 if (GL_SUPPORT(NV_HALF_FLOAT)) {
3553 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3554 WINED3DDTCAPS_FLOAT16_4;
3556 } else
3557 pCaps->DeclTypes = 0;
3559 /* Set DirectDraw helper Caps */
3560 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3561 WINEDDCKEYCAPS_SRCBLT;
3562 fx_caps = WINEDDFXCAPS_BLTALPHA |
3563 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3564 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3565 WINEDDFXCAPS_BLTROTATION90 |
3566 WINEDDFXCAPS_BLTSHRINKX |
3567 WINEDDFXCAPS_BLTSHRINKXN |
3568 WINEDDFXCAPS_BLTSHRINKY |
3569 WINEDDFXCAPS_BLTSHRINKXN |
3570 WINEDDFXCAPS_BLTSTRETCHX |
3571 WINEDDFXCAPS_BLTSTRETCHXN |
3572 WINEDDFXCAPS_BLTSTRETCHY |
3573 WINEDDFXCAPS_BLTSTRETCHYN;
3574 blit_caps = WINEDDCAPS_BLT |
3575 WINEDDCAPS_BLTCOLORFILL |
3576 WINEDDCAPS_BLTDEPTHFILL |
3577 WINEDDCAPS_BLTSTRETCH |
3578 WINEDDCAPS_CANBLTSYSMEM |
3579 WINEDDCAPS_CANCLIP |
3580 WINEDDCAPS_CANCLIPSTRETCHED |
3581 WINEDDCAPS_COLORKEY |
3582 WINEDDCAPS_COLORKEYHWASSIST |
3583 WINEDDCAPS_ALIGNBOUNDARYSRC;
3585 /* Fill the ddraw caps structure */
3586 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3587 WINEDDCAPS_PALETTE |
3588 blit_caps;
3589 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3590 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3591 WINEDDCAPS2_PRIMARYGAMMA |
3592 WINEDDCAPS2_WIDESURFACES |
3593 WINEDDCAPS2_CANRENDERWINDOWED;
3594 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3595 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3596 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3597 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3598 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3599 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3600 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3601 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3602 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3604 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3605 WINEDDSCAPS_BACKBUFFER |
3606 WINEDDSCAPS_FLIP |
3607 WINEDDSCAPS_FRONTBUFFER |
3608 WINEDDSCAPS_OFFSCREENPLAIN |
3609 WINEDDSCAPS_PALETTE |
3610 WINEDDSCAPS_PRIMARYSURFACE |
3611 WINEDDSCAPS_SYSTEMMEMORY |
3612 WINEDDSCAPS_VIDEOMEMORY |
3613 WINEDDSCAPS_VISIBLE;
3614 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3616 /* Set D3D caps if OpenGL is available. */
3617 if(Adapters[Adapter].opengl) {
3618 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3619 WINEDDSCAPS_MIPMAP |
3620 WINEDDSCAPS_TEXTURE |
3621 WINEDDSCAPS_ZBUFFER;
3622 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3625 return WINED3D_OK;
3628 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3629 and fields being inserted in the middle, a new structure is used in place */
3630 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
3631 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
3632 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
3634 IWineD3DDeviceImpl *object = NULL;
3635 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3636 WINED3DDISPLAYMODE mode;
3637 const struct fragment_pipeline *frag_pipeline = NULL;
3638 int i;
3639 struct fragment_caps ffp_caps;
3640 HRESULT hr;
3642 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3643 * number and create a device without a 3D adapter for 2D only operation.
3645 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3646 return WINED3DERR_INVALIDCALL;
3649 /* Create a WineD3DDevice object */
3650 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3651 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3652 TRACE("Created WineD3DDevice object @ %p\n", object);
3653 if (NULL == object) {
3654 return WINED3DERR_OUTOFVIDEOMEMORY;
3657 /* Set up initial COM information */
3658 object->lpVtbl = &IWineD3DDevice_Vtbl;
3659 object->ref = 1;
3660 object->wineD3D = iface;
3661 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
3662 IWineD3D_AddRef(object->wineD3D);
3663 object->parent = parent;
3664 object->device_parent = device_parent;
3665 list_init(&object->resources);
3666 list_init(&object->shaders);
3668 if(This->dxVersion == 7) {
3669 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3670 } else {
3671 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3673 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3675 /* Set the state up as invalid until the device is fully created */
3676 object->state = WINED3DERR_DRIVERINTERNALERROR;
3678 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3679 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3681 /* Save the creation parameters */
3682 object->createParms.AdapterOrdinal = Adapter;
3683 object->createParms.DeviceType = DeviceType;
3684 object->createParms.hFocusWindow = hFocusWindow;
3685 object->createParms.BehaviorFlags = BehaviourFlags;
3687 /* Initialize other useful values */
3688 object->adapterNo = Adapter;
3689 object->devType = DeviceType;
3691 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
3692 object->shader_backend = select_shader_backend(Adapter, DeviceType);
3694 memset(&ffp_caps, 0, sizeof(ffp_caps));
3695 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3696 object->frag_pipe = frag_pipeline;
3697 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
3698 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3699 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3700 hr = compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
3701 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3703 if (FAILED(hr)) {
3704 IWineD3D_Release(object->wineD3D);
3705 HeapFree(GetProcessHeap(), 0, object);
3707 return hr;
3710 object->blitter = select_blit_implementation(Adapter, DeviceType);
3712 /* set the state of the device to valid */
3713 object->state = WINED3D_OK;
3715 /* Get the initial screen setup for ddraw */
3716 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3718 object->ddraw_width = mode.Width;
3719 object->ddraw_height = mode.Height;
3720 object->ddraw_format = mode.Format;
3722 for(i = 0; i < PATCHMAP_SIZE; i++) {
3723 list_init(&object->patches[i]);
3725 return WINED3D_OK;
3727 #undef GLINFO_LOCATION
3729 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3730 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3731 IUnknown_AddRef(This->parent);
3732 *pParent = This->parent;
3733 return WINED3D_OK;
3736 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3737 IUnknown* surfaceParent;
3738 TRACE("(%p) call back\n", pSurface);
3740 /* Now, release the parent, which will take care of cleaning up the surface for us */
3741 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3742 IUnknown_Release(surfaceParent);
3743 return IUnknown_Release(surfaceParent);
3746 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3747 IUnknown* volumeParent;
3748 TRACE("(%p) call back\n", pVolume);
3750 /* Now, release the parent, which will take care of cleaning up the volume for us */
3751 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3752 IUnknown_Release(volumeParent);
3753 return IUnknown_Release(volumeParent);
3756 static BOOL implementation_is_apple(const WineD3D_GL_Info *gl_info)
3758 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3759 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3760 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3762 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3763 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3764 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3765 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3766 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3767 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3768 * DirectDraw, not OpenGL.
3770 if(gl_info->supported[APPLE_FENCE] &&
3771 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3772 gl_info->supported[APPLE_FLUSH_RENDER] &&
3773 gl_info->supported[APPLE_YCBCR_422]) {
3774 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3775 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3776 return TRUE;
3777 } else {
3778 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3779 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3780 return FALSE;
3784 #define GLINFO_LOCATION (*gl_info)
3785 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3786 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3787 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3788 * all the texture. This function detects this bug by its symptom and disables PBOs
3789 * if the test fails.
3791 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3792 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3793 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3794 * read back is compared to the original. If they are equal PBOs are assumed to work,
3795 * otherwise the PBO extension is disabled.
3797 GLuint texture, pbo;
3798 static const unsigned int pattern[] = {
3799 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3800 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3801 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3802 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3804 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3806 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3807 /* No PBO -> No point in testing them */
3808 return;
3811 while(glGetError());
3812 glGenTextures(1, &texture);
3813 glBindTexture(GL_TEXTURE_2D, texture);
3814 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3815 checkGLcall("Specifying the PBO test texture\n");
3817 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3818 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3819 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3820 checkGLcall("Specifying the PBO test pbo\n");
3822 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3823 checkGLcall("Loading the PBO test texture\n");
3825 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3826 glFinish(); /* just to be sure */
3828 memset(check, 0, sizeof(check));
3829 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3830 checkGLcall("Reading back the PBO test texture\n");
3832 glDeleteTextures(1, &texture);
3833 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3834 checkGLcall("PBO test cleanup\n");
3836 if(memcmp(check, pattern, sizeof(check)) != 0) {
3837 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3838 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3839 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3840 } else {
3841 TRACE_(d3d_caps)("PBO test successful\n");
3844 #undef GLINFO_LOCATION
3846 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3847 * reporting a driver version is moot because we are not the Windows driver, and we have different
3848 * bugs, features, etc.
3850 * If a card is not found in this table, the gl driver version is reported
3852 struct driver_version_information {
3853 WORD vendor; /* reported PCI card vendor ID */
3854 WORD card; /* reported PCI card device ID */
3855 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3856 WORD lopart_hi, lopart_lo; /* driver loword to report */
3859 static const struct driver_version_information driver_version_table[] = {
3860 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/
3861 /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */
3862 /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */
3863 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 },
3864 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 },
3865 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 },
3866 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 },
3867 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 },
3868 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 },
3869 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 },
3870 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 },
3871 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 },
3872 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 },
3873 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 },
3874 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 },
3875 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 },
3876 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 },
3877 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 },
3878 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 },
3879 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 },
3881 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
3882 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
3883 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
3884 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
3885 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
3886 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
3887 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
3889 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
3892 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
3893 unsigned int i;
3894 BOOL apple = implementation_is_apple(gl_info);
3896 if(apple) {
3897 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
3898 * used it falls back to software. While the compiler can detect if the shader uses all declared
3899 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
3900 * using relative addressing falls back to software.
3902 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
3904 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
3905 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
3906 } else {
3907 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3908 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3909 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3912 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3913 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3914 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3915 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3916 * according to the spec.
3918 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3919 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3921 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
3922 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
3923 * this workaround is activated on cards that do not need it, it won't break things, just affect
3924 * performance negatively.
3926 if(gl_info->gl_vendor == VENDOR_INTEL ||
3927 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
3928 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
3929 gl_info->set_texcoord_w = TRUE;
3933 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
3934 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
3935 * If real NP2 textures are used, the driver falls back to software. We could just remove the
3936 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
3937 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
3938 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
3939 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
3941 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
3942 * has this extension promoted to core. The extension loading code sets this extension supported
3943 * due to that, so this code works on fglrx as well.
3945 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
3946 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
3947 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
3948 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
3949 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
3950 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3951 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
3955 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
3956 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
3957 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
3958 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
3959 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
3960 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
3962 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
3963 * triggering the software fallback. There is not much we can do here apart from disabling the
3964 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
3965 * in IWineD3DImpl_FillGLCaps).
3966 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
3967 * post-processing effects in the game "Max Payne 2").
3968 * The behaviour can be verified through a simple test app attached in bugreport #14724.
3970 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
3971 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
3972 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
3973 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3974 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
3978 /* Find out if PBOs work as they are supposed to */
3979 test_pbo_functionality(gl_info);
3981 /* Fixup the driver version */
3982 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
3983 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
3984 gl_info->gl_card == driver_version_table[i].card) {
3985 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
3987 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
3988 driver_version_table[i].lopart_lo);
3989 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
3990 driver_version_table[i].hipart_lo);
3991 break;
3996 static void WINE_GLAPI invalid_func(const void *data)
3998 ERR("Invalid vertex attribute function called\n");
3999 DebugBreak();
4002 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4004 ERR("Invalid texcoord function called\n");
4005 DebugBreak();
4008 #define GLINFO_LOCATION (Adapters[0].gl_info)
4010 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4011 * the extension detection and are used in drawStridedSlow
4013 static void WINE_GLAPI position_d3dcolor(const void *data)
4015 DWORD pos = *((const DWORD *)data);
4017 FIXME("Add a test for fixed function position from d3dcolor type\n");
4018 glVertex4s(D3DCOLOR_B_R(pos),
4019 D3DCOLOR_B_G(pos),
4020 D3DCOLOR_B_B(pos),
4021 D3DCOLOR_B_A(pos));
4024 static void WINE_GLAPI position_float4(const void *data)
4026 const GLfloat *pos = data;
4028 if (pos[3] < eps && pos[3] > -eps)
4029 glVertex3fv(pos);
4030 else {
4031 float w = 1.0 / pos[3];
4033 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4037 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4039 DWORD diffuseColor = *((const DWORD *)data);
4041 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4042 D3DCOLOR_B_G(diffuseColor),
4043 D3DCOLOR_B_B(diffuseColor),
4044 D3DCOLOR_B_A(diffuseColor));
4047 static void WINE_GLAPI specular_d3dcolor(const void *data)
4049 DWORD specularColor = *((const DWORD *)data);
4051 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
4052 D3DCOLOR_B_G(specularColor),
4053 D3DCOLOR_B_B(specularColor));
4056 static void WINE_GLAPI warn_no_specular_func(const void *data)
4058 WARN("GL_EXT_secondary_color not supported\n");
4061 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4063 position_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4064 position_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4065 position_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glVertex3fv;
4066 position_funcs[WINED3DDECLTYPE_FLOAT4] = position_float4;
4067 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = position_d3dcolor;
4068 position_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4069 position_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4070 position_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glVertex2sv;
4071 position_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4072 position_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4073 position_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4074 position_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4075 position_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4076 position_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4077 position_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4078 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4079 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4081 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4082 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4083 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glColor3fv;
4084 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glColor4fv;
4085 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = diffuse_d3dcolor;
4086 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4087 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4088 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4089 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (glAttribFunc)glColor4ubv;
4090 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4091 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (glAttribFunc)glColor4sv;
4092 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4093 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (glAttribFunc)glColor4usv;
4094 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4095 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4096 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4097 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4099 /* No 4 component entry points here */
4100 specular_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4101 specular_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4102 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4103 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4104 } else {
4105 specular_funcs[WINED3DDECLTYPE_FLOAT3] = warn_no_specular_func;
4107 specular_funcs[WINED3DDECLTYPE_FLOAT4] = invalid_func;
4108 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4109 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = specular_d3dcolor;
4110 } else {
4111 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = warn_no_specular_func;
4113 specular_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4114 specular_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4115 specular_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4116 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4117 specular_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4118 specular_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4119 specular_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4120 specular_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4121 specular_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4122 specular_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4123 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4124 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4126 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4127 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4129 normal_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4130 normal_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4131 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glNormal3fv;
4132 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4133 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4134 normal_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4135 normal_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4136 normal_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4137 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4138 normal_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4139 normal_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4140 normal_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4141 normal_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4142 normal_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4143 normal_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4144 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4145 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4147 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4148 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4149 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4150 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4151 multi_texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_texcoord_func;
4152 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_texcoord_func;
4153 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4154 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4155 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_texcoord_func;
4156 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_texcoord_func;
4157 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_texcoord_func;
4158 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_texcoord_func;
4159 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_texcoord_func;
4160 multi_texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_texcoord_func;
4161 multi_texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_texcoord_func;
4162 if (GL_SUPPORT(NV_HALF_FLOAT))
4164 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4165 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4166 } else {
4167 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
4168 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
4172 #define PUSH1(att) attribs[nAttribs++] = (att);
4173 BOOL InitAdapters(void) {
4174 static HMODULE mod_gl;
4175 BOOL ret;
4176 int ps_selected_mode, vs_selected_mode;
4178 /* No need to hold any lock. The calling library makes sure only one thread calls
4179 * wined3d simultaneously
4181 if(numAdapters > 0) return Adapters[0].opengl;
4183 TRACE("Initializing adapters\n");
4185 if(!mod_gl) {
4186 #ifdef USE_WIN32_OPENGL
4187 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4188 mod_gl = LoadLibraryA("opengl32.dll");
4189 if(!mod_gl) {
4190 ERR("Can't load opengl32.dll!\n");
4191 goto nogl_adapter;
4193 #else
4194 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4195 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4196 mod_gl = GetModuleHandleA("gdi32.dll");
4197 #endif
4200 /* Load WGL core functions from opengl32.dll */
4201 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4202 WGL_FUNCS_GEN;
4203 #undef USE_WGL_FUNC
4205 if(!pwglGetProcAddress) {
4206 ERR("Unable to load wglGetProcAddress!\n");
4207 goto nogl_adapter;
4210 /* Dynamically load all GL core functions */
4211 GL_FUNCS_GEN;
4212 #undef USE_GL_FUNC
4214 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4215 * otherwise because we have to use winex11.drv's override
4217 #ifdef USE_WIN32_OPENGL
4218 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4219 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4220 #else
4221 glFinish = (void*)pwglGetProcAddress("wglFinish");
4222 glFlush = (void*)pwglGetProcAddress("wglFlush");
4223 #endif
4225 glEnableWINE = glEnable;
4226 glDisableWINE = glDisable;
4228 /* For now only one default adapter */
4230 int iPixelFormat;
4231 int attribs[10];
4232 int values[10];
4233 int nAttribs = 0;
4234 int res;
4235 int i;
4236 WineD3D_PixelFormat *cfgs;
4237 int attribute;
4238 DISPLAY_DEVICEW DisplayDevice;
4239 HDC hdc;
4241 TRACE("Initializing default adapter\n");
4242 Adapters[0].num = 0;
4243 Adapters[0].monitorPoint.x = -1;
4244 Adapters[0].monitorPoint.y = -1;
4246 if (!WineD3D_CreateFakeGLContext()) {
4247 ERR("Failed to get a gl context for default adapter\n");
4248 WineD3D_ReleaseFakeGLContext();
4249 goto nogl_adapter;
4252 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
4253 if(!ret) {
4254 ERR("Failed to initialize gl caps for default adapter\n");
4255 WineD3D_ReleaseFakeGLContext();
4256 goto nogl_adapter;
4258 ret = initPixelFormats(&Adapters[0].gl_info);
4259 if(!ret) {
4260 ERR("Failed to init gl formats\n");
4261 WineD3D_ReleaseFakeGLContext();
4262 goto nogl_adapter;
4265 hdc = pwglGetCurrentDC();
4266 if(!hdc) {
4267 ERR("Failed to get gl HDC\n");
4268 WineD3D_ReleaseFakeGLContext();
4269 goto nogl_adapter;
4272 Adapters[0].driver = "Display";
4273 Adapters[0].description = "Direct3D HAL";
4275 /* Use the VideoRamSize registry setting when set */
4276 if(wined3d_settings.emulated_textureram)
4277 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4278 else
4279 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
4280 Adapters[0].UsedTextureRam = 0;
4281 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
4283 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4284 DisplayDevice.cb = sizeof(DisplayDevice);
4285 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4286 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4287 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
4289 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4290 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
4292 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
4293 cfgs = Adapters[0].cfgs;
4294 PUSH1(WGL_RED_BITS_ARB)
4295 PUSH1(WGL_GREEN_BITS_ARB)
4296 PUSH1(WGL_BLUE_BITS_ARB)
4297 PUSH1(WGL_ALPHA_BITS_ARB)
4298 PUSH1(WGL_DEPTH_BITS_ARB)
4299 PUSH1(WGL_STENCIL_BITS_ARB)
4300 PUSH1(WGL_DRAW_TO_WINDOW_ARB)
4301 PUSH1(WGL_PIXEL_TYPE_ARB)
4302 PUSH1(WGL_DOUBLE_BUFFER_ARB)
4303 PUSH1(WGL_AUX_BUFFERS_ARB)
4305 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
4306 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4308 if(!res)
4309 continue;
4311 /* Cache the pixel format */
4312 cfgs->iPixelFormat = iPixelFormat;
4313 cfgs->redSize = values[0];
4314 cfgs->greenSize = values[1];
4315 cfgs->blueSize = values[2];
4316 cfgs->alphaSize = values[3];
4317 cfgs->depthSize = values[4];
4318 cfgs->stencilSize = values[5];
4319 cfgs->windowDrawable = values[6];
4320 cfgs->iPixelType = values[7];
4321 cfgs->doubleBuffer = values[8];
4322 cfgs->auxBuffers = values[9];
4324 cfgs->pbufferDrawable = FALSE;
4325 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4326 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4327 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4328 int value;
4329 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4330 cfgs->pbufferDrawable = value;
4333 cfgs->numSamples = 0;
4334 /* Check multisample support */
4335 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4336 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4337 int value[2];
4338 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4339 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4340 * value[1] = number of multi sample buffers*/
4341 if(value[0])
4342 cfgs->numSamples = value[1];
4346 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4347 cfgs++;
4350 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4351 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4352 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4353 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4354 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4355 * driver is allowed to consume more bits EXCEPT for stencil bits.
4357 * Mark an adapter with this broken stencil behavior.
4359 Adapters[0].brokenStencil = TRUE;
4360 for(i=0, cfgs=Adapters[0].cfgs; i<Adapters[0].nCfgs; i++) {
4361 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4362 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4363 Adapters[0].brokenStencil = FALSE;
4364 break;
4368 fixup_extensions(&Adapters[0].gl_info);
4369 add_gl_compat_wrappers(&Adapters[0].gl_info);
4371 WineD3D_ReleaseFakeGLContext();
4373 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4374 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
4375 fillGLAttribFuncs(&Adapters[0].gl_info);
4376 init_type_lookup(&Adapters[0].gl_info);
4377 Adapters[0].opengl = TRUE;
4379 numAdapters = 1;
4380 TRACE("%d adapters successfully initialized\n", numAdapters);
4382 return TRUE;
4384 nogl_adapter:
4385 /* Initialize an adapter for ddraw-only memory counting */
4386 memset(Adapters, 0, sizeof(Adapters));
4387 Adapters[0].num = 0;
4388 Adapters[0].opengl = FALSE;
4389 Adapters[0].monitorPoint.x = -1;
4390 Adapters[0].monitorPoint.y = -1;
4392 Adapters[0].driver = "Display";
4393 Adapters[0].description = "WineD3D DirectDraw Emulation";
4394 if(wined3d_settings.emulated_textureram) {
4395 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4396 } else {
4397 Adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4400 numAdapters = 1;
4401 return FALSE;
4403 #undef PUSH1
4404 #undef GLINFO_LOCATION
4406 /**********************************************************
4407 * IWineD3D VTbl follows
4408 **********************************************************/
4410 const IWineD3DVtbl IWineD3D_Vtbl =
4412 /* IUnknown */
4413 IWineD3DImpl_QueryInterface,
4414 IWineD3DImpl_AddRef,
4415 IWineD3DImpl_Release,
4416 /* IWineD3D */
4417 IWineD3DImpl_GetParent,
4418 IWineD3DImpl_GetAdapterCount,
4419 IWineD3DImpl_RegisterSoftwareDevice,
4420 IWineD3DImpl_GetAdapterMonitor,
4421 IWineD3DImpl_GetAdapterModeCount,
4422 IWineD3DImpl_EnumAdapterModes,
4423 IWineD3DImpl_GetAdapterDisplayMode,
4424 IWineD3DImpl_GetAdapterIdentifier,
4425 IWineD3DImpl_CheckDeviceMultiSampleType,
4426 IWineD3DImpl_CheckDepthStencilMatch,
4427 IWineD3DImpl_CheckDeviceType,
4428 IWineD3DImpl_CheckDeviceFormat,
4429 IWineD3DImpl_CheckDeviceFormatConversion,
4430 IWineD3DImpl_GetDeviceCaps,
4431 IWineD3DImpl_CreateDevice