jscript: Implement the String.fixed() method.
[wine/hacks.git] / dlls / wined3d / directx.c
blob23a455c0ce322438cc59ce2642f89784af552b9e
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];
190 glAttribFunc texcoord_funcs[WINED3DDECLTYPE_UNUSED];
193 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
194 * i.e., there is no GL Context - Get a default rendering context to enable the
195 * function query some info from GL.
198 static int wined3d_fake_gl_context_ref = 0;
199 static BOOL wined3d_fake_gl_context_foreign;
200 static BOOL wined3d_fake_gl_context_available = FALSE;
201 static HDC wined3d_fake_gl_context_hdc = NULL;
202 static HWND wined3d_fake_gl_context_hwnd = NULL;
204 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
205 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
207 0, 0, &wined3d_fake_gl_context_cs,
208 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
209 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
210 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
212 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
214 static void WineD3D_ReleaseFakeGLContext(void) {
215 HGLRC glCtx;
217 EnterCriticalSection(&wined3d_fake_gl_context_cs);
219 if(!wined3d_fake_gl_context_available) {
220 TRACE_(d3d_caps)("context not available\n");
221 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
222 return;
225 glCtx = pwglGetCurrentContext();
227 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
228 if (0 == (--wined3d_fake_gl_context_ref) ) {
229 if(!wined3d_fake_gl_context_foreign && glCtx) {
230 TRACE_(d3d_caps)("destroying fake GL context\n");
231 pwglMakeCurrent(NULL, NULL);
232 pwglDeleteContext(glCtx);
234 if(wined3d_fake_gl_context_hdc)
235 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
236 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
237 if(wined3d_fake_gl_context_hwnd)
238 DestroyWindow(wined3d_fake_gl_context_hwnd);
239 wined3d_fake_gl_context_hwnd = NULL;
240 wined3d_fake_gl_context_available = FALSE;
242 assert(wined3d_fake_gl_context_ref >= 0);
244 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
247 static BOOL WineD3D_CreateFakeGLContext(void) {
248 HGLRC glCtx = NULL;
250 EnterCriticalSection(&wined3d_fake_gl_context_cs);
252 TRACE("getting context...\n");
253 if(wined3d_fake_gl_context_ref > 0) goto ret;
254 assert(0 == wined3d_fake_gl_context_ref);
256 wined3d_fake_gl_context_foreign = TRUE;
258 glCtx = pwglGetCurrentContext();
259 if (!glCtx) {
260 PIXELFORMATDESCRIPTOR pfd;
261 int iPixelFormat;
263 wined3d_fake_gl_context_foreign = FALSE;
265 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
266 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
267 if(!wined3d_fake_gl_context_hwnd) {
268 ERR("HWND creation failed!\n");
269 goto fail;
271 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
272 if(!wined3d_fake_gl_context_hdc) {
273 ERR("GetDC failed!\n");
274 goto fail;
277 /* PixelFormat selection */
278 ZeroMemory(&pfd, sizeof(pfd));
279 pfd.nSize = sizeof(pfd);
280 pfd.nVersion = 1;
281 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
282 pfd.iPixelType = PFD_TYPE_RGBA;
283 pfd.cColorBits = 32;
284 pfd.iLayerType = PFD_MAIN_PLANE;
286 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
287 if(!iPixelFormat) {
288 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
289 ERR("Can't find a suitable iPixelFormat\n");
290 goto fail;
292 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
293 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
295 /* Create a GL context */
296 glCtx = pwglCreateContext(wined3d_fake_gl_context_hdc);
297 if (!glCtx) {
298 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
299 goto fail;
302 /* Make it the current GL context */
303 if (!pwglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
304 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
305 goto fail;
309 ret:
310 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
311 wined3d_fake_gl_context_ref++;
312 wined3d_fake_gl_context_available = TRUE;
313 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
314 return TRUE;
315 fail:
316 if(wined3d_fake_gl_context_hdc)
317 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
318 wined3d_fake_gl_context_hdc = NULL;
319 if(wined3d_fake_gl_context_hwnd)
320 DestroyWindow(wined3d_fake_gl_context_hwnd);
321 wined3d_fake_gl_context_hwnd = NULL;
322 if(glCtx) pwglDeleteContext(glCtx);
323 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
324 return FALSE;
327 /* Adjust the amount of used texture memory */
328 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
329 UINT Adapter = D3DDevice->adapterNo;
331 Adapters[Adapter].UsedTextureRam += glram;
332 TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
333 return Adapters[Adapter].UsedTextureRam;
336 /**********************************************************
337 * IUnknown parts follows
338 **********************************************************/
340 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
344 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
345 if (IsEqualGUID(riid, &IID_IUnknown)
346 || IsEqualGUID(riid, &IID_IWineD3DBase)
347 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
348 IUnknown_AddRef(iface);
349 *ppobj = This;
350 return S_OK;
352 *ppobj = NULL;
353 return E_NOINTERFACE;
356 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
357 IWineD3DImpl *This = (IWineD3DImpl *)iface;
358 ULONG refCount = InterlockedIncrement(&This->ref);
360 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
361 return refCount;
364 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
365 IWineD3DImpl *This = (IWineD3DImpl *)iface;
366 ULONG ref;
367 TRACE("(%p) : Releasing from %d\n", This, This->ref);
368 ref = InterlockedDecrement(&This->ref);
369 if (ref == 0) {
370 HeapFree(GetProcessHeap(), 0, This);
373 return ref;
376 /* Set the shader type for this device, depending on the given capabilities,
377 * the device type, and the user preferences in wined3d_settings */
379 static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
381 if (wined3d_settings.vs_mode == VS_NONE) {
382 *vs_selected = SHADER_NONE;
383 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
384 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
385 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
386 * shaders only on this card. */
387 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
388 *vs_selected = SHADER_ARB;
389 else
390 *vs_selected = SHADER_GLSL;
391 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
392 *vs_selected = SHADER_ARB;
393 } else {
394 *vs_selected = SHADER_NONE;
397 if (wined3d_settings.ps_mode == PS_NONE) {
398 *ps_selected = SHADER_NONE;
399 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
400 *ps_selected = SHADER_GLSL;
401 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
402 *ps_selected = SHADER_ARB;
403 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
404 *ps_selected = SHADER_ATI;
405 } else {
406 *ps_selected = SHADER_NONE;
410 /** Select the number of report maximum shader constants based on the selected shader modes */
411 static void select_shader_max_constants(
412 int ps_selected_mode,
413 int vs_selected_mode,
414 WineD3D_GL_Info *gl_info) {
416 switch (vs_selected_mode) {
417 case SHADER_GLSL:
418 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
419 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
420 break;
421 case SHADER_ARB:
422 /* We have to subtract any other PARAMs that we might use in our shader programs.
423 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
424 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
425 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
426 break;
427 default:
428 gl_info->max_vshader_constantsF = 0;
429 break;
432 switch (ps_selected_mode) {
433 case SHADER_GLSL:
434 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
435 * In theory the texbem instruction may need one more shader constant too. But lets assume
436 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
437 * and lets not take away a uniform needlessly from all other shaders.
439 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
440 break;
441 case SHADER_ARB:
442 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
443 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
445 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
446 break;
447 default:
448 gl_info->max_pshader_constantsF = 0;
449 break;
453 /**********************************************************
454 * IWineD3D parts follows
455 **********************************************************/
457 #define GLINFO_LOCATION (*gl_info)
458 static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
460 GLuint prog;
461 BOOL ret = FALSE;
462 const char *testcode =
463 "!!ARBvp1.0\n"
464 "PARAM C[66] = { program.env[0..65] };\n"
465 "ADDRESS A0;"
466 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
467 "ARL A0.x, zero.x;\n"
468 "MOV result.position, C[A0.x + 65];\n"
469 "END\n";
471 while(glGetError());
472 GL_EXTCALL(glGenProgramsARB(1, &prog));
473 if(!prog) {
474 ERR("Failed to create an ARB offset limit test program\n");
476 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
477 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
478 strlen(testcode), testcode));
479 if(glGetError() != 0) {
480 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
481 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
482 ret = TRUE;
483 } else TRACE("OpenGL implementation allows offsets > 63\n");
485 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
486 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
487 checkGLcall("ARB vp offset limit test cleanup\n");
489 return ret;
492 static DWORD ver_for_ext(GL_SupportedExt ext)
494 unsigned int i;
495 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
496 if(EXTENSION_MAP[i].extension == ext) {
497 return EXTENSION_MAP[i].version;
500 return 0;
503 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
504 const char *GL_Extensions = NULL;
505 const char *WGL_Extensions = NULL;
506 const char *gl_string = NULL;
507 const char *gl_string_cursor = NULL;
508 GLint gl_max;
509 GLfloat gl_floatv[2];
510 int major = 1, minor = 0;
511 BOOL return_value = TRUE;
512 unsigned i;
513 HDC hdc;
514 unsigned int vidmem=0;
516 TRACE_(d3d_caps)("(%p)\n", gl_info);
518 ENTER_GL();
520 gl_string = (const char *) glGetString(GL_RENDERER);
521 if (NULL == gl_string)
522 gl_string = "None";
523 strcpy(gl_info->gl_renderer, gl_string);
525 gl_string = (const char *) glGetString(GL_VENDOR);
526 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
527 if (gl_string != NULL) {
528 /* Fill in the GL vendor */
529 if (strstr(gl_string, "NVIDIA")) {
530 gl_info->gl_vendor = VENDOR_NVIDIA;
531 } else if (strstr(gl_string, "ATI")) {
532 gl_info->gl_vendor = VENDOR_ATI;
533 } else if (strstr(gl_string, "Intel(R)") ||
534 strstr(gl_info->gl_renderer, "Intel(R)") ||
535 strstr(gl_string, "Intel Inc.")) {
536 gl_info->gl_vendor = VENDOR_INTEL;
537 } else if (strstr(gl_string, "Mesa")) {
538 gl_info->gl_vendor = VENDOR_MESA;
539 } else {
540 gl_info->gl_vendor = VENDOR_WINE;
542 } else {
543 gl_info->gl_vendor = VENDOR_WINE;
547 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
549 /* Parse the GL_VERSION field into major and minor information */
550 gl_string = (const char *) glGetString(GL_VERSION);
551 if (gl_string != NULL) {
553 /* First, parse the generic opengl version. This is supposed not to be convoluted with
554 * driver specific information
556 gl_string_cursor = gl_string;
557 major = atoi(gl_string_cursor);
558 if(major <= 0) {
559 ERR("Invalid opengl major version: %d\n", major);
561 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
562 ++gl_string_cursor;
564 if (*gl_string_cursor++ != '.') {
565 ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
567 minor = atoi(gl_string_cursor);
568 TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
569 gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
571 /* Now parse the driver specific string which we'll report to the app */
572 switch (gl_info->gl_vendor) {
573 case VENDOR_NVIDIA:
574 gl_string_cursor = strstr(gl_string, "NVIDIA");
575 if (!gl_string_cursor) {
576 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
577 break;
580 gl_string_cursor = strstr(gl_string_cursor, " ");
581 if (!gl_string_cursor) {
582 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
583 break;
586 while (*gl_string_cursor == ' ') {
587 ++gl_string_cursor;
590 if (!*gl_string_cursor) {
591 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
592 break;
595 major = atoi(gl_string_cursor);
596 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
597 ++gl_string_cursor;
600 if (*gl_string_cursor++ != '.') {
601 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
602 break;
605 minor = atoi(gl_string_cursor);
606 minor = major*100+minor;
607 major = 10;
609 break;
611 case VENDOR_ATI:
612 major = minor = 0;
613 gl_string_cursor = strchr(gl_string, '-');
614 if (gl_string_cursor) {
615 int error = 0;
616 gl_string_cursor++;
618 /* Check if version number is of the form x.y.z */
619 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
620 error = 1;
621 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
622 error = 1;
623 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
624 error = 1;
625 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
626 error = 1;
628 /* Mark version number as malformed */
629 if (error)
630 gl_string_cursor = 0;
633 if (!gl_string_cursor)
634 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
635 else {
636 major = *gl_string_cursor - '0';
637 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
639 break;
641 case VENDOR_INTEL:
642 /* Apple and Mesa version strings look differently, but both provide intel drivers */
643 if(strstr(gl_string, "APPLE")) {
644 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
645 * We only need the first part, and use the APPLE as identification
646 * "1.2 APPLE-1.4.56"
648 gl_string_cursor = gl_string;
649 major = atoi(gl_string_cursor);
650 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
651 ++gl_string_cursor;
654 if (*gl_string_cursor++ != '.') {
655 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
656 break;
659 minor = atoi(gl_string_cursor);
660 break;
663 case VENDOR_MESA:
664 gl_string_cursor = strstr(gl_string, "Mesa");
665 gl_string_cursor = strstr(gl_string_cursor, " ");
666 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
667 if (*gl_string_cursor) {
668 char tmp[16];
669 int cursor = 0;
671 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
672 tmp[cursor++] = *gl_string_cursor;
673 ++gl_string_cursor;
675 tmp[cursor] = 0;
676 major = atoi(tmp);
678 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
679 ++gl_string_cursor;
681 cursor = 0;
682 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
683 tmp[cursor++] = *gl_string_cursor;
684 ++gl_string_cursor;
686 tmp[cursor] = 0;
687 minor = atoi(tmp);
689 break;
691 default:
692 major = 0;
693 minor = 9;
695 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
696 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
697 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
698 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
699 } else {
700 FIXME("OpenGL driver did not return version information\n");
701 gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
702 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
705 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
708 * Initialize openGL extension related variables
709 * with Default values
711 memset(gl_info->supported, 0, sizeof(gl_info->supported));
712 gl_info->max_buffers = 1;
713 gl_info->max_textures = 1;
714 gl_info->max_texture_stages = 1;
715 gl_info->max_fragment_samplers = 1;
716 gl_info->max_vertex_samplers = 0;
717 gl_info->max_combined_samplers = 0;
718 gl_info->max_sampler_stages = 1;
719 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
720 gl_info->ps_arb_max_temps = 0;
721 gl_info->ps_arb_max_instructions = 0;
722 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
723 gl_info->vs_arb_max_temps = 0;
724 gl_info->vs_arb_max_instructions = 0;
725 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
726 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
727 gl_info->vs_glsl_constantsF = 0;
728 gl_info->ps_glsl_constantsF = 0;
729 gl_info->vs_arb_constantsF = 0;
730 gl_info->ps_arb_constantsF = 0;
732 /* Retrieve opengl defaults */
733 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
734 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
735 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
737 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
738 gl_info->max_lights = gl_max;
739 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
741 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
742 gl_info->max_texture_size = gl_max;
743 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
745 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
746 gl_info->max_pointsizemin = gl_floatv[0];
747 gl_info->max_pointsize = gl_floatv[1];
748 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
750 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
751 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
752 TRACE_(d3d_caps)("GL_Extensions reported:\n");
754 if (NULL == GL_Extensions) {
755 ERR(" GL_Extensions returns NULL\n");
756 } else {
757 while (*GL_Extensions != 0x00) {
758 const char *Start;
759 char ThisExtn[256];
760 size_t len;
762 while (isspace(*GL_Extensions)) GL_Extensions++;
763 Start = GL_Extensions;
764 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
765 GL_Extensions++;
768 len = GL_Extensions - Start;
769 if (len == 0 || len >= sizeof(ThisExtn))
770 continue;
772 memcpy(ThisExtn, Start, len);
773 ThisExtn[len] = '\0';
774 TRACE_(d3d_caps)("- %s\n", ThisExtn);
776 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
777 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
778 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
779 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
780 break;
785 LEAVE_GL();
787 /* Now work out what GL support this card really has */
788 #define USE_GL_FUNC(type, pfn, ext, replace) { \
789 DWORD ver = ver_for_ext(ext); \
790 if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
791 else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
792 else gl_info->pfn = NULL; \
794 GL_EXT_FUNCS_GEN;
795 #undef USE_GL_FUNC
797 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type) pwglGetProcAddress(#pfn);
798 WGL_EXT_FUNCS_GEN;
799 #undef USE_GL_FUNC
801 ENTER_GL();
802 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
803 * loading the functions, otherwise the code above will load the extension entry points instead of the
804 * core functions, which may not work
806 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
807 if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
808 EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
809 TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
810 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
814 if (gl_info->supported[APPLE_FENCE]) {
815 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
816 * The apple extension interacts with some other apple exts. Disable the NV
817 * extension if the apple one is support to prevent confusion in other parts
818 * of the code
820 gl_info->supported[NV_FENCE] = FALSE;
822 if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
823 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
825 * The enums are the same:
826 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
827 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
828 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
829 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
830 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
832 if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
833 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
834 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
836 if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
837 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
838 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
841 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
842 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
843 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
845 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
846 if(gl_info->supported[NV_REGISTER_COMBINERS]) {
847 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
848 * are supported. The nv extensions provide the same functionality as the
849 * ATI one, and a bit more(signed pixelformats)
851 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
854 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
855 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
856 gl_info->max_buffers = gl_max;
857 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
859 if (gl_info->supported[ARB_MULTITEXTURE]) {
860 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
861 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
862 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
864 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
865 GLint tmp;
866 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
867 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
868 } else {
869 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
871 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
873 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
874 GLint tmp;
875 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
876 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
877 } else {
878 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
880 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
882 if (gl_info->supported[ARB_VERTEX_SHADER]) {
883 GLint tmp;
884 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
885 gl_info->max_vertex_samplers = tmp;
886 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
887 gl_info->max_combined_samplers = tmp;
889 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
890 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
891 * an issue because then the sampler setup only depends on the two shaders. If a pixel
892 * shader is used with fixed function vertex processing we're fine too because fixed function
893 * vertex processing doesn't use any samplers. If fixed function fragment processing is
894 * used we have to make sure that all vertex sampler setups are valid together with all
895 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
896 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
897 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
898 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
899 * a fixed function pipeline anymore.
901 * So this is just a check to check that our assumption holds true. If not, write a warning
902 * and reduce the number of vertex samplers or probably disable vertex texture fetch.
904 if(gl_info->max_vertex_samplers &&
905 MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
906 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
907 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
908 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
909 if( gl_info->max_combined_samplers > MAX_TEXTURES )
910 gl_info->max_vertex_samplers =
911 gl_info->max_combined_samplers - MAX_TEXTURES;
912 else
913 gl_info->max_vertex_samplers = 0;
915 } else {
916 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
918 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
919 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
921 if (gl_info->supported[ARB_VERTEX_BLEND]) {
922 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
923 gl_info->max_blends = gl_max;
924 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
926 if (gl_info->supported[EXT_TEXTURE3D]) {
927 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
928 gl_info->max_texture3d_size = gl_max;
929 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
931 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
932 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
933 gl_info->max_anisotropy = gl_max;
934 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
936 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
937 gl_info->ps_arb_version = PS_VERSION_11;
938 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
939 gl_info->ps_arb_constantsF = gl_max;
940 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
941 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
942 gl_info->ps_arb_max_temps = gl_max;
943 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d\n", gl_info->ps_arb_max_temps);
944 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
945 gl_info->ps_arb_max_instructions = gl_max;
946 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d\n", gl_info->ps_arb_max_instructions);
948 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
949 gl_info->vs_arb_version = VS_VERSION_11;
950 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
951 gl_info->vs_arb_constantsF = gl_max;
952 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
953 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
954 gl_info->vs_arb_max_temps = gl_max;
955 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d\n", gl_info->vs_arb_max_temps);
956 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
957 gl_info->vs_arb_max_instructions = gl_max;
958 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d\n", gl_info->vs_arb_max_instructions);
960 gl_info->arb_vs_offset_limit = test_arb_vs_offset_limit(gl_info);
962 if (gl_info->supported[ARB_VERTEX_SHADER]) {
963 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
964 gl_info->vs_glsl_constantsF = gl_max / 4;
965 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
967 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
968 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
969 gl_info->ps_glsl_constantsF = gl_max / 4;
970 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
971 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
972 gl_info->max_glsl_varyings = gl_max;
973 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings)\n", gl_max, gl_max / 4);
975 if (gl_info->supported[EXT_VERTEX_SHADER]) {
976 gl_info->vs_ati_version = VS_VERSION_11;
978 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
979 gl_info->vs_nv_version = VS_VERSION_30;
980 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
981 gl_info->vs_nv_version = VS_VERSION_20;
982 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
983 gl_info->vs_nv_version = VS_VERSION_11;
984 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
985 gl_info->vs_nv_version = VS_VERSION_10;
987 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
988 gl_info->ps_nv_version = PS_VERSION_30;
989 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
990 gl_info->ps_nv_version = PS_VERSION_20;
992 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
993 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
994 } else {
995 gl_info->max_shininess = 128.0;
997 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
998 /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
999 * This saves a few redundant glDisable calls
1001 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1003 if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
1004 /* Disable NV_register_combiners and fragment shader if this is supported.
1005 * generally the NV extensions are preferred over the ATI ones, and this
1006 * extension is disabled if register_combiners and texture_shader2 are both
1007 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1008 * fragment processing support
1010 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1011 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1012 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1013 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1014 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1018 checkGLcall("extension detection\n");
1020 /* In some cases the number of texture stages can be larger than the number
1021 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1022 * shaders), but 8 texture stages (register combiners). */
1023 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1025 /* We can only use ORM_FBO when the hardware supports it. */
1026 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1027 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
1028 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
1031 /* MRTs are currently only supported when FBOs are used. */
1032 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1033 gl_info->max_buffers = 1;
1036 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1037 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1038 * in case of the latest videocards in the number of pixel/vertex pipelines.
1040 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1041 * rendering. Various games use this information to get a rough estimation of the features of the card
1042 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1043 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1044 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1045 * not the PCI id.
1047 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1048 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1049 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1050 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1051 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1052 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1053 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1054 * is limited.
1056 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1057 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1058 * similar 3d features.
1060 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1061 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1062 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1063 * won't pass we return a default card. This way is better than maintaining a full card database as even
1064 * without a full database we can return a card with similar features. Second the size of the database
1065 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1066 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1067 * to distinguishes between different models from that family.
1069 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1070 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1071 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1072 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1073 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1074 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1075 * memory behind our backs if really needed.
1076 * Note that the amount of video memory can be overruled using a registry setting.
1078 switch (gl_info->gl_vendor) {
1079 case VENDOR_NVIDIA:
1080 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1081 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1083 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1084 /* Geforce GTX - highend */
1085 if(strstr(gl_info->gl_renderer, "GTX 280")) {
1086 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1087 vidmem = 1024;
1089 /* Geforce9 - highend */
1090 else if(strstr(gl_info->gl_renderer, "9800")) {
1091 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1092 vidmem = 512;
1094 /* Geforce9 - midend */
1095 else if(strstr(gl_info->gl_renderer, "9600")) {
1096 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1097 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1099 /* Geforce8 - highend */
1100 else if (strstr(gl_info->gl_renderer, "8800")) {
1101 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1102 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1104 /* Geforce8 - midend mobile */
1105 else if(strstr(gl_info->gl_renderer, "8600 M")) {
1106 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1107 vidmem = 512;
1109 /* Geforce8 - midend */
1110 else if(strstr(gl_info->gl_renderer, "8600") ||
1111 strstr(gl_info->gl_renderer, "8700"))
1113 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1114 vidmem = 256;
1116 /* Geforce8 - lowend */
1117 else if(strstr(gl_info->gl_renderer, "8300") ||
1118 strstr(gl_info->gl_renderer, "8400") ||
1119 strstr(gl_info->gl_renderer, "8500"))
1121 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1122 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1124 /* Geforce7 - highend */
1125 else if(strstr(gl_info->gl_renderer, "7800") ||
1126 strstr(gl_info->gl_renderer, "7900") ||
1127 strstr(gl_info->gl_renderer, "7950") ||
1128 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
1129 strstr(gl_info->gl_renderer, "Quadro FX 5"))
1131 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1132 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1134 /* Geforce7 midend */
1135 else if(strstr(gl_info->gl_renderer, "7600") ||
1136 strstr(gl_info->gl_renderer, "7700")) {
1137 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1138 vidmem = 256; /* The 7600 uses 256-512MB */
1139 /* Geforce7 lower medium */
1140 } else if(strstr(gl_info->gl_renderer, "7400")) {
1141 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1142 vidmem = 256; /* The 7400 uses 256-512MB */
1144 /* Geforce7 lowend */
1145 else if(strstr(gl_info->gl_renderer, "7300")) {
1146 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1147 vidmem = 256; /* Mac Pros with this card have 256 MB */
1149 /* Geforce6 highend */
1150 else if(strstr(gl_info->gl_renderer, "6800"))
1152 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1153 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1155 /* Geforce6 - midend */
1156 else if(strstr(gl_info->gl_renderer, "6600") ||
1157 strstr(gl_info->gl_renderer, "6610") ||
1158 strstr(gl_info->gl_renderer, "6700"))
1160 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1161 vidmem = 128; /* A 6600GT has 128-256MB */
1163 /* Geforce6/7 lowend */
1164 else {
1165 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1166 vidmem = 64; /* */
1168 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1169 /* GeforceFX - highend */
1170 if (strstr(gl_info->gl_renderer, "5800") ||
1171 strstr(gl_info->gl_renderer, "5900") ||
1172 strstr(gl_info->gl_renderer, "5950") ||
1173 strstr(gl_info->gl_renderer, "Quadro FX"))
1175 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1176 vidmem = 256; /* 5800-5900 cards use 256MB */
1178 /* GeforceFX - midend */
1179 else if(strstr(gl_info->gl_renderer, "5600") ||
1180 strstr(gl_info->gl_renderer, "5650") ||
1181 strstr(gl_info->gl_renderer, "5700") ||
1182 strstr(gl_info->gl_renderer, "5750"))
1184 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1185 vidmem = 128; /* A 5600 uses 128-256MB */
1187 /* GeforceFX - lowend */
1188 else {
1189 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1190 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1192 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1193 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4")) {
1194 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1195 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1197 else {
1198 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1199 vidmem = 64; /* Geforce3 cards have 64-128MB */
1201 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1202 if (strstr(gl_info->gl_renderer, "GeForce4 MX")) {
1203 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1204 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1206 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR")) {
1207 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1208 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1210 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2")) {
1211 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1212 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1214 else {
1215 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1216 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1218 } else {
1219 if (strstr(gl_info->gl_renderer, "TNT2")) {
1220 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1221 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1223 else {
1224 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1225 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1228 break;
1229 case VENDOR_ATI:
1230 if(WINE_D3D9_CAPABLE(gl_info)) {
1231 /* Radeon R6xx HD2900/HD3800 - highend */
1232 if (strstr(gl_info->gl_renderer, "HD 2900") ||
1233 strstr(gl_info->gl_renderer, "HD 3870") ||
1234 strstr(gl_info->gl_renderer, "HD 3850"))
1236 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1237 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1239 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1240 else if (strstr(gl_info->gl_renderer, "HD 2600") ||
1241 strstr(gl_info->gl_renderer, "HD 3830") ||
1242 strstr(gl_info->gl_renderer, "HD 3690") ||
1243 strstr(gl_info->gl_renderer, "HD 3650"))
1245 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1246 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1248 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1249 else if (strstr(gl_info->gl_renderer, "HD 2300") ||
1250 strstr(gl_info->gl_renderer, "HD 2400") ||
1251 strstr(gl_info->gl_renderer, "HD 3470") ||
1252 strstr(gl_info->gl_renderer, "HD 3450") ||
1253 strstr(gl_info->gl_renderer, "HD 3430"))
1255 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1256 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1258 /* Radeon R6xx/R7xx integrated */
1259 else if (strstr(gl_info->gl_renderer, "HD 3100") ||
1260 strstr(gl_info->gl_renderer, "HD 3200") ||
1261 strstr(gl_info->gl_renderer, "HD 3300"))
1263 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1264 vidmem = 128; /* 128MB */
1266 /* Radeon R5xx */
1267 else if (strstr(gl_info->gl_renderer, "X1600") ||
1268 strstr(gl_info->gl_renderer, "X1650") ||
1269 strstr(gl_info->gl_renderer, "X1800") ||
1270 strstr(gl_info->gl_renderer, "X1900") ||
1271 strstr(gl_info->gl_renderer, "X1950"))
1273 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1274 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1276 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1277 else if(strstr(gl_info->gl_renderer, "X700") ||
1278 strstr(gl_info->gl_renderer, "X800") ||
1279 strstr(gl_info->gl_renderer, "X850") ||
1280 strstr(gl_info->gl_renderer, "X1300") ||
1281 strstr(gl_info->gl_renderer, "X1400") ||
1282 strstr(gl_info->gl_renderer, "X1450") ||
1283 strstr(gl_info->gl_renderer, "X1550"))
1285 gl_info->gl_card = CARD_ATI_RADEON_X700;
1286 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1288 /* Radeon R3xx */
1289 else {
1290 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1291 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1293 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1294 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1295 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1296 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1297 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1298 vidmem = 32; /* There are models with up to 64MB */
1299 } else {
1300 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1301 vidmem = 16; /* There are 16-32MB models */
1303 break;
1304 case VENDOR_INTEL:
1305 if (strstr(gl_info->gl_renderer, "GMA 950")) {
1306 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1307 gl_info->gl_card = CARD_INTEL_I945GM;
1308 vidmem = 64;
1309 } else if (strstr(gl_info->gl_renderer, "915GM")) {
1310 gl_info->gl_card = CARD_INTEL_I915GM;
1311 } else if (strstr(gl_info->gl_renderer, "915G")) {
1312 gl_info->gl_card = CARD_INTEL_I915G;
1313 } else if (strstr(gl_info->gl_renderer, "865G")) {
1314 gl_info->gl_card = CARD_INTEL_I865G;
1315 } else if (strstr(gl_info->gl_renderer, "855G")) {
1316 gl_info->gl_card = CARD_INTEL_I855G;
1317 } else if (strstr(gl_info->gl_renderer, "830G")) {
1318 gl_info->gl_card = CARD_INTEL_I830G;
1319 } else {
1320 gl_info->gl_card = CARD_INTEL_I915G;
1322 break;
1323 case VENDOR_MESA:
1324 case VENDOR_WINE:
1325 default:
1326 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1327 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1328 * them a good generic choice.
1330 gl_info->gl_vendor = VENDOR_NVIDIA;
1331 if(WINE_D3D9_CAPABLE(gl_info))
1332 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1333 else if(WINE_D3D8_CAPABLE(gl_info))
1334 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1335 else if(WINE_D3D7_CAPABLE(gl_info))
1336 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1337 else if(WINE_D3D6_CAPABLE(gl_info))
1338 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1339 else
1340 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1342 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1344 /* If we have an estimate use it, else default to 64MB; */
1345 if(vidmem)
1346 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1347 else
1348 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1350 /* Load all the lookup tables */
1351 for (i = 0; i < MAX_LOOKUPS; i++) {
1352 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1355 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1356 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1357 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1358 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1359 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1360 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1361 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1362 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1363 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1364 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1366 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1367 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1368 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1369 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1370 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
1373 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1374 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
1375 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
1376 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
1377 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
1378 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
1379 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
1380 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
1381 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
1382 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
1383 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1384 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
1385 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
1386 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
1387 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
1389 /* TODO: config lookups */
1391 /* Make sure there's an active HDC else the WGL extensions will fail */
1392 hdc = pwglGetCurrentDC();
1393 if (hdc) {
1394 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1395 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1397 if (NULL == WGL_Extensions) {
1398 ERR(" WGL_Extensions returns NULL\n");
1399 } else {
1400 while (*WGL_Extensions != 0x00) {
1401 const char *Start;
1402 char ThisExtn[256];
1403 size_t len;
1405 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1406 Start = WGL_Extensions;
1407 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1408 WGL_Extensions++;
1411 len = WGL_Extensions - Start;
1412 if (len == 0 || len >= sizeof(ThisExtn))
1413 continue;
1415 memcpy(ThisExtn, Start, len);
1416 ThisExtn[len] = '\0';
1417 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1419 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1420 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1421 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1423 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1424 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1425 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1430 LEAVE_GL();
1432 return return_value;
1434 #undef GLINFO_LOCATION
1436 /**********************************************************
1437 * IWineD3D implementation follows
1438 **********************************************************/
1440 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1441 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1443 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1444 return numAdapters;
1447 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1448 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1449 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1450 return WINED3D_OK;
1453 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1454 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1456 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1458 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1459 return NULL;
1462 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1465 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1466 of the same bpp but different resolutions */
1468 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1469 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1470 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1471 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1473 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1474 return 0;
1477 /* TODO: Store modes per adapter and read it from the adapter structure */
1478 if (Adapter == 0) { /* Display */
1479 int i = 0;
1480 int j = 0;
1482 if (!DEBUG_SINGLE_MODE) {
1483 DEVMODEW DevModeW;
1485 ZeroMemory(&DevModeW, sizeof(DevModeW));
1486 DevModeW.dmSize = sizeof(DevModeW);
1487 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1488 j++;
1489 switch (Format)
1491 case WINED3DFMT_UNKNOWN:
1492 /* This is for D3D8, do not enumerate P8 here */
1493 if (DevModeW.dmBitsPerPel == 32 ||
1494 DevModeW.dmBitsPerPel == 16) i++;
1495 break;
1496 case WINED3DFMT_X8R8G8B8:
1497 if (DevModeW.dmBitsPerPel == 32) i++;
1498 break;
1499 case WINED3DFMT_R5G6B5:
1500 if (DevModeW.dmBitsPerPel == 16) i++;
1501 break;
1502 case WINED3DFMT_P8:
1503 if (DevModeW.dmBitsPerPel == 8) i++;
1504 break;
1505 default:
1506 /* Skip other modes as they do not match the requested format */
1507 break;
1510 } else {
1511 i = 1;
1512 j = 1;
1515 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1516 return i;
1517 } else {
1518 FIXME_(d3d_caps)("Adapter not primary display\n");
1520 return 0;
1523 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1524 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1525 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1526 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1528 /* Validate the parameters as much as possible */
1529 if (NULL == pMode ||
1530 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1531 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1532 return WINED3DERR_INVALIDCALL;
1535 /* TODO: Store modes per adapter and read it from the adapter structure */
1536 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1537 DEVMODEW DevModeW;
1538 int ModeIdx = 0;
1539 UINT i = 0;
1540 int j = 0;
1542 ZeroMemory(&DevModeW, sizeof(DevModeW));
1543 DevModeW.dmSize = sizeof(DevModeW);
1545 /* If we are filtering to a specific format (D3D9), then need to skip
1546 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1547 just count through the ones with valid bit depths */
1548 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1549 switch (Format)
1551 case WINED3DFMT_UNKNOWN:
1552 /* This is D3D8. Do not enumerate P8 here */
1553 if (DevModeW.dmBitsPerPel == 32 ||
1554 DevModeW.dmBitsPerPel == 16) i++;
1555 break;
1556 case WINED3DFMT_X8R8G8B8:
1557 if (DevModeW.dmBitsPerPel == 32) i++;
1558 break;
1559 case WINED3DFMT_R5G6B5:
1560 if (DevModeW.dmBitsPerPel == 16) i++;
1561 break;
1562 case WINED3DFMT_P8:
1563 if (DevModeW.dmBitsPerPel == 8) i++;
1564 break;
1565 default:
1566 /* Modes that don't match what we support can get an early-out */
1567 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1568 return WINED3DERR_INVALIDCALL;
1572 if (i == 0) {
1573 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1574 return WINED3DERR_INVALIDCALL;
1576 ModeIdx = j - 1;
1578 /* Now get the display mode via the calculated index */
1579 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1580 pMode->Width = DevModeW.dmPelsWidth;
1581 pMode->Height = DevModeW.dmPelsHeight;
1582 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1583 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1584 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1586 if (Format == WINED3DFMT_UNKNOWN) {
1587 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
1588 } else {
1589 pMode->Format = Format;
1591 } else {
1592 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1593 return WINED3DERR_INVALIDCALL;
1596 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1597 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1598 DevModeW.dmBitsPerPel);
1600 } else if (DEBUG_SINGLE_MODE) {
1601 /* Return one setting of the format requested */
1602 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1603 pMode->Width = 800;
1604 pMode->Height = 600;
1605 pMode->RefreshRate = 60;
1606 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1607 } else {
1608 FIXME_(d3d_caps)("Adapter not primary display\n");
1611 return WINED3D_OK;
1614 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1615 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1616 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1618 if (NULL == pMode ||
1619 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1620 return WINED3DERR_INVALIDCALL;
1623 if (Adapter == 0) { /* Display */
1624 int bpp = 0;
1625 DEVMODEW DevModeW;
1627 ZeroMemory(&DevModeW, sizeof(DevModeW));
1628 DevModeW.dmSize = sizeof(DevModeW);
1630 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1631 pMode->Width = DevModeW.dmPelsWidth;
1632 pMode->Height = DevModeW.dmPelsHeight;
1633 bpp = DevModeW.dmBitsPerPel;
1634 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1635 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1637 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1640 pMode->Format = pixelformat_for_depth(bpp);
1641 } else {
1642 FIXME_(d3d_caps)("Adapter not primary display\n");
1645 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1646 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1647 return WINED3D_OK;
1650 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1651 and fields being inserted in the middle, a new structure is used in place */
1652 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1653 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1654 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1656 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1658 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1659 return WINED3DERR_INVALIDCALL;
1662 /* Return the information requested */
1663 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1664 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1665 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1667 /* Note dx8 doesn't supply a DeviceName */
1668 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1669 pIdentifier->DriverVersion->u.HighPart = Adapters[Adapter].gl_info.driver_version_hipart;
1670 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.driver_version;
1671 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1672 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1673 *(pIdentifier->SubSysId) = 0;
1674 *(pIdentifier->Revision) = 0;
1675 *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
1677 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1679 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
1680 *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
1683 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
1685 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
1686 *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
1689 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1690 *(pIdentifier->WHQLLevel) = 0;
1691 } else {
1692 *(pIdentifier->WHQLLevel) = 1;
1695 return WINED3D_OK;
1698 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1699 short redSize, greenSize, blueSize, alphaSize, colorBits;
1701 if(!cfg)
1702 return FALSE;
1704 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
1705 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1706 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1707 return FALSE;
1710 if(cfg->redSize < redSize)
1711 return FALSE;
1713 if(cfg->greenSize < greenSize)
1714 return FALSE;
1716 if(cfg->blueSize < blueSize)
1717 return FALSE;
1719 if(cfg->alphaSize < alphaSize)
1720 return FALSE;
1722 return TRUE;
1723 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
1724 if(Format == WINED3DFMT_R16F)
1725 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1726 if(Format == WINED3DFMT_G16R16F)
1727 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1728 if(Format == WINED3DFMT_A16B16G16R16F)
1729 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
1730 if(Format == WINED3DFMT_R32F)
1731 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1732 if(Format == WINED3DFMT_G32R32F)
1733 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
1734 if(Format == WINED3DFMT_A32B32G32R32F)
1735 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
1736 } else {
1737 /* Probably a color index mode */
1738 return FALSE;
1741 return FALSE;
1744 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1745 short depthSize, stencilSize;
1746 BOOL lockable = FALSE;
1748 if(!cfg)
1749 return FALSE;
1751 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1752 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1753 return FALSE;
1756 if((Format == WINED3DFMT_D16_LOCKABLE) || (Format == WINED3DFMT_D32F_LOCKABLE))
1757 lockable = TRUE;
1759 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
1760 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
1761 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
1762 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
1763 return FALSE;
1765 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
1766 * allow more stencil bits than requested. */
1767 if(cfg->stencilSize < stencilSize)
1768 return FALSE;
1770 return TRUE;
1773 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1774 WINED3DFORMAT AdapterFormat,
1775 WINED3DFORMAT RenderTargetFormat,
1776 WINED3DFORMAT DepthStencilFormat) {
1777 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1778 int nCfgs;
1779 const WineD3D_PixelFormat *cfgs;
1780 int it;
1782 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1783 This, Adapter,
1784 DeviceType, debug_d3ddevicetype(DeviceType),
1785 AdapterFormat, debug_d3dformat(AdapterFormat),
1786 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1787 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1789 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1790 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1791 return WINED3DERR_INVALIDCALL;
1794 cfgs = Adapters[Adapter].cfgs;
1795 nCfgs = Adapters[Adapter].nCfgs;
1796 for (it = 0; it < nCfgs; ++it) {
1797 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1798 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1799 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1800 return WINED3D_OK;
1804 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1806 return WINED3DERR_NOTAVAILABLE;
1809 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1810 WINED3DFORMAT SurfaceFormat,
1811 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1813 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1814 const GlPixelFormatDesc *glDesc;
1815 const StaticPixelFormatDesc *desc;
1817 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1818 This,
1819 Adapter,
1820 DeviceType, debug_d3ddevicetype(DeviceType),
1821 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1822 Windowed,
1823 MultiSampleType,
1824 pQualityLevels);
1826 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1827 return WINED3DERR_INVALIDCALL;
1830 /* TODO: handle Windowed, add more quality levels */
1832 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1834 /* By default multisampling is disabled right now as it causes issues
1835 * on some Nvidia driver versions and it doesn't work well in combination
1836 * with FBOs yet. */
1837 if(!wined3d_settings.allow_multisampling)
1838 return WINED3DERR_NOTAVAILABLE;
1840 desc = getFormatDescEntry(SurfaceFormat, &Adapters[Adapter].gl_info, &glDesc);
1841 if(!desc || !glDesc) {
1842 return WINED3DERR_INVALIDCALL;
1845 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
1846 int i, nCfgs;
1847 const WineD3D_PixelFormat *cfgs;
1849 cfgs = Adapters[Adapter].cfgs;
1850 nCfgs = Adapters[Adapter].nCfgs;
1851 for(i=0; i<nCfgs; i++) {
1852 if(cfgs[i].numSamples != MultiSampleType)
1853 continue;
1855 if(!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[i], SurfaceFormat))
1856 continue;
1858 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1860 if(pQualityLevels)
1861 *pQualityLevels = 1; /* Guess at a value! */
1862 return WINED3D_OK;
1865 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
1866 short redSize, greenSize, blueSize, alphaSize, colorBits;
1867 int i, nCfgs;
1868 const WineD3D_PixelFormat *cfgs;
1870 if(!getColorBits(SurfaceFormat, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1871 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
1872 return WINED3DERR_NOTAVAILABLE;
1875 cfgs = Adapters[Adapter].cfgs;
1876 nCfgs = Adapters[Adapter].nCfgs;
1877 for(i=0; i<nCfgs; i++) {
1878 if(cfgs[i].numSamples != MultiSampleType)
1879 continue;
1880 if(cfgs[i].redSize != redSize)
1881 continue;
1882 if(cfgs[i].greenSize != greenSize)
1883 continue;
1884 if(cfgs[i].blueSize != blueSize)
1885 continue;
1886 if(cfgs[i].alphaSize != alphaSize)
1887 continue;
1889 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
1891 if(pQualityLevels)
1892 *pQualityLevels = 1; /* Guess at a value! */
1893 return WINED3D_OK;
1896 return WINED3DERR_NOTAVAILABLE;
1899 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1900 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1902 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1903 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1904 UINT nmodes;
1906 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1907 This,
1908 Adapter,
1909 DeviceType, debug_d3ddevicetype(DeviceType),
1910 DisplayFormat, debug_d3dformat(DisplayFormat),
1911 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1912 Windowed);
1914 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1915 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1916 return WINED3DERR_INVALIDCALL;
1919 /* The task of this function is to check whether a certain display / backbuffer format
1920 * combination is available on the given adapter. In fullscreen mode microsoft specified
1921 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
1922 * and display format should match exactly.
1923 * In windowed mode format conversion can occur and this depends on the driver. When format
1924 * conversion is done, this function should nevertheless fail and applications need to use
1925 * CheckDeviceFormatConversion.
1926 * At the moment we assume that fullscreen and windowed have the same capabilities */
1928 /* There are only 4 display formats */
1929 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
1930 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
1931 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
1932 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
1934 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
1935 return WINED3DERR_NOTAVAILABLE;
1938 /* If the requested DisplayFormat is not available, don't continue */
1939 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
1940 if(!nmodes) {
1941 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
1942 return WINED3DERR_NOTAVAILABLE;
1945 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
1946 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
1947 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
1948 return WINED3DERR_NOTAVAILABLE;
1951 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
1952 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
1953 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1954 return WINED3DERR_NOTAVAILABLE;
1957 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
1958 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
1959 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1960 return WINED3DERR_NOTAVAILABLE;
1963 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
1964 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
1965 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1966 return WINED3DERR_NOTAVAILABLE;
1969 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
1970 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
1971 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1972 return WINED3DERR_NOTAVAILABLE;
1975 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
1976 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
1977 if(FAILED(hr))
1978 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
1980 return hr;
1984 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1985 /* Check if we support bumpmapping for a format */
1986 static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
1988 const struct fragment_pipeline *fp;
1989 const GlPixelFormatDesc *glDesc;
1991 switch(CheckFormat) {
1992 case WINED3DFMT_V8U8:
1993 case WINED3DFMT_V16U16:
1994 case WINED3DFMT_L6V5U5:
1995 case WINED3DFMT_X8L8V8U8:
1996 case WINED3DFMT_Q8W8V8U8:
1997 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
1998 if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
1999 /* We have a GL extension giving native support */
2000 TRACE_(d3d_caps)("[OK]\n");
2001 return TRUE;
2004 /* No native support: Ask the fixed function pipeline implementation if it
2005 * can deal with the conversion
2007 fp = select_fragment_implementation(Adapter, DeviceType);
2008 if(fp->conv_supported(CheckFormat)) {
2009 TRACE_(d3d_caps)("[OK]\n");
2010 return TRUE;
2011 } else {
2012 TRACE_(d3d_caps)("[FAILED]\n");
2013 return FALSE;
2016 default:
2017 TRACE_(d3d_caps)("[FAILED]\n");
2018 return FALSE;
2022 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2023 static BOOL CheckDepthStencilCapability(UINT Adapter, WINED3DFORMAT DisplayFormat, WINED3DFORMAT DepthStencilFormat)
2025 int it=0;
2026 const GlPixelFormatDesc *glDesc;
2027 const StaticPixelFormatDesc *desc = getFormatDescEntry(DepthStencilFormat, &GLINFO_LOCATION, &glDesc);
2029 /* Fail if we weren't able to get a description of the format */
2030 if(!desc || !glDesc)
2031 return FALSE;
2033 /* Only allow depth/stencil formats */
2034 if(!(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2035 return FALSE;
2037 /* Walk through all WGL pixel formats to find a match */
2038 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2039 WineD3D_PixelFormat *cfg = &Adapters[Adapter].cfgs[it];
2040 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(cfg, DisplayFormat)) {
2041 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(cfg, DepthStencilFormat)) {
2042 return TRUE;
2047 return FALSE;
2050 static BOOL CheckFilterCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2052 const GlPixelFormatDesc *glDesc;
2053 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2055 /* Fail if we weren't able to get a description of the format */
2056 if(!desc || !glDesc)
2057 return FALSE;
2059 /* The flags entry of a format contains the filtering capability */
2060 if(glDesc->Flags & WINED3DFMT_FLAG_FILTERING)
2061 return TRUE;
2063 return FALSE;
2066 /* Check the render target capabilities of a format */
2067 static BOOL CheckRenderTargetCapability(WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat)
2069 UINT Adapter = 0;
2070 const GlPixelFormatDesc *glDesc;
2071 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2073 /* Fail if we weren't able to get a description of the format */
2074 if(!desc || !glDesc)
2075 return FALSE;
2077 /* Filter out non-RT formats */
2078 if(!(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET))
2079 return FALSE;
2081 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2082 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2083 int it;
2084 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2085 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2087 getColorBits(AdapterFormat, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2088 getColorBits(CheckFormat, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2090 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2091 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2092 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2093 TRACE_(d3d_caps)("[FAILED]\n");
2094 return FALSE;
2097 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2098 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2099 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2100 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2101 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2102 return TRUE;
2105 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2106 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2107 WineD3D_PixelFormat *cfgs = Adapters[Adapter].cfgs;
2108 int it;
2110 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2111 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
2112 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], CheckFormat)) {
2113 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n", cfgs[it].iPixelFormat, debug_d3dformat(CheckFormat));
2114 return TRUE;
2117 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2118 /* For now return TRUE for FBOs until we have some proper checks.
2119 * Note that this function will only be called when the format is around for texturing. */
2120 return TRUE;
2122 return FALSE;
2125 static BOOL CheckSrgbReadCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2127 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2128 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2129 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2130 return FALSE;
2133 switch (CheckFormat) {
2134 case WINED3DFMT_A8R8G8B8:
2135 case WINED3DFMT_X8R8G8B8:
2136 case WINED3DFMT_A4R4G4B4:
2137 case WINED3DFMT_L8:
2138 case WINED3DFMT_A8L8:
2139 case WINED3DFMT_DXT1:
2140 case WINED3DFMT_DXT2:
2141 case WINED3DFMT_DXT3:
2142 case WINED3DFMT_DXT4:
2143 case WINED3DFMT_DXT5:
2144 TRACE_(d3d_caps)("[OK]\n");
2145 return TRUE;
2147 default:
2148 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
2149 return FALSE;
2151 return FALSE;
2154 static BOOL CheckSrgbWriteCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2156 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2157 * doing the color fixup in shaders.
2158 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2159 if((CheckFormat == WINED3DFMT_X8R8G8B8) || (CheckFormat == WINED3DFMT_A8R8G8B8)) {
2160 int vs_selected_mode;
2161 int ps_selected_mode;
2162 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
2164 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2165 TRACE_(d3d_caps)("[OK]\n");
2166 return TRUE;
2170 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(CheckFormat));
2171 return FALSE;
2174 /* Check if a format support blending in combination with pixel shaders */
2175 static BOOL CheckPostPixelShaderBlendingCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2177 const GlPixelFormatDesc *glDesc;
2178 const StaticPixelFormatDesc *desc = getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2180 /* Fail if we weren't able to get a description of the format */
2181 if(!desc || !glDesc)
2182 return FALSE;
2184 /* The flags entry of a format contains the post pixel shader blending capability */
2185 if(glDesc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2186 return TRUE;
2188 return FALSE;
2191 static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
2192 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2193 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2194 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2195 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2196 * capability anyway.
2198 * For now lets report this on all formats, but in the future we may want to
2199 * restrict it to some should games need that
2201 return TRUE;
2204 /* Check if a texture format is supported on the given adapter */
2205 static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
2207 const shader_backend_t *shader_backend;
2208 const struct fragment_pipeline *fp;
2209 const GlPixelFormatDesc *glDesc;
2211 switch (CheckFormat) {
2213 /*****
2214 * supported: RGB(A) formats
2216 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2217 case WINED3DFMT_A8R8G8B8:
2218 case WINED3DFMT_X8R8G8B8:
2219 case WINED3DFMT_R5G6B5:
2220 case WINED3DFMT_X1R5G5B5:
2221 case WINED3DFMT_A1R5G5B5:
2222 case WINED3DFMT_A4R4G4B4:
2223 case WINED3DFMT_A8:
2224 case WINED3DFMT_X4R4G4B4:
2225 case WINED3DFMT_A8B8G8R8:
2226 case WINED3DFMT_X8B8G8R8:
2227 case WINED3DFMT_A2R10G10B10:
2228 case WINED3DFMT_A2B10G10R10:
2229 case WINED3DFMT_G16R16:
2230 TRACE_(d3d_caps)("[OK]\n");
2231 return TRUE;
2233 case WINED3DFMT_R3G3B2:
2234 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2235 return FALSE;
2237 /*****
2238 * supported: Palettized
2240 case WINED3DFMT_P8:
2241 TRACE_(d3d_caps)("[OK]\n");
2242 return TRUE;
2243 /* No Windows driver offers A8P8, so don't offer it either */
2244 case WINED3DFMT_A8P8:
2245 return FALSE;
2247 /*****
2248 * Supported: (Alpha)-Luminance
2250 case WINED3DFMT_L8:
2251 case WINED3DFMT_A8L8:
2252 case WINED3DFMT_L16:
2253 TRACE_(d3d_caps)("[OK]\n");
2254 return TRUE;
2256 /* Not supported on Windows, thus disabled */
2257 case WINED3DFMT_A4L4:
2258 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2259 return FALSE;
2261 /*****
2262 * Supported: Depth/Stencil formats
2264 case WINED3DFMT_D16_LOCKABLE:
2265 case WINED3DFMT_D16:
2266 case WINED3DFMT_D15S1:
2267 case WINED3DFMT_D24X8:
2268 case WINED3DFMT_D24X4S4:
2269 case WINED3DFMT_D24S8:
2270 case WINED3DFMT_D24FS8:
2271 case WINED3DFMT_D32:
2272 case WINED3DFMT_D32F_LOCKABLE:
2273 return TRUE;
2275 /*****
2276 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2277 * GL_NV_texture_shader). Emulated by shaders
2279 case WINED3DFMT_V8U8:
2280 case WINED3DFMT_X8L8V8U8:
2281 case WINED3DFMT_L6V5U5:
2282 case WINED3DFMT_Q8W8V8U8:
2283 case WINED3DFMT_V16U16:
2284 case WINED3DFMT_W11V11U10:
2285 getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
2286 if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
2287 /* We have a GL extension giving native support */
2288 TRACE_(d3d_caps)("[OK]\n");
2289 return TRUE;
2292 /* No native support: Ask the fixed function pipeline implementation if it
2293 * can deal with the conversion
2295 shader_backend = select_shader_backend(Adapter, DeviceType);
2296 if(shader_backend->shader_conv_supported(CheckFormat)) {
2297 TRACE_(d3d_caps)("[OK]\n");
2298 return TRUE;
2299 } else {
2300 TRACE_(d3d_caps)("[FAILED]\n");
2301 return FALSE;
2304 case WINED3DFMT_DXT1:
2305 case WINED3DFMT_DXT2:
2306 case WINED3DFMT_DXT3:
2307 case WINED3DFMT_DXT4:
2308 case WINED3DFMT_DXT5:
2309 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2310 TRACE_(d3d_caps)("[OK]\n");
2311 return TRUE;
2313 TRACE_(d3d_caps)("[FAILED]\n");
2314 return FALSE;
2317 /*****
2318 * Odd formats - not supported
2320 case WINED3DFMT_VERTEXDATA:
2321 case WINED3DFMT_INDEX16:
2322 case WINED3DFMT_INDEX32:
2323 case WINED3DFMT_Q16W16V16U16:
2324 case WINED3DFMT_A2W10V10U10:
2325 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2326 return FALSE;
2328 /*****
2329 * WINED3DFMT_CxV8U8: Not supported right now
2331 case WINED3DFMT_CxV8U8:
2332 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2333 return FALSE;
2335 /* YUV formats */
2336 case WINED3DFMT_UYVY:
2337 case WINED3DFMT_YUY2:
2338 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2339 TRACE_(d3d_caps)("[OK]\n");
2340 return TRUE;
2342 TRACE_(d3d_caps)("[FAILED]\n");
2343 return FALSE;
2344 case WINED3DFMT_YV12:
2345 TRACE_(d3d_caps)("[FAILED]\n");
2346 return FALSE;
2348 /* Not supported */
2349 case WINED3DFMT_A16B16G16R16:
2350 case WINED3DFMT_A8R3G3B2:
2351 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2352 return FALSE;
2354 /* Floating point formats */
2355 case WINED3DFMT_R16F:
2356 case WINED3DFMT_A16B16G16R16F:
2357 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2358 TRACE_(d3d_caps)("[OK]\n");
2359 return TRUE;
2361 TRACE_(d3d_caps)("[FAILED]\n");
2362 return FALSE;
2364 case WINED3DFMT_R32F:
2365 case WINED3DFMT_A32B32G32R32F:
2366 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2367 TRACE_(d3d_caps)("[OK]\n");
2368 return TRUE;
2370 TRACE_(d3d_caps)("[FAILED]\n");
2371 return FALSE;
2373 case WINED3DFMT_G16R16F:
2374 case WINED3DFMT_G32R32F:
2375 TRACE_(d3d_caps)("[FAILED]\n");
2376 return FALSE;
2378 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2379 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2380 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2381 * We can do instancing with all shader versions, but we need vertex shaders.
2383 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2384 * to enable instancing. WineD3D doesn't need that and just ignores it.
2386 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2388 case WINEMAKEFOURCC('I','N','S','T'):
2389 TRACE("ATI Instancing check hack\n");
2390 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2391 TRACE_(d3d_caps)("[OK]\n");
2392 return TRUE;
2394 TRACE_(d3d_caps)("[FAILED]\n");
2395 return FALSE;
2397 /* Some weird FOURCC formats */
2398 case WINED3DFMT_R8G8_B8G8:
2399 case WINED3DFMT_G8R8_G8B8:
2400 case WINED3DFMT_MULTI2_ARGB8:
2401 TRACE_(d3d_caps)("[FAILED]\n");
2402 return FALSE;
2404 /* Vendor specific formats */
2405 case WINED3DFMT_ATI2N:
2406 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2407 shader_backend = select_shader_backend(Adapter, DeviceType);
2408 fp = select_fragment_implementation(Adapter, DeviceType);
2409 if(shader_backend->shader_conv_supported(CheckFormat) &&
2410 fp->conv_supported(CheckFormat)) {
2411 TRACE_(d3d_caps)("[OK]\n");
2412 return TRUE;
2415 TRACE_(d3d_caps)("[OK]\n");
2416 return TRUE;
2418 TRACE_(d3d_caps)("[FAILED]\n");
2419 return FALSE;
2421 case WINED3DFMT_NVHU:
2422 case WINED3DFMT_NVHS:
2423 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2424 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2425 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2426 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2427 * Applications have to deal with not having NVHS and NVHU.
2429 TRACE_(d3d_caps)("[FAILED]\n");
2430 return FALSE;
2432 case WINED3DFMT_UNKNOWN:
2433 return FALSE;
2435 default:
2436 ERR("Unhandled format=%s\n", debug_d3dformat(CheckFormat));
2437 break;
2439 return FALSE;
2442 static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType) {
2443 const struct blit_shader *blitter;
2445 if(SurfaceType == SURFACE_GDI) {
2446 switch(CheckFormat) {
2447 case WINED3DFMT_R8G8B8:
2448 case WINED3DFMT_A8R8G8B8:
2449 case WINED3DFMT_X8R8G8B8:
2450 case WINED3DFMT_R5G6B5:
2451 case WINED3DFMT_X1R5G5B5:
2452 case WINED3DFMT_A1R5G5B5:
2453 case WINED3DFMT_A4R4G4B4:
2454 case WINED3DFMT_R3G3B2:
2455 case WINED3DFMT_A8:
2456 case WINED3DFMT_A8R3G3B2:
2457 case WINED3DFMT_X4R4G4B4:
2458 case WINED3DFMT_A2B10G10R10:
2459 case WINED3DFMT_A8B8G8R8:
2460 case WINED3DFMT_X8B8G8R8:
2461 case WINED3DFMT_G16R16:
2462 case WINED3DFMT_A2R10G10B10:
2463 case WINED3DFMT_A16B16G16R16:
2464 case WINED3DFMT_P8:
2465 TRACE_(d3d_caps)("[OK]\n");
2466 return TRUE;
2467 default:
2468 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
2469 return FALSE;
2473 /* All format that are supported for textures are supported for surfaces as well */
2474 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE;
2475 /* All depth stencil formats are supported on surfaces */
2476 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) return TRUE;
2478 /* If opengl can't process the format natively, the blitter may be able to convert it */
2479 blitter = select_blit_implementation(Adapter, DeviceType);
2480 if(blitter->conv_supported(CheckFormat)) {
2481 TRACE_(d3d_caps)("[OK]\n");
2482 return TRUE;
2485 /* Reject other formats */
2486 TRACE_(d3d_caps)("[FAILED]\n");
2487 return FALSE;
2490 static BOOL CheckVertexTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
2492 if (!GL_LIMITS(vertex_samplers)) {
2493 TRACE_(d3d_caps)("[FAILED]\n");
2494 return FALSE;
2497 switch (CheckFormat) {
2498 case WINED3DFMT_A32B32G32R32F:
2499 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2500 TRACE_(d3d_caps)("[FAILED]\n");
2501 return FALSE;
2503 TRACE_(d3d_caps)("[OK]\n");
2504 return TRUE;
2506 default:
2507 TRACE_(d3d_caps)("[FAILED]\n");
2508 return FALSE;
2510 return FALSE;
2513 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2514 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
2515 WINED3DSURFTYPE SurfaceType) {
2516 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2517 DWORD UsageCaps = 0;
2519 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
2520 This,
2521 Adapter,
2522 DeviceType, debug_d3ddevicetype(DeviceType),
2523 AdapterFormat, debug_d3dformat(AdapterFormat),
2524 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
2525 RType, debug_d3dresourcetype(RType),
2526 CheckFormat, debug_d3dformat(CheckFormat));
2528 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2529 return WINED3DERR_INVALIDCALL;
2532 if(RType == WINED3DRTYPE_CUBETEXTURE) {
2534 if(SurfaceType != SURFACE_OPENGL) {
2535 TRACE("[FAILED]\n");
2536 return WINED3DERR_NOTAVAILABLE;
2539 /* Cubetexture allows:
2540 * - D3DUSAGE_AUTOGENMIPMAP
2541 * - D3DUSAGE_DEPTHSTENCIL
2542 * - D3DUSAGE_DYNAMIC
2543 * - D3DUSAGE_NONSECURE (d3d9ex)
2544 * - D3DUSAGE_RENDERTARGET
2545 * - D3DUSAGE_SOFTWAREPROCESSING
2546 * - D3DUSAGE_QUERY_WRAPANDMIP
2548 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2549 /* Check if the texture format is around */
2550 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2551 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2552 /* Check for automatic mipmap generation support */
2553 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2554 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2555 } else {
2556 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2557 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2561 /* Always report dynamic locking */
2562 if(Usage & WINED3DUSAGE_DYNAMIC)
2563 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2565 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2566 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2567 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2568 } else {
2569 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2570 return WINED3DERR_NOTAVAILABLE;
2574 /* Always report software processing */
2575 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2576 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2578 /* Check QUERY_FILTER support */
2579 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2580 if(CheckFilterCapability(Adapter, CheckFormat)) {
2581 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2582 } else {
2583 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2584 return WINED3DERR_NOTAVAILABLE;
2588 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2589 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2590 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2591 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2592 } else {
2593 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2594 return WINED3DERR_NOTAVAILABLE;
2598 /* Check QUERY_SRGBREAD support */
2599 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2600 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2601 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2602 } else {
2603 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2604 return WINED3DERR_NOTAVAILABLE;
2608 /* Check QUERY_SRGBWRITE support */
2609 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2610 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2611 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2612 } else {
2613 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2614 return WINED3DERR_NOTAVAILABLE;
2618 /* Check QUERY_VERTEXTEXTURE support */
2619 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2620 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2621 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2622 } else {
2623 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2624 return WINED3DERR_NOTAVAILABLE;
2628 /* Check QUERY_WRAPANDMIP support */
2629 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2630 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2631 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2632 } else {
2633 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2634 return WINED3DERR_NOTAVAILABLE;
2637 } else {
2638 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
2639 return WINED3DERR_NOTAVAILABLE;
2641 } else {
2642 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
2643 return WINED3DERR_NOTAVAILABLE;
2645 } else if(RType == WINED3DRTYPE_SURFACE) {
2646 /* Surface allows:
2647 * - D3DUSAGE_DEPTHSTENCIL
2648 * - D3DUSAGE_NONSECURE (d3d9ex)
2649 * - D3DUSAGE_RENDERTARGET
2652 if(CheckSurfaceCapability(Adapter, AdapterFormat, DeviceType, CheckFormat, SurfaceType)) {
2653 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2654 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2655 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2656 } else {
2657 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
2658 return WINED3DERR_NOTAVAILABLE;
2662 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2663 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2664 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2665 } else {
2666 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2667 return WINED3DERR_NOTAVAILABLE;
2671 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2672 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2673 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2674 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2675 } else {
2676 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2677 return WINED3DERR_NOTAVAILABLE;
2680 } else {
2681 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
2682 return WINED3DERR_NOTAVAILABLE;
2685 } else if(RType == WINED3DRTYPE_TEXTURE) {
2686 /* Texture allows:
2687 * - D3DUSAGE_AUTOGENMIPMAP
2688 * - D3DUSAGE_DEPTHSTENCIL
2689 * - D3DUSAGE_DMAP
2690 * - D3DUSAGE_DYNAMIC
2691 * - D3DUSAGE_NONSECURE (d3d9ex)
2692 * - D3DUSAGE_RENDERTARGET
2693 * - D3DUSAGE_SOFTWAREPROCESSING
2694 * - D3DUSAGE_TEXTAPI (d3d9ex)
2695 * - D3DUSAGE_QUERY_WRAPANDMIP
2698 if(SurfaceType != SURFACE_OPENGL) {
2699 TRACE("[FAILED]\n");
2700 return WINED3DERR_NOTAVAILABLE;
2703 /* Check if the texture format is around */
2704 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
2705 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
2706 /* Check for automatic mipmap generation support */
2707 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
2708 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
2709 } else {
2710 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
2711 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
2715 /* Always report dynamic locking */
2716 if(Usage & WINED3DUSAGE_DYNAMIC)
2717 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2719 if(Usage & WINED3DUSAGE_RENDERTARGET) {
2720 if(CheckRenderTargetCapability(AdapterFormat, CheckFormat)) {
2721 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
2722 } else {
2723 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
2724 return WINED3DERR_NOTAVAILABLE;
2728 /* Always report software processing */
2729 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2730 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2732 /* Check QUERY_FILTER support */
2733 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2734 if(CheckFilterCapability(Adapter, CheckFormat)) {
2735 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2736 } else {
2737 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2738 return WINED3DERR_NOTAVAILABLE;
2742 /* Check QUERY_LEGACYBUMPMAP support */
2743 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
2744 if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) {
2745 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
2746 } else {
2747 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
2748 return WINED3DERR_NOTAVAILABLE;
2752 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2753 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2754 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2755 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2756 } else {
2757 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2758 return WINED3DERR_NOTAVAILABLE;
2762 /* Check QUERY_SRGBREAD support */
2763 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2764 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2765 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2766 } else {
2767 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2768 return WINED3DERR_NOTAVAILABLE;
2772 /* Check QUERY_SRGBWRITE support */
2773 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2774 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2775 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2776 } else {
2777 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2778 return WINED3DERR_NOTAVAILABLE;
2782 /* Check QUERY_VERTEXTEXTURE support */
2783 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2784 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2785 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2786 } else {
2787 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2788 return WINED3DERR_NOTAVAILABLE;
2792 /* Check QUERY_WRAPANDMIP support */
2793 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2794 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2795 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2796 } else {
2797 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2798 return WINED3DERR_NOTAVAILABLE;
2802 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
2803 if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
2804 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
2805 } else {
2806 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
2807 return WINED3DERR_NOTAVAILABLE;
2810 } else {
2811 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
2812 return WINED3DERR_NOTAVAILABLE;
2814 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
2815 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
2816 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
2818 * Volumetexture allows:
2819 * - D3DUSAGE_DYNAMIC
2820 * - D3DUSAGE_NONSECURE (d3d9ex)
2821 * - D3DUSAGE_SOFTWAREPROCESSING
2822 * - D3DUSAGE_QUERY_WRAPANDMIP
2825 if(SurfaceType != SURFACE_OPENGL) {
2826 TRACE("[FAILED]\n");
2827 return WINED3DERR_NOTAVAILABLE;
2830 /* Check volume texture and volume usage caps */
2831 if(GL_SUPPORT(EXT_TEXTURE3D)) {
2832 if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) {
2833 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
2834 return WINED3DERR_NOTAVAILABLE;
2837 /* Always report dynamic locking */
2838 if(Usage & WINED3DUSAGE_DYNAMIC)
2839 UsageCaps |= WINED3DUSAGE_DYNAMIC;
2841 /* Always report software processing */
2842 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
2843 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
2845 /* Check QUERY_FILTER support */
2846 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
2847 if(CheckFilterCapability(Adapter, CheckFormat)) {
2848 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
2849 } else {
2850 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
2851 return WINED3DERR_NOTAVAILABLE;
2855 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
2856 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
2857 if(CheckPostPixelShaderBlendingCapability(Adapter, CheckFormat)) {
2858 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
2859 } else {
2860 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
2861 return WINED3DERR_NOTAVAILABLE;
2865 /* Check QUERY_SRGBREAD support */
2866 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
2867 if(CheckSrgbReadCapability(Adapter, CheckFormat)) {
2868 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
2869 } else {
2870 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
2871 return WINED3DERR_NOTAVAILABLE;
2875 /* Check QUERY_SRGBWRITE support */
2876 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
2877 if(CheckSrgbWriteCapability(Adapter, DeviceType, CheckFormat)) {
2878 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
2879 } else {
2880 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
2881 return WINED3DERR_NOTAVAILABLE;
2885 /* Check QUERY_VERTEXTEXTURE support */
2886 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
2887 if(CheckVertexTextureCapability(Adapter, CheckFormat)) {
2888 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
2889 } else {
2890 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
2891 return WINED3DERR_NOTAVAILABLE;
2895 /* Check QUERY_WRAPANDMIP support */
2896 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
2897 if(CheckWrapAndMipCapability(Adapter, CheckFormat)) {
2898 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
2899 } else {
2900 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
2901 return WINED3DERR_NOTAVAILABLE;
2904 } else {
2905 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
2906 return WINED3DERR_NOTAVAILABLE;
2909 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
2910 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
2911 * app needing one of those formats, don't advertize them to avoid leading apps into
2912 * temptation. The windows drivers don't support most of those formats on volumes anyway,
2913 * except of R32F.
2915 switch(CheckFormat) {
2916 case WINED3DFMT_P8:
2917 case WINED3DFMT_A4L4:
2918 case WINED3DFMT_R32F:
2919 case WINED3DFMT_R16F:
2920 case WINED3DFMT_X8L8V8U8:
2921 case WINED3DFMT_L6V5U5:
2922 case WINED3DFMT_G16R16:
2923 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2924 return WINED3DERR_NOTAVAILABLE;
2926 case WINED3DFMT_Q8W8V8U8:
2927 case WINED3DFMT_V16U16:
2928 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2929 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2930 return WINED3DERR_NOTAVAILABLE;
2932 break;
2934 case WINED3DFMT_V8U8:
2935 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
2936 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
2937 return WINED3DERR_NOTAVAILABLE;
2939 break;
2941 case WINED3DFMT_DXT1:
2942 case WINED3DFMT_DXT2:
2943 case WINED3DFMT_DXT3:
2944 case WINED3DFMT_DXT4:
2945 case WINED3DFMT_DXT5:
2946 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
2947 * compressed texture results in an error. While the D3D refrast does
2948 * support s3tc volumes, at least the nvidia windows driver does not, so
2949 * we're free not to support this format.
2951 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
2952 return WINED3DERR_NOTAVAILABLE;
2954 default:
2955 /* Do nothing, continue with checking the format below */
2956 break;
2958 } else if((RType == WINED3DRTYPE_INDEXBUFFER) || (RType == WINED3DRTYPE_VERTEXBUFFER)){
2959 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
2960 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
2961 return WINED3DERR_NOTAVAILABLE;
2964 /* This format is nothing special and it is supported perfectly.
2965 * However, ati and nvidia driver on windows do not mark this format as
2966 * supported (tested with the dxCapsViewer) and pretending to
2967 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
2968 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
2969 * Enable it on dx7. It will need additional checking on dx10 when we support it.
2971 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
2972 TRACE_(d3d_caps)("[FAILED]\n");
2973 return WINED3DERR_NOTAVAILABLE;
2976 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
2977 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
2978 * usage flags match. */
2979 if(UsageCaps == Usage) {
2980 return WINED3D_OK;
2981 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
2982 return WINED3DOK_NOAUTOGEN;
2983 } else {
2984 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);
2985 return WINED3DERR_NOTAVAILABLE;
2989 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2990 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
2991 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2993 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
2994 This,
2995 Adapter,
2996 DeviceType, debug_d3ddevicetype(DeviceType),
2997 SourceFormat, debug_d3dformat(SourceFormat),
2998 TargetFormat, debug_d3dformat(TargetFormat));
2999 return WINED3D_OK;
3002 static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3003 const shader_backend_t *ret;
3004 int vs_selected_mode;
3005 int ps_selected_mode;
3007 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3008 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3009 ret = &glsl_shader_backend;
3010 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3011 ret = &arb_program_shader_backend;
3012 } else {
3013 ret = &none_shader_backend;
3015 return ret;
3018 static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3019 int vs_selected_mode;
3020 int ps_selected_mode;
3022 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3023 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3024 return &arbfp_fragment_pipeline;
3025 } else if(ps_selected_mode == SHADER_ATI) {
3026 return &atifs_fragment_pipeline;
3027 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3028 return &nvts_fragment_pipeline;
3029 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3030 return &nvrc_fragment_pipeline;
3031 } else {
3032 return &ffp_fragment_pipeline;
3036 static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType) {
3037 int vs_selected_mode;
3038 int ps_selected_mode;
3040 select_shader_mode(&GLINFO_LOCATION, DeviceType, &ps_selected_mode, &vs_selected_mode);
3041 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3042 return &arbfp_blit;
3043 } else {
3044 return &ffp_blit;
3048 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3049 subset of a D3DCAPS9 structure. However, it has to come via a void *
3050 as the d3d8 interface cannot import the d3d9 header */
3051 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3053 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3054 int vs_selected_mode;
3055 int ps_selected_mode;
3056 struct shader_caps shader_caps;
3057 struct fragment_caps fragment_caps;
3058 const shader_backend_t *shader_backend;
3059 const struct fragment_pipeline *frag_pipeline = NULL;
3060 DWORD ckey_caps, blit_caps, fx_caps;
3062 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3064 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3065 return WINED3DERR_INVALIDCALL;
3068 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3070 /* This function should *not* be modifying GL caps
3071 * TODO: move the functionality where it belongs */
3072 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
3074 /* ------------------------------------------------
3075 The following fields apply to both d3d8 and d3d9
3076 ------------------------------------------------ */
3077 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3078 pCaps->AdapterOrdinal = Adapter;
3080 pCaps->Caps = 0;
3081 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3082 WINED3DCAPS2_FULLSCREENGAMMA |
3083 WINED3DCAPS2_DYNAMICTEXTURES;
3084 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3085 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3088 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3089 WINED3DCAPS3_COPY_TO_VIDMEM |
3090 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3092 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3093 WINED3DPRESENT_INTERVAL_ONE;
3095 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3096 WINED3DCURSORCAPS_LOWRES;
3098 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3099 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3100 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3101 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3102 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3103 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3104 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3105 WINED3DDEVCAPS_PUREDEVICE |
3106 WINED3DDEVCAPS_HWRASTERIZATION |
3107 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3108 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3109 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3110 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3111 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3112 WINED3DDEVCAPS_RTPATCHES;
3114 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3115 WINED3DPMISCCAPS_CULLCCW |
3116 WINED3DPMISCCAPS_CULLCW |
3117 WINED3DPMISCCAPS_COLORWRITEENABLE |
3118 WINED3DPMISCCAPS_CLIPTLVERTS |
3119 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3120 WINED3DPMISCCAPS_MASKZ |
3121 WINED3DPMISCCAPS_BLENDOP |
3122 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3123 /* TODO:
3124 WINED3DPMISCCAPS_NULLREFERENCE
3125 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3126 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3127 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3128 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3130 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3131 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3133 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3134 WINED3DPRASTERCAPS_PAT |
3135 WINED3DPRASTERCAPS_WFOG |
3136 WINED3DPRASTERCAPS_ZFOG |
3137 WINED3DPRASTERCAPS_FOGVERTEX |
3138 WINED3DPRASTERCAPS_FOGTABLE |
3139 WINED3DPRASTERCAPS_STIPPLE |
3140 WINED3DPRASTERCAPS_SUBPIXEL |
3141 WINED3DPRASTERCAPS_ZTEST |
3142 WINED3DPRASTERCAPS_SCISSORTEST |
3143 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3144 WINED3DPRASTERCAPS_DEPTHBIAS;
3146 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3147 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3148 WINED3DPRASTERCAPS_ZBIAS |
3149 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3151 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3152 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3154 /* FIXME Add:
3155 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3156 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3157 WINED3DPRASTERCAPS_ANTIALIASEDGES
3158 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3159 WINED3DPRASTERCAPS_WBUFFER */
3161 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3162 WINED3DPCMPCAPS_EQUAL |
3163 WINED3DPCMPCAPS_GREATER |
3164 WINED3DPCMPCAPS_GREATEREQUAL |
3165 WINED3DPCMPCAPS_LESS |
3166 WINED3DPCMPCAPS_LESSEQUAL |
3167 WINED3DPCMPCAPS_NEVER |
3168 WINED3DPCMPCAPS_NOTEQUAL;
3170 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3171 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3172 WINED3DPBLENDCAPS_DESTALPHA |
3173 WINED3DPBLENDCAPS_DESTCOLOR |
3174 WINED3DPBLENDCAPS_INVDESTALPHA |
3175 WINED3DPBLENDCAPS_INVDESTCOLOR |
3176 WINED3DPBLENDCAPS_INVSRCALPHA |
3177 WINED3DPBLENDCAPS_INVSRCCOLOR |
3178 WINED3DPBLENDCAPS_ONE |
3179 WINED3DPBLENDCAPS_SRCALPHA |
3180 WINED3DPBLENDCAPS_SRCALPHASAT |
3181 WINED3DPBLENDCAPS_SRCCOLOR |
3182 WINED3DPBLENDCAPS_ZERO;
3184 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3185 WINED3DPBLENDCAPS_DESTCOLOR |
3186 WINED3DPBLENDCAPS_INVDESTALPHA |
3187 WINED3DPBLENDCAPS_INVDESTCOLOR |
3188 WINED3DPBLENDCAPS_INVSRCALPHA |
3189 WINED3DPBLENDCAPS_INVSRCCOLOR |
3190 WINED3DPBLENDCAPS_ONE |
3191 WINED3DPBLENDCAPS_SRCALPHA |
3192 WINED3DPBLENDCAPS_SRCCOLOR |
3193 WINED3DPBLENDCAPS_ZERO;
3194 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3195 * according to the glBlendFunc manpage
3197 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3198 * legacy settings for srcblend only
3201 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3202 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3203 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3207 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3208 WINED3DPCMPCAPS_EQUAL |
3209 WINED3DPCMPCAPS_GREATER |
3210 WINED3DPCMPCAPS_GREATEREQUAL |
3211 WINED3DPCMPCAPS_LESS |
3212 WINED3DPCMPCAPS_LESSEQUAL |
3213 WINED3DPCMPCAPS_NEVER |
3214 WINED3DPCMPCAPS_NOTEQUAL;
3216 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3217 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3218 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3219 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3220 WINED3DPSHADECAPS_COLORFLATRGB |
3221 WINED3DPSHADECAPS_FOGFLAT |
3222 WINED3DPSHADECAPS_FOGGOURAUD |
3223 WINED3DPSHADECAPS_SPECULARFLATRGB;
3225 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3226 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3227 WINED3DPTEXTURECAPS_TRANSPARENCY |
3228 WINED3DPTEXTURECAPS_BORDER |
3229 WINED3DPTEXTURECAPS_MIPMAP |
3230 WINED3DPTEXTURECAPS_PROJECTED |
3231 WINED3DPTEXTURECAPS_PERSPECTIVE;
3233 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3234 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3235 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3238 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3239 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3240 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3241 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3244 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3245 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3246 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3247 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3251 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3252 WINED3DPTFILTERCAPS_MAGFPOINT |
3253 WINED3DPTFILTERCAPS_MINFLINEAR |
3254 WINED3DPTFILTERCAPS_MINFPOINT |
3255 WINED3DPTFILTERCAPS_MIPFLINEAR |
3256 WINED3DPTFILTERCAPS_MIPFPOINT |
3257 WINED3DPTFILTERCAPS_LINEAR |
3258 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3259 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3260 WINED3DPTFILTERCAPS_MIPLINEAR |
3261 WINED3DPTFILTERCAPS_MIPNEAREST |
3262 WINED3DPTFILTERCAPS_NEAREST;
3264 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3265 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3266 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3269 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3270 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3271 WINED3DPTFILTERCAPS_MAGFPOINT |
3272 WINED3DPTFILTERCAPS_MINFLINEAR |
3273 WINED3DPTFILTERCAPS_MINFPOINT |
3274 WINED3DPTFILTERCAPS_MIPFLINEAR |
3275 WINED3DPTFILTERCAPS_MIPFPOINT |
3276 WINED3DPTFILTERCAPS_LINEAR |
3277 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3278 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3279 WINED3DPTFILTERCAPS_MIPLINEAR |
3280 WINED3DPTFILTERCAPS_MIPNEAREST |
3281 WINED3DPTFILTERCAPS_NEAREST;
3283 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3284 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3285 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3287 } else
3288 pCaps->CubeTextureFilterCaps = 0;
3290 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3291 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3292 WINED3DPTFILTERCAPS_MAGFPOINT |
3293 WINED3DPTFILTERCAPS_MINFLINEAR |
3294 WINED3DPTFILTERCAPS_MINFPOINT |
3295 WINED3DPTFILTERCAPS_MIPFLINEAR |
3296 WINED3DPTFILTERCAPS_MIPFPOINT |
3297 WINED3DPTFILTERCAPS_LINEAR |
3298 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3299 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3300 WINED3DPTFILTERCAPS_MIPLINEAR |
3301 WINED3DPTFILTERCAPS_MIPNEAREST |
3302 WINED3DPTFILTERCAPS_NEAREST;
3303 } else
3304 pCaps->VolumeTextureFilterCaps = 0;
3306 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3307 WINED3DPTADDRESSCAPS_CLAMP |
3308 WINED3DPTADDRESSCAPS_WRAP;
3310 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3311 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3313 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3314 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3316 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3317 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3320 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3321 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3322 WINED3DPTADDRESSCAPS_CLAMP |
3323 WINED3DPTADDRESSCAPS_WRAP;
3324 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3325 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3327 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3328 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3330 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3331 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3333 } else
3334 pCaps->VolumeTextureAddressCaps = 0;
3336 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3337 WINED3DLINECAPS_ZTEST |
3338 WINED3DLINECAPS_BLEND |
3339 WINED3DLINECAPS_ALPHACMP |
3340 WINED3DLINECAPS_FOG;
3341 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3342 * idea how generating the smoothing alpha values works; the result is different
3345 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3346 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3348 if(GL_SUPPORT(EXT_TEXTURE3D))
3349 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3350 else
3351 pCaps->MaxVolumeExtent = 0;
3353 pCaps->MaxTextureRepeat = 32768;
3354 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3355 pCaps->MaxVertexW = 1.0;
3357 pCaps->GuardBandLeft = 0;
3358 pCaps->GuardBandTop = 0;
3359 pCaps->GuardBandRight = 0;
3360 pCaps->GuardBandBottom = 0;
3362 pCaps->ExtentsAdjust = 0;
3364 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3365 WINED3DSTENCILCAPS_INCRSAT |
3366 WINED3DSTENCILCAPS_INVERT |
3367 WINED3DSTENCILCAPS_KEEP |
3368 WINED3DSTENCILCAPS_REPLACE |
3369 WINED3DSTENCILCAPS_ZERO;
3370 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3371 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3372 WINED3DSTENCILCAPS_INCR;
3374 if ( This->dxVersion > 8 &&
3375 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
3376 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
3377 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3380 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3382 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3383 pCaps->MaxActiveLights = GL_LIMITS(lights);
3385 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3386 pCaps->MaxVertexBlendMatrixIndex = 0;
3388 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3389 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3392 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3393 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3394 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3395 WINED3DVTXPCAPS_LOCALVIEWER |
3396 WINED3DVTXPCAPS_VERTEXFOG |
3397 WINED3DVTXPCAPS_TEXGEN;
3398 /* FIXME: Add
3399 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3401 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3402 pCaps->MaxVertexIndex = 0xFFFFF;
3403 pCaps->MaxStreams = MAX_STREAMS;
3404 pCaps->MaxStreamStride = 1024;
3406 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3407 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3408 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3409 pCaps->MaxNpatchTessellationLevel = 0;
3410 pCaps->MasterAdapterOrdinal = 0;
3411 pCaps->AdapterOrdinalInGroup = 0;
3412 pCaps->NumberOfAdaptersInGroup = 1;
3414 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3416 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3417 WINED3DPTFILTERCAPS_MAGFPOINT |
3418 WINED3DPTFILTERCAPS_MINFLINEAR |
3419 WINED3DPTFILTERCAPS_MAGFLINEAR;
3420 pCaps->VertexTextureFilterCaps = 0;
3422 memset(&shader_caps, 0, sizeof(shader_caps));
3423 shader_backend = select_shader_backend(Adapter, DeviceType);
3424 shader_backend->shader_get_caps(DeviceType, &GLINFO_LOCATION, &shader_caps);
3426 memset(&fragment_caps, 0, sizeof(fragment_caps));
3427 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3428 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &fragment_caps);
3430 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3431 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3433 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3434 * Ignore shader model capabilities if disabled in config
3436 if(vs_selected_mode == SHADER_NONE) {
3437 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
3438 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
3439 pCaps->MaxVertexShaderConst = 0;
3440 } else {
3441 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
3442 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
3445 if(ps_selected_mode == SHADER_NONE) {
3446 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
3447 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
3448 pCaps->PixelShader1xMaxValue = 0.0;
3449 } else {
3450 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
3451 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
3454 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
3455 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
3456 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
3458 pCaps->VS20Caps = shader_caps.VS20Caps;
3459 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
3460 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
3461 pCaps->PS20Caps = shader_caps.PS20Caps;
3462 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
3463 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
3465 /* The following caps are shader specific, but they are things we cannot detect, or which
3466 * are the same among all shader models. So to avoid code duplication set the shader version
3467 * specific, but otherwise constant caps here
3469 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
3470 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3471 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
3472 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
3473 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3474 pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
3475 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
3477 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
3478 pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
3479 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
3480 pCaps->VS20Caps.Caps = 0;
3481 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
3482 pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
3483 pCaps->VS20Caps.StaticFlowControlDepth = 1;
3485 pCaps->MaxVShaderInstructionsExecuted = 65535;
3486 pCaps->MaxVertexShader30InstructionSlots = 0;
3487 } else { /* VS 1.x */
3488 pCaps->VS20Caps.Caps = 0;
3489 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
3490 pCaps->VS20Caps.NumTemps = 0;
3491 pCaps->VS20Caps.StaticFlowControlDepth = 0;
3493 pCaps->MaxVShaderInstructionsExecuted = 0;
3494 pCaps->MaxVertexShader30InstructionSlots = 0;
3497 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
3498 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
3499 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
3501 /* 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 */
3502 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
3503 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
3504 WINED3DPS20CAPS_PREDICATION |
3505 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
3506 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
3507 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
3508 pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
3509 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
3510 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
3512 pCaps->MaxPShaderInstructionsExecuted = 65535;
3513 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
3514 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
3515 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
3516 pCaps->PS20Caps.Caps = 0;
3517 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
3518 pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
3519 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
3520 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
3522 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
3523 pCaps->MaxPixelShader30InstructionSlots = 0;
3524 } else { /* PS 1.x */
3525 pCaps->PS20Caps.Caps = 0;
3526 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
3527 pCaps->PS20Caps.NumTemps = 0;
3528 pCaps->PS20Caps.StaticFlowControlDepth = 0;
3529 pCaps->PS20Caps.NumInstructionSlots = 0;
3531 pCaps->MaxPShaderInstructionsExecuted = 0;
3532 pCaps->MaxPixelShader30InstructionSlots = 0;
3535 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
3536 /* OpenGL supports all the formats below, perhaps not always
3537 * without conversion, but it supports them.
3538 * Further GLSL doesn't seem to have an official unsigned type so
3539 * don't advertise it yet as I'm not sure how we handle it.
3540 * We might need to add some clamping in the shader engine to
3541 * support it.
3542 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
3543 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
3544 WINED3DDTCAPS_UBYTE4N |
3545 WINED3DDTCAPS_SHORT2N |
3546 WINED3DDTCAPS_SHORT4N;
3547 if (GL_SUPPORT(NV_HALF_FLOAT)) {
3548 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
3549 WINED3DDTCAPS_FLOAT16_4;
3551 } else
3552 pCaps->DeclTypes = 0;
3554 /* Set DirectDraw helper Caps */
3555 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
3556 WINEDDCKEYCAPS_SRCBLT;
3557 fx_caps = WINEDDFXCAPS_BLTALPHA |
3558 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
3559 WINEDDFXCAPS_BLTMIRRORUPDOWN |
3560 WINEDDFXCAPS_BLTROTATION90 |
3561 WINEDDFXCAPS_BLTSHRINKX |
3562 WINEDDFXCAPS_BLTSHRINKXN |
3563 WINEDDFXCAPS_BLTSHRINKY |
3564 WINEDDFXCAPS_BLTSHRINKXN |
3565 WINEDDFXCAPS_BLTSTRETCHX |
3566 WINEDDFXCAPS_BLTSTRETCHXN |
3567 WINEDDFXCAPS_BLTSTRETCHY |
3568 WINEDDFXCAPS_BLTSTRETCHYN;
3569 blit_caps = WINEDDCAPS_BLT |
3570 WINEDDCAPS_BLTCOLORFILL |
3571 WINEDDCAPS_BLTDEPTHFILL |
3572 WINEDDCAPS_BLTSTRETCH |
3573 WINEDDCAPS_CANBLTSYSMEM |
3574 WINEDDCAPS_CANCLIP |
3575 WINEDDCAPS_CANCLIPSTRETCHED |
3576 WINEDDCAPS_COLORKEY |
3577 WINEDDCAPS_COLORKEYHWASSIST |
3578 WINEDDCAPS_ALIGNBOUNDARYSRC;
3580 /* Fill the ddraw caps structure */
3581 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
3582 WINEDDCAPS_PALETTE |
3583 blit_caps;
3584 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
3585 WINEDDCAPS2_NOPAGELOCKREQUIRED |
3586 WINEDDCAPS2_PRIMARYGAMMA |
3587 WINEDDCAPS2_WIDESURFACES |
3588 WINEDDCAPS2_CANRENDERWINDOWED;
3589 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
3590 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
3591 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
3592 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
3593 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
3594 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
3595 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
3596 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
3597 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
3599 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
3600 WINEDDSCAPS_BACKBUFFER |
3601 WINEDDSCAPS_FLIP |
3602 WINEDDSCAPS_FRONTBUFFER |
3603 WINEDDSCAPS_OFFSCREENPLAIN |
3604 WINEDDSCAPS_PALETTE |
3605 WINEDDSCAPS_PRIMARYSURFACE |
3606 WINEDDSCAPS_SYSTEMMEMORY |
3607 WINEDDSCAPS_VIDEOMEMORY |
3608 WINEDDSCAPS_VISIBLE;
3609 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
3611 /* Set D3D caps if OpenGL is available. */
3612 if(Adapters[Adapter].opengl) {
3613 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
3614 WINEDDSCAPS_MIPMAP |
3615 WINEDDSCAPS_TEXTURE |
3616 WINEDDSCAPS_ZBUFFER;
3617 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
3620 return WINED3D_OK;
3623 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
3624 and fields being inserted in the middle, a new structure is used in place */
3625 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
3626 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
3627 IUnknown *parent) {
3629 IWineD3DDeviceImpl *object = NULL;
3630 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3631 WINED3DDISPLAYMODE mode;
3632 const struct fragment_pipeline *frag_pipeline = NULL;
3633 int i;
3634 struct fragment_caps ffp_caps;
3636 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
3637 * number and create a device without a 3D adapter for 2D only operation.
3639 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
3640 return WINED3DERR_INVALIDCALL;
3643 /* Create a WineD3DDevice object */
3644 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
3645 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
3646 TRACE("Created WineD3DDevice object @ %p\n", object);
3647 if (NULL == object) {
3648 return WINED3DERR_OUTOFVIDEOMEMORY;
3651 /* Set up initial COM information */
3652 object->lpVtbl = &IWineD3DDevice_Vtbl;
3653 object->ref = 1;
3654 object->wineD3D = iface;
3655 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
3656 IWineD3D_AddRef(object->wineD3D);
3657 object->parent = parent;
3658 list_init(&object->resources);
3659 list_init(&object->shaders);
3661 if(This->dxVersion == 7) {
3662 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
3663 } else {
3664 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
3666 object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
3668 /* Set the state up as invalid until the device is fully created */
3669 object->state = WINED3DERR_DRIVERINTERNALERROR;
3671 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
3672 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
3674 /* Save the creation parameters */
3675 object->createParms.AdapterOrdinal = Adapter;
3676 object->createParms.DeviceType = DeviceType;
3677 object->createParms.hFocusWindow = hFocusWindow;
3678 object->createParms.BehaviorFlags = BehaviourFlags;
3680 /* Initialize other useful values */
3681 object->adapterNo = Adapter;
3682 object->devType = DeviceType;
3684 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
3685 object->shader_backend = select_shader_backend(Adapter, DeviceType);
3687 memset(&ffp_caps, 0, sizeof(ffp_caps));
3688 frag_pipeline = select_fragment_implementation(Adapter, DeviceType);
3689 object->frag_pipe = frag_pipeline;
3690 frag_pipeline->get_caps(DeviceType, &GLINFO_LOCATION, &ffp_caps);
3691 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
3692 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
3693 compile_state_table(object->StateTable, object->multistate_funcs, &GLINFO_LOCATION,
3694 ffp_vertexstate_template, frag_pipeline, misc_state_template);
3696 object->blitter = select_blit_implementation(Adapter, DeviceType);
3698 /* Prefer the vtable with functions optimized for single dirtifyable objects if the shader
3699 * model can deal with that. It is essentially the same, just with adjusted
3700 * Set*ShaderConstantF implementations
3702 if(object->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *) object)) {
3703 object->lpVtbl = &IWineD3DDevice_DirtyConst_Vtbl;
3706 /* set the state of the device to valid */
3707 object->state = WINED3D_OK;
3709 /* Get the initial screen setup for ddraw */
3710 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
3712 object->ddraw_width = mode.Width;
3713 object->ddraw_height = mode.Height;
3714 object->ddraw_format = mode.Format;
3716 for(i = 0; i < PATCHMAP_SIZE; i++) {
3717 list_init(&object->patches[i]);
3719 return WINED3D_OK;
3721 #undef GLINFO_LOCATION
3723 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
3724 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3725 IUnknown_AddRef(This->parent);
3726 *pParent = This->parent;
3727 return WINED3D_OK;
3730 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
3731 IUnknown* surfaceParent;
3732 TRACE("(%p) call back\n", pSurface);
3734 /* Now, release the parent, which will take care of cleaning up the surface for us */
3735 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
3736 IUnknown_Release(surfaceParent);
3737 return IUnknown_Release(surfaceParent);
3740 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
3741 IUnknown* volumeParent;
3742 TRACE("(%p) call back\n", pVolume);
3744 /* Now, release the parent, which will take care of cleaning up the volume for us */
3745 IWineD3DVolume_GetParent(pVolume, &volumeParent);
3746 IUnknown_Release(volumeParent);
3747 return IUnknown_Release(volumeParent);
3750 static BOOL implementation_is_apple(const WineD3D_GL_Info *gl_info)
3752 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
3753 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
3754 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
3756 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
3757 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
3758 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
3759 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
3760 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
3761 * the chance that other implementations support them is rather small since Win32 QuickTime uses
3762 * DirectDraw, not OpenGL.
3764 if(gl_info->supported[APPLE_FENCE] &&
3765 gl_info->supported[APPLE_CLIENT_STORAGE] &&
3766 gl_info->supported[APPLE_FLUSH_RENDER] &&
3767 gl_info->supported[APPLE_YCBCR_422]) {
3768 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported\n");
3769 TRACE_(d3d_caps)("Activating MacOS fixups\n");
3770 return TRUE;
3771 } else {
3772 TRACE_(d3d_caps)("Apple extensions are not supported\n");
3773 TRACE_(d3d_caps)("Not activating MacOS fixups\n");
3774 return FALSE;
3778 #define GLINFO_LOCATION (*gl_info)
3779 static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
3780 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
3781 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
3782 * all the texture. This function detects this bug by its symptom and disables PBOs
3783 * if the test fails.
3785 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
3786 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
3787 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
3788 * read back is compared to the original. If they are equal PBOs are assumed to work,
3789 * otherwise the PBO extension is disabled.
3791 GLuint texture, pbo;
3792 static const unsigned int pattern[] = {
3793 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
3794 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
3795 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
3796 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
3798 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
3800 if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
3801 /* No PBO -> No point in testing them */
3802 return;
3805 while(glGetError());
3806 glGenTextures(1, &texture);
3807 glBindTexture(GL_TEXTURE_2D, texture);
3808 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3809 checkGLcall("Specifying the PBO test texture\n");
3811 GL_EXTCALL(glGenBuffersARB(1, &pbo));
3812 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
3813 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
3814 checkGLcall("Specifying the PBO test pbo\n");
3816 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3817 checkGLcall("Loading the PBO test texture\n");
3819 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
3820 glFinish(); /* just to be sure */
3822 memset(check, 0, sizeof(check));
3823 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
3824 checkGLcall("Reading back the PBO test texture\n");
3826 glDeleteTextures(1, &texture);
3827 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
3828 checkGLcall("PBO test cleanup\n");
3830 if(memcmp(check, pattern, sizeof(check)) != 0) {
3831 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
3832 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
3833 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
3834 } else {
3835 TRACE_(d3d_caps)("PBO test successful\n");
3838 #undef GLINFO_LOCATION
3840 /* Certain applications(Steam) complain if we report an outdated driver version. In general,
3841 * reporting a driver version is moot because we are not the Windows driver, and we have different
3842 * bugs, features, etc.
3844 * If a card is not found in this table, the gl driver version is reported
3846 struct driver_version_information {
3847 WORD vendor; /* reported PCI card vendor ID */
3848 WORD card; /* reported PCI card device ID */
3849 WORD hipart_hi, hipart_lo; /* driver hiword to report */
3850 WORD lopart_hi, lopart_lo; /* driver loword to report */
3853 static const struct driver_version_information driver_version_table[] = {
3854 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (177.x)*/
3855 /* GeforceFX support is up to 173.x, Geforce2MX/3/4 up to 96.x, TNT/Geforce1/2 up to 71.x */
3856 /* Note that version numbers >100 lets say 123.45 use >= x.y.11.2345 and not x.y.10.12345 */
3857 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, 7, 15, 11, 7341 },
3858 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, 7, 15, 11, 7341 },
3859 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, 7, 15, 11, 7341 },
3860 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, 7, 15, 11, 7341 },
3861 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, 7, 15, 11, 7341 },
3862 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, 7, 15, 11, 7341 },
3863 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, 7, 15, 11, 7341 },
3864 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, 7, 15, 11, 7341 },
3865 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, 7, 15, 11, 7341 },
3866 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, 7, 15, 11, 7341 },
3867 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, 7, 15, 11, 7341 },
3868 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, 7, 15, 11, 7341 },
3869 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, 7, 15, 11, 7341 },
3870 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, 7, 15, 11, 7341 },
3871 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, 7, 15, 11, 7341 },
3872 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, 7, 15, 11, 7341 },
3873 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, 7, 15, 11, 7341 },
3875 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
3876 {VENDOR_ATI, CARD_ATI_RADEON_9500, 6, 14, 10, 6764 },
3877 {VENDOR_ATI, CARD_ATI_RADEON_X700, 6, 14, 10, 6764 },
3878 {VENDOR_ATI, CARD_ATI_RADEON_X1600, 6, 14, 10, 6764 },
3879 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, 6, 14, 10, 6764 },
3880 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, 6, 14, 10, 6764 },
3881 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, 6, 14, 10, 6764 },
3883 /* TODO: Add information about legacy nvidia and ATI hardware, Intel and other cards */
3886 static void fixup_extensions(WineD3D_GL_Info *gl_info) {
3887 unsigned int i;
3888 BOOL apple = implementation_is_apple(gl_info);
3890 if(apple) {
3891 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
3892 * used it falls back to software. While the compiler can detect if the shader uses all declared
3893 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
3894 * using relative addressing falls back to software.
3896 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
3898 if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
3899 FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
3900 } else {
3901 TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
3902 gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
3903 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
3906 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
3907 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
3908 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
3909 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
3910 * according to the spec.
3912 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
3913 * makes the shader slower and eats instruction slots which should be available to the d3d app.
3915 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
3916 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
3917 * this workaround is activated on cards that do not need it, it won't break things, just affect
3918 * performance negatively.
3920 if(gl_info->gl_vendor == VENDOR_INTEL ||
3921 (gl_info->gl_vendor == VENDOR_ATI && gl_info->gl_card != CARD_ATI_RADEON_X1600)) {
3922 TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
3923 gl_info->set_texcoord_w = TRUE;
3927 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
3928 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
3929 * If real NP2 textures are used, the driver falls back to software. We could just remove the
3930 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
3931 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
3932 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
3933 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
3935 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
3936 * has this extension promoted to core. The extension loading code sets this extension supported
3937 * due to that, so this code works on fglrx as well.
3939 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
3940 if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
3941 gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
3942 gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
3943 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
3944 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3945 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
3949 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
3950 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
3951 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
3952 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
3953 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
3954 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
3956 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
3957 * triggering the software fallback. There is not much we can do here apart from disabling the
3958 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
3959 * in IWineD3DImpl_FillGLCaps).
3960 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
3961 * post-processing effects in the game "Max Payne 2").
3962 * The behaviour can be verified through a simple test app attached in bugreport #14724.
3964 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_NVIDIA) {
3965 if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
3966 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
3967 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
3968 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
3972 /* Find out if PBOs work as they are supposed to */
3973 test_pbo_functionality(gl_info);
3975 /* Fixup the driver version */
3976 for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
3977 if(gl_info->gl_vendor == driver_version_table[i].vendor &&
3978 gl_info->gl_card == driver_version_table[i].card) {
3979 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
3981 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
3982 driver_version_table[i].lopart_lo);
3983 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
3984 driver_version_table[i].hipart_lo);
3985 break;
3990 static void WINE_GLAPI invalid_func(const void *data)
3992 ERR("Invalid vertex attribute function called\n");
3993 DebugBreak();
3996 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
3998 ERR("Invalid texcoord function called\n");
3999 DebugBreak();
4002 #define GLINFO_LOCATION (Adapters[0].gl_info)
4004 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4005 * the extension detection and are used in drawStridedSlow
4007 static void WINE_GLAPI position_d3dcolor(const void *data)
4009 DWORD pos = *((const DWORD *)data);
4011 FIXME("Add a test for fixed function position from d3dcolor type\n");
4012 glVertex4s(D3DCOLOR_B_R(pos),
4013 D3DCOLOR_B_G(pos),
4014 D3DCOLOR_B_B(pos),
4015 D3DCOLOR_B_A(pos));
4018 static void WINE_GLAPI position_float4(const void *data)
4020 const GLfloat *pos = data;
4022 if (pos[3] < eps && pos[3] > -eps)
4023 glVertex3fv(pos);
4024 else {
4025 float w = 1.0 / pos[3];
4027 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4031 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4033 DWORD diffuseColor = *((const DWORD *)data);
4035 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4036 D3DCOLOR_B_G(diffuseColor),
4037 D3DCOLOR_B_B(diffuseColor),
4038 D3DCOLOR_B_A(diffuseColor));
4041 static void WINE_GLAPI specular_d3dcolor(const void *data)
4043 DWORD specularColor = *((const DWORD *)data);
4045 GL_EXTCALL(glSecondaryColor3ubEXT)(D3DCOLOR_B_R(specularColor),
4046 D3DCOLOR_B_G(specularColor),
4047 D3DCOLOR_B_B(specularColor));
4050 static void WINE_GLAPI warn_no_specular_func(const void *data)
4052 WARN("GL_EXT_secondary_color not supported\n");
4055 static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
4057 position_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4058 position_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4059 position_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glVertex3fv;
4060 position_funcs[WINED3DDECLTYPE_FLOAT4] = position_float4;
4061 position_funcs[WINED3DDECLTYPE_D3DCOLOR] = position_d3dcolor;
4062 position_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4063 position_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4064 position_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glVertex2sv;
4065 position_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4066 position_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4067 position_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4068 position_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4069 position_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4070 position_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4071 position_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4072 position_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4073 position_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4075 diffuse_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4076 diffuse_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4077 diffuse_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glColor3fv;
4078 diffuse_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glColor4fv;
4079 diffuse_funcs[WINED3DDECLTYPE_D3DCOLOR] = diffuse_d3dcolor;
4080 diffuse_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4081 diffuse_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4082 diffuse_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4083 diffuse_funcs[WINED3DDECLTYPE_UBYTE4N] = (glAttribFunc)glColor4ubv;
4084 diffuse_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4085 diffuse_funcs[WINED3DDECLTYPE_SHORT4N] = (glAttribFunc)glColor4sv;
4086 diffuse_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4087 diffuse_funcs[WINED3DDECLTYPE_USHORT4N] = (glAttribFunc)glColor4usv;
4088 diffuse_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4089 diffuse_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4090 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4091 diffuse_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4093 /* No 4 component entry points here */
4094 specular_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4095 specular_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4096 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4097 specular_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4098 } else {
4099 specular_funcs[WINED3DDECLTYPE_FLOAT3] = warn_no_specular_func;
4101 specular_funcs[WINED3DDECLTYPE_FLOAT4] = invalid_func;
4102 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4103 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = specular_d3dcolor;
4104 } else {
4105 specular_funcs[WINED3DDECLTYPE_D3DCOLOR] = warn_no_specular_func;
4107 specular_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4108 specular_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4109 specular_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4110 specular_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4111 specular_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4112 specular_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4113 specular_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4114 specular_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4115 specular_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4116 specular_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4117 specular_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4118 specular_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4120 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4121 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4123 normal_funcs[WINED3DDECLTYPE_FLOAT1] = invalid_func;
4124 normal_funcs[WINED3DDECLTYPE_FLOAT2] = invalid_func;
4125 normal_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glNormal3fv;
4126 normal_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4127 normal_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4128 normal_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4129 normal_funcs[WINED3DDECLTYPE_SHORT2] = invalid_func;
4130 normal_funcs[WINED3DDECLTYPE_SHORT4] = invalid_func;
4131 normal_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4132 normal_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4133 normal_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4134 normal_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4135 normal_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4136 normal_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4137 normal_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4138 normal_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4139 normal_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4141 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4142 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4143 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4144 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4145 multi_texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_texcoord_func;
4146 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_texcoord_func;
4147 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4148 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4149 multi_texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_texcoord_func;
4150 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_texcoord_func;
4151 multi_texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_texcoord_func;
4152 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_texcoord_func;
4153 multi_texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_texcoord_func;
4154 multi_texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_texcoord_func;
4155 multi_texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_texcoord_func;
4156 if (GL_SUPPORT(NV_HALF_FLOAT))
4158 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4159 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4160 } else {
4161 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_texcoord_func;
4162 multi_texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_texcoord_func;
4165 texcoord_funcs[WINED3DDECLTYPE_FLOAT1] = (glAttribFunc)glTexCoord1fv;
4166 texcoord_funcs[WINED3DDECLTYPE_FLOAT2] = (glAttribFunc)glTexCoord2fv;
4167 texcoord_funcs[WINED3DDECLTYPE_FLOAT3] = (glAttribFunc)glTexCoord3fv;
4168 texcoord_funcs[WINED3DDECLTYPE_FLOAT4] = (glAttribFunc)glTexCoord4fv;
4169 texcoord_funcs[WINED3DDECLTYPE_D3DCOLOR] = invalid_func;
4170 texcoord_funcs[WINED3DDECLTYPE_UBYTE4] = invalid_func;
4171 texcoord_funcs[WINED3DDECLTYPE_SHORT2] = (glAttribFunc)glTexCoord2sv;
4172 texcoord_funcs[WINED3DDECLTYPE_SHORT4] = (glAttribFunc)glTexCoord4sv;
4173 texcoord_funcs[WINED3DDECLTYPE_UBYTE4N] = invalid_func;
4174 texcoord_funcs[WINED3DDECLTYPE_SHORT2N] = invalid_func;
4175 texcoord_funcs[WINED3DDECLTYPE_SHORT4N] = invalid_func;
4176 texcoord_funcs[WINED3DDECLTYPE_USHORT2N] = invalid_func;
4177 texcoord_funcs[WINED3DDECLTYPE_USHORT4N] = invalid_func;
4178 texcoord_funcs[WINED3DDECLTYPE_UDEC3] = invalid_func;
4179 texcoord_funcs[WINED3DDECLTYPE_DEC3N] = invalid_func;
4180 if (GL_SUPPORT(NV_HALF_FLOAT))
4182 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = (glAttribFunc)GL_EXTCALL(glTexCoord2hvNV);
4183 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = (glAttribFunc)GL_EXTCALL(glTexCoord4hvNV);
4184 } else {
4185 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_2] = invalid_func;
4186 texcoord_funcs[WINED3DDECLTYPE_FLOAT16_4] = invalid_func;
4190 #define PUSH1(att) attribs[nAttribs++] = (att);
4191 BOOL InitAdapters(void) {
4192 static HMODULE mod_gl, mod_win32gl;
4193 BOOL ret;
4194 int ps_selected_mode, vs_selected_mode;
4196 /* No need to hold any lock. The calling library makes sure only one thread calls
4197 * wined3d simultaneously
4199 if(numAdapters > 0) return Adapters[0].opengl;
4201 TRACE("Initializing adapters\n");
4203 if(!mod_gl) {
4204 #ifdef USE_WIN32_OPENGL
4205 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4206 mod_gl = LoadLibraryA("opengl32.dll");
4207 if(!mod_gl) {
4208 ERR("Can't load opengl32.dll!\n");
4209 goto nogl_adapter;
4211 mod_win32gl = mod_gl;
4212 #else
4213 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4214 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4215 mod_gl = GetModuleHandleA("gdi32.dll");
4216 mod_win32gl = LoadLibraryA("opengl32.dll");
4217 if(!mod_win32gl) {
4218 ERR("Can't load opengl32.dll!\n");
4219 goto nogl_adapter;
4221 #endif
4224 /* Load WGL core functions from opengl32.dll */
4225 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4226 WGL_FUNCS_GEN;
4227 #undef USE_WGL_FUNC
4229 if(!pwglGetProcAddress) {
4230 ERR("Unable to load wglGetProcAddress!\n");
4231 goto nogl_adapter;
4234 /* Dynamically load all GL core functions */
4235 GL_FUNCS_GEN;
4236 #undef USE_GL_FUNC
4238 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4239 * otherwise because we have to use winex11.drv's override
4241 glFinish = (void*)GetProcAddress(mod_win32gl, "glFinish");
4242 glFlush = (void*)GetProcAddress(mod_win32gl, "glFlush");
4244 /* For now only one default adapter */
4246 int iPixelFormat;
4247 int attribs[10];
4248 int values[10];
4249 int nAttribs = 0;
4250 int res;
4251 int i;
4252 WineD3D_PixelFormat *cfgs;
4253 int attribute;
4254 DISPLAY_DEVICEW DisplayDevice;
4255 HDC hdc;
4257 TRACE("Initializing default adapter\n");
4258 Adapters[0].num = 0;
4259 Adapters[0].monitorPoint.x = -1;
4260 Adapters[0].monitorPoint.y = -1;
4262 if (!WineD3D_CreateFakeGLContext()) {
4263 ERR("Failed to get a gl context for default adapter\n");
4264 WineD3D_ReleaseFakeGLContext();
4265 goto nogl_adapter;
4268 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
4269 if(!ret) {
4270 ERR("Failed to initialize gl caps for default adapter\n");
4271 WineD3D_ReleaseFakeGLContext();
4272 goto nogl_adapter;
4274 ret = initPixelFormats(&Adapters[0].gl_info);
4275 if(!ret) {
4276 ERR("Failed to init gl formats\n");
4277 WineD3D_ReleaseFakeGLContext();
4278 goto nogl_adapter;
4281 hdc = pwglGetCurrentDC();
4282 if(!hdc) {
4283 ERR("Failed to get gl HDC\n");
4284 WineD3D_ReleaseFakeGLContext();
4285 goto nogl_adapter;
4288 Adapters[0].driver = "Display";
4289 Adapters[0].description = "Direct3D HAL";
4291 /* Use the VideoRamSize registry setting when set */
4292 if(wined3d_settings.emulated_textureram)
4293 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4294 else
4295 Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
4296 Adapters[0].UsedTextureRam = 0;
4297 TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
4299 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4300 DisplayDevice.cb = sizeof(DisplayDevice);
4301 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4302 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4303 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
4305 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4306 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
4308 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
4309 cfgs = Adapters[0].cfgs;
4310 PUSH1(WGL_RED_BITS_ARB)
4311 PUSH1(WGL_GREEN_BITS_ARB)
4312 PUSH1(WGL_BLUE_BITS_ARB)
4313 PUSH1(WGL_ALPHA_BITS_ARB)
4314 PUSH1(WGL_DEPTH_BITS_ARB)
4315 PUSH1(WGL_STENCIL_BITS_ARB)
4316 PUSH1(WGL_DRAW_TO_WINDOW_ARB)
4317 PUSH1(WGL_PIXEL_TYPE_ARB)
4318 PUSH1(WGL_DOUBLE_BUFFER_ARB)
4319 PUSH1(WGL_AUX_BUFFERS_ARB)
4321 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
4322 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4324 if(!res)
4325 continue;
4327 /* Cache the pixel format */
4328 cfgs->iPixelFormat = iPixelFormat;
4329 cfgs->redSize = values[0];
4330 cfgs->greenSize = values[1];
4331 cfgs->blueSize = values[2];
4332 cfgs->alphaSize = values[3];
4333 cfgs->depthSize = values[4];
4334 cfgs->stencilSize = values[5];
4335 cfgs->windowDrawable = values[6];
4336 cfgs->iPixelType = values[7];
4337 cfgs->doubleBuffer = values[8];
4338 cfgs->auxBuffers = values[9];
4340 cfgs->pbufferDrawable = FALSE;
4341 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4342 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4343 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4344 int value;
4345 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4346 cfgs->pbufferDrawable = value;
4349 cfgs->numSamples = 0;
4350 /* Check multisample support */
4351 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4352 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4353 int value[2];
4354 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4355 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4356 * value[1] = number of multi sample buffers*/
4357 if(value[0])
4358 cfgs->numSamples = value[1];
4362 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);
4363 cfgs++;
4366 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4367 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4368 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4369 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4370 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4371 * driver is allowed to consume more bits EXCEPT for stencil bits.
4373 * Mark an adapter with this broken stencil behavior.
4375 Adapters[0].brokenStencil = TRUE;
4376 for(i=0, cfgs=Adapters[0].cfgs; i<Adapters[0].nCfgs; i++) {
4377 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4378 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4379 Adapters[0].brokenStencil = FALSE;
4380 break;
4384 fixup_extensions(&Adapters[0].gl_info);
4386 WineD3D_ReleaseFakeGLContext();
4388 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4389 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
4390 fillGLAttribFuncs(&Adapters[0].gl_info);
4391 init_type_lookup(&Adapters[0].gl_info);
4392 Adapters[0].opengl = TRUE;
4394 numAdapters = 1;
4395 TRACE("%d adapters successfully initialized\n", numAdapters);
4397 return TRUE;
4399 nogl_adapter:
4400 /* Initialize an adapter for ddraw-only memory counting */
4401 memset(Adapters, 0, sizeof(Adapters));
4402 Adapters[0].num = 0;
4403 Adapters[0].opengl = FALSE;
4404 Adapters[0].monitorPoint.x = -1;
4405 Adapters[0].monitorPoint.y = -1;
4407 Adapters[0].driver = "Display";
4408 Adapters[0].description = "WineD3D DirectDraw Emulation";
4409 if(wined3d_settings.emulated_textureram) {
4410 Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4411 } else {
4412 Adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4415 numAdapters = 1;
4416 return FALSE;
4418 #undef PUSH1
4419 #undef GLINFO_LOCATION
4421 /**********************************************************
4422 * IWineD3D VTbl follows
4423 **********************************************************/
4425 const IWineD3DVtbl IWineD3D_Vtbl =
4427 /* IUnknown */
4428 IWineD3DImpl_QueryInterface,
4429 IWineD3DImpl_AddRef,
4430 IWineD3DImpl_Release,
4431 /* IWineD3D */
4432 IWineD3DImpl_GetParent,
4433 IWineD3DImpl_GetAdapterCount,
4434 IWineD3DImpl_RegisterSoftwareDevice,
4435 IWineD3DImpl_GetAdapterMonitor,
4436 IWineD3DImpl_GetAdapterModeCount,
4437 IWineD3DImpl_EnumAdapterModes,
4438 IWineD3DImpl_GetAdapterDisplayMode,
4439 IWineD3DImpl_GetAdapterIdentifier,
4440 IWineD3DImpl_CheckDeviceMultiSampleType,
4441 IWineD3DImpl_CheckDepthStencilMatch,
4442 IWineD3DImpl_CheckDeviceType,
4443 IWineD3DImpl_CheckDeviceFormat,
4444 IWineD3DImpl_CheckDeviceFormatConversion,
4445 IWineD3DImpl_GetDeviceCaps,
4446 IWineD3DImpl_CreateDevice