wined3d: Track shader constants in the shader backend.
[wine/wine64.git] / dlls / wined3d / directx.c
blobfb7869a0f96afe8b3eabaed81399b5dc64b8427f
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_vertex_blend", ARB_VERTEX_BLEND, 0 },
86 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
87 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
88 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
89 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
91 /* EXT */
92 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
93 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
94 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
95 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
96 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
97 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
98 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
99 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
100 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
101 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
102 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
103 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
104 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
105 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
106 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
107 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
108 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
109 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
110 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
111 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
112 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
113 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
114 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
115 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
116 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
118 /* NV */
119 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
120 {"GL_NV_fence", NV_FENCE, 0 },
121 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
122 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
123 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
124 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
125 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
126 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
127 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
128 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
129 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
130 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
131 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
132 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
133 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
134 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
135 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
136 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
137 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
139 /* SGI */
140 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
143 /**********************************************************
144 * Utility functions follow
145 **********************************************************/
147 /* Adapters */
148 static int numAdapters = 0;
149 static struct WineD3DAdapter Adapters[1];
151 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
152 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
153 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType);
154 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
156 /* lookup tables */
157 const int minLookup[MAX_LOOKUPS] =
159 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
162 const int maxLookup[MAX_LOOKUPS] =
164 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
167 DWORD *stateLookup[MAX_LOOKUPS];
169 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
170 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
172 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
173 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
174 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
178 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
179 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
181 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
184 /* drawStridedSlow attributes */
185 glAttribFunc position_funcs[WINED3DDECLTYPE_UNUSED];
186 glAttribFunc diffuse_funcs[WINED3DDECLTYPE_UNUSED];
187 glAttribFunc specular_funcs[WINED3DDECLTYPE_UNUSED];
188 glAttribFunc normal_funcs[WINED3DDECLTYPE_UNUSED];
189 glMultiTexCoordFunc multi_texcoord_funcs[WINED3DDECLTYPE_UNUSED];
192 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
193 * i.e., there is no GL Context - Get a default rendering context to enable the
194 * function query some info from GL.
197 static int wined3d_fake_gl_context_ref = 0;
198 static BOOL wined3d_fake_gl_context_foreign;
199 static BOOL wined3d_fake_gl_context_available = FALSE;
200 static HDC wined3d_fake_gl_context_hdc = NULL;
201 static HWND wined3d_fake_gl_context_hwnd = NULL;
203 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
204 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
206 0, 0, &wined3d_fake_gl_context_cs,
207 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
208 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
209 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
211 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
213 static void WineD3D_ReleaseFakeGLContext(void) {
214 HGLRC glCtx;
216 EnterCriticalSection(&wined3d_fake_gl_context_cs);
218 if(!wined3d_fake_gl_context_available) {
219 TRACE_(d3d_caps)("context not available\n");
220 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
221 return;
224 glCtx = pwglGetCurrentContext();
226 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
227 if (0 == (--wined3d_fake_gl_context_ref) ) {
228 if(!wined3d_fake_gl_context_foreign && glCtx) {
229 TRACE_(d3d_caps)("destroying fake GL context\n");
230 pwglMakeCurrent(NULL, NULL);
231 pwglDeleteContext(glCtx);
233 if(wined3d_fake_gl_context_hdc)
234 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
235 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
236 if(wined3d_fake_gl_context_hwnd)
237 DestroyWindow(wined3d_fake_gl_context_hwnd);
238 wined3d_fake_gl_context_hwnd = NULL;
239 wined3d_fake_gl_context_available = FALSE;
241 assert(wined3d_fake_gl_context_ref >= 0);
243 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
246 static BOOL WineD3D_CreateFakeGLContext(void) {
247 HGLRC glCtx = NULL;
249 EnterCriticalSection(&wined3d_fake_gl_context_cs);
251 TRACE("getting context...\n");
252 if(wined3d_fake_gl_context_ref > 0) goto ret;
253 assert(0 == wined3d_fake_gl_context_ref);
255 wined3d_fake_gl_context_foreign = TRUE;
257 glCtx = pwglGetCurrentContext();
258 if (!glCtx) {
259 PIXELFORMATDESCRIPTOR pfd;
260 int iPixelFormat;
262 wined3d_fake_gl_context_foreign = FALSE;
264 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
265 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
266 if(!wined3d_fake_gl_context_hwnd) {
267 ERR("HWND creation failed!\n");
268 goto fail;
270 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
271 if(!wined3d_fake_gl_context_hdc) {
272 ERR("GetDC failed!\n");
273 goto fail;
276 /* PixelFormat selection */
277 ZeroMemory(&pfd, sizeof(pfd));
278 pfd.nSize = sizeof(pfd);
279 pfd.nVersion = 1;
280 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
281 pfd.iPixelType = PFD_TYPE_RGBA;
282 pfd.cColorBits = 32;
283 pfd.iLayerType = PFD_MAIN_PLANE;
285 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
286 if(!iPixelFormat) {
287 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
288 ERR("Can't find a suitable iPixelFormat\n");
289 goto fail;
291 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
292 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
294 /* Create a GL context */
295 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
296 if (!glCtx) {
297 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
298 goto fail;
301 /* Make it the current GL context */
302 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
303 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
304 goto fail;
308 ret:
309 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
310 wined3d_fake_gl_context_ref++;
311 wined3d_fake_gl_context_available = TRUE;
312 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
313 return TRUE;
314 fail:
315 if(wined3d_fake_gl_context_hdc)
316 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
317 wined3d_fake_gl_context_hdc = NULL;
318 if(wined3d_fake_gl_context_hwnd)
319 DestroyWindow(wined3d_fake_gl_context_hwnd);
320 wined3d_fake_gl_context_hwnd = NULL;
321 if(glCtx) pwglDeleteContext(glCtx);
322 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
323 return FALSE;
326 /* Adjust the amount of used texture memory */
327 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
328 UINT Adapter = D3DDevice->adapterNo;
330 Adapters[Adapter].UsedTextureRam += glram;
331 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
332 return Adapters[Adapter].UsedTextureRam;
335 /**********************************************************
336 * IUnknown parts follows
337 **********************************************************/
339 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
343 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
344 if (IsEqualGUID(riid, &IID_IUnknown)
345 || IsEqualGUID(riid, &IID_IWineD3DBase)
346 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
347 IUnknown_AddRef(iface);
348 *ppobj = This;
349 return S_OK;
351 *ppobj = NULL;
352 return E_NOINTERFACE;
355 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
356 IWineD3DImpl *This = (IWineD3DImpl *)iface;
357 ULONG refCount = InterlockedIncrement(&This->ref);
359 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
360 return refCount;
363 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
364 IWineD3DImpl *This = (IWineD3DImpl *)iface;
365 ULONG ref;
366 TRACE("(%p) : Releasing from %d\n", This, This->ref);
367 ref = InterlockedDecrement(&This->ref);
368 if (ref == 0) {
369 HeapFree(GetProcessHeap(), 0, This);
372 return ref;
375 /* Set the shader type for this device, depending on the given capabilities,
376 * the device type, and the user preferences in wined3d_settings */
378 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
380 if (wined3d_settings.vs_mode == VS_NONE) {
381 *vs_selected = SHADER_NONE;
382 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
383 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
384 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
385 * shaders only on this card. */
386 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
387 *vs_selected = SHADER_ARB;
388 else
389 *vs_selected = SHADER_GLSL;
390 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
391 *vs_selected = SHADER_ARB;
392 } else {
393 *vs_selected = SHADER_NONE;
396 if (wined3d_settings.ps_mode == PS_NONE) {
397 *ps_selected = SHADER_NONE;
398 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
399 *ps_selected = SHADER_GLSL;
400 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
401 *ps_selected = SHADER_ARB;
402 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
403 *ps_selected = SHADER_ATI;
404 } else {
405 *ps_selected = SHADER_NONE;
409 /** Select the number of report maximum shader constants based on the selected shader modes */
410 static void select_shader_max_constants(
411 int ps_selected_mode,
412 int vs_selected_mode,
413 WineD3D_GL_Info *gl_info) {
415 switch (vs_selected_mode) {
416 case SHADER_GLSL:
417 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
418 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
419 break;
420 case SHADER_ARB:
421 /* We have to subtract any other PARAMs that we might use in our shader programs.
422 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
423 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
424 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
425 break;
426 default:
427 gl_info->max_vshader_constantsF = 0;
428 break;
431 switch (ps_selected_mode) {
432 case SHADER_GLSL:
433 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
434 * In theory the texbem instruction may need one more shader constant too. But lets assume
435 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
436 * and lets not take away a uniform needlessly from all other shaders.
438 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
439 break;
440 case SHADER_ARB:
441 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
442 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
444 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
445 break;
446 default:
447 gl_info->max_pshader_constantsF = 0;
448 break;
452 /**********************************************************
453 * IWineD3D parts follows
454 **********************************************************/
456 #define GLINFO_LOCATION (*gl_info)
457 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
459 GLuint prog;
460 BOOL ret = FALSE;
461 const char *testcode =
462 "!!ARBvp1.0\n"
463 "PARAM C[66] = { program.env[0..65] };\n"
464 "ADDRESS A0;"
465 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
466 "ARL A0.x, zero.x;\n"
467 "MOV result.position, C[A0.x + 65];\n"
468 "END\n";
470 while(glGetError());
471 GL_EXTCALL(glGenProgramsARB(1, &prog));
472 if(!prog) {
473 ERR("Failed to create an ARB offset limit test program\n");
475 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
476 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
477 strlen(testcode), testcode));
478 if(glGetError() != 0) {
479 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
480 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
481 ret = TRUE;
482 } else TRACE("OpenGL implementation allows offsets > 63\n");
484 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
485 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
486 checkGLcall("ARB vp offset limit test cleanup\n");
488 return ret;
491 static DWORD ver_for_ext(GL_SupportedExt ext)
493 unsigned int i;
494 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
495 if(EXTENSION_MAP[i].extension == ext) {
496 return EXTENSION_MAP[i].version;
499 return 0;
502 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
503 const char *GL_Extensions = NULL;
504 const char *WGL_Extensions = NULL;
505 const char *gl_string = NULL;
506 const char *gl_string_cursor = NULL;
507 GLint gl_max;
508 GLfloat gl_floatv[2];
509 int major = 1, minor = 0;
510 BOOL return_value = TRUE;
511 unsigned i;
512 HDC hdc;
513 unsigned int vidmem=0;
515 TRACE_(d3d_caps)("(%p)\n", gl_info);
517 ENTER_GL();
519 gl_string = (const char *) glGetString(GL_RENDERER);
520 if (NULL == gl_string)
521 gl_string = "None";
522 strcpy(gl_info->gl_renderer, gl_string);
524 gl_string = (const char *) glGetString(GL_VENDOR);
525 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
526 if (gl_string != NULL) {
527 /* Fill in the GL vendor */
528 if (strstr(gl_string, "NVIDIA")) {
529 gl_info->gl_vendor = VENDOR_NVIDIA;
530 } else if (strstr(gl_string, "ATI")) {
531 gl_info->gl_vendor = VENDOR_ATI;
532 } else if (strstr(gl_string, "Intel(R)") ||
533 strstr(gl_info->gl_renderer, "Intel(R)") ||
534 strstr(gl_string, "Intel Inc.")) {
535 gl_info->gl_vendor = VENDOR_INTEL;
536 } else if (strstr(gl_string, "Mesa")) {
537 gl_info->gl_vendor = VENDOR_MESA;
538 } else {
539 gl_info->gl_vendor = VENDOR_WINE;
541 } else {
542 gl_info->gl_vendor = VENDOR_WINE;
546 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
548 /* Parse the GL_VERSION field into major and minor information */
549 gl_string = (const char *) glGetString(GL_VERSION);
550 if (gl_string != NULL) {
552 /* First, parse the generic opengl version. This is supposed not to be convoluted with
553 * driver specific information
555 gl_string_cursor = gl_string;
556 major = atoi(gl_string_cursor);
557 if(major <= 0) {
558 ERR("Invalid opengl major version: %d\n", major);
560 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
561 ++gl_string_cursor;
563 if (*gl_string_cursor++ != '.') {
564 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
566 minor = atoi(gl_string_cursor);
567 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
568 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
570 /* Now parse the driver specific string which we'll report to the app */
571 switch (gl_info->gl_vendor) {
572 case VENDOR_NVIDIA:
573 gl_string_cursor = strstr(gl_string, "NVIDIA");
574 if (!gl_string_cursor) {
575 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
576 break;
579 gl_string_cursor = strstr(gl_string_cursor, " ");
580 if (!gl_string_cursor) {
581 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
582 break;
585 while (*gl_string_cursor == ' ') {
586 ++gl_string_cursor;
589 if (!*gl_string_cursor) {
590 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
591 break;
594 major = atoi(gl_string_cursor);
595 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
596 ++gl_string_cursor;
599 if (*gl_string_cursor++ != '.') {
600 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
601 break;
604 minor = atoi(gl_string_cursor);
605 minor = major*100+minor;
606 major = 10;
608 break;
610 case VENDOR_ATI:
611 major = minor = 0;
612 gl_string_cursor = strchr(gl_string, '-');
613 if (gl_string_cursor) {
614 int error = 0;
615 gl_string_cursor++;
617 /* Check if version number is of the form x.y.z */
618 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
619 error = 1;
620 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
621 error = 1;
622 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
623 error = 1;
624 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
625 error = 1;
627 /* Mark version number as malformed */
628 if (error)
629 gl_string_cursor = 0;
632 if (!gl_string_cursor)
633 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
634 else {
635 major = *gl_string_cursor - '0';
636 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
638 break;
640 case VENDOR_INTEL:
641 /* Apple and Mesa version strings look differently, but both provide intel drivers */
642 if(strstr(gl_string, "APPLE")) {
643 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
644 * We only need the first part, and use the APPLE as identification
645 * "1.2 APPLE-1.4.56"
647 gl_string_cursor = gl_string;
648 major = atoi(gl_string_cursor);
649 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
650 ++gl_string_cursor;
653 if (*gl_string_cursor++ != '.') {
654 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
655 break;
658 minor = atoi(gl_string_cursor);
659 break;
662 case VENDOR_MESA:
663 gl_string_cursor = strstr(gl_string, "Mesa");
664 gl_string_cursor = strstr(gl_string_cursor, " ");
665 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
666 if (*gl_string_cursor) {
667 char tmp[16];
668 int cursor = 0;
670 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
671 tmp[cursor++] = *gl_string_cursor;
672 ++gl_string_cursor;
674 tmp[cursor] = 0;
675 major = atoi(tmp);
677 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
678 ++gl_string_cursor;
680 cursor = 0;
681 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
682 tmp[cursor++] = *gl_string_cursor;
683 ++gl_string_cursor;
685 tmp[cursor] = 0;
686 minor = atoi(tmp);
688 break;
690 default:
691 major = 0;
692 minor = 9;
694 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
695 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
696 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
697 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
698 } else {
699 FIXME("OpenGL driver did not return version information\n");
700 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
701 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
704 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
707 * Initialize openGL extension related variables
708 * with Default values
710 memset(gl_info->supported, 0, sizeof(gl_info->supported));
711 gl_info->max_buffers = 1;
712 gl_info->max_textures = 1;
713 gl_info->max_texture_stages = 1;
714 gl_info->max_fragment_samplers = 1;
715 gl_info->max_vertex_samplers = 0;
716 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
717 gl_info->max_sampler_stages = 1;
718 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
719 gl_info->ps_arb_max_temps = 0;
720 gl_info->ps_arb_max_instructions = 0;
721 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
722 gl_info->vs_arb_max_temps = 0;
723 gl_info->vs_arb_max_instructions = 0;
724 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
725 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
726 gl_info->vs_glsl_constantsF = 0;
727 gl_info->ps_glsl_constantsF = 0;
728 gl_info->vs_arb_constantsF = 0;
729 gl_info->ps_arb_constantsF = 0;
731 /* Retrieve opengl defaults */
732 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
733 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
734 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
736 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
737 gl_info->max_lights = gl_max;
738 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
740 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
741 gl_info->max_texture_size = gl_max;
742 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
744 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
745 gl_info->max_pointsizemin = gl_floatv[0];
746 gl_info->max_pointsize = gl_floatv[1];
747 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
749 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
750 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
751 TRACE_(d3d_caps)("GL_Extensions reported:\n");
753 if (NULL == GL_Extensions) {
754 ERR(" GL_Extensions returns NULL\n");
755 } else {
756 while (*GL_Extensions != 0x00) {
757 const char *Start;
758 char ThisExtn[256];
759 size_t len;
761 while (isspace(*GL_Extensions)) GL_Extensions++;
762 Start = GL_Extensions;
763 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
764 GL_Extensions++;
767 len = GL_Extensions - Start;
768 if (len == 0 || len >= sizeof(ThisExtn))
769 continue;
771 memcpy(ThisExtn, Start, len);
772 ThisExtn[len] = '\0';
773 TRACE_(d3d_caps)("- %s\n", ThisExtn);
775 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
776 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
777 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
778 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
779 break;
784 LEAVE_GL();
786 /* Now work out what GL support this card really has */
787 #define USE_GL_FUNC(type, pfn, ext, replace) { \
788 DWORD ver = ver_for_ext(ext); \
789 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
790 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
791 else gl_info->pfn = NULL; \
793 GL_EXT_FUNCS_GEN;
794 #undef USE_GL_FUNC
796 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
797 WGL_EXT_FUNCS_GEN;
798 #undef USE_GL_FUNC
800 ENTER_GL();
801 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
802 * loading the functions, otherwise the code above will load the extension entry points instead of the
803 * core functions, which may not work
805 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
806 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
807 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
808 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
809 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
813 if (gl_info->supported[APPLE_FENCE]) {
814 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
815 * The apple extension interacts with some other apple exts. Disable the NV
816 * extension if the apple one is support to prevent confusion in other parts
817 * of the code
819 gl_info->supported[NV_FENCE] = FALSE;
821 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
822 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
824 * The enums are the same:
825 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
826 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
827 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
828 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
829 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
831 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
832 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
833 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
835 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
836 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
837 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
840 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
841 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
842 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
844 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
845 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
846 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
847 * are supported. The nv extensions provide the same functionality as the
848 * ATI one, and a bit more(signed pixelformats)
850 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
853 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
854 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
855 gl_info->max_buffers = gl_max;
856 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
858 if (gl_info->supported[ARB_MULTITEXTURE]) {
859 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
860 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
861 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
863 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
864 GLint tmp;
865 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
866 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
867 } else {
868 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
870 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
872 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
873 GLint tmp;
874 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
875 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
876 } else {
877 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
879 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
881 if (gl_info->supported[ARB_VERTEX_SHADER]) {
882 GLint tmp;
883 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
884 gl_info->max_vertex_samplers = tmp;
885 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
886 gl_info->max_combined_samplers = tmp;
888 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
889 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
890 * an issue because then the sampler setup only depends on the two shaders. If a pixel
891 * shader is used with fixed function vertex processing we're fine too because fixed function
892 * vertex processing doesn't use any samplers. If fixed function fragment processing is
893 * used we have to make sure that all vertex sampler setups are valid together with all
894 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
895 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
896 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
897 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
898 * a fixed function pipeline anymore.
900 * So this is just a check to check that our assumption holds true. If not, write a warning
901 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
903 if(gl_info->max_vertex_samplers &&
904 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
905 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
906 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
907 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
908 if( gl_info->max_combined_samplers > MAX_TEXTURES )
909 gl_info->max_vertex_samplers =
910 gl_info->max_combined_samplers - MAX_TEXTURES;
911 else
912 gl_info->max_vertex_samplers = 0;
914 } else {
915 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
917 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
918 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
920 if (gl_info->supported[ARB_VERTEX_BLEND]) {
921 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
922 gl_info->max_blends = gl_max;
923 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
925 if (gl_info->supported[EXT_TEXTURE3D]) {
926 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
927 gl_info->max_texture3d_size = gl_max;
928 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
930 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
931 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
932 gl_info->max_anisotropy = gl_max;
933 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
935 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
936 gl_info->ps_arb_version = PS_VERSION_11;
937 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
938 gl_info->ps_arb_constantsF = gl_max;
939 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
940 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
941 gl_info->ps_arb_max_temps = gl_max;
942 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
943 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
944 gl_info->ps_arb_max_instructions = gl_max;
945 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
947 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
948 gl_info->vs_arb_version = VS_VERSION_11;
949 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
950 gl_info->vs_arb_constantsF = gl_max;
951 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
952 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
953 gl_info->vs_arb_max_temps = gl_max;
954 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
955 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
956 gl_info->vs_arb_max_instructions = gl_max;
957 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
959 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
961 if (gl_info->supported[ARB_VERTEX_SHADER]) {
962 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
963 gl_info->vs_glsl_constantsF = gl_max / 4;
964 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
966 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
967 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
968 gl_info->ps_glsl_constantsF = gl_max / 4;
969 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
970 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
971 gl_info->max_glsl_varyings = gl_max;
972 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
974 if (gl_info->supported[EXT_VERTEX_SHADER]) {
975 gl_info->vs_ati_version = VS_VERSION_11;
977 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
978 gl_info->vs_nv_version = VS_VERSION_30;
979 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
980 gl_info->vs_nv_version = VS_VERSION_20;
981 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
982 gl_info->vs_nv_version = VS_VERSION_11;
983 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
984 gl_info->vs_nv_version = VS_VERSION_10;
986 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
987 gl_info->ps_nv_version = PS_VERSION_30;
988 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
989 gl_info->ps_nv_version = PS_VERSION_20;
991 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
992 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
993 } else {
994 gl_info->max_shininess = 128.0;
996 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
997 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
998 * This saves a few redundant glDisable calls
1000 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1002 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1003 /* Disable NV_register_combiners and fragment shader if this is supported.
1004 * generally the NV extensions are preferred over the ATI ones, and this
1005 * extension is disabled if register_combiners and texture_shader2 are both
1006 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1007 * fragment processing support
1009 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1010 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1011 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1012 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1013 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1017 checkGLcall("extension detection\n");
1019 /* In some cases the number of texture stages can be larger than the number
1020 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1021 * shaders), but 8 texture stages (register combiners). */
1022 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1024 /* We can only use ORM_FBO when the hardware supports it. */
1025 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1026 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
1027 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
1030 /* MRTs are currently only supported when FBOs are used. */
1031 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1032 gl_info->max_buffers = 1;
1035 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1036 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1037 * in case of the latest videocards in the number of pixel/vertex pipelines.
1039 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1040 * rendering. Various games use this information to get a rough estimation of the features of the card
1041 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1042 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1043 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1044 * not the PCI id.
1046 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1047 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1048 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1049 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1050 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1051 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1052 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1053 * is limited.
1055 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1056 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1057 * similar 3d features.
1059 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1060 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1061 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1062 * won't pass we return a default card. This way is better than maintaining a full card database as even
1063 * without a full database we can return a card with similar features. Second the size of the database
1064 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1065 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1066 * to distinguishes between different models from that family.
1068 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1069 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1070 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1071 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1072 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1073 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1074 * memory behind our backs if really needed.
1075 * Note that the amount of video memory can be overruled using a registry setting.
1077 switch (gl_info->gl_vendor) {
1078 case VENDOR_NVIDIA:
1079 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1080 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1082 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1083 /* Geforce GTX - highend */
1084 if(strstr(gl_info->gl_renderer, "GTX 280")) {
1085 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1086 vidmem = 1024;
1088 /* Geforce9 - highend */
1089 else if(strstr(gl_info->gl_renderer, "9800")) {
1090 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1091 vidmem = 512;
1093 /* Geforce9 - midend */
1094 else if(strstr(gl_info->gl_renderer, "9600")) {
1095 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1096 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1098 /* Geforce8 - highend */
1099 else if (strstr(gl_info->gl_renderer, "8800")) {
1100 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1101 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1103 /* Geforce8 - midend mobile */
1104 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1105 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1106 vidmem = 512;
1108 /* Geforce8 - midend */
1109 else if(strstr(gl_info->gl_renderer, "8600") ||
1110 strstr(gl_info->gl_renderer, "8700"))
1112 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1113 vidmem = 256;
1115 /* Geforce8 - lowend */
1116 else if(strstr(gl_info->gl_renderer, "8300") ||
1117 strstr(gl_info->gl_renderer, "8400") ||
1118 strstr(gl_info->gl_renderer, "8500"))
1120 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1121 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1123 /* Geforce7 - highend */
1124 else if(strstr(gl_info->gl_renderer, "7800") ||
1125 strstr(gl_info->gl_renderer, "7900") ||
1126 strstr(gl_info->gl_renderer, "7950") ||
1127 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1128 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1130 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1131 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1133 /* Geforce7 midend */
1134 else if(strstr(gl_info->gl_renderer, "7600") ||
1135 strstr(gl_info->gl_renderer, "7700")) {
1136 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1137 vidmem = 256; /* The 7600 uses 256-512MB */
1138 /* Geforce7 lower medium */
1139 } else if(strstr(gl_info->gl_renderer, "7400")) {
1140 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1141 vidmem = 256; /* The 7400 uses 256-512MB */
1143 /* Geforce7 lowend */
1144 else if(strstr(gl_info->gl_renderer, "7300")) {
1145 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1146 vidmem = 256; /* Mac Pros with this card have 256 MB */
1148 /* Geforce6 highend */
1149 else if(strstr(gl_info->gl_renderer, "6800"))
1151 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1152 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1154 /* Geforce6 - midend */
1155 else if(strstr(gl_info->gl_renderer, "6600") ||
1156 strstr(gl_info->gl_renderer, "6610") ||
1157 strstr(gl_info->gl_renderer, "6700"))
1159 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1160 vidmem = 128; /* A 6600GT has 128-256MB */
1162 /* Geforce6/7 lowend */
1163 else {
1164 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1165 vidmem = 64; /* */
1167 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1168 /* GeforceFX - highend */
1169 if (strstr(gl_info->gl_renderer, "5800") ||
1170 strstr(gl_info->gl_renderer, "5900") ||
1171 strstr(gl_info->gl_renderer, "5950") ||
1172 strstr(gl_info->gl_renderer, "Quadro FX"))
1174 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1175 vidmem = 256; /* 5800-5900 cards use 256MB */
1177 /* GeforceFX - midend */
1178 else if(strstr(gl_info->gl_renderer, "5600") ||
1179 strstr(gl_info->gl_renderer, "5650") ||
1180 strstr(gl_info->gl_renderer, "5700") ||
1181 strstr(gl_info->gl_renderer, "5750"))
1183 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1184 vidmem = 128; /* A 5600 uses 128-256MB */
1186 /* GeforceFX - lowend */
1187 else {
1188 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1189 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1191 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1192 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1193 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1194 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1196 else {
1197 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1198 vidmem = 64; /* Geforce3 cards have 64-128MB */
1200 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1201 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1202 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1203 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1205 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1206 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1207 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1209 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1210 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1211 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1213 else {
1214 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1215 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1217 } else {
1218 if (strstr(gl_info->gl_renderer, "TNT2")) {
1219 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1220 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1222 else {
1223 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1224 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1227 break;
1228 case VENDOR_ATI:
1229 if(WINE_D3D9_CAPABLE(gl_info)) {
1230 /* Radeon R6xx HD2900/HD3800 - highend */
1231 if (strstr(gl_info->gl_renderer, "HD 2900") ||
1232 strstr(gl_info->gl_renderer, "HD 3870") ||
1233 strstr(gl_info->gl_renderer, "HD 3850"))
1235 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1236 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1238 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1239 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1240 strstr(gl_info->gl_renderer, "HD 3830") ||
1241 strstr(gl_info->gl_renderer, "HD 3690") ||
1242 strstr(gl_info->gl_renderer, "HD 3650"))
1244 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1245 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1247 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1248 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1249 strstr(gl_info->gl_renderer, "HD 2400") ||
1250 strstr(gl_info->gl_renderer, "HD 3470") ||
1251 strstr(gl_info->gl_renderer, "HD 3450") ||
1252 strstr(gl_info->gl_renderer, "HD 3430"))
1254 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1255 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1257 /* Radeon R6xx/R7xx integrated */
1258 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1259 strstr(gl_info->gl_renderer, "HD 3200") ||
1260 strstr(gl_info->gl_renderer, "HD 3300"))
1262 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1263 vidmem = 128; /* 128MB */
1265 /* Radeon R5xx */
1266 else if (strstr(gl_info->gl_renderer, "X1600") ||
1267 strstr(gl_info->gl_renderer, "X1650") ||
1268 strstr(gl_info->gl_renderer, "X1800") ||
1269 strstr(gl_info->gl_renderer, "X1900") ||
1270 strstr(gl_info->gl_renderer, "X1950"))
1272 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1273 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1275 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1276 else if(strstr(gl_info->gl_renderer, "X700") ||
1277 strstr(gl_info->gl_renderer, "X800") ||
1278 strstr(gl_info->gl_renderer, "X850") ||
1279 strstr(gl_info->gl_renderer, "X1300") ||
1280 strstr(gl_info->gl_renderer, "X1400") ||
1281 strstr(gl_info->gl_renderer, "X1450") ||
1282 strstr(gl_info->gl_renderer, "X1550"))
1284 gl_info->gl_card = CARD_ATI_RADEON_X700;
1285 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1287 /* Radeon R3xx */
1288 else {
1289 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1290 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1292 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1293 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1294 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1295 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1296 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1297 vidmem = 32; /* There are models with up to 64MB */
1298 } else {
1299 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1300 vidmem = 16; /* There are 16-32MB models */
1302 break;
1303 case VENDOR_INTEL:
1304 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1305 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1306 gl_info->gl_card = CARD_INTEL_I945GM;
1307 vidmem = 64;
1308 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1309 gl_info->gl_card = CARD_INTEL_I915GM;
1310 } else if (strstr(gl_info->gl_renderer, "915G")) {
1311 gl_info->gl_card = CARD_INTEL_I915G;
1312 } else if (strstr(gl_info->gl_renderer, "865G")) {
1313 gl_info->gl_card = CARD_INTEL_I865G;
1314 } else if (strstr(gl_info->gl_renderer, "855G")) {
1315 gl_info->gl_card = CARD_INTEL_I855G;
1316 } else if (strstr(gl_info->gl_renderer, "830G")) {
1317 gl_info->gl_card = CARD_INTEL_I830G;
1318 } else {
1319 gl_info->gl_card = CARD_INTEL_I915G;
1321 break;
1322 case VENDOR_MESA:
1323 case VENDOR_WINE:
1324 default:
1325 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1326 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1327 * them a good generic choice.
1329 gl_info->gl_vendor = VENDOR_NVIDIA;
1330 if(WINE_D3D9_CAPABLE(gl_info))
1331 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1332 else if(WINE_D3D8_CAPABLE(gl_info))
1333 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1334 else if(WINE_D3D7_CAPABLE(gl_info))
1335 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1336 else if(WINE_D3D6_CAPABLE(gl_info))
1337 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1338 else
1339 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1341 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1343 /* If we have an estimate use it, else default to 64MB; */
1344 if(vidmem)
1345 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1346 else
1347 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1349 /* Load all the lookup tables */
1350 for (i = 0; i < MAX_LOOKUPS; i++) {
1351 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1354 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1355 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1356 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1357 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1358 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1359 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1360 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1361 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1362 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1363 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1365 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1366 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1367 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1368 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1369 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1372 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1373 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1374 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1375 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1376 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1377 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1378 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1379 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1380 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1381 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1382 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1383 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1384 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1385 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1386 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1388 /* TODO: config lookups */
1390 /* Make sure there's an active HDC else the WGL extensions will fail */
1391 hdc = pwglGetCurrentDC();
1392 if (hdc) {
1393 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1394 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1396 if (NULL == WGL_Extensions) {
1397 ERR(" WGL_Extensions returns NULL\n");
1398 } else {
1399 while (*WGL_Extensions != 0x00) {
1400 const char *Start;
1401 char ThisExtn[256];
1402 size_t len;
1404 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1405 Start = WGL_Extensions;
1406 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1407 WGL_Extensions++;
1410 len = WGL_Extensions - Start;
1411 if (len == 0 || len >= sizeof(ThisExtn))
1412 continue;
1414 memcpy(ThisExtn, Start, len);
1415 ThisExtn[len] = '\0';
1416 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1418 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1419 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1420 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1422 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1423 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1424 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1429 LEAVE_GL();
1431 return return_value;
1433 #undef GLINFO_LOCATION
1435 /**********************************************************
1436 * IWineD3D implementation follows
1437 **********************************************************/
1439 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1440 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1442 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1443 return numAdapters;
1446 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1447 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1448 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1449 return WINED3D_OK;
1452 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1453 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1455 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1457 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1458 return NULL;
1461 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1464 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1465 of the same bpp but different resolutions */
1467 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1468 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1469 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1470 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1472 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1473 return 0;
1476 /* TODO: Store modes per adapter and read it from the adapter structure */
1477 if (Adapter == 0) { /* Display */
1478 int i = 0;
1479 int j = 0;
1481 if (!DEBUG_SINGLE_MODE) {
1482 DEVMODEW DevModeW;
1484 ZeroMemory(&DevModeW, sizeof(DevModeW));
1485 DevModeW.dmSize = sizeof(DevModeW);
1486 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1487 j++;
1488 switch (Format)
1490 case WINED3DFMT_UNKNOWN:
1491 /* This is for D3D8, do not enumerate P8 here */
1492 if (DevModeW.dmBitsPerPel == 32 ||
1493 DevModeW.dmBitsPerPel == 16) i++;
1494 break;
1495 case WINED3DFMT_X8R8G8B8:
1496 if (DevModeW.dmBitsPerPel == 32) i++;
1497 break;
1498 case WINED3DFMT_R5G6B5:
1499 if (DevModeW.dmBitsPerPel == 16) i++;
1500 break;
1501 case WINED3DFMT_P8:
1502 if (DevModeW.dmBitsPerPel == 8) i++;
1503 break;
1504 default:
1505 /* Skip other modes as they do not match the requested format */
1506 break;
1509 } else {
1510 i = 1;
1511 j = 1;
1514 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1515 return i;
1516 } else {
1517 FIXME_(d3d_caps)("Adapter not primary display\n");
1519 return 0;
1522 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1523 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1524 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1525 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1527 /* Validate the parameters as much as possible */
1528 if (NULL == pMode ||
1529 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1530 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1531 return WINED3DERR_INVALIDCALL;
1534 /* TODO: Store modes per adapter and read it from the adapter structure */
1535 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1536 DEVMODEW DevModeW;
1537 int ModeIdx = 0;
1538 UINT i = 0;
1539 int j = 0;
1541 ZeroMemory(&DevModeW, sizeof(DevModeW));
1542 DevModeW.dmSize = sizeof(DevModeW);
1544 /* If we are filtering to a specific format (D3D9), then need to skip
1545 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1546 just count through the ones with valid bit depths */
1547 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1548 switch (Format)
1550 case WINED3DFMT_UNKNOWN:
1551 /* This is D3D8. Do not enumerate P8 here */
1552 if (DevModeW.dmBitsPerPel == 32 ||
1553 DevModeW.dmBitsPerPel == 16) i++;
1554 break;
1555 case WINED3DFMT_X8R8G8B8:
1556 if (DevModeW.dmBitsPerPel == 32) i++;
1557 break;
1558 case WINED3DFMT_R5G6B5:
1559 if (DevModeW.dmBitsPerPel == 16) i++;
1560 break;
1561 case WINED3DFMT_P8:
1562 if (DevModeW.dmBitsPerPel == 8) i++;
1563 break;
1564 default:
1565 /* Modes that don't match what we support can get an early-out */
1566 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1567 return WINED3DERR_INVALIDCALL;
1571 if (i == 0) {
1572 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1573 return WINED3DERR_INVALIDCALL;
1575 ModeIdx = j - 1;
1577 /* Now get the display mode via the calculated index */
1578 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1579 pMode->Width = DevModeW.dmPelsWidth;
1580 pMode->Height = DevModeW.dmPelsHeight;
1581 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1582 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1583 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1585 if (Format == WINED3DFMT_UNKNOWN) {
1586 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1587 } else {
1588 pMode->Format = Format;
1590 } else {
1591 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1592 return WINED3DERR_INVALIDCALL;
1595 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1596 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1597 DevModeW.dmBitsPerPel);
1599 } else if (DEBUG_SINGLE_MODE) {
1600 /* Return one setting of the format requested */
1601 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1602 pMode->Width = 800;
1603 pMode->Height = 600;
1604 pMode->RefreshRate = 60;
1605 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1606 } else {
1607 FIXME_(d3d_caps)("Adapter not primary display\n");
1610 return WINED3D_OK;
1613 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1614 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1615 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1617 if (NULL == pMode ||
1618 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1619 return WINED3DERR_INVALIDCALL;
1622 if (Adapter == 0) { /* Display */
1623 int bpp = 0;
1624 DEVMODEW DevModeW;
1626 ZeroMemory(&DevModeW, sizeof(DevModeW));
1627 DevModeW.dmSize = sizeof(DevModeW);
1629 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1630 pMode->Width = DevModeW.dmPelsWidth;
1631 pMode->Height = DevModeW.dmPelsHeight;
1632 bpp = DevModeW.dmBitsPerPel;
1633 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1634 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1636 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1639 pMode->Format = pixelformat_for_depth(bpp);
1640 } else {
1641 FIXME_(d3d_caps)("Adapter not primary display\n");
1644 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1645 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1646 return WINED3D_OK;
1649 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1650 and fields being inserted in the middle, a new structure is used in place */
1651 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1652 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1653 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1655 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1657 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1658 return WINED3DERR_INVALIDCALL;
1661 /* Return the information requested */
1662 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1663 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1664 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1666 /* Note dx8 doesn't supply a DeviceName */
1667 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1668 pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart;
1669 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version;
1670 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1671 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1672 *(pIdentifier->SubSysId) = 0;
1673 *(pIdentifier->Revision) = 0;
1674 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1676 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1678 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1679 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1682 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1684 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1685 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1688 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1689 *(pIdentifier->WHQLLevel) = 0;
1690 } else {
1691 *(pIdentifier->WHQLLevel) = 1;
1694 return WINED3D_OK;
1697 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1698 short redSize, greenSize, blueSize, alphaSize, colorBits;
1700 if(!cfg)
1701 return FALSE;
1703 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1704 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1705 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1706 return FALSE;
1709 if(cfg->redSize < redSize)
1710 return FALSE;
1712 if(cfg->greenSize < greenSize)
1713 return FALSE;
1715 if(cfg->blueSize < blueSize)
1716 return FALSE;
1718 if(cfg->alphaSize < alphaSize)
1719 return FALSE;
1721 return TRUE;
1722 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1723 if(Format == WINED3DFMT_R16F)
1724 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1725 if(Format == WINED3DFMT_G16R16F)
1726 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1727 if(Format == WINED3DFMT_A16B16G16R16F)
1728 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1729 if(Format == WINED3DFMT_R32F)
1730 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1731 if(Format == WINED3DFMT_G32R32F)
1732 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1733 if(Format == WINED3DFMT_A32B32G32R32F)
1734 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1735 } else {
1736 /* Probably a color index mode */
1737 return FALSE;
1740 return FALSE;
1743 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1744 short depthSize, stencilSize;
1745 BOOL lockable = FALSE;
1747 if(!cfg)
1748 return FALSE;
1750 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1751 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1752 return FALSE;
1755 if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE))
1756 lockable = TRUE;
1758 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1759 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1760 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1761 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1762 return FALSE;
1764 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1765 * allow more stencil bits than requested. */
1766 if(cfg->stencilSize < stencilSize)
1767 return FALSE;
1769 return TRUE;
1772 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1773 WINED3DFORMAT AdapterFormat,
1774 WINED3DFORMAT RenderTargetFormat,
1775 WINED3DFORMAT DepthStencilFormat) {
1776 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1777 int nCfgs;
1778 const WineD3D_PixelFormat *cfgs;
1779 int it;
1781 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1782 This, Adapter,
1783 DeviceType, debug_d3ddevicetype(DeviceType),
1784 AdapterFormat, debug_d3dformat(AdapterFormat),
1785 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1786 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1788 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1789 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1790 return WINED3DERR_INVALIDCALL;
1793 cfgs = Adapters[Adapter].cfgs;
1794 nCfgs = Adapters[Adapter].nCfgs;
1795 for (it = 0; it < nCfgs; ++it) {
1796 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1797 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1798 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1799 return WINED3D_OK;
1803 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1805 return WINED3DERR_NOTAVAILABLE;
1808 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1809 WINED3DFORMAT SurfaceFormat,
1810 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1812 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1813 const struct GlPixelFormatDesc *glDesc;
1814 const StaticPixelFormatDesc *desc;
1816 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1817 This,
1818 Adapter,
1819 DeviceType, debug_d3ddevicetype(DeviceType),
1820 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1821 Windowed,
1822 MultiSampleType,
1823 pQualityLevels);
1825 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1826 return WINED3DERR_INVALIDCALL;
1829 /* TODO: handle Windowed, add more quality levels */
1831 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1833 /* By default multisampling is disabled right now as it causes issues
1834 * on some Nvidia driver versions and it doesn't work well in combination
1835 * with FBOs yet. */
1836 if(!wined3d_settings.allow_multisampling)
1837 return WINED3DERR_NOTAVAILABLE;
1839 desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc);
1840 if(!desc || !glDesc) {
1841 return WINED3DERR_INVALIDCALL;
1844 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1845 int i, nCfgs;
1846 const WineD3D_PixelFormat *cfgs;
1848 cfgs = Adapters[Adapter].cfgs;
1849 nCfgs = Adapters[Adapter].nCfgs;
1850 for(i=0; i<nCfgs; i++) {
1851 if(cfgs[i].numSamples != MultiSampleType)
1852 continue;
1854 if(!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[i], SurfaceFormat))
1855 continue;
1857 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1859 if(pQualityLevels)
1860 *pQualityLevels = 1; /* Guess at a value! */
1861 return WINED3D_OK;
1864 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1865 short redSize, greenSize, blueSize, alphaSize, colorBits;
1866 int i, nCfgs;
1867 const WineD3D_PixelFormat *cfgs;
1869 if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1870 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1871 return WINED3DERR_NOTAVAILABLE;
1874 cfgs = Adapters[Adapter].cfgs;
1875 nCfgs = Adapters[Adapter].nCfgs;
1876 for(i=0; i<nCfgs; i++) {
1877 if(cfgs[i].numSamples != MultiSampleType)
1878 continue;
1879 if(cfgs[i].redSize != redSize)
1880 continue;
1881 if(cfgs[i].greenSize != greenSize)
1882 continue;
1883 if(cfgs[i].blueSize != blueSize)
1884 continue;
1885 if(cfgs[i].alphaSize != alphaSize)
1886 continue;
1888 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1890 if(pQualityLevels)
1891 *pQualityLevels = 1; /* Guess at a value! */
1892 return WINED3D_OK;
1895 return WINED3DERR_NOTAVAILABLE;
1898 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1899 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1901 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1902 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1903 UINT nmodes;
1905 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1906 This,
1907 Adapter,
1908 DeviceType, debug_d3ddevicetype(DeviceType),
1909 DisplayFormat, debug_d3dformat(DisplayFormat),
1910 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1911 Windowed);
1913 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1914 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1915 return WINED3DERR_INVALIDCALL;
1918 /* The task of this function is to check whether a certain display / backbuffer format
1919 * combination is available on the given adapter. In fullscreen mode microsoft specified
1920 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
1921 * and display format should match exactly.
1922 * In windowed mode format conversion can occur and this depends on the driver. When format
1923 * conversion is done, this function should nevertheless fail and applications need to use
1924 * CheckDeviceFormatConversion.
1925 * At the moment we assume that fullscreen and windowed have the same capabilities */
1927 /* There are only 4 display formats */
1928 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
1929 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
1930 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
1931 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
1933 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
1934 return WINED3DERR_NOTAVAILABLE;
1937 /* If the requested DisplayFormat is not available, don't continue */
1938 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
1939 if(!nmodes) {
1940 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
1941 return WINED3DERR_NOTAVAILABLE;
1944 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
1945 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
1946 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
1947 return WINED3DERR_NOTAVAILABLE;
1950 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
1951 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
1952 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1953 return WINED3DERR_NOTAVAILABLE;
1956 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
1957 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
1958 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1959 return WINED3DERR_NOTAVAILABLE;
1962 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
1963 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
1964 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1965 return WINED3DERR_NOTAVAILABLE;
1968 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
1969 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
1970 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1971 return WINED3DERR_NOTAVAILABLE;
1974 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
1975 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
1976 if(FAILED(hr))
1977 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1979 return hr;
1983 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1984 /* Check if we support bumpmapping for a format */
1985 static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
1987 const struct fragment_pipeline *fp;
1988 const struct GlPixelFormatDesc *glDesc;
1990 switch(CheckFormat) {
1991 case WINED3DFMT_V8U8:
1992 case WINED3DFMT_V16U16:
1993 case WINED3DFMT_L6V5U5:
1994 case WINED3DFMT_X8L8V8U8:
1995 case WINED3DFMT_Q8W8V8U8:
1996 /* Ask the fixed function pipeline implementation if it can deal
1997 * with the conversion. If we've got a GL extension giving native
1998 * support this will be an identity conversion. */
1999 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2000 fp = select_fragment_implementation(Adapter, DeviceType);
2001 if (fp->color_fixup_supported(glDesc->color_fixup))
2003 TRACE_(d3d_caps)("[OK]\n");
2004 return TRUE;
2006 TRACE_(d3d_caps)("[FAILED]\n");
2007 return FALSE;
2009 default:
2010 TRACE_(d3d_caps)("[FAILED]\n");
2011 return FALSE;
2015 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2016 static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
2018 int it=0;
2019 const struct GlPixelFormatDesc *glDesc;
2020 const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc);
2022 /* Fail if we weren't able to get a description of the format */
2023 if(!desc || !glDesc)
2024 return FALSE;
2026 /* Only allow depth/stencil formats */
2027 if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2028 return FALSE;
2030 /* Walk through all WGL pixel formats to find a match */
2031 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2032 WineD3D_PixelFormat *cfg = &Adapters[Adapter].cfgs[it];
2033 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(cfg, DisplayFormat)) {
2034 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(cfg, DepthStencilFormat)) {
2035 return TRUE;
2040 return FALSE;
2043 static BOOL CheckFilterCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2045 const struct GlPixelFormatDesc *glDesc;
2046 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2048 /* Fail if we weren't able to get a description of the format */
2049 if(!desc || !glDesc)
2050 return FALSE;
2052 /* The flags entry of a format contains the filtering capability */
2053 if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING)
2054 return TRUE;
2056 return FALSE;
2059 /* Check the render target capabilities of a format */
2060 static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat)
2062 UINT Adapter = 0;
2063 const struct GlPixelFormatDesc *glDesc;
2064 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2066 /* Fail if we weren't able to get a description of the format */
2067 if(!desc || !glDesc)
2068 return FALSE;
2070 /* Filter out non-RT formats */
2071 if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET))
2072 return FALSE;
2074 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2075 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2076 int it;
2077 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2078 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2080 getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2081 getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2083 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2084 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2085 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2086 TRACE_(d3d_caps)("[FAILED]\n");
2087 return FALSE;
2090 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2091 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2092 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2093 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2094 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2095 return TRUE;
2098 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2099 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2100 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2101 int it;
2103 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2104 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2105 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2106 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2107 return TRUE;
2110 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2111 /* For now return TRUE for FBOs until we have some proper checks.
2112 * Note that this function will only be called when the format is around for texturing. */
2113 return TRUE;
2115 return FALSE;
2118 static BOOL CheckSrgbReadCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2120 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2121 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2122 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2123 return FALSE;
2126 switch (CheckFormat) {
2127 case WINED3DFMT_A8R8G8B8:
2128 case WINED3DFMT_X8R8G8B8:
2129 case WINED3DFMT_A4R4G4B4:
2130 case WINED3DFMT_L8:
2131 case WINED3DFMT_A8L8:
2132 case WINED3DFMT_DXT1:
2133 case WINED3DFMT_DXT2:
2134 case WINED3DFMT_DXT3:
2135 case WINED3DFMT_DXT4:
2136 case WINED3DFMT_DXT5:
2137 TRACE_(d3d_caps)("[OK]\n");
2138 return TRUE;
2140 default:
2141 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
2142 return FALSE;
2144 return FALSE;
2147 static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2149 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2150 * doing the color fixup in shaders.
2151 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2152 if((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) {
2153 int vs_selected_mode;
2154 int ps_selected_mode;
2155 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
2157 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2158 TRACE_(d3d_caps)("[OK]\n");
2159 return TRUE;
2163 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
2164 return FALSE;
2167 /* Check if a format support blending in combination with pixel shaders */
2168 static BOOL CheckPostPixelShaderBlendingCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2170 const struct GlPixelFormatDesc *glDesc;
2171 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2173 /* Fail if we weren't able to get a description of the format */
2174 if(!desc || !glDesc)
2175 return FALSE;
2177 /* The flags entry of a format contains the post pixel shader blending capability */
2178 if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2179 return TRUE;
2181 return FALSE;
2184 static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
2185 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2186 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2187 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2188 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2189 * capability anyway.
2191 * For now lets report this on all formats, but in the future we may want to
2192 * restrict it to some should games need that
2194 return TRUE;
2197 /* Check if a texture format is supported on the given adapter */
2198 static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2200 const shader_backend_t *shader_backend;
2201 const struct fragment_pipeline *fp;
2202 const struct GlPixelFormatDesc *glDesc;
2204 switch (CheckFormat) {
2206 /*****
2207 * supported: RGB(A) formats
2209 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2210 case WINED3DFMT_A8R8G8B8:
2211 case WINED3DFMT_X8R8G8B8:
2212 case WINED3DFMT_R5G6B5:
2213 case WINED3DFMT_X1R5G5B5:
2214 case WINED3DFMT_A1R5G5B5:
2215 case WINED3DFMT_A4R4G4B4:
2216 case WINED3DFMT_A8:
2217 case WINED3DFMT_X4R4G4B4:
2218 case WINED3DFMT_A8B8G8R8:
2219 case WINED3DFMT_X8B8G8R8:
2220 case WINED3DFMT_A2R10G10B10:
2221 case WINED3DFMT_A2B10G10R10:
2222 case WINED3DFMT_G16R16:
2223 TRACE_(d3d_caps)("[OK]\n");
2224 return TRUE;
2226 case WINED3DFMT_R3G3B2:
2227 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2228 return FALSE;
2230 /*****
2231 * supported: Palettized
2233 case WINED3DFMT_P8:
2234 TRACE_(d3d_caps)("[OK]\n");
2235 return TRUE;
2236 /* No Windows driver offers A8P8, so don't offer it either */
2237 case WINED3DFMT_A8P8:
2238 return FALSE;
2240 /*****
2241 * Supported: (Alpha)-Luminance
2243 case WINED3DFMT_L8:
2244 case WINED3DFMT_A8L8:
2245 case WINED3DFMT_L16:
2246 TRACE_(d3d_caps)("[OK]\n");
2247 return TRUE;
2249 /* Not supported on Windows, thus disabled */
2250 case WINED3DFMT_A4L4:
2251 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2252 return FALSE;
2254 /*****
2255 * Supported: Depth/Stencil formats
2257 case WINED3DFMT_D16_LOCKABLE:
2258 case WINED3DFMT_D16:
2259 case WINED3DFMT_D15S1:
2260 case WINED3DFMT_D24X8:
2261 case WINED3DFMT_D24X4S4:
2262 case WINED3DFMT_D24S8:
2263 case WINED3DFMT_D24FS8:
2264 case WINED3DFMT_D32:
2265 case WINED3DFMT_D32F_LOCKABLE:
2266 return TRUE;
2268 /*****
2269 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2270 * GL_NV_texture_shader). Emulated by shaders
2272 case WINED3DFMT_V8U8:
2273 case WINED3DFMT_X8L8V8U8:
2274 case WINED3DFMT_L6V5U5:
2275 case WINED3DFMT_Q8W8V8U8:
2276 case WINED3DFMT_V16U16:
2277 /* Ask the shader backend if it can deal with the conversion. If
2278 * we've got a GL extension giving native support this will be an
2279 * identity conversion. */
2280 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2281 shader_backend = select_shader_backend(Adapter, DeviceType);
2282 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup))
2284 TRACE_(d3d_caps)("[OK]\n");
2285 return TRUE;
2287 TRACE_(d3d_caps)("[FAILED]\n");
2288 return FALSE;
2290 case WINED3DFMT_DXT1:
2291 case WINED3DFMT_DXT2:
2292 case WINED3DFMT_DXT3:
2293 case WINED3DFMT_DXT4:
2294 case WINED3DFMT_DXT5:
2295 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2296 TRACE_(d3d_caps)("[OK]\n");
2297 return TRUE;
2299 TRACE_(d3d_caps)("[FAILED]\n");
2300 return FALSE;
2303 /*****
2304 * Odd formats - not supported
2306 case WINED3DFMT_VERTEXDATA:
2307 case WINED3DFMT_INDEX16:
2308 case WINED3DFMT_INDEX32:
2309 case WINED3DFMT_Q16W16V16U16:
2310 case WINED3DFMT_A2W10V10U10:
2311 case WINED3DFMT_W11V11U10:
2312 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2313 return FALSE;
2315 /*****
2316 * WINED3DFMT_CxV8U8: Not supported right now
2318 case WINED3DFMT_CxV8U8:
2319 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2320 return FALSE;
2322 /* YUV formats */
2323 case WINED3DFMT_UYVY:
2324 case WINED3DFMT_YUY2:
2325 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2326 TRACE_(d3d_caps)("[OK]\n");
2327 return TRUE;
2329 TRACE_(d3d_caps)("[FAILED]\n");
2330 return FALSE;
2331 case WINED3DFMT_YV12:
2332 TRACE_(d3d_caps)("[FAILED]\n");
2333 return FALSE;
2335 /* Not supported */
2336 case WINED3DFMT_A16B16G16R16:
2337 case WINED3DFMT_A8R3G3B2:
2338 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2339 return FALSE;
2341 /* Floating point formats */
2342 case WINED3DFMT_R16F:
2343 case WINED3DFMT_A16B16G16R16F:
2344 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2345 TRACE_(d3d_caps)("[OK]\n");
2346 return TRUE;
2348 TRACE_(d3d_caps)("[FAILED]\n");
2349 return FALSE;
2351 case WINED3DFMT_R32F:
2352 case WINED3DFMT_A32B32G32R32F:
2353 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2354 TRACE_(d3d_caps)("[OK]\n");
2355 return TRUE;
2357 TRACE_(d3d_caps)("[FAILED]\n");
2358 return FALSE;
2360 case WINED3DFMT_G16R16F:
2361 case WINED3DFMT_G32R32F:
2362 TRACE_(d3d_caps)("[FAILED]\n");
2363 return FALSE;
2365 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2366 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2367 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2368 * We can do instancing with all shader versions, but we need vertex shaders.
2370 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2371 * to enable instancing. WineD3D doesn't need that and just ignores it.
2373 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2375 case WINEMAKEFOURCC('I','N','S','T'):
2376 TRACE("ATI Instancing check hack\n");
2377 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2378 TRACE_(d3d_caps)("[OK]\n");
2379 return TRUE;
2381 TRACE_(d3d_caps)("[FAILED]\n");
2382 return FALSE;
2384 /* Some weird FOURCC formats */
2385 case WINED3DFMT_R8G8_B8G8:
2386 case WINED3DFMT_G8R8_G8B8:
2387 case WINED3DFMT_MULTI2_ARGB8:
2388 TRACE_(d3d_caps)("[FAILED]\n");
2389 return FALSE;
2391 /* Vendor specific formats */
2392 case WINED3DFMT_ATI2N:
2393 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2394 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2395 shader_backend = select_shader_backend(Adapter, DeviceType);
2396 fp = select_fragment_implementation(Adapter, DeviceType);
2397 if (shader_backend->shader_color_fixup_supported(glDesc->color_fixup)
2398 && fp->color_fixup_supported(glDesc->color_fixup))
2400 TRACE_(d3d_caps)("[OK]\n");
2401 return TRUE;
2404 TRACE_(d3d_caps)("[OK]\n");
2405 return TRUE;
2407 TRACE_(d3d_caps)("[FAILED]\n");
2408 return FALSE;
2410 case WINED3DFMT_NVHU:
2411 case WINED3DFMT_NVHS:
2412 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2413 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2414 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2415 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2416 * Applications have to deal with not having NVHS and NVHU.
2418 TRACE_(d3d_caps)("[FAILED]\n");
2419 return FALSE;
2421 case WINED3DFMT_UNKNOWN:
2422 return FALSE;
2424 default:
2425 ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat));
2426 break;
2428 return FALSE;
2431 static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) {
2432 const struct GlPixelFormatDesc *format_desc;
2433 const struct blit_shader *blitter;
2435 if(SurfaceType == SURFACE_GDI) {
2436 switch(CheckFormat) {
2437 case WINED3DFMT_R8G8B8:
2438 case WINED3DFMT_A8R8G8B8:
2439 case WINED3DFMT_X8R8G8B8:
2440 case WINED3DFMT_R5G6B5:
2441 case WINED3DFMT_X1R5G5B5:
2442 case WINED3DFMT_A1R5G5B5:
2443 case WINED3DFMT_A4R4G4B4:
2444 case WINED3DFMT_R3G3B2:
2445 case WINED3DFMT_A8:
2446 case WINED3DFMT_A8R3G3B2:
2447 case WINED3DFMT_X4R4G4B4:
2448 case WINED3DFMT_A2B10G10R10:
2449 case WINED3DFMT_A8B8G8R8:
2450 case WINED3DFMT_X8B8G8R8:
2451 case WINED3DFMT_G16R16:
2452 case WINED3DFMT_A2R10G10B10:
2453 case WINED3DFMT_A16B16G16R16:
2454 case WINED3DFMT_P8:
2455 TRACE_(d3d_caps)("[OK]\n");
2456 return TRUE;
2457 default:
2458 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2459 return FALSE;
2463 /* All format that are supported for textures are supported for surfaces as well */
2464 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE;
2465 /* All depth stencil formats are supported on surfaces */
2466 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) return TRUE;
2468 /* If opengl can't process the format natively, the blitter may be able to convert it */
2469 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &format_desc);
2470 blitter = select_blit_implementation(Adapter, DeviceType);
2471 if (blitter->color_fixup_supported(format_desc->color_fixup))
2473 TRACE_(d3d_caps)("[OK]\n");
2474 return TRUE;
2477 /* Reject other formats */
2478 TRACE_(d3d_caps)("[FAILED]\n");
2479 return FALSE;
2482 static BOOL CheckVertexTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2484 if (!GL_LIMITS(vertex_samplers)) {
2485 TRACE_(d3d_caps)("[FAILED]\n");
2486 return FALSE;
2489 switch (CheckFormat) {
2490 case WINED3DFMT_A32B32G32R32F:
2491 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2492 TRACE_(d3d_caps)("[FAILED]\n");
2493 return FALSE;
2495 TRACE_(d3d_caps)("[OK]\n");
2496 return TRUE;
2498 default:
2499 TRACE_(d3d_caps)("[FAILED]\n");
2500 return FALSE;
2502 return FALSE;
2505 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2506 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2507 WINED3DSURFTYPE SurfaceType) {
2508 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2509 DWORD UsageCaps = 0;
2511 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2512 This,
2513 Adapter,
2514 DeviceType, debug_d3ddevicetype(DeviceType),
2515 AdapterFormat, debug_d3dformat(AdapterFormat),
2516 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2517 RType, debug_d3dresourcetype(RType),
2518 CheckFormat, debug_d3dformat(CheckFormat));
2520 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2521 return WINED3DERR_INVALIDCALL;
2524 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2526 if(SurfaceType != SURFACE_OPENGL) {
2527 TRACE("[FAILED]\n");
2528 return WINED3DERR_NOTAVAILABLE;
2531 /* Cubetexture allows:
2532 * - D3DUSAGE_AUTOGENMIPMAP
2533 * - D3DUSAGE_DEPTHSTENCIL
2534 * - D3DUSAGE_DYNAMIC
2535 * - D3DUSAGE_NONSECURE (d3d9ex)
2536 * - D3DUSAGE_RENDERTARGET
2537 * - D3DUSAGE_SOFTWAREPROCESSING
2538 * - D3DUSAGE_QUERY_WRAPANDMIP
2540 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2541 /* Check if the texture format is around */
2542 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2543 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2544 /* Check for automatic mipmap generation support */
2545 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2546 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2547 } else {
2548 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2549 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2553 /* Always report dynamic locking */
2554 if(Usage & WINED3DUSAGE_DYNAMIC)
2555 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2557 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2558 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2559 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2560 } else {
2561 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2562 return WINED3DERR_NOTAVAILABLE;
2566 /* Always report software processing */
2567 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2568 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2570 /* Check QUERY_FILTER support */
2571 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2572 if(CheckFilterCapability(Adapter, CheckFormat)) {
2573 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2574 } else {
2575 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2576 return WINED3DERR_NOTAVAILABLE;
2580 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2581 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2582 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2583 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2584 } else {
2585 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2586 return WINED3DERR_NOTAVAILABLE;
2590 /* Check QUERY_SRGBREAD support */
2591 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2592 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2593 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2594 } else {
2595 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2596 return WINED3DERR_NOTAVAILABLE;
2600 /* Check QUERY_SRGBWRITE support */
2601 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2602 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2603 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2604 } else {
2605 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2606 return WINED3DERR_NOTAVAILABLE;
2610 /* Check QUERY_VERTEXTEXTURE support */
2611 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2612 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2613 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2614 } else {
2615 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2616 return WINED3DERR_NOTAVAILABLE;
2620 /* Check QUERY_WRAPANDMIP support */
2621 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2622 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2623 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2624 } else {
2625 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2626 return WINED3DERR_NOTAVAILABLE;
2629 } else {
2630 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2631 return WINED3DERR_NOTAVAILABLE;
2633 } else {
2634 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2635 return WINED3DERR_NOTAVAILABLE;
2637 } else if(RType == WINED3DRTYPE_SURFACE) {
2638 /* Surface allows:
2639 * - D3DUSAGE_DEPTHSTENCIL
2640 * - D3DUSAGE_NONSECURE (d3d9ex)
2641 * - D3DUSAGE_RENDERTARGET
2644 if(CheckSurfaceCapability(Adapter, AdapterFormat, DeviceType, CheckFormat, SurfaceType)) {
2645 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2646 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2647 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2648 } else {
2649 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2650 return WINED3DERR_NOTAVAILABLE;
2654 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2655 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2656 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2657 } else {
2658 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2659 return WINED3DERR_NOTAVAILABLE;
2663 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2664 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2665 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2666 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2667 } else {
2668 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2669 return WINED3DERR_NOTAVAILABLE;
2672 } else {
2673 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2674 return WINED3DERR_NOTAVAILABLE;
2677 } else if(RType == WINED3DRTYPE_TEXTURE) {
2678 /* Texture allows:
2679 * - D3DUSAGE_AUTOGENMIPMAP
2680 * - D3DUSAGE_DEPTHSTENCIL
2681 * - D3DUSAGE_DMAP
2682 * - D3DUSAGE_DYNAMIC
2683 * - D3DUSAGE_NONSECURE (d3d9ex)
2684 * - D3DUSAGE_RENDERTARGET
2685 * - D3DUSAGE_SOFTWAREPROCESSING
2686 * - D3DUSAGE_TEXTAPI (d3d9ex)
2687 * - D3DUSAGE_QUERY_WRAPANDMIP
2690 if(SurfaceType != SURFACE_OPENGL) {
2691 TRACE("[FAILED]\n");
2692 return WINED3DERR_NOTAVAILABLE;
2695 /* Check if the texture format is around */
2696 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2697 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2698 /* Check for automatic mipmap generation support */
2699 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2700 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2701 } else {
2702 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2703 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2707 /* Always report dynamic locking */
2708 if(Usage & WINED3DUSAGE_DYNAMIC)
2709 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2711 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2712 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2713 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2714 } else {
2715 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2716 return WINED3DERR_NOTAVAILABLE;
2720 /* Always report software processing */
2721 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2722 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2724 /* Check QUERY_FILTER support */
2725 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2726 if(CheckFilterCapability(Adapter, CheckFormat)) {
2727 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2728 } else {
2729 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2730 return WINED3DERR_NOTAVAILABLE;
2734 /* Check QUERY_LEGACYBUMPMAP support */
2735 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2736 if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) {
2737 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2738 } else {
2739 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2740 return WINED3DERR_NOTAVAILABLE;
2744 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2745 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2746 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2747 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2748 } else {
2749 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2750 return WINED3DERR_NOTAVAILABLE;
2754 /* Check QUERY_SRGBREAD support */
2755 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2756 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2757 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2758 } else {
2759 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2760 return WINED3DERR_NOTAVAILABLE;
2764 /* Check QUERY_SRGBWRITE support */
2765 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2766 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2767 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2768 } else {
2769 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2770 return WINED3DERR_NOTAVAILABLE;
2774 /* Check QUERY_VERTEXTEXTURE support */
2775 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2776 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2777 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2778 } else {
2779 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2780 return WINED3DERR_NOTAVAILABLE;
2784 /* Check QUERY_WRAPANDMIP support */
2785 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2786 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2787 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2788 } else {
2789 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2790 return WINED3DERR_NOTAVAILABLE;
2794 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2795 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2796 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2797 } else {
2798 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2799 return WINED3DERR_NOTAVAILABLE;
2802 } else {
2803 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2804 return WINED3DERR_NOTAVAILABLE;
2806 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2807 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2808 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2810 * Volumetexture allows:
2811 * - D3DUSAGE_DYNAMIC
2812 * - D3DUSAGE_NONSECURE (d3d9ex)
2813 * - D3DUSAGE_SOFTWAREPROCESSING
2814 * - D3DUSAGE_QUERY_WRAPANDMIP
2817 if(SurfaceType != SURFACE_OPENGL) {
2818 TRACE("[FAILED]\n");
2819 return WINED3DERR_NOTAVAILABLE;
2822 /* Check volume texture and volume usage caps */
2823 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2824 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) {
2825 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2826 return WINED3DERR_NOTAVAILABLE;
2829 /* Always report dynamic locking */
2830 if(Usage & WINED3DUSAGE_DYNAMIC)
2831 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2833 /* Always report software processing */
2834 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2835 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2837 /* Check QUERY_FILTER support */
2838 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2839 if(CheckFilterCapability(Adapter, CheckFormat)) {
2840 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2841 } else {
2842 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2843 return WINED3DERR_NOTAVAILABLE;
2847 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2848 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2849 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2850 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2851 } else {
2852 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2853 return WINED3DERR_NOTAVAILABLE;
2857 /* Check QUERY_SRGBREAD support */
2858 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2859 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2860 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2861 } else {
2862 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2863 return WINED3DERR_NOTAVAILABLE;
2867 /* Check QUERY_SRGBWRITE support */
2868 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2869 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2870 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2871 } else {
2872 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2873 return WINED3DERR_NOTAVAILABLE;
2877 /* Check QUERY_VERTEXTEXTURE support */
2878 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2879 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2880 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2881 } else {
2882 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2883 return WINED3DERR_NOTAVAILABLE;
2887 /* Check QUERY_WRAPANDMIP support */
2888 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2889 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2890 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2891 } else {
2892 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2893 return WINED3DERR_NOTAVAILABLE;
2896 } else {
2897 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
2898 return WINED3DERR_NOTAVAILABLE;
2901 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
2902 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
2903 * app needing one of those formats, don't advertize them to avoid leading apps into
2904 * temptation. The windows drivers don't support most of those formats on volumes anyway,
2905 * except of R32F.
2907 switch(CheckFormat) {
2908 case WINED3DFMT_P8:
2909 case WINED3DFMT_A4L4:
2910 case WINED3DFMT_R32F:
2911 case WINED3DFMT_R16F:
2912 case WINED3DFMT_X8L8V8U8:
2913 case WINED3DFMT_L6V5U5:
2914 case WINED3DFMT_G16R16:
2915 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2916 return WINED3DERR_NOTAVAILABLE;
2918 case WINED3DFMT_Q8W8V8U8:
2919 case WINED3DFMT_V16U16:
2920 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2921 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2922 return WINED3DERR_NOTAVAILABLE;
2924 break;
2926 case WINED3DFMT_V8U8:
2927 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2928 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2929 return WINED3DERR_NOTAVAILABLE;
2931 break;
2933 case WINED3DFMT_DXT1:
2934 case WINED3DFMT_DXT2:
2935 case WINED3DFMT_DXT3:
2936 case WINED3DFMT_DXT4:
2937 case WINED3DFMT_DXT5:
2938 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
2939 * compressed texture results in an error. While the D3D refrast does
2940 * support s3tc volumes, at least the nvidia windows driver does not, so
2941 * we're free not to support this format.
2943 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
2944 return WINED3DERR_NOTAVAILABLE;
2946 default:
2947 /* Do nothing, continue with checking the format below */
2948 break;
2950 } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){
2951 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
2952 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
2953 return WINED3DERR_NOTAVAILABLE;
2956 /* This format is nothing special and it is supported perfectly.
2957 * However, ati and nvidia driver on windows do not mark this format as
2958 * supported (tested with the dxCapsViewer) and pretending to
2959 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
2960 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
2961 * Enable it on dx7. It will need additional checking on dx10 when we support it.
2963 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
2964 TRACE_(d3d_caps)("[FAILED]\n");
2965 return WINED3DERR_NOTAVAILABLE;
2968 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
2969 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
2970 * usage flags match. */
2971 if(UsageCaps == Usage) {
2972 return WINED3D_OK;
2973 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
2974 return WINED3DOK_NOAUTOGEN;
2975 } else {
2976 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);
2977 return WINED3DERR_NOTAVAILABLE;
2981 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2982 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2983 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2985 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2986 This,
2987 Adapter,
2988 DeviceType, debug_d3ddevicetype(DeviceType),
2989 SourceFormat, debug_d3dformat(SourceFormat),
2990 TargetFormat, debug_d3dformat(TargetFormat));
2991 return WINED3D_OK;
2994 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType) {
2995 const shader_backend_t *ret;
2996 int vs_selected_mode;
2997 int ps_selected_mode;
2999 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3000 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3001 ret = &glsl_shader_backend;
3002 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3003 ret = &arb_program_shader_backend;
3004 } else {
3005 ret = &none_shader_backend;
3007 return ret;
3010 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3011 int vs_selected_mode;
3012 int ps_selected_mode;
3014 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3015 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3016 return &arbfp_fragment_pipeline;
3017 } else if(ps_selected_mode == SHADER_ATI) {
3018 return &atifs_fragment_pipeline;
3019 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3020 return &nvts_fragment_pipeline;
3021 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3022 return &nvrc_fragment_pipeline;
3023 } else {
3024 return &ffp_fragment_pipeline;
3028 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3029 int vs_selected_mode;
3030 int ps_selected_mode;
3032 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3033 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3034 return &arbfp_blit;
3035 } else {
3036 return &ffp_blit;
3040 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3041 subset of a D3DCAPS9 structure. However, it has to come via a void *
3042 as the d3d8 interface cannot import the d3d9 header */
3043 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3045 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3046 int vs_selected_mode;
3047 int ps_selected_mode;
3048 struct shader_caps shader_caps;
3049 struct fragment_caps fragment_caps;
3050 const shader_backend_t *shader_backend;
3051 const struct fragment_pipeline *frag_pipeline = NULL;
3052 DWORD ckey_caps, blit_caps, fx_caps;
3054 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3056 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3057 return WINED3DERR_INVALIDCALL;
3060 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3062 /* This function should *not* be modifying GL caps
3063 * TODO: move the functionality where it belongs */
3064 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
3066 /* ------------------------------------------------
3067 The following fields apply to both d3d8 and d3d9
3068 ------------------------------------------------ */
3069 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3070 pCaps->AdapterOrdinal = Adapter;
3072 pCaps->Caps = 0;
3073 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3074 WINED3DCAPS2_FULLSCREENGAMMA |
3075 WINED3DCAPS2_DYNAMICTEXTURES;
3076 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3077 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3080 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3081 WINED3DCAPS3_COPY_TO_VIDMEM |
3082 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3084 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3085 WINED3DPRESENT_INTERVAL_ONE;
3087 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3088 WINED3DCURSORCAPS_LOWRES;
3090 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3091 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3092 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3093 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3094 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3095 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3096 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3097 WINED3DDEVCAPS_PUREDEVICE |
3098 WINED3DDEVCAPS_HWRASTERIZATION |
3099 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3100 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3101 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3102 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3103 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3104 WINED3DDEVCAPS_RTPATCHES;
3106 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3107 WINED3DPMISCCAPS_CULLCCW |
3108 WINED3DPMISCCAPS_CULLCW |
3109 WINED3DPMISCCAPS_COLORWRITEENABLE |
3110 WINED3DPMISCCAPS_CLIPTLVERTS |
3111 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3112 WINED3DPMISCCAPS_MASKZ |
3113 WINED3DPMISCCAPS_BLENDOP |
3114 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3115 /* TODO:
3116 WINED3DPMISCCAPS_NULLREFERENCE
3117 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3118 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3119 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3120 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3122 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3123 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3125 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3126 WINED3DPRASTERCAPS_PAT |
3127 WINED3DPRASTERCAPS_WFOG |
3128 WINED3DPRASTERCAPS_ZFOG |
3129 WINED3DPRASTERCAPS_FOGVERTEX |
3130 WINED3DPRASTERCAPS_FOGTABLE |
3131 WINED3DPRASTERCAPS_STIPPLE |
3132 WINED3DPRASTERCAPS_SUBPIXEL |
3133 WINED3DPRASTERCAPS_ZTEST |
3134 WINED3DPRASTERCAPS_SCISSORTEST |
3135 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3136 WINED3DPRASTERCAPS_DEPTHBIAS;
3138 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3139 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3140 WINED3DPRASTERCAPS_ZBIAS |
3141 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3143 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3144 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3146 /* FIXME Add:
3147 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3148 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3149 WINED3DPRASTERCAPS_ANTIALIASEDGES
3150 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3151 WINED3DPRASTERCAPS_WBUFFER */
3153 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3154 WINED3DPCMPCAPS_EQUAL |
3155 WINED3DPCMPCAPS_GREATER |
3156 WINED3DPCMPCAPS_GREATEREQUAL |
3157 WINED3DPCMPCAPS_LESS |
3158 WINED3DPCMPCAPS_LESSEQUAL |
3159 WINED3DPCMPCAPS_NEVER |
3160 WINED3DPCMPCAPS_NOTEQUAL;
3162 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3163 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3164 WINED3DPBLENDCAPS_DESTALPHA |
3165 WINED3DPBLENDCAPS_DESTCOLOR |
3166 WINED3DPBLENDCAPS_INVDESTALPHA |
3167 WINED3DPBLENDCAPS_INVDESTCOLOR |
3168 WINED3DPBLENDCAPS_INVSRCALPHA |
3169 WINED3DPBLENDCAPS_INVSRCCOLOR |
3170 WINED3DPBLENDCAPS_ONE |
3171 WINED3DPBLENDCAPS_SRCALPHA |
3172 WINED3DPBLENDCAPS_SRCALPHASAT |
3173 WINED3DPBLENDCAPS_SRCCOLOR |
3174 WINED3DPBLENDCAPS_ZERO;
3176 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3177 WINED3DPBLENDCAPS_DESTCOLOR |
3178 WINED3DPBLENDCAPS_INVDESTALPHA |
3179 WINED3DPBLENDCAPS_INVDESTCOLOR |
3180 WINED3DPBLENDCAPS_INVSRCALPHA |
3181 WINED3DPBLENDCAPS_INVSRCCOLOR |
3182 WINED3DPBLENDCAPS_ONE |
3183 WINED3DPBLENDCAPS_SRCALPHA |
3184 WINED3DPBLENDCAPS_SRCCOLOR |
3185 WINED3DPBLENDCAPS_ZERO;
3186 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3187 * according to the glBlendFunc manpage
3189 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3190 * legacy settings for srcblend only
3193 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3194 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3195 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3199 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3200 WINED3DPCMPCAPS_EQUAL |
3201 WINED3DPCMPCAPS_GREATER |
3202 WINED3DPCMPCAPS_GREATEREQUAL |
3203 WINED3DPCMPCAPS_LESS |
3204 WINED3DPCMPCAPS_LESSEQUAL |
3205 WINED3DPCMPCAPS_NEVER |
3206 WINED3DPCMPCAPS_NOTEQUAL;
3208 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3209 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3210 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3211 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3212 WINED3DPSHADECAPS_COLORFLATRGB |
3213 WINED3DPSHADECAPS_FOGFLAT |
3214 WINED3DPSHADECAPS_FOGGOURAUD |
3215 WINED3DPSHADECAPS_SPECULARFLATRGB;
3217 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3218 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3219 WINED3DPTEXTURECAPS_TRANSPARENCY |
3220 WINED3DPTEXTURECAPS_BORDER |
3221 WINED3DPTEXTURECAPS_MIPMAP |
3222 WINED3DPTEXTURECAPS_PROJECTED |
3223 WINED3DPTEXTURECAPS_PERSPECTIVE;
3225 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3226 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3227 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3230 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3231 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3232 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3233 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3236 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3237 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3238 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3239 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3243 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3244 WINED3DPTFILTERCAPS_MAGFPOINT |
3245 WINED3DPTFILTERCAPS_MINFLINEAR |
3246 WINED3DPTFILTERCAPS_MINFPOINT |
3247 WINED3DPTFILTERCAPS_MIPFLINEAR |
3248 WINED3DPTFILTERCAPS_MIPFPOINT |
3249 WINED3DPTFILTERCAPS_LINEAR |
3250 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3251 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3252 WINED3DPTFILTERCAPS_MIPLINEAR |
3253 WINED3DPTFILTERCAPS_MIPNEAREST |
3254 WINED3DPTFILTERCAPS_NEAREST;
3256 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3257 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3258 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3261 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3262 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3263 WINED3DPTFILTERCAPS_MAGFPOINT |
3264 WINED3DPTFILTERCAPS_MINFLINEAR |
3265 WINED3DPTFILTERCAPS_MINFPOINT |
3266 WINED3DPTFILTERCAPS_MIPFLINEAR |
3267 WINED3DPTFILTERCAPS_MIPFPOINT |
3268 WINED3DPTFILTERCAPS_LINEAR |
3269 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3270 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3271 WINED3DPTFILTERCAPS_MIPLINEAR |
3272 WINED3DPTFILTERCAPS_MIPNEAREST |
3273 WINED3DPTFILTERCAPS_NEAREST;
3275 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3276 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3277 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3279 } else
3280 pCaps->CubeTextureFilterCaps = 0;
3282 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3283 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3284 WINED3DPTFILTERCAPS_MAGFPOINT |
3285 WINED3DPTFILTERCAPS_MINFLINEAR |
3286 WINED3DPTFILTERCAPS_MINFPOINT |
3287 WINED3DPTFILTERCAPS_MIPFLINEAR |
3288 WINED3DPTFILTERCAPS_MIPFPOINT |
3289 WINED3DPTFILTERCAPS_LINEAR |
3290 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3291 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3292 WINED3DPTFILTERCAPS_MIPLINEAR |
3293 WINED3DPTFILTERCAPS_MIPNEAREST |
3294 WINED3DPTFILTERCAPS_NEAREST;
3295 } else
3296 pCaps->VolumeTextureFilterCaps = 0;
3298 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3299 WINED3DPTADDRESSCAPS_CLAMP |
3300 WINED3DPTADDRESSCAPS_WRAP;
3302 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3303 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3305 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3306 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3308 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3309 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3312 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3313 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3314 WINED3DPTADDRESSCAPS_CLAMP |
3315 WINED3DPTADDRESSCAPS_WRAP;
3316 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3317 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3319 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3320 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3322 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3323 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3325 } else
3326 pCaps->VolumeTextureAddressCaps = 0;
3328 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3329 WINED3DLINECAPS_ZTEST |
3330 WINED3DLINECAPS_BLEND |
3331 WINED3DLINECAPS_ALPHACMP |
3332 WINED3DLINECAPS_FOG;
3333 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3334 * idea how generating the smoothing alpha values works; the result is different
3337 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3338 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3340 if(GL_SUPPORT(EXT_TEXTURE3D))
3341 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3342 else
3343 pCaps->MaxVolumeExtent = 0;
3345 pCaps->MaxTextureRepeat = 32768;
3346 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3347 pCaps->MaxVertexW = 1.0;
3349 pCaps->GuardBandLeft = 0;
3350 pCaps->GuardBandTop = 0;
3351 pCaps->GuardBandRight = 0;
3352 pCaps->GuardBandBottom = 0;
3354 pCaps->ExtentsAdjust = 0;
3356 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3357 WINED3DSTENCILCAPS_INCRSAT |
3358 WINED3DSTENCILCAPS_INVERT |
3359 WINED3DSTENCILCAPS_KEEP |
3360 WINED3DSTENCILCAPS_REPLACE |
3361 WINED3DSTENCILCAPS_ZERO;
3362 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3363 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3364 WINED3DSTENCILCAPS_INCR;
3366 if ( This->dxVersion > 8 &&
3367 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3368 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3369 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3372 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3374 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3375 pCaps->MaxActiveLights = GL_LIMITS(lights);
3377 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3378 pCaps->MaxVertexBlendMatrixIndex = 0;
3380 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3381 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3384 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3385 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3386 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3387 WINED3DVTXPCAPS_LOCALVIEWER |
3388 WINED3DVTXPCAPS_VERTEXFOG |
3389 WINED3DVTXPCAPS_TEXGEN;
3390 /* FIXME: Add
3391 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3393 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3394 pCaps->MaxVertexIndex = 0xFFFFF;
3395 pCaps->MaxStreams = MAX_STREAMS;
3396 pCaps->MaxStreamStride = 1024;
3398 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3399 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3400 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3401 pCaps->MaxNpatchTessellationLevel = 0;
3402 pCaps->MasterAdapterOrdinal = 0;
3403 pCaps->AdapterOrdinalInGroup = 0;
3404 pCaps->NumberOfAdaptersInGroup = 1;
3406 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3408 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3409 WINED3DPTFILTERCAPS_MAGFPOINT |
3410 WINED3DPTFILTERCAPS_MINFLINEAR |
3411 WINED3DPTFILTERCAPS_MAGFLINEAR;
3412 pCaps->VertexTextureFilterCaps = 0;
3414 memset(&shader_caps, 0, sizeof(shader_caps));
3415 shader_backend = select_shader_backend(Adapter, DeviceType);
3416 shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps);
3418 memset(&fragment_caps, 0, sizeof(fragment_caps));
3419 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3420 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &fragment_caps);
3422 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3423 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3425 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3426 * Ignore shader model capabilities if disabled in config
3428 if(vs_selected_mode == SHADER_NONE) {
3429 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3430 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3431 pCaps->MaxVertexShaderConst = 0;
3432 } else {
3433 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3434 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3437 if(ps_selected_mode == SHADER_NONE) {
3438 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3439 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3440 pCaps->PixelShader1xMaxValue = 0.0;
3441 } else {
3442 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3443 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3446 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3447 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3448 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3450 pCaps->VS20Caps = shader_caps.VS20Caps;
3451 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3452 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3453 pCaps->PS20Caps = shader_caps.PS20Caps;
3454 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3455 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3457 /* The following caps are shader specific, but they are things we cannot detect, or which
3458 * are the same among all shader models. So to avoid code duplication set the shader version
3459 * specific, but otherwise constant caps here
3461 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3462 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3463 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3464 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3465 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3466 pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
3467 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3469 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3470 pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
3471 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3472 pCaps->VS20Caps.Caps = 0;
3473 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3474 pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
3475 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3477 pCaps->MaxVShaderInstructionsExecuted = 65535;
3478 pCaps->MaxVertexShader30InstructionSlots = 0;
3479 } else { /* VS 1.x */
3480 pCaps->VS20Caps.Caps = 0;
3481 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3482 pCaps->VS20Caps.NumTemps = 0;
3483 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3485 pCaps->MaxVShaderInstructionsExecuted = 0;
3486 pCaps->MaxVertexShader30InstructionSlots = 0;
3489 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3490 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3491 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3493 /* 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 */
3494 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3495 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3496 WINED3DPS20CAPS_PREDICATION |
3497 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3498 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3499 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3500 pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
3501 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3502 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3504 pCaps->MaxPShaderInstructionsExecuted = 65535;
3505 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
3506 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3507 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3508 pCaps->PS20Caps.Caps = 0;
3509 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3510 pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
3511 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3512 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3514 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3515 pCaps->MaxPixelShader30InstructionSlots = 0;
3516 } else { /* PS 1.x */
3517 pCaps->PS20Caps.Caps = 0;
3518 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3519 pCaps->PS20Caps.NumTemps = 0;
3520 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3521 pCaps->PS20Caps.NumInstructionSlots = 0;
3523 pCaps->MaxPShaderInstructionsExecuted = 0;
3524 pCaps->MaxPixelShader30InstructionSlots = 0;
3527 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3528 /* OpenGL supports all the formats below, perhaps not always
3529 * without conversion, but it supports them.
3530 * Further GLSL doesn't seem to have an official unsigned type so
3531 * don't advertise it yet as I'm not sure how we handle it.
3532 * We might need to add some clamping in the shader engine to
3533 * support it.
3534 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3535 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3536 WINED3DDTCAPS_UBYTE4N |
3537 WINED3DDTCAPS_SHORT2N |
3538 WINED3DDTCAPS_SHORT4N;
3539 if (GL_SUPPORT(NV_HALF_FLOAT)) {
3540 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3541 WINED3DDTCAPS_FLOAT16_4;
3543 } else
3544 pCaps->DeclTypes = 0;
3546 /* Set DirectDraw helper Caps */
3547 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3548 WINEDDCKEYCAPS_SRCBLT;
3549 fx_caps = WINEDDFXCAPS_BLTALPHA |
3550 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3551 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3552 WINEDDFXCAPS_BLTROTATION90 |
3553 WINEDDFXCAPS_BLTSHRINKX |
3554 WINEDDFXCAPS_BLTSHRINKXN |
3555 WINEDDFXCAPS_BLTSHRINKY |
3556 WINEDDFXCAPS_BLTSHRINKXN |
3557 WINEDDFXCAPS_BLTSTRETCHX |
3558 WINEDDFXCAPS_BLTSTRETCHXN |
3559 WINEDDFXCAPS_BLTSTRETCHY |
3560 WINEDDFXCAPS_BLTSTRETCHYN;
3561 blit_caps = WINEDDCAPS_BLT |
3562 WINEDDCAPS_BLTCOLORFILL |
3563 WINEDDCAPS_BLTDEPTHFILL |
3564 WINEDDCAPS_BLTSTRETCH |
3565 WINEDDCAPS_CANBLTSYSMEM |
3566 WINEDDCAPS_CANCLIP |
3567 WINEDDCAPS_CANCLIPSTRETCHED |
3568 WINEDDCAPS_COLORKEY |
3569 WINEDDCAPS_COLORKEYHWASSIST |
3570 WINEDDCAPS_ALIGNBOUNDARYSRC;
3572 /* Fill the ddraw caps structure */
3573 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3574 WINEDDCAPS_PALETTE |
3575 blit_caps;
3576 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3577 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3578 WINEDDCAPS2_PRIMARYGAMMA |
3579 WINEDDCAPS2_WIDESURFACES |
3580 WINEDDCAPS2_CANRENDERWINDOWED;
3581 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3582 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3583 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3584 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3585 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3586 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3587 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3588 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3589 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3591 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3592 WINEDDSCAPS_BACKBUFFER |
3593 WINEDDSCAPS_FLIP |
3594 WINEDDSCAPS_FRONTBUFFER |
3595 WINEDDSCAPS_OFFSCREENPLAIN |
3596 WINEDDSCAPS_PALETTE |
3597 WINEDDSCAPS_PRIMARYSURFACE |
3598 WINEDDSCAPS_SYSTEMMEMORY |
3599 WINEDDSCAPS_VIDEOMEMORY |
3600 WINEDDSCAPS_VISIBLE;
3601 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3603 /* Set D3D caps if OpenGL is available. */
3604 if(Adapters[Adapter].opengl) {
3605 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3606 WINEDDSCAPS_MIPMAP |
3607 WINEDDSCAPS_TEXTURE |
3608 WINEDDSCAPS_ZBUFFER;
3609 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3612 return WINED3D_OK;
3615 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3616 and fields being inserted in the middle, a new structure is used in place */
3617 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
3618 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
3619 IUnknown *parent) {
3621 IWineD3DDeviceImpl *object = NULL;
3622 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3623 WINED3DDISPLAYMODE mode;
3624 const struct fragment_pipeline *frag_pipeline = NULL;
3625 int i;
3626 struct fragment_caps ffp_caps;
3628 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3629 * number and create a device without a 3D adapter for 2D only operation.
3631 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3632 return WINED3DERR_INVALIDCALL;
3635 /* Create a WineD3DDevice object */
3636 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3637 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3638 TRACE("Created WineD3DDevice object @ %p\n", object);
3639 if (NULL == object) {
3640 return WINED3DERR_OUTOFVIDEOMEMORY;
3643 /* Set up initial COM information */
3644 object->lpVtbl = &IWineD3DDevice_Vtbl;
3645 object->ref = 1;
3646 object->wineD3D = iface;
3647 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
3648 IWineD3D_AddRef(object->wineD3D);
3649 object->parent = parent;
3650 list_init(&object->resources);
3651 list_init(&object->shaders);
3653 if(This->dxVersion == 7) {
3654 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3655 } else {
3656 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3658 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3660 /* Set the state up as invalid until the device is fully created */
3661 object->state = WINED3DERR_DRIVERINTERNALERROR;
3663 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3664 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3666 /* Save the creation parameters */
3667 object->createParms.AdapterOrdinal = Adapter;
3668 object->createParms.DeviceType = DeviceType;
3669 object->createParms.hFocusWindow = hFocusWindow;
3670 object->createParms.BehaviorFlags = BehaviourFlags;
3672 /* Initialize other useful values */
3673 object->adapterNo = Adapter;
3674 object->devType = DeviceType;
3676 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
3677 object->shader_backend = select_shader_backend(Adapter, DeviceType);
3679 memset(&ffp_caps, 0, sizeof(ffp_caps));
3680 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3681 object->frag_pipe = frag_pipeline;
3682 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
3683 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3684 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3685 compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
3686 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3688 object->blitter = select_blit_implementation(Adapter, DeviceType);
3690 /* set the state of the device to valid */
3691 object->state = WINED3D_OK;
3693 /* Get the initial screen setup for ddraw */
3694 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3696 object->ddraw_width = mode.Width;
3697 object->ddraw_height = mode.Height;
3698 object->ddraw_format = mode.Format;
3700 for(i = 0; i < PATCHMAP_SIZE; i++) {
3701 list_init(&object->patches[i]);
3703 return WINED3D_OK;
3705 #undef GLINFO_LOCATION
3707 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3708 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3709 IUnknown_AddRef(This->parent);
3710 *pParent = This->parent;
3711 return WINED3D_OK;
3714 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3715 IUnknown* surfaceParent;
3716 TRACE("(%p) call back\n", pSurface);
3718 /* Now, release the parent, which will take care of cleaning up the surface for us */
3719 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3720 IUnknown_Release(surfaceParent);
3721 return IUnknown_Release(surfaceParent);
3724 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3725 IUnknown* volumeParent;
3726 TRACE("(%p) call back\n", pVolume);
3728 /* Now, release the parent, which will take care of cleaning up the volume for us */
3729 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3730 IUnknown_Release(volumeParent);
3731 return IUnknown_Release(volumeParent);
3734 static BOOL implementation_is_apple(const WineD3D_GL_Info *gl_info)
3736 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3737 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3738 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3740 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3741 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3742 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3743 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3744 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3745 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3746 * DirectDraw, not OpenGL.
3748 if(gl_info->supported[APPLE_FENCE] &&
3749 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3750 gl_info->supported[APPLE_FLUSH_RENDER] &&
3751 gl_info->supported[APPLE_YCBCR_422]) {
3752 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3753 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3754 return TRUE;
3755 } else {
3756 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3757 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3758 return FALSE;
3762 #define GLINFO_LOCATION (*gl_info)
3763 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3764 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3765 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3766 * all the texture. This function detects this bug by its symptom and disables PBOs
3767 * if the test fails.
3769 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3770 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3771 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3772 * read back is compared to the original. If they are equal PBOs are assumed to work,
3773 * otherwise the PBO extension is disabled.
3775 GLuint texture, pbo;
3776 static const unsigned int pattern[] = {
3777 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3778 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3779 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3780 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3782 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3784 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3785 /* No PBO -> No point in testing them */
3786 return;
3789 while(glGetError());
3790 glGenTextures(1, &texture);
3791 glBindTexture(GL_TEXTURE_2D, texture);
3792 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3793 checkGLcall("Specifying the PBO test texture\n");
3795 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3796 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3797 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3798 checkGLcall("Specifying the PBO test pbo\n");
3800 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3801 checkGLcall("Loading the PBO test texture\n");
3803 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3804 glFinish(); /* just to be sure */
3806 memset(check, 0, sizeof(check));
3807 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3808 checkGLcall("Reading back the PBO test texture\n");
3810 glDeleteTextures(1, &texture);
3811 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3812 checkGLcall("PBO test cleanup\n");
3814 if(memcmp(check, pattern, sizeof(check)) != 0) {
3815 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3816 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3817 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3818 } else {
3819 TRACE_(d3d_caps)("PBO test successful\n");
3822 #undef GLINFO_LOCATION
3824 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3825 * reporting a driver version is moot because we are not the Windows driver, and we have different
3826 * bugs, features, etc.
3828 * If a card is not found in this table, the gl driver version is reported
3830 struct driver_version_information {
3831 WORD vendor; /* reported PCI card vendor ID */
3832 WORD card; /* reported PCI card device ID */
3833 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3834 WORD lopart_hi, lopart_lo; /* driver loword to report */
3837 static const struct driver_version_information driver_version_table[] = {
3838 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/
3839 /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */
3840 /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */
3841 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 },
3842 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 },
3843 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 },
3844 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 },
3845 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 },
3846 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 },
3847 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 },
3848 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 },
3849 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 },
3850 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 },
3851 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 },
3852 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 },
3853 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 },
3854 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 },
3855 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 },
3856 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 },
3857 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 },
3859 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
3860 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
3861 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
3862 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
3863 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
3864 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
3865 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
3867 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
3870 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
3871 unsigned int i;
3872 BOOL apple = implementation_is_apple(gl_info);
3874 if(apple) {
3875 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
3876 * used it falls back to software. While the compiler can detect if the shader uses all declared
3877 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
3878 * using relative addressing falls back to software.
3880 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
3882 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
3883 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
3884 } else {
3885 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3886 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3887 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3890 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3891 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3892 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3893 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3894 * according to the spec.
3896 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3897 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3899 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
3900 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
3901 * this workaround is activated on cards that do not need it, it won't break things, just affect
3902 * performance negatively.
3904 if(gl_info->gl_vendor == VENDOR_INTEL ||
3905 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
3906 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
3907 gl_info->set_texcoord_w = TRUE;
3911 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
3912 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
3913 * If real NP2 textures are used, the driver falls back to software. We could just remove the
3914 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
3915 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
3916 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
3917 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
3919 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
3920 * has this extension promoted to core. The extension loading code sets this extension supported
3921 * due to that, so this code works on fglrx as well.
3923 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
3924 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
3925 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
3926 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
3927 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
3928 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3929 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
3933 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
3934 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
3935 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
3936 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
3937 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
3938 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
3940 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
3941 * triggering the software fallback. There is not much we can do here apart from disabling the
3942 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
3943 * in IWineD3DImpl_FillGLCaps).
3944 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
3945 * post-processing effects in the game "Max Payne 2").
3946 * The behaviour can be verified through a simple test app attached in bugreport #14724.
3948 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
3949 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
3950 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
3951 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3952 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
3956 /* Find out if PBOs work as they are supposed to */
3957 test_pbo_functionality(gl_info);
3959 /* Fixup the driver version */
3960 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
3961 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
3962 gl_info->gl_card == driver_version_table[i].card) {
3963 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
3965 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
3966 driver_version_table[i].lopart_lo);
3967 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
3968 driver_version_table[i].hipart_lo);
3969 break;
3974 static void WINE_GLAPI invalid_func(const void *data)
3976 ERR("Invalid vertex attribute function called\n");
3977 DebugBreak();
3980 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
3982 ERR("Invalid texcoord function called\n");
3983 DebugBreak();
3986 #define GLINFO_LOCATION (Adapters[0].gl_info)
3988 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
3989 * the extension detection and are used in drawStridedSlow
3991 static void WINE_GLAPI position_d3dcolor(const void *data)
3993 DWORD pos = *((const DWORD *)data);
3995 FIXME("Add a test for fixed function position from d3dcolor type\n");
3996 glVertex4s(D3DCOLOR_B_R(pos),
3997 D3DCOLOR_B_G(pos),
3998 D3DCOLOR_B_B(pos),
3999 D3DCOLOR_B_A(pos));
4002 static void WINE_GLAPI position_float4(const void *data)
4004 const GLfloat *pos = data;
4006 if (pos[3] < eps && pos[3] > -eps)
4007 glVertex3fv(pos);
4008 else {
4009 float w = 1.0 / pos[3];
4011 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4015 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4017 DWORD diffuseColor = *((const DWORD *)data);
4019 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4020 D3DCOLOR_B_G(diffuseColor),
4021 D3DCOLOR_B_B(diffuseColor),
4022 D3DCOLOR_B_A(diffuseColor));
4025 static void WINE_GLAPI specular_d3dcolor(const void *data)
4027 DWORD specularColor = *((const DWORD *)data);
4029 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
4030 D3DCOLOR_B_G(specularColor),
4031 D3DCOLOR_B_B(specularColor));
4034 static void WINE_GLAPI warn_no_specular_func(const void *data)
4036 WARN("GL_EXT_secondary_color not supported\n");
4039 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4041 position_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4042 position_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4043 position_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glVertex3fv;
4044 position_funcs[WINED3DDECLTYPE_FLOAT4] = position_float4;
4045 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = position_d3dcolor;
4046 position_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4047 position_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4048 position_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glVertex2sv;
4049 position_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4050 position_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4051 position_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4052 position_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4053 position_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4054 position_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4055 position_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4056 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4057 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4059 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4060 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4061 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glColor3fv;
4062 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glColor4fv;
4063 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = diffuse_d3dcolor;
4064 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4065 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4066 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4067 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (glAttribFunc)glColor4ubv;
4068 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4069 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (glAttribFunc)glColor4sv;
4070 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4071 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (glAttribFunc)glColor4usv;
4072 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4073 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4074 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4075 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4077 /* No 4 component entry points here */
4078 specular_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4079 specular_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4080 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4081 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4082 } else {
4083 specular_funcs[WINED3DDECLTYPE_FLOAT3] = warn_no_specular_func;
4085 specular_funcs[WINED3DDECLTYPE_FLOAT4] = invalid_func;
4086 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4087 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = specular_d3dcolor;
4088 } else {
4089 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = warn_no_specular_func;
4091 specular_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4092 specular_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4093 specular_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4094 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4095 specular_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4096 specular_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4097 specular_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4098 specular_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4099 specular_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4100 specular_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4101 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4102 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4104 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4105 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4107 normal_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4108 normal_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4109 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glNormal3fv;
4110 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4111 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4112 normal_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4113 normal_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4114 normal_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4115 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4116 normal_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4117 normal_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4118 normal_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4119 normal_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4120 normal_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4121 normal_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4122 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4123 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4125 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4126 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4127 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4128 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4129 multi_texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_texcoord_func;
4130 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_texcoord_func;
4131 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4132 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4133 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_texcoord_func;
4134 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_texcoord_func;
4135 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_texcoord_func;
4136 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_texcoord_func;
4137 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_texcoord_func;
4138 multi_texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_texcoord_func;
4139 multi_texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_texcoord_func;
4140 if (GL_SUPPORT(NV_HALF_FLOAT))
4142 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4143 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4144 } else {
4145 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
4146 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
4150 #define PUSH1(att) attribs[nAttribs++] = (att);
4151 BOOL InitAdapters(void) {
4152 static HMODULE mod_gl;
4153 BOOL ret;
4154 int ps_selected_mode, vs_selected_mode;
4156 /* No need to hold any lock. The calling library makes sure only one thread calls
4157 * wined3d simultaneously
4159 if(numAdapters > 0) return Adapters[0].opengl;
4161 TRACE("Initializing adapters\n");
4163 if(!mod_gl) {
4164 #ifdef USE_WIN32_OPENGL
4165 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4166 mod_gl = LoadLibraryA("opengl32.dll");
4167 if(!mod_gl) {
4168 ERR("Can't load opengl32.dll!\n");
4169 goto nogl_adapter;
4171 mod_win32gl = mod_gl;
4172 #else
4173 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4174 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4175 mod_gl = GetModuleHandleA("gdi32.dll");
4176 #endif
4179 /* Load WGL core functions from opengl32.dll */
4180 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4181 WGL_FUNCS_GEN;
4182 #undef USE_WGL_FUNC
4184 if(!pwglGetProcAddress) {
4185 ERR("Unable to load wglGetProcAddress!\n");
4186 goto nogl_adapter;
4189 /* Dynamically load all GL core functions */
4190 GL_FUNCS_GEN;
4191 #undef USE_GL_FUNC
4193 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4194 * otherwise because we have to use winex11.drv's override
4196 #ifdef USE_WIN32_OPENGL
4197 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4198 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4199 #else
4200 glFinish = (void*)pwglGetProcAddress("wglFinish");
4201 glFlush = (void*)pwglGetProcAddress("wglFlush");
4202 #endif
4204 /* For now only one default adapter */
4206 int iPixelFormat;
4207 int attribs[10];
4208 int values[10];
4209 int nAttribs = 0;
4210 int res;
4211 int i;
4212 WineD3D_PixelFormat *cfgs;
4213 int attribute;
4214 DISPLAY_DEVICEW DisplayDevice;
4215 HDC hdc;
4217 TRACE("Initializing default adapter\n");
4218 Adapters[0].num = 0;
4219 Adapters[0].monitorPoint.x = -1;
4220 Adapters[0].monitorPoint.y = -1;
4222 if (!WineD3D_CreateFakeGLContext()) {
4223 ERR("Failed to get a gl context for default adapter\n");
4224 WineD3D_ReleaseFakeGLContext();
4225 goto nogl_adapter;
4228 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
4229 if(!ret) {
4230 ERR("Failed to initialize gl caps for default adapter\n");
4231 WineD3D_ReleaseFakeGLContext();
4232 goto nogl_adapter;
4234 ret = initPixelFormats(&Adapters[0].gl_info);
4235 if(!ret) {
4236 ERR("Failed to init gl formats\n");
4237 WineD3D_ReleaseFakeGLContext();
4238 goto nogl_adapter;
4241 hdc = pwglGetCurrentDC();
4242 if(!hdc) {
4243 ERR("Failed to get gl HDC\n");
4244 WineD3D_ReleaseFakeGLContext();
4245 goto nogl_adapter;
4248 Adapters[0].driver = "Display";
4249 Adapters[0].description = "Direct3D HAL";
4251 /* Use the VideoRamSize registry setting when set */
4252 if(wined3d_settings.emulated_textureram)
4253 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4254 else
4255 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
4256 Adapters[0].UsedTextureRam = 0;
4257 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
4259 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4260 DisplayDevice.cb = sizeof(DisplayDevice);
4261 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4262 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4263 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
4265 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4266 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
4268 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
4269 cfgs = Adapters[0].cfgs;
4270 PUSH1(WGL_RED_BITS_ARB)
4271 PUSH1(WGL_GREEN_BITS_ARB)
4272 PUSH1(WGL_BLUE_BITS_ARB)
4273 PUSH1(WGL_ALPHA_BITS_ARB)
4274 PUSH1(WGL_DEPTH_BITS_ARB)
4275 PUSH1(WGL_STENCIL_BITS_ARB)
4276 PUSH1(WGL_DRAW_TO_WINDOW_ARB)
4277 PUSH1(WGL_PIXEL_TYPE_ARB)
4278 PUSH1(WGL_DOUBLE_BUFFER_ARB)
4279 PUSH1(WGL_AUX_BUFFERS_ARB)
4281 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
4282 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4284 if(!res)
4285 continue;
4287 /* Cache the pixel format */
4288 cfgs->iPixelFormat = iPixelFormat;
4289 cfgs->redSize = values[0];
4290 cfgs->greenSize = values[1];
4291 cfgs->blueSize = values[2];
4292 cfgs->alphaSize = values[3];
4293 cfgs->depthSize = values[4];
4294 cfgs->stencilSize = values[5];
4295 cfgs->windowDrawable = values[6];
4296 cfgs->iPixelType = values[7];
4297 cfgs->doubleBuffer = values[8];
4298 cfgs->auxBuffers = values[9];
4300 cfgs->pbufferDrawable = FALSE;
4301 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4302 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4303 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4304 int value;
4305 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4306 cfgs->pbufferDrawable = value;
4309 cfgs->numSamples = 0;
4310 /* Check multisample support */
4311 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4312 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4313 int value[2];
4314 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4315 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4316 * value[1] = number of multi sample buffers*/
4317 if(value[0])
4318 cfgs->numSamples = value[1];
4322 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);
4323 cfgs++;
4326 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4327 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4328 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4329 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4330 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4331 * driver is allowed to consume more bits EXCEPT for stencil bits.
4333 * Mark an adapter with this broken stencil behavior.
4335 Adapters[0].brokenStencil = TRUE;
4336 for(i=0, cfgs=Adapters[0].cfgs; i<Adapters[0].nCfgs; i++) {
4337 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4338 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4339 Adapters[0].brokenStencil = FALSE;
4340 break;
4344 fixup_extensions(&Adapters[0].gl_info);
4345 add_gl_compat_wrappers(&Adapters[0].gl_info);
4347 WineD3D_ReleaseFakeGLContext();
4349 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4350 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
4351 fillGLAttribFuncs(&Adapters[0].gl_info);
4352 init_type_lookup(&Adapters[0].gl_info);
4353 Adapters[0].opengl = TRUE;
4355 numAdapters = 1;
4356 TRACE("%d adapters successfully initialized\n", numAdapters);
4358 return TRUE;
4360 nogl_adapter:
4361 /* Initialize an adapter for ddraw-only memory counting */
4362 memset(Adapters, 0, sizeof(Adapters));
4363 Adapters[0].num = 0;
4364 Adapters[0].opengl = FALSE;
4365 Adapters[0].monitorPoint.x = -1;
4366 Adapters[0].monitorPoint.y = -1;
4368 Adapters[0].driver = "Display";
4369 Adapters[0].description = "WineD3D DirectDraw Emulation";
4370 if(wined3d_settings.emulated_textureram) {
4371 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4372 } else {
4373 Adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4376 numAdapters = 1;
4377 return FALSE;
4379 #undef PUSH1
4380 #undef GLINFO_LOCATION
4382 /**********************************************************
4383 * IWineD3D VTbl follows
4384 **********************************************************/
4386 const IWineD3DVtbl IWineD3D_Vtbl =
4388 /* IUnknown */
4389 IWineD3DImpl_QueryInterface,
4390 IWineD3DImpl_AddRef,
4391 IWineD3DImpl_Release,
4392 /* IWineD3D */
4393 IWineD3DImpl_GetParent,
4394 IWineD3DImpl_GetAdapterCount,
4395 IWineD3DImpl_RegisterSoftwareDevice,
4396 IWineD3DImpl_GetAdapterMonitor,
4397 IWineD3DImpl_GetAdapterModeCount,
4398 IWineD3DImpl_EnumAdapterModes,
4399 IWineD3DImpl_GetAdapterDisplayMode,
4400 IWineD3DImpl_GetAdapterIdentifier,
4401 IWineD3DImpl_CheckDeviceMultiSampleType,
4402 IWineD3DImpl_CheckDepthStencilMatch,
4403 IWineD3DImpl_CheckDeviceType,
4404 IWineD3DImpl_CheckDeviceFormat,
4405 IWineD3DImpl_CheckDeviceFormatConversion,
4406 IWineD3DImpl_GetDeviceCaps,
4407 IWineD3DImpl_CreateDevice