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