rpcrt4: Support multiple interfaces and transfer syntaxes in bind and bind ack messages.
[wine.git] / dlls / wined3d / directx.c
blobae5f2cb3165cc7145045ed714a3bea9cc99cae18
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
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
26 #include "config.h"
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 */
38 static const struct {
39 const char *extension_string;
40 GL_SupportedExt extension;
41 DWORD version;
42 } EXTENSION_MAP[] = {
43 /* APPLE */
44 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
45 {"GL_APPLE_fence", APPLE_FENCE, 0 },
46 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
47 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
48 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
50 /* ATI */
51 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
52 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
53 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
54 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
55 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
57 /* ARB */
58 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
59 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
60 {"GL_ARB_depth_clamp", ARB_DEPTH_CLAMP, 0 },
61 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
62 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
63 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
64 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
65 {"GL_ARB_framebuffer_object", ARB_FRAMEBUFFER_OBJECT, 0 },
66 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
67 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
68 {"GL_ARB_imaging", ARB_IMAGING, 0 },
69 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
70 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
71 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
72 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
73 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
74 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
75 {"GL_ARB_provoking_vertex", ARB_PROVOKING_VERTEX, 0 },
76 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
77 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
78 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
79 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
80 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
81 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
82 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
83 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
84 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
85 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
86 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
87 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
88 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
89 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
90 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
91 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
92 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
93 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
95 /* EXT */
96 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
97 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 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_fog_coord", EXT_FOG_COORD, 0 },
101 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
102 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
103 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
104 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
105 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
106 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
107 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
108 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
109 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
110 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
111 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
112 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
113 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
114 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
115 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
116 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
117 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
118 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
119 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
120 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
121 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
122 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
123 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
124 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
126 /* NV */
127 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
128 {"GL_NV_fence", NV_FENCE, 0 },
129 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
130 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
131 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
132 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
133 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
134 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
135 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
136 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
137 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
138 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
139 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
140 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
141 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
142 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
143 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
144 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
145 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
146 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
147 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
149 /* SGI */
150 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
153 /**********************************************************
154 * Utility functions follow
155 **********************************************************/
157 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
158 static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter,
159 WINED3DDEVTYPE DeviceType);
160 static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter, WINED3DDEVTYPE DeviceType);
161 static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter, WINED3DDEVTYPE DeviceType);
163 GLint wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP + 1];
165 const struct min_lookup minMipLookup[] =
167 /* NONE POINT LINEAR */
168 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
169 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
170 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
173 const struct min_lookup minMipLookup_noFilter[] =
175 /* NONE POINT LINEAR */
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
178 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
181 const struct min_lookup minMipLookup_noMip[] =
183 /* NONE POINT LINEAR */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
185 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
186 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
189 const GLenum magLookup[] =
191 /* NONE POINT LINEAR */
192 GL_NEAREST, GL_NEAREST, GL_LINEAR,
195 const GLenum magLookup_noFilter[] =
197 /* NONE POINT LINEAR */
198 GL_NEAREST, GL_NEAREST, GL_NEAREST,
201 /* drawStridedSlow attributes */
202 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
203 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
204 glAttribFunc specular_func_3ubv;
205 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
206 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
207 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
210 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
211 * i.e., there is no GL Context - Get a default rendering context to enable the
212 * function query some info from GL.
215 struct wined3d_fake_gl_ctx
217 HDC dc;
218 HWND wnd;
219 HGLRC gl_ctx;
220 HDC restore_dc;
221 HGLRC restore_gl_ctx;
224 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
226 TRACE_(d3d_caps)("Destroying fake GL context.\n");
228 if (!pwglMakeCurrent(NULL, NULL))
230 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
233 if (!pwglDeleteContext(ctx->gl_ctx))
235 DWORD err = GetLastError();
236 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
239 ReleaseDC(ctx->wnd, ctx->dc);
240 DestroyWindow(ctx->wnd);
242 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
244 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
248 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
250 PIXELFORMATDESCRIPTOR pfd;
251 int iPixelFormat;
253 TRACE("getting context...\n");
255 ctx->restore_dc = pwglGetCurrentDC();
256 ctx->restore_gl_ctx = pwglGetCurrentContext();
258 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
259 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
260 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
261 if (!ctx->wnd)
263 ERR_(d3d_caps)("Failed to create a window.\n");
264 goto fail;
267 ctx->dc = GetDC(ctx->wnd);
268 if (!ctx->dc)
270 ERR_(d3d_caps)("Failed to get a DC.\n");
271 goto fail;
274 /* PixelFormat selection */
275 ZeroMemory(&pfd, sizeof(pfd));
276 pfd.nSize = sizeof(pfd);
277 pfd.nVersion = 1;
278 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
279 pfd.iPixelType = PFD_TYPE_RGBA;
280 pfd.cColorBits = 32;
281 pfd.iLayerType = PFD_MAIN_PLANE;
283 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
284 if (!iPixelFormat)
286 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
287 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
288 goto fail;
290 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
291 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
293 /* Create a GL context. */
294 ctx->gl_ctx = pwglCreateContext(ctx->dc);
295 if (!ctx->gl_ctx)
297 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
298 goto fail;
301 /* Make it the current GL context. */
302 if (!context_set_current(NULL))
304 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
307 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
309 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
310 goto fail;
313 return TRUE;
315 fail:
316 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
317 ctx->gl_ctx = NULL;
318 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
319 ctx->dc = NULL;
320 if (ctx->wnd) DestroyWindow(ctx->wnd);
321 ctx->wnd = NULL;
322 if (ctx->restore_gl_ctx && !pwglMakeCurrent(ctx->restore_dc, ctx->restore_gl_ctx))
324 ERR_(d3d_caps)("Failed to restore previous GL context.\n");
327 return FALSE;
330 /* Adjust the amount of used texture memory */
331 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram)
333 struct wined3d_adapter *adapter = D3DDevice->adapter;
335 adapter->UsedTextureRam += glram;
336 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
337 return adapter->UsedTextureRam;
340 static void wined3d_adapter_cleanup(struct wined3d_adapter *adapter)
342 HeapFree(GetProcessHeap(), 0, adapter->gl_info.gl_formats);
343 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
346 /**********************************************************
347 * IUnknown parts follows
348 **********************************************************/
350 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
354 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
355 if (IsEqualGUID(riid, &IID_IUnknown)
356 || IsEqualGUID(riid, &IID_IWineD3DBase)
357 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
358 IUnknown_AddRef(iface);
359 *ppobj = This;
360 return S_OK;
362 *ppobj = NULL;
363 return E_NOINTERFACE;
366 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
367 IWineD3DImpl *This = (IWineD3DImpl *)iface;
368 ULONG refCount = InterlockedIncrement(&This->ref);
370 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
371 return refCount;
374 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
375 IWineD3DImpl *This = (IWineD3DImpl *)iface;
376 ULONG ref;
377 TRACE("(%p) : Releasing from %d\n", This, This->ref);
378 ref = InterlockedDecrement(&This->ref);
379 if (ref == 0) {
380 unsigned int i;
382 for (i = 0; i < This->adapter_count; ++i)
384 wined3d_adapter_cleanup(&This->adapters[i]);
386 HeapFree(GetProcessHeap(), 0, This);
389 return ref;
392 /* Set the shader type for this device, depending on the given capabilities
393 * and the user preferences in wined3d_settings. */
394 static void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, int *vs_selected)
396 if (wined3d_settings.vs_mode == VS_NONE) {
397 *vs_selected = SHADER_NONE;
398 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
399 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
400 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
401 * shaders only on this card. */
402 if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2])
403 *vs_selected = SHADER_ARB;
404 else
405 *vs_selected = SHADER_GLSL;
406 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
407 *vs_selected = SHADER_ARB;
408 } else {
409 *vs_selected = SHADER_NONE;
412 if (wined3d_settings.ps_mode == PS_NONE) {
413 *ps_selected = SHADER_NONE;
414 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
415 *ps_selected = SHADER_GLSL;
416 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
417 *ps_selected = SHADER_ARB;
418 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
419 *ps_selected = SHADER_ATI;
420 } else {
421 *ps_selected = SHADER_NONE;
425 /**********************************************************
426 * IWineD3D parts follows
427 **********************************************************/
429 /* GL locking is done by the caller */
430 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
432 GLuint prog;
433 BOOL ret = FALSE;
434 const char *testcode =
435 "!!ARBvp1.0\n"
436 "PARAM C[66] = { program.env[0..65] };\n"
437 "ADDRESS A0;"
438 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
439 "ARL A0.x, zero.x;\n"
440 "MOV result.position, C[A0.x + 65];\n"
441 "END\n";
443 while(glGetError());
444 GL_EXTCALL(glGenProgramsARB(1, &prog));
445 if(!prog) {
446 ERR("Failed to create an ARB offset limit test program\n");
448 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
449 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
450 strlen(testcode), testcode));
451 if(glGetError() != 0) {
452 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
453 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
454 ret = TRUE;
455 } else TRACE("OpenGL implementation allows offsets > 63\n");
457 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
458 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
459 checkGLcall("ARB vp offset limit test cleanup");
461 return ret;
464 static DWORD ver_for_ext(GL_SupportedExt ext)
466 unsigned int i;
467 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
468 if(EXTENSION_MAP[i].extension == ext) {
469 return EXTENSION_MAP[i].version;
472 return 0;
475 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
476 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
478 if (vendor != VENDOR_ATI) return FALSE;
479 if (device == CARD_ATI_RADEON_9500) return TRUE;
480 if (device == CARD_ATI_RADEON_X700) return TRUE;
481 if (device == CARD_ATI_RADEON_X1600) return TRUE;
482 return FALSE;
485 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
486 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
488 if (vendor == VENDOR_NVIDIA)
490 if (device == CARD_NVIDIA_GEFORCEFX_5800 || device == CARD_NVIDIA_GEFORCEFX_5600)
492 return TRUE;
495 return FALSE;
498 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
499 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
501 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
502 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
503 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
505 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
506 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
507 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
508 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
509 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
510 * the chance that other implementations support them is rather small since Win32 QuickTime uses
511 * DirectDraw, not OpenGL. */
512 if (gl_info->supported[APPLE_FENCE]
513 && gl_info->supported[APPLE_CLIENT_STORAGE]
514 && gl_info->supported[APPLE_FLUSH_RENDER]
515 && gl_info->supported[APPLE_YCBCR_422])
517 return TRUE;
519 else
521 return FALSE;
525 /* Context activation is done by the caller. */
526 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
528 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
529 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
530 * all the texture. This function detects this bug by its symptom and disables PBOs
531 * if the test fails.
533 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
534 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
535 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
536 * read back is compared to the original. If they are equal PBOs are assumed to work,
537 * otherwise the PBO extension is disabled. */
538 GLuint texture, pbo;
539 static const unsigned int pattern[] =
541 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
542 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
543 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
544 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
546 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
548 /* No PBO -> No point in testing them. */
549 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
551 ENTER_GL();
553 while (glGetError());
554 glGenTextures(1, &texture);
555 glBindTexture(GL_TEXTURE_2D, texture);
557 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
558 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
559 checkGLcall("Specifying the PBO test texture");
561 GL_EXTCALL(glGenBuffersARB(1, &pbo));
562 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
563 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
564 checkGLcall("Specifying the PBO test pbo");
566 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
567 checkGLcall("Loading the PBO test texture");
569 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
570 wglFinish(); /* just to be sure */
572 memset(check, 0, sizeof(check));
573 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
574 checkGLcall("Reading back the PBO test texture");
576 glDeleteTextures(1, &texture);
577 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
578 checkGLcall("PBO test cleanup");
580 LEAVE_GL();
582 if (memcmp(check, pattern, sizeof(check)))
584 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
585 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
586 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
588 else
590 TRACE_(d3d_caps)("PBO test successful.\n");
594 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
595 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
597 return vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer, vendor, device);
600 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
601 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
603 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
604 if (vendor != VENDOR_ATI) return FALSE;
605 if (device == CARD_ATI_RADEON_X1600) return FALSE;
606 return TRUE;
609 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
610 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
612 if (vendor != VENDOR_ATI) return FALSE;
613 if (match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
614 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
615 return TRUE;
618 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
619 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
621 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
622 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
623 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
624 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
625 * hardcoded
627 * dx10 cards usually have 64 varyings */
628 return gl_info->limits.glsl_varyings > 44;
631 /* A GL context is provided by the caller */
632 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
633 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
635 GLenum error;
636 DWORD data[16];
638 if (!gl_info->supported[EXT_SECONDARY_COLOR]) return FALSE;
640 ENTER_GL();
641 while(glGetError());
642 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
643 error = glGetError();
644 LEAVE_GL();
646 if(error == GL_NO_ERROR)
648 TRACE("GL Implementation accepts 4 component specular color pointers\n");
649 return TRUE;
651 else
653 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
654 debug_glerror(error));
655 return FALSE;
659 static BOOL match_apple_nvts(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
660 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
662 if (!match_apple(gl_info, gl_renderer, vendor, device)) return FALSE;
663 return gl_info->supported[NV_TEXTURE_SHADER];
666 /* A GL context is provided by the caller */
667 static BOOL match_broken_nv_clip(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
668 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
670 GLuint prog;
671 BOOL ret = FALSE;
672 GLint pos;
673 const char *testcode =
674 "!!ARBvp1.0\n"
675 "OPTION NV_vertex_program2;\n"
676 "MOV result.clip[0], 0.0;\n"
677 "MOV result.position, 0.0;\n"
678 "END\n";
680 if (!gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]) return FALSE;
682 ENTER_GL();
683 while(glGetError());
685 GL_EXTCALL(glGenProgramsARB(1, &prog));
686 if(!prog)
688 ERR("Failed to create the NVvp clip test program\n");
689 LEAVE_GL();
690 return FALSE;
692 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
693 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
694 strlen(testcode), testcode));
695 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
696 if(pos != -1)
698 WARN("GL_NV_vertex_program2_option result.clip[] test failed\n");
699 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
700 ret = TRUE;
701 while(glGetError());
703 else TRACE("GL_NV_vertex_program2_option result.clip[] test passed\n");
705 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
706 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
707 checkGLcall("GL_NV_vertex_program2_option result.clip[] test cleanup");
709 LEAVE_GL();
710 return ret;
713 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
715 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->limits.arb_vs_native_constants);
716 gl_info->limits.glsl_vs_float_constants = gl_info->limits.arb_vs_native_constants;
717 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->limits.arb_ps_native_constants);
718 gl_info->limits.glsl_ps_float_constants = gl_info->limits.arb_ps_native_constants;
721 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
723 quirk_arb_constants(gl_info);
724 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
725 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
726 * allow 48 different offsets or other helper immediate values. */
727 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
728 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
731 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
732 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
733 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
734 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
735 * most games, but avoids the crash
737 * A more sophisticated way would be to find all units that need texture coordinates and enable
738 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
739 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
741 * Note that disabling the extension entirely does not gain predictability because there is no point
742 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
743 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
745 if (gl_info->supported[ARB_POINT_SPRITE])
747 TRACE("Limiting point sprites to one texture unit.\n");
748 gl_info->limits.point_sprite_units = 1;
752 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
754 quirk_arb_constants(gl_info);
756 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
757 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
758 * If real NP2 textures are used, the driver falls back to software. We could just remove the
759 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
760 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
761 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
762 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
764 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
765 * has this extension promoted to core. The extension loading code sets this extension supported
766 * due to that, so this code works on fglrx as well. */
767 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
769 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
770 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
771 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
774 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
775 * it is generally more efficient. Reserve just 8 constants. */
776 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
777 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
780 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
782 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
783 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
784 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
785 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
786 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
787 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
789 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
790 * triggering the software fallback. There is not much we can do here apart from disabling the
791 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
792 * in IWineD3DImpl_FillGLCaps).
793 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
794 * post-processing effects in the game "Max Payne 2").
795 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
796 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
797 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
798 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
801 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
803 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
804 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
805 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
806 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
807 * according to the spec.
809 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
810 * makes the shader slower and eats instruction slots which should be available to the d3d app.
812 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
813 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
814 * this workaround is activated on cards that do not need it, it won't break things, just affect
815 * performance negatively. */
816 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
817 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
820 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
822 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
825 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
827 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
830 static void quirk_apple_nvts(struct wined3d_gl_info *gl_info)
832 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
833 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
834 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
837 static void quirk_disable_nvvp_clip(struct wined3d_gl_info *gl_info)
839 gl_info->quirks |= WINED3D_QUIRK_NV_CLIP_BROKEN;
842 struct driver_quirk
844 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
845 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device);
846 void (*apply)(struct wined3d_gl_info *gl_info);
847 const char *description;
850 static const struct driver_quirk quirk_table[] =
853 match_ati_r300_to_500,
854 quirk_ati_dx9,
855 "ATI GLSL constant and normalized texrect quirk"
857 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
858 * used it falls back to software. While the compiler can detect if the shader uses all declared
859 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
860 * using relative addressing falls back to software.
862 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
864 match_apple,
865 quirk_apple_glsl_constants,
866 "Apple GLSL uniform override"
869 match_geforce5,
870 quirk_no_np2,
871 "Geforce 5 NP2 disable"
874 match_apple_intel,
875 quirk_texcoord_w,
876 "Init texcoord .w for Apple Intel GPU driver"
879 match_apple_nonr500ati,
880 quirk_texcoord_w,
881 "Init texcoord .w for Apple ATI >= r600 GPU driver"
884 match_fglrx,
885 quirk_one_point_sprite,
886 "Fglrx point sprite crash workaround"
889 match_dx10_capable,
890 quirk_clip_varying,
891 "Reserved varying for gl_ClipPos"
894 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
895 * GL implementations accept it. The Mac GL is the only implementation known to
896 * reject it.
898 * If we can pass 4 component specular colors, do it, because (a) we don't have
899 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
900 * passes specular alpha to the pixel shader if any is used. Otherwise the
901 * specular alpha is used to pass the fog coordinate, which we pass to opengl
902 * via GL_EXT_fog_coord.
904 match_allows_spec_alpha,
905 quirk_allows_specular_alpha,
906 "Allow specular alpha quirk"
909 /* The pixel formats provided by GL_NV_texture_shader are broken on OSX
910 * (rdar://5682521).
912 match_apple_nvts,
913 quirk_apple_nvts,
914 "Apple NV_texture_shader disable"
917 match_broken_nv_clip,
918 quirk_disable_nvvp_clip,
919 "Apple NV_vertex_program clip bug quirk"
923 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
924 * reporting a driver version is moot because we are not the Windows driver, and we have different
925 * bugs, features, etc.
927 * If a card is not found in this table, the GL driver version is reported. */
928 struct driver_version_information
930 WORD vendor; /* reported PCI card vendor ID */
931 WORD card; /* reported PCI card device ID */
932 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
933 WORD hipart_hi, hipart_lo; /* driver hiword to report */
934 WORD lopart_hi, lopart_lo; /* driver loword to report */
937 static const struct driver_version_information driver_version_table[] =
939 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
940 * 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
941 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
942 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
944 * All version numbers used below are from the Linux nvidia drivers. */
945 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
946 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
947 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
948 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
949 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
950 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 },
951 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 },
952 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 },
953 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 },
954 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 },
955 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 },
956 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 },
957 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 },
958 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 },
959 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 },
960 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 },
961 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 },
962 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 },
963 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 },
964 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 },
965 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 },
966 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 },
967 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 },
968 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 },
969 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 },
970 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 },
971 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 },
972 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 },
973 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 },
974 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 },
976 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
977 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
978 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
979 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
980 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
981 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
982 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
983 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
984 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
985 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
986 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
988 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
991 static void init_driver_info(struct wined3d_driver_info *driver_info,
992 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
994 unsigned int i;
996 if (wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
998 TRACE_(d3d_caps)("Overriding PCI vendor ID with: %04x\n", wined3d_settings.pci_vendor_id);
999 vendor = wined3d_settings.pci_vendor_id;
1001 driver_info->vendor = vendor;
1003 if (wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
1005 TRACE_(d3d_caps)("Overriding PCI device ID with: %04x\n", wined3d_settings.pci_device_id);
1006 device = wined3d_settings.pci_device_id;
1008 driver_info->device = device;
1010 switch (vendor)
1012 case VENDOR_ATI:
1013 driver_info->name = "ati2dvag.dll";
1014 break;
1016 case VENDOR_NVIDIA:
1017 driver_info->name = "nv4_disp.dll";
1018 break;
1020 default:
1021 FIXME_(d3d_caps)("Unhandled vendor %04x.\n", vendor);
1022 driver_info->name = "Display";
1023 break;
1026 driver_info->description = "Direct3D HAL";
1027 driver_info->version_high = MAKEDWORD_VERSION(7, 1);
1028 driver_info->version_low = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
1030 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
1032 if (vendor == driver_version_table[i].vendor && device == driver_version_table[i].card)
1034 TRACE_(d3d_caps)("Found card %04x:%04x in driver DB.\n", vendor, device);
1036 driver_info->description = driver_version_table[i].description;
1037 driver_info->version_high = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
1038 driver_version_table[i].hipart_lo);
1039 driver_info->version_low = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
1040 driver_version_table[i].lopart_lo);
1041 break;
1045 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08x-0x%08x.\n",
1046 driver_info->version_high, driver_info->version_low);
1049 /* Context activation is done by the caller. */
1050 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer,
1051 enum wined3d_pci_vendor vendor, enum wined3d_pci_device device)
1053 unsigned int i;
1055 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
1057 if (!quirk_table[i].match(gl_info, gl_renderer, vendor, device)) continue;
1058 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
1059 quirk_table[i].apply(gl_info);
1062 /* Find out if PBOs work as they are supposed to. */
1063 test_pbo_functionality(gl_info);
1066 static DWORD wined3d_parse_gl_version(const char *gl_version)
1068 const char *ptr = gl_version;
1069 int major, minor;
1071 major = atoi(ptr);
1072 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1074 while (isdigit(*ptr)) ++ptr;
1075 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
1077 minor = atoi(ptr);
1079 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1081 return MAKEDWORD_VERSION(major, minor);
1084 static enum wined3d_pci_vendor wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer)
1086 if (strstr(gl_vendor, "NVIDIA"))
1087 return VENDOR_NVIDIA;
1089 if (strstr(gl_vendor, "ATI"))
1090 return VENDOR_ATI;
1092 if (strstr(gl_vendor, "Intel(R)")
1093 || strstr(gl_renderer, "Intel(R)")
1094 || strstr(gl_vendor, "Intel Inc."))
1095 return VENDOR_INTEL;
1097 if (strstr(gl_vendor, "Mesa")
1098 || strstr(gl_vendor, "DRI R300 Project")
1099 || strstr(gl_vendor, "Tungsten Graphics, Inc"))
1100 return VENDOR_MESA;
1102 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor));
1104 return VENDOR_WINE;
1107 static enum wined3d_pci_device wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
1108 enum wined3d_pci_vendor *vendor, unsigned int *vidmem)
1110 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1111 * different GPUs with roughly the same features. In most cases GPUs from a
1112 * certain family differ in clockspeeds, the amount of video memory and the
1113 * number of shader pipelines.
1115 * A Direct3D device object contains the PCI id (vendor + device) of the
1116 * videocard which is used for rendering. Various applications use this
1117 * information to get a rough estimation of the features of the card and
1118 * some might use it for enabling 3d effects only on certain types of
1119 * videocards. In some cases games might even use it to work around bugs
1120 * which happen on certain videocards/driver combinations. The problem is
1121 * that OpenGL only exposes a rendering string containing the name of the
1122 * videocard and not the PCI id.
1124 * Various games depend on the PCI id, so somehow we need to provide one.
1125 * A simple option is to parse the renderer string and translate this to
1126 * the right PCI id. This is a lot of work because there are more than 200
1127 * GPUs just for Nvidia. Various cards share the same renderer string, so
1128 * the amount of code might be 'small' but there are quite a number of
1129 * exceptions which would make this a pain to maintain. Another way would
1130 * be to query the PCI id from the operating system (assuming this is the
1131 * videocard which is used for rendering which is not always the case).
1132 * This would work but it is not very portable. Second it would not work
1133 * well in, let's say, a remote X situation in which the amount of 3d
1134 * features which can be used is limited.
1136 * As said most games only use the PCI id to get an indication of the
1137 * capabilities of the card. It doesn't really matter if the given id is
1138 * the correct one if we return the id of a card with similar 3d features.
1140 * The code below checks the OpenGL capabilities of a videocard and matches
1141 * that to a certain level of Direct3D functionality. Once a card passes
1142 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1143 * least a GeforceFX. To give a better estimate we do a basic check on the
1144 * renderer string but if that won't pass we return a default card. This
1145 * way is better than maintaining a full card database as even without a
1146 * full database we can return a card with similar features. Second the
1147 * size of the database can be made quite small because when you know what
1148 * type of 3d functionality a card has, you know to which GPU family the
1149 * GPU must belong. Because of this you only have to check a small part of
1150 * the renderer string to distinguishes between different models from that
1151 * family.
1153 * The code also selects a default amount of video memory which we will
1154 * use for an estimation of the amount of free texture memory. In case of
1155 * real D3D the amount of texture memory includes video memory and system
1156 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1157 * HyperMemory). We don't know how much system memory can be addressed by
1158 * the system but we can make a reasonable estimation about the amount of
1159 * video memory. If the value is slightly wrong it doesn't matter as we
1160 * didn't include AGP-like memory which makes the amount of addressable
1161 * memory higher and second OpenGL isn't that critical it moves to system
1162 * memory behind our backs if really needed. Note that the amount of video
1163 * memory can be overruled using a registry setting. */
1165 switch (*vendor)
1167 case VENDOR_NVIDIA:
1168 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1169 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1171 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1173 /* Geforce 200 - highend */
1174 if (strstr(gl_renderer, "GTX 280")
1175 || strstr(gl_renderer, "GTX 285")
1176 || strstr(gl_renderer, "GTX 295"))
1178 *vidmem = 1024;
1179 return CARD_NVIDIA_GEFORCE_GTX280;
1182 /* Geforce 200 - midend high */
1183 if (strstr(gl_renderer, "GTX 275"))
1185 *vidmem = 896;
1186 return CARD_NVIDIA_GEFORCE_GTX275;
1189 /* Geforce 200 - midend */
1190 if (strstr(gl_renderer, "GTX 260"))
1192 *vidmem = 1024;
1193 return CARD_NVIDIA_GEFORCE_GTX260;
1196 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1197 if (strstr(gl_renderer, "9800")
1198 || strstr(gl_renderer, "GTS 150")
1199 || strstr(gl_renderer, "GTS 250"))
1201 *vidmem = 512;
1202 return CARD_NVIDIA_GEFORCE_9800GT;
1205 /* Geforce9 - midend */
1206 if (strstr(gl_renderer, "9600"))
1208 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1209 return CARD_NVIDIA_GEFORCE_9600GT;
1212 /* Geforce9 - midend low / Geforce 200 - low */
1213 if (strstr(gl_renderer, "9500")
1214 || strstr(gl_renderer, "GT 120")
1215 || strstr(gl_renderer, "GT 130"))
1217 *vidmem = 256; /* The 9500GT has 256-1024MB */
1218 return CARD_NVIDIA_GEFORCE_9500GT;
1221 /* Geforce9 - lowend */
1222 if (strstr(gl_renderer, "9400"))
1224 *vidmem = 256; /* The 9400GT has 256-1024MB */
1225 return CARD_NVIDIA_GEFORCE_9400GT;
1228 /* Geforce9 - lowend low */
1229 if (strstr(gl_renderer, "9100")
1230 || strstr(gl_renderer, "9200")
1231 || strstr(gl_renderer, "9300")
1232 || strstr(gl_renderer, "G 100"))
1234 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1235 return CARD_NVIDIA_GEFORCE_9200;
1238 /* Geforce8 - highend */
1239 if (strstr(gl_renderer, "8800"))
1241 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1242 return CARD_NVIDIA_GEFORCE_8800GTS;
1245 /* Geforce8 - midend mobile */
1246 if (strstr(gl_renderer, "8600 M"))
1248 *vidmem = 512;
1249 return CARD_NVIDIA_GEFORCE_8600MGT;
1252 /* Geforce8 - midend */
1253 if (strstr(gl_renderer, "8600")
1254 || strstr(gl_renderer, "8700"))
1256 *vidmem = 256;
1257 return CARD_NVIDIA_GEFORCE_8600GT;
1260 /* Geforce8 - lowend */
1261 if (strstr(gl_renderer, "8300")
1262 || strstr(gl_renderer, "8400")
1263 || strstr(gl_renderer, "8500"))
1265 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1266 return CARD_NVIDIA_GEFORCE_8300GS;
1269 /* Geforce7 - highend */
1270 if (strstr(gl_renderer, "7800")
1271 || strstr(gl_renderer, "7900")
1272 || strstr(gl_renderer, "7950")
1273 || strstr(gl_renderer, "Quadro FX 4")
1274 || strstr(gl_renderer, "Quadro FX 5"))
1276 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1277 return CARD_NVIDIA_GEFORCE_7800GT;
1280 /* Geforce7 midend */
1281 if (strstr(gl_renderer, "7600")
1282 || strstr(gl_renderer, "7700"))
1284 *vidmem = 256; /* The 7600 uses 256-512MB */
1285 return CARD_NVIDIA_GEFORCE_7600;
1288 /* Geforce7 lower medium */
1289 if (strstr(gl_renderer, "7400"))
1291 *vidmem = 256; /* The 7400 uses 256-512MB */
1292 return CARD_NVIDIA_GEFORCE_7400;
1295 /* Geforce7 lowend */
1296 if (strstr(gl_renderer, "7300"))
1298 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1299 return CARD_NVIDIA_GEFORCE_7300;
1302 /* Geforce6 highend */
1303 if (strstr(gl_renderer, "6800"))
1305 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1306 return CARD_NVIDIA_GEFORCE_6800;
1309 /* Geforce6 - midend */
1310 if (strstr(gl_renderer, "6600")
1311 || strstr(gl_renderer, "6610")
1312 || strstr(gl_renderer, "6700"))
1314 *vidmem = 128; /* A 6600GT has 128-256MB */
1315 return CARD_NVIDIA_GEFORCE_6600GT;
1318 /* Geforce6/7 lowend */
1319 *vidmem = 64; /* */
1320 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1323 if (WINE_D3D9_CAPABLE(gl_info))
1325 /* GeforceFX - highend */
1326 if (strstr(gl_renderer, "5800")
1327 || strstr(gl_renderer, "5900")
1328 || strstr(gl_renderer, "5950")
1329 || strstr(gl_renderer, "Quadro FX"))
1331 *vidmem = 256; /* 5800-5900 cards use 256MB */
1332 return CARD_NVIDIA_GEFORCEFX_5800;
1335 /* GeforceFX - midend */
1336 if (strstr(gl_renderer, "5600")
1337 || strstr(gl_renderer, "5650")
1338 || strstr(gl_renderer, "5700")
1339 || strstr(gl_renderer, "5750"))
1341 *vidmem = 128; /* A 5600 uses 128-256MB */
1342 return CARD_NVIDIA_GEFORCEFX_5600;
1345 /* GeforceFX - lowend */
1346 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1347 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1350 if (WINE_D3D8_CAPABLE(gl_info))
1352 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1354 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1355 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1358 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1359 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1362 if (WINE_D3D7_CAPABLE(gl_info))
1364 if (strstr(gl_renderer, "GeForce4 MX"))
1366 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1367 * early models had 32MB but most have 64MB or even 128MB. */
1368 *vidmem = 64;
1369 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1372 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1374 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1375 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1378 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1380 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1381 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1384 /* Most Geforce1 cards have 32MB, there are also some rare 16
1385 * and 64MB (Dell) models. */
1386 *vidmem = 32;
1387 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1390 if (strstr(gl_renderer, "TNT2"))
1392 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1393 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1396 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1397 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1399 case VENDOR_ATI:
1400 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1402 * Beware: renderer string do not match exact card model,
1403 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1404 if (WINE_D3D9_CAPABLE(gl_info))
1406 /* Radeon R7xx HD4800 - highend */
1407 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1408 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1409 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1410 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1411 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1413 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1414 return CARD_ATI_RADEON_HD4800;
1417 /* Radeon R740 HD4700 - midend */
1418 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1419 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1421 *vidmem = 512;
1422 return CARD_ATI_RADEON_HD4700;
1425 /* Radeon R730 HD4600 - midend */
1426 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1427 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1428 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1430 *vidmem = 512;
1431 return CARD_ATI_RADEON_HD4600;
1434 /* Radeon R710 HD4500/HD4350 - lowend */
1435 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1436 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1438 *vidmem = 256;
1439 return CARD_ATI_RADEON_HD4350;
1442 /* Radeon R6xx HD2900/HD3800 - highend */
1443 if (strstr(gl_renderer, "HD 2900")
1444 || strstr(gl_renderer, "HD 3870")
1445 || strstr(gl_renderer, "HD 3850"))
1447 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1448 return CARD_ATI_RADEON_HD2900;
1451 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1452 if (strstr(gl_renderer, "HD 2600")
1453 || strstr(gl_renderer, "HD 3830")
1454 || strstr(gl_renderer, "HD 3690")
1455 || strstr(gl_renderer, "HD 3650"))
1457 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1458 return CARD_ATI_RADEON_HD2600;
1461 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1462 if (strstr(gl_renderer, "HD 2300")
1463 || strstr(gl_renderer, "HD 2400")
1464 || strstr(gl_renderer, "HD 3470")
1465 || strstr(gl_renderer, "HD 3450")
1466 || strstr(gl_renderer, "HD 3430")
1467 || strstr(gl_renderer, "HD 3400"))
1469 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1470 return CARD_ATI_RADEON_HD2300;
1473 /* Radeon R6xx/R7xx integrated */
1474 if (strstr(gl_renderer, "HD 3100")
1475 || strstr(gl_renderer, "HD 3200")
1476 || strstr(gl_renderer, "HD 3300"))
1478 *vidmem = 128; /* 128MB */
1479 return CARD_ATI_RADEON_HD3200;
1482 /* Radeon R5xx */
1483 if (strstr(gl_renderer, "X1600")
1484 || strstr(gl_renderer, "X1650")
1485 || strstr(gl_renderer, "X1800")
1486 || strstr(gl_renderer, "X1900")
1487 || strstr(gl_renderer, "X1950"))
1489 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1490 return CARD_ATI_RADEON_X1600;
1493 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1494 if (strstr(gl_renderer, "X700")
1495 || strstr(gl_renderer, "X800")
1496 || strstr(gl_renderer, "X850")
1497 || strstr(gl_renderer, "X1300")
1498 || strstr(gl_renderer, "X1400")
1499 || strstr(gl_renderer, "X1450")
1500 || strstr(gl_renderer, "X1550"))
1502 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1503 return CARD_ATI_RADEON_X700;
1506 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1507 if (strstr(gl_renderer, "Radeon Xpress"))
1509 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1510 return CARD_ATI_RADEON_XPRESS_200M;
1513 /* Radeon R3xx */
1514 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1515 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1518 if (WINE_D3D8_CAPABLE(gl_info))
1520 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1521 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1524 if (WINE_D3D7_CAPABLE(gl_info))
1526 *vidmem = 32; /* There are models with up to 64MB */
1527 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1530 *vidmem = 16; /* There are 16-32MB models */
1531 return CARD_ATI_RAGE_128PRO;
1533 case VENDOR_INTEL:
1534 if (strstr(gl_renderer, "X3100"))
1536 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1537 *vidmem = 128;
1538 return CARD_INTEL_X3100;
1541 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1543 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1544 *vidmem = 64;
1545 return CARD_INTEL_I945GM;
1548 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1549 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1550 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1551 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1552 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1553 return CARD_INTEL_I915G;
1555 case VENDOR_MESA:
1556 case VENDOR_WINE:
1557 default:
1558 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1559 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1560 * them a good generic choice. */
1561 *vendor = VENDOR_NVIDIA;
1562 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1563 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1564 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1565 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1566 return CARD_NVIDIA_RIVA_128;
1570 /* Context activation is done by the caller. */
1571 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_driver_info *driver_info, struct wined3d_gl_info *gl_info)
1573 const char *GL_Extensions = NULL;
1574 const char *WGL_Extensions = NULL;
1575 const char *gl_string = NULL;
1576 enum wined3d_pci_vendor vendor;
1577 enum wined3d_pci_device device;
1578 GLint gl_max;
1579 GLfloat gl_floatv[2];
1580 unsigned i;
1581 HDC hdc;
1582 unsigned int vidmem=0;
1583 char *gl_renderer;
1584 DWORD gl_version;
1585 size_t len;
1587 TRACE_(d3d_caps)("(%p)\n", gl_info);
1589 ENTER_GL();
1591 gl_string = (const char *)glGetString(GL_RENDERER);
1592 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string));
1593 if (!gl_string)
1595 LEAVE_GL();
1596 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
1597 return FALSE;
1600 len = strlen(gl_string) + 1;
1601 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
1602 if (!gl_renderer)
1604 LEAVE_GL();
1605 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
1606 return FALSE;
1608 memcpy(gl_renderer, gl_string, len);
1610 gl_string = (const char *)glGetString(GL_VENDOR);
1611 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string));
1612 if (!gl_string)
1614 LEAVE_GL();
1615 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
1616 HeapFree(GetProcessHeap(), 0, gl_renderer);
1617 return FALSE;
1619 vendor = wined3d_guess_vendor(gl_string, gl_renderer);
1620 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), vendor);
1622 /* Parse the GL_VERSION field into major and minor information */
1623 gl_string = (const char *)glGetString(GL_VERSION);
1624 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string));
1625 if (!gl_string)
1627 LEAVE_GL();
1628 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1629 HeapFree(GetProcessHeap(), 0, gl_renderer);
1630 return FALSE;
1632 gl_version = wined3d_parse_gl_version(gl_string);
1635 * Initialize openGL extension related variables
1636 * with Default values
1638 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1639 gl_info->limits.buffers = 1;
1640 gl_info->limits.textures = 1;
1641 gl_info->limits.texture_stages = 1;
1642 gl_info->limits.fragment_samplers = 1;
1643 gl_info->limits.vertex_samplers = 0;
1644 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers + gl_info->limits.vertex_samplers;
1645 gl_info->limits.sampler_stages = 1;
1646 gl_info->limits.glsl_vs_float_constants = 0;
1647 gl_info->limits.glsl_ps_float_constants = 0;
1648 gl_info->limits.arb_vs_float_constants = 0;
1649 gl_info->limits.arb_vs_native_constants = 0;
1650 gl_info->limits.arb_vs_instructions = 0;
1651 gl_info->limits.arb_vs_temps = 0;
1652 gl_info->limits.arb_ps_float_constants = 0;
1653 gl_info->limits.arb_ps_local_constants = 0;
1654 gl_info->limits.arb_ps_instructions = 0;
1655 gl_info->limits.arb_ps_temps = 0;
1657 /* Retrieve opengl defaults */
1658 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1659 gl_info->limits.clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1660 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1662 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1663 gl_info->limits.lights = gl_max;
1664 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1666 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1667 gl_info->limits.texture_size = gl_max;
1668 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1670 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1671 gl_info->limits.pointsize_min = gl_floatv[0];
1672 gl_info->limits.pointsize_max = gl_floatv[1];
1673 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1675 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1676 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1677 if (!GL_Extensions)
1679 LEAVE_GL();
1680 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1681 HeapFree(GetProcessHeap(), 0, gl_renderer);
1682 return FALSE;
1685 LEAVE_GL();
1687 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1689 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1691 while (*GL_Extensions)
1693 const char *start;
1694 char current_ext[256];
1696 while (isspace(*GL_Extensions)) ++GL_Extensions;
1697 start = GL_Extensions;
1698 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1700 len = GL_Extensions - start;
1701 if (!len || len >= sizeof(current_ext)) continue;
1703 memcpy(current_ext, start, len);
1704 current_ext[len] = '\0';
1705 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
1707 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1709 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1711 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1712 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1713 break;
1718 /* Now work out what GL support this card really has */
1719 #define USE_GL_FUNC(type, pfn, ext, replace) \
1721 DWORD ver = ver_for_ext(ext); \
1722 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1723 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1724 else gl_info->pfn = NULL; \
1726 GL_EXT_FUNCS_GEN;
1727 #undef USE_GL_FUNC
1729 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1730 WGL_EXT_FUNCS_GEN;
1731 #undef USE_GL_FUNC
1733 ENTER_GL();
1735 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1736 * loading the functions, otherwise the code above will load the extension entry points instead of the
1737 * core functions, which may not work. */
1738 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1740 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1741 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1743 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1744 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1748 if (gl_info->supported[APPLE_FENCE])
1750 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1751 * The apple extension interacts with some other apple exts. Disable the NV
1752 * extension if the apple one is support to prevent confusion in other parts
1753 * of the code. */
1754 gl_info->supported[NV_FENCE] = FALSE;
1756 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1758 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1760 * The enums are the same:
1761 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1762 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1763 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1764 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1765 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1767 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1769 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1770 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1772 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1774 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1775 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1778 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1780 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1781 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1783 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
1785 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
1786 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
1788 if (gl_info->supported[NV_TEXTURE_SHADER2])
1790 if (gl_info->supported[NV_REGISTER_COMBINERS])
1792 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1793 * are supported. The nv extensions provide the same functionality as the
1794 * ATI one, and a bit more(signed pixelformats). */
1795 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1798 if (gl_info->supported[ARB_DRAW_BUFFERS])
1800 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1801 gl_info->limits.buffers = gl_max;
1802 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1804 if (gl_info->supported[ARB_MULTITEXTURE])
1806 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1807 gl_info->limits.textures = min(MAX_TEXTURES, gl_max);
1808 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->limits.textures);
1810 if (gl_info->supported[NV_REGISTER_COMBINERS])
1812 GLint tmp;
1813 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1814 gl_info->limits.texture_stages = min(MAX_TEXTURES, tmp);
1816 else
1818 gl_info->limits.texture_stages = min(MAX_TEXTURES, gl_max);
1820 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->limits.texture_stages);
1822 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1824 GLint tmp;
1825 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1826 gl_info->limits.fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1828 else
1830 gl_info->limits.fragment_samplers = max(gl_info->limits.fragment_samplers, gl_max);
1832 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->limits.fragment_samplers);
1834 if (gl_info->supported[ARB_VERTEX_SHADER])
1836 GLint tmp;
1837 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1838 gl_info->limits.vertex_samplers = tmp;
1839 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1840 gl_info->limits.combined_samplers = tmp;
1842 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1843 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1844 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1845 * shader is used with fixed function vertex processing we're fine too because fixed function
1846 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1847 * used we have to make sure that all vertex sampler setups are valid together with all
1848 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1849 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1850 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1851 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1852 * a fixed function pipeline anymore.
1854 * So this is just a check to check that our assumption holds true. If not, write a warning
1855 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1856 if (gl_info->limits.vertex_samplers && gl_info->limits.combined_samplers < 12
1857 && MAX_TEXTURES + gl_info->limits.vertex_samplers > gl_info->limits.combined_samplers)
1859 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1860 gl_info->limits.vertex_samplers, gl_info->limits.combined_samplers);
1861 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1862 if (gl_info->limits.combined_samplers > MAX_TEXTURES)
1863 gl_info->limits.vertex_samplers = gl_info->limits.combined_samplers - MAX_TEXTURES;
1864 else
1865 gl_info->limits.vertex_samplers = 0;
1868 else
1870 gl_info->limits.combined_samplers = gl_info->limits.fragment_samplers;
1872 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->limits.vertex_samplers);
1873 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->limits.combined_samplers);
1875 if (gl_info->supported[ARB_VERTEX_BLEND])
1877 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1878 gl_info->limits.blends = gl_max;
1879 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->limits.blends);
1881 if (gl_info->supported[EXT_TEXTURE3D])
1883 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1884 gl_info->limits.texture3d_size = gl_max;
1885 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->limits.texture3d_size);
1887 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1889 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1890 gl_info->limits.anisotropy = gl_max;
1891 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->limits.anisotropy);
1893 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1895 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1896 gl_info->limits.arb_ps_float_constants = gl_max;
1897 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->limits.arb_ps_float_constants);
1898 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1899 gl_info->limits.arb_ps_native_constants = gl_max;
1900 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native float constants: %d.\n",
1901 gl_info->limits.arb_ps_native_constants);
1902 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1903 gl_info->limits.arb_ps_temps = gl_max;
1904 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_ps_temps);
1905 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1906 gl_info->limits.arb_ps_instructions = gl_max;
1907 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->limits.arb_ps_instructions);
1908 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
1909 gl_info->limits.arb_ps_local_constants = gl_max;
1910 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->limits.arb_ps_instructions);
1912 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1914 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1915 gl_info->limits.arb_vs_float_constants = gl_max;
1916 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->limits.arb_vs_float_constants);
1917 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, &gl_max));
1918 gl_info->limits.arb_vs_native_constants = gl_max;
1919 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native float constants: %d.\n",
1920 gl_info->limits.arb_vs_native_constants);
1921 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1922 gl_info->limits.arb_vs_temps = gl_max;
1923 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->limits.arb_vs_temps);
1924 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1925 gl_info->limits.arb_vs_instructions = gl_max;
1926 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->limits.arb_vs_instructions);
1928 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1930 if (gl_info->supported[ARB_VERTEX_SHADER])
1932 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1933 gl_info->limits.glsl_vs_float_constants = gl_max / 4;
1934 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->limits.glsl_vs_float_constants);
1936 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1938 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1939 gl_info->limits.glsl_ps_float_constants = gl_max / 4;
1940 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->limits.glsl_ps_float_constants);
1941 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1942 gl_info->limits.glsl_varyings = gl_max;
1943 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
1945 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
1947 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->limits.shininess);
1949 else
1951 gl_info->limits.shininess = 128.0f;
1953 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1955 /* If we have full NP2 texture support, disable
1956 * GL_ARB_texture_rectangle because we will never use it.
1957 * This saves a few redundant glDisable calls. */
1958 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1960 if (gl_info->supported[ATI_FRAGMENT_SHADER])
1962 /* Disable NV_register_combiners and fragment shader if this is supported.
1963 * generally the NV extensions are preferred over the ATI ones, and this
1964 * extension is disabled if register_combiners and texture_shader2 are both
1965 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1966 * fragment processing support. */
1967 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1968 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1969 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1970 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1971 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1973 if (gl_info->supported[NV_HALF_FLOAT])
1975 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
1976 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1978 if (gl_info->supported[ARB_POINT_SPRITE])
1980 gl_info->limits.point_sprite_units = gl_info->limits.textures;
1982 else
1984 gl_info->limits.point_sprite_units = 0;
1986 checkGLcall("extension detection");
1988 LEAVE_GL();
1990 /* In some cases the number of texture stages can be larger than the number
1991 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1992 * shaders), but 8 texture stages (register combiners). */
1993 gl_info->limits.sampler_stages = max(gl_info->limits.fragment_samplers, gl_info->limits.texture_stages);
1995 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
1997 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbuffer;
1998 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbuffer;
1999 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffers;
2000 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffers;
2001 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorage;
2002 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisample;
2003 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameteriv;
2004 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebuffer;
2005 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebuffer;
2006 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffers;
2007 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffers;
2008 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatus;
2009 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1D;
2010 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2D;
2011 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3D;
2012 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbuffer;
2013 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameteriv;
2014 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebuffer;
2015 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmap;
2017 else
2019 if (gl_info->supported[EXT_FRAMEBUFFER_OBJECT])
2021 gl_info->fbo_ops.glIsRenderbuffer = gl_info->glIsRenderbufferEXT;
2022 gl_info->fbo_ops.glBindRenderbuffer = gl_info->glBindRenderbufferEXT;
2023 gl_info->fbo_ops.glDeleteRenderbuffers = gl_info->glDeleteRenderbuffersEXT;
2024 gl_info->fbo_ops.glGenRenderbuffers = gl_info->glGenRenderbuffersEXT;
2025 gl_info->fbo_ops.glRenderbufferStorage = gl_info->glRenderbufferStorageEXT;
2026 gl_info->fbo_ops.glGetRenderbufferParameteriv = gl_info->glGetRenderbufferParameterivEXT;
2027 gl_info->fbo_ops.glIsFramebuffer = gl_info->glIsFramebufferEXT;
2028 gl_info->fbo_ops.glBindFramebuffer = gl_info->glBindFramebufferEXT;
2029 gl_info->fbo_ops.glDeleteFramebuffers = gl_info->glDeleteFramebuffersEXT;
2030 gl_info->fbo_ops.glGenFramebuffers = gl_info->glGenFramebuffersEXT;
2031 gl_info->fbo_ops.glCheckFramebufferStatus = gl_info->glCheckFramebufferStatusEXT;
2032 gl_info->fbo_ops.glFramebufferTexture1D = gl_info->glFramebufferTexture1DEXT;
2033 gl_info->fbo_ops.glFramebufferTexture2D = gl_info->glFramebufferTexture2DEXT;
2034 gl_info->fbo_ops.glFramebufferTexture3D = gl_info->glFramebufferTexture3DEXT;
2035 gl_info->fbo_ops.glFramebufferRenderbuffer = gl_info->glFramebufferRenderbufferEXT;
2036 gl_info->fbo_ops.glGetFramebufferAttachmentParameteriv = gl_info->glGetFramebufferAttachmentParameterivEXT;
2037 gl_info->fbo_ops.glGenerateMipmap = gl_info->glGenerateMipmapEXT;
2039 else if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
2041 WARN_(d3d_caps)("Framebuffer objects not supported, falling back to backbuffer offscreen rendering mode.\n");
2042 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
2044 if (gl_info->supported[EXT_FRAMEBUFFER_BLIT])
2046 gl_info->fbo_ops.glBlitFramebuffer = gl_info->glBlitFramebufferEXT;
2048 if (gl_info->supported[EXT_FRAMEBUFFER_MULTISAMPLE])
2050 gl_info->fbo_ops.glRenderbufferStorageMultisample = gl_info->glRenderbufferStorageMultisampleEXT;
2054 /* MRTs are currently only supported when FBOs are used. */
2055 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
2057 gl_info->limits.buffers = 1;
2060 device = wined3d_guess_card(gl_info, gl_renderer, &vendor, &vidmem);
2061 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", vendor, device);
2063 /* If we have an estimate use it, else default to 64MB; */
2064 if(vidmem)
2065 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
2066 else
2067 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
2069 wrap_lookup[WINED3DTADDRESS_WRAP - WINED3DTADDRESS_WRAP] = GL_REPEAT;
2070 wrap_lookup[WINED3DTADDRESS_MIRROR - WINED3DTADDRESS_WRAP] =
2071 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2072 wrap_lookup[WINED3DTADDRESS_CLAMP - WINED3DTADDRESS_WRAP] = GL_CLAMP_TO_EDGE;
2073 wrap_lookup[WINED3DTADDRESS_BORDER - WINED3DTADDRESS_WRAP] =
2074 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2075 wrap_lookup[WINED3DTADDRESS_MIRRORONCE - WINED3DTADDRESS_WRAP] =
2076 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2078 /* Make sure there's an active HDC else the WGL extensions will fail */
2079 hdc = pwglGetCurrentDC();
2080 if (hdc) {
2081 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2082 if(GL_EXTCALL(wglGetExtensionsStringARB))
2083 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2085 if (NULL == WGL_Extensions) {
2086 ERR(" WGL_Extensions returns NULL\n");
2087 } else {
2088 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2089 while (*WGL_Extensions != 0x00) {
2090 const char *Start;
2091 char ThisExtn[256];
2093 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2094 Start = WGL_Extensions;
2095 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2096 WGL_Extensions++;
2099 len = WGL_Extensions - Start;
2100 if (len == 0 || len >= sizeof(ThisExtn))
2101 continue;
2103 memcpy(ThisExtn, Start, len);
2104 ThisExtn[len] = '\0';
2105 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
2107 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2108 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
2109 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2111 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2112 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2113 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2115 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2116 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2117 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2123 fixup_extensions(gl_info, gl_renderer, vendor, device);
2124 init_driver_info(driver_info, vendor, device);
2125 add_gl_compat_wrappers(gl_info);
2127 HeapFree(GetProcessHeap(), 0, gl_renderer);
2128 return TRUE;
2131 /**********************************************************
2132 * IWineD3D implementation follows
2133 **********************************************************/
2135 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2136 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2138 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2140 return This->adapter_count;
2143 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
2144 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2145 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
2146 return WINED3D_OK;
2149 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2150 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2152 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2154 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2155 return NULL;
2158 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2161 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2162 of the same bpp but different resolutions */
2164 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2165 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2166 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2167 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2169 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2170 return 0;
2173 /* TODO: Store modes per adapter and read it from the adapter structure */
2174 if (Adapter == 0) { /* Display */
2175 unsigned int i = 0;
2176 unsigned int j = 0;
2177 DEVMODEW mode;
2179 memset(&mode, 0, sizeof(mode));
2180 mode.dmSize = sizeof(mode);
2182 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2184 ++j;
2185 switch (Format)
2187 case WINED3DFMT_UNKNOWN:
2188 /* This is for D3D8, do not enumerate P8 here */
2189 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2190 break;
2192 case WINED3DFMT_B8G8R8X8_UNORM:
2193 if (mode.dmBitsPerPel == 32) ++i;
2194 break;
2196 case WINED3DFMT_B5G6R5_UNORM:
2197 if (mode.dmBitsPerPel == 16) ++i;
2198 break;
2200 case WINED3DFMT_P8_UINT:
2201 if (mode.dmBitsPerPel == 8) ++i;
2202 break;
2204 default:
2205 /* Skip other modes as they do not match the requested format */
2206 break;
2210 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2211 return i;
2212 } else {
2213 FIXME_(d3d_caps)("Adapter not primary display\n");
2215 return 0;
2218 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2219 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2220 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2221 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2223 /* Validate the parameters as much as possible */
2224 if (NULL == pMode ||
2225 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2226 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2227 return WINED3DERR_INVALIDCALL;
2230 /* TODO: Store modes per adapter and read it from the adapter structure */
2231 if (Adapter == 0)
2233 DEVMODEW DevModeW;
2234 int ModeIdx = 0;
2235 UINT i = 0;
2236 int j = 0;
2238 ZeroMemory(&DevModeW, sizeof(DevModeW));
2239 DevModeW.dmSize = sizeof(DevModeW);
2241 /* If we are filtering to a specific format (D3D9), then need to skip
2242 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2243 just count through the ones with valid bit depths */
2244 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
2245 switch (Format)
2247 case WINED3DFMT_UNKNOWN:
2248 /* This is D3D8. Do not enumerate P8 here */
2249 if (DevModeW.dmBitsPerPel == 32 ||
2250 DevModeW.dmBitsPerPel == 16) i++;
2251 break;
2252 case WINED3DFMT_B8G8R8X8_UNORM:
2253 if (DevModeW.dmBitsPerPel == 32) i++;
2254 break;
2255 case WINED3DFMT_B5G6R5_UNORM:
2256 if (DevModeW.dmBitsPerPel == 16) i++;
2257 break;
2258 case WINED3DFMT_P8_UINT:
2259 if (DevModeW.dmBitsPerPel == 8) i++;
2260 break;
2261 default:
2262 /* Modes that don't match what we support can get an early-out */
2263 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
2264 return WINED3DERR_INVALIDCALL;
2268 if (i == 0) {
2269 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2270 return WINED3DERR_INVALIDCALL;
2272 ModeIdx = j - 1;
2274 /* Now get the display mode via the calculated index */
2275 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2276 pMode->Width = DevModeW.dmPelsWidth;
2277 pMode->Height = DevModeW.dmPelsHeight;
2278 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2279 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2280 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2282 if (Format == WINED3DFMT_UNKNOWN) {
2283 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2284 } else {
2285 pMode->Format = Format;
2287 } else {
2288 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2289 return WINED3DERR_INVALIDCALL;
2292 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2293 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2294 DevModeW.dmBitsPerPel);
2297 else
2299 FIXME_(d3d_caps)("Adapter not primary display\n");
2302 return WINED3D_OK;
2305 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2306 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2307 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
2309 if (NULL == pMode ||
2310 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2311 return WINED3DERR_INVALIDCALL;
2314 if (Adapter == 0) { /* Display */
2315 int bpp = 0;
2316 DEVMODEW DevModeW;
2318 ZeroMemory(&DevModeW, sizeof(DevModeW));
2319 DevModeW.dmSize = sizeof(DevModeW);
2321 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2322 pMode->Width = DevModeW.dmPelsWidth;
2323 pMode->Height = DevModeW.dmPelsHeight;
2324 bpp = DevModeW.dmBitsPerPel;
2325 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2326 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2328 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2331 pMode->Format = pixelformat_for_depth(bpp);
2332 } else {
2333 FIXME_(d3d_caps)("Adapter not primary display\n");
2336 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2337 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2338 return WINED3D_OK;
2341 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2342 and fields being inserted in the middle, a new structure is used in place */
2343 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2344 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2345 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2346 struct wined3d_adapter *adapter;
2347 size_t len;
2349 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2351 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2352 return WINED3DERR_INVALIDCALL;
2355 adapter = &This->adapters[Adapter];
2357 /* Return the information requested */
2358 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2360 if (pIdentifier->driver_size)
2362 const char *name = adapter->driver_info.name;
2363 len = min(strlen(name), pIdentifier->driver_size - 1);
2364 memcpy(pIdentifier->driver, name, len);
2365 pIdentifier->driver[len] = '\0';
2368 if (pIdentifier->description_size)
2370 const char *description = adapter->driver_info.description;
2371 len = min(strlen(description), pIdentifier->description_size - 1);
2372 memcpy(pIdentifier->description, description, len);
2373 pIdentifier->description[len] = '\0';
2376 /* Note that d3d8 doesn't supply a device name. */
2377 if (pIdentifier->device_name_size)
2379 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2381 len = strlen(device_name);
2382 if (len >= pIdentifier->device_name_size)
2384 ERR("Device name size too small.\n");
2385 return WINED3DERR_INVALIDCALL;
2388 memcpy(pIdentifier->device_name, device_name, len);
2389 pIdentifier->device_name[len] = '\0';
2392 pIdentifier->driver_version.u.HighPart = adapter->driver_info.version_high;
2393 pIdentifier->driver_version.u.LowPart = adapter->driver_info.version_low;
2394 pIdentifier->vendor_id = adapter->driver_info.vendor;
2395 pIdentifier->device_id = adapter->driver_info.device;
2396 pIdentifier->subsystem_id = 0;
2397 pIdentifier->revision = 0;
2398 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2399 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2401 return WINED3D_OK;
2404 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2405 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2407 short redSize, greenSize, blueSize, alphaSize, colorBits;
2409 if(!cfg)
2410 return FALSE;
2412 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2413 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2415 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2416 return FALSE;
2419 if(cfg->redSize < redSize)
2420 return FALSE;
2422 if(cfg->greenSize < greenSize)
2423 return FALSE;
2425 if(cfg->blueSize < blueSize)
2426 return FALSE;
2428 if(cfg->alphaSize < alphaSize)
2429 return FALSE;
2431 return TRUE;
2432 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2433 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2434 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2435 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2436 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2437 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2438 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2439 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2440 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2441 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2442 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2443 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2444 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2445 } else {
2446 /* Probably a color index mode */
2447 return FALSE;
2450 return FALSE;
2453 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2454 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2456 short depthSize, stencilSize;
2457 BOOL lockable = FALSE;
2459 if(!cfg)
2460 return FALSE;
2462 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2464 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2465 return FALSE;
2468 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32_FLOAT))
2469 lockable = TRUE;
2471 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2472 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2473 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2474 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2475 return FALSE;
2477 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2478 * allow more stencil bits than requested. */
2479 if(cfg->stencilSize < stencilSize)
2480 return FALSE;
2482 return TRUE;
2485 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2486 WINED3DFORMAT AdapterFormat,
2487 WINED3DFORMAT RenderTargetFormat,
2488 WINED3DFORMAT DepthStencilFormat) {
2489 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2490 int nCfgs;
2491 const WineD3D_PixelFormat *cfgs;
2492 const struct wined3d_adapter *adapter;
2493 const struct GlPixelFormatDesc *rt_format_desc;
2494 const struct GlPixelFormatDesc *ds_format_desc;
2495 int it;
2497 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2498 This, Adapter,
2499 DeviceType, debug_d3ddevicetype(DeviceType),
2500 AdapterFormat, debug_d3dformat(AdapterFormat),
2501 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2502 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2504 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2505 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2506 return WINED3DERR_INVALIDCALL;
2509 adapter = &This->adapters[Adapter];
2510 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2511 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2512 cfgs = adapter->cfgs;
2513 nCfgs = adapter->nCfgs;
2514 for (it = 0; it < nCfgs; ++it) {
2515 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2517 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2519 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2520 return WINED3D_OK;
2524 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2526 return WINED3DERR_NOTAVAILABLE;
2529 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2530 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2532 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2533 const struct GlPixelFormatDesc *glDesc;
2534 const struct wined3d_adapter *adapter;
2536 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2537 This,
2538 Adapter,
2539 DeviceType, debug_d3ddevicetype(DeviceType),
2540 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2541 Windowed,
2542 MultiSampleType,
2543 pQualityLevels);
2545 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2546 return WINED3DERR_INVALIDCALL;
2549 /* TODO: handle Windowed, add more quality levels */
2551 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2552 if(pQualityLevels) *pQualityLevels = 1;
2553 return WINED3D_OK;
2556 /* By default multisampling is disabled right now as it causes issues
2557 * on some Nvidia driver versions and it doesn't work well in combination
2558 * with FBOs yet. */
2559 if(!wined3d_settings.allow_multisampling)
2560 return WINED3DERR_NOTAVAILABLE;
2562 adapter = &This->adapters[Adapter];
2563 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2564 if (!glDesc) return WINED3DERR_INVALIDCALL;
2566 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2567 int i, nCfgs;
2568 const WineD3D_PixelFormat *cfgs;
2570 cfgs = adapter->cfgs;
2571 nCfgs = adapter->nCfgs;
2572 for(i=0; i<nCfgs; i++) {
2573 if(cfgs[i].numSamples != MultiSampleType)
2574 continue;
2576 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2577 continue;
2579 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2581 if(pQualityLevels)
2582 *pQualityLevels = 1; /* Guess at a value! */
2583 return WINED3D_OK;
2586 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2587 short redSize, greenSize, blueSize, alphaSize, colorBits;
2588 int i, nCfgs;
2589 const WineD3D_PixelFormat *cfgs;
2591 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2593 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2594 return WINED3DERR_NOTAVAILABLE;
2597 cfgs = adapter->cfgs;
2598 nCfgs = adapter->nCfgs;
2599 for(i=0; i<nCfgs; i++) {
2600 if(cfgs[i].numSamples != MultiSampleType)
2601 continue;
2602 if(cfgs[i].redSize != redSize)
2603 continue;
2604 if(cfgs[i].greenSize != greenSize)
2605 continue;
2606 if(cfgs[i].blueSize != blueSize)
2607 continue;
2608 if(cfgs[i].alphaSize != alphaSize)
2609 continue;
2611 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2613 if(pQualityLevels)
2614 *pQualityLevels = 1; /* Guess at a value! */
2615 return WINED3D_OK;
2618 return WINED3DERR_NOTAVAILABLE;
2621 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2622 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2624 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2625 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2626 UINT nmodes;
2628 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2629 This,
2630 Adapter,
2631 DeviceType, debug_d3ddevicetype(DeviceType),
2632 DisplayFormat, debug_d3dformat(DisplayFormat),
2633 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2634 Windowed);
2636 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2637 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2638 return WINED3DERR_INVALIDCALL;
2641 /* The task of this function is to check whether a certain display / backbuffer format
2642 * combination is available on the given adapter. In fullscreen mode microsoft specified
2643 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2644 * and display format should match exactly.
2645 * In windowed mode format conversion can occur and this depends on the driver. When format
2646 * conversion is done, this function should nevertheless fail and applications need to use
2647 * CheckDeviceFormatConversion.
2648 * At the moment we assume that fullscreen and windowed have the same capabilities */
2650 /* There are only 4 display formats */
2651 if (!(DisplayFormat == WINED3DFMT_B5G6R5_UNORM
2652 || DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2653 || DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2654 || DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM))
2656 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2657 return WINED3DERR_NOTAVAILABLE;
2660 /* If the requested DisplayFormat is not available, don't continue */
2661 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2662 if(!nmodes) {
2663 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2664 return WINED3DERR_NOTAVAILABLE;
2667 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2668 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2669 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2670 return WINED3DERR_NOTAVAILABLE;
2673 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2674 if (DisplayFormat == WINED3DFMT_B5G6R5_UNORM && BackBufferFormat != WINED3DFMT_B5G6R5_UNORM)
2676 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2677 return WINED3DERR_NOTAVAILABLE;
2680 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2681 if (DisplayFormat == WINED3DFMT_B5G5R5X1_UNORM
2682 && !(BackBufferFormat == WINED3DFMT_B5G5R5X1_UNORM || BackBufferFormat == WINED3DFMT_B5G5R5A1_UNORM))
2684 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2685 return WINED3DERR_NOTAVAILABLE;
2688 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2689 if (DisplayFormat == WINED3DFMT_B8G8R8X8_UNORM
2690 && !(BackBufferFormat == WINED3DFMT_B8G8R8X8_UNORM || BackBufferFormat == WINED3DFMT_B8G8R8A8_UNORM))
2692 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2693 return WINED3DERR_NOTAVAILABLE;
2696 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2697 if (DisplayFormat == WINED3DFMT_B10G10R10A2_UNORM
2698 && (BackBufferFormat != WINED3DFMT_B10G10R10A2_UNORM || Windowed))
2700 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2701 return WINED3DERR_NOTAVAILABLE;
2704 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2705 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2706 if(FAILED(hr))
2707 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2709 return hr;
2713 /* Check if we support bumpmapping for a format */
2714 static BOOL CheckBumpMapCapability(struct wined3d_adapter *adapter,
2715 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2717 const struct fragment_pipeline *fp;
2719 switch(format_desc->format)
2721 case WINED3DFMT_R8G8_SNORM:
2722 case WINED3DFMT_R16G16_SNORM:
2723 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
2724 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
2725 case WINED3DFMT_R8G8B8A8_SNORM:
2726 /* Ask the fixed function pipeline implementation if it can deal
2727 * with the conversion. If we've got a GL extension giving native
2728 * support this will be an identity conversion. */
2729 fp = select_fragment_implementation(adapter, DeviceType);
2730 if (fp->color_fixup_supported(format_desc->color_fixup))
2732 TRACE_(d3d_caps)("[OK]\n");
2733 return TRUE;
2735 TRACE_(d3d_caps)("[FAILED]\n");
2736 return FALSE;
2738 default:
2739 TRACE_(d3d_caps)("[FAILED]\n");
2740 return FALSE;
2744 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2745 static BOOL CheckDepthStencilCapability(struct wined3d_adapter *adapter,
2746 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2748 int it=0;
2750 /* Only allow depth/stencil formats */
2751 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2753 /* Walk through all WGL pixel formats to find a match */
2754 for (it = 0; it < adapter->nCfgs; ++it)
2756 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2757 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2759 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2761 return TRUE;
2766 return FALSE;
2769 static BOOL CheckFilterCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2771 /* The flags entry of a format contains the filtering capability */
2772 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2774 return FALSE;
2777 /* Check the render target capabilities of a format */
2778 static BOOL CheckRenderTargetCapability(struct wined3d_adapter *adapter,
2779 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2781 /* Filter out non-RT formats */
2782 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2784 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2785 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2786 int it;
2787 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2788 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2790 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2791 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2793 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2794 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2795 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2796 TRACE_(d3d_caps)("[FAILED]\n");
2797 return FALSE;
2800 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2801 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2802 for (it = 0; it < adapter->nCfgs; ++it)
2804 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2805 &cfgs[it], check_format_desc))
2807 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2808 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2809 return TRUE;
2812 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2813 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2814 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2815 int it;
2817 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2818 for (it = 0; it < adapter->nCfgs; ++it)
2820 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2821 &cfgs[it], check_format_desc))
2823 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2824 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2825 return TRUE;
2828 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2829 /* For now return TRUE for FBOs until we have some proper checks.
2830 * Note that this function will only be called when the format is around for texturing. */
2831 return TRUE;
2833 return FALSE;
2836 static BOOL CheckSrgbReadCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2838 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2840 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2841 if (!gl_info->supported[EXT_TEXTURE_SRGB])
2843 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2844 return FALSE;
2847 switch (format_desc->format)
2849 case WINED3DFMT_B8G8R8A8_UNORM:
2850 case WINED3DFMT_B8G8R8X8_UNORM:
2851 case WINED3DFMT_B4G4R4A4_UNORM:
2852 case WINED3DFMT_L8_UNORM:
2853 case WINED3DFMT_L8A8_UNORM:
2854 case WINED3DFMT_DXT1:
2855 case WINED3DFMT_DXT2:
2856 case WINED3DFMT_DXT3:
2857 case WINED3DFMT_DXT4:
2858 case WINED3DFMT_DXT5:
2859 TRACE_(d3d_caps)("[OK]\n");
2860 return TRUE;
2862 default:
2863 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2864 return FALSE;
2866 return FALSE;
2869 static BOOL CheckSrgbWriteCapability(struct wined3d_adapter *adapter,
2870 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2872 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2873 * doing the color fixup in shaders.
2874 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2875 if ((format_desc->format == WINED3DFMT_B8G8R8X8_UNORM) || (format_desc->format == WINED3DFMT_B8G8R8A8_UNORM))
2877 int vs_selected_mode;
2878 int ps_selected_mode;
2879 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
2881 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2882 TRACE_(d3d_caps)("[OK]\n");
2883 return TRUE;
2887 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2888 return FALSE;
2891 /* Check if a format support blending in combination with pixel shaders */
2892 static BOOL CheckPostPixelShaderBlendingCapability(struct wined3d_adapter *adapter,
2893 const struct GlPixelFormatDesc *format_desc)
2895 /* The flags entry of a format contains the post pixel shader blending capability */
2896 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2898 return FALSE;
2901 static BOOL CheckWrapAndMipCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
2903 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2904 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2905 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2906 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2907 * capability anyway.
2909 * For now lets report this on all formats, but in the future we may want to
2910 * restrict it to some should games need that
2912 return TRUE;
2915 /* Check if a texture format is supported on the given adapter */
2916 static BOOL CheckTextureCapability(struct wined3d_adapter *adapter,
2917 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2919 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2920 const shader_backend_t *shader_backend;
2921 const struct fragment_pipeline *fp;
2923 switch (format_desc->format)
2925 /*****
2926 * supported: RGB(A) formats
2928 case WINED3DFMT_B8G8R8_UNORM: /* Enable for dx7, blacklisted for 8 and 9 above */
2929 case WINED3DFMT_B8G8R8A8_UNORM:
2930 case WINED3DFMT_B8G8R8X8_UNORM:
2931 case WINED3DFMT_B5G6R5_UNORM:
2932 case WINED3DFMT_B5G5R5X1_UNORM:
2933 case WINED3DFMT_B5G5R5A1_UNORM:
2934 case WINED3DFMT_B4G4R4A4_UNORM:
2935 case WINED3DFMT_A8_UNORM:
2936 case WINED3DFMT_B4G4R4X4_UNORM:
2937 case WINED3DFMT_R8G8B8A8_UNORM:
2938 case WINED3DFMT_R8G8B8X8_UNORM:
2939 case WINED3DFMT_B10G10R10A2_UNORM:
2940 case WINED3DFMT_R10G10B10A2_UNORM:
2941 case WINED3DFMT_R16G16_UNORM:
2942 TRACE_(d3d_caps)("[OK]\n");
2943 return TRUE;
2945 case WINED3DFMT_B2G3R3_UNORM:
2946 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2947 return FALSE;
2949 /*****
2950 * supported: Palettized
2952 case WINED3DFMT_P8_UINT:
2953 TRACE_(d3d_caps)("[OK]\n");
2954 return TRUE;
2955 /* No Windows driver offers WINED3DFMT_P8_UINT_A8_UNORM, so don't offer it either */
2956 case WINED3DFMT_P8_UINT_A8_UNORM:
2957 return FALSE;
2959 /*****
2960 * Supported: (Alpha)-Luminance
2962 case WINED3DFMT_L8_UNORM:
2963 case WINED3DFMT_L8A8_UNORM:
2964 case WINED3DFMT_L16_UNORM:
2965 TRACE_(d3d_caps)("[OK]\n");
2966 return TRUE;
2968 /* Not supported on Windows, thus disabled */
2969 case WINED3DFMT_L4A4_UNORM:
2970 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2971 return FALSE;
2973 /*****
2974 * Supported: Depth/Stencil formats
2976 case WINED3DFMT_D16_LOCKABLE:
2977 case WINED3DFMT_D16_UNORM:
2978 case WINED3DFMT_S1_UINT_D15_UNORM:
2979 case WINED3DFMT_X8D24_UNORM:
2980 case WINED3DFMT_S4X4_UINT_D24_UNORM:
2981 case WINED3DFMT_D24_UNORM_S8_UINT:
2982 case WINED3DFMT_S8_UINT_D24_FLOAT:
2983 case WINED3DFMT_D32_UNORM:
2984 case WINED3DFMT_D32_FLOAT:
2985 return TRUE;
2987 /*****
2988 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2989 * GL_NV_texture_shader). Emulated by shaders
2991 case WINED3DFMT_R8G8_SNORM:
2992 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
2993 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
2994 case WINED3DFMT_R8G8B8A8_SNORM:
2995 case WINED3DFMT_R16G16_SNORM:
2996 /* Ask the shader backend if it can deal with the conversion. If
2997 * we've got a GL extension giving native support this will be an
2998 * identity conversion. */
2999 shader_backend = select_shader_backend(adapter, DeviceType);
3000 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
3002 TRACE_(d3d_caps)("[OK]\n");
3003 return TRUE;
3005 TRACE_(d3d_caps)("[FAILED]\n");
3006 return FALSE;
3008 case WINED3DFMT_DXT1:
3009 case WINED3DFMT_DXT2:
3010 case WINED3DFMT_DXT3:
3011 case WINED3DFMT_DXT4:
3012 case WINED3DFMT_DXT5:
3013 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC])
3015 TRACE_(d3d_caps)("[OK]\n");
3016 return TRUE;
3018 TRACE_(d3d_caps)("[FAILED]\n");
3019 return FALSE;
3022 /*****
3023 * Odd formats - not supported
3025 case WINED3DFMT_VERTEXDATA:
3026 case WINED3DFMT_R16_UINT:
3027 case WINED3DFMT_R32_UINT:
3028 case WINED3DFMT_R16G16B16A16_SNORM:
3029 case WINED3DFMT_R10G10B10_SNORM_A2_UNORM:
3030 case WINED3DFMT_R10G11B11_SNORM:
3031 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3032 return FALSE;
3034 /*****
3035 * WINED3DFMT_R8G8_SNORM_Cx: Not supported right now
3037 case WINED3DFMT_R8G8_SNORM_Cx:
3038 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3039 return FALSE;
3041 /* YUV formats */
3042 case WINED3DFMT_UYVY:
3043 case WINED3DFMT_YUY2:
3044 if (gl_info->supported[APPLE_YCBCR_422])
3046 TRACE_(d3d_caps)("[OK]\n");
3047 return TRUE;
3049 TRACE_(d3d_caps)("[FAILED]\n");
3050 return FALSE;
3051 case WINED3DFMT_YV12:
3052 TRACE_(d3d_caps)("[FAILED]\n");
3053 return FALSE;
3055 /* Not supported */
3056 case WINED3DFMT_R16G16B16A16_UNORM:
3057 case WINED3DFMT_B2G3R3A8_UNORM:
3058 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3059 return FALSE;
3061 /* Floating point formats */
3062 case WINED3DFMT_R16_FLOAT:
3063 case WINED3DFMT_R16G16_FLOAT:
3064 case WINED3DFMT_R16G16B16A16_FLOAT:
3065 if (gl_info->supported[ARB_TEXTURE_FLOAT] && gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3067 TRACE_(d3d_caps)("[OK]\n");
3068 return TRUE;
3070 TRACE_(d3d_caps)("[FAILED]\n");
3071 return FALSE;
3073 case WINED3DFMT_R32_FLOAT:
3074 case WINED3DFMT_R32G32_FLOAT:
3075 case WINED3DFMT_R32G32B32A32_FLOAT:
3076 if (gl_info->supported[ARB_TEXTURE_FLOAT])
3078 TRACE_(d3d_caps)("[OK]\n");
3079 return TRUE;
3081 TRACE_(d3d_caps)("[FAILED]\n");
3082 return FALSE;
3084 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3085 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3086 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3087 * We can do instancing with all shader versions, but we need vertex shaders.
3089 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3090 * to enable instancing. WineD3D doesn't need that and just ignores it.
3092 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3094 case WINEMAKEFOURCC('I','N','S','T'):
3095 TRACE("ATI Instancing check hack\n");
3096 if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3098 TRACE_(d3d_caps)("[OK]\n");
3099 return TRUE;
3101 TRACE_(d3d_caps)("[FAILED]\n");
3102 return FALSE;
3104 /* Some weird FOURCC formats */
3105 case WINED3DFMT_R8G8_B8G8:
3106 case WINED3DFMT_G8R8_G8B8:
3107 case WINED3DFMT_MULTI2_ARGB8:
3108 TRACE_(d3d_caps)("[FAILED]\n");
3109 return FALSE;
3111 /* Vendor specific formats */
3112 case WINED3DFMT_ATI2N:
3113 if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC]
3114 || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3116 shader_backend = select_shader_backend(adapter, DeviceType);
3117 fp = select_fragment_implementation(adapter, DeviceType);
3118 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3119 && fp->color_fixup_supported(format_desc->color_fixup))
3121 TRACE_(d3d_caps)("[OK]\n");
3122 return TRUE;
3125 TRACE_(d3d_caps)("[OK]\n");
3126 return TRUE;
3128 TRACE_(d3d_caps)("[FAILED]\n");
3129 return FALSE;
3131 case WINED3DFMT_NVHU:
3132 case WINED3DFMT_NVHS:
3133 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3134 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3135 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3136 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3137 * Applications have to deal with not having NVHS and NVHU.
3139 TRACE_(d3d_caps)("[FAILED]\n");
3140 return FALSE;
3142 case WINED3DFMT_UNKNOWN:
3143 return FALSE;
3145 default:
3146 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3147 break;
3149 return FALSE;
3152 static BOOL CheckSurfaceCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3153 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3155 const struct blit_shader *blitter;
3157 if(SurfaceType == SURFACE_GDI) {
3158 switch(check_format_desc->format)
3160 case WINED3DFMT_B8G8R8_UNORM:
3161 case WINED3DFMT_B8G8R8A8_UNORM:
3162 case WINED3DFMT_B8G8R8X8_UNORM:
3163 case WINED3DFMT_B5G6R5_UNORM:
3164 case WINED3DFMT_B5G5R5X1_UNORM:
3165 case WINED3DFMT_B5G5R5A1_UNORM:
3166 case WINED3DFMT_B4G4R4A4_UNORM:
3167 case WINED3DFMT_B2G3R3_UNORM:
3168 case WINED3DFMT_A8_UNORM:
3169 case WINED3DFMT_B2G3R3A8_UNORM:
3170 case WINED3DFMT_B4G4R4X4_UNORM:
3171 case WINED3DFMT_R10G10B10A2_UNORM:
3172 case WINED3DFMT_R8G8B8A8_UNORM:
3173 case WINED3DFMT_R8G8B8X8_UNORM:
3174 case WINED3DFMT_R16G16_UNORM:
3175 case WINED3DFMT_B10G10R10A2_UNORM:
3176 case WINED3DFMT_R16G16B16A16_UNORM:
3177 case WINED3DFMT_P8_UINT:
3178 TRACE_(d3d_caps)("[OK]\n");
3179 return TRUE;
3180 default:
3181 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3182 return FALSE;
3186 /* All format that are supported for textures are supported for surfaces as well */
3187 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3188 /* All depth stencil formats are supported on surfaces */
3189 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3191 /* If opengl can't process the format natively, the blitter may be able to convert it */
3192 blitter = select_blit_implementation(adapter, DeviceType);
3193 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3195 TRACE_(d3d_caps)("[OK]\n");
3196 return TRUE;
3199 /* Reject other formats */
3200 TRACE_(d3d_caps)("[FAILED]\n");
3201 return FALSE;
3204 static BOOL CheckVertexTextureCapability(struct wined3d_adapter *adapter, const struct GlPixelFormatDesc *format_desc)
3206 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3208 if (!gl_info->limits.vertex_samplers)
3210 TRACE_(d3d_caps)("[FAILED]\n");
3211 return FALSE;
3214 switch (format_desc->format)
3216 case WINED3DFMT_R32G32B32A32_FLOAT:
3217 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
3219 TRACE_(d3d_caps)("[FAILED]\n");
3220 return FALSE;
3222 TRACE_(d3d_caps)("[OK]\n");
3223 return TRUE;
3225 default:
3226 TRACE_(d3d_caps)("[FAILED]\n");
3227 return FALSE;
3229 return FALSE;
3232 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3233 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3234 WINED3DSURFTYPE SurfaceType)
3236 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3237 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3238 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3239 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3240 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3241 DWORD UsageCaps = 0;
3243 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3244 This,
3245 Adapter,
3246 DeviceType, debug_d3ddevicetype(DeviceType),
3247 AdapterFormat, debug_d3dformat(AdapterFormat),
3248 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3249 RType, debug_d3dresourcetype(RType),
3250 CheckFormat, debug_d3dformat(CheckFormat));
3252 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3253 return WINED3DERR_INVALIDCALL;
3256 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3258 if(SurfaceType != SURFACE_OPENGL) {
3259 TRACE("[FAILED]\n");
3260 return WINED3DERR_NOTAVAILABLE;
3263 /* Cubetexture allows:
3264 * - D3DUSAGE_AUTOGENMIPMAP
3265 * - D3DUSAGE_DEPTHSTENCIL
3266 * - D3DUSAGE_DYNAMIC
3267 * - D3DUSAGE_NONSECURE (d3d9ex)
3268 * - D3DUSAGE_RENDERTARGET
3269 * - D3DUSAGE_SOFTWAREPROCESSING
3270 * - D3DUSAGE_QUERY_WRAPANDMIP
3272 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3274 /* Check if the texture format is around */
3275 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3277 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3278 /* Check for automatic mipmap generation support */
3279 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3281 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3282 } else {
3283 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3284 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3288 /* Always report dynamic locking */
3289 if(Usage & WINED3DUSAGE_DYNAMIC)
3290 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3292 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3293 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3295 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3296 } else {
3297 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3298 return WINED3DERR_NOTAVAILABLE;
3302 /* Always report software processing */
3303 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3304 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3306 /* Check QUERY_FILTER support */
3307 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3308 if (CheckFilterCapability(adapter, format_desc))
3310 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3311 } else {
3312 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3313 return WINED3DERR_NOTAVAILABLE;
3317 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3318 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3319 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3321 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3322 } else {
3323 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3324 return WINED3DERR_NOTAVAILABLE;
3328 /* Check QUERY_SRGBREAD support */
3329 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3330 if (CheckSrgbReadCapability(adapter, format_desc))
3332 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3333 } else {
3334 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3335 return WINED3DERR_NOTAVAILABLE;
3339 /* Check QUERY_SRGBWRITE support */
3340 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3341 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3343 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3344 } else {
3345 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3346 return WINED3DERR_NOTAVAILABLE;
3350 /* Check QUERY_VERTEXTEXTURE support */
3351 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3352 if (CheckVertexTextureCapability(adapter, format_desc))
3354 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3355 } else {
3356 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3357 return WINED3DERR_NOTAVAILABLE;
3361 /* Check QUERY_WRAPANDMIP support */
3362 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3363 if (CheckWrapAndMipCapability(adapter, format_desc))
3365 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3366 } else {
3367 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3368 return WINED3DERR_NOTAVAILABLE;
3371 } else {
3372 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3373 return WINED3DERR_NOTAVAILABLE;
3375 } else {
3376 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3377 return WINED3DERR_NOTAVAILABLE;
3379 } else if(RType == WINED3DRTYPE_SURFACE) {
3380 /* Surface allows:
3381 * - D3DUSAGE_DEPTHSTENCIL
3382 * - D3DUSAGE_NONSECURE (d3d9ex)
3383 * - D3DUSAGE_RENDERTARGET
3386 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3388 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3389 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3391 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3392 } else {
3393 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3394 return WINED3DERR_NOTAVAILABLE;
3398 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3399 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3401 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3402 } else {
3403 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3404 return WINED3DERR_NOTAVAILABLE;
3408 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3409 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3410 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3412 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3413 } else {
3414 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3415 return WINED3DERR_NOTAVAILABLE;
3418 } else {
3419 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3420 return WINED3DERR_NOTAVAILABLE;
3423 } else if(RType == WINED3DRTYPE_TEXTURE) {
3424 /* Texture allows:
3425 * - D3DUSAGE_AUTOGENMIPMAP
3426 * - D3DUSAGE_DEPTHSTENCIL
3427 * - D3DUSAGE_DMAP
3428 * - D3DUSAGE_DYNAMIC
3429 * - D3DUSAGE_NONSECURE (d3d9ex)
3430 * - D3DUSAGE_RENDERTARGET
3431 * - D3DUSAGE_SOFTWAREPROCESSING
3432 * - D3DUSAGE_TEXTAPI (d3d9ex)
3433 * - D3DUSAGE_QUERY_WRAPANDMIP
3436 if(SurfaceType != SURFACE_OPENGL) {
3437 TRACE("[FAILED]\n");
3438 return WINED3DERR_NOTAVAILABLE;
3441 /* Check if the texture format is around */
3442 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3444 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3445 /* Check for automatic mipmap generation support */
3446 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3448 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3449 } else {
3450 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3451 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3455 /* Always report dynamic locking */
3456 if(Usage & WINED3DUSAGE_DYNAMIC)
3457 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3459 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3460 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3462 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3463 } else {
3464 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3465 return WINED3DERR_NOTAVAILABLE;
3469 /* Always report software processing */
3470 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3471 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3473 /* Check QUERY_FILTER support */
3474 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3475 if (CheckFilterCapability(adapter, format_desc))
3477 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3478 } else {
3479 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3480 return WINED3DERR_NOTAVAILABLE;
3484 /* Check QUERY_LEGACYBUMPMAP support */
3485 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3486 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3488 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3489 } else {
3490 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3491 return WINED3DERR_NOTAVAILABLE;
3495 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3496 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3497 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3499 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3500 } else {
3501 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3502 return WINED3DERR_NOTAVAILABLE;
3506 /* Check QUERY_SRGBREAD support */
3507 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3508 if (CheckSrgbReadCapability(adapter, format_desc))
3510 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3511 } else {
3512 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3513 return WINED3DERR_NOTAVAILABLE;
3517 /* Check QUERY_SRGBWRITE support */
3518 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3519 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3521 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3522 } else {
3523 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3524 return WINED3DERR_NOTAVAILABLE;
3528 /* Check QUERY_VERTEXTEXTURE support */
3529 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3530 if (CheckVertexTextureCapability(adapter, format_desc))
3532 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3533 } else {
3534 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3535 return WINED3DERR_NOTAVAILABLE;
3539 /* Check QUERY_WRAPANDMIP support */
3540 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3541 if (CheckWrapAndMipCapability(adapter, format_desc))
3543 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3544 } else {
3545 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3546 return WINED3DERR_NOTAVAILABLE;
3550 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3551 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3553 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3554 } else {
3555 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3556 return WINED3DERR_NOTAVAILABLE;
3559 } else {
3560 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3561 return WINED3DERR_NOTAVAILABLE;
3563 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3564 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3565 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3567 * Volumetexture allows:
3568 * - D3DUSAGE_DYNAMIC
3569 * - D3DUSAGE_NONSECURE (d3d9ex)
3570 * - D3DUSAGE_SOFTWAREPROCESSING
3571 * - D3DUSAGE_QUERY_WRAPANDMIP
3574 if(SurfaceType != SURFACE_OPENGL) {
3575 TRACE("[FAILED]\n");
3576 return WINED3DERR_NOTAVAILABLE;
3579 /* Check volume texture and volume usage caps */
3580 if (gl_info->supported[EXT_TEXTURE3D])
3582 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3584 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3585 return WINED3DERR_NOTAVAILABLE;
3588 /* Always report dynamic locking */
3589 if(Usage & WINED3DUSAGE_DYNAMIC)
3590 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3592 /* Always report software processing */
3593 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3594 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3596 /* Check QUERY_FILTER support */
3597 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3598 if (CheckFilterCapability(adapter, format_desc))
3600 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3601 } else {
3602 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3603 return WINED3DERR_NOTAVAILABLE;
3607 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3608 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3609 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3611 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3612 } else {
3613 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3614 return WINED3DERR_NOTAVAILABLE;
3618 /* Check QUERY_SRGBREAD support */
3619 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3620 if (CheckSrgbReadCapability(adapter, format_desc))
3622 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3623 } else {
3624 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3625 return WINED3DERR_NOTAVAILABLE;
3629 /* Check QUERY_SRGBWRITE support */
3630 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3631 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3633 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3634 } else {
3635 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3636 return WINED3DERR_NOTAVAILABLE;
3640 /* Check QUERY_VERTEXTEXTURE support */
3641 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3642 if (CheckVertexTextureCapability(adapter, format_desc))
3644 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3645 } else {
3646 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3647 return WINED3DERR_NOTAVAILABLE;
3651 /* Check QUERY_WRAPANDMIP support */
3652 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3653 if (CheckWrapAndMipCapability(adapter, format_desc))
3655 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3656 } else {
3657 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3658 return WINED3DERR_NOTAVAILABLE;
3661 } else {
3662 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3663 return WINED3DERR_NOTAVAILABLE;
3666 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3667 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3668 * app needing one of those formats, don't advertize them to avoid leading apps into
3669 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3670 * except of R32F.
3672 switch(CheckFormat) {
3673 case WINED3DFMT_P8_UINT:
3674 case WINED3DFMT_L4A4_UNORM:
3675 case WINED3DFMT_R32_FLOAT:
3676 case WINED3DFMT_R16_FLOAT:
3677 case WINED3DFMT_R8G8_SNORM_L8X8_UNORM:
3678 case WINED3DFMT_R5G5_SNORM_L6_UNORM:
3679 case WINED3DFMT_R16G16_UNORM:
3680 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3681 return WINED3DERR_NOTAVAILABLE;
3683 case WINED3DFMT_R8G8B8A8_SNORM:
3684 case WINED3DFMT_R16G16_SNORM:
3685 if (!gl_info->supported[NV_TEXTURE_SHADER])
3687 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3688 return WINED3DERR_NOTAVAILABLE;
3690 break;
3692 case WINED3DFMT_R8G8_SNORM:
3693 if (!gl_info->supported[NV_TEXTURE_SHADER])
3695 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3696 return WINED3DERR_NOTAVAILABLE;
3698 break;
3700 case WINED3DFMT_DXT1:
3701 case WINED3DFMT_DXT2:
3702 case WINED3DFMT_DXT3:
3703 case WINED3DFMT_DXT4:
3704 case WINED3DFMT_DXT5:
3705 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3706 * compressed texture results in an error. While the D3D refrast does
3707 * support s3tc volumes, at least the nvidia windows driver does not, so
3708 * we're free not to support this format.
3710 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3711 return WINED3DERR_NOTAVAILABLE;
3713 default:
3714 /* Do nothing, continue with checking the format below */
3715 break;
3717 } else if(RType == WINED3DRTYPE_BUFFER){
3718 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3719 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3720 return WINED3DERR_NOTAVAILABLE;
3723 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3724 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3725 * usage flags match. */
3726 if(UsageCaps == Usage) {
3727 return WINED3D_OK;
3728 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3729 return WINED3DOK_NOAUTOGEN;
3730 } else {
3731 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);
3732 return WINED3DERR_NOTAVAILABLE;
3736 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3737 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3738 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3740 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3741 This,
3742 Adapter,
3743 DeviceType, debug_d3ddevicetype(DeviceType),
3744 SourceFormat, debug_d3dformat(SourceFormat),
3745 TargetFormat, debug_d3dformat(TargetFormat));
3746 return WINED3D_OK;
3749 static const shader_backend_t *select_shader_backend(struct wined3d_adapter *adapter, WINED3DDEVTYPE DeviceType)
3751 const shader_backend_t *ret;
3752 int vs_selected_mode;
3753 int ps_selected_mode;
3755 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3756 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3757 ret = &glsl_shader_backend;
3758 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3759 ret = &arb_program_shader_backend;
3760 } else {
3761 ret = &none_shader_backend;
3763 return ret;
3766 static const struct fragment_pipeline *select_fragment_implementation(struct wined3d_adapter *adapter,
3767 WINED3DDEVTYPE DeviceType)
3769 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3770 int vs_selected_mode;
3771 int ps_selected_mode;
3773 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3774 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
3775 && gl_info->supported[ARB_FRAGMENT_PROGRAM])
3777 return &arbfp_fragment_pipeline;
3779 else if (ps_selected_mode == SHADER_ATI)
3781 return &atifs_fragment_pipeline;
3783 else if (gl_info->supported[NV_REGISTER_COMBINERS] && gl_info->supported[NV_TEXTURE_SHADER2])
3785 return &nvts_fragment_pipeline;
3787 else if (gl_info->supported[NV_REGISTER_COMBINERS])
3789 return &nvrc_fragment_pipeline;
3791 else
3793 return &ffp_fragment_pipeline;
3797 static const struct blit_shader *select_blit_implementation(struct wined3d_adapter *adapter, WINED3DDEVTYPE DeviceType)
3799 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3800 int vs_selected_mode;
3801 int ps_selected_mode;
3803 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3804 if ((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL)
3805 && gl_info->supported[ARB_FRAGMENT_PROGRAM])
3807 return &arbfp_blit;
3809 else
3811 return &ffp_blit;
3815 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3816 subset of a D3DCAPS9 structure. However, it has to come via a void *
3817 as the d3d8 interface cannot import the d3d9 header */
3818 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3820 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3821 struct wined3d_adapter *adapter = &This->adapters[Adapter];
3822 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3823 int vs_selected_mode;
3824 int ps_selected_mode;
3825 struct shader_caps shader_caps;
3826 struct fragment_caps fragment_caps;
3827 const shader_backend_t *shader_backend;
3828 const struct fragment_pipeline *frag_pipeline = NULL;
3829 DWORD ckey_caps, blit_caps, fx_caps;
3831 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3833 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3834 return WINED3DERR_INVALIDCALL;
3837 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
3839 /* ------------------------------------------------
3840 The following fields apply to both d3d8 and d3d9
3841 ------------------------------------------------ */
3842 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3843 pCaps->AdapterOrdinal = Adapter;
3845 pCaps->Caps = 0;
3846 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3847 WINED3DCAPS2_FULLSCREENGAMMA |
3848 WINED3DCAPS2_DYNAMICTEXTURES;
3849 if (gl_info->supported[SGIS_GENERATE_MIPMAP])
3851 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3854 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3855 WINED3DCAPS3_COPY_TO_VIDMEM |
3856 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3858 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3859 WINED3DPRESENT_INTERVAL_ONE;
3861 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3862 WINED3DCURSORCAPS_LOWRES;
3864 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3865 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3866 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3867 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3868 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3869 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3870 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3871 WINED3DDEVCAPS_PUREDEVICE |
3872 WINED3DDEVCAPS_HWRASTERIZATION |
3873 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3874 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3875 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3876 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3877 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3878 WINED3DDEVCAPS_RTPATCHES;
3880 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3881 WINED3DPMISCCAPS_CULLCCW |
3882 WINED3DPMISCCAPS_CULLCW |
3883 WINED3DPMISCCAPS_COLORWRITEENABLE |
3884 WINED3DPMISCCAPS_CLIPTLVERTS |
3885 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3886 WINED3DPMISCCAPS_MASKZ |
3887 WINED3DPMISCCAPS_BLENDOP |
3888 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3889 /* TODO:
3890 WINED3DPMISCCAPS_NULLREFERENCE
3891 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3892 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3893 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3894 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3896 if (gl_info->supported[EXT_BLEND_EQUATION_SEPARATE] && gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
3897 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3899 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3900 WINED3DPRASTERCAPS_PAT |
3901 WINED3DPRASTERCAPS_WFOG |
3902 WINED3DPRASTERCAPS_ZFOG |
3903 WINED3DPRASTERCAPS_FOGVERTEX |
3904 WINED3DPRASTERCAPS_FOGTABLE |
3905 WINED3DPRASTERCAPS_STIPPLE |
3906 WINED3DPRASTERCAPS_SUBPIXEL |
3907 WINED3DPRASTERCAPS_ZTEST |
3908 WINED3DPRASTERCAPS_SCISSORTEST |
3909 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3910 WINED3DPRASTERCAPS_DEPTHBIAS;
3912 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
3914 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3915 WINED3DPRASTERCAPS_ZBIAS |
3916 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3918 if (gl_info->supported[NV_FOG_DISTANCE])
3920 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3922 /* FIXME Add:
3923 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3924 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3925 WINED3DPRASTERCAPS_ANTIALIASEDGES
3926 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3927 WINED3DPRASTERCAPS_WBUFFER */
3929 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3930 WINED3DPCMPCAPS_EQUAL |
3931 WINED3DPCMPCAPS_GREATER |
3932 WINED3DPCMPCAPS_GREATEREQUAL |
3933 WINED3DPCMPCAPS_LESS |
3934 WINED3DPCMPCAPS_LESSEQUAL |
3935 WINED3DPCMPCAPS_NEVER |
3936 WINED3DPCMPCAPS_NOTEQUAL;
3938 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3939 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3940 WINED3DPBLENDCAPS_DESTALPHA |
3941 WINED3DPBLENDCAPS_DESTCOLOR |
3942 WINED3DPBLENDCAPS_INVDESTALPHA |
3943 WINED3DPBLENDCAPS_INVDESTCOLOR |
3944 WINED3DPBLENDCAPS_INVSRCALPHA |
3945 WINED3DPBLENDCAPS_INVSRCCOLOR |
3946 WINED3DPBLENDCAPS_ONE |
3947 WINED3DPBLENDCAPS_SRCALPHA |
3948 WINED3DPBLENDCAPS_SRCALPHASAT |
3949 WINED3DPBLENDCAPS_SRCCOLOR |
3950 WINED3DPBLENDCAPS_ZERO;
3952 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3953 WINED3DPBLENDCAPS_DESTCOLOR |
3954 WINED3DPBLENDCAPS_INVDESTALPHA |
3955 WINED3DPBLENDCAPS_INVDESTCOLOR |
3956 WINED3DPBLENDCAPS_INVSRCALPHA |
3957 WINED3DPBLENDCAPS_INVSRCCOLOR |
3958 WINED3DPBLENDCAPS_ONE |
3959 WINED3DPBLENDCAPS_SRCALPHA |
3960 WINED3DPBLENDCAPS_SRCCOLOR |
3961 WINED3DPBLENDCAPS_ZERO;
3962 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3963 * according to the glBlendFunc manpage
3965 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3966 * legacy settings for srcblend only
3969 if (gl_info->supported[EXT_BLEND_COLOR])
3971 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3972 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3976 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3977 WINED3DPCMPCAPS_EQUAL |
3978 WINED3DPCMPCAPS_GREATER |
3979 WINED3DPCMPCAPS_GREATEREQUAL |
3980 WINED3DPCMPCAPS_LESS |
3981 WINED3DPCMPCAPS_LESSEQUAL |
3982 WINED3DPCMPCAPS_NEVER |
3983 WINED3DPCMPCAPS_NOTEQUAL;
3985 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3986 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3987 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3988 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3989 WINED3DPSHADECAPS_COLORFLATRGB |
3990 WINED3DPSHADECAPS_FOGFLAT |
3991 WINED3DPSHADECAPS_FOGGOURAUD |
3992 WINED3DPSHADECAPS_SPECULARFLATRGB;
3994 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3995 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3996 WINED3DPTEXTURECAPS_TRANSPARENCY |
3997 WINED3DPTEXTURECAPS_BORDER |
3998 WINED3DPTEXTURECAPS_MIPMAP |
3999 WINED3DPTEXTURECAPS_PROJECTED |
4000 WINED3DPTEXTURECAPS_PERSPECTIVE;
4002 if (!gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
4004 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
4005 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
4008 if (gl_info->supported[EXT_TEXTURE3D])
4010 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
4011 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
4012 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
4015 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4017 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
4018 WINED3DPTEXTURECAPS_MIPCUBEMAP |
4019 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
4023 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4024 WINED3DPTFILTERCAPS_MAGFPOINT |
4025 WINED3DPTFILTERCAPS_MINFLINEAR |
4026 WINED3DPTFILTERCAPS_MINFPOINT |
4027 WINED3DPTFILTERCAPS_MIPFLINEAR |
4028 WINED3DPTFILTERCAPS_MIPFPOINT |
4029 WINED3DPTFILTERCAPS_LINEAR |
4030 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4031 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4032 WINED3DPTFILTERCAPS_MIPLINEAR |
4033 WINED3DPTFILTERCAPS_MIPNEAREST |
4034 WINED3DPTFILTERCAPS_NEAREST;
4036 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4038 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4039 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4042 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
4044 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4045 WINED3DPTFILTERCAPS_MAGFPOINT |
4046 WINED3DPTFILTERCAPS_MINFLINEAR |
4047 WINED3DPTFILTERCAPS_MINFPOINT |
4048 WINED3DPTFILTERCAPS_MIPFLINEAR |
4049 WINED3DPTFILTERCAPS_MIPFPOINT |
4050 WINED3DPTFILTERCAPS_LINEAR |
4051 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4052 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4053 WINED3DPTFILTERCAPS_MIPLINEAR |
4054 WINED3DPTFILTERCAPS_MIPNEAREST |
4055 WINED3DPTFILTERCAPS_NEAREST;
4057 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
4059 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
4060 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
4062 } else
4063 pCaps->CubeTextureFilterCaps = 0;
4065 if (gl_info->supported[EXT_TEXTURE3D])
4067 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
4068 WINED3DPTFILTERCAPS_MAGFPOINT |
4069 WINED3DPTFILTERCAPS_MINFLINEAR |
4070 WINED3DPTFILTERCAPS_MINFPOINT |
4071 WINED3DPTFILTERCAPS_MIPFLINEAR |
4072 WINED3DPTFILTERCAPS_MIPFPOINT |
4073 WINED3DPTFILTERCAPS_LINEAR |
4074 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
4075 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4076 WINED3DPTFILTERCAPS_MIPLINEAR |
4077 WINED3DPTFILTERCAPS_MIPNEAREST |
4078 WINED3DPTFILTERCAPS_NEAREST;
4079 } else
4080 pCaps->VolumeTextureFilterCaps = 0;
4082 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4083 WINED3DPTADDRESSCAPS_CLAMP |
4084 WINED3DPTADDRESSCAPS_WRAP;
4086 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4088 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4090 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4092 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4094 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4096 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4099 if (gl_info->supported[EXT_TEXTURE3D])
4101 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4102 WINED3DPTADDRESSCAPS_CLAMP |
4103 WINED3DPTADDRESSCAPS_WRAP;
4104 if (gl_info->supported[ARB_TEXTURE_BORDER_CLAMP])
4106 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4108 if (gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT])
4110 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4112 if (gl_info->supported[ATI_TEXTURE_MIRROR_ONCE])
4114 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4116 } else
4117 pCaps->VolumeTextureAddressCaps = 0;
4119 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4120 WINED3DLINECAPS_ZTEST |
4121 WINED3DLINECAPS_BLEND |
4122 WINED3DLINECAPS_ALPHACMP |
4123 WINED3DLINECAPS_FOG;
4124 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4125 * idea how generating the smoothing alpha values works; the result is different
4128 pCaps->MaxTextureWidth = gl_info->limits.texture_size;
4129 pCaps->MaxTextureHeight = gl_info->limits.texture_size;
4131 if (gl_info->supported[EXT_TEXTURE3D])
4132 pCaps->MaxVolumeExtent = gl_info->limits.texture3d_size;
4133 else
4134 pCaps->MaxVolumeExtent = 0;
4136 pCaps->MaxTextureRepeat = 32768;
4137 pCaps->MaxTextureAspectRatio = gl_info->limits.texture_size;
4138 pCaps->MaxVertexW = 1.0f;
4140 pCaps->GuardBandLeft = 0.0f;
4141 pCaps->GuardBandTop = 0.0f;
4142 pCaps->GuardBandRight = 0.0f;
4143 pCaps->GuardBandBottom = 0.0f;
4145 pCaps->ExtentsAdjust = 0.0f;
4147 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4148 WINED3DSTENCILCAPS_INCRSAT |
4149 WINED3DSTENCILCAPS_INVERT |
4150 WINED3DSTENCILCAPS_KEEP |
4151 WINED3DSTENCILCAPS_REPLACE |
4152 WINED3DSTENCILCAPS_ZERO;
4153 if (gl_info->supported[EXT_STENCIL_WRAP])
4155 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4156 WINED3DSTENCILCAPS_INCR;
4158 if (gl_info->supported[EXT_STENCIL_TWO_SIDE] || gl_info->supported[ATI_SEPARATE_STENCIL])
4160 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4163 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4165 pCaps->MaxUserClipPlanes = gl_info->limits.clipplanes;
4166 pCaps->MaxActiveLights = gl_info->limits.lights;
4168 pCaps->MaxVertexBlendMatrices = gl_info->limits.blends;
4169 pCaps->MaxVertexBlendMatrixIndex = 0;
4171 pCaps->MaxAnisotropy = gl_info->limits.anisotropy;
4172 pCaps->MaxPointSize = gl_info->limits.pointsize_max;
4175 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4176 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4177 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4178 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4179 WINED3DVTXPCAPS_LOCALVIEWER |
4180 WINED3DVTXPCAPS_VERTEXFOG |
4181 WINED3DVTXPCAPS_TEXGEN;
4183 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4184 pCaps->MaxVertexIndex = 0xFFFFF;
4185 pCaps->MaxStreams = MAX_STREAMS;
4186 pCaps->MaxStreamStride = 1024;
4188 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4189 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4190 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4191 pCaps->MaxNpatchTessellationLevel = 0;
4192 pCaps->MasterAdapterOrdinal = 0;
4193 pCaps->AdapterOrdinalInGroup = 0;
4194 pCaps->NumberOfAdaptersInGroup = 1;
4196 pCaps->NumSimultaneousRTs = gl_info->limits.buffers;
4198 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4199 WINED3DPTFILTERCAPS_MAGFPOINT |
4200 WINED3DPTFILTERCAPS_MINFLINEAR |
4201 WINED3DPTFILTERCAPS_MAGFLINEAR;
4202 pCaps->VertexTextureFilterCaps = 0;
4204 memset(&shader_caps, 0, sizeof(shader_caps));
4205 shader_backend = select_shader_backend(adapter, DeviceType);
4206 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4208 memset(&fragment_caps, 0, sizeof(fragment_caps));
4209 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4210 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4212 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4213 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4215 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4216 * Ignore shader model capabilities if disabled in config
4218 if(vs_selected_mode == SHADER_NONE) {
4219 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4220 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4221 pCaps->MaxVertexShaderConst = 0;
4222 } else {
4223 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4224 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4227 if(ps_selected_mode == SHADER_NONE) {
4228 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4229 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4230 pCaps->PixelShader1xMaxValue = 0.0f;
4231 } else {
4232 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4233 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4236 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4237 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4238 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4240 pCaps->VS20Caps = shader_caps.VS20Caps;
4241 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4242 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4243 pCaps->PS20Caps = shader_caps.PS20Caps;
4244 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4245 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4247 /* The following caps are shader specific, but they are things we cannot detect, or which
4248 * are the same among all shader models. So to avoid code duplication set the shader version
4249 * specific, but otherwise constant caps here
4251 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4252 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4253 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4254 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4255 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4256 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_vs_temps);
4257 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4259 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4260 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.limits.arb_vs_instructions);
4262 else if (pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0))
4264 pCaps->VS20Caps.Caps = 0;
4265 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4266 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_vs_temps);
4267 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4269 pCaps->MaxVShaderInstructionsExecuted = 65535;
4270 pCaps->MaxVertexShader30InstructionSlots = 0;
4271 } else { /* VS 1.x */
4272 pCaps->VS20Caps.Caps = 0;
4273 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4274 pCaps->VS20Caps.NumTemps = 0;
4275 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4277 pCaps->MaxVShaderInstructionsExecuted = 0;
4278 pCaps->MaxVertexShader30InstructionSlots = 0;
4281 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4282 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4283 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4285 /* 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 */
4286 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4287 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4288 WINED3DPS20CAPS_PREDICATION |
4289 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4290 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4291 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4292 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.limits.arb_ps_temps);
4293 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4294 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4296 pCaps->MaxPShaderInstructionsExecuted = 65535;
4297 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS,
4298 adapter->gl_info.limits.arb_ps_instructions);
4300 else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0))
4302 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4303 pCaps->PS20Caps.Caps = 0;
4304 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4305 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.limits.arb_ps_temps);
4306 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4307 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4309 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4310 pCaps->MaxPixelShader30InstructionSlots = 0;
4311 } else { /* PS 1.x */
4312 pCaps->PS20Caps.Caps = 0;
4313 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4314 pCaps->PS20Caps.NumTemps = 0;
4315 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4316 pCaps->PS20Caps.NumInstructionSlots = 0;
4318 pCaps->MaxPShaderInstructionsExecuted = 0;
4319 pCaps->MaxPixelShader30InstructionSlots = 0;
4322 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4323 /* OpenGL supports all the formats below, perhaps not always
4324 * without conversion, but it supports them.
4325 * Further GLSL doesn't seem to have an official unsigned type so
4326 * don't advertise it yet as I'm not sure how we handle it.
4327 * We might need to add some clamping in the shader engine to
4328 * support it.
4329 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4330 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4331 WINED3DDTCAPS_UBYTE4N |
4332 WINED3DDTCAPS_SHORT2N |
4333 WINED3DDTCAPS_SHORT4N;
4334 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
4336 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4337 WINED3DDTCAPS_FLOAT16_4;
4339 } else
4340 pCaps->DeclTypes = 0;
4342 /* Set DirectDraw helper Caps */
4343 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4344 WINEDDCKEYCAPS_SRCBLT;
4345 fx_caps = WINEDDFXCAPS_BLTALPHA |
4346 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4347 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4348 WINEDDFXCAPS_BLTROTATION90 |
4349 WINEDDFXCAPS_BLTSHRINKX |
4350 WINEDDFXCAPS_BLTSHRINKXN |
4351 WINEDDFXCAPS_BLTSHRINKY |
4352 WINEDDFXCAPS_BLTSHRINKXN |
4353 WINEDDFXCAPS_BLTSTRETCHX |
4354 WINEDDFXCAPS_BLTSTRETCHXN |
4355 WINEDDFXCAPS_BLTSTRETCHY |
4356 WINEDDFXCAPS_BLTSTRETCHYN;
4357 blit_caps = WINEDDCAPS_BLT |
4358 WINEDDCAPS_BLTCOLORFILL |
4359 WINEDDCAPS_BLTDEPTHFILL |
4360 WINEDDCAPS_BLTSTRETCH |
4361 WINEDDCAPS_CANBLTSYSMEM |
4362 WINEDDCAPS_CANCLIP |
4363 WINEDDCAPS_CANCLIPSTRETCHED |
4364 WINEDDCAPS_COLORKEY |
4365 WINEDDCAPS_COLORKEYHWASSIST |
4366 WINEDDCAPS_ALIGNBOUNDARYSRC;
4368 /* Fill the ddraw caps structure */
4369 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4370 WINEDDCAPS_PALETTE |
4371 blit_caps;
4372 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4373 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4374 WINEDDCAPS2_PRIMARYGAMMA |
4375 WINEDDCAPS2_WIDESURFACES |
4376 WINEDDCAPS2_CANRENDERWINDOWED;
4377 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4378 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4379 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4380 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4381 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4382 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4383 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4384 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4385 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4387 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4388 WINEDDSCAPS_BACKBUFFER |
4389 WINEDDSCAPS_FLIP |
4390 WINEDDSCAPS_FRONTBUFFER |
4391 WINEDDSCAPS_OFFSCREENPLAIN |
4392 WINEDDSCAPS_PALETTE |
4393 WINEDDSCAPS_PRIMARYSURFACE |
4394 WINEDDSCAPS_SYSTEMMEMORY |
4395 WINEDDSCAPS_VIDEOMEMORY |
4396 WINEDDSCAPS_VISIBLE;
4397 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4399 /* Set D3D caps if OpenGL is available. */
4400 if (adapter->opengl)
4402 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4403 WINEDDSCAPS_MIPMAP |
4404 WINEDDSCAPS_TEXTURE |
4405 WINEDDSCAPS_ZBUFFER;
4406 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4409 return WINED3D_OK;
4412 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
4413 and fields being inserted in the middle, a new structure is used in place */
4414 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
4415 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
4416 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
4418 IWineD3DDeviceImpl *object = NULL;
4419 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4420 struct wined3d_adapter *adapter = &This->adapters[Adapter];
4421 WINED3DDISPLAYMODE mode;
4422 const struct fragment_pipeline *frag_pipeline = NULL;
4423 int i;
4424 struct fragment_caps ffp_caps;
4425 struct shader_caps shader_caps;
4426 HRESULT hr;
4428 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4429 * number and create a device without a 3D adapter for 2D only operation.
4431 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4432 return WINED3DERR_INVALIDCALL;
4435 /* Create a WineD3DDevice object */
4436 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
4437 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4438 TRACE("Created WineD3DDevice object @ %p\n", object);
4439 if (NULL == object) {
4440 return WINED3DERR_OUTOFVIDEOMEMORY;
4443 /* Set up initial COM information */
4444 object->lpVtbl = &IWineD3DDevice_Vtbl;
4445 object->ref = 1;
4446 object->wineD3D = iface;
4447 object->adapter = This->adapter_count ? adapter : NULL;
4448 IWineD3D_AddRef(object->wineD3D);
4449 object->parent = parent;
4450 object->device_parent = device_parent;
4451 list_init(&object->resources);
4452 list_init(&object->shaders);
4454 if(This->dxVersion == 7) {
4455 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
4456 } else {
4457 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4459 object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4461 /* Set the state up as invalid until the device is fully created */
4462 object->state = WINED3DERR_DRIVERINTERNALERROR;
4464 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
4465 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4467 /* Save the creation parameters */
4468 object->createParms.AdapterOrdinal = Adapter;
4469 object->createParms.DeviceType = DeviceType;
4470 object->createParms.hFocusWindow = hFocusWindow;
4471 object->createParms.BehaviorFlags = BehaviourFlags;
4473 /* Initialize other useful values */
4474 object->adapterNo = Adapter;
4475 object->devType = DeviceType;
4477 select_shader_mode(&adapter->gl_info, &object->ps_selected_mode, &object->vs_selected_mode);
4478 object->shader_backend = select_shader_backend(adapter, DeviceType);
4480 memset(&shader_caps, 0, sizeof(shader_caps));
4481 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4482 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
4483 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
4484 object->vs_clipping = shader_caps.VSClipping;
4486 memset(&ffp_caps, 0, sizeof(ffp_caps));
4487 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4488 object->frag_pipe = frag_pipeline;
4489 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
4490 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
4491 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
4492 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
4493 ffp_vertexstate_template, frag_pipeline, misc_state_template);
4495 if (FAILED(hr)) {
4496 IWineD3D_Release(object->wineD3D);
4497 HeapFree(GetProcessHeap(), 0, object);
4499 return hr;
4502 object->blitter = select_blit_implementation(adapter, DeviceType);
4504 /* set the state of the device to valid */
4505 object->state = WINED3D_OK;
4507 /* Get the initial screen setup for ddraw */
4508 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4510 object->ddraw_width = mode.Width;
4511 object->ddraw_height = mode.Height;
4512 object->ddraw_format = mode.Format;
4514 for(i = 0; i < PATCHMAP_SIZE; i++) {
4515 list_init(&object->patches[i]);
4518 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4520 return WINED3D_OK;
4523 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4524 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4525 IUnknown_AddRef(This->parent);
4526 *pParent = This->parent;
4527 return WINED3D_OK;
4530 static void WINE_GLAPI invalid_func(const void *data)
4532 ERR("Invalid vertex attribute function called\n");
4533 DebugBreak();
4536 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4538 ERR("Invalid texcoord function called\n");
4539 DebugBreak();
4542 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4543 * the extension detection and are used in drawStridedSlow
4545 static void WINE_GLAPI position_d3dcolor(const void *data)
4547 DWORD pos = *((const DWORD *)data);
4549 FIXME("Add a test for fixed function position from d3dcolor type\n");
4550 glVertex4s(D3DCOLOR_B_R(pos),
4551 D3DCOLOR_B_G(pos),
4552 D3DCOLOR_B_B(pos),
4553 D3DCOLOR_B_A(pos));
4556 static void WINE_GLAPI position_float4(const void *data)
4558 const GLfloat *pos = data;
4560 if (pos[3] != 0.0f && pos[3] != 1.0f)
4562 float w = 1.0f / pos[3];
4564 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4566 else
4568 glVertex3fv(pos);
4572 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4574 DWORD diffuseColor = *((const DWORD *)data);
4576 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4577 D3DCOLOR_B_G(diffuseColor),
4578 D3DCOLOR_B_B(diffuseColor),
4579 D3DCOLOR_B_A(diffuseColor));
4582 static void WINE_GLAPI specular_d3dcolor(const void *data)
4584 DWORD specularColor = *((const DWORD *)data);
4585 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4586 D3DCOLOR_B_G(specularColor),
4587 D3DCOLOR_B_B(specularColor)};
4589 specular_func_3ubv(d);
4592 static void WINE_GLAPI warn_no_specular_func(const void *data)
4594 WARN("GL_EXT_secondary_color not supported\n");
4597 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4599 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4600 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4601 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4602 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4603 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4604 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4605 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4606 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4607 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4608 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4609 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4610 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4611 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4612 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4613 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4614 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4615 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4617 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4618 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4619 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4620 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4621 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4622 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4623 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4624 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4625 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4626 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4627 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4628 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4629 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4630 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4631 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4632 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4633 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4635 /* No 4 component entry points here */
4636 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4637 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4638 if (gl_info->supported[EXT_SECONDARY_COLOR])
4640 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4642 else
4644 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4646 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4647 if (gl_info->supported[EXT_SECONDARY_COLOR])
4649 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4650 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4652 else
4654 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4656 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4657 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4658 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4659 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4660 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4661 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4662 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4663 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4664 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4665 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4666 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4667 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4669 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4670 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4672 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4673 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4674 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4675 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4676 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4677 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4678 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4679 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4680 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4681 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4682 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4683 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4684 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4685 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4686 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4687 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4688 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4690 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4691 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4692 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4693 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4694 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4695 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4696 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4697 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4698 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4699 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4700 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4701 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4702 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4703 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4704 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4705 if (gl_info->supported[NV_HALF_FLOAT])
4707 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4708 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4709 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4710 } else {
4711 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4712 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4716 BOOL InitAdapters(IWineD3DImpl *This)
4718 static HMODULE mod_gl;
4719 BOOL ret;
4720 int ps_selected_mode, vs_selected_mode;
4722 /* No need to hold any lock. The calling library makes sure only one thread calls
4723 * wined3d simultaneously
4726 TRACE("Initializing adapters\n");
4728 if(!mod_gl) {
4729 #ifdef USE_WIN32_OPENGL
4730 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4731 mod_gl = LoadLibraryA("opengl32.dll");
4732 if(!mod_gl) {
4733 ERR("Can't load opengl32.dll!\n");
4734 goto nogl_adapter;
4736 #else
4737 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4738 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4739 mod_gl = GetModuleHandleA("gdi32.dll");
4740 #endif
4743 /* Load WGL core functions from opengl32.dll */
4744 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4745 WGL_FUNCS_GEN;
4746 #undef USE_WGL_FUNC
4748 if(!pwglGetProcAddress) {
4749 ERR("Unable to load wglGetProcAddress!\n");
4750 goto nogl_adapter;
4753 /* Dynamically load all GL core functions */
4754 GL_FUNCS_GEN;
4755 #undef USE_GL_FUNC
4757 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4758 * otherwise because we have to use winex11.drv's override
4760 #ifdef USE_WIN32_OPENGL
4761 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4762 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4763 #else
4764 wglFinish = (void*)pwglGetProcAddress("wglFinish");
4765 wglFlush = (void*)pwglGetProcAddress("wglFlush");
4766 #endif
4768 glEnableWINE = glEnable;
4769 glDisableWINE = glDisable;
4771 /* For now only one default adapter */
4773 struct wined3d_adapter *adapter = &This->adapters[0];
4774 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4775 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4776 int iPixelFormat;
4777 int res;
4778 int i;
4779 WineD3D_PixelFormat *cfgs;
4780 DISPLAY_DEVICEW DisplayDevice;
4781 HDC hdc;
4783 TRACE("Initializing default adapter\n");
4784 adapter->num = 0;
4785 adapter->monitorPoint.x = -1;
4786 adapter->monitorPoint.y = -1;
4788 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4790 ERR("Failed to get a gl context for default adapter\n");
4791 goto nogl_adapter;
4794 ret = IWineD3DImpl_FillGLCaps(&adapter->driver_info, &adapter->gl_info);
4795 if(!ret) {
4796 ERR("Failed to initialize gl caps for default adapter\n");
4797 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4798 goto nogl_adapter;
4800 ret = initPixelFormats(&adapter->gl_info, adapter->driver_info.vendor);
4801 if(!ret) {
4802 ERR("Failed to init gl formats\n");
4803 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4804 goto nogl_adapter;
4807 hdc = fake_gl_ctx.dc;
4809 /* Use the VideoRamSize registry setting when set */
4810 if(wined3d_settings.emulated_textureram)
4811 adapter->TextureRam = wined3d_settings.emulated_textureram;
4812 else
4813 adapter->TextureRam = adapter->gl_info.vidmem;
4814 adapter->UsedTextureRam = 0;
4815 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4817 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4818 DisplayDevice.cb = sizeof(DisplayDevice);
4819 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4820 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4821 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4823 if (gl_info->supported[WGL_ARB_PIXEL_FORMAT])
4825 int attribute;
4826 int attribs[10];
4827 int values[10];
4828 int nAttribs = 0;
4830 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4831 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4833 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4834 cfgs = adapter->cfgs;
4835 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4836 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4837 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4838 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4839 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4840 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4841 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4842 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4843 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4844 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4846 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4848 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4850 if(!res)
4851 continue;
4853 /* Cache the pixel format */
4854 cfgs->iPixelFormat = iPixelFormat;
4855 cfgs->redSize = values[0];
4856 cfgs->greenSize = values[1];
4857 cfgs->blueSize = values[2];
4858 cfgs->alphaSize = values[3];
4859 cfgs->depthSize = values[4];
4860 cfgs->stencilSize = values[5];
4861 cfgs->windowDrawable = values[6];
4862 cfgs->iPixelType = values[7];
4863 cfgs->doubleBuffer = values[8];
4864 cfgs->auxBuffers = values[9];
4866 cfgs->pbufferDrawable = FALSE;
4867 /* Check for pbuffer support when it is around as
4868 * wglGetPixelFormatAttribiv fails for unknown attributes. */
4869 if (gl_info->supported[WGL_ARB_PBUFFER])
4871 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4872 int value;
4873 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4874 cfgs->pbufferDrawable = value;
4877 cfgs->numSamples = 0;
4878 /* Check multisample support */
4879 if (gl_info->supported[ARB_MULTISAMPLE])
4881 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4882 int value[2];
4883 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4884 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4885 * value[1] = number of multi sample buffers*/
4886 if(value[0])
4887 cfgs->numSamples = value[1];
4891 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);
4892 cfgs++;
4895 else
4897 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4898 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4899 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4901 cfgs = adapter->cfgs;
4902 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4904 PIXELFORMATDESCRIPTOR ppfd;
4906 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4907 if(!res)
4908 continue;
4910 /* We only want HW acceleration using an OpenGL ICD driver.
4911 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4912 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4914 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4916 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4917 continue;
4920 cfgs->iPixelFormat = iPixelFormat;
4921 cfgs->redSize = ppfd.cRedBits;
4922 cfgs->greenSize = ppfd.cGreenBits;
4923 cfgs->blueSize = ppfd.cBlueBits;
4924 cfgs->alphaSize = ppfd.cAlphaBits;
4925 cfgs->depthSize = ppfd.cDepthBits;
4926 cfgs->stencilSize = ppfd.cStencilBits;
4927 cfgs->pbufferDrawable = 0;
4928 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4929 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4930 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4931 cfgs->auxBuffers = ppfd.cAuxBuffers;
4932 cfgs->numSamples = 0;
4934 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);
4935 cfgs++;
4936 adapter->nCfgs++;
4939 /* 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 */
4940 if(!adapter->nCfgs)
4942 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4944 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4945 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4946 goto nogl_adapter;
4950 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4951 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4952 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4953 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4954 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4955 * driver is allowed to consume more bits EXCEPT for stencil bits.
4957 * Mark an adapter with this broken stencil behavior.
4959 adapter->brokenStencil = TRUE;
4960 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4962 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4963 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4964 adapter->brokenStencil = FALSE;
4965 break;
4969 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4971 select_shader_mode(&adapter->gl_info, &ps_selected_mode, &vs_selected_mode);
4972 fillGLAttribFuncs(&adapter->gl_info);
4973 adapter->opengl = TRUE;
4975 This->adapter_count = 1;
4976 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4978 return TRUE;
4980 nogl_adapter:
4981 /* Initialize an adapter for ddraw-only memory counting */
4982 memset(This->adapters, 0, sizeof(This->adapters));
4983 This->adapters[0].num = 0;
4984 This->adapters[0].opengl = FALSE;
4985 This->adapters[0].monitorPoint.x = -1;
4986 This->adapters[0].monitorPoint.y = -1;
4988 This->adapters[0].driver_info.name = "Display";
4989 This->adapters[0].driver_info.description = "WineD3D DirectDraw Emulation";
4990 if(wined3d_settings.emulated_textureram) {
4991 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4992 } else {
4993 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4996 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4998 This->adapter_count = 1;
4999 return FALSE;
5002 /**********************************************************
5003 * IWineD3D VTbl follows
5004 **********************************************************/
5006 const IWineD3DVtbl IWineD3D_Vtbl =
5008 /* IUnknown */
5009 IWineD3DImpl_QueryInterface,
5010 IWineD3DImpl_AddRef,
5011 IWineD3DImpl_Release,
5012 /* IWineD3D */
5013 IWineD3DImpl_GetParent,
5014 IWineD3DImpl_GetAdapterCount,
5015 IWineD3DImpl_RegisterSoftwareDevice,
5016 IWineD3DImpl_GetAdapterMonitor,
5017 IWineD3DImpl_GetAdapterModeCount,
5018 IWineD3DImpl_EnumAdapterModes,
5019 IWineD3DImpl_GetAdapterDisplayMode,
5020 IWineD3DImpl_GetAdapterIdentifier,
5021 IWineD3DImpl_CheckDeviceMultiSampleType,
5022 IWineD3DImpl_CheckDepthStencilMatch,
5023 IWineD3DImpl_CheckDeviceType,
5024 IWineD3DImpl_CheckDeviceFormat,
5025 IWineD3DImpl_CheckDeviceFormatConversion,
5026 IWineD3DImpl_GetDeviceCaps,
5027 IWineD3DImpl_CreateDevice
5030 static void STDMETHODCALLTYPE wined3d_null_wined3d_object_destroyed(void *parent) {}
5032 const struct wined3d_parent_ops wined3d_null_parent_ops =
5034 wined3d_null_wined3d_object_destroyed,