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
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
39 /* Extension detection */
41 const char *extension_string;
42 GL_SupportedExt extension;
45 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE},
46 {"GL_APPLE_fence", APPLE_FENCE},
49 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL},
50 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3},
51 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE},
52 {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP},
55 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS},
56 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM},
57 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER},
58 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL},
59 {"GL_ARB_imaging", ARB_IMAGING},
60 {"GL_ARB_multisample", ARB_MULTISAMPLE}, /* needs GLX_ARB_MULTISAMPLE as well */
61 {"GL_ARB_multitexture", ARB_MULTITEXTURE},
62 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY},
63 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT},
64 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS},
65 {"GL_ARB_point_sprite", ARB_POINT_SPRITE},
66 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP},
67 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION},
68 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP},
69 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD},
70 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE},
71 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3},
72 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT},
73 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT},
74 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO},
75 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND},
76 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT},
77 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM},
78 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER},
81 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX},
82 {"GL_EXT_fog_coord", EXT_FOG_COORD},
83 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT},
84 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT},
85 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE},
86 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS},
87 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR},
88 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE},
89 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP},
90 {"GL_EXT_texture3D", EXT_TEXTURE3D},
91 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC},
92 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD},
93 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE},
94 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3},
95 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB},
96 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC},
97 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD},
98 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS},
99 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER},
100 {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING},
103 {"GL_NV_half_float", NV_HALF_FLOAT},
104 {"GL_NV_fence", NV_FENCE},
105 {"GL_NV_fog_distance", NV_FOG_DISTANCE},
106 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM},
107 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2},
108 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS},
109 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2},
110 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION},
111 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4},
112 {"GL_NV_texture_shader", NV_TEXTURE_SHADER},
113 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2},
114 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3},
115 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY},
116 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM},
117 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1},
118 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2},
119 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3},
122 /**********************************************************
123 * Utility functions follow
124 **********************************************************/
127 static int numAdapters = 0;
128 static struct WineD3DAdapter Adapters[1];
131 int minLookup[MAX_LOOKUPS];
132 int maxLookup[MAX_LOOKUPS];
133 DWORD *stateLookup[MAX_LOOKUPS];
135 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
139 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
140 * ie there is no GL Context - Get a default rendering context to enable the
141 * function query some info from GL
144 static int wined3d_fake_gl_context_ref = 0;
145 static BOOL wined3d_fake_gl_context_foreign;
146 static BOOL wined3d_fake_gl_context_available = FALSE;
147 static HDC wined3d_fake_gl_context_hdc = NULL;
148 static HWND wined3d_fake_gl_context_hwnd = NULL;
150 static CRITICAL_SECTION wined3d_fake_gl_context_cs;
151 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug =
153 0, 0, &wined3d_fake_gl_context_cs,
154 { &wined3d_fake_gl_context_cs_debug.ProcessLocksList,
155 &wined3d_fake_gl_context_cs_debug.ProcessLocksList },
156 0, 0, { (DWORD_PTR)(__FILE__ ": wined3d_fake_gl_context_cs") }
158 static CRITICAL_SECTION wined3d_fake_gl_context_cs = { &wined3d_fake_gl_context_cs_debug, -1, 0, 0, 0, 0 };
160 static void WineD3D_ReleaseFakeGLContext(void) {
163 EnterCriticalSection(&wined3d_fake_gl_context_cs);
165 if(!wined3d_fake_gl_context_available) {
166 TRACE_(d3d_caps)("context not available\n");
167 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
171 glCtx = wglGetCurrentContext();
173 TRACE_(d3d_caps)("decrementing ref from %i\n", wined3d_fake_gl_context_ref);
174 if (0 == (--wined3d_fake_gl_context_ref) ) {
175 if(!wined3d_fake_gl_context_foreign && glCtx) {
176 TRACE_(d3d_caps)("destroying fake GL context\n");
177 wglMakeCurrent(NULL, NULL);
178 wglDeleteContext(glCtx);
180 if(wined3d_fake_gl_context_hdc)
181 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
182 wined3d_fake_gl_context_hdc = NULL; /* Make sure we don't think that it is still around */
183 if(wined3d_fake_gl_context_hwnd)
184 DestroyWindow(wined3d_fake_gl_context_hwnd);
185 wined3d_fake_gl_context_hwnd = NULL;
186 wined3d_fake_gl_context_available = FALSE;
188 assert(wined3d_fake_gl_context_ref >= 0);
190 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
194 static BOOL WineD3D_CreateFakeGLContext(void) {
198 EnterCriticalSection(&wined3d_fake_gl_context_cs);
200 TRACE("getting context...\n");
201 if(wined3d_fake_gl_context_ref > 0) goto ret;
202 assert(0 == wined3d_fake_gl_context_ref);
204 wined3d_fake_gl_context_foreign = TRUE;
206 glCtx = wglGetCurrentContext();
208 PIXELFORMATDESCRIPTOR pfd;
211 wined3d_fake_gl_context_foreign = FALSE;
213 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes */
214 wined3d_fake_gl_context_hwnd = CreateWindowA("WineD3D_OpenGL", "WineD3D fake window", WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
215 if(!wined3d_fake_gl_context_hwnd) {
216 ERR("HWND creation failed!\n");
219 wined3d_fake_gl_context_hdc = GetDC(wined3d_fake_gl_context_hwnd);
220 if(!wined3d_fake_gl_context_hdc) {
221 ERR("GetDC failed!\n");
225 /* PixelFormat selection */
226 ZeroMemory(&pfd, sizeof(pfd));
227 pfd.nSize = sizeof(pfd);
229 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW;/*PFD_GENERIC_ACCELERATED*/
230 pfd.iPixelType = PFD_TYPE_RGBA;
232 pfd.iLayerType = PFD_MAIN_PLANE;
234 iPixelFormat = ChoosePixelFormat(wined3d_fake_gl_context_hdc, &pfd);
236 /* If this happens something is very wrong as ChoosePixelFormat barely fails */
237 ERR("Can't find a suitable iPixelFormat\n");
240 DescribePixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, sizeof(pfd), &pfd);
241 SetPixelFormat(wined3d_fake_gl_context_hdc, iPixelFormat, &pfd);
243 /* Create a GL context */
244 glCtx = wglCreateContext(wined3d_fake_gl_context_hdc);
246 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
250 /* Make it the current GL context */
251 if (!wglMakeCurrent(wined3d_fake_gl_context_hdc, glCtx)) {
252 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
258 TRACE("incrementing ref from %i\n", wined3d_fake_gl_context_ref);
259 wined3d_fake_gl_context_ref++;
260 wined3d_fake_gl_context_available = TRUE;
261 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
264 if(wined3d_fake_gl_context_hdc)
265 ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
266 wined3d_fake_gl_context_hdc = NULL;
267 if(wined3d_fake_gl_context_hwnd)
268 DestroyWindow(wined3d_fake_gl_context_hwnd);
269 wined3d_fake_gl_context_hwnd = NULL;
270 if(glCtx) wglDeleteContext(glCtx);
271 LeaveCriticalSection(&wined3d_fake_gl_context_cs);
277 /**********************************************************
278 * IUnknown parts follows
279 **********************************************************/
281 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
285 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
286 if (IsEqualGUID(riid, &IID_IUnknown)
287 || IsEqualGUID(riid, &IID_IWineD3DBase)
288 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
289 IUnknown_AddRef(iface);
294 return E_NOINTERFACE;
297 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
298 IWineD3DImpl *This = (IWineD3DImpl *)iface;
299 ULONG refCount = InterlockedIncrement(&This->ref);
301 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
305 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
308 TRACE("(%p) : Releasing from %d\n", This, This->ref);
309 ref = InterlockedDecrement(&This->ref);
311 HeapFree(GetProcessHeap(), 0, This);
317 /* Set the shader type for this device, depending on the given capabilities,
318 * the device type, and the user preferences in wined3d_settings */
320 static void select_shader_mode(
321 WineD3D_GL_Info *gl_info,
322 WINED3DDEVTYPE DeviceType,
326 if (wined3d_settings.vs_mode == VS_NONE) {
327 *vs_selected = SHADER_NONE;
328 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
329 *vs_selected = SHADER_GLSL;
330 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
331 *vs_selected = SHADER_ARB;
333 *vs_selected = SHADER_NONE;
336 if (wined3d_settings.ps_mode == PS_NONE) {
337 *ps_selected = SHADER_NONE;
338 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
339 *ps_selected = SHADER_GLSL;
340 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
341 *ps_selected = SHADER_ARB;
343 *ps_selected = SHADER_NONE;
347 /** Select the number of report maximum shader constants based on the selected shader modes */
348 static void select_shader_max_constants(
349 int ps_selected_mode,
350 int vs_selected_mode,
351 WineD3D_GL_Info *gl_info) {
353 switch (vs_selected_mode) {
355 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
356 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
359 /* We have to subtract any other PARAMs that we might use in our shader programs.
360 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
361 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
362 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
365 gl_info->max_vshader_constantsF = 0;
369 switch (ps_selected_mode) {
371 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
372 * In theory the texbem instruction may need one more shader constant too. But lets assume
373 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
374 * and lets not take away a uniform needlessly from all other shaders.
376 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
379 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
380 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
382 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
385 gl_info->max_pshader_constantsF = 0;
390 /**********************************************************
391 * IWineD3D parts follows
392 **********************************************************/
394 #define GLINFO_LOCATION (*gl_info)
395 BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
396 const char *GL_Extensions = NULL;
397 const char *WGL_Extensions = NULL;
398 const char *gl_string = NULL;
399 const char *gl_string_cursor = NULL;
401 GLfloat gl_floatv[2];
402 int major = 1, minor = 0;
403 BOOL return_value = TRUE;
407 PROC (WINAPI *p_wglGetProcAddress)(LPCSTR lpszProc);
409 /* Make sure that we've got a context */
410 /* TODO: CreateFakeGLContext should really take a display as a parameter */
411 /* Only save the values obtained when a display is provided */
412 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign)
413 return_value = FALSE;
415 TRACE_(d3d_caps)("(%p)\n", gl_info);
417 gl_string = (const char *) glGetString(GL_RENDERER);
418 if (NULL == gl_string)
420 strcpy(gl_info->gl_renderer, gl_string);
422 gl_string = (const char *) glGetString(GL_VENDOR);
423 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
424 if (gl_string != NULL) {
425 /* Fill in the GL vendor */
426 if (strstr(gl_string, "NVIDIA")) {
427 gl_info->gl_vendor = VENDOR_NVIDIA;
428 } else if (strstr(gl_string, "ATI")) {
429 gl_info->gl_vendor = VENDOR_ATI;
430 } else if (strstr(gl_string, "Intel(R)") ||
431 strstr(gl_info->gl_renderer, "Intel(R)")) {
432 gl_info->gl_vendor = VENDOR_INTEL;
433 } else if (strstr(gl_string, "Mesa")) {
434 gl_info->gl_vendor = VENDOR_MESA;
436 gl_info->gl_vendor = VENDOR_WINE;
439 gl_info->gl_vendor = VENDOR_WINE;
443 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
445 /* Parse the GL_VERSION field into major and minor information */
446 gl_string = (const char *) glGetString(GL_VERSION);
447 if (gl_string != NULL) {
449 switch (gl_info->gl_vendor) {
451 gl_string_cursor = strstr(gl_string, "NVIDIA");
452 if (!gl_string_cursor) {
453 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
457 gl_string_cursor = strstr(gl_string_cursor, " ");
458 if (!gl_string_cursor) {
459 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
463 while (*gl_string_cursor == ' ') {
467 if (!*gl_string_cursor) {
468 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
472 major = atoi(gl_string_cursor);
473 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
477 if (*gl_string_cursor++ != '.') {
478 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
482 minor = atoi(gl_string_cursor);
483 minor = major*100+minor;
490 gl_string_cursor = strchr(gl_string, '-');
491 if (gl_string_cursor) {
495 /* Check if version number is of the form x.y.z */
496 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
498 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
500 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
502 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
505 /* Mark version number as malformed */
507 gl_string_cursor = 0;
510 if (!gl_string_cursor)
511 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
513 major = *gl_string_cursor - '0';
514 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
520 gl_string_cursor = strstr(gl_string, "Mesa");
521 gl_string_cursor = strstr(gl_string_cursor, " ");
522 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
523 if (*gl_string_cursor) {
527 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
528 tmp[cursor++] = *gl_string_cursor;
534 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
538 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
539 tmp[cursor++] = *gl_string_cursor;
551 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
552 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
555 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
558 * Initialize openGL extension related variables
559 * with Default values
561 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
562 gl_info->max_buffers = 1;
563 gl_info->max_textures = 1;
564 gl_info->max_texture_stages = 1;
565 gl_info->max_fragment_samplers = 1;
566 gl_info->max_vertex_samplers = 0;
567 gl_info->max_combined_samplers = 0;
568 gl_info->max_sampler_stages = 1;
569 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
570 gl_info->ps_arb_max_temps = 0;
571 gl_info->ps_arb_max_instructions = 0;
572 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
573 gl_info->vs_arb_max_temps = 0;
574 gl_info->vs_arb_max_instructions = 0;
575 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
576 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
577 gl_info->vs_glsl_constantsF = 0;
578 gl_info->ps_glsl_constantsF = 0;
579 gl_info->vs_arb_constantsF = 0;
580 gl_info->ps_arb_constantsF = 0;
582 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
583 mod_gl = LoadLibraryA("gdi32.dll");
585 ERR("Can't load gdi32.dll!\n");
589 p_wglGetProcAddress = (void*)GetProcAddress(mod_gl, "wglGetProcAddress");
590 if(!p_wglGetProcAddress) {
591 ERR("Unable to load wglGetProcAddress!\n");
595 /* Now work out what GL support this card really has */
596 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) p_wglGetProcAddress( (const char *) #pfn);
601 /* Retrieve opengl defaults */
602 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
603 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
604 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
606 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
607 gl_info->max_lights = gl_max;
608 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
610 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
611 gl_info->max_texture_size = gl_max;
612 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
614 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
615 gl_info->max_pointsize = gl_floatv[1];
616 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
618 glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
619 gl_info->max_aux_buffers = gl_max;
620 TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
622 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
623 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
624 TRACE_(d3d_caps)("GL_Extensions reported:\n");
626 if (NULL == GL_Extensions) {
627 ERR(" GL_Extensions returns NULL\n");
629 while (*GL_Extensions != 0x00) {
630 const char *Start = GL_Extensions;
633 memset(ThisExtn, 0x00, sizeof(ThisExtn));
634 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
637 memcpy(ThisExtn, Start, (GL_Extensions - Start));
638 TRACE_(d3d_caps)("- %s\n", ThisExtn);
640 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
641 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
642 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
643 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
648 if (*GL_Extensions == ' ') GL_Extensions++;
651 if (gl_info->supported[APPLE_FENCE]) {
652 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
653 * The apple extension interacts with some other apple exts. Disable the NV
654 * extension if the apple one is support to prevent confusion in other parts
657 gl_info->supported[NV_FENCE] = FALSE;
659 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
660 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
661 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
663 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
664 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
665 * Won't occur in any real world situation though
667 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
669 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
670 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
671 gl_info->max_buffers = gl_max;
672 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
674 if (gl_info->supported[ARB_MULTITEXTURE]) {
675 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
676 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
677 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
679 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
681 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
682 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
684 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
686 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
688 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
690 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
691 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
693 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
695 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
697 if (gl_info->supported[ARB_VERTEX_SHADER]) {
699 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
700 gl_info->max_vertex_samplers = tmp;
701 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
702 gl_info->max_combined_samplers = tmp;
704 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
706 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
707 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
709 if (gl_info->supported[ARB_VERTEX_BLEND]) {
710 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
711 gl_info->max_blends = gl_max;
712 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
714 if (gl_info->supported[EXT_TEXTURE3D]) {
715 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
716 gl_info->max_texture3d_size = gl_max;
717 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
719 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
720 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
721 gl_info->max_anisotropy = gl_max;
722 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
724 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
725 gl_info->ps_arb_version = PS_VERSION_11;
726 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
727 gl_info->ps_arb_constantsF = gl_max;
728 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
729 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
730 gl_info->ps_arb_max_temps = gl_max;
731 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
732 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
733 gl_info->ps_arb_max_instructions = gl_max;
734 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
736 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
737 gl_info->vs_arb_version = VS_VERSION_11;
738 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
739 gl_info->vs_arb_constantsF = gl_max;
740 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
741 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
742 gl_info->vs_arb_max_temps = gl_max;
743 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
744 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
745 gl_info->vs_arb_max_instructions = gl_max;
746 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
748 if (gl_info->supported[ARB_VERTEX_SHADER]) {
749 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
750 gl_info->vs_glsl_constantsF = gl_max / 4;
751 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
753 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
754 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
755 gl_info->ps_glsl_constantsF = gl_max / 4;
756 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
758 if (gl_info->supported[EXT_VERTEX_SHADER]) {
759 gl_info->vs_ati_version = VS_VERSION_11;
761 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
762 gl_info->vs_nv_version = VS_VERSION_30;
763 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
764 gl_info->vs_nv_version = VS_VERSION_20;
765 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
766 gl_info->vs_nv_version = VS_VERSION_11;
767 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
768 gl_info->vs_nv_version = VS_VERSION_10;
770 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
771 gl_info->ps_nv_version = PS_VERSION_30;
772 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
773 gl_info->ps_nv_version = PS_VERSION_20;
777 checkGLcall("extension detection\n");
779 /* In some cases the number of texture stages can be larger than the number
780 * of samplers. The GF4 for example can use only 2 samplers (no fragment
781 * shaders), but 8 texture stages (register combiners). */
782 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
784 /* We can only use ORM_FBO when the hardware supports it. */
785 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
786 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
787 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
790 /* MRTs are currently only supported when FBOs are used. */
791 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
792 gl_info->max_buffers = 1;
795 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
796 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
797 * in case of the latest videocards in the number of pixel/vertex pipelines.
799 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
800 * rendering. Various games use this information to get a rough estimation of the features of the card
801 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
802 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
803 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
806 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
807 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
808 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
809 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
810 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
811 * is used for rendering which is not always the case). This would work but it is not very portable. Second
812 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
815 * As said most games only use the PCI id to get an indication of the capabilities of the card.
816 * It doesn't really matter if the given id is the correct one if we return the id of a card with
817 * similar 3d features.
819 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
820 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
821 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
822 * won't pass we return a default card. This way is better than maintaining a full card database as even
823 * without a full database we can return a card with similar features. Second the size of the database
824 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
825 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
826 * to distinguishes between different models from that family.
828 switch (gl_info->gl_vendor) {
830 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
831 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
833 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
834 if (strstr(gl_info->gl_renderer, "7800") ||
835 strstr(gl_info->gl_renderer, "7900") ||
836 strstr(gl_info->gl_renderer, "7950") ||
837 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
838 strstr(gl_info->gl_renderer, "Quadro FX 5"))
839 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
840 else if(strstr(gl_info->gl_renderer, "6800") ||
841 strstr(gl_info->gl_renderer, "7600"))
842 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
843 else if(strstr(gl_info->gl_renderer, "6600") ||
844 strstr(gl_info->gl_renderer, "6610") ||
845 strstr(gl_info->gl_renderer, "6700"))
846 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
848 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
849 } else if(WINE_D3D9_CAPABLE(gl_info)) {
850 if (strstr(gl_info->gl_renderer, "5800") ||
851 strstr(gl_info->gl_renderer, "5900") ||
852 strstr(gl_info->gl_renderer, "5950") ||
853 strstr(gl_info->gl_renderer, "Quadro FX"))
854 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
855 else if(strstr(gl_info->gl_renderer, "5600") ||
856 strstr(gl_info->gl_renderer, "5650") ||
857 strstr(gl_info->gl_renderer, "5700") ||
858 strstr(gl_info->gl_renderer, "5750"))
859 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
861 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
862 } else if(WINE_D3D8_CAPABLE(gl_info)) {
863 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
864 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
866 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
867 } else if(WINE_D3D7_CAPABLE(gl_info)) {
868 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
869 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
870 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
871 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
872 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
873 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
875 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
877 if (strstr(gl_info->gl_renderer, "TNT2"))
878 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
880 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
884 if(WINE_D3D9_CAPABLE(gl_info)) {
886 if (strstr(gl_info->gl_renderer, "X1600") ||
887 strstr(gl_info->gl_renderer, "X1800") ||
888 strstr(gl_info->gl_renderer, "X1900") ||
889 strstr(gl_info->gl_renderer, "X1950"))
890 gl_info->gl_card = CARD_ATI_RADEON_X1600;
891 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
892 else if(strstr(gl_info->gl_renderer, "X700") ||
893 strstr(gl_info->gl_renderer, "X800") ||
894 strstr(gl_info->gl_renderer, "X850") ||
895 strstr(gl_info->gl_renderer, "X1300") ||
896 strstr(gl_info->gl_renderer, "X1400"))
897 gl_info->gl_card = CARD_ATI_RADEON_X700;
900 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
901 } else if(WINE_D3D8_CAPABLE(gl_info)) {
902 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
903 } else if(WINE_D3D7_CAPABLE(gl_info)) {
904 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
906 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
909 if (strstr(gl_info->gl_renderer, "915GM")) {
910 gl_info->gl_card = CARD_INTEL_I915GM;
911 } else if (strstr(gl_info->gl_renderer, "915G")) {
912 gl_info->gl_card = CARD_INTEL_I915G;
913 } else if (strstr(gl_info->gl_renderer, "865G")) {
914 gl_info->gl_card = CARD_INTEL_I865G;
915 } else if (strstr(gl_info->gl_renderer, "855G")) {
916 gl_info->gl_card = CARD_INTEL_I855G;
917 } else if (strstr(gl_info->gl_renderer, "830G")) {
918 gl_info->gl_card = CARD_INTEL_I830G;
920 gl_info->gl_card = CARD_INTEL_I915G;
926 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
927 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
928 * them a good generic choice.
930 gl_info->gl_vendor = VENDOR_NVIDIA;
931 if(WINE_D3D9_CAPABLE(gl_info))
932 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
933 else if(WINE_D3D8_CAPABLE(gl_info))
934 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
935 else if(WINE_D3D7_CAPABLE(gl_info))
936 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
937 else if(WINE_D3D6_CAPABLE(gl_info))
938 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
940 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
942 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
944 /* Load all the lookup tables
945 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
946 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
947 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
949 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
950 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
953 for (i = 0; i < MAX_LOOKUPS; i++) {
954 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
957 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
958 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
959 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
960 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
961 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
962 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
963 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
964 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
965 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
966 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
968 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
969 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
970 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
971 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
972 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
975 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
976 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
977 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
978 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
979 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
980 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
981 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
982 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
983 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
984 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
985 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
986 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
987 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
989 /* TODO: config lookups */
991 /* Make sure there's an active HDC else the WGL extensions will fail */
992 hdc = wglGetCurrentDC();
994 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
995 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
997 if (NULL == WGL_Extensions) {
998 ERR(" WGL_Extensions returns NULL\n");
1000 while (*WGL_Extensions != 0x00) {
1001 const char *Start = WGL_Extensions;
1004 memset(ThisExtn, 0x00, sizeof(ThisExtn));
1005 while (*WGL_Extensions != ' ' && *WGL_Extensions != 0x00) {
1008 memcpy(ThisExtn, Start, (WGL_Extensions - Start));
1009 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1011 if (strstr(ThisExtn, "WGL_ARB_pbuffer")) {
1012 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1013 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1016 if (*WGL_Extensions == ' ') WGL_Extensions++;
1022 WineD3D_ReleaseFakeGLContext();
1023 return return_value;
1025 #undef GLINFO_LOCATION
1027 /**********************************************************
1028 * IWineD3D implementation follows
1029 **********************************************************/
1031 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1032 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1034 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1038 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1039 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1040 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1044 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1045 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1047 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1051 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1052 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1055 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1056 of the same bpp but different resolutions */
1058 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1059 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1060 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1061 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1063 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1067 /* TODO: Store modes per adapter and read it from the adapter structure */
1068 if (Adapter == 0) { /* Display */
1072 if (!DEBUG_SINGLE_MODE) {
1075 ZeroMemory(&DevModeW, sizeof(DevModeW));
1076 DevModeW.dmSize = sizeof(DevModeW);
1077 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1081 case WINED3DFMT_UNKNOWN:
1082 /* This is for D3D8, do not enumerate P8 here */
1083 if (DevModeW.dmBitsPerPel == 32 ||
1084 DevModeW.dmBitsPerPel == 16) i++;
1086 case WINED3DFMT_X8R8G8B8:
1087 if (DevModeW.dmBitsPerPel == 32) i++;
1089 case WINED3DFMT_R5G6B5:
1090 if (DevModeW.dmBitsPerPel == 16) i++;
1093 if (DevModeW.dmBitsPerPel == 8) i++;
1096 /* Skip other modes as they do not match the requested format */
1105 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1108 FIXME_(d3d_caps)("Adapter not primary display\n");
1113 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1114 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1115 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1116 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1118 /* Validate the parameters as much as possible */
1119 if (NULL == pMode ||
1120 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1121 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1122 return WINED3DERR_INVALIDCALL;
1125 /* TODO: Store modes per adapter and read it from the adapter structure */
1126 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1132 ZeroMemory(&DevModeW, sizeof(DevModeW));
1133 DevModeW.dmSize = sizeof(DevModeW);
1135 /* If we are filtering to a specific format (D3D9), then need to skip
1136 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1137 just count through the ones with valid bit depths */
1138 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1141 case WINED3DFMT_UNKNOWN:
1142 /* This is D3D8. Do not enumerate P8 here */
1143 if (DevModeW.dmBitsPerPel == 32 ||
1144 DevModeW.dmBitsPerPel == 16) i++;
1146 case WINED3DFMT_X8R8G8B8:
1147 if (DevModeW.dmBitsPerPel == 32) i++;
1149 case WINED3DFMT_R5G6B5:
1150 if (DevModeW.dmBitsPerPel == 16) i++;
1153 if (DevModeW.dmBitsPerPel == 8) i++;
1156 /* Modes that don't match what we support can get an early-out */
1157 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1158 return WINED3DERR_INVALIDCALL;
1163 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1164 return WINED3DERR_INVALIDCALL;
1168 /* Now get the display mode via the calculated index */
1169 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1170 pMode->Width = DevModeW.dmPelsWidth;
1171 pMode->Height = DevModeW.dmPelsHeight;
1172 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1173 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1174 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1176 if (Format == WINED3DFMT_UNKNOWN)
1178 switch (DevModeW.dmBitsPerPel)
1181 pMode->Format = WINED3DFMT_P8;
1184 pMode->Format = WINED3DFMT_R5G6B5;
1187 pMode->Format = WINED3DFMT_X8R8G8B8;
1190 pMode->Format = WINED3DFMT_UNKNOWN;
1191 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1194 pMode->Format = Format;
1197 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1198 return WINED3DERR_INVALIDCALL;
1201 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1202 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1203 DevModeW.dmBitsPerPel);
1205 } else if (DEBUG_SINGLE_MODE) {
1206 /* Return one setting of the format requested */
1207 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1209 pMode->Height = 600;
1210 pMode->RefreshRate = 60;
1211 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1213 FIXME_(d3d_caps)("Adapter not primary display\n");
1219 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1220 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1221 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1223 if (NULL == pMode ||
1224 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1225 return WINED3DERR_INVALIDCALL;
1228 if (Adapter == 0) { /* Display */
1232 ZeroMemory(&DevModeW, sizeof(DevModeW));
1233 DevModeW.dmSize = sizeof(DevModeW);
1235 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1236 pMode->Width = DevModeW.dmPelsWidth;
1237 pMode->Height = DevModeW.dmPelsHeight;
1238 bpp = DevModeW.dmBitsPerPel;
1239 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1240 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1242 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1246 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1247 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1248 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1249 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1250 default: pMode->Format = WINED3DFMT_UNKNOWN;
1254 FIXME_(d3d_caps)("Adapter not primary display\n");
1257 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1258 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1262 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1263 and fields being inserted in the middle, a new structure is used in place */
1264 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1265 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1266 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1268 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1270 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1271 return WINED3DERR_INVALIDCALL;
1274 /* Return the information requested */
1275 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1276 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1277 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1279 /* Note dx8 doesn't supply a DeviceName */
1280 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1281 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1282 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1283 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1284 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1285 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1286 *(pIdentifier->SubSysId) = 0;
1287 *(pIdentifier->Revision) = 0;
1289 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1290 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1291 *(pIdentifier->WHQLLevel) = 0;
1293 *(pIdentifier->WHQLLevel) = 1;
1299 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(int iPixelFormat, WINED3DFORMAT Format) {
1300 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1302 int rb, gb, bb, ab, type, buf_sz;
1304 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RED_SIZE, &rb);
1305 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_GREEN_SIZE, &gb);
1306 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BLUE_SIZE, &bb);
1307 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_ALPHA_SIZE, &ab);
1308 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_RENDER_TYPE, &type);
1309 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1312 case WINED3DFMT_X8R8G8B8:
1313 case WINED3DFMT_R8G8B8:
1314 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1316 case WINED3DFMT_A8R8G8B8:
1317 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1319 case WINED3DFMT_A2R10G10B10:
1320 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1322 case WINED3DFMT_X1R5G5B5:
1323 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1325 case WINED3DFMT_A1R5G5B5:
1326 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1328 case WINED3DFMT_X4R4G4B4:
1329 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1331 case WINED3DFMT_R5G6B5:
1332 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1334 case WINED3DFMT_R3G3B2:
1335 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1337 case WINED3DFMT_A8P8:
1338 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1341 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1347 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1349 case WINED3DFMT_X8R8G8B8:
1350 case WINED3DFMT_R8G8B8:
1351 case WINED3DFMT_A8R8G8B8:
1352 case WINED3DFMT_A2R10G10B10:
1353 case WINED3DFMT_X1R5G5B5:
1354 case WINED3DFMT_A1R5G5B5:
1355 case WINED3DFMT_R5G6B5:
1356 case WINED3DFMT_R3G3B2:
1357 case WINED3DFMT_A8P8:
1367 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(int iPixelFormat, WINED3DFORMAT Format) {
1368 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1372 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_DEPTH_SIZE, &db);
1373 gl_test = glXGetFBConfigAttrib(display, cfgs, GLX_STENCIL_SIZE, &sb);
1376 case WINED3DFMT_D16:
1377 case WINED3DFMT_D16_LOCKABLE:
1378 if (16 == db) return TRUE;
1380 case WINED3DFMT_D32:
1381 if (32 == db) return TRUE;
1383 case WINED3DFMT_D15S1:
1384 if (15 == db) return TRUE;
1386 case WINED3DFMT_D24S8:
1387 if (24 == db && 8 == sb) return TRUE;
1389 case WINED3DFMT_D24FS8:
1390 if (24 == db && 8 == sb) return TRUE;
1392 case WINED3DFMT_D24X8:
1393 if (24 == db) return TRUE;
1395 case WINED3DFMT_D24X4S4:
1396 if (24 == db && 4 == sb) return TRUE;
1398 case WINED3DFMT_D32F_LOCKABLE:
1399 if (32 == db) return TRUE;
1405 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1407 case WINED3DFMT_D16:
1408 case WINED3DFMT_D16_LOCKABLE:
1409 case WINED3DFMT_D32:
1410 case WINED3DFMT_D15S1:
1411 case WINED3DFMT_D24S8:
1412 case WINED3DFMT_D24FS8:
1413 case WINED3DFMT_D24X8:
1414 case WINED3DFMT_D24X4S4:
1415 case WINED3DFMT_D32F_LOCKABLE:
1424 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1425 WINED3DFORMAT AdapterFormat,
1426 WINED3DFORMAT RenderTargetFormat,
1427 WINED3DFORMAT DepthStencilFormat) {
1428 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1431 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1433 DeviceType, debug_d3ddevicetype(DeviceType),
1434 AdapterFormat, debug_d3dformat(AdapterFormat),
1435 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1436 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1438 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1439 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1440 return WINED3DERR_INVALIDCALL;
1443 for (it = 0; it < Adapters[Adapter].nCfgs; ++it) {
1444 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(it, RenderTargetFormat)) {
1445 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(it, DepthStencilFormat)) {
1446 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1451 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1453 return WINED3DERR_NOTAVAILABLE;
1456 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1457 WINED3DFORMAT SurfaceFormat,
1458 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1460 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1461 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1464 DeviceType, debug_d3ddevicetype(DeviceType),
1465 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1470 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1471 return WINED3DERR_INVALIDCALL;
1474 /* TODO: Store in Adapter structure */
1475 if (pQualityLevels != NULL) {
1476 static int s_single_shot = 0;
1477 if (!s_single_shot) {
1478 FIXME("Quality levels unsupported at present\n");
1481 *pQualityLevels = 1; /* Guess at a value! */
1484 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1485 return WINED3DERR_NOTAVAILABLE;
1488 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1489 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1491 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1494 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1496 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1499 CheckType, debug_d3ddevicetype(CheckType),
1500 DisplayFormat, debug_d3dformat(DisplayFormat),
1501 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1504 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1505 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1506 return WINED3DERR_INVALIDCALL;
1509 /* TODO: Store in adapter structure */
1510 if (WineD3D_CreateFakeGLContext()) {
1511 nCfgs = DescribePixelFormat(wined3d_fake_gl_context_hdc, 0, 0, NULL);
1512 for (it = 0; it < nCfgs; ++it) {
1513 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(it, DisplayFormat)) {
1515 TRACE_(d3d_caps)("OK\n");
1520 if(hr != WINED3D_OK)
1521 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1522 WineD3D_ReleaseFakeGLContext();
1525 if(hr != WINED3D_OK)
1526 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1531 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1532 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1533 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1534 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1535 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1538 DeviceType, debug_d3ddevicetype(DeviceType),
1539 AdapterFormat, debug_d3dformat(AdapterFormat),
1540 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1541 RType, debug_d3dresourcetype(RType),
1542 CheckFormat, debug_d3dformat(CheckFormat));
1544 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1545 return WINED3DERR_INVALIDCALL;
1548 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1549 switch (CheckFormat) {
1550 /* Filtering not supported */
1551 case WINED3DFMT_A32B32G32R32F:
1552 TRACE_(d3d_caps)("[FAILED]\n");
1553 return WINED3DERR_NOTAVAILABLE;
1559 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1560 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1561 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1562 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1563 if (!GL_LIMITS(vertex_samplers)) {
1564 TRACE_(d3d_caps)("[FAILED]\n");
1565 return WINED3DERR_NOTAVAILABLE;
1568 switch (CheckFormat) {
1569 case WINED3DFMT_A32B32G32R32F:
1570 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1571 TRACE_(d3d_caps)("[FAILED]\n");
1572 return WINED3DERR_NOTAVAILABLE;
1574 TRACE_(d3d_caps)("[OK]\n");
1578 TRACE_(d3d_caps)("[FAILED]\n");
1579 return WINED3DERR_NOTAVAILABLE;
1583 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1584 switch (CheckFormat) {
1585 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1586 * Windows supports only those 3, and enumerating the other formats confuses applications
1588 case WINED3DFMT_D24S8:
1589 case WINED3DFMT_D24X8:
1590 case WINED3DFMT_D16:
1591 TRACE_(d3d_caps)("[OK]\n");
1593 case WINED3DFMT_D16_LOCKABLE:
1594 case WINED3DFMT_D24FS8:
1595 case WINED3DFMT_D32F_LOCKABLE:
1596 case WINED3DFMT_D24X4S4:
1597 case WINED3DFMT_D15S1:
1598 case WINED3DFMT_D32:
1599 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1600 return WINED3DERR_NOTAVAILABLE;
1602 TRACE_(d3d_caps)("[FAILED]\n");
1603 return WINED3DERR_NOTAVAILABLE;
1605 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1606 switch (CheckFormat) {
1607 case WINED3DFMT_R8G8B8:
1608 case WINED3DFMT_A8R8G8B8:
1609 case WINED3DFMT_X8R8G8B8:
1610 case WINED3DFMT_R5G6B5:
1611 case WINED3DFMT_X1R5G5B5:
1612 case WINED3DFMT_A1R5G5B5:
1613 case WINED3DFMT_A4R4G4B4:
1614 case WINED3DFMT_R3G3B2:
1615 case WINED3DFMT_X4R4G4B4:
1616 case WINED3DFMT_A8B8G8R8:
1617 case WINED3DFMT_X8B8G8R8:
1619 TRACE_(d3d_caps)("[OK]\n");
1621 case WINED3DFMT_R16F:
1622 case WINED3DFMT_A16B16G16R16F:
1623 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1624 TRACE_(d3d_caps)("[FAILED]\n");
1625 return WINED3DERR_NOTAVAILABLE;
1627 TRACE_(d3d_caps)("[OK]\n");
1629 case WINED3DFMT_A32B32G32R32F:
1630 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1631 TRACE_(d3d_caps)("[FAILED]\n");
1632 return WINED3DERR_NOTAVAILABLE;
1634 TRACE_(d3d_caps)("[OK]\n");
1637 TRACE_(d3d_caps)("[FAILED]\n");
1638 return WINED3DERR_NOTAVAILABLE;
1640 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1641 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1642 switch (CheckFormat) {
1643 case WINED3DFMT_V8U8:
1644 TRACE_(d3d_caps)("[OK]\n");
1646 /* TODO: Other bump map formats */
1648 TRACE_(d3d_caps)("[FAILED]\n");
1649 return WINED3DERR_NOTAVAILABLE;
1652 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1653 switch (CheckFormat) {
1654 case WINED3DFMT_V8U8:
1655 TRACE_(d3d_caps)("[OK]\n");
1658 TRACE_(d3d_caps)("[FAILED]\n");
1659 return WINED3DERR_NOTAVAILABLE;
1662 TRACE_(d3d_caps)("[FAILED]\n");
1663 return WINED3DERR_NOTAVAILABLE;
1666 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1667 switch (CheckFormat) {
1668 case WINED3DFMT_DXT1:
1669 case WINED3DFMT_DXT2:
1670 case WINED3DFMT_DXT3:
1671 case WINED3DFMT_DXT4:
1672 case WINED3DFMT_DXT5:
1673 TRACE_(d3d_caps)("[OK]\n");
1676 break; /* Avoid compiler warnings */
1680 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1681 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1682 switch (CheckFormat) {
1683 case WINED3DFMT_A8R8G8B8:
1684 case WINED3DFMT_X8R8G8B8:
1685 case WINED3DFMT_A4R4G4B4:
1687 case WINED3DFMT_A8L8:
1688 case WINED3DFMT_DXT1:
1689 case WINED3DFMT_DXT2:
1690 case WINED3DFMT_DXT3:
1691 case WINED3DFMT_DXT4:
1692 case WINED3DFMT_DXT5:
1693 TRACE_(d3d_caps)("[OK]\n");
1697 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1698 return WINED3DERR_NOTAVAILABLE;
1702 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1704 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1706 switch (CheckFormat) {
1707 case WINED3DFMT_R16F:
1708 case WINED3DFMT_A16B16G16R16F:
1709 if (!half_pixel_support) break;
1710 case WINED3DFMT_R32F:
1711 case WINED3DFMT_A32B32G32R32F:
1712 TRACE_(d3d_caps)("[OK]\n");
1715 break; /* Avoid compiler warnings */
1719 /* This format is nothing special and it is supported perfectly.
1720 * However, ati and nvidia driver on windows do not mark this format as
1721 * supported (tested with the dxCapsViewer) and pretending to
1722 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1723 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1724 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1726 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1727 TRACE_(d3d_caps)("[FAILED]\n");
1728 return WINED3DERR_NOTAVAILABLE;
1731 switch (CheckFormat) {
1734 * supported: RGB(A) formats
1736 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1737 case WINED3DFMT_A8R8G8B8:
1738 case WINED3DFMT_X8R8G8B8:
1739 case WINED3DFMT_R5G6B5:
1740 case WINED3DFMT_X1R5G5B5:
1741 case WINED3DFMT_A1R5G5B5:
1742 case WINED3DFMT_A4R4G4B4:
1743 case WINED3DFMT_R3G3B2:
1745 case WINED3DFMT_A8R3G3B2:
1746 case WINED3DFMT_X4R4G4B4:
1747 case WINED3DFMT_A8B8G8R8:
1748 case WINED3DFMT_X8B8G8R8:
1749 case WINED3DFMT_A2R10G10B10:
1750 case WINED3DFMT_A2B10G10R10:
1751 TRACE_(d3d_caps)("[OK]\n");
1755 * supported: Palettized
1758 TRACE_(d3d_caps)("[OK]\n");
1762 * Supported: (Alpha)-Luminance
1765 case WINED3DFMT_A8L8:
1766 case WINED3DFMT_A4L4:
1767 TRACE_(d3d_caps)("[OK]\n");
1771 * Not supported for now: Bump mapping formats
1772 * Enable some because games often fail when they are not available
1773 * and are still playable even without bump mapping
1775 case WINED3DFMT_V8U8:
1776 case WINED3DFMT_V16U16:
1777 case WINED3DFMT_L6V5U5:
1778 case WINED3DFMT_X8L8V8U8:
1779 case WINED3DFMT_Q8W8V8U8:
1780 case WINED3DFMT_W11V11U10:
1781 case WINED3DFMT_A2W10V10U10:
1782 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1786 * DXTN Formats: Handled above
1795 * Odd formats - not supported
1797 case WINED3DFMT_VERTEXDATA:
1798 case WINED3DFMT_INDEX16:
1799 case WINED3DFMT_INDEX32:
1800 case WINED3DFMT_Q16W16V16U16:
1801 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1802 return WINED3DERR_NOTAVAILABLE;
1805 * Float formats: Not supported right now
1807 case WINED3DFMT_G16R16F:
1808 case WINED3DFMT_G32R32F:
1809 case WINED3DFMT_CxV8U8:
1810 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1811 return WINED3DERR_NOTAVAILABLE;
1814 case WINED3DFMT_G16R16:
1815 case WINED3DFMT_A16B16G16R16:
1816 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1817 return WINED3DERR_NOTAVAILABLE;
1819 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1820 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1821 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1822 * We can do instancing with all shader versions, but we need vertex shaders.
1824 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1825 * to enable instancing. WineD3D doesn't need that and just ignores it.
1827 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1829 case WINEMAKEFOURCC('I','N','S','T'):
1830 TRACE("ATI Instancing check hack\n");
1831 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1832 TRACE_(d3d_caps)("[OK]\n");
1835 TRACE_(d3d_caps)("[FAILED]\n");
1836 return WINED3DERR_NOTAVAILABLE;
1843 TRACE_(d3d_caps)("[FAILED]\n");
1844 return WINED3DERR_NOTAVAILABLE;
1847 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1848 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1849 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1851 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1854 DeviceType, debug_d3ddevicetype(DeviceType),
1855 SourceFormat, debug_d3dformat(SourceFormat),
1856 TargetFormat, debug_d3dformat(TargetFormat));
1860 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1861 subset of a D3DCAPS9 structure. However, it has to come via a void *
1862 as the d3d8 interface cannot import the d3d9 header */
1863 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1865 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1866 int vs_selected_mode;
1867 int ps_selected_mode;
1869 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1871 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1872 return WINED3DERR_INVALIDCALL;
1875 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1877 /* This function should *not* be modifying GL caps
1878 * TODO: move the functionality where it belongs */
1879 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1881 /* ------------------------------------------------
1882 The following fields apply to both d3d8 and d3d9
1883 ------------------------------------------------ */
1884 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1885 *pCaps->AdapterOrdinal = Adapter;
1888 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1889 WINED3DCAPS2_FULLSCREENGAMMA |
1890 WINED3DCAPS2_DYNAMICTEXTURES;
1891 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1892 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1894 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1895 WINED3DCURSORCAPS_LOWRES;
1897 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1898 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1899 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1900 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1901 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1902 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1903 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1904 WINED3DDEVCAPS_PUREDEVICE |
1905 WINED3DDEVCAPS_HWRASTERIZATION |
1906 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1907 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1908 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1909 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1910 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1911 WINED3DDEVCAPS_RTPATCHES;
1913 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1914 WINED3DPMISCCAPS_CULLCCW |
1915 WINED3DPMISCCAPS_CULLCW |
1916 WINED3DPMISCCAPS_COLORWRITEENABLE |
1917 WINED3DPMISCCAPS_CLIPTLVERTS |
1918 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1919 WINED3DPMISCCAPS_MASKZ |
1920 WINED3DPMISCCAPS_BLENDOP;
1922 WINED3DPMISCCAPS_NULLREFERENCE
1923 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1924 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1925 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1926 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1927 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1928 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1930 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1932 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1933 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1934 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1935 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1938 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1939 WINED3DPRASTERCAPS_PAT |
1940 WINED3DPRASTERCAPS_WFOG |
1941 WINED3DPRASTERCAPS_ZFOG |
1942 WINED3DPRASTERCAPS_FOGVERTEX |
1943 WINED3DPRASTERCAPS_FOGTABLE |
1944 WINED3DPRASTERCAPS_FOGRANGE |
1945 WINED3DPRASTERCAPS_STIPPLE |
1946 WINED3DPRASTERCAPS_SUBPIXEL |
1947 WINED3DPRASTERCAPS_ZTEST |
1948 WINED3DPRASTERCAPS_SCISSORTEST |
1949 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1950 WINED3DPRASTERCAPS_DEPTHBIAS;
1952 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1953 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1954 WINED3DPRASTERCAPS_ZBIAS |
1955 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1958 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1959 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1960 WINED3DPRASTERCAPS_ANTIALIASEDGES
1961 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1962 WINED3DPRASTERCAPS_WBUFFER */
1964 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1965 WINED3DPCMPCAPS_EQUAL |
1966 WINED3DPCMPCAPS_GREATER |
1967 WINED3DPCMPCAPS_GREATEREQUAL |
1968 WINED3DPCMPCAPS_LESS |
1969 WINED3DPCMPCAPS_LESSEQUAL |
1970 WINED3DPCMPCAPS_NEVER |
1971 WINED3DPCMPCAPS_NOTEQUAL;
1973 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1974 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1975 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1976 WINED3DPBLENDCAPS_DESTALPHA |
1977 WINED3DPBLENDCAPS_DESTCOLOR |
1978 WINED3DPBLENDCAPS_INVDESTALPHA |
1979 WINED3DPBLENDCAPS_INVDESTCOLOR |
1980 WINED3DPBLENDCAPS_INVSRCALPHA |
1981 WINED3DPBLENDCAPS_INVSRCCOLOR |
1982 WINED3DPBLENDCAPS_ONE |
1983 WINED3DPBLENDCAPS_SRCALPHA |
1984 WINED3DPBLENDCAPS_SRCALPHASAT |
1985 WINED3DPBLENDCAPS_SRCCOLOR |
1986 WINED3DPBLENDCAPS_ZERO;
1988 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1989 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1990 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1991 WINED3DPBLENDCAPS_DESTALPHA |
1992 WINED3DPBLENDCAPS_DESTCOLOR |
1993 WINED3DPBLENDCAPS_INVDESTALPHA |
1994 WINED3DPBLENDCAPS_INVDESTCOLOR |
1995 WINED3DPBLENDCAPS_INVSRCALPHA |
1996 WINED3DPBLENDCAPS_INVSRCCOLOR |
1997 WINED3DPBLENDCAPS_ONE |
1998 WINED3DPBLENDCAPS_SRCALPHA |
1999 WINED3DPBLENDCAPS_SRCALPHASAT |
2000 WINED3DPBLENDCAPS_SRCCOLOR |
2001 WINED3DPBLENDCAPS_ZERO;
2003 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
2004 WINED3DPCMPCAPS_EQUAL |
2005 WINED3DPCMPCAPS_GREATER |
2006 WINED3DPCMPCAPS_GREATEREQUAL |
2007 WINED3DPCMPCAPS_LESS |
2008 WINED3DPCMPCAPS_LESSEQUAL |
2009 WINED3DPCMPCAPS_NEVER |
2010 WINED3DPCMPCAPS_NOTEQUAL;
2012 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
2013 WINED3DPSHADECAPS_COLORGOURAUDRGB |
2014 WINED3DPSHADECAPS_ALPHAFLATBLEND |
2015 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
2016 WINED3DPSHADECAPS_COLORFLATRGB |
2017 WINED3DPSHADECAPS_FOGFLAT |
2018 WINED3DPSHADECAPS_FOGGOURAUD |
2019 WINED3DPSHADECAPS_SPECULARFLATRGB;
2021 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
2022 WINED3DPTEXTURECAPS_ALPHAPALETTE |
2023 WINED3DPTEXTURECAPS_BORDER |
2024 WINED3DPTEXTURECAPS_MIPMAP |
2025 WINED3DPTEXTURECAPS_PROJECTED |
2026 WINED3DPTEXTURECAPS_PERSPECTIVE |
2027 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
2029 if( GL_SUPPORT(EXT_TEXTURE3D)) {
2030 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
2031 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
2032 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
2035 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2036 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
2037 WINED3DPTEXTURECAPS_MIPCUBEMAP |
2038 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
2042 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2043 WINED3DPTFILTERCAPS_MAGFPOINT |
2044 WINED3DPTFILTERCAPS_MINFLINEAR |
2045 WINED3DPTFILTERCAPS_MINFPOINT |
2046 WINED3DPTFILTERCAPS_MIPFLINEAR |
2047 WINED3DPTFILTERCAPS_MIPFPOINT |
2048 WINED3DPTFILTERCAPS_LINEAR |
2049 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2050 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2051 WINED3DPTFILTERCAPS_MIPLINEAR |
2052 WINED3DPTFILTERCAPS_MIPNEAREST |
2053 WINED3DPTFILTERCAPS_NEAREST;
2055 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2056 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2057 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2060 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2061 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2062 WINED3DPTFILTERCAPS_MAGFPOINT |
2063 WINED3DPTFILTERCAPS_MINFLINEAR |
2064 WINED3DPTFILTERCAPS_MINFPOINT |
2065 WINED3DPTFILTERCAPS_MIPFLINEAR |
2066 WINED3DPTFILTERCAPS_MIPFPOINT |
2067 WINED3DPTFILTERCAPS_LINEAR |
2068 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2069 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2070 WINED3DPTFILTERCAPS_MIPLINEAR |
2071 WINED3DPTFILTERCAPS_MIPNEAREST |
2072 WINED3DPTFILTERCAPS_NEAREST;
2074 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2075 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2076 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2079 *pCaps->CubeTextureFilterCaps = 0;
2081 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2082 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2083 WINED3DPTFILTERCAPS_MAGFPOINT |
2084 WINED3DPTFILTERCAPS_MINFLINEAR |
2085 WINED3DPTFILTERCAPS_MINFPOINT |
2086 WINED3DPTFILTERCAPS_MIPFLINEAR |
2087 WINED3DPTFILTERCAPS_MIPFPOINT |
2088 WINED3DPTFILTERCAPS_LINEAR |
2089 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2090 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2091 WINED3DPTFILTERCAPS_MIPLINEAR |
2092 WINED3DPTFILTERCAPS_MIPNEAREST |
2093 WINED3DPTFILTERCAPS_NEAREST;
2095 *pCaps->VolumeTextureFilterCaps = 0;
2097 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2098 WINED3DPTADDRESSCAPS_CLAMP |
2099 WINED3DPTADDRESSCAPS_WRAP;
2101 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2102 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2104 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2105 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2107 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2108 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2111 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2112 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2113 WINED3DPTADDRESSCAPS_CLAMP |
2114 WINED3DPTADDRESSCAPS_WRAP;
2115 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2116 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2118 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2119 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2121 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2122 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2125 *pCaps->VolumeTextureAddressCaps = 0;
2127 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2128 WINED3DLINECAPS_ZTEST;
2130 WINED3DLINECAPS_BLEND
2131 WINED3DLINECAPS_ALPHACMP
2132 WINED3DLINECAPS_FOG */
2134 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2135 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2137 if(GL_SUPPORT(EXT_TEXTURE3D))
2138 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2140 *pCaps->MaxVolumeExtent = 0;
2142 *pCaps->MaxTextureRepeat = 32768;
2143 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2144 *pCaps->MaxVertexW = 1.0;
2146 *pCaps->GuardBandLeft = 0;
2147 *pCaps->GuardBandTop = 0;
2148 *pCaps->GuardBandRight = 0;
2149 *pCaps->GuardBandBottom = 0;
2151 *pCaps->ExtentsAdjust = 0;
2153 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2154 WINED3DSTENCILCAPS_INCRSAT |
2155 WINED3DSTENCILCAPS_INVERT |
2156 WINED3DSTENCILCAPS_KEEP |
2157 WINED3DSTENCILCAPS_REPLACE |
2158 WINED3DSTENCILCAPS_ZERO;
2159 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2160 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2161 WINED3DSTENCILCAPS_INCR;
2163 if ( This->dxVersion > 8 &&
2164 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2165 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2166 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2169 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2171 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2172 WINED3DTEXOPCAPS_ADDSIGNED |
2173 WINED3DTEXOPCAPS_ADDSIGNED2X |
2174 WINED3DTEXOPCAPS_MODULATE |
2175 WINED3DTEXOPCAPS_MODULATE2X |
2176 WINED3DTEXOPCAPS_MODULATE4X |
2177 WINED3DTEXOPCAPS_SELECTARG1 |
2178 WINED3DTEXOPCAPS_SELECTARG2 |
2179 WINED3DTEXOPCAPS_DISABLE;
2181 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2182 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2183 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2184 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2185 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2186 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2187 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2188 WINED3DTEXOPCAPS_LERP |
2189 WINED3DTEXOPCAPS_SUBTRACT;
2191 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2192 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2193 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2194 WINED3DTEXOPCAPS_MULTIPLYADD |
2195 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2196 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2197 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2199 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2200 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2202 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2203 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2204 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2207 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2208 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2209 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2210 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2211 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2212 * and 3D textures. It also allows us to keep the code simpler by having texture
2213 * shaders constantly enabled.
2215 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2216 /* TODO: Luminance bump map? */
2220 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2221 WINED3DTEXOPCAPS_PREMODULATE */
2224 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2225 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2226 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2227 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2229 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2230 *pCaps->MaxVertexBlendMatrixIndex = 0;
2232 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2233 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2236 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2237 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2238 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2239 WINED3DVTXPCAPS_LOCALVIEWER |
2240 WINED3DVTXPCAPS_VERTEXFOG |
2241 WINED3DVTXPCAPS_TEXGEN;
2243 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2245 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2246 *pCaps->MaxVertexIndex = 0xFFFFF;
2247 *pCaps->MaxStreams = MAX_STREAMS;
2248 *pCaps->MaxStreamStride = 1024;
2250 if (vs_selected_mode == SHADER_GLSL) {
2251 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2252 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2253 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2254 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2255 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2256 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2258 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2259 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2260 } else if (vs_selected_mode == SHADER_ARB) {
2261 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2262 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2264 *pCaps->VertexShaderVersion = 0;
2265 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2268 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2270 if (ps_selected_mode == SHADER_GLSL) {
2271 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2272 in case of GeforceFX cards. */
2273 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2274 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2276 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2277 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2278 *pCaps->PixelShader1xMaxValue = 1.0;
2279 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2280 } else if (ps_selected_mode == SHADER_ARB) {
2281 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2282 *pCaps->PixelShader1xMaxValue = 1.0;
2283 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2285 *pCaps->PixelShaderVersion = 0;
2286 *pCaps->PixelShader1xMaxValue = 0.0;
2287 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2290 /* ------------------------------------------------
2291 The following fields apply to d3d9 only
2292 ------------------------------------------------ */
2293 if (This->dxVersion > 8) {
2294 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2295 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2296 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2297 *pCaps->MaxNpatchTessellationLevel = 0;
2298 *pCaps->MasterAdapterOrdinal = 0;
2299 *pCaps->AdapterOrdinalInGroup = 0;
2300 *pCaps->NumberOfAdaptersInGroup = 1;
2302 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2303 /* OpenGL supports all the formats below, perhaps not always
2304 * without conversion, but it supports them.
2305 * Further GLSL doesn't seem to have an official unsigned type so
2306 * don't advertise it yet as I'm not sure how we handle it.
2307 * We might need to add some clamping in the shader engine to
2309 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2310 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2311 WINED3DDTCAPS_UBYTE4N |
2312 WINED3DDTCAPS_SHORT2N |
2313 WINED3DDTCAPS_SHORT4N;
2314 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2315 *pCaps->DeclTypes |=
2316 WINED3DDTCAPS_FLOAT16_2 |
2317 WINED3DDTCAPS_FLOAT16_4;
2320 *pCaps->DeclTypes = 0;
2322 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2325 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2326 WINED3DPTFILTERCAPS_MAGFPOINT |
2327 WINED3DPTFILTERCAPS_MINFLINEAR |
2328 WINED3DPTFILTERCAPS_MAGFLINEAR;
2329 *pCaps->VertexTextureFilterCaps = 0;
2331 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2332 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2333 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2334 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2335 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2336 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2337 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2339 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2340 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2341 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2342 *pCaps->VS20Caps.Caps = 0;
2343 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2344 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2345 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2347 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2348 *pCaps->MaxVertexShader30InstructionSlots = 0;
2349 } else { /* VS 1.x */
2350 *pCaps->VS20Caps.Caps = 0;
2351 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2352 *pCaps->VS20Caps.NumTemps = 0;
2353 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2355 *pCaps->MaxVShaderInstructionsExecuted = 0;
2356 *pCaps->MaxVertexShader30InstructionSlots = 0;
2359 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2360 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2361 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2363 /* 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 */
2364 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2365 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2366 WINED3DPS20CAPS_PREDICATION |
2367 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2368 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2369 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2370 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2371 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2372 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2374 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2375 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2376 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2377 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2378 *pCaps->PS20Caps.Caps = 0;
2379 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2380 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2381 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2382 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2384 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2385 *pCaps->MaxPixelShader30InstructionSlots = 0;
2386 } else { /* PS 1.x */
2387 *pCaps->PS20Caps.Caps = 0;
2388 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2389 *pCaps->PS20Caps.NumTemps = 0;
2390 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2391 *pCaps->PS20Caps.NumInstructionSlots = 0;
2393 *pCaps->MaxPShaderInstructionsExecuted = 0;
2394 *pCaps->MaxPixelShader30InstructionSlots = 0;
2401 static unsigned int glsl_program_key_hash(void *key) {
2402 glsl_program_key_t *k = (glsl_program_key_t *)key;
2404 unsigned int hash = k->vshader | k->pshader << 16;
2405 hash += ~(hash << 15);
2406 hash ^= (hash >> 10);
2407 hash += (hash << 3);
2408 hash ^= (hash >> 6);
2409 hash += ~(hash << 11);
2410 hash ^= (hash >> 16);
2415 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2416 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2417 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2419 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2422 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2423 and fields being inserted in the middle, a new structure is used in place */
2424 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2425 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2428 IWineD3DDeviceImpl *object = NULL;
2429 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2433 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2434 * number and create a device without a 3D adapter for 2D only operation.
2436 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2437 return WINED3DERR_INVALIDCALL;
2440 /* Create a WineD3DDevice object */
2441 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2442 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2443 TRACE("Created WineD3DDevice object @ %p\n", object);
2444 if (NULL == object) {
2445 return WINED3DERR_OUTOFVIDEOMEMORY;
2448 /* Set up initial COM information */
2449 object->lpVtbl = &IWineD3DDevice_Vtbl;
2451 object->wineD3D = iface;
2452 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2453 IWineD3D_AddRef(object->wineD3D);
2454 object->parent = parent;
2456 if(This->dxVersion == 7) {
2457 object->surface_alignment = 8;
2459 object->surface_alignment = 4;
2462 /* Set the state up as invalid until the device is fully created */
2463 object->state = WINED3DERR_DRIVERINTERNALERROR;
2465 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2466 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2468 /* Save the creation parameters */
2469 object->createParms.AdapterOrdinal = Adapter;
2470 object->createParms.DeviceType = DeviceType;
2471 object->createParms.hFocusWindow = hFocusWindow;
2472 object->createParms.BehaviorFlags = BehaviourFlags;
2474 /* Initialize other useful values */
2475 object->adapterNo = Adapter;
2476 object->devType = DeviceType;
2478 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2479 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2480 object->shader_backend = &glsl_shader_backend;
2481 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2482 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2483 object->shader_backend = &arb_program_shader_backend;
2485 object->shader_backend = &none_shader_backend;
2488 /* set the state of the device to valid */
2489 object->state = WINED3D_OK;
2491 /* Get the initial screen setup for ddraw */
2492 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2493 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2495 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2498 for(i = 0; i < PATCHMAP_SIZE; i++) {
2499 list_init(&object->patches[i]);
2503 #undef GLINFO_LOCATION
2505 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2506 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2507 IUnknown_AddRef(This->parent);
2508 *pParent = This->parent;
2512 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2513 IUnknown* surfaceParent;
2514 TRACE("(%p) call back\n", pSurface);
2516 /* Now, release the parent, which will take care of cleaning up the surface for us */
2517 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2518 IUnknown_Release(surfaceParent);
2519 return IUnknown_Release(surfaceParent);
2522 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2523 IUnknown* volumeParent;
2524 TRACE("(%p) call back\n", pVolume);
2526 /* Now, release the parent, which will take care of cleaning up the volume for us */
2527 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2528 IUnknown_Release(volumeParent);
2529 return IUnknown_Release(volumeParent);
2532 #define GLINFO_LOCATION (Adapters[0].gl_info)
2533 BOOL InitAdapters(void) {
2535 int ps_selected_mode, vs_selected_mode;
2537 /* No need to hold any lock. The calling library makes sure only one thread calls
2538 * wined3d simultaneously
2540 if(numAdapters > 0) return TRUE;
2542 TRACE("Initializing adapters\n");
2543 /* For now only one default adapter */
2546 TRACE("Initializing default adapter\n");
2547 Adapters[0].monitorPoint.x = -1;
2548 Adapters[0].monitorPoint.y = -1;
2550 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2552 ERR("Failed to initialize gl caps for default adapter\n");
2553 HeapFree(GetProcessHeap(), 0, Adapters);
2556 ret = initPixelFormats(&Adapters[0].gl_info);
2558 ERR("Failed to init gl formats\n");
2559 HeapFree(GetProcessHeap(), 0, Adapters);
2563 Adapters[0].driver = "Display";
2564 Adapters[0].description = "Direct3D HAL";
2566 if (WineD3D_CreateFakeGLContext()) {
2567 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2568 GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2569 WineD3D_ReleaseFakeGLContext();
2572 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2573 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2577 TRACE("%d adapters successfully initialized\n", numAdapters);
2581 #undef GLINFO_LOCATION
2583 /**********************************************************
2584 * IWineD3D VTbl follows
2585 **********************************************************/
2587 const IWineD3DVtbl IWineD3D_Vtbl =
2590 IWineD3DImpl_QueryInterface,
2591 IWineD3DImpl_AddRef,
2592 IWineD3DImpl_Release,
2594 IWineD3DImpl_GetParent,
2595 IWineD3DImpl_GetAdapterCount,
2596 IWineD3DImpl_RegisterSoftwareDevice,
2597 IWineD3DImpl_GetAdapterMonitor,
2598 IWineD3DImpl_GetAdapterModeCount,
2599 IWineD3DImpl_EnumAdapterModes,
2600 IWineD3DImpl_GetAdapterDisplayMode,
2601 IWineD3DImpl_GetAdapterIdentifier,
2602 IWineD3DImpl_CheckDeviceMultiSampleType,
2603 IWineD3DImpl_CheckDepthStencilMatch,
2604 IWineD3DImpl_CheckDeviceType,
2605 IWineD3DImpl_CheckDeviceFormat,
2606 IWineD3DImpl_CheckDeviceFormatConversion,
2607 IWineD3DImpl_GetDeviceCaps,
2608 IWineD3DImpl_CreateDevice