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) {
634 while (isspace(*GL_Extensions)) GL_Extensions++;
635 Start = GL_Extensions;
636 while (!isspace(*GL_Extensions) && *GL_Extensions != 0x00) {
640 len = GL_Extensions - Start;
641 if (len == 0 || len >= sizeof(ThisExtn))
644 memcpy(ThisExtn, Start, len);
645 ThisExtn[len] = '\0';
646 TRACE_(d3d_caps)("- %s\n", ThisExtn);
648 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
649 if (!strcmp(ThisExtn, EXTENSION_MAP[i].extension_string)) {
650 TRACE_(d3d_caps)(" FOUND: %s support\n", EXTENSION_MAP[i].extension_string);
651 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
657 if (gl_info->supported[APPLE_FENCE]) {
658 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
659 * The apple extension interacts with some other apple exts. Disable the NV
660 * extension if the apple one is support to prevent confusion in other parts
663 gl_info->supported[NV_FENCE] = FALSE;
665 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
666 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
667 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
669 if (gl_info->supported[NV_TEXTURE_SHADER2]) {
670 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
671 * Won't occur in any real world situation though
673 gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
675 if (gl_info->supported[ARB_DRAW_BUFFERS]) {
676 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
677 gl_info->max_buffers = gl_max;
678 TRACE_(d3d_caps)("Max draw buffers: %u\n", gl_max);
680 if (gl_info->supported[ARB_MULTITEXTURE]) {
681 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
682 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
683 TRACE_(d3d_caps)("Max textures: %d\n", gl_info->max_textures);
685 if (gl_info->supported[NV_REGISTER_COMBINERS]) {
687 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
688 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
690 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
692 TRACE_(d3d_caps)("Max texture stages: %d\n", gl_info->max_texture_stages);
694 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
696 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
697 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
699 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
701 TRACE_(d3d_caps)("Max fragment samplers: %d\n", gl_info->max_fragment_samplers);
703 if (gl_info->supported[ARB_VERTEX_SHADER]) {
705 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
706 gl_info->max_vertex_samplers = tmp;
707 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
708 gl_info->max_combined_samplers = tmp;
710 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
712 TRACE_(d3d_caps)("Max vertex samplers: %u\n", gl_info->max_vertex_samplers);
713 TRACE_(d3d_caps)("Max combined samplers: %u\n", gl_info->max_combined_samplers);
715 if (gl_info->supported[ARB_VERTEX_BLEND]) {
716 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
717 gl_info->max_blends = gl_max;
718 TRACE_(d3d_caps)("Max blends: %u\n", gl_info->max_blends);
720 if (gl_info->supported[EXT_TEXTURE3D]) {
721 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
722 gl_info->max_texture3d_size = gl_max;
723 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_info->max_texture3d_size);
725 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC]) {
726 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
727 gl_info->max_anisotropy = gl_max;
728 TRACE_(d3d_caps)("Max anisotropy: %d\n", gl_info->max_anisotropy);
730 if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
731 gl_info->ps_arb_version = PS_VERSION_11;
732 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
733 gl_info->ps_arb_constantsF = gl_max;
734 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d\n", gl_info->ps_arb_constantsF);
735 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
736 gl_info->ps_arb_max_temps = gl_max;
737 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM temporaries: %d\n", gl_info->ps_arb_max_temps);
738 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
739 gl_info->ps_arb_max_instructions = gl_max;
740 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM instructions: %d\n", gl_info->ps_arb_max_instructions);
742 if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
743 gl_info->vs_arb_version = VS_VERSION_11;
744 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
745 gl_info->vs_arb_constantsF = gl_max;
746 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d\n", gl_info->vs_arb_constantsF);
747 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
748 gl_info->vs_arb_max_temps = gl_max;
749 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM temporaries: %d\n", gl_info->vs_arb_max_temps);
750 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
751 gl_info->vs_arb_max_instructions = gl_max;
752 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM instructions: %d\n", gl_info->vs_arb_max_instructions);
754 if (gl_info->supported[ARB_VERTEX_SHADER]) {
755 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
756 gl_info->vs_glsl_constantsF = gl_max / 4;
757 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u\n", gl_info->vs_glsl_constantsF);
759 if (gl_info->supported[ARB_FRAGMENT_SHADER]) {
760 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
761 gl_info->ps_glsl_constantsF = gl_max / 4;
762 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u\n", gl_info->ps_glsl_constantsF);
764 if (gl_info->supported[EXT_VERTEX_SHADER]) {
765 gl_info->vs_ati_version = VS_VERSION_11;
767 if (gl_info->supported[NV_VERTEX_PROGRAM3]) {
768 gl_info->vs_nv_version = VS_VERSION_30;
769 } else if (gl_info->supported[NV_VERTEX_PROGRAM2]) {
770 gl_info->vs_nv_version = VS_VERSION_20;
771 } else if (gl_info->supported[NV_VERTEX_PROGRAM1_1]) {
772 gl_info->vs_nv_version = VS_VERSION_11;
773 } else if (gl_info->supported[NV_VERTEX_PROGRAM]) {
774 gl_info->vs_nv_version = VS_VERSION_10;
776 if (gl_info->supported[NV_FRAGMENT_PROGRAM2]) {
777 gl_info->ps_nv_version = PS_VERSION_30;
778 } else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
779 gl_info->ps_nv_version = PS_VERSION_20;
783 checkGLcall("extension detection\n");
785 /* In some cases the number of texture stages can be larger than the number
786 * of samplers. The GF4 for example can use only 2 samplers (no fragment
787 * shaders), but 8 texture stages (register combiners). */
788 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
790 /* We can only use ORM_FBO when the hardware supports it. */
791 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
792 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
793 wined3d_settings.offscreen_rendering_mode = ORM_PBUFFER;
796 /* MRTs are currently only supported when FBOs are used. */
797 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
798 gl_info->max_buffers = 1;
801 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
802 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
803 * in case of the latest videocards in the number of pixel/vertex pipelines.
805 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
806 * rendering. Various games use this information to get a rough estimation of the features of the card
807 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
808 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
809 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
812 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
813 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
814 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
815 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
816 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
817 * is used for rendering which is not always the case). This would work but it is not very portable. Second
818 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
821 * As said most games only use the PCI id to get an indication of the capabilities of the card.
822 * It doesn't really matter if the given id is the correct one if we return the id of a card with
823 * similar 3d features.
825 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
826 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
827 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
828 * won't pass we return a default card. This way is better than maintaining a full card database as even
829 * without a full database we can return a card with similar features. Second the size of the database
830 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
831 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
832 * to distinguishes between different models from that family.
834 switch (gl_info->gl_vendor) {
836 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
837 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
839 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
840 if (strstr(gl_info->gl_renderer, "7800") ||
841 strstr(gl_info->gl_renderer, "7900") ||
842 strstr(gl_info->gl_renderer, "7950") ||
843 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
844 strstr(gl_info->gl_renderer, "Quadro FX 5"))
845 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
846 else if(strstr(gl_info->gl_renderer, "6800") ||
847 strstr(gl_info->gl_renderer, "7600"))
848 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
849 else if(strstr(gl_info->gl_renderer, "6600") ||
850 strstr(gl_info->gl_renderer, "6610") ||
851 strstr(gl_info->gl_renderer, "6700"))
852 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
854 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
855 } else if(WINE_D3D9_CAPABLE(gl_info)) {
856 if (strstr(gl_info->gl_renderer, "5800") ||
857 strstr(gl_info->gl_renderer, "5900") ||
858 strstr(gl_info->gl_renderer, "5950") ||
859 strstr(gl_info->gl_renderer, "Quadro FX"))
860 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
861 else if(strstr(gl_info->gl_renderer, "5600") ||
862 strstr(gl_info->gl_renderer, "5650") ||
863 strstr(gl_info->gl_renderer, "5700") ||
864 strstr(gl_info->gl_renderer, "5750"))
865 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
867 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
868 } else if(WINE_D3D8_CAPABLE(gl_info)) {
869 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
870 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
872 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
873 } else if(WINE_D3D7_CAPABLE(gl_info)) {
874 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
875 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
876 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
877 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
878 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
879 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
881 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
883 if (strstr(gl_info->gl_renderer, "TNT2"))
884 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
886 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
890 if(WINE_D3D9_CAPABLE(gl_info)) {
892 if (strstr(gl_info->gl_renderer, "X1600") ||
893 strstr(gl_info->gl_renderer, "X1800") ||
894 strstr(gl_info->gl_renderer, "X1900") ||
895 strstr(gl_info->gl_renderer, "X1950"))
896 gl_info->gl_card = CARD_ATI_RADEON_X1600;
897 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
898 else if(strstr(gl_info->gl_renderer, "X700") ||
899 strstr(gl_info->gl_renderer, "X800") ||
900 strstr(gl_info->gl_renderer, "X850") ||
901 strstr(gl_info->gl_renderer, "X1300") ||
902 strstr(gl_info->gl_renderer, "X1400"))
903 gl_info->gl_card = CARD_ATI_RADEON_X700;
906 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
907 } else if(WINE_D3D8_CAPABLE(gl_info)) {
908 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
909 } else if(WINE_D3D7_CAPABLE(gl_info)) {
910 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
912 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
915 if (strstr(gl_info->gl_renderer, "915GM")) {
916 gl_info->gl_card = CARD_INTEL_I915GM;
917 } else if (strstr(gl_info->gl_renderer, "915G")) {
918 gl_info->gl_card = CARD_INTEL_I915G;
919 } else if (strstr(gl_info->gl_renderer, "865G")) {
920 gl_info->gl_card = CARD_INTEL_I865G;
921 } else if (strstr(gl_info->gl_renderer, "855G")) {
922 gl_info->gl_card = CARD_INTEL_I855G;
923 } else if (strstr(gl_info->gl_renderer, "830G")) {
924 gl_info->gl_card = CARD_INTEL_I830G;
926 gl_info->gl_card = CARD_INTEL_I915G;
932 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
933 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
934 * them a good generic choice.
936 gl_info->gl_vendor = VENDOR_NVIDIA;
937 if(WINE_D3D9_CAPABLE(gl_info))
938 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
939 else if(WINE_D3D8_CAPABLE(gl_info))
940 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
941 else if(WINE_D3D7_CAPABLE(gl_info))
942 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
943 else if(WINE_D3D6_CAPABLE(gl_info))
944 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
946 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
948 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
950 /* Load all the lookup tables
951 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
952 minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
953 maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
955 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
956 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
959 for (i = 0; i < MAX_LOOKUPS; i++) {
960 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
963 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
964 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
965 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
966 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
967 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
968 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
969 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
970 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
971 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
972 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
974 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
975 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
976 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
977 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
978 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
981 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
982 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
983 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
984 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
985 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
986 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
987 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
988 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
989 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
990 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
991 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
992 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
993 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
995 /* TODO: config lookups */
997 /* Make sure there's an active HDC else the WGL extensions will fail */
998 hdc = wglGetCurrentDC();
1000 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1001 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1003 if (NULL == WGL_Extensions) {
1004 ERR(" WGL_Extensions returns NULL\n");
1006 while (*WGL_Extensions != 0x00) {
1011 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1012 Start = WGL_Extensions;
1013 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1017 len = WGL_Extensions - Start;
1018 if (len == 0 || len >= sizeof(ThisExtn))
1021 memcpy(ThisExtn, Start, len);
1022 ThisExtn[len] = '\0';
1023 TRACE_(d3d_caps)("- %s\n", ThisExtn);
1025 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1026 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1027 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1034 WineD3D_ReleaseFakeGLContext();
1035 return return_value;
1037 #undef GLINFO_LOCATION
1039 /**********************************************************
1040 * IWineD3D implementation follows
1041 **********************************************************/
1043 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1044 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1046 TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
1050 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1051 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1052 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1056 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1057 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1059 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1063 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1064 return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1067 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1068 of the same bpp but different resolutions */
1070 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1071 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1072 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1073 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1075 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1079 /* TODO: Store modes per adapter and read it from the adapter structure */
1080 if (Adapter == 0) { /* Display */
1084 if (!DEBUG_SINGLE_MODE) {
1087 ZeroMemory(&DevModeW, sizeof(DevModeW));
1088 DevModeW.dmSize = sizeof(DevModeW);
1089 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1093 case WINED3DFMT_UNKNOWN:
1094 /* This is for D3D8, do not enumerate P8 here */
1095 if (DevModeW.dmBitsPerPel == 32 ||
1096 DevModeW.dmBitsPerPel == 16) i++;
1098 case WINED3DFMT_X8R8G8B8:
1099 if (DevModeW.dmBitsPerPel == 32) i++;
1101 case WINED3DFMT_R5G6B5:
1102 if (DevModeW.dmBitsPerPel == 16) i++;
1105 if (DevModeW.dmBitsPerPel == 8) i++;
1108 /* Skip other modes as they do not match the requested format */
1117 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1120 FIXME_(d3d_caps)("Adapter not primary display\n");
1125 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1126 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1127 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1128 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1130 /* Validate the parameters as much as possible */
1131 if (NULL == pMode ||
1132 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1133 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1134 return WINED3DERR_INVALIDCALL;
1137 /* TODO: Store modes per adapter and read it from the adapter structure */
1138 if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
1144 ZeroMemory(&DevModeW, sizeof(DevModeW));
1145 DevModeW.dmSize = sizeof(DevModeW);
1147 /* If we are filtering to a specific format (D3D9), then need to skip
1148 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1149 just count through the ones with valid bit depths */
1150 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
1153 case WINED3DFMT_UNKNOWN:
1154 /* This is D3D8. Do not enumerate P8 here */
1155 if (DevModeW.dmBitsPerPel == 32 ||
1156 DevModeW.dmBitsPerPel == 16) i++;
1158 case WINED3DFMT_X8R8G8B8:
1159 if (DevModeW.dmBitsPerPel == 32) i++;
1161 case WINED3DFMT_R5G6B5:
1162 if (DevModeW.dmBitsPerPel == 16) i++;
1165 if (DevModeW.dmBitsPerPel == 8) i++;
1168 /* Modes that don't match what we support can get an early-out */
1169 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
1170 return WINED3DERR_INVALIDCALL;
1175 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
1176 return WINED3DERR_INVALIDCALL;
1180 /* Now get the display mode via the calculated index */
1181 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
1182 pMode->Width = DevModeW.dmPelsWidth;
1183 pMode->Height = DevModeW.dmPelsHeight;
1184 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1185 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1186 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1188 if (Format == WINED3DFMT_UNKNOWN)
1190 switch (DevModeW.dmBitsPerPel)
1193 pMode->Format = WINED3DFMT_P8;
1196 pMode->Format = WINED3DFMT_R5G6B5;
1199 pMode->Format = WINED3DFMT_X8R8G8B8;
1202 pMode->Format = WINED3DFMT_UNKNOWN;
1203 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
1206 pMode->Format = Format;
1209 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1210 return WINED3DERR_INVALIDCALL;
1213 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1214 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
1215 DevModeW.dmBitsPerPel);
1217 } else if (DEBUG_SINGLE_MODE) {
1218 /* Return one setting of the format requested */
1219 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1221 pMode->Height = 600;
1222 pMode->RefreshRate = 60;
1223 pMode->Format = (Format == WINED3DFMT_UNKNOWN) ? WINED3DFMT_X8R8G8B8 : Format;
1225 FIXME_(d3d_caps)("Adapter not primary display\n");
1231 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1232 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1233 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1235 if (NULL == pMode ||
1236 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1237 return WINED3DERR_INVALIDCALL;
1240 if (Adapter == 0) { /* Display */
1244 ZeroMemory(&DevModeW, sizeof(DevModeW));
1245 DevModeW.dmSize = sizeof(DevModeW);
1247 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
1248 pMode->Width = DevModeW.dmPelsWidth;
1249 pMode->Height = DevModeW.dmPelsHeight;
1250 bpp = DevModeW.dmBitsPerPel;
1251 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
1252 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1254 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1258 case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
1259 case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
1260 case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1261 case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1262 default: pMode->Format = WINED3DFMT_UNKNOWN;
1266 FIXME_(d3d_caps)("Adapter not primary display\n");
1269 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1270 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1274 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1275 and fields being inserted in the middle, a new structure is used in place */
1276 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1277 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1278 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1280 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1282 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1283 return WINED3DERR_INVALIDCALL;
1286 /* Return the information requested */
1287 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1288 strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
1289 strcpy(pIdentifier->Description, Adapters[Adapter].description);
1291 /* Note dx8 doesn't supply a DeviceName */
1292 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1293 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1294 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1295 pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
1296 *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
1297 *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
1298 *(pIdentifier->SubSysId) = 0;
1299 *(pIdentifier->Revision) = 0;
1301 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1302 if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
1303 *(pIdentifier->WHQLLevel) = 0;
1305 *(pIdentifier->WHQLLevel) = 1;
1311 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1312 short redSize, greenSize, blueSize, alphaSize, colorBits;
1317 if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
1318 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1322 if(cfg->redSize < redSize)
1325 if(cfg->greenSize < greenSize)
1328 if(cfg->blueSize < blueSize)
1331 if(cfg->alphaSize < alphaSize)
1337 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
1338 short depthSize, stencilSize;
1343 if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
1344 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
1348 if(cfg->depthSize < depthSize)
1351 if(cfg->stencilSize < stencilSize)
1357 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1358 WINED3DFORMAT AdapterFormat,
1359 WINED3DFORMAT RenderTargetFormat,
1360 WINED3DFORMAT DepthStencilFormat) {
1361 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1363 WineD3D_PixelFormat *cfgs;
1366 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1368 DeviceType, debug_d3ddevicetype(DeviceType),
1369 AdapterFormat, debug_d3dformat(AdapterFormat),
1370 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1371 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1373 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1374 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1375 return WINED3DERR_INVALIDCALL;
1378 cfgs = Adapters[Adapter].cfgs;
1379 nCfgs = Adapters[Adapter].nCfgs;
1380 for (it = 0; it < nCfgs; ++it) {
1381 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
1382 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
1383 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
1388 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
1390 return WINED3DERR_NOTAVAILABLE;
1393 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1394 WINED3DFORMAT SurfaceFormat,
1395 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1397 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1398 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1401 DeviceType, debug_d3ddevicetype(DeviceType),
1402 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1407 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1408 return WINED3DERR_INVALIDCALL;
1411 /* TODO: Store in Adapter structure */
1412 if (pQualityLevels != NULL) {
1413 static int s_single_shot = 0;
1414 if (!s_single_shot) {
1415 FIXME("Quality levels unsupported at present\n");
1418 *pQualityLevels = 1; /* Guess at a value! */
1421 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1422 return WINED3DERR_NOTAVAILABLE;
1425 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1426 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1428 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1430 WineD3D_PixelFormat *cfgs;
1432 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1434 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1437 CheckType, debug_d3ddevicetype(CheckType),
1438 DisplayFormat, debug_d3dformat(DisplayFormat),
1439 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1442 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1443 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1444 return WINED3DERR_INVALIDCALL;
1447 cfgs = Adapters[Adapter].cfgs;
1448 nCfgs = Adapters[Adapter].nCfgs;
1449 for (it = 0; it < nCfgs; ++it) {
1450 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
1452 TRACE_(d3d_caps)("OK\n");
1457 if(hr != WINED3D_OK)
1458 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
1460 if(hr != WINED3D_OK)
1461 TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
1466 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1467 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1468 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1469 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1470 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1473 DeviceType, debug_d3ddevicetype(DeviceType),
1474 AdapterFormat, debug_d3dformat(AdapterFormat),
1475 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1476 RType, debug_d3dresourcetype(RType),
1477 CheckFormat, debug_d3dformat(CheckFormat));
1479 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1480 return WINED3DERR_INVALIDCALL;
1483 if (Usage & WINED3DUSAGE_QUERY_FILTER) {
1484 switch (CheckFormat) {
1485 /* Filtering not supported */
1486 case WINED3DFMT_A32B32G32R32F:
1487 TRACE_(d3d_caps)("[FAILED]\n");
1488 return WINED3DERR_NOTAVAILABLE;
1494 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1495 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1496 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1497 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1498 if (!GL_LIMITS(vertex_samplers)) {
1499 TRACE_(d3d_caps)("[FAILED]\n");
1500 return WINED3DERR_NOTAVAILABLE;
1503 switch (CheckFormat) {
1504 case WINED3DFMT_A32B32G32R32F:
1505 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1506 TRACE_(d3d_caps)("[FAILED]\n");
1507 return WINED3DERR_NOTAVAILABLE;
1509 TRACE_(d3d_caps)("[OK]\n");
1513 TRACE_(d3d_caps)("[FAILED]\n");
1514 return WINED3DERR_NOTAVAILABLE;
1518 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1519 switch (CheckFormat) {
1520 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1521 * Windows supports only those 3, and enumerating the other formats confuses applications
1523 case WINED3DFMT_D24S8:
1524 case WINED3DFMT_D24X8:
1525 case WINED3DFMT_D16:
1526 TRACE_(d3d_caps)("[OK]\n");
1528 case WINED3DFMT_D16_LOCKABLE:
1529 case WINED3DFMT_D24FS8:
1530 case WINED3DFMT_D32F_LOCKABLE:
1531 case WINED3DFMT_D24X4S4:
1532 case WINED3DFMT_D15S1:
1533 case WINED3DFMT_D32:
1534 TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
1535 return WINED3DERR_NOTAVAILABLE;
1537 TRACE_(d3d_caps)("[FAILED]\n");
1538 return WINED3DERR_NOTAVAILABLE;
1540 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1541 switch (CheckFormat) {
1542 case WINED3DFMT_R8G8B8:
1543 case WINED3DFMT_A8R8G8B8:
1544 case WINED3DFMT_X8R8G8B8:
1545 case WINED3DFMT_R5G6B5:
1546 case WINED3DFMT_X1R5G5B5:
1547 case WINED3DFMT_A1R5G5B5:
1548 case WINED3DFMT_A4R4G4B4:
1549 case WINED3DFMT_R3G3B2:
1550 case WINED3DFMT_X4R4G4B4:
1551 case WINED3DFMT_A8B8G8R8:
1552 case WINED3DFMT_X8B8G8R8:
1554 TRACE_(d3d_caps)("[OK]\n");
1556 case WINED3DFMT_R16F:
1557 case WINED3DFMT_A16B16G16R16F:
1558 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1559 TRACE_(d3d_caps)("[FAILED]\n");
1560 return WINED3DERR_NOTAVAILABLE;
1562 TRACE_(d3d_caps)("[OK]\n");
1564 case WINED3DFMT_A32B32G32R32F:
1565 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1566 TRACE_(d3d_caps)("[FAILED]\n");
1567 return WINED3DERR_NOTAVAILABLE;
1569 TRACE_(d3d_caps)("[OK]\n");
1572 TRACE_(d3d_caps)("[FAILED]\n");
1573 return WINED3DERR_NOTAVAILABLE;
1575 } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
1576 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
1577 switch (CheckFormat) {
1578 case WINED3DFMT_V8U8:
1579 TRACE_(d3d_caps)("[OK]\n");
1581 /* TODO: Other bump map formats */
1583 TRACE_(d3d_caps)("[FAILED]\n");
1584 return WINED3DERR_NOTAVAILABLE;
1587 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1588 switch (CheckFormat) {
1589 case WINED3DFMT_V8U8:
1590 TRACE_(d3d_caps)("[OK]\n");
1593 TRACE_(d3d_caps)("[FAILED]\n");
1594 return WINED3DERR_NOTAVAILABLE;
1597 TRACE_(d3d_caps)("[FAILED]\n");
1598 return WINED3DERR_NOTAVAILABLE;
1601 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1602 switch (CheckFormat) {
1603 case WINED3DFMT_DXT1:
1604 case WINED3DFMT_DXT2:
1605 case WINED3DFMT_DXT3:
1606 case WINED3DFMT_DXT4:
1607 case WINED3DFMT_DXT5:
1608 TRACE_(d3d_caps)("[OK]\n");
1611 break; /* Avoid compiler warnings */
1615 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1616 if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
1617 switch (CheckFormat) {
1618 case WINED3DFMT_A8R8G8B8:
1619 case WINED3DFMT_X8R8G8B8:
1620 case WINED3DFMT_A4R4G4B4:
1622 case WINED3DFMT_A8L8:
1623 case WINED3DFMT_DXT1:
1624 case WINED3DFMT_DXT2:
1625 case WINED3DFMT_DXT3:
1626 case WINED3DFMT_DXT4:
1627 case WINED3DFMT_DXT5:
1628 TRACE_(d3d_caps)("[OK]\n");
1632 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
1633 return WINED3DERR_NOTAVAILABLE;
1637 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1639 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1641 switch (CheckFormat) {
1642 case WINED3DFMT_R16F:
1643 case WINED3DFMT_A16B16G16R16F:
1644 if (!half_pixel_support) break;
1645 case WINED3DFMT_R32F:
1646 case WINED3DFMT_A32B32G32R32F:
1647 TRACE_(d3d_caps)("[OK]\n");
1650 break; /* Avoid compiler warnings */
1654 /* This format is nothing special and it is supported perfectly.
1655 * However, ati and nvidia driver on windows do not mark this format as
1656 * supported (tested with the dxCapsViewer) and pretending to
1657 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1658 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1659 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1661 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1662 TRACE_(d3d_caps)("[FAILED]\n");
1663 return WINED3DERR_NOTAVAILABLE;
1666 switch (CheckFormat) {
1669 * supported: RGB(A) formats
1671 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1672 case WINED3DFMT_A8R8G8B8:
1673 case WINED3DFMT_X8R8G8B8:
1674 case WINED3DFMT_R5G6B5:
1675 case WINED3DFMT_X1R5G5B5:
1676 case WINED3DFMT_A1R5G5B5:
1677 case WINED3DFMT_A4R4G4B4:
1678 case WINED3DFMT_R3G3B2:
1680 case WINED3DFMT_A8R3G3B2:
1681 case WINED3DFMT_X4R4G4B4:
1682 case WINED3DFMT_A8B8G8R8:
1683 case WINED3DFMT_X8B8G8R8:
1684 case WINED3DFMT_A2R10G10B10:
1685 case WINED3DFMT_A2B10G10R10:
1686 TRACE_(d3d_caps)("[OK]\n");
1690 * supported: Palettized
1693 TRACE_(d3d_caps)("[OK]\n");
1697 * Supported: (Alpha)-Luminance
1700 case WINED3DFMT_A8L8:
1701 case WINED3DFMT_A4L4:
1702 TRACE_(d3d_caps)("[OK]\n");
1706 * Not supported for now: Bump mapping formats
1707 * Enable some because games often fail when they are not available
1708 * and are still playable even without bump mapping
1710 case WINED3DFMT_V8U8:
1711 case WINED3DFMT_V16U16:
1712 case WINED3DFMT_L6V5U5:
1713 case WINED3DFMT_X8L8V8U8:
1714 case WINED3DFMT_Q8W8V8U8:
1715 case WINED3DFMT_W11V11U10:
1716 case WINED3DFMT_A2W10V10U10:
1717 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1721 * DXTN Formats: Handled above
1730 * Odd formats - not supported
1732 case WINED3DFMT_VERTEXDATA:
1733 case WINED3DFMT_INDEX16:
1734 case WINED3DFMT_INDEX32:
1735 case WINED3DFMT_Q16W16V16U16:
1736 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1737 return WINED3DERR_NOTAVAILABLE;
1740 * Float formats: Not supported right now
1742 case WINED3DFMT_G16R16F:
1743 case WINED3DFMT_G32R32F:
1744 case WINED3DFMT_CxV8U8:
1745 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1746 return WINED3DERR_NOTAVAILABLE;
1749 case WINED3DFMT_G16R16:
1750 case WINED3DFMT_A16B16G16R16:
1751 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1752 return WINED3DERR_NOTAVAILABLE;
1754 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1755 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1756 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1757 * We can do instancing with all shader versions, but we need vertex shaders.
1759 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1760 * to enable instancing. WineD3D doesn't need that and just ignores it.
1762 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1764 case WINEMAKEFOURCC('I','N','S','T'):
1765 TRACE("ATI Instancing check hack\n");
1766 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
1767 TRACE_(d3d_caps)("[OK]\n");
1770 TRACE_(d3d_caps)("[FAILED]\n");
1771 return WINED3DERR_NOTAVAILABLE;
1778 TRACE_(d3d_caps)("[FAILED]\n");
1779 return WINED3DERR_NOTAVAILABLE;
1782 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1783 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1784 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1786 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1789 DeviceType, debug_d3ddevicetype(DeviceType),
1790 SourceFormat, debug_d3dformat(SourceFormat),
1791 TargetFormat, debug_d3dformat(TargetFormat));
1795 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1796 subset of a D3DCAPS9 structure. However, it has to come via a void *
1797 as the d3d8 interface cannot import the d3d9 header */
1798 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1800 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1801 int vs_selected_mode;
1802 int ps_selected_mode;
1804 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1806 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1807 return WINED3DERR_INVALIDCALL;
1810 select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
1812 /* This function should *not* be modifying GL caps
1813 * TODO: move the functionality where it belongs */
1814 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
1816 /* ------------------------------------------------
1817 The following fields apply to both d3d8 and d3d9
1818 ------------------------------------------------ */
1819 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1820 *pCaps->AdapterOrdinal = Adapter;
1823 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1824 WINED3DCAPS2_FULLSCREENGAMMA |
1825 WINED3DCAPS2_DYNAMICTEXTURES;
1826 *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
1827 *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE;
1829 *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
1830 WINED3DCURSORCAPS_LOWRES;
1832 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1833 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1834 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1835 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1836 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1837 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1838 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1839 WINED3DDEVCAPS_PUREDEVICE |
1840 WINED3DDEVCAPS_HWRASTERIZATION |
1841 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1842 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1843 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1844 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1845 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
1846 WINED3DDEVCAPS_RTPATCHES;
1848 *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
1849 WINED3DPMISCCAPS_CULLCCW |
1850 WINED3DPMISCCAPS_CULLCW |
1851 WINED3DPMISCCAPS_COLORWRITEENABLE |
1852 WINED3DPMISCCAPS_CLIPTLVERTS |
1853 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1854 WINED3DPMISCCAPS_MASKZ |
1855 WINED3DPMISCCAPS_BLENDOP;
1857 WINED3DPMISCCAPS_NULLREFERENCE
1858 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1859 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1860 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1861 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1862 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1863 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1865 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1867 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1868 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
1869 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1870 *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
1873 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1874 WINED3DPRASTERCAPS_PAT |
1875 WINED3DPRASTERCAPS_WFOG |
1876 WINED3DPRASTERCAPS_ZFOG |
1877 WINED3DPRASTERCAPS_FOGVERTEX |
1878 WINED3DPRASTERCAPS_FOGTABLE |
1879 WINED3DPRASTERCAPS_FOGRANGE |
1880 WINED3DPRASTERCAPS_STIPPLE |
1881 WINED3DPRASTERCAPS_SUBPIXEL |
1882 WINED3DPRASTERCAPS_ZTEST |
1883 WINED3DPRASTERCAPS_SCISSORTEST |
1884 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1885 WINED3DPRASTERCAPS_DEPTHBIAS;
1887 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1888 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1889 WINED3DPRASTERCAPS_ZBIAS |
1890 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1893 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1894 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1895 WINED3DPRASTERCAPS_ANTIALIASEDGES
1896 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1897 WINED3DPRASTERCAPS_WBUFFER */
1899 *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1900 WINED3DPCMPCAPS_EQUAL |
1901 WINED3DPCMPCAPS_GREATER |
1902 WINED3DPCMPCAPS_GREATEREQUAL |
1903 WINED3DPCMPCAPS_LESS |
1904 WINED3DPCMPCAPS_LESSEQUAL |
1905 WINED3DPCMPCAPS_NEVER |
1906 WINED3DPCMPCAPS_NOTEQUAL;
1908 *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1909 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1910 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1911 WINED3DPBLENDCAPS_DESTALPHA |
1912 WINED3DPBLENDCAPS_DESTCOLOR |
1913 WINED3DPBLENDCAPS_INVDESTALPHA |
1914 WINED3DPBLENDCAPS_INVDESTCOLOR |
1915 WINED3DPBLENDCAPS_INVSRCALPHA |
1916 WINED3DPBLENDCAPS_INVSRCCOLOR |
1917 WINED3DPBLENDCAPS_ONE |
1918 WINED3DPBLENDCAPS_SRCALPHA |
1919 WINED3DPBLENDCAPS_SRCALPHASAT |
1920 WINED3DPBLENDCAPS_SRCCOLOR |
1921 WINED3DPBLENDCAPS_ZERO;
1923 *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
1924 WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
1925 WINED3DPBLENDCAPS_BOTHSRCALPHA |
1926 WINED3DPBLENDCAPS_DESTALPHA |
1927 WINED3DPBLENDCAPS_DESTCOLOR |
1928 WINED3DPBLENDCAPS_INVDESTALPHA |
1929 WINED3DPBLENDCAPS_INVDESTCOLOR |
1930 WINED3DPBLENDCAPS_INVSRCALPHA |
1931 WINED3DPBLENDCAPS_INVSRCCOLOR |
1932 WINED3DPBLENDCAPS_ONE |
1933 WINED3DPBLENDCAPS_SRCALPHA |
1934 WINED3DPBLENDCAPS_SRCALPHASAT |
1935 WINED3DPBLENDCAPS_SRCCOLOR |
1936 WINED3DPBLENDCAPS_ZERO;
1938 *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
1939 WINED3DPCMPCAPS_EQUAL |
1940 WINED3DPCMPCAPS_GREATER |
1941 WINED3DPCMPCAPS_GREATEREQUAL |
1942 WINED3DPCMPCAPS_LESS |
1943 WINED3DPCMPCAPS_LESSEQUAL |
1944 WINED3DPCMPCAPS_NEVER |
1945 WINED3DPCMPCAPS_NOTEQUAL;
1947 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1948 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1949 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1950 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1951 WINED3DPSHADECAPS_COLORFLATRGB |
1952 WINED3DPSHADECAPS_FOGFLAT |
1953 WINED3DPSHADECAPS_FOGGOURAUD |
1954 WINED3DPSHADECAPS_SPECULARFLATRGB;
1956 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1957 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1958 WINED3DPTEXTURECAPS_BORDER |
1959 WINED3DPTEXTURECAPS_MIPMAP |
1960 WINED3DPTEXTURECAPS_PROJECTED |
1961 WINED3DPTEXTURECAPS_PERSPECTIVE |
1962 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1964 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1965 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1966 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1967 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1970 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1971 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1972 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1973 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1977 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1978 WINED3DPTFILTERCAPS_MAGFPOINT |
1979 WINED3DPTFILTERCAPS_MINFLINEAR |
1980 WINED3DPTFILTERCAPS_MINFPOINT |
1981 WINED3DPTFILTERCAPS_MIPFLINEAR |
1982 WINED3DPTFILTERCAPS_MIPFPOINT |
1983 WINED3DPTFILTERCAPS_LINEAR |
1984 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1985 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1986 WINED3DPTFILTERCAPS_MIPLINEAR |
1987 WINED3DPTFILTERCAPS_MIPNEAREST |
1988 WINED3DPTFILTERCAPS_NEAREST;
1990 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1991 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1992 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1995 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1996 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1997 WINED3DPTFILTERCAPS_MAGFPOINT |
1998 WINED3DPTFILTERCAPS_MINFLINEAR |
1999 WINED3DPTFILTERCAPS_MINFPOINT |
2000 WINED3DPTFILTERCAPS_MIPFLINEAR |
2001 WINED3DPTFILTERCAPS_MIPFPOINT |
2002 WINED3DPTFILTERCAPS_LINEAR |
2003 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2004 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2005 WINED3DPTFILTERCAPS_MIPLINEAR |
2006 WINED3DPTFILTERCAPS_MIPNEAREST |
2007 WINED3DPTFILTERCAPS_NEAREST;
2009 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2010 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2011 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2014 *pCaps->CubeTextureFilterCaps = 0;
2016 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2017 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2018 WINED3DPTFILTERCAPS_MAGFPOINT |
2019 WINED3DPTFILTERCAPS_MINFLINEAR |
2020 WINED3DPTFILTERCAPS_MINFPOINT |
2021 WINED3DPTFILTERCAPS_MIPFLINEAR |
2022 WINED3DPTFILTERCAPS_MIPFPOINT |
2023 WINED3DPTFILTERCAPS_LINEAR |
2024 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2025 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2026 WINED3DPTFILTERCAPS_MIPLINEAR |
2027 WINED3DPTFILTERCAPS_MIPNEAREST |
2028 WINED3DPTFILTERCAPS_NEAREST;
2030 *pCaps->VolumeTextureFilterCaps = 0;
2032 *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2033 WINED3DPTADDRESSCAPS_CLAMP |
2034 WINED3DPTADDRESSCAPS_WRAP;
2036 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2037 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2039 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2040 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2042 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2043 *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2046 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2047 *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
2048 WINED3DPTADDRESSCAPS_CLAMP |
2049 WINED3DPTADDRESSCAPS_WRAP;
2050 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2051 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
2053 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2054 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
2056 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2057 *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
2060 *pCaps->VolumeTextureAddressCaps = 0;
2062 *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
2063 WINED3DLINECAPS_ZTEST;
2065 WINED3DLINECAPS_BLEND
2066 WINED3DLINECAPS_ALPHACMP
2067 WINED3DLINECAPS_FOG */
2069 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2070 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2072 if(GL_SUPPORT(EXT_TEXTURE3D))
2073 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2075 *pCaps->MaxVolumeExtent = 0;
2077 *pCaps->MaxTextureRepeat = 32768;
2078 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2079 *pCaps->MaxVertexW = 1.0;
2081 *pCaps->GuardBandLeft = 0;
2082 *pCaps->GuardBandTop = 0;
2083 *pCaps->GuardBandRight = 0;
2084 *pCaps->GuardBandBottom = 0;
2086 *pCaps->ExtentsAdjust = 0;
2088 *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
2089 WINED3DSTENCILCAPS_INCRSAT |
2090 WINED3DSTENCILCAPS_INVERT |
2091 WINED3DSTENCILCAPS_KEEP |
2092 WINED3DSTENCILCAPS_REPLACE |
2093 WINED3DSTENCILCAPS_ZERO;
2094 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2095 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
2096 WINED3DSTENCILCAPS_INCR;
2098 if ( This->dxVersion > 8 &&
2099 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2100 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2101 *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
2104 *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2106 *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
2107 WINED3DTEXOPCAPS_ADDSIGNED |
2108 WINED3DTEXOPCAPS_ADDSIGNED2X |
2109 WINED3DTEXOPCAPS_MODULATE |
2110 WINED3DTEXOPCAPS_MODULATE2X |
2111 WINED3DTEXOPCAPS_MODULATE4X |
2112 WINED3DTEXOPCAPS_SELECTARG1 |
2113 WINED3DTEXOPCAPS_SELECTARG2 |
2114 WINED3DTEXOPCAPS_DISABLE;
2116 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2117 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2118 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2119 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2120 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
2121 WINED3DTEXOPCAPS_BLENDFACTORALPHA |
2122 WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
2123 WINED3DTEXOPCAPS_LERP |
2124 WINED3DTEXOPCAPS_SUBTRACT;
2126 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
2127 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2128 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
2129 WINED3DTEXOPCAPS_MULTIPLYADD |
2130 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2131 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2132 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2134 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2135 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
2137 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2138 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2139 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2142 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2143 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2144 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2145 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2146 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2147 * and 3D textures. It also allows us to keep the code simpler by having texture
2148 * shaders constantly enabled.
2150 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
2151 /* TODO: Luminance bump map? */
2155 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2156 WINED3DTEXOPCAPS_PREMODULATE */
2159 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2160 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2161 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2162 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2164 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2165 *pCaps->MaxVertexBlendMatrixIndex = 0;
2167 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2168 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2171 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2172 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2173 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2174 WINED3DVTXPCAPS_LOCALVIEWER |
2175 WINED3DVTXPCAPS_VERTEXFOG |
2176 WINED3DVTXPCAPS_TEXGEN;
2178 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2180 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2181 *pCaps->MaxVertexIndex = 0xFFFFF;
2182 *pCaps->MaxStreams = MAX_STREAMS;
2183 *pCaps->MaxStreamStride = 1024;
2185 if (vs_selected_mode == SHADER_GLSL) {
2186 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2187 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2188 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2189 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2190 if(GLINFO_LOCATION.vs_nv_version == VS_VERSION_20)
2191 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
2193 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
2194 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2195 } else if (vs_selected_mode == SHADER_ARB) {
2196 *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
2197 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2199 *pCaps->VertexShaderVersion = 0;
2200 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2203 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2205 if (ps_selected_mode == SHADER_GLSL) {
2206 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2207 in case of GeforceFX cards. */
2208 if(GLINFO_LOCATION.ps_nv_version == PS_VERSION_20)
2209 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
2211 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
2212 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2213 *pCaps->PixelShader1xMaxValue = 1.0;
2214 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2215 } else if (ps_selected_mode == SHADER_ARB) {
2216 *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
2217 *pCaps->PixelShader1xMaxValue = 1.0;
2218 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2220 *pCaps->PixelShaderVersion = 0;
2221 *pCaps->PixelShader1xMaxValue = 0.0;
2222 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2225 /* ------------------------------------------------
2226 The following fields apply to d3d9 only
2227 ------------------------------------------------ */
2228 if (This->dxVersion > 8) {
2229 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2230 *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
2231 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2232 *pCaps->MaxNpatchTessellationLevel = 0;
2233 *pCaps->MasterAdapterOrdinal = 0;
2234 *pCaps->AdapterOrdinalInGroup = 0;
2235 *pCaps->NumberOfAdaptersInGroup = 1;
2237 if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
2238 /* OpenGL supports all the formats below, perhaps not always
2239 * without conversion, but it supports them.
2240 * Further GLSL doesn't seem to have an official unsigned type so
2241 * don't advertise it yet as I'm not sure how we handle it.
2242 * We might need to add some clamping in the shader engine to
2244 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2245 *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
2246 WINED3DDTCAPS_UBYTE4N |
2247 WINED3DDTCAPS_SHORT2N |
2248 WINED3DDTCAPS_SHORT4N;
2249 if (GL_SUPPORT(NV_HALF_FLOAT)) {
2250 *pCaps->DeclTypes |=
2251 WINED3DDTCAPS_FLOAT16_2 |
2252 WINED3DDTCAPS_FLOAT16_4;
2255 *pCaps->DeclTypes = 0;
2257 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2260 *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
2261 WINED3DPTFILTERCAPS_MAGFPOINT |
2262 WINED3DPTFILTERCAPS_MINFLINEAR |
2263 WINED3DPTFILTERCAPS_MAGFLINEAR;
2264 *pCaps->VertexTextureFilterCaps = 0;
2266 if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
2267 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2268 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2269 *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
2270 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2271 *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
2272 *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2274 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2275 *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
2276 } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
2277 *pCaps->VS20Caps.Caps = 0;
2278 *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2279 *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
2280 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2282 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2283 *pCaps->MaxVertexShader30InstructionSlots = 0;
2284 } else { /* VS 1.x */
2285 *pCaps->VS20Caps.Caps = 0;
2286 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2287 *pCaps->VS20Caps.NumTemps = 0;
2288 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2290 *pCaps->MaxVShaderInstructionsExecuted = 0;
2291 *pCaps->MaxVertexShader30InstructionSlots = 0;
2294 if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
2295 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2296 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2298 /* 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 */
2299 *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
2300 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
2301 WINED3DPS20CAPS_PREDICATION |
2302 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
2303 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2304 *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2305 *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
2306 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2307 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2309 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2310 *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
2311 } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
2312 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2313 *pCaps->PS20Caps.Caps = 0;
2314 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2315 *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
2316 *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2317 *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2319 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2320 *pCaps->MaxPixelShader30InstructionSlots = 0;
2321 } else { /* PS 1.x */
2322 *pCaps->PS20Caps.Caps = 0;
2323 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2324 *pCaps->PS20Caps.NumTemps = 0;
2325 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2326 *pCaps->PS20Caps.NumInstructionSlots = 0;
2328 *pCaps->MaxPShaderInstructionsExecuted = 0;
2329 *pCaps->MaxPixelShader30InstructionSlots = 0;
2336 static unsigned int glsl_program_key_hash(void *key) {
2337 glsl_program_key_t *k = (glsl_program_key_t *)key;
2339 unsigned int hash = k->vshader | k->pshader << 16;
2340 hash += ~(hash << 15);
2341 hash ^= (hash >> 10);
2342 hash += (hash << 3);
2343 hash ^= (hash >> 6);
2344 hash += ~(hash << 11);
2345 hash ^= (hash >> 16);
2350 static BOOL glsl_program_key_compare(void *keya, void *keyb) {
2351 glsl_program_key_t *ka = (glsl_program_key_t *)keya;
2352 glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
2354 return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
2357 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2358 and fields being inserted in the middle, a new structure is used in place */
2359 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2360 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2363 IWineD3DDeviceImpl *object = NULL;
2364 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2368 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
2369 * number and create a device without a 3D adapter for 2D only operation.
2371 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
2372 return WINED3DERR_INVALIDCALL;
2375 /* Create a WineD3DDevice object */
2376 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2377 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2378 TRACE("Created WineD3DDevice object @ %p\n", object);
2379 if (NULL == object) {
2380 return WINED3DERR_OUTOFVIDEOMEMORY;
2383 /* Set up initial COM information */
2384 object->lpVtbl = &IWineD3DDevice_Vtbl;
2386 object->wineD3D = iface;
2387 object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
2388 IWineD3D_AddRef(object->wineD3D);
2389 object->parent = parent;
2391 if(This->dxVersion == 7) {
2392 object->surface_alignment = 8;
2394 object->surface_alignment = 4;
2397 /* Set the state up as invalid until the device is fully created */
2398 object->state = WINED3DERR_DRIVERINTERNALERROR;
2400 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2401 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2403 /* Save the creation parameters */
2404 object->createParms.AdapterOrdinal = Adapter;
2405 object->createParms.DeviceType = DeviceType;
2406 object->createParms.hFocusWindow = hFocusWindow;
2407 object->createParms.BehaviorFlags = BehaviourFlags;
2409 /* Initialize other useful values */
2410 object->adapterNo = Adapter;
2411 object->devType = DeviceType;
2413 select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
2414 if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
2415 object->shader_backend = &glsl_shader_backend;
2416 object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
2417 } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
2418 object->shader_backend = &arb_program_shader_backend;
2420 object->shader_backend = &none_shader_backend;
2423 /* set the state of the device to valid */
2424 object->state = WINED3D_OK;
2426 /* Get the initial screen setup for ddraw */
2427 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2428 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2430 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2433 for(i = 0; i < PATCHMAP_SIZE; i++) {
2434 list_init(&object->patches[i]);
2438 #undef GLINFO_LOCATION
2440 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2441 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2442 IUnknown_AddRef(This->parent);
2443 *pParent = This->parent;
2447 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
2448 IUnknown* surfaceParent;
2449 TRACE("(%p) call back\n", pSurface);
2451 /* Now, release the parent, which will take care of cleaning up the surface for us */
2452 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
2453 IUnknown_Release(surfaceParent);
2454 return IUnknown_Release(surfaceParent);
2457 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
2458 IUnknown* volumeParent;
2459 TRACE("(%p) call back\n", pVolume);
2461 /* Now, release the parent, which will take care of cleaning up the volume for us */
2462 IWineD3DVolume_GetParent(pVolume, &volumeParent);
2463 IUnknown_Release(volumeParent);
2464 return IUnknown_Release(volumeParent);
2467 #define PUSH1(att) attribs[nAttribs++] = (att);
2468 #define GLINFO_LOCATION (Adapters[0].gl_info)
2469 BOOL InitAdapters(void) {
2471 int ps_selected_mode, vs_selected_mode;
2473 /* No need to hold any lock. The calling library makes sure only one thread calls
2474 * wined3d simultaneously
2476 if(numAdapters > 0) return TRUE;
2478 TRACE("Initializing adapters\n");
2479 /* For now only one default adapter */
2482 DISPLAY_DEVICEW DisplayDevice;
2484 TRACE("Initializing default adapter\n");
2485 Adapters[0].monitorPoint.x = -1;
2486 Adapters[0].monitorPoint.y = -1;
2488 ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
2490 ERR("Failed to initialize gl caps for default adapter\n");
2491 HeapFree(GetProcessHeap(), 0, Adapters);
2494 ret = initPixelFormats(&Adapters[0].gl_info);
2496 ERR("Failed to init gl formats\n");
2497 HeapFree(GetProcessHeap(), 0, Adapters);
2501 Adapters[0].driver = "Display";
2502 Adapters[0].description = "Direct3D HAL";
2504 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
2505 DisplayDevice.cb = sizeof(DisplayDevice);
2506 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
2507 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
2508 strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
2510 if (WineD3D_CreateFakeGLContext()) {
2516 WineD3D_PixelFormat *cfgs;
2518 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
2519 GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
2521 Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
2522 cfgs = Adapters[0].cfgs;
2523 PUSH1(WGL_RED_BITS_ARB)
2524 PUSH1(WGL_GREEN_BITS_ARB)
2525 PUSH1(WGL_BLUE_BITS_ARB)
2526 PUSH1(WGL_ALPHA_BITS_ARB)
2527 PUSH1(WGL_DEPTH_BITS_ARB)
2528 PUSH1(WGL_STENCIL_BITS_ARB)
2530 for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
2531 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(wined3d_fake_gl_context_hdc, iPixelFormat, 0, nAttribs, attribs, values));
2536 /* Cache the pixel format */
2537 cfgs->iPixelFormat = iPixelFormat;
2538 cfgs->redSize = values[0];
2539 cfgs->greenSize = values[1];
2540 cfgs->blueSize = values[2];
2541 cfgs->alphaSize = values[3];
2542 cfgs->depthSize = values[4];
2543 cfgs->stencilSize = values[5];
2545 TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize);
2548 WineD3D_ReleaseFakeGLContext();
2551 select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
2552 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
2556 TRACE("%d adapters successfully initialized\n", numAdapters);
2561 #undef GLINFO_LOCATION
2563 /**********************************************************
2564 * IWineD3D VTbl follows
2565 **********************************************************/
2567 const IWineD3DVtbl IWineD3D_Vtbl =
2570 IWineD3DImpl_QueryInterface,
2571 IWineD3DImpl_AddRef,
2572 IWineD3DImpl_Release,
2574 IWineD3DImpl_GetParent,
2575 IWineD3DImpl_GetAdapterCount,
2576 IWineD3DImpl_RegisterSoftwareDevice,
2577 IWineD3DImpl_GetAdapterMonitor,
2578 IWineD3DImpl_GetAdapterModeCount,
2579 IWineD3DImpl_EnumAdapterModes,
2580 IWineD3DImpl_GetAdapterDisplayMode,
2581 IWineD3DImpl_GetAdapterIdentifier,
2582 IWineD3DImpl_CheckDeviceMultiSampleType,
2583 IWineD3DImpl_CheckDepthStencilMatch,
2584 IWineD3DImpl_CheckDeviceType,
2585 IWineD3DImpl_CheckDeviceFormat,
2586 IWineD3DImpl_CheckDeviceFormatConversion,
2587 IWineD3DImpl_GetDeviceCaps,
2588 IWineD3DImpl_CreateDevice