2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
9 * Copyright 2009 Henri Verbeet for CodeWeavers
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
32 #define GLINFO_LOCATION (*gl_info)
34 /* The d3d device ID */
35 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
37 /* Extension detection */
39 const char *extension_string;
40 GL_SupportedExt extension;
44 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
45 {"GL_APPLE_fence", APPLE_FENCE, 0 },
46 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
47 {"GL_APPLE_flush_buffer_range", APPLE_FLUSH_BUFFER_RANGE, 0 },
48 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
49 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
52 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
53 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
54 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
55 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
56 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
57 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
58 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
59 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
60 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
61 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
62 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
63 {"GL_ARB_imaging", ARB_IMAGING, 0 },
64 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
65 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
66 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
67 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
68 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
69 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
70 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
71 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
72 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
73 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
74 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
75 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
76 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
77 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
78 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
79 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
80 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
81 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
82 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
83 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
84 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
85 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
86 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
87 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
90 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
91 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
92 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
93 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
94 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
97 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
98 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
99 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
100 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
101 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
102 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
103 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
104 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
105 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
106 {"GL_EXT_gpu_shader4", EXT_GPU_SHADER4, 0 },
107 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
108 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
109 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
110 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
111 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
112 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
113 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
114 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
115 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
116 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
117 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
118 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
119 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
120 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
121 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
122 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
123 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
124 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
125 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
126 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
129 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
130 {"GL_NV_fence", NV_FENCE, 0 },
131 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
132 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
133 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
134 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
135 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
136 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
137 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
138 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
139 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
140 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
141 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
142 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
143 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
144 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
145 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
146 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
147 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
148 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
151 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
154 /**********************************************************
155 * Utility functions follow
156 **********************************************************/
158 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
160 const struct min_lookup minMipLookup[] =
162 /* NONE POINT LINEAR */
163 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
164 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
165 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
168 const struct min_lookup minMipLookup_noFilter[] =
170 /* NONE POINT LINEAR */
171 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
172 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
173 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
176 const struct min_lookup minMipLookup_noMip[] =
178 /* NONE POINT LINEAR */
179 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
180 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
181 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
184 const GLenum magLookup[] =
186 /* NONE POINT LINEAR */
187 GL_NEAREST, GL_NEAREST, GL_LINEAR,
190 const GLenum magLookup_noFilter[] =
192 /* NONE POINT LINEAR */
193 GL_NEAREST, GL_NEAREST, GL_NEAREST,
196 /* drawStridedSlow attributes */
197 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
198 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
199 glAttribFunc specular_func_3ubv;
200 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
201 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
202 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
205 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
206 * i.e., there is no GL Context - Get a default rendering context to enable the
207 * function query some info from GL.
210 struct wined3d_fake_gl_ctx
216 HGLRC restore_gl_ctx;
219 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
221 TRACE_(d3d_caps)("Destroying fake GL context.\n");
223 if (!pwglMakeCurrent(NULL, NULL))
225 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
228 if (!pwglDeleteContext(ctx->gl_ctx))
230 DWORD err = GetLastError();
231 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
234 ReleaseDC(ctx->wnd, ctx->dc);
235 DestroyWindow(ctx->wnd);
237 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
239 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
243 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
245 PIXELFORMATDESCRIPTOR pfd;
248 TRACE("getting context...\n");
250 ctx->restore_dc = pwglGetCurrentDC();
251 ctx->restore_gl_ctx = pwglGetCurrentContext();
253 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
254 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
255 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
258 ERR_(d3d_caps)("Failed to create a window.\n");
262 ctx->dc = GetDC(ctx->wnd);
265 ERR_(d3d_caps)("Failed to get a DC.\n");
269 /* PixelFormat selection */
270 ZeroMemory(&pfd, sizeof(pfd));
271 pfd.nSize = sizeof(pfd);
273 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
274 pfd.iPixelType = PFD_TYPE_RGBA;
276 pfd.iLayerType = PFD_MAIN_PLANE;
278 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
281 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
282 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
285 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
286 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
288 /* Create a GL context. */
289 ctx->gl_ctx = pwglCreateContext(ctx->dc);
292 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
296 /* Make it the current GL context. */
297 if (!context_set_current(NULL))
299 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
302 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
304 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
311 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
313 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
315 if (ctx->wnd) DestroyWindow(ctx->wnd);
317 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
319 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
325 /* Adjust the amount of used texture memory */
326 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram)
328 struct wined3d_adapter *adapter = D3DDevice->adapter;
330 adapter->UsedTextureRam += glram;
331 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
332 return adapter->UsedTextureRam;
335 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
337 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
338 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
341 /**********************************************************
342 * IUnknown parts follows
343 **********************************************************/
345 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
349 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
350 if (IsEqualGUID(riid, &IID_IUnknown)
351 || IsEqualGUID(riid, &IID_IWineD3DBase)
352 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
353 IUnknown_AddRef(iface);
358 return E_NOINTERFACE;
361 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
362 IWineD3DImpl *This = (IWineD3DImpl *)iface;
363 ULONG refCount = InterlockedIncrement(&This->ref);
365 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
369 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
370 IWineD3DImpl *This = (IWineD3DImpl *)iface;
372 TRACE("(%p) : Releasing from %d\n", This, This->ref);
373 ref = InterlockedDecrement(&This->ref);
377 for (i = 0; i < This->adapter_count; ++i)
379 wined3d_adapter_cleanup(&This->adapters[i]);
381 HeapFree(GetProcessHeap(), 0, This);
387 /**********************************************************
388 * IWineD3D parts follows
389 **********************************************************/
391 /* GL locking is done by the caller */
392 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
396 const char *testcode =
398 "PARAM C[66] = { program.env[0..65] };\n"
400 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
401 "ARL A0.x, zero.x;\n"
402 "MOV result.position, C[A0.x + 65];\n"
406 GL_EXTCALL(glGenProgramsARB(1, &prog));
408 ERR("Failed to create an ARB offset limit test program\n");
410 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
411 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
412 strlen(testcode), testcode));
413 if(glGetError() != 0) {
414 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
415 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
417 } else TRACE("OpenGL implementation allows offsets > 63\n");
419 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
420 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
421 checkGLcall("ARB vp offset limit test cleanup");
426 static DWORD ver_for_ext(GL_SupportedExt ext)
429 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
430 if(EXTENSION_MAP[i].extension == ext) {
431 return EXTENSION_MAP[i].version;
437 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
438 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
440 if (vendor != VENDOR_ATI) return FALSE;
441 if (device == CARD_ATI_RADEON_9500) return TRUE;
442 if (device == CARD_ATI_RADEON_X700) return TRUE;
443 if (device == CARD_ATI_RADEON_X1600) return TRUE;
447 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
448 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
450 if (vendor == VENDOR_NVIDIA)
452 if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600)
460 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
461 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
463 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
464 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
465 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
467 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
468 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
469 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
470 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
471 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
472 * the chance that other implementations support them is rather small since Win32 QuickTime uses
473 * DirectDraw, not OpenGL. */
474 if (gl_info->supported[APPLE_FENCE]
475 && gl_info->supported[APPLE_CLIENT_STORAGE]
476 && gl_info->supported[APPLE_FLUSH_RENDER]
477 && gl_info->supported[APPLE_YCBCR_422])
487 /* Context activation is done by the caller. */
488 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
490 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
491 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
492 * all the texture. This function detects this bug by its symptom and disables PBOs
495 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
496 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
497 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
498 * read back is compared to the original. If they are equal PBOs are assumed to work,
499 * otherwise the PBO extension is disabled. */
501 static const unsigned int pattern[] =
503 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
504 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
505 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
506 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
508 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
510 /* No PBO -> No point in testing them. */
511 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
515 while (glGetError());
516 glGenTextures(1, &texture);
517 glBindTexture(GL_TEXTURE_2D, texture);
519 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
520 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
521 checkGLcall("Specifying the PBO test texture");
523 GL_EXTCALL(glGenBuffersARB(1, &pbo));
524 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
525 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
526 checkGLcall("Specifying the PBO test pbo");
528 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
529 checkGLcall("Loading the PBO test texture");
531 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
532 wglFinish(); /* just to be sure */
534 memset(check, 0, sizeof(check));
535 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
536 checkGLcall("Reading back the PBO test texture");
538 glDeleteTextures(1, &texture);
539 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
540 checkGLcall("PBO test cleanup");
544 if (memcmp(check, pattern, sizeof(check)))
546 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
547 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
548 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
552 TRACE_(d3d_caps)("PBO test successful.\n");
556 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
557 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
559 return vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer, vendor, device);
562 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
563 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
565 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
566 if (vendor != VENDOR_ATI) return FALSE;
567 if (device == CARD_ATI_RADEON_X1600) return FALSE;
571 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
572 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
574 if (vendor != VENDOR_ATI) return FALSE;
575 if (match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
576 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
580 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
581 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
583 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
584 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
585 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
586 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
589 * dx10 cards usually have 64 varyings */
590 return gl_info->limits.glsl_varyings > 44;
593 /* A GL context is provided by the caller */
594 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
595 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
600 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
604 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
605 error = glGetError();
608 if(error == GL_NO_ERROR)
610 TRACE("GL Implementation accepts 4 component specular color pointers\n");
615 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
616 debug_glerror(error));
621 static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
622 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
624 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
625 return gl_info->supported[NV_TEXTURE_SHADER];
628 /* A GL context is provided by the caller */
629 static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
630 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
635 const char *testcode =
637 "OPTION NV_vertex_program2;\n"
638 "MOV result.clip[0], 0.0;\n"
639 "MOV result.position, 0.0;\n"
642 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
647 GL_EXTCALL(glGenProgramsARB(1, &prog));
650 ERR("Failed to create the NVvp clip test program\n");
654 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
655 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
656 strlen(testcode), testcode));
657 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
660 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
661 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
665 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
667 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
668 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
669 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
675 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
677 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
678 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
679 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
680 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
683 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
685 quirk_arb_constants(gl_info);
686 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
687 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
688 * allow 48 different offsets or other helper immediate values. */
689 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
690 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
693 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
694 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
695 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
696 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
697 * most games, but avoids the crash
699 * A more sophisticated way would be to find all units that need texture coordinates and enable
700 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
701 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
703 * Note that disabling the extension entirely does not gain predictability because there is no point
704 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
705 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
707 if (gl_info->supported[ARB_POINT_SPRITE])
709 TRACE("Limiting point sprites to one texture unit.\n");
710 gl_info->limits.point_sprite_units = 1;
714 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
716 quirk_arb_constants(gl_info);
718 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
719 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
720 * If real NP2 textures are used, the driver falls back to software. We could just remove the
721 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
722 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
723 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
724 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
726 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
727 * has this extension promoted to core. The extension loading code sets this extension supported
728 * due to that, so this code works on fglrx as well. */
729 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
731 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
732 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
733 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
736 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
737 * it is generally more efficient. Reserve just 8 constants. */
738 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
739 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
742 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
744 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
745 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
746 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
747 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
748 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
749 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
751 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
752 * triggering the software fallback. There is not much we can do here apart from disabling the
753 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
754 * in IWineD3DImpl_FillGLCaps).
755 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
756 * post-processing effects in the game "Max Payne 2").
757 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
758 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
759 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
760 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
763 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
765 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
766 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
767 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
768 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
769 * according to the spec.
771 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
772 * makes the shader slower and eats instruction slots which should be available to the d3d app.
774 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
775 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
776 * this workaround is activated on cards that do not need it, it won't break things, just affect
777 * performance negatively. */
778 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
779 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
782 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
784 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
787 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
789 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
792 static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
794 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
795 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
796 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
799 static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
801 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
806 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
807 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device);
808 void (*apply)(struct wined3d_gl_info *gl_info);
809 const char *description;
812 static const struct driver_quirk quirk_table[] =
815 match_ati_r300_to_500,
817 "ATI GLSL constant and normalized texrect quirk"
819 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
820 * used it falls back to software. While the compiler can detect if the shader uses all declared
821 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
822 * using relative addressing falls back to software.
824 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
827 quirk_apple_glsl_constants,
828 "Apple GLSL uniform override"
833 "Geforce 5 NP2 disable"
838 "Init texcoord .w for Apple Intel GPU driver"
841 match_apple_nonr500ati,
843 "Init texcoord .w for Apple ATI >= r600 GPU driver"
847 quirk_one_point_sprite,
848 "Fglrx point sprite crash workaround"
853 "Reserved varying for gl_ClipPos"
856 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
857 * GL implementations accept it. The Mac GL is the only implementation known to
860 * If we can pass 4 component specular colors, do it, because (a) we don't have
861 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
862 * passes specular alpha to the pixel shader if any is used. Otherwise the
863 * specular alpha is used to pass the fog coordinate, which we pass to opengl
864 * via GL_EXT_fog_coord.
866 match_allows_spec_alpha,
867 quirk_allows_specular_alpha,
868 "Allow specular alpha quirk"
871 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
876 "Apple NV_texture_shader disable"
879 match_broken_nv_clip,
880 quirk_disable_nvvp_clip,
881 "Apple NV_vertex_program clip bug quirk"
885 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
886 * reporting a driver version is moot because we are not the Windows driver, and we have different
887 * bugs, features, etc.
889 * The driver version has the form "x.y.z.w".
891 * "x" is the Windows version the driver is meant for:
898 * "y" is the Direct3D level the driver supports:
905 * "z" is unknown, possibly vendor specific.
907 * "w" is the vendor specific driver version.
909 struct driver_version_information
911 WORD vendor; /* reported PCI card vendor ID */
912 WORD card; /* reported PCI card device ID */
913 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
914 WORD d3d_level; /* driver hiword to report */
915 WORD lopart_hi, lopart_lo; /* driver loword to report */
918 static const struct driver_version_information driver_version_table[] =
920 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
921 * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown
922 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
923 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
925 * All version numbers used below are from the Linux nvidia drivers. */
926 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 1, 8, 6 },
927 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 1, 8, 6 },
928 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 1, 8, 6 },
929 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 6, 4, 3 },
930 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 1, 8, 6 },
931 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 6, 10, 9371 },
932 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 6, 10, 9371 },
933 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 6, 10, 9371 },
934 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 15, 11, 7516 },
935 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 15, 11, 7516 },
936 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 15, 11, 7516 },
937 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 15, 11, 8618 },
938 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 15, 11, 8618 },
939 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 15, 11, 8618 },
940 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 15, 11, 8585 },
941 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 15, 11, 8585 },
942 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 15, 11, 8618 },
943 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 15, 11, 8618 },
944 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 15, 11, 8618 },
945 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 15, 11, 8618 },
946 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 15, 11, 8585 },
947 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 15, 11, 8618 },
948 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 15, 11, 8618 },
949 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 15, 11, 8618 },
950 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 15, 11, 8618 },
951 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 15, 11, 8618 },
952 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 15, 11, 8618 },
953 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 15, 11, 8618 },
954 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 15, 11, 8618 },
955 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 15, 11, 8618 },
956 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GT240, "NVIDIA GeForce GT 240", 15, 11, 8618 },
958 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
959 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 14, 10, 6764 },
960 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 14, 10, 6764 },
961 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 14, 10, 6764 },
962 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 14, 10, 6764 },
963 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 14, 10, 6764 },
964 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 14, 10, 6764 },
965 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 14, 10, 6764 },
966 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 14, 10, 6764 },
967 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 14, 10, 6764 },
968 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 14, 10, 6764 },
969 {VENDOR_ATI, CARD_ATI_RADEON_HD5700, "ATI Radeon HD 5700 Series", 14, 10, 8681 },
970 {VENDOR_ATI, CARD_ATI_RADEON_HD5800, "ATI Radeon HD 5800 Series", 14, 10, 8681 },
972 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
975 static void init_driver_info(struct wined3d_driver_info *driver_info,
976 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
978 OSVERSIONINFOW os_version;
979 WORD driver_os_version;
982 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
984 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
985 vendor = wined3d_settings.pci_vendor_id;
987 driver_info->vendor = vendor;
989 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
991 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
992 device = wined3d_settings.pci_device_id;
994 driver_info->device = device;
999 driver_info->name = "ati2dvag.dll";
1003 driver_info->name = "nv4_disp.dll";
1007 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1008 driver_info->name = "Display";
1012 memset(&os_version, 0, sizeof(os_version));
1013 os_version.dwOSVersionInfoSize = sizeof(os_version);
1014 if (!GetVersionExW(&os_version))
1016 ERR("Failed to get OS version, reporting 2000/XP.\n");
1017 driver_os_version = 6;
1021 TRACE("OS version %u.%u.\n", os_version.dwMajorVersion, os_version.dwMinorVersion);
1022 switch (os_version.dwMajorVersion)
1025 driver_os_version = 4;
1029 driver_os_version = 6;
1033 if (os_version.dwMinorVersion == 0)
1035 driver_os_version = 7;
1039 if (os_version.dwMinorVersion > 1)
1041 FIXME("Unhandled OS version %u.%u, reporting Win 7.\n",
1042 os_version.dwMajorVersion, os_version.dwMinorVersion);
1044 driver_os_version = 8;
1049 FIXME("Unhandled OS version %u.%u, reporting 2000/XP.\n",
1050 os_version.dwMajorVersion, os_version.dwMinorVersion);
1051 driver_os_version = 6;
1056 driver_info->description = "Direct3D HAL";
1057 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, 15);
1058 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1060 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1062 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1064 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1066 driver_info->description = driver_version_table[i].description;
1067 driver_info->version_high = MAKEDWORD_VERSION(driver_os_version, driver_version_table[i].d3d_level);
1068 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1069 driver_version_table[i].lopart_lo);
1074 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1075 driver_info->version_high, driver_info->version_low);
1078 /* Context activation is done by the caller. */
1079 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1080 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1084 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1086 if (!quirk_table[i].match(gl_info, gl_renderer, vendor, device)) continue;
1087 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1088 quirk_table[i].apply(gl_info);
1091 /* Find out if PBOs work as they are supposed to. */
1092 test_pbo_functionality(gl_info);
1095 static DWORD wined3d_parse_gl_version(const char *gl_version)
1097 const char *ptr = gl_version;
1101 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1103 while (isdigit(*ptr)) ++ptr;
1104 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1108 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1110 return MAKEDWORD_VERSION(major, minor);
1113 static enum wined3d_pci_vendor wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer)
1115 if (strstr(gl_vendor, "NVIDIA"))
1116 return VENDOR_NVIDIA;
1118 if (strstr(gl_vendor, "ATI"))
1121 if (strstr(gl_vendor, "Intel(R)")
1122 || strstr(gl_renderer, "Intel(R)")
1123 || strstr(gl_vendor, "Intel Inc."))
1124 return VENDOR_INTEL;
1126 if (strstr(gl_vendor, "Mesa")
1127 || strstr(gl_vendor, "DRI R300 Project")
1128 || strstr(gl_vendor, "Tungsten Graphics, Inc")
1129 || strstr(gl_vendor, "VMware, Inc."))
1132 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor));
1137 static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1138 enum wined3d_pci_vendor *vendor, unsigned int *vidmem)
1140 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1141 * different GPUs with roughly the same features. In most cases GPUs from a
1142 * certain family differ in clockspeeds, the amount of video memory and the
1143 * number of shader pipelines.
1145 * A Direct3D device object contains the PCI id (vendor + device) of the
1146 * videocard which is used for rendering. Various applications use this
1147 * information to get a rough estimation of the features of the card and
1148 * some might use it for enabling 3d effects only on certain types of
1149 * videocards. In some cases games might even use it to work around bugs
1150 * which happen on certain videocards/driver combinations. The problem is
1151 * that OpenGL only exposes a rendering string containing the name of the
1152 * videocard and not the PCI id.
1154 * Various games depend on the PCI id, so somehow we need to provide one.
1155 * A simple option is to parse the renderer string and translate this to
1156 * the right PCI id. This is a lot of work because there are more than 200
1157 * GPUs just for Nvidia. Various cards share the same renderer string, so
1158 * the amount of code might be 'small' but there are quite a number of
1159 * exceptions which would make this a pain to maintain. Another way would
1160 * be to query the PCI id from the operating system (assuming this is the
1161 * videocard which is used for rendering which is not always the case).
1162 * This would work but it is not very portable. Second it would not work
1163 * well in, let's say, a remote X situation in which the amount of 3d
1164 * features which can be used is limited.
1166 * As said most games only use the PCI id to get an indication of the
1167 * capabilities of the card. It doesn't really matter if the given id is
1168 * the correct one if we return the id of a card with similar 3d features.
1170 * The code below checks the OpenGL capabilities of a videocard and matches
1171 * that to a certain level of Direct3D functionality. Once a card passes
1172 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1173 * least a GeforceFX. To give a better estimate we do a basic check on the
1174 * renderer string but if that won't pass we return a default card. This
1175 * way is better than maintaining a full card database as even without a
1176 * full database we can return a card with similar features. Second the
1177 * size of the database can be made quite small because when you know what
1178 * type of 3d functionality a card has, you know to which GPU family the
1179 * GPU must belong. Because of this you only have to check a small part of
1180 * the renderer string to distinguishes between different models from that
1183 * The code also selects a default amount of video memory which we will
1184 * use for an estimation of the amount of free texture memory. In case of
1185 * real D3D the amount of texture memory includes video memory and system
1186 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1187 * HyperMemory). We don't know how much system memory can be addressed by
1188 * the system but we can make a reasonable estimation about the amount of
1189 * video memory. If the value is slightly wrong it doesn't matter as we
1190 * didn't include AGP-like memory which makes the amount of addressable
1191 * memory higher and second OpenGL isn't that critical it moves to system
1192 * memory behind our backs if really needed. Note that the amount of video
1193 * memory can be overruled using a registry setting. */
1198 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1199 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1201 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1203 /* Geforce 200 - highend */
1204 if (strstr(gl_renderer, "GTX 280")
1205 || strstr(gl_renderer, "GTX 285")
1206 || strstr(gl_renderer, "GTX 295"))
1209 return CARD_NVIDIA_GEFORCE_GTX280;
1212 /* Geforce 200 - midend high */
1213 if (strstr(gl_renderer, "GTX 275"))
1216 return CARD_NVIDIA_GEFORCE_GTX275;
1219 /* Geforce 200 - midend */
1220 if (strstr(gl_renderer, "GTX 260"))
1223 return CARD_NVIDIA_GEFORCE_GTX260;
1225 /* Geforce 200 - midend */
1226 if (strstr(gl_renderer, "GT 240"))
1229 return CARD_NVIDIA_GEFORCE_GT240;
1232 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1233 if (strstr(gl_renderer, "9800")
1234 || strstr(gl_renderer, "GTS 150")
1235 || strstr(gl_renderer, "GTS 250"))
1238 return CARD_NVIDIA_GEFORCE_9800GT;
1241 /* Geforce9 - midend */
1242 if (strstr(gl_renderer, "9600"))
1244 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1245 return CARD_NVIDIA_GEFORCE_9600GT;
1248 /* Geforce9 - midend low / Geforce 200 - low */
1249 if (strstr(gl_renderer, "9500")
1250 || strstr(gl_renderer, "GT 120")
1251 || strstr(gl_renderer, "GT 130"))
1253 *vidmem = 256; /* The 9500GT has 256-1024MB */
1254 return CARD_NVIDIA_GEFORCE_9500GT;
1257 /* Geforce9 - lowend */
1258 if (strstr(gl_renderer, "9400"))
1260 *vidmem = 256; /* The 9400GT has 256-1024MB */
1261 return CARD_NVIDIA_GEFORCE_9400GT;
1264 /* Geforce9 - lowend low */
1265 if (strstr(gl_renderer, "9100")
1266 || strstr(gl_renderer, "9200")
1267 || strstr(gl_renderer, "9300")
1268 || strstr(gl_renderer, "G 100"))
1270 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1271 return CARD_NVIDIA_GEFORCE_9200;
1274 /* Geforce8 - highend */
1275 if (strstr(gl_renderer, "8800"))
1277 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1278 return CARD_NVIDIA_GEFORCE_8800GTS;
1281 /* Geforce8 - midend mobile */
1282 if (strstr(gl_renderer, "8600 M"))
1285 return CARD_NVIDIA_GEFORCE_8600MGT;
1288 /* Geforce8 - midend */
1289 if (strstr(gl_renderer, "8600")
1290 || strstr(gl_renderer, "8700"))
1293 return CARD_NVIDIA_GEFORCE_8600GT;
1296 /* Geforce8 - lowend */
1297 if (strstr(gl_renderer, "8100")
1298 || strstr(gl_renderer, "8200")
1299 || strstr(gl_renderer, "8300")
1300 || strstr(gl_renderer, "8400")
1301 || strstr(gl_renderer, "8500"))
1303 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1304 return CARD_NVIDIA_GEFORCE_8300GS;
1307 /* Geforce7 - highend */
1308 if (strstr(gl_renderer, "7800")
1309 || strstr(gl_renderer, "7900")
1310 || strstr(gl_renderer, "7950")
1311 || strstr(gl_renderer, "Quadro FX 4")
1312 || strstr(gl_renderer, "Quadro FX 5"))
1314 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1315 return CARD_NVIDIA_GEFORCE_7800GT;
1318 /* Geforce7 midend */
1319 if (strstr(gl_renderer, "7600")
1320 || strstr(gl_renderer, "7700"))
1322 *vidmem = 256; /* The 7600 uses 256-512MB */
1323 return CARD_NVIDIA_GEFORCE_7600;
1326 /* Geforce7 lower medium */
1327 if (strstr(gl_renderer, "7400"))
1329 *vidmem = 256; /* The 7400 uses 256-512MB */
1330 return CARD_NVIDIA_GEFORCE_7400;
1333 /* Geforce7 lowend */
1334 if (strstr(gl_renderer, "7300"))
1336 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1337 return CARD_NVIDIA_GEFORCE_7300;
1340 /* Geforce6 highend */
1341 if (strstr(gl_renderer, "6800"))
1343 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1344 return CARD_NVIDIA_GEFORCE_6800;
1347 /* Geforce6 - midend */
1348 if (strstr(gl_renderer, "6600")
1349 || strstr(gl_renderer, "6610")
1350 || strstr(gl_renderer, "6700"))
1352 *vidmem = 128; /* A 6600GT has 128-256MB */
1353 return CARD_NVIDIA_GEFORCE_6600GT;
1356 /* Geforce6/7 lowend */
1358 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1361 if (WINE_D3D9_CAPABLE(gl_info))
1363 /* GeforceFX - highend */
1364 if (strstr(gl_renderer, "5800")
1365 || strstr(gl_renderer, "5900")
1366 || strstr(gl_renderer, "5950")
1367 || strstr(gl_renderer, "Quadro FX"))
1369 *vidmem = 256; /* 5800-5900 cards use 256MB */
1370 return CARD_NVIDIA_GEFORCEFX_5800;
1373 /* GeforceFX - midend */
1374 if (strstr(gl_renderer, "5600")
1375 || strstr(gl_renderer, "5650")
1376 || strstr(gl_renderer, "5700")
1377 || strstr(gl_renderer, "5750"))
1379 *vidmem = 128; /* A 5600 uses 128-256MB */
1380 return CARD_NVIDIA_GEFORCEFX_5600;
1383 /* GeforceFX - lowend */
1384 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1385 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1388 if (WINE_D3D8_CAPABLE(gl_info))
1390 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1392 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1393 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1396 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1397 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1400 if (WINE_D3D7_CAPABLE(gl_info))
1402 if (strstr(gl_renderer, "GeForce4 MX"))
1404 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1405 * early models had 32MB but most have 64MB or even 128MB. */
1407 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1410 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1412 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1413 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1416 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1418 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1419 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1422 /* Most Geforce1 cards have 32MB, there are also some rare 16
1423 * and 64MB (Dell) models. */
1425 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1428 if (strstr(gl_renderer, "TNT2"))
1430 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1431 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1434 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1435 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1438 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1440 * Beware: renderer string do not match exact card model,
1441 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1442 if (WINE_D3D9_CAPABLE(gl_info))
1444 /* Radeon EG CYPRESS XT / PRO HD5800 - highend */
1445 if (strstr(gl_renderer, "HD 5800") /* Radeon EG CYPRESS HD58xx generic renderer string */
1446 || strstr(gl_renderer, "HD 5850") /* Radeon EG CYPRESS XT */
1447 || strstr(gl_renderer, "HD 5870")) /* Radeon EG CYPRESS PRO */
1449 *vidmem = 1024; /* note: HD58xx cards use 1024MB */
1450 return CARD_ATI_RADEON_HD5800;
1453 /* Radeon EG JUNIPER XT / LE HD5700 - midend */
1454 if (strstr(gl_renderer, "HD 5700") /* Radeon EG JUNIPER HD57xx generic renderer string */
1455 || strstr(gl_renderer, "HD 5750") /* Radeon EG JUNIPER LE */
1456 || strstr(gl_renderer, "HD 5770")) /* Radeon EG JUNIPER XT */
1458 *vidmem = 512; /* note: HD5770 cards use 1024MB and HD5750 cards use 512MB or 1024MB */
1459 return CARD_ATI_RADEON_HD5700;
1462 /* Radeon R7xx HD4800 - highend */
1463 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1464 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1465 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1466 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1467 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1469 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1470 return CARD_ATI_RADEON_HD4800;
1473 /* Radeon R740 HD4700 - midend */
1474 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1475 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1478 return CARD_ATI_RADEON_HD4700;
1481 /* Radeon R730 HD4600 - midend */
1482 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1483 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1484 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1487 return CARD_ATI_RADEON_HD4600;
1490 /* Radeon R710 HD4500/HD4350 - lowend */
1491 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1492 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1495 return CARD_ATI_RADEON_HD4350;
1498 /* Radeon R6xx HD2900/HD3800 - highend */
1499 if (strstr(gl_renderer, "HD 2900")
1500 || strstr(gl_renderer, "HD 3870")
1501 || strstr(gl_renderer, "HD 3850"))
1503 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1504 return CARD_ATI_RADEON_HD2900;
1507 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1508 if (strstr(gl_renderer, "HD 2600")
1509 || strstr(gl_renderer, "HD 3830")
1510 || strstr(gl_renderer, "HD 3690")
1511 || strstr(gl_renderer, "HD 3650"))
1513 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1514 return CARD_ATI_RADEON_HD2600;
1517 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1518 if (strstr(gl_renderer, "HD 2300")
1519 || strstr(gl_renderer, "HD 2400")
1520 || strstr(gl_renderer, "HD 3470")
1521 || strstr(gl_renderer, "HD 3450")
1522 || strstr(gl_renderer, "HD 3430")
1523 || strstr(gl_renderer, "HD 3400"))
1525 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1526 return CARD_ATI_RADEON_HD2300;
1529 /* Radeon R6xx/R7xx integrated */
1530 if (strstr(gl_renderer, "HD 3100")
1531 || strstr(gl_renderer, "HD 3200")
1532 || strstr(gl_renderer, "HD 3300"))
1534 *vidmem = 128; /* 128MB */
1535 return CARD_ATI_RADEON_HD3200;
1539 if (strstr(gl_renderer, "X1600")
1540 || strstr(gl_renderer, "X1650")
1541 || strstr(gl_renderer, "X1800")
1542 || strstr(gl_renderer, "X1900")
1543 || strstr(gl_renderer, "X1950"))
1545 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1546 return CARD_ATI_RADEON_X1600;
1549 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1550 if (strstr(gl_renderer, "X700")
1551 || strstr(gl_renderer, "X800")
1552 || strstr(gl_renderer, "X850")
1553 || strstr(gl_renderer, "X1300")
1554 || strstr(gl_renderer, "X1400")
1555 || strstr(gl_renderer, "X1450")
1556 || strstr(gl_renderer, "X1550"))
1558 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1559 return CARD_ATI_RADEON_X700;
1562 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1563 if (strstr(gl_renderer, "Radeon Xpress"))
1565 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1566 return CARD_ATI_RADEON_XPRESS_200M;
1570 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1571 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1574 if (WINE_D3D8_CAPABLE(gl_info))
1576 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1577 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1580 if (WINE_D3D7_CAPABLE(gl_info))
1582 *vidmem = 32; /* There are models with up to 64MB */
1583 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1586 *vidmem = 16; /* There are 16-32MB models */
1587 return CARD_ATI_RAGE_128PRO;
1590 if (strstr(gl_renderer, "X3100"))
1592 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1594 return CARD_INTEL_X3100;
1597 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1599 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1601 return CARD_INTEL_I945GM;
1604 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1605 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1606 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1607 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1608 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1609 return CARD_INTEL_I915G;
1614 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1615 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1616 * them a good generic choice. */
1617 *vendor = VENDOR_NVIDIA;
1618 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1619 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1620 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1621 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1622 return CARD_NVIDIA_RIVA_128;
1626 /* Context activation is done by the caller. */
1627 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_driver_info *driver_info, struct wined3d_gl_info *gl_info)
1629 const char *GL_Extensions = NULL;
1630 const char *WGL_Extensions = NULL;
1631 const char *gl_string = NULL;
1632 enum wined3d_pci_vendor vendor;
1633 enum wined3d_pci_device device;
1635 GLfloat gl_floatv[2];
1638 unsigned int vidmem=0;
1643 TRACE_(d3d_caps)("(%p)\n", gl_info);
1647 gl_string = (const char *)glGetString(GL_RENDERER);
1648 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string));
1652 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
1656 len = strlen(gl_string) + 1;
1657 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
1661 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
1664 memcpy(gl_renderer, gl_string, len);
1666 gl_string = (const char *)glGetString(GL_VENDOR);
1667 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string));
1671 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
1672 HeapFree(GetProcessHeap(), 0, gl_renderer);
1675 vendor = wined3d_guess_vendor(gl_string, gl_renderer);
1676 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), vendor);
1678 /* Parse the GL_VERSION field into major and minor information */
1679 gl_string = (const char *)glGetString(GL_VERSION);
1680 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string));
1684 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1685 HeapFree(GetProcessHeap(), 0, gl_renderer);
1688 gl_version = wined3d_parse_gl_version(gl_string);
1691 * Initialize openGL extension related variables
1692 * with Default values
1694 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1695 gl_info->limits.buffers = 1;
1696 gl_info->limits.textures = 1;
1697 gl_info->limits.texture_stages = 1;
1698 gl_info->limits.fragment_samplers = 1;
1699 gl_info->limits.vertex_samplers = 0;
1700 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
1701 gl_info->limits.sampler_stages = 1;
1702 gl_info->limits.glsl_vs_float_constants = 0;
1703 gl_info->limits.glsl_ps_float_constants = 0;
1704 gl_info->limits.arb_vs_float_constants = 0;
1705 gl_info->limits.arb_vs_native_constants = 0;
1706 gl_info->limits.arb_vs_instructions = 0;
1707 gl_info->limits.arb_vs_temps = 0;
1708 gl_info->limits.arb_ps_float_constants = 0;
1709 gl_info->limits.arb_ps_local_constants = 0;
1710 gl_info->limits.arb_ps_instructions = 0;
1711 gl_info->limits.arb_ps_temps = 0;
1713 /* Retrieve opengl defaults */
1714 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1715 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1716 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1718 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1719 gl_info->limits.lights = gl_max;
1720 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1722 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1723 gl_info->limits.texture_size = gl_max;
1724 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1726 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1727 gl_info->limits.pointsize_min = gl_floatv[0];
1728 gl_info->limits.pointsize_max = gl_floatv[1];
1729 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1731 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1732 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1736 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1737 HeapFree(GetProcessHeap(), 0, gl_renderer);
1743 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1745 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1747 while (*GL_Extensions)
1750 char current_ext[256];
1752 while (isspace(*GL_Extensions)) ++GL_Extensions;
1753 start = GL_Extensions;
1754 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1756 len = GL_Extensions - start;
1757 if (!len || len >= sizeof(current_ext)) continue;
1759 memcpy(current_ext, start, len);
1760 current_ext[len] = '\0';
1761 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
1763 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1765 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1767 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1768 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1774 /* Now work out what GL support this card really has */
1775 #define USE_GL_FUNC(type, pfn, ext, replace) \
1777 DWORD ver = ver_for_ext(ext); \
1778 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1779 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1780 else gl_info->pfn = NULL; \
1785 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1791 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1792 * loading the functions, otherwise the code above will load the extension entry points instead of the
1793 * core functions, which may not work. */
1794 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1796 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1797 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1799 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1800 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1804 if (gl_info->supported[APPLE_FENCE])
1806 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1807 * The apple extension interacts with some other apple exts. Disable the NV
1808 * extension if the apple one is support to prevent confusion in other parts
1810 gl_info->supported[NV_FENCE] = FALSE;
1812 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1814 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1816 * The enums are the same:
1817 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1818 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1819 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1820 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1821 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1823 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1825 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1826 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1828 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1830 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1831 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1834 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1836 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1837 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1839 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
1841 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
1842 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
1844 if (gl_info->supported[NV_TEXTURE_SHADER2])
1846 if (gl_info->supported[NV_REGISTER_COMBINERS])
1848 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1849 * are supported. The nv extensions provide the same functionality as the
1850 * ATI one, and a bit more(signed pixelformats). */
1851 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1854 if (gl_info->supported[ARB_DRAW_BUFFERS])
1856 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1857 gl_info->limits.buffers = gl_max;
1858 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1860 if (gl_info->supported[ARB_MULTITEXTURE])
1862 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1863 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
1864 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
1866 if (gl_info->supported[NV_REGISTER_COMBINERS])
1869 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1870 gl_info->limits.texture_stages = min(MAX_TEXTURES, tmp);
1874 gl_info->limits.texture_stages = min(MAX_TEXTURES, gl_max);
1876 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->limits.texture_stages);
1878 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1881 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1882 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1886 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
1888 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
1890 if (gl_info->supported[ARB_VERTEX_SHADER])
1893 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1894 gl_info->limits.vertex_samplers = tmp;
1895 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1896 gl_info->limits.combined_samplers = tmp;
1898 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1899 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1900 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1901 * shader is used with fixed function vertex processing we're fine too because fixed function
1902 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1903 * used we have to make sure that all vertex sampler setups are valid together with all
1904 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1905 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1906 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1907 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1908 * a fixed function pipeline anymore.
1910 * So this is just a check to check that our assumption holds true. If not, write a warning
1911 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1912 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
1913 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
1915 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1916 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
1917 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1918 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
1919 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
1921 gl_info->limits.vertex_samplers = 0;
1926 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
1928 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
1929 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
1931 if (gl_info->supported[ARB_VERTEX_BLEND])
1933 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1934 gl_info->limits.blends = gl_max;
1935 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
1937 if (gl_info->supported[EXT_TEXTURE3D])
1939 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1940 gl_info->limits.texture3d_size = gl_max;
1941 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
1943 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1945 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1946 gl_info->limits.anisotropy = gl_max;
1947 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
1949 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1951 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1952 gl_info->limits.arb_ps_float_constants = gl_max;
1953 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
1954 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1955 gl_info->limits.arb_ps_native_constants = gl_max;
1956 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
1957 gl_info->limits.arb_ps_native_constants);
1958 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1959 gl_info->limits.arb_ps_temps = gl_max;
1960 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
1961 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1962 gl_info->limits.arb_ps_instructions = gl_max;
1963 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
1964 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
1965 gl_info->limits.arb_ps_local_constants = gl_max;
1966 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
1968 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1970 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1971 gl_info->limits.arb_vs_float_constants = gl_max;
1972 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
1973 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1974 gl_info->limits.arb_vs_native_constants = gl_max;
1975 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
1976 gl_info->limits.arb_vs_native_constants);
1977 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1978 gl_info->limits.arb_vs_temps = gl_max;
1979 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
1980 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1981 gl_info->limits.arb_vs_instructions = gl_max;
1982 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
1984 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1986 if (gl_info->supported[ARB_VERTEX_SHADER])
1988 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1989 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
1990 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
1992 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1994 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1995 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
1996 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
1997 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1998 gl_info->limits.glsl_varyings = gl_max;
1999 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
2001 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
2003 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
2007 gl_info->limits.shininess = 128.0f;
2009 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
2011 /* If we have full NP2 texture support, disable
2012 * GL_ARB_texture_rectangle because we will never use it.
2013 * This saves a few redundant glDisable calls. */
2014 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
2016 if (gl_info->supported[ATI_FRAGMENT_SHADER])
2018 /* Disable NV_register_combiners and fragment shader if this is supported.
2019 * generally the NV extensions are preferred over the ATI ones, and this
2020 * extension is disabled if register_combiners and texture_shader2 are both
2021 * supported. So we reach this place only if we have incomplete NV dxlevel 8
2022 * fragment processing support. */
2023 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
2024 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
2025 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
2026 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
2027 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
2029 if (gl_info->supported[NV_HALF_FLOAT])
2031 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
2032 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
2034 if (gl_info->supported[ARB_POINT_SPRITE])
2036 gl_info->limits.point_sprite_units = gl_info->limits.textures;
2040 gl_info->limits.point_sprite_units = 0;
2042 checkGLcall("extension detection");
2046 /* In some cases the number of texture stages can be larger than the number
2047 * of samplers. The GF4 for example can use only 2 samplers (no fragment
2048 * shaders), but 8 texture stages (register combiners). */
2049 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
2051 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
2053 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
2054 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
2055 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2056 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2057 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2058 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2059 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2060 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2061 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2062 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2063 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2064 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2065 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2066 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2067 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2068 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2069 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2070 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2071 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2075 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2077 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2078 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2079 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2080 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2081 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2082 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2083 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2084 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2085 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2086 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2087 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2088 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2089 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2090 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2091 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2092 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2093 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2095 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2097 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2098 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2100 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2102 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2104 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2106 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2110 /* MRTs are currently only supported when FBOs are used. */
2111 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2113 gl_info->limits.buffers = 1;
2116 device = wined3d_guess_card(gl_info, gl_renderer, &vendor, &vidmem);
2117 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", vendor, device);
2119 /* If we have an estimate use it, else default to 64MB; */
2121 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2123 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2125 gl_info->wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2126 gl_info->wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2127 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2128 gl_info->wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2129 gl_info->wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2130 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2131 gl_info->wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2132 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2134 /* Make sure there's an active HDC else the WGL extensions will fail */
2135 hdc = pwglGetCurrentDC();
2137 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2138 if(GL_EXTCALL(wglGetExtensionsStringARB))
2139 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2141 if (NULL == WGL_Extensions) {
2142 ERR(" WGL_Extensions returns NULL\n");
2144 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2145 while (*WGL_Extensions != 0x00) {
2149 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2150 Start = WGL_Extensions;
2151 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2155 len = WGL_Extensions - Start;
2156 if (len == 0 || len >= sizeof(ThisExtn))
2159 memcpy(ThisExtn, Start, len);
2160 ThisExtn[len] = '\0';
2161 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2163 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2164 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
2165 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2167 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2168 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2169 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2171 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2172 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2173 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2179 fixup_extensions(gl_info, gl_renderer, vendor, device);
2180 init_driver_info(driver_info, vendor, device);
2181 add_gl_compat_wrappers(gl_info);
2183 HeapFree(GetProcessHeap(), 0, gl_renderer);
2187 /**********************************************************
2188 * IWineD3D implementation follows
2189 **********************************************************/
2191 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2192 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2194 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2196 return This->adapter_count;
2199 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void *init_function)
2201 FIXME("iface %p, init_function %p stub!\n", iface, init_function);
2206 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2207 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2209 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2211 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2215 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2218 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2219 of the same bpp but different resolutions */
2221 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2222 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2223 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2224 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2226 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2230 /* TODO: Store modes per adapter and read it from the adapter structure */
2231 if (Adapter == 0) { /* Display */
2232 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2233 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2238 memset(&mode, 0, sizeof(mode));
2239 mode.dmSize = sizeof(mode);
2241 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2245 if (Format == WINED3DFMT_UNKNOWN)
2247 /* This is for D3D8, do not enumerate P8 here */
2248 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2250 else if (mode.dmBitsPerPel == format_bits)
2256 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2259 FIXME_(d3d_caps)("Adapter not primary display\n");
2264 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2265 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2266 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2267 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2269 /* Validate the parameters as much as possible */
2270 if (NULL == pMode ||
2271 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2272 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2273 return WINED3DERR_INVALIDCALL;
2276 /* TODO: Store modes per adapter and read it from the adapter structure */
2279 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(Format, &This->adapters[Adapter].gl_info);
2280 UINT format_bits = format_desc->byte_count * CHAR_BIT;
2286 ZeroMemory(&DevModeW, sizeof(DevModeW));
2287 DevModeW.dmSize = sizeof(DevModeW);
2289 /* If we are filtering to a specific format (D3D9), then need to skip
2290 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2291 just count through the ones with valid bit depths */
2292 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0))
2294 if (Format == WINED3DFMT_UNKNOWN)
2296 /* This is for D3D8, do not enumerate P8 here */
2297 if (DevModeW.dmBitsPerPel == 32 || DevModeW.dmBitsPerPel == 16) ++i;
2299 else if (DevModeW.dmBitsPerPel == format_bits)
2306 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2307 return WINED3DERR_INVALIDCALL;
2311 /* Now get the display mode via the calculated index */
2312 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2313 pMode->Width = DevModeW.dmPelsWidth;
2314 pMode->Height = DevModeW.dmPelsHeight;
2315 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2316 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2317 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2319 if (Format == WINED3DFMT_UNKNOWN) {
2320 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2322 pMode->Format = Format;
2325 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2326 return WINED3DERR_INVALIDCALL;
2329 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2330 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2331 DevModeW.dmBitsPerPel);
2336 FIXME_(d3d_caps)("Adapter not primary display\n");
2342 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE *pMode)
2344 TRACE("iface %p, adapter_idx %u, display_mode %p.\n", iface, Adapter, pMode);
2346 if (NULL == pMode ||
2347 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2348 return WINED3DERR_INVALIDCALL;
2351 if (Adapter == 0) { /* Display */
2355 ZeroMemory(&DevModeW, sizeof(DevModeW));
2356 DevModeW.dmSize = sizeof(DevModeW);
2358 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2359 pMode->Width = DevModeW.dmPelsWidth;
2360 pMode->Height = DevModeW.dmPelsHeight;
2361 bpp = DevModeW.dmBitsPerPel;
2362 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2363 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2365 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2368 pMode->Format = pixelformat_for_depth(bpp);
2370 FIXME_(d3d_caps)("Adapter not primary display\n");
2373 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2374 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2378 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2379 and fields being inserted in the middle, a new structure is used in place */
2380 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2381 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2382 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2383 struct wined3d_adapter *adapter;
2386 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2388 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2389 return WINED3DERR_INVALIDCALL;
2392 adapter = &This->adapters[Adapter];
2394 /* Return the information requested */
2395 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2397 if (pIdentifier->driver_size)
2399 const char *name = adapter->driver_info.name;
2400 len = min(strlen(name), pIdentifier->driver_size - 1);
2401 memcpy(pIdentifier->driver, name, len);
2402 pIdentifier->driver[len] = '\0';
2405 if (pIdentifier->description_size)
2407 const char *description = adapter->driver_info.description;
2408 len = min(strlen(description), pIdentifier->description_size - 1);
2409 memcpy(pIdentifier->description, description, len);
2410 pIdentifier->description[len] = '\0';
2413 /* Note that d3d8 doesn't supply a device name. */
2414 if (pIdentifier->device_name_size)
2416 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2418 len = strlen(device_name);
2419 if (len >= pIdentifier->device_name_size)
2421 ERR("Device name size too small.\n");
2422 return WINED3DERR_INVALIDCALL;
2425 memcpy(pIdentifier->device_name, device_name, len);
2426 pIdentifier->device_name[len] = '\0';
2429 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2430 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2431 pIdentifier->vendor_id = adapter->driver_info.vendor;
2432 pIdentifier->device_id = adapter->driver_info.device;
2433 pIdentifier->subsystem_id = 0;
2434 pIdentifier->revision = 0;
2435 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2436 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2437 memcpy(&pIdentifier->adapter_luid, &adapter->luid, sizeof(pIdentifier->adapter_luid));
2438 pIdentifier->video_memory = adapter->TextureRam;
2443 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2444 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2446 short redSize, greenSize, blueSize, alphaSize, colorBits;
2451 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2452 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2454 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2458 if(cfg->redSize < redSize)
2461 if(cfg->greenSize < greenSize)
2464 if(cfg->blueSize < blueSize)
2467 if(cfg->alphaSize < alphaSize)
2471 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2472 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2473 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2474 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2475 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2476 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2477 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2478 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2479 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2480 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2481 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2482 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2483 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2485 /* Probably a color index mode */
2492 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2493 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2495 short depthSize, stencilSize;
2496 BOOL lockable = FALSE;
2501 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2503 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2507 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2510 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2511 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2512 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2513 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2516 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2517 * allow more stencil bits than requested. */
2518 if(cfg->stencilSize < stencilSize)
2524 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2525 WINED3DFORMAT AdapterFormat,
2526 WINED3DFORMAT RenderTargetFormat,
2527 WINED3DFORMAT DepthStencilFormat) {
2528 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2530 const WineD3D_PixelFormat *cfgs;
2531 const struct wined3d_adapter *adapter;
2532 const struct GlPixelFormatDesc *rt_format_desc;
2533 const struct GlPixelFormatDesc *ds_format_desc;
2536 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2538 DeviceType, debug_d3ddevicetype(DeviceType),
2539 AdapterFormat, debug_d3dformat(AdapterFormat),
2540 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2541 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2543 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2544 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2545 return WINED3DERR_INVALIDCALL;
2548 adapter = &This->adapters[Adapter];
2549 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2550 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2551 cfgs = adapter->cfgs;
2552 nCfgs = adapter->nCfgs;
2553 for (it = 0; it < nCfgs; ++it) {
2554 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2556 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2558 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2563 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2565 return WINED3DERR_NOTAVAILABLE;
2568 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2569 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2571 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2572 const struct GlPixelFormatDesc *glDesc;
2573 const struct wined3d_adapter *adapter;
2575 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2578 DeviceType, debug_d3ddevicetype(DeviceType),
2579 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2584 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2585 return WINED3DERR_INVALIDCALL;
2588 /* TODO: handle Windowed, add more quality levels */
2590 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2591 if(pQualityLevels) *pQualityLevels = 1;
2595 /* By default multisampling is disabled right now as it causes issues
2596 * on some Nvidia driver versions and it doesn't work well in combination
2598 if(!wined3d_settings.allow_multisampling)
2599 return WINED3DERR_NOTAVAILABLE;
2601 adapter = &This->adapters[Adapter];
2602 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2603 if (!glDesc) return WINED3DERR_INVALIDCALL;
2605 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2607 const WineD3D_PixelFormat *cfgs;
2609 cfgs = adapter->cfgs;
2610 nCfgs = adapter->nCfgs;
2611 for(i=0; i<nCfgs; i++) {
2612 if(cfgs[i].numSamples != MultiSampleType)
2615 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2618 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2621 *pQualityLevels = 1; /* Guess at a value! */
2625 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2626 short redSize, greenSize, blueSize, alphaSize, colorBits;
2628 const WineD3D_PixelFormat *cfgs;
2630 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2632 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2633 return WINED3DERR_NOTAVAILABLE;
2636 cfgs = adapter->cfgs;
2637 nCfgs = adapter->nCfgs;
2638 for(i=0; i<nCfgs; i++) {
2639 if(cfgs[i].numSamples != MultiSampleType)
2641 if(cfgs[i].redSize != redSize)
2643 if(cfgs[i].greenSize != greenSize)
2645 if(cfgs[i].blueSize != blueSize)
2647 if(cfgs[i].alphaSize != alphaSize)
2650 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2653 *pQualityLevels = 1; /* Guess at a value! */
2657 return WINED3DERR_NOTAVAILABLE;
2660 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2661 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed)
2663 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2666 TRACE("iface %p, adapter_idx %u, device_type %s, display_format %s, backbuffer_format %s, windowed %#x.\n",
2667 iface, Adapter, debug_d3ddevicetype(DeviceType), debug_d3dformat(DisplayFormat),
2668 debug_d3dformat(BackBufferFormat), Windowed);
2670 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2671 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2672 return WINED3DERR_INVALIDCALL;
2675 /* The task of this function is to check whether a certain display / backbuffer format
2676 * combination is available on the given adapter. In fullscreen mode microsoft specified
2677 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2678 * and display format should match exactly.
2679 * In windowed mode format conversion can occur and this depends on the driver. When format
2680 * conversion is done, this function should nevertheless fail and applications need to use
2681 * CheckDeviceFormatConversion.
2682 * At the moment we assume that fullscreen and windowed have the same capabilities */
2684 /* There are only 4 display formats */
2685 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
2686 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2687 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2688 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
2690 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2691 return WINED3DERR_NOTAVAILABLE;
2694 /* If the requested DisplayFormat is not available, don't continue */
2695 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2697 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2698 return WINED3DERR_NOTAVAILABLE;
2701 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2702 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2703 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2704 return WINED3DERR_NOTAVAILABLE;
2707 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2708 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
2710 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2711 return WINED3DERR_NOTAVAILABLE;
2714 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2715 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2716 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
2718 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2719 return WINED3DERR_NOTAVAILABLE;
2722 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2723 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2724 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
2726 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2727 return WINED3DERR_NOTAVAILABLE;
2730 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2731 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
2732 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
2734 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2735 return WINED3DERR_NOTAVAILABLE;
2738 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2739 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2741 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2747 /* Check if we support bumpmapping for a format */
2748 static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
2749 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2751 const struct fragment_pipeline *fp;
2753 switch(format_desc->format)
2755 case WINED3DFMT_R8G8_SNORM:
2756 case WINED3DFMT_R16G16_SNORM:
2757 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
2758 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
2759 case WINED3DFMT_R8G8B8A8_SNORM:
2760 /* Ask the fixed function pipeline implementation if it can deal
2761 * with the conversion. If we've got a GL extension giving native
2762 * support this will be an identity conversion. */
2763 fp = select_fragment_implementation(adapter, DeviceType);
2764 if (fp->color_fixup_supported(format_desc->color_fixup))
2766 TRACE_(d3d_caps)("[OK]\n");
2769 TRACE_(d3d_caps)("[FAILED]\n");
2773 TRACE_(d3d_caps)("[FAILED]\n");
2778 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2779 static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
2780 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2784 /* Only allow depth/stencil formats */
2785 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2787 /* Walk through all WGL pixel formats to find a match */
2788 for (it = 0; it < adapter->nCfgs; ++it)
2790 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2791 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2793 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2803 static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2805 /* The flags entry of a format contains the filtering capability */
2806 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2811 /* Check the render target capabilities of a format */
2812 static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
2813 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2815 /* Filter out non-RT formats */
2816 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2818 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2819 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2821 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2822 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2824 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2825 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2827 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2828 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2829 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2830 TRACE_(d3d_caps)("[FAILED]\n");
2834 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2835 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2836 for (it = 0; it < adapter->nCfgs; ++it)
2838 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2839 &cfgs[it], check_format_desc))
2841 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2842 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2846 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2847 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2848 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2851 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2852 for (it = 0; it < adapter->nCfgs; ++it)
2854 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2855 &cfgs[it], check_format_desc))
2857 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2858 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2862 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2863 /* For now return TRUE for FBOs until we have some proper checks.
2864 * Note that this function will only be called when the format is around for texturing. */
2870 static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2872 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2874 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2875 if (!gl_info->supported[EXT_TEXTURE_SRGB])
2877 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2881 switch (format_desc->format)
2883 case WINED3DFMT_B8G8R8A8_UNORM:
2884 case WINED3DFMT_B8G8R8X8_UNORM:
2885 case WINED3DFMT_B4G4R4A4_UNORM:
2886 case WINED3DFMT_L8_UNORM:
2887 case WINED3DFMT_L8A8_UNORM:
2888 case WINED3DFMT_DXT1:
2889 case WINED3DFMT_DXT2:
2890 case WINED3DFMT_DXT3:
2891 case WINED3DFMT_DXT4:
2892 case WINED3DFMT_DXT5:
2893 TRACE_(d3d_caps)("[OK]\n");
2897 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2903 static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
2904 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2906 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2907 * doing the color fixup in shaders.
2908 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2909 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
2911 int vs_selected_mode;
2912 int ps_selected_mode;
2913 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2915 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2916 TRACE_(d3d_caps)("[OK]\n");
2921 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2925 /* Check if a format support blending in combination with pixel shaders */
2926 static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
2927 const struct GlPixelFormatDesc *format_desc)
2929 /* The flags entry of a format contains the post pixel shader blending capability */
2930 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2935 static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2937 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2938 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2939 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2940 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2941 * capability anyway.
2943 * For now lets report this on all formats, but in the future we may want to
2944 * restrict it to some should games need that
2949 /* Check if a texture format is supported on the given adapter */
2950 static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
2951 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2953 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2954 const shader_backend_t *shader_backend;
2955 const struct fragment_pipeline *fp;
2957 switch (format_desc->format)
2960 * supported: RGB(A) formats
2962 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
2963 case WINED3DFMT_B8G8R8A8_UNORM:
2964 case WINED3DFMT_B8G8R8X8_UNORM:
2965 case WINED3DFMT_B5G6R5_UNORM:
2966 case WINED3DFMT_B5G5R5X1_UNORM:
2967 case WINED3DFMT_B5G5R5A1_UNORM:
2968 case WINED3DFMT_B4G4R4A4_UNORM:
2969 case WINED3DFMT_A8_UNORM:
2970 case WINED3DFMT_B4G4R4X4_UNORM:
2971 case WINED3DFMT_R8G8B8A8_UNORM:
2972 case WINED3DFMT_R8G8B8X8_UNORM:
2973 case WINED3DFMT_B10G10R10A2_UNORM:
2974 case WINED3DFMT_R10G10B10A2_UNORM:
2975 case WINED3DFMT_R16G16_UNORM:
2976 TRACE_(d3d_caps)("[OK]\n");
2979 case WINED3DFMT_B2G3R3_UNORM:
2980 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2984 * supported: Palettized
2986 case WINED3DFMT_P8_UINT:
2987 TRACE_(d3d_caps)("[OK]\n");
2989 /* No Windows driver offers WINED3DFMT_P8_UINT_A8_UNORM, so don't offer it either */
2990 case WINED3DFMT_P8_UINT_A8_UNORM:
2994 * Supported: (Alpha)-Luminance
2996 case WINED3DFMT_L8_UNORM:
2997 case WINED3DFMT_L8A8_UNORM:
2998 case WINED3DFMT_L16_UNORM:
2999 TRACE_(d3d_caps)("[OK]\n");
3002 /* Not supported on Windows, thus disabled */
3003 case WINED3DFMT_L4A4_UNORM:
3004 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
3008 * Supported: Depth/Stencil formats
3010 case WINED3DFMT_D16_LOCKABLE:
3011 case WINED3DFMT_D16_UNORM:
3012 case WINED3DFMT_S1_UINT_D15_UNORM:
3013 case WINED3DFMT_X8D24_UNORM:
3014 case WINED3DFMT_S4X4_UINT_D24_UNORM:
3015 case WINED3DFMT_D24_UNORM_S8_UINT:
3016 case WINED3DFMT_S8_UINT_D24_FLOAT:
3017 case WINED3DFMT_D32_UNORM:
3018 case WINED3DFMT_D32_FLOAT:
3022 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
3023 * GL_NV_texture_shader). Emulated by shaders
3025 case WINED3DFMT_R8G8_SNORM:
3026 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3027 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3028 case WINED3DFMT_R8G8B8A8_SNORM:
3029 case WINED3DFMT_R16G16_SNORM:
3030 /* Ask the shader backend if it can deal with the conversion. If
3031 * we've got a GL extension giving native support this will be an
3032 * identity conversion. */
3033 shader_backend = select_shader_backend(adapter, DeviceType);
3034 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3036 TRACE_(d3d_caps)("[OK]\n");
3039 TRACE_(d3d_caps)("[FAILED]\n");
3042 case WINED3DFMT_DXT1:
3043 case WINED3DFMT_DXT2:
3044 case WINED3DFMT_DXT3:
3045 case WINED3DFMT_DXT4:
3046 case WINED3DFMT_DXT5:
3047 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3049 TRACE_(d3d_caps)("[OK]\n");
3052 TRACE_(d3d_caps)("[FAILED]\n");
3057 * Odd formats - not supported
3059 case WINED3DFMT_VERTEXDATA:
3060 case WINED3DFMT_R16_UINT:
3061 case WINED3DFMT_R32_UINT:
3062 case WINED3DFMT_R16G16B16A16_SNORM:
3063 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3064 case WINED3DFMT_R10G11B11_SNORM:
3065 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3069 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3071 case WINED3DFMT_R8G8_SNORM_Cx:
3072 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3076 case WINED3DFMT_UYVY:
3077 case WINED3DFMT_YUY2:
3078 if (gl_info->supported[APPLE_YCBCR_422])
3080 TRACE_(d3d_caps)("[OK]\n");
3083 TRACE_(d3d_caps)("[FAILED]\n");
3085 case WINED3DFMT_YV12:
3086 TRACE_(d3d_caps)("[FAILED]\n");
3090 case WINED3DFMT_R16G16B16A16_UNORM:
3091 case WINED3DFMT_B2G3R3A8_UNORM:
3092 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3095 /* Floating point formats */
3096 case WINED3DFMT_R16_FLOAT:
3097 case WINED3DFMT_R16G16_FLOAT:
3098 case WINED3DFMT_R16G16B16A16_FLOAT:
3099 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3101 TRACE_(d3d_caps)("[OK]\n");
3104 TRACE_(d3d_caps)("[FAILED]\n");
3107 case WINED3DFMT_R32_FLOAT:
3108 case WINED3DFMT_R32G32_FLOAT:
3109 case WINED3DFMT_R32G32B32A32_FLOAT:
3110 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3112 TRACE_(d3d_caps)("[OK]\n");
3115 TRACE_(d3d_caps)("[FAILED]\n");
3118 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3119 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3120 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3121 * We can do instancing with all shader versions, but we need vertex shaders.
3123 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3124 * to enable instancing. WineD3D doesn't need that and just ignores it.
3126 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3128 case WINED3DFMT_INST:
3129 TRACE("ATI Instancing check hack\n");
3130 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3132 TRACE_(d3d_caps)("[OK]\n");
3135 TRACE_(d3d_caps)("[FAILED]\n");
3138 /* Some weird FOURCC formats */
3139 case WINED3DFMT_R8G8_B8G8:
3140 case WINED3DFMT_G8R8_G8B8:
3141 case WINED3DFMT_MULTI2_ARGB8:
3142 TRACE_(d3d_caps)("[FAILED]\n");
3145 /* Vendor specific formats */
3146 case WINED3DFMT_ATI2N:
3147 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3148 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3150 shader_backend = select_shader_backend(adapter, DeviceType);
3151 fp = select_fragment_implementation(adapter, DeviceType);
3152 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3153 && fp->color_fixup_supported(format_desc->color_fixup))
3155 TRACE_(d3d_caps)("[OK]\n");
3159 TRACE_(d3d_caps)("[OK]\n");
3162 TRACE_(d3d_caps)("[FAILED]\n");
3165 case WINED3DFMT_NVHU:
3166 case WINED3DFMT_NVHS:
3167 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3168 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3169 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3170 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3171 * Applications have to deal with not having NVHS and NVHU.
3173 TRACE_(d3d_caps)("[FAILED]\n");
3176 case WINED3DFMT_UNKNOWN:
3180 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3186 static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3187 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3189 const struct blit_shader *blitter;
3191 if(SurfaceType == SURFACE_GDI) {
3192 switch(check_format_desc->format)
3194 case WINED3DFMT_B8G8R8_UNORM:
3195 case WINED3DFMT_B8G8R8A8_UNORM:
3196 case WINED3DFMT_B8G8R8X8_UNORM:
3197 case WINED3DFMT_B5G6R5_UNORM:
3198 case WINED3DFMT_B5G5R5X1_UNORM:
3199 case WINED3DFMT_B5G5R5A1_UNORM:
3200 case WINED3DFMT_B4G4R4A4_UNORM:
3201 case WINED3DFMT_B2G3R3_UNORM:
3202 case WINED3DFMT_A8_UNORM:
3203 case WINED3DFMT_B2G3R3A8_UNORM:
3204 case WINED3DFMT_B4G4R4X4_UNORM:
3205 case WINED3DFMT_R10G10B10A2_UNORM:
3206 case WINED3DFMT_R8G8B8A8_UNORM:
3207 case WINED3DFMT_R8G8B8X8_UNORM:
3208 case WINED3DFMT_R16G16_UNORM:
3209 case WINED3DFMT_B10G10R10A2_UNORM:
3210 case WINED3DFMT_R16G16B16A16_UNORM:
3211 case WINED3DFMT_P8_UINT:
3212 TRACE_(d3d_caps)("[OK]\n");
3215 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3220 /* All format that are supported for textures are supported for surfaces as well */
3221 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3222 /* All depth stencil formats are supported on surfaces */
3223 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3225 /* If opengl can't process the format natively, the blitter may be able to convert it */
3226 blitter = select_blit_implementation(adapter, DeviceType);
3227 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3229 TRACE_(d3d_caps)("[OK]\n");
3233 /* Reject other formats */
3234 TRACE_(d3d_caps)("[FAILED]\n");
3238 static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3240 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3242 if (!gl_info->limits.vertex_samplers)
3244 TRACE_(d3d_caps)("[FAILED]\n");
3248 switch (format_desc->format)
3250 case WINED3DFMT_R32G32B32A32_FLOAT:
3251 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3253 TRACE_(d3d_caps)("[FAILED]\n");
3256 TRACE_(d3d_caps)("[OK]\n");
3260 TRACE_(d3d_caps)("[FAILED]\n");
3266 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3267 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3268 WINED3DSURFTYPE SurfaceType)
3270 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3271 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3272 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3273 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3274 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3275 DWORD UsageCaps = 0;
3277 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3280 DeviceType, debug_d3ddevicetype(DeviceType),
3281 AdapterFormat, debug_d3dformat(AdapterFormat),
3282 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3283 RType, debug_d3dresourcetype(RType),
3284 CheckFormat, debug_d3dformat(CheckFormat));
3286 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3287 return WINED3DERR_INVALIDCALL;
3290 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3292 if(SurfaceType != SURFACE_OPENGL) {
3293 TRACE("[FAILED]\n");
3294 return WINED3DERR_NOTAVAILABLE;
3297 /* Cubetexture allows:
3298 * - D3DUSAGE_AUTOGENMIPMAP
3299 * - D3DUSAGE_DEPTHSTENCIL
3300 * - D3DUSAGE_DYNAMIC
3301 * - D3DUSAGE_NONSECURE (d3d9ex)
3302 * - D3DUSAGE_RENDERTARGET
3303 * - D3DUSAGE_SOFTWAREPROCESSING
3304 * - D3DUSAGE_QUERY_WRAPANDMIP
3306 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3308 /* Check if the texture format is around */
3309 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3311 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3312 /* Check for automatic mipmap generation support */
3313 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3315 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3317 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3318 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3322 /* Always report dynamic locking */
3323 if(Usage & WINED3DUSAGE_DYNAMIC)
3324 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3326 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3327 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3329 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3331 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3332 return WINED3DERR_NOTAVAILABLE;
3336 /* Always report software processing */
3337 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3338 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3340 /* Check QUERY_FILTER support */
3341 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3342 if (CheckFilterCapability(adapter, format_desc))
3344 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3346 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3347 return WINED3DERR_NOTAVAILABLE;
3351 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3352 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3353 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3355 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3357 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3358 return WINED3DERR_NOTAVAILABLE;
3362 /* Check QUERY_SRGBREAD support */
3363 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3364 if (CheckSrgbReadCapability(adapter, format_desc))
3366 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3368 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3369 return WINED3DERR_NOTAVAILABLE;
3373 /* Check QUERY_SRGBWRITE support */
3374 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3375 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3377 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3379 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3380 return WINED3DERR_NOTAVAILABLE;
3384 /* Check QUERY_VERTEXTEXTURE support */
3385 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3386 if (CheckVertexTextureCapability(adapter, format_desc))
3388 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3390 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3391 return WINED3DERR_NOTAVAILABLE;
3395 /* Check QUERY_WRAPANDMIP support */
3396 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3397 if (CheckWrapAndMipCapability(adapter, format_desc))
3399 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3401 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3402 return WINED3DERR_NOTAVAILABLE;
3406 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3407 return WINED3DERR_NOTAVAILABLE;
3410 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3411 return WINED3DERR_NOTAVAILABLE;
3413 } else if(RType == WINED3DRTYPE_SURFACE) {
3415 * - D3DUSAGE_DEPTHSTENCIL
3416 * - D3DUSAGE_NONSECURE (d3d9ex)
3417 * - D3DUSAGE_RENDERTARGET
3420 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3422 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3423 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3425 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3427 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3428 return WINED3DERR_NOTAVAILABLE;
3432 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3433 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3435 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3437 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3438 return WINED3DERR_NOTAVAILABLE;
3442 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3443 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3444 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3446 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3448 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3449 return WINED3DERR_NOTAVAILABLE;
3453 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3454 return WINED3DERR_NOTAVAILABLE;
3457 } else if(RType == WINED3DRTYPE_TEXTURE) {
3459 * - D3DUSAGE_AUTOGENMIPMAP
3460 * - D3DUSAGE_DEPTHSTENCIL
3462 * - D3DUSAGE_DYNAMIC
3463 * - D3DUSAGE_NONSECURE (d3d9ex)
3464 * - D3DUSAGE_RENDERTARGET
3465 * - D3DUSAGE_SOFTWAREPROCESSING
3466 * - D3DUSAGE_TEXTAPI (d3d9ex)
3467 * - D3DUSAGE_QUERY_WRAPANDMIP
3470 if(SurfaceType != SURFACE_OPENGL) {
3471 TRACE("[FAILED]\n");
3472 return WINED3DERR_NOTAVAILABLE;
3475 /* Check if the texture format is around */
3476 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3478 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3479 /* Check for automatic mipmap generation support */
3480 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3482 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3484 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3485 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3489 /* Always report dynamic locking */
3490 if(Usage & WINED3DUSAGE_DYNAMIC)
3491 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3493 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3494 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3496 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3498 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3499 return WINED3DERR_NOTAVAILABLE;
3503 /* Always report software processing */
3504 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3505 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3507 /* Check QUERY_FILTER support */
3508 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3509 if (CheckFilterCapability(adapter, format_desc))
3511 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3513 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3514 return WINED3DERR_NOTAVAILABLE;
3518 /* Check QUERY_LEGACYBUMPMAP support */
3519 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3520 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3522 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3524 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3525 return WINED3DERR_NOTAVAILABLE;
3529 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3530 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3531 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3533 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3535 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3536 return WINED3DERR_NOTAVAILABLE;
3540 /* Check QUERY_SRGBREAD support */
3541 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3542 if (CheckSrgbReadCapability(adapter, format_desc))
3544 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3546 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3547 return WINED3DERR_NOTAVAILABLE;
3551 /* Check QUERY_SRGBWRITE support */
3552 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3553 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3555 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3557 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3558 return WINED3DERR_NOTAVAILABLE;
3562 /* Check QUERY_VERTEXTEXTURE support */
3563 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3564 if (CheckVertexTextureCapability(adapter, format_desc))
3566 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3568 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3569 return WINED3DERR_NOTAVAILABLE;
3573 /* Check QUERY_WRAPANDMIP support */
3574 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3575 if (CheckWrapAndMipCapability(adapter, format_desc))
3577 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3579 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3580 return WINED3DERR_NOTAVAILABLE;
3584 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3585 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3587 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3589 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3590 return WINED3DERR_NOTAVAILABLE;
3594 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3595 return WINED3DERR_NOTAVAILABLE;
3597 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3598 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3599 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3601 * Volumetexture allows:
3602 * - D3DUSAGE_DYNAMIC
3603 * - D3DUSAGE_NONSECURE (d3d9ex)
3604 * - D3DUSAGE_SOFTWAREPROCESSING
3605 * - D3DUSAGE_QUERY_WRAPANDMIP
3608 if(SurfaceType != SURFACE_OPENGL) {
3609 TRACE("[FAILED]\n");
3610 return WINED3DERR_NOTAVAILABLE;
3613 /* Check volume texture and volume usage caps */
3614 if (gl_info->supported[EXT_TEXTURE3D])
3616 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3618 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3619 return WINED3DERR_NOTAVAILABLE;
3622 /* Always report dynamic locking */
3623 if(Usage & WINED3DUSAGE_DYNAMIC)
3624 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3626 /* Always report software processing */
3627 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3628 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3630 /* Check QUERY_FILTER support */
3631 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3632 if (CheckFilterCapability(adapter, format_desc))
3634 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3636 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3637 return WINED3DERR_NOTAVAILABLE;
3641 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3642 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3643 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3645 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3647 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3648 return WINED3DERR_NOTAVAILABLE;
3652 /* Check QUERY_SRGBREAD support */
3653 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3654 if (CheckSrgbReadCapability(adapter, format_desc))
3656 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3658 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3659 return WINED3DERR_NOTAVAILABLE;
3663 /* Check QUERY_SRGBWRITE support */
3664 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3665 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3667 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3669 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3670 return WINED3DERR_NOTAVAILABLE;
3674 /* Check QUERY_VERTEXTEXTURE support */
3675 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3676 if (CheckVertexTextureCapability(adapter, format_desc))
3678 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3680 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3681 return WINED3DERR_NOTAVAILABLE;
3685 /* Check QUERY_WRAPANDMIP support */
3686 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3687 if (CheckWrapAndMipCapability(adapter, format_desc))
3689 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3691 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3692 return WINED3DERR_NOTAVAILABLE;
3696 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3697 return WINED3DERR_NOTAVAILABLE;
3700 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3701 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3702 * app needing one of those formats, don't advertize them to avoid leading apps into
3703 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3706 switch(CheckFormat) {
3707 case WINED3DFMT_P8_UINT:
3708 case WINED3DFMT_L4A4_UNORM:
3709 case WINED3DFMT_R32_FLOAT:
3710 case WINED3DFMT_R16_FLOAT:
3711 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3712 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3713 case WINED3DFMT_R16G16_UNORM:
3714 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3715 return WINED3DERR_NOTAVAILABLE;
3717 case WINED3DFMT_R8G8B8A8_SNORM:
3718 case WINED3DFMT_R16G16_SNORM:
3719 if (!gl_info->supported[NV_TEXTURE_SHADER])
3721 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3722 return WINED3DERR_NOTAVAILABLE;
3726 case WINED3DFMT_R8G8_SNORM:
3727 if (!gl_info->supported[NV_TEXTURE_SHADER])
3729 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3730 return WINED3DERR_NOTAVAILABLE;
3734 case WINED3DFMT_DXT1:
3735 case WINED3DFMT_DXT2:
3736 case WINED3DFMT_DXT3:
3737 case WINED3DFMT_DXT4:
3738 case WINED3DFMT_DXT5:
3739 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3740 * compressed texture results in an error. While the D3D refrast does
3741 * support s3tc volumes, at least the nvidia windows driver does not, so
3742 * we're free not to support this format.
3744 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3745 return WINED3DERR_NOTAVAILABLE;
3748 /* Do nothing, continue with checking the format below */
3751 } else if(RType == WINED3DRTYPE_BUFFER){
3752 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3753 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3754 return WINED3DERR_NOTAVAILABLE;
3757 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3758 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3759 * usage flags match. */
3760 if(UsageCaps == Usage) {
3762 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3763 return WINED3DOK_NOAUTOGEN;
3765 TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
3766 return WINED3DERR_NOTAVAILABLE;
3770 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT adapter_idx,
3771 WINED3DDEVTYPE device_type, WINED3DFORMAT src_format, WINED3DFORMAT dst_format)
3773 FIXME("iface %p, adapter_idx %u, device_type %s, src_format %s, dst_format %s stub!\n",
3774 iface, adapter_idx, debug_d3ddevicetype(device_type), debug_d3dformat(src_format),
3775 debug_d3dformat(dst_format));
3780 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3781 subset of a D3DCAPS9 structure. However, it has to come via a void *
3782 as the d3d8 interface cannot import the d3d9 header */
3783 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3785 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3786 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3787 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3788 int vs_selected_mode;
3789 int ps_selected_mode;
3790 struct shader_caps shader_caps;
3791 struct fragment_caps fragment_caps;
3792 const shader_backend_t *shader_backend;
3793 const struct fragment_pipeline *frag_pipeline = NULL;
3794 DWORD ckey_caps, blit_caps, fx_caps;
3796 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3798 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3799 return WINED3DERR_INVALIDCALL;
3802 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3804 /* ------------------------------------------------
3805 The following fields apply to both d3d8 and d3d9
3806 ------------------------------------------------ */
3807 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3808 pCaps->AdapterOrdinal = Adapter;
3811 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3812 WINED3DCAPS2_FULLSCREENGAMMA |
3813 WINED3DCAPS2_DYNAMICTEXTURES;
3814 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3816 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3819 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3820 WINED3DCAPS3_COPY_TO_VIDMEM |
3821 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3823 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3824 WINED3DPRESENT_INTERVAL_ONE;
3826 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3827 WINED3DCURSORCAPS_LOWRES;
3829 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3830 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3831 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3832 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3833 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3834 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3835 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3836 WINED3DDEVCAPS_PUREDEVICE |
3837 WINED3DDEVCAPS_HWRASTERIZATION |
3838 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3839 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3840 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3841 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3842 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3843 WINED3DDEVCAPS_RTPATCHES;
3845 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3846 WINED3DPMISCCAPS_CULLCCW |
3847 WINED3DPMISCCAPS_CULLCW |
3848 WINED3DPMISCCAPS_COLORWRITEENABLE |
3849 WINED3DPMISCCAPS_CLIPTLVERTS |
3850 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3851 WINED3DPMISCCAPS_MASKZ |
3852 WINED3DPMISCCAPS_BLENDOP |
3853 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3855 WINED3DPMISCCAPS_NULLREFERENCE
3856 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3857 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3858 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3859 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3861 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
3862 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3864 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3865 WINED3DPRASTERCAPS_PAT |
3866 WINED3DPRASTERCAPS_WFOG |
3867 WINED3DPRASTERCAPS_ZFOG |
3868 WINED3DPRASTERCAPS_FOGVERTEX |
3869 WINED3DPRASTERCAPS_FOGTABLE |
3870 WINED3DPRASTERCAPS_STIPPLE |
3871 WINED3DPRASTERCAPS_SUBPIXEL |
3872 WINED3DPRASTERCAPS_ZTEST |
3873 WINED3DPRASTERCAPS_SCISSORTEST |
3874 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3875 WINED3DPRASTERCAPS_DEPTHBIAS;
3877 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
3879 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3880 WINED3DPRASTERCAPS_ZBIAS |
3881 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3883 if (gl_info->supported[NV_FOG_DISTANCE])
3885 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3888 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3889 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3890 WINED3DPRASTERCAPS_ANTIALIASEDGES
3891 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3892 WINED3DPRASTERCAPS_WBUFFER */
3894 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3895 WINED3DPCMPCAPS_EQUAL |
3896 WINED3DPCMPCAPS_GREATER |
3897 WINED3DPCMPCAPS_GREATEREQUAL |
3898 WINED3DPCMPCAPS_LESS |
3899 WINED3DPCMPCAPS_LESSEQUAL |
3900 WINED3DPCMPCAPS_NEVER |
3901 WINED3DPCMPCAPS_NOTEQUAL;
3903 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3904 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3905 WINED3DPBLENDCAPS_DESTALPHA |
3906 WINED3DPBLENDCAPS_DESTCOLOR |
3907 WINED3DPBLENDCAPS_INVDESTALPHA |
3908 WINED3DPBLENDCAPS_INVDESTCOLOR |
3909 WINED3DPBLENDCAPS_INVSRCALPHA |
3910 WINED3DPBLENDCAPS_INVSRCCOLOR |
3911 WINED3DPBLENDCAPS_ONE |
3912 WINED3DPBLENDCAPS_SRCALPHA |
3913 WINED3DPBLENDCAPS_SRCALPHASAT |
3914 WINED3DPBLENDCAPS_SRCCOLOR |
3915 WINED3DPBLENDCAPS_ZERO;
3917 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3918 WINED3DPBLENDCAPS_DESTCOLOR |
3919 WINED3DPBLENDCAPS_INVDESTALPHA |
3920 WINED3DPBLENDCAPS_INVDESTCOLOR |
3921 WINED3DPBLENDCAPS_INVSRCALPHA |
3922 WINED3DPBLENDCAPS_INVSRCCOLOR |
3923 WINED3DPBLENDCAPS_ONE |
3924 WINED3DPBLENDCAPS_SRCALPHA |
3925 WINED3DPBLENDCAPS_SRCCOLOR |
3926 WINED3DPBLENDCAPS_ZERO;
3927 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3928 * according to the glBlendFunc manpage
3930 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3931 * legacy settings for srcblend only
3934 if (gl_info->supported[EXT_BLEND_COLOR])
3936 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3937 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3941 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3942 WINED3DPCMPCAPS_EQUAL |
3943 WINED3DPCMPCAPS_GREATER |
3944 WINED3DPCMPCAPS_GREATEREQUAL |
3945 WINED3DPCMPCAPS_LESS |
3946 WINED3DPCMPCAPS_LESSEQUAL |
3947 WINED3DPCMPCAPS_NEVER |
3948 WINED3DPCMPCAPS_NOTEQUAL;
3950 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3951 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3952 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3953 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3954 WINED3DPSHADECAPS_COLORFLATRGB |
3955 WINED3DPSHADECAPS_FOGFLAT |
3956 WINED3DPSHADECAPS_FOGGOURAUD |
3957 WINED3DPSHADECAPS_SPECULARFLATRGB;
3959 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3960 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3961 WINED3DPTEXTURECAPS_TRANSPARENCY |
3962 WINED3DPTEXTURECAPS_BORDER |
3963 WINED3DPTEXTURECAPS_MIPMAP |
3964 WINED3DPTEXTURECAPS_PROJECTED |
3965 WINED3DPTEXTURECAPS_PERSPECTIVE;
3967 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
3969 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3970 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3973 if (gl_info->supported[EXT_TEXTURE3D])
3975 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3976 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3977 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3980 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3982 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3983 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3984 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3988 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3989 WINED3DPTFILTERCAPS_MAGFPOINT |
3990 WINED3DPTFILTERCAPS_MINFLINEAR |
3991 WINED3DPTFILTERCAPS_MINFPOINT |
3992 WINED3DPTFILTERCAPS_MIPFLINEAR |
3993 WINED3DPTFILTERCAPS_MIPFPOINT |
3994 WINED3DPTFILTERCAPS_LINEAR |
3995 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3996 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3997 WINED3DPTFILTERCAPS_MIPLINEAR |
3998 WINED3DPTFILTERCAPS_MIPNEAREST |
3999 WINED3DPTFILTERCAPS_NEAREST;
4001 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4003 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4004 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4007 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4009 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4010 WINED3DPTFILTERCAPS_MAGFPOINT |
4011 WINED3DPTFILTERCAPS_MINFLINEAR |
4012 WINED3DPTFILTERCAPS_MINFPOINT |
4013 WINED3DPTFILTERCAPS_MIPFLINEAR |
4014 WINED3DPTFILTERCAPS_MIPFPOINT |
4015 WINED3DPTFILTERCAPS_LINEAR |
4016 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4017 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4018 WINED3DPTFILTERCAPS_MIPLINEAR |
4019 WINED3DPTFILTERCAPS_MIPNEAREST |
4020 WINED3DPTFILTERCAPS_NEAREST;
4022 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4024 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4025 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4028 pCaps->CubeTextureFilterCaps = 0;
4030 if (gl_info->supported[EXT_TEXTURE3D])
4032 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4033 WINED3DPTFILTERCAPS_MAGFPOINT |
4034 WINED3DPTFILTERCAPS_MINFLINEAR |
4035 WINED3DPTFILTERCAPS_MINFPOINT |
4036 WINED3DPTFILTERCAPS_MIPFLINEAR |
4037 WINED3DPTFILTERCAPS_MIPFPOINT |
4038 WINED3DPTFILTERCAPS_LINEAR |
4039 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4040 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4041 WINED3DPTFILTERCAPS_MIPLINEAR |
4042 WINED3DPTFILTERCAPS_MIPNEAREST |
4043 WINED3DPTFILTERCAPS_NEAREST;
4045 pCaps->VolumeTextureFilterCaps = 0;
4047 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4048 WINED3DPTADDRESSCAPS_CLAMP |
4049 WINED3DPTADDRESSCAPS_WRAP;
4051 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4053 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4055 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4057 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4059 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4061 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4064 if (gl_info->supported[EXT_TEXTURE3D])
4066 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4067 WINED3DPTADDRESSCAPS_CLAMP |
4068 WINED3DPTADDRESSCAPS_WRAP;
4069 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4071 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4073 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4075 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4077 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4079 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4082 pCaps->VolumeTextureAddressCaps = 0;
4084 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4085 WINED3DLINECAPS_ZTEST |
4086 WINED3DLINECAPS_BLEND |
4087 WINED3DLINECAPS_ALPHACMP |
4088 WINED3DLINECAPS_FOG;
4089 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4090 * idea how generating the smoothing alpha values works; the result is different
4093 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4094 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4096 if (gl_info->supported[EXT_TEXTURE3D])
4097 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4099 pCaps->MaxVolumeExtent = 0;
4101 pCaps->MaxTextureRepeat = 32768;
4102 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4103 pCaps->MaxVertexW = 1.0f;
4105 pCaps->GuardBandLeft = 0.0f;
4106 pCaps->GuardBandTop = 0.0f;
4107 pCaps->GuardBandRight = 0.0f;
4108 pCaps->GuardBandBottom = 0.0f;
4110 pCaps->ExtentsAdjust = 0.0f;
4112 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4113 WINED3DSTENCILCAPS_INCRSAT |
4114 WINED3DSTENCILCAPS_INVERT |
4115 WINED3DSTENCILCAPS_KEEP |
4116 WINED3DSTENCILCAPS_REPLACE |
4117 WINED3DSTENCILCAPS_ZERO;
4118 if (gl_info->supported[EXT_STENCIL_WRAP])
4120 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4121 WINED3DSTENCILCAPS_INCR;
4123 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4125 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4128 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4130 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4131 pCaps->MaxActiveLights = gl_info->limits.lights;
4133 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4134 pCaps->MaxVertexBlendMatrixIndex = 0;
4136 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4137 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4140 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4141 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4142 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4143 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4144 WINED3DVTXPCAPS_LOCALVIEWER |
4145 WINED3DVTXPCAPS_VERTEXFOG |
4146 WINED3DVTXPCAPS_TEXGEN;
4148 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4149 pCaps->MaxVertexIndex = 0xFFFFF;
4150 pCaps->MaxStreams = MAX_STREAMS;
4151 pCaps->MaxStreamStride = 1024;
4153 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4154 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4155 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4156 pCaps->MaxNpatchTessellationLevel = 0;
4157 pCaps->MasterAdapterOrdinal = 0;
4158 pCaps->AdapterOrdinalInGroup = 0;
4159 pCaps->NumberOfAdaptersInGroup = 1;
4161 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4163 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4164 WINED3DPTFILTERCAPS_MAGFPOINT |
4165 WINED3DPTFILTERCAPS_MINFLINEAR |
4166 WINED3DPTFILTERCAPS_MAGFLINEAR;
4167 pCaps->VertexTextureFilterCaps = 0;
4169 memset(&shader_caps, 0, sizeof(shader_caps));
4170 shader_backend = select_shader_backend(adapter, DeviceType);
4171 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4173 memset(&fragment_caps, 0, sizeof(fragment_caps));
4174 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4175 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4177 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4178 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4180 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4181 * Ignore shader model capabilities if disabled in config
4183 if(vs_selected_mode == SHADER_NONE) {
4184 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4185 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4186 pCaps->MaxVertexShaderConst = 0;
4188 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4189 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4192 if(ps_selected_mode == SHADER_NONE) {
4193 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4194 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4195 pCaps->PixelShader1xMaxValue = 0.0f;
4197 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4198 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4201 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4202 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4203 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4205 pCaps->VS20Caps = shader_caps.VS20Caps;
4206 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4207 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4208 pCaps->PS20Caps = shader_caps.PS20Caps;
4209 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4210 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4212 /* The following caps are shader specific, but they are things we cannot detect, or which
4213 * are the same among all shader models. So to avoid code duplication set the shader version
4214 * specific, but otherwise constant caps here
4216 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4217 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4218 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4219 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4220 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4221 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4222 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4224 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4225 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4227 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4229 pCaps->VS20Caps.Caps = 0;
4230 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4231 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4232 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4234 pCaps->MaxVShaderInstructionsExecuted = 65535;
4235 pCaps->MaxVertexShader30InstructionSlots = 0;
4236 } else { /* VS 1.x */
4237 pCaps->VS20Caps.Caps = 0;
4238 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4239 pCaps->VS20Caps.NumTemps = 0;
4240 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4242 pCaps->MaxVShaderInstructionsExecuted = 0;
4243 pCaps->MaxVertexShader30InstructionSlots = 0;
4246 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4247 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4248 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4250 /* 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 */
4251 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4252 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4253 WINED3DPS20CAPS_PREDICATION |
4254 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4255 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4256 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4257 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4258 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4259 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4261 pCaps->MaxPShaderInstructionsExecuted = 65535;
4262 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4263 adapter->gl_info.limits.arb_ps_instructions);
4265 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4267 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4268 pCaps->PS20Caps.Caps = 0;
4269 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4270 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4271 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4272 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4274 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4275 pCaps->MaxPixelShader30InstructionSlots = 0;
4276 } else { /* PS 1.x */
4277 pCaps->PS20Caps.Caps = 0;
4278 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4279 pCaps->PS20Caps.NumTemps = 0;
4280 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4281 pCaps->PS20Caps.NumInstructionSlots = 0;
4283 pCaps->MaxPShaderInstructionsExecuted = 0;
4284 pCaps->MaxPixelShader30InstructionSlots = 0;
4287 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4288 /* OpenGL supports all the formats below, perhaps not always
4289 * without conversion, but it supports them.
4290 * Further GLSL doesn't seem to have an official unsigned type so
4291 * don't advertise it yet as I'm not sure how we handle it.
4292 * We might need to add some clamping in the shader engine to
4294 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4295 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4296 WINED3DDTCAPS_UBYTE4N |
4297 WINED3DDTCAPS_SHORT2N |
4298 WINED3DDTCAPS_SHORT4N;
4299 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4301 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4302 WINED3DDTCAPS_FLOAT16_4;
4305 pCaps->DeclTypes = 0;
4307 /* Set DirectDraw helper Caps */
4308 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4309 WINEDDCKEYCAPS_SRCBLT;
4310 fx_caps = WINEDDFXCAPS_BLTALPHA |
4311 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4312 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4313 WINEDDFXCAPS_BLTROTATION90 |
4314 WINEDDFXCAPS_BLTSHRINKX |
4315 WINEDDFXCAPS_BLTSHRINKXN |
4316 WINEDDFXCAPS_BLTSHRINKY |
4317 WINEDDFXCAPS_BLTSHRINKXN |
4318 WINEDDFXCAPS_BLTSTRETCHX |
4319 WINEDDFXCAPS_BLTSTRETCHXN |
4320 WINEDDFXCAPS_BLTSTRETCHY |
4321 WINEDDFXCAPS_BLTSTRETCHYN;
4322 blit_caps = WINEDDCAPS_BLT |
4323 WINEDDCAPS_BLTCOLORFILL |
4324 WINEDDCAPS_BLTDEPTHFILL |
4325 WINEDDCAPS_BLTSTRETCH |
4326 WINEDDCAPS_CANBLTSYSMEM |
4327 WINEDDCAPS_CANCLIP |
4328 WINEDDCAPS_CANCLIPSTRETCHED |
4329 WINEDDCAPS_COLORKEY |
4330 WINEDDCAPS_COLORKEYHWASSIST |
4331 WINEDDCAPS_ALIGNBOUNDARYSRC;
4333 /* Fill the ddraw caps structure */
4334 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4335 WINEDDCAPS_PALETTE |
4337 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4338 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4339 WINEDDCAPS2_PRIMARYGAMMA |
4340 WINEDDCAPS2_WIDESURFACES |
4341 WINEDDCAPS2_CANRENDERWINDOWED;
4342 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4343 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4344 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4345 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4346 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4347 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4348 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4349 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4350 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4352 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4353 WINEDDSCAPS_BACKBUFFER |
4355 WINEDDSCAPS_FRONTBUFFER |
4356 WINEDDSCAPS_OFFSCREENPLAIN |
4357 WINEDDSCAPS_PALETTE |
4358 WINEDDSCAPS_PRIMARYSURFACE |
4359 WINEDDSCAPS_SYSTEMMEMORY |
4360 WINEDDSCAPS_VIDEOMEMORY |
4361 WINEDDSCAPS_VISIBLE;
4362 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4364 /* Set D3D caps if OpenGL is available. */
4365 if (adapter->opengl)
4367 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4368 WINEDDSCAPS_MIPMAP |
4369 WINEDDSCAPS_TEXTURE |
4370 WINEDDSCAPS_ZBUFFER;
4371 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4377 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT adapter_idx,
4378 WINED3DDEVTYPE device_type, HWND focus_window, DWORD flags, IUnknown *parent,
4379 IWineD3DDeviceParent *device_parent, IWineD3DDevice **device)
4381 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4382 IWineD3DDeviceImpl *object;
4385 TRACE("iface %p, adapter_idx %u, device_type %#x, focus_window %p, flags %#x.\n"
4386 "parent %p, device_parent %p, device %p.\n",
4387 iface, adapter_idx, device_type, focus_window, flags,
4388 parent, device_parent, device);
4390 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4391 * number and create a device without a 3D adapter for 2D only operation. */
4392 if (IWineD3D_GetAdapterCount(iface) && adapter_idx >= IWineD3D_GetAdapterCount(iface))
4394 return WINED3DERR_INVALIDCALL;
4397 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
4400 ERR("Failed to allocate device memory.\n");
4401 return E_OUTOFMEMORY;
4404 hr = device_init(object, This, adapter_idx, device_type, focus_window, flags, parent, device_parent);
4407 WARN("Failed to initialize device, hr %#x.\n", hr);
4408 HeapFree(GetProcessHeap(), 0, object);
4412 TRACE("Created device %p.\n", object);
4413 *device = (IWineD3DDevice *)object;
4415 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *device);
4420 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4421 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4422 IUnknown_AddRef(This->parent);
4423 *pParent = This->parent;
4427 static void WINE_GLAPI invalid_func(const void *data)
4429 ERR("Invalid vertex attribute function called\n");
4433 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4435 ERR("Invalid texcoord function called\n");
4439 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4440 * the extension detection and are used in drawStridedSlow
4442 static void WINE_GLAPI position_d3dcolor(const void *data)
4444 DWORD pos = *((const DWORD *)data);
4446 FIXME("Add a test for fixed function position from d3dcolor type\n");
4447 glVertex4s(D3DCOLOR_B_R(pos),
4453 static void WINE_GLAPI position_float4(const void *data)
4455 const GLfloat *pos = data;
4457 if (pos[3] != 0.0f && pos[3] != 1.0f)
4459 float w = 1.0f / pos[3];
4461 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4469 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4471 DWORD diffuseColor = *((const DWORD *)data);
4473 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4474 D3DCOLOR_B_G(diffuseColor),
4475 D3DCOLOR_B_B(diffuseColor),
4476 D3DCOLOR_B_A(diffuseColor));
4479 static void WINE_GLAPI specular_d3dcolor(const void *data)
4481 DWORD specularColor = *((const DWORD *)data);
4482 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4483 D3DCOLOR_B_G(specularColor),
4484 D3DCOLOR_B_B(specularColor)};
4486 specular_func_3ubv(d);
4489 static void WINE_GLAPI warn_no_specular_func(const void *data)
4491 WARN("GL_EXT_secondary_color not supported\n");
4494 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4496 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4497 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4498 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4499 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4500 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4501 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4502 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4503 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4504 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4505 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4506 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4507 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4508 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4509 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4510 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4511 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4512 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4514 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4515 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4516 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4517 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4518 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4519 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4520 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4521 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4522 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4523 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4524 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4525 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4526 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4527 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4528 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4529 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4530 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4532 /* No 4 component entry points here */
4533 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4534 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4535 if (gl_info->supported[EXT_SECONDARY_COLOR])
4537 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4541 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4543 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4544 if (gl_info->supported[EXT_SECONDARY_COLOR])
4546 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4547 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4551 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4553 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4554 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4555 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4556 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4557 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4558 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4559 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4560 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4561 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4562 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4563 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4564 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4566 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4567 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4569 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4570 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4571 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4572 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4573 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4574 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4575 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4576 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4577 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4578 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4579 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4580 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4581 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4582 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4583 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4584 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4585 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4587 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4588 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4589 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4590 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4591 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4592 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4593 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4594 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4595 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4596 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4597 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4598 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4599 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4600 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4601 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4602 if (gl_info->supported[NV_HALF_FLOAT])
4604 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4605 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4606 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4608 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4609 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4613 BOOL InitAdapters(IWineD3DImpl *This)
4615 static HMODULE mod_gl;
4617 int ps_selected_mode, vs_selected_mode;
4619 /* No need to hold any lock. The calling library makes sure only one thread calls
4620 * wined3d simultaneously
4623 TRACE("Initializing adapters\n");
4626 #ifdef USE_WIN32_OPENGL
4627 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4628 mod_gl = LoadLibraryA("opengl32.dll");
4630 ERR("Can't load opengl32.dll!\n");
4634 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4635 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4636 mod_gl = GetModuleHandleA("gdi32.dll");
4640 /* Load WGL core functions from opengl32.dll */
4641 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4645 if(!pwglGetProcAddress) {
4646 ERR("Unable to load wglGetProcAddress!\n");
4650 /* Dynamically load all GL core functions */
4654 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4655 * otherwise because we have to use winex11.drv's override
4657 #ifdef USE_WIN32_OPENGL
4658 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4659 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4661 wglFinish = (void*)pwglGetProcAddress("wglFinish");
4662 wglFlush = (void*)pwglGetProcAddress("wglFlush");
4665 glEnableWINE = glEnable;
4666 glDisableWINE = glDisable;
4668 /* For now only one default adapter */
4670 struct wined3d_adapter *adapter = &This->adapters[0];
4671 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4672 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4676 WineD3D_PixelFormat *cfgs;
4677 DISPLAY_DEVICEW DisplayDevice;
4680 TRACE("Initializing default adapter\n");
4681 adapter->ordinal = 0;
4682 adapter->monitorPoint.x = -1;
4683 adapter->monitorPoint.y = -1;
4685 if (!AllocateLocallyUniqueId(&adapter->luid))
4687 DWORD err = GetLastError();
4688 ERR("Failed to set adapter LUID (%#x).\n", err);
4691 TRACE("Allocated LUID %08x:%08x for adapter.\n",
4692 adapter->luid.HighPart, adapter->luid.LowPart);
4694 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4696 ERR("Failed to get a gl context for default adapter\n");
4700 ret = IWineD3DImpl_FillGLCaps(&adapter->driver_info, &adapter->gl_info);
4702 ERR("Failed to initialize gl caps for default adapter\n");
4703 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4706 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
4708 ERR("Failed to init gl formats\n");
4709 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4713 hdc = fake_gl_ctx.dc;
4715 /* Use the VideoRamSize registry setting when set */
4716 if(wined3d_settings.emulated_textureram)
4717 adapter->TextureRam = wined3d_settings.emulated_textureram;
4719 adapter->TextureRam = adapter->gl_info.vidmem;
4720 adapter->UsedTextureRam = 0;
4721 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4723 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4724 DisplayDevice.cb = sizeof(DisplayDevice);
4725 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4726 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4727 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4729 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
4736 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4737 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4739 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4740 cfgs = adapter->cfgs;
4741 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4742 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4743 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4744 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4745 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4746 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4747 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4748 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4749 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4750 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4752 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4754 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4759 /* Cache the pixel format */
4760 cfgs->iPixelFormat = iPixelFormat;
4761 cfgs->redSize = values[0];
4762 cfgs->greenSize = values[1];
4763 cfgs->blueSize = values[2];
4764 cfgs->alphaSize = values[3];
4765 cfgs->depthSize = values[4];
4766 cfgs->stencilSize = values[5];
4767 cfgs->windowDrawable = values[6];
4768 cfgs->iPixelType = values[7];
4769 cfgs->doubleBuffer = values[8];
4770 cfgs->auxBuffers = values[9];
4772 cfgs->pbufferDrawable = FALSE;
4773 /* Check for pbuffer support when it is around as
4774 * wglGetPixelFormatAttribiv fails for unknown attributes. */
4775 if (gl_info->supported[WGL_ARB_PBUFFER])
4777 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4779 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4780 cfgs->pbufferDrawable = value;
4783 cfgs->numSamples = 0;
4784 /* Check multisample support */
4785 if (gl_info->supported[ARB_MULTISAMPLE])
4787 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4789 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4790 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4791 * value[1] = number of multi sample buffers*/
4793 cfgs->numSamples = value[1];
4797 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4803 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4804 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4805 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4807 cfgs = adapter->cfgs;
4808 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4810 PIXELFORMATDESCRIPTOR ppfd;
4812 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4816 /* We only want HW acceleration using an OpenGL ICD driver.
4817 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4818 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4820 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4822 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4826 cfgs->iPixelFormat = iPixelFormat;
4827 cfgs->redSize = ppfd.cRedBits;
4828 cfgs->greenSize = ppfd.cGreenBits;
4829 cfgs->blueSize = ppfd.cBlueBits;
4830 cfgs->alphaSize = ppfd.cAlphaBits;
4831 cfgs->depthSize = ppfd.cDepthBits;
4832 cfgs->stencilSize = ppfd.cStencilBits;
4833 cfgs->pbufferDrawable = 0;
4834 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4835 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4836 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4837 cfgs->auxBuffers = ppfd.cAuxBuffers;
4838 cfgs->numSamples = 0;
4840 TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
4845 /* Yikes we haven't found any suitable formats. This should only happen in case of GDI software rendering which we can't use anyway as its 3D functionality is very, very limited */
4848 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4850 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4851 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4856 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4857 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4858 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4859 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4860 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4861 * driver is allowed to consume more bits EXCEPT for stencil bits.
4863 * Mark an adapter with this broken stencil behavior.
4865 adapter->brokenStencil = TRUE;
4866 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4868 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4869 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4870 adapter->brokenStencil = FALSE;
4875 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4877 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4878 fillGLAttribFuncs(&adapter->gl_info);
4879 adapter->opengl = TRUE;
4881 This->adapter_count = 1;
4882 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4887 /* Initialize an adapter for ddraw-only memory counting */
4888 memset(This->adapters, 0, sizeof(This->adapters));
4889 This->adapters[0].ordinal = 0;
4890 This->adapters[0].opengl = FALSE;
4891 This->adapters[0].monitorPoint.x = -1;
4892 This->adapters[0].monitorPoint.y = -1;
4894 This->adapters[0].driver_info.name = "Display";
4895 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
4896 if(wined3d_settings.emulated_textureram) {
4897 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4899 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4902 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4904 This->adapter_count = 1;
4908 /**********************************************************
4909 * IWineD3D VTbl follows
4910 **********************************************************/
4912 const IWineD3DVtbl IWineD3D_Vtbl =
4915 IWineD3DImpl_QueryInterface,
4916 IWineD3DImpl_AddRef,
4917 IWineD3DImpl_Release,
4919 IWineD3DImpl_GetParent,
4920 IWineD3DImpl_GetAdapterCount,
4921 IWineD3DImpl_RegisterSoftwareDevice,
4922 IWineD3DImpl_GetAdapterMonitor,
4923 IWineD3DImpl_GetAdapterModeCount,
4924 IWineD3DImpl_EnumAdapterModes,
4925 IWineD3DImpl_GetAdapterDisplayMode,
4926 IWineD3DImpl_GetAdapterIdentifier,
4927 IWineD3DImpl_CheckDeviceMultiSampleType,
4928 IWineD3DImpl_CheckDepthStencilMatch,
4929 IWineD3DImpl_CheckDeviceType,
4930 IWineD3DImpl_CheckDeviceFormat,
4931 IWineD3DImpl_CheckDeviceFormatConversion,
4932 IWineD3DImpl_GetDeviceCaps,
4933 IWineD3DImpl_CreateDevice
4936 static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
4938 const struct wined3d_parent_ops wined3d_null_parent_ops =
4940 wined3d_null_wined3d_object_destroyed,