push 5aff8350ceade24f8243f07a9cf7ecb816236fb1
[wine/hacks.git] / dlls / wined3d / directx.c
blob1498684243e5214b3f383757e27eaa8a2cec1e85
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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
31 #define GLINFO_LOCATION (*gl_info)
33 /* The d3d device ID */
34 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
36 /* Extension detection */
37 static const struct {
38 const char *extension_string;
39 GL_SupportedExt extension;
40 DWORD version;
41 } EXTENSION_MAP[] = {
42 /* APPLE */
43 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
44 {"GL_APPLE_fence", APPLE_FENCE, 0 },
45 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
46 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
47 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
49 /* ATI */
50 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
51 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
52 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
53 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
54 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
56 /* ARB */
57 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
58 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
59 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
60 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
61 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
62 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
63 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
64 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
65 {"GL_ARB_imaging", ARB_IMAGING, 0 },
66 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
67 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
68 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
69 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
70 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
71 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
72 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
73 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
74 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
75 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
76 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
77 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
78 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
79 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
80 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
81 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
82 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
83 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
84 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
85 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
86 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
87 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
88 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
89 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
91 /* EXT */
92 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
93 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
94 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
95 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
96 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
97 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
98 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
99 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
100 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
101 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
102 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
103 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
104 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
105 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
106 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
107 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
108 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
109 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
110 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
111 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
112 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
113 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
114 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
115 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
116 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
117 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
118 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
119 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
121 /* NV */
122 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
123 {"GL_NV_fence", NV_FENCE, 0 },
124 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
125 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
126 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
127 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
128 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
129 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
130 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
131 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
132 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
133 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
134 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
135 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
136 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
137 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
138 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
139 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
140 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
141 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
142 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
144 /* SGI */
145 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
148 /**********************************************************
149 * Utility functions follow
150 **********************************************************/
152 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
153 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
154 WINED3DDEVTYPE DeviceType);
155 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
156 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
158 /* lookup tables */
159 const int minLookup[MAX_LOOKUPS] =
161 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
164 const int maxLookup[MAX_LOOKUPS] =
166 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
169 DWORD *stateLookup[MAX_LOOKUPS];
171 const struct min_lookup minMipLookup[] =
173 /* NONE POINT LINEAR */
174 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
175 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
176 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
179 const struct min_lookup minMipLookup_noFilter[] =
181 /* NONE POINT LINEAR */
182 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
183 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
187 const GLenum magLookup[] =
189 /* NONE POINT LINEAR */
190 GL_NEAREST, GL_NEAREST, GL_LINEAR,
193 const GLenum magLookup_noFilter[] =
195 /* NONE POINT LINEAR */
196 GL_NEAREST, GL_NEAREST, GL_NEAREST,
199 /* drawStridedSlow attributes */
200 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
201 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
202 glAttribFunc specular_func_3ubv;
203 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
204 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
205 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
208 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
209 * i.e., there is no GL Context - Get a default rendering context to enable the
210 * function query some info from GL.
213 struct wined3d_fake_gl_ctx
215 HDC dc;
216 HWND wnd;
217 HGLRC gl_ctx;
220 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
222 TRACE_(d3d_caps)("Destroying fake GL context.\n");
224 if (!pwglMakeCurrent(NULL, NULL))
226 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
229 if (!pwglDeleteContext(ctx->gl_ctx))
231 DWORD err = GetLastError();
232 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
235 ReleaseDC(ctx->wnd, ctx->dc);
236 DestroyWindow(ctx->wnd);
239 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
241 PIXELFORMATDESCRIPTOR pfd;
242 int iPixelFormat;
244 TRACE("getting context...\n");
246 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
247 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
248 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
249 if (!ctx->wnd)
251 ERR_(d3d_caps)("Failed to create a window.\n");
252 goto fail;
255 ctx->dc = GetDC(ctx->wnd);
256 if (!ctx->dc)
258 ERR_(d3d_caps)("Failed to get a DC.\n");
259 goto fail;
262 /* PixelFormat selection */
263 ZeroMemory(&pfd, sizeof(pfd));
264 pfd.nSize = sizeof(pfd);
265 pfd.nVersion = 1;
266 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
267 pfd.iPixelType = PFD_TYPE_RGBA;
268 pfd.cColorBits = 32;
269 pfd.iLayerType = PFD_MAIN_PLANE;
271 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
272 if (!iPixelFormat)
274 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
275 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
276 goto fail;
278 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
279 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
281 /* Create a GL context. */
282 ctx->gl_ctx = pwglCreateContext(ctx->dc);
283 if (!ctx->gl_ctx)
285 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
286 goto fail;
289 /* Make it the current GL context. */
290 if (!context_set_current(NULL))
292 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
295 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
297 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
298 goto fail;
301 return TRUE;
303 fail:
304 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
305 ctx->gl_ctx = NULL;
306 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
307 ctx->dc = NULL;
308 if (ctx->wnd) DestroyWindow(ctx->wnd);
309 ctx->wnd = NULL;
311 return FALSE;
314 /* Adjust the amount of used texture memory */
315 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
316 struct WineD3DAdapter *adapter = D3DDevice->adapter;
318 adapter->UsedTextureRam += glram;
319 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
320 return adapter->UsedTextureRam;
323 /**********************************************************
324 * IUnknown parts follows
325 **********************************************************/
327 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
331 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
332 if (IsEqualGUID(riid, &IID_IUnknown)
333 || IsEqualGUID(riid, &IID_IWineD3DBase)
334 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
335 IUnknown_AddRef(iface);
336 *ppobj = This;
337 return S_OK;
339 *ppobj = NULL;
340 return E_NOINTERFACE;
343 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
344 IWineD3DImpl *This = (IWineD3DImpl *)iface;
345 ULONG refCount = InterlockedIncrement(&This->ref);
347 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
348 return refCount;
351 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
352 IWineD3DImpl *This = (IWineD3DImpl *)iface;
353 ULONG ref;
354 TRACE("(%p) : Releasing from %d\n", This, This->ref);
355 ref = InterlockedDecrement(&This->ref);
356 if (ref == 0) {
357 unsigned int i;
359 for (i = 0; i < This->adapter_count; ++i)
361 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
363 HeapFree(GetProcessHeap(), 0, This);
366 return ref;
369 /* Set the shader type for this device, depending on the given capabilities,
370 * the device type, and the user preferences in wined3d_settings */
372 static void select_shader_mode(const struct wined3d_gl_info *gl_info,
373 WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
375 if (wined3d_settings.vs_mode == VS_NONE) {
376 *vs_selected = SHADER_NONE;
377 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
378 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
379 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
380 * shaders only on this card. */
381 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
382 *vs_selected = SHADER_ARB;
383 else
384 *vs_selected = SHADER_GLSL;
385 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
386 *vs_selected = SHADER_ARB;
387 } else {
388 *vs_selected = SHADER_NONE;
391 if (wined3d_settings.ps_mode == PS_NONE) {
392 *ps_selected = SHADER_NONE;
393 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
394 *ps_selected = SHADER_GLSL;
395 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
396 *ps_selected = SHADER_ARB;
397 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
398 *ps_selected = SHADER_ATI;
399 } else {
400 *ps_selected = SHADER_NONE;
404 /** Select the number of report maximum shader constants based on the selected shader modes */
405 static void select_shader_max_constants(int ps_selected_mode, int vs_selected_mode, struct wined3d_gl_info *gl_info)
407 switch (vs_selected_mode) {
408 case SHADER_GLSL:
409 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
410 break;
411 case SHADER_ARB:
412 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
413 break;
414 default:
415 gl_info->max_vshader_constantsF = 0;
416 break;
419 switch (ps_selected_mode) {
420 case SHADER_GLSL:
421 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
422 break;
423 case SHADER_ARB:
424 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
425 break;
426 default:
427 gl_info->max_pshader_constantsF = 0;
428 break;
432 /**********************************************************
433 * IWineD3D parts follows
434 **********************************************************/
436 /* GL locking is done by the caller */
437 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
439 GLuint prog;
440 BOOL ret = FALSE;
441 const char *testcode =
442 "!!ARBvp1.0\n"
443 "PARAM C[66] = { program.env[0..65] };\n"
444 "ADDRESS A0;"
445 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
446 "ARL A0.x, zero.x;\n"
447 "MOV result.position, C[A0.x + 65];\n"
448 "END\n";
450 while(glGetError());
451 GL_EXTCALL(glGenProgramsARB(1, &prog));
452 if(!prog) {
453 ERR("Failed to create an ARB offset limit test program\n");
455 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
456 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
457 strlen(testcode), testcode));
458 if(glGetError() != 0) {
459 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
460 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
461 ret = TRUE;
462 } else TRACE("OpenGL implementation allows offsets > 63\n");
464 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
465 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
466 checkGLcall("ARB vp offset limit test cleanup");
468 return ret;
471 static DWORD ver_for_ext(GL_SupportedExt ext)
473 unsigned int i;
474 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
475 if(EXTENSION_MAP[i].extension == ext) {
476 return EXTENSION_MAP[i].version;
479 return 0;
482 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
484 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
485 if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
486 if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
487 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
488 return FALSE;
491 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
493 if (gl_info->gl_vendor == VENDOR_NVIDIA)
495 if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600)
497 return TRUE;
500 return FALSE;
503 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
505 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
506 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
507 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
509 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
510 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
511 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
512 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
513 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
514 * the chance that other implementations support them is rather small since Win32 QuickTime uses
515 * DirectDraw, not OpenGL. */
516 if (gl_info->supported[APPLE_FENCE]
517 && gl_info->supported[APPLE_CLIENT_STORAGE]
518 && gl_info->supported[APPLE_FLUSH_RENDER]
519 && gl_info->supported[APPLE_YCBCR_422])
521 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported.\n");
522 TRACE_(d3d_caps)("Activating MacOS fixups.\n");
523 return TRUE;
525 else
527 TRACE_(d3d_caps)("Apple extensions are not supported.\n");
528 TRACE_(d3d_caps)("Not activating MacOS fixups.\n");
529 return FALSE;
533 /* Context activation is done by the caller. */
534 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
536 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
537 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
538 * all the texture. This function detects this bug by its symptom and disables PBOs
539 * if the test fails.
541 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
542 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
543 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
544 * read back is compared to the original. If they are equal PBOs are assumed to work,
545 * otherwise the PBO extension is disabled. */
546 GLuint texture, pbo;
547 static const unsigned int pattern[] =
549 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
550 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
551 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
552 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
554 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
556 /* No PBO -> No point in testing them. */
557 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
559 ENTER_GL();
561 while (glGetError());
562 glGenTextures(1, &texture);
563 glBindTexture(GL_TEXTURE_2D, texture);
565 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
566 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
567 checkGLcall("Specifying the PBO test texture");
569 GL_EXTCALL(glGenBuffersARB(1, &pbo));
570 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
571 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
572 checkGLcall("Specifying the PBO test pbo");
574 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
575 checkGLcall("Loading the PBO test texture");
577 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
578 glFinish(); /* just to be sure */
580 memset(check, 0, sizeof(check));
581 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
582 checkGLcall("Reading back the PBO test texture");
584 glDeleteTextures(1, &texture);
585 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
586 checkGLcall("PBO test cleanup");
588 LEAVE_GL();
590 if (memcmp(check, pattern, sizeof(check)))
592 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
593 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
594 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
596 else
598 TRACE_(d3d_caps)("PBO test successful.\n");
602 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
604 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer);
607 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
609 if (!match_apple(gl_info, gl_renderer)) return FALSE;
610 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
611 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
612 return TRUE;
615 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
617 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
618 if (match_apple(gl_info, gl_renderer)) return FALSE;
619 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
620 return TRUE;
623 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
625 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
626 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
627 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
628 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
629 * hardcoded
631 * dx10 cards usually have 64 varyings */
632 return gl_info->max_glsl_varyings > 44;
635 /* A GL context is provided by the caller */
636 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
638 GLenum error;
639 DWORD data[16];
641 if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE;
643 ENTER_GL();
644 while(glGetError());
645 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
646 error = glGetError();
647 LEAVE_GL();
649 if(error == GL_NO_ERROR)
651 TRACE("GL Implementation accepts 4 component specular color pointers\n");
652 return TRUE;
654 else
656 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
657 debug_glerror(error));
658 return FALSE;
662 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
664 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF);
665 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
666 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF);
667 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
670 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
672 quirk_arb_constants(gl_info);
673 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
674 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
675 * allow 48 different offsets or other helper immediate values. */
676 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
677 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
680 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
681 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
682 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
683 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
684 * most games, but avoids the crash
686 * A more sophisticated way would be to find all units that need texture coordinates and enable
687 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
688 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
690 * Note that disabling the extension entirely does not gain predictability because there is no point
691 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
692 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
694 if (gl_info->supported[ARB_POINT_SPRITE])
696 TRACE("Limiting point sprites to one texture unit.\n");
697 gl_info->max_point_sprite_units = 1;
701 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
703 quirk_arb_constants(gl_info);
705 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
706 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
707 * If real NP2 textures are used, the driver falls back to software. We could just remove the
708 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
709 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
710 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
711 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
713 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
714 * has this extension promoted to core. The extension loading code sets this extension supported
715 * due to that, so this code works on fglrx as well. */
716 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
718 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
719 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
720 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
723 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
724 * it is generally more efficient. Reserve just 8 constants. */
725 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
726 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
729 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
731 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
732 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
733 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
734 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
735 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
736 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
738 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
739 * triggering the software fallback. There is not much we can do here apart from disabling the
740 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
741 * in IWineD3DImpl_FillGLCaps).
742 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
743 * post-processing effects in the game "Max Payne 2").
744 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
745 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
746 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
747 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
750 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
752 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
753 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
754 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
755 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
756 * according to the spec.
758 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
759 * makes the shader slower and eats instruction slots which should be available to the d3d app.
761 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
762 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
763 * this workaround is activated on cards that do not need it, it won't break things, just affect
764 * performance negatively. */
765 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
766 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
769 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
771 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
774 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
776 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
779 struct driver_quirk
781 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
782 void (*apply)(struct wined3d_gl_info *gl_info);
783 const char *description;
786 struct driver_quirk quirk_table[] =
789 match_ati_r300_to_500,
790 quirk_ati_dx9,
791 "ATI GLSL constant and normalized texrect quirk"
793 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
794 * used it falls back to software. While the compiler can detect if the shader uses all declared
795 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
796 * using relative addressing falls back to software.
798 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
800 match_apple,
801 quirk_apple_glsl_constants,
802 "Apple GLSL uniform override"
805 match_geforce5,
806 quirk_no_np2,
807 "Geforce 5 NP2 disable"
810 match_apple_intel,
811 quirk_texcoord_w,
812 "Init texcoord .w for Apple Intel GPU driver"
815 match_apple_nonr500ati,
816 quirk_texcoord_w,
817 "Init texcoord .w for Apple ATI >= r600 GPU driver"
820 match_fglrx,
821 quirk_one_point_sprite,
822 "Fglrx point sprite crash workaround"
825 match_dx10_capable,
826 quirk_clip_varying,
827 "Reserved varying for gl_ClipPos"
830 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
831 * GL implementations accept it. The Mac GL is the only implementation known to
832 * reject it.
834 * If we can pass 4 component specular colors, do it, because (a) we don't have
835 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
836 * passes specular alpha to the pixel shader if any is used. Otherwise the
837 * specular alpha is used to pass the fog coordinate, which we pass to opengl
838 * via GL_EXT_fog_coord.
840 match_allows_spec_alpha,
841 quirk_allows_specular_alpha,
842 "Allow specular alpha quirk"
846 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
847 * reporting a driver version is moot because we are not the Windows driver, and we have different
848 * bugs, features, etc.
850 * If a card is not found in this table, the GL driver version is reported. */
851 struct driver_version_information
853 WORD vendor; /* reported PCI card vendor ID */
854 WORD card; /* reported PCI card device ID */
855 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
856 WORD hipart_hi, hipart_lo; /* driver hiword to report */
857 WORD lopart_hi, lopart_lo; /* driver loword to report */
860 static const struct driver_version_information driver_version_table[] =
862 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
863 * 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
864 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
865 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
867 * All version numbers used below are from the Linux nvidia drivers. */
868 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
869 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
870 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
871 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
872 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
873 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 },
874 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 },
875 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 },
876 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 },
877 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 },
878 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 },
879 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 },
880 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 },
881 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 },
882 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 },
883 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 },
884 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 },
885 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 },
886 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 },
887 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 },
888 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 },
889 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 },
890 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 },
891 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 },
892 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 },
893 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 },
894 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 },
895 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 },
896 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 },
897 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 },
899 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
900 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
901 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
902 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
903 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
904 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
905 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
906 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
907 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
908 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
909 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
911 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
914 /* Context activation is done by the caller. */
915 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer)
917 unsigned int i;
919 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
921 if (!quirk_table[i].match(gl_info, gl_renderer)) continue;
922 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
923 quirk_table[i].apply(gl_info);
926 /* Find out if PBOs work as they are supposed to. */
927 test_pbo_functionality(gl_info);
929 /* Fixup the driver version */
930 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
932 if (gl_info->gl_vendor == driver_version_table[i].vendor
933 && gl_info->gl_card == driver_version_table[i].card)
935 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB.\n",
936 gl_info->gl_vendor, gl_info->gl_card);
938 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
939 driver_version_table[i].lopart_lo);
940 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
941 driver_version_table[i].hipart_lo);
942 gl_info->driver_description = driver_version_table[i].description;
943 break;
948 /* Context activation is done by the caller. */
949 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_gl_info *gl_info)
951 const char *GL_Extensions = NULL;
952 const char *WGL_Extensions = NULL;
953 const char *gl_string = NULL;
954 const char *gl_string_cursor = NULL;
955 GLint gl_max;
956 GLfloat gl_floatv[2];
957 int major = 1, minor = 0;
958 unsigned i;
959 HDC hdc;
960 unsigned int vidmem=0;
961 char *gl_renderer;
962 DWORD gl_version;
963 size_t len;
965 TRACE_(d3d_caps)("(%p)\n", gl_info);
967 ENTER_GL();
969 gl_string = (const char *)glGetString(GL_RENDERER);
970 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", gl_string);
971 if (!gl_string)
973 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
974 return FALSE;
977 len = strlen(gl_string) + 1;
978 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
979 if (!gl_renderer)
981 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
982 return FALSE;
984 memcpy(gl_renderer, gl_string, len);
986 gl_string = (const char *)glGetString(GL_VENDOR);
987 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", gl_string);
988 if (!gl_string)
990 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
991 HeapFree(GetProcessHeap(), 0, gl_renderer);
992 return FALSE;
995 /* Fill in the GL vendor */
996 if (strstr(gl_string, "NVIDIA"))
998 gl_info->gl_vendor = VENDOR_NVIDIA;
1000 else if (strstr(gl_string, "ATI"))
1002 gl_info->gl_vendor = VENDOR_ATI;
1004 else if (strstr(gl_string, "Intel(R)")
1005 || strstr(gl_renderer, "Intel(R)")
1006 || strstr(gl_string, "Intel Inc."))
1008 gl_info->gl_vendor = VENDOR_INTEL;
1010 else if (strstr(gl_string, "Mesa"))
1012 gl_info->gl_vendor = VENDOR_MESA;
1014 else
1016 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Setting VENDOR_WINE.\n", gl_string);
1017 gl_info->gl_vendor = VENDOR_WINE;
1019 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
1021 /* Parse the GL_VERSION field into major and minor information */
1022 gl_string = (const char *)glGetString(GL_VERSION);
1023 TRACE_(d3d_caps)("GL_VERSION: %s.\n", gl_string);
1024 if (!gl_string)
1026 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1027 HeapFree(GetProcessHeap(), 0, gl_renderer);
1028 return FALSE;
1031 /* First, parse the generic opengl version. This is supposed not to be
1032 * convoluted with driver specific information. */
1033 gl_string_cursor = gl_string;
1035 major = atoi(gl_string_cursor);
1036 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1037 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1038 if (*gl_string_cursor++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_string));
1040 minor = atoi(gl_string_cursor);
1041 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1042 gl_version = MAKEDWORD_VERSION(major, minor);
1044 /* Now parse the driver specific string which we'll report to the app. */
1045 switch (gl_info->gl_vendor)
1047 case VENDOR_NVIDIA:
1048 gl_string_cursor = strstr(gl_string, "NVIDIA");
1049 if (!gl_string_cursor)
1051 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1052 break;
1055 gl_string_cursor = strstr(gl_string_cursor, " ");
1056 if (!gl_string_cursor)
1058 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1059 break;
1062 while (*gl_string_cursor == ' ') ++gl_string_cursor;
1064 if (!*gl_string_cursor)
1066 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1067 break;
1070 major = atoi(gl_string_cursor);
1071 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1073 if (*gl_string_cursor++ != '.')
1075 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1076 break;
1079 minor = atoi(gl_string_cursor);
1080 minor = major * 100 + minor;
1081 major = 10;
1082 break;
1084 case VENDOR_ATI:
1085 major = minor = 0;
1086 gl_string_cursor = strchr(gl_string, '-');
1087 if (gl_string_cursor)
1089 ++gl_string_cursor;
1091 /* Check if version number is of the form x.y.z. */
1092 if (*gl_string_cursor < '0' || *gl_string_cursor > '9'
1093 || gl_string_cursor[1] != '.'
1094 || gl_string_cursor[2] < '0' || gl_string_cursor[2] > '9'
1095 || gl_string_cursor[3] != '.'
1096 || gl_string_cursor[4] < '0' || gl_string_cursor[4] > '9')
1097 /* Mark version number as malformed. */
1098 gl_string_cursor = 0;
1101 if (!gl_string_cursor)
1103 WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
1105 else
1107 major = *gl_string_cursor - '0';
1108 minor = (gl_string_cursor[2] - '0') * 256 + (gl_string_cursor[4] - '0');
1110 break;
1112 case VENDOR_INTEL:
1113 /* Apple and Mesa version strings look differently, but both provide intel drivers. */
1114 if (strstr(gl_string, "APPLE"))
1116 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
1117 * We only need the first part, and use the APPLE as identification
1118 * "1.2 APPLE-1.4.56". */
1119 gl_string_cursor = gl_string;
1120 major = atoi(gl_string_cursor);
1121 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1123 if (*gl_string_cursor++ != '.')
1125 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s.\n", debugstr_a(gl_string));
1126 break;
1129 minor = atoi(gl_string_cursor);
1130 break;
1132 /* Fallthrough */
1134 case VENDOR_MESA:
1135 gl_string_cursor = strstr(gl_string, "Mesa");
1136 gl_string_cursor = strstr(gl_string_cursor, " ");
1137 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
1138 if (*gl_string_cursor)
1140 char tmp[16];
1141 int cursor = 0;
1143 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
1145 tmp[cursor++] = *gl_string_cursor;
1146 ++gl_string_cursor;
1148 tmp[cursor] = 0;
1149 major = atoi(tmp);
1151 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
1152 ++gl_string_cursor;
1154 cursor = 0;
1155 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
1157 tmp[cursor++] = *gl_string_cursor;
1158 ++gl_string_cursor;
1160 tmp[cursor] = 0;
1161 minor = atoi(tmp);
1163 break;
1165 default:
1166 major = 0;
1167 minor = 9;
1168 break;
1171 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
1172 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x).\n",
1173 debugstr_a(gl_string), major, minor, gl_info->driver_version);
1174 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version). */
1175 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
1178 * Initialize openGL extension related variables
1179 * with Default values
1181 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1182 gl_info->max_buffers = 1;
1183 gl_info->max_textures = 1;
1184 gl_info->max_texture_stages = 1;
1185 gl_info->max_fragment_samplers = 1;
1186 gl_info->max_vertex_samplers = 0;
1187 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
1188 gl_info->max_sampler_stages = 1;
1189 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
1190 gl_info->ps_arb_max_temps = 0;
1191 gl_info->ps_arb_max_instructions = 0;
1192 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
1193 gl_info->vs_arb_max_temps = 0;
1194 gl_info->vs_arb_max_instructions = 0;
1195 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
1196 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
1197 gl_info->vs_glsl_constantsF = 0;
1198 gl_info->ps_glsl_constantsF = 0;
1199 gl_info->vs_arb_constantsF = 0;
1200 gl_info->ps_arb_constantsF = 0;
1201 gl_info->ps_arb_max_local_constants = 0;
1203 /* Retrieve opengl defaults */
1204 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1205 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1206 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1208 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1209 gl_info->max_lights = gl_max;
1210 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1212 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1213 gl_info->max_texture_size = gl_max;
1214 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1216 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1217 gl_info->max_pointsizemin = gl_floatv[0];
1218 gl_info->max_pointsize = gl_floatv[1];
1219 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1221 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1222 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1223 if (!GL_Extensions)
1225 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1226 HeapFree(GetProcessHeap(), 0, gl_renderer);
1227 return FALSE;
1230 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1232 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1234 while (*GL_Extensions)
1236 const char *start;
1237 char current_ext[256];
1239 while (isspace(*GL_Extensions)) ++GL_Extensions;
1240 start = GL_Extensions;
1241 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1243 len = GL_Extensions - start;
1244 if (!len || len >= sizeof(current_ext)) continue;
1246 memcpy(current_ext, start, len);
1247 current_ext[len] = '\0';
1248 TRACE_(d3d_caps)("- %s\n", current_ext);
1250 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1252 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1254 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1255 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1256 break;
1261 LEAVE_GL();
1263 /* Now work out what GL support this card really has */
1264 #define USE_GL_FUNC(type, pfn, ext, replace) \
1266 DWORD ver = ver_for_ext(ext); \
1267 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1268 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1269 else gl_info->pfn = NULL; \
1271 GL_EXT_FUNCS_GEN;
1272 #undef USE_GL_FUNC
1274 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1275 WGL_EXT_FUNCS_GEN;
1276 #undef USE_GL_FUNC
1278 ENTER_GL();
1280 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1281 * loading the functions, otherwise the code above will load the extension entry points instead of the
1282 * core functions, which may not work. */
1283 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1285 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1286 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1288 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1289 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1293 if (gl_info->supported[APPLE_FENCE])
1295 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1296 * The apple extension interacts with some other apple exts. Disable the NV
1297 * extension if the apple one is support to prevent confusion in other parts
1298 * of the code. */
1299 gl_info->supported[NV_FENCE] = FALSE;
1301 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1303 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1305 * The enums are the same:
1306 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1307 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1308 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1309 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1310 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1312 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1314 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1315 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1317 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1319 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1320 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1323 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1325 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1326 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1328 if (gl_info->supported[NV_TEXTURE_SHADER2])
1330 if (gl_info->supported[NV_REGISTER_COMBINERS])
1332 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1333 * are supported. The nv extensions provide the same functionality as the
1334 * ATI one, and a bit more(signed pixelformats). */
1335 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1338 if (gl_info->supported[ARB_DRAW_BUFFERS])
1340 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1341 gl_info->max_buffers = gl_max;
1342 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1344 if (gl_info->supported[ARB_MULTITEXTURE])
1346 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1347 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
1348 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures);
1350 if (gl_info->supported[NV_REGISTER_COMBINERS])
1352 GLint tmp;
1353 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1354 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
1356 else
1358 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
1360 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages);
1362 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1364 GLint tmp;
1365 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1366 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1368 else
1370 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
1372 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers);
1374 if (gl_info->supported[ARB_VERTEX_SHADER])
1376 GLint tmp;
1377 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1378 gl_info->max_vertex_samplers = tmp;
1379 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1380 gl_info->max_combined_samplers = tmp;
1382 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1383 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1384 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1385 * shader is used with fixed function vertex processing we're fine too because fixed function
1386 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1387 * used we have to make sure that all vertex sampler setups are valid together with all
1388 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1389 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1390 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1391 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1392 * a fixed function pipeline anymore.
1394 * So this is just a check to check that our assumption holds true. If not, write a warning
1395 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1396 if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12
1397 && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers)
1399 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1400 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
1401 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1402 if (gl_info->max_combined_samplers > MAX_TEXTURES)
1403 gl_info->max_vertex_samplers = gl_info->max_combined_samplers - MAX_TEXTURES;
1404 else
1405 gl_info->max_vertex_samplers = 0;
1408 else
1410 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
1412 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers);
1413 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers);
1415 if (gl_info->supported[ARB_VERTEX_BLEND])
1417 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1418 gl_info->max_blends = gl_max;
1419 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends);
1421 if (gl_info->supported[EXT_TEXTURE3D])
1423 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1424 gl_info->max_texture3d_size = gl_max;
1425 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size);
1427 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1429 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1430 gl_info->max_anisotropy = gl_max;
1431 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy);
1433 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1435 gl_info->ps_arb_version = PS_VERSION_11;
1436 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1437 gl_info->ps_arb_constantsF = gl_max;
1438 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF);
1439 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1440 gl_info->ps_arb_max_temps = gl_max;
1441 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps);
1442 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1443 gl_info->ps_arb_max_instructions = gl_max;
1444 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions);
1446 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1448 gl_info->vs_arb_version = VS_VERSION_11;
1449 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1450 gl_info->vs_arb_constantsF = gl_max;
1451 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF);
1452 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1453 gl_info->vs_arb_max_temps = gl_max;
1454 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps);
1455 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1456 gl_info->vs_arb_max_instructions = gl_max;
1457 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions);
1459 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1461 if (gl_info->supported[ARB_VERTEX_SHADER])
1463 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1464 gl_info->vs_glsl_constantsF = gl_max / 4;
1465 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF);
1467 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1469 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1470 gl_info->ps_glsl_constantsF = gl_max / 4;
1471 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF);
1472 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1473 gl_info->max_glsl_varyings = gl_max;
1474 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
1476 if (gl_info->supported[EXT_VERTEX_SHADER])
1478 gl_info->vs_ati_version = VS_VERSION_11;
1480 if (gl_info->supported[NV_VERTEX_PROGRAM3])
1482 gl_info->vs_nv_version = VS_VERSION_30;
1484 else if (gl_info->supported[NV_VERTEX_PROGRAM2])
1486 gl_info->vs_nv_version = VS_VERSION_20;
1488 else if (gl_info->supported[NV_VERTEX_PROGRAM1_1])
1490 gl_info->vs_nv_version = VS_VERSION_11;
1492 else if (gl_info->supported[NV_VERTEX_PROGRAM])
1494 gl_info->vs_nv_version = VS_VERSION_10;
1496 if (gl_info->supported[NV_FRAGMENT_PROGRAM2])
1498 gl_info->ps_nv_version = PS_VERSION_30;
1500 else if (gl_info->supported[NV_FRAGMENT_PROGRAM])
1502 gl_info->ps_nv_version = PS_VERSION_20;
1504 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
1506 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
1508 else
1510 gl_info->max_shininess = 128.0f;
1512 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1514 /* If we have full NP2 texture support, disable
1515 * GL_ARB_texture_rectangle because we will never use it.
1516 * This saves a few redundant glDisable calls. */
1517 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1519 if (gl_info->supported[ATI_FRAGMENT_SHADER])
1521 /* Disable NV_register_combiners and fragment shader if this is supported.
1522 * generally the NV extensions are preferred over the ATI ones, and this
1523 * extension is disabled if register_combiners and texture_shader2 are both
1524 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1525 * fragment processing support. */
1526 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1527 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1528 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1529 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1530 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1532 if (gl_info->supported[NV_HALF_FLOAT])
1534 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
1535 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1537 if (gl_info->supported[ARB_POINT_SPRITE])
1539 gl_info->max_point_sprite_units = gl_info->max_textures;
1541 else
1543 gl_info->max_point_sprite_units = 0;
1545 checkGLcall("extension detection");
1547 /* In some cases the number of texture stages can be larger than the number
1548 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1549 * shaders), but 8 texture stages (register combiners). */
1550 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1552 /* We can only use ORM_FBO when the hardware supports it. */
1553 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1554 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
1555 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1558 /* MRTs are currently only supported when FBOs are used. */
1559 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1560 gl_info->max_buffers = 1;
1563 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1564 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1565 * in case of the latest videocards in the number of pixel/vertex pipelines.
1567 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1568 * rendering. Various games use this information to get a rough estimation of the features of the card
1569 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1570 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1571 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1572 * not the PCI id.
1574 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1575 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1576 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1577 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1578 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1579 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1580 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1581 * is limited.
1583 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1584 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1585 * similar 3d features.
1587 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1588 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1589 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1590 * won't pass we return a default card. This way is better than maintaining a full card database as even
1591 * without a full database we can return a card with similar features. Second the size of the database
1592 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1593 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1594 * to distinguishes between different models from that family.
1596 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1597 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1598 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1599 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1600 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1601 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1602 * memory behind our backs if really needed.
1603 * Note that the amount of video memory can be overruled using a registry setting.
1605 switch (gl_info->gl_vendor) {
1606 case VENDOR_NVIDIA:
1607 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1608 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1610 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1611 /* Geforce 200 - highend */
1612 if (strstr(gl_renderer, "GTX 280")
1613 || strstr(gl_renderer, "GTX 285")
1614 || strstr(gl_renderer, "GTX 295"))
1616 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1617 vidmem = 1024;
1619 /* Geforce 200 - midend high */
1620 else if (strstr(gl_renderer, "GTX 275"))
1622 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
1623 vidmem = 896;
1625 /* Geforce 200 - midend */
1626 else if (strstr(gl_renderer, "GTX 260"))
1628 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
1629 vidmem = 1024;
1631 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1632 else if (strstr(gl_renderer, "9800")
1633 || strstr(gl_renderer, "GTS 150")
1634 || strstr(gl_renderer, "GTS 250"))
1636 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1637 vidmem = 512;
1639 /* Geforce9 - midend */
1640 else if (strstr(gl_renderer, "9600"))
1642 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1643 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1645 /* Geforce9 - midend low / Geforce 200 - low*/
1646 else if (strstr(gl_renderer, "9500")
1647 || strstr(gl_renderer, "GT 120")
1648 || strstr(gl_renderer, "GT 130"))
1650 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
1651 vidmem = 256; /* The 9500GT has 256-1024MB */
1653 /* Geforce9 - lowend */
1654 else if (strstr(gl_renderer, "9400"))
1656 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
1657 vidmem = 256; /* The 9400GT has 256-1024MB */
1659 /* Geforce9 - lowend low */
1660 else if (strstr(gl_renderer, "9100")
1661 || strstr(gl_renderer, "9200")
1662 || strstr(gl_renderer, "9300")
1663 || strstr(gl_renderer, "G 100"))
1665 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
1666 vidmem = 256; /* The 9100-9300 cards have 256MB */
1668 /* Geforce8 - highend */
1669 else if (strstr(gl_renderer, "8800"))
1671 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1672 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1674 /* Geforce8 - midend mobile */
1675 else if (strstr(gl_renderer, "8600 M"))
1677 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1678 vidmem = 512;
1680 /* Geforce8 - midend */
1681 else if (strstr(gl_renderer, "8600")
1682 || strstr(gl_renderer, "8700"))
1684 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1685 vidmem = 256;
1687 /* Geforce8 - lowend */
1688 else if (strstr(gl_renderer, "8300")
1689 || strstr(gl_renderer, "8400")
1690 || strstr(gl_renderer, "8500"))
1692 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1693 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1695 /* Geforce7 - highend */
1696 else if (strstr(gl_renderer, "7800")
1697 || strstr(gl_renderer, "7900")
1698 || strstr(gl_renderer, "7950")
1699 || strstr(gl_renderer, "Quadro FX 4")
1700 || strstr(gl_renderer, "Quadro FX 5"))
1702 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1703 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1705 /* Geforce7 midend */
1706 else if (strstr(gl_renderer, "7600")
1707 || strstr(gl_renderer, "7700"))
1709 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1710 vidmem = 256; /* The 7600 uses 256-512MB */
1711 /* Geforce7 lower medium */
1713 else if (strstr(gl_renderer, "7400"))
1715 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1716 vidmem = 256; /* The 7400 uses 256-512MB */
1718 /* Geforce7 lowend */
1719 else if (strstr(gl_renderer, "7300"))
1721 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1722 vidmem = 256; /* Mac Pros with this card have 256 MB */
1724 /* Geforce6 highend */
1725 else if (strstr(gl_renderer, "6800"))
1727 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1728 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1730 /* Geforce6 - midend */
1731 else if (strstr(gl_renderer, "6600")
1732 || strstr(gl_renderer, "6610")
1733 || strstr(gl_renderer, "6700"))
1735 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1736 vidmem = 128; /* A 6600GT has 128-256MB */
1738 /* Geforce6/7 lowend */
1739 else {
1740 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1741 vidmem = 64; /* */
1743 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1744 /* GeforceFX - highend */
1745 if (strstr(gl_renderer, "5800")
1746 || strstr(gl_renderer, "5900")
1747 || strstr(gl_renderer, "5950")
1748 || strstr(gl_renderer, "Quadro FX"))
1750 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1751 vidmem = 256; /* 5800-5900 cards use 256MB */
1753 /* GeforceFX - midend */
1754 else if (strstr(gl_renderer, "5600")
1755 || strstr(gl_renderer, "5650")
1756 || strstr(gl_renderer, "5700")
1757 || strstr(gl_renderer, "5750"))
1759 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1760 vidmem = 128; /* A 5600 uses 128-256MB */
1762 /* GeforceFX - lowend */
1763 else {
1764 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1765 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1767 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1768 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1770 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1771 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1773 else
1775 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1776 vidmem = 64; /* Geforce3 cards have 64-128MB */
1778 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1779 if (strstr(gl_renderer, "GeForce4 MX"))
1781 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1782 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1784 else if(strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1786 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1787 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1789 else if(strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1791 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1792 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1794 else
1796 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1797 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1799 } else {
1800 if (strstr(gl_renderer, "TNT2"))
1802 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1803 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1805 else
1807 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1808 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1811 break;
1812 case VENDOR_ATI:
1813 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1815 * beware: renderer string do not match exact card model,
1816 * eg HD 4800 is returned for multiple card, even for RV790 based one
1818 if(WINE_D3D9_CAPABLE(gl_info)) {
1819 /* Radeon R7xx HD4800 - highend */
1820 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1821 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1822 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1823 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1824 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1826 gl_info->gl_card = CARD_ATI_RADEON_HD4800;
1827 vidmem = 512; /* note: HD4890 cards use 1024MB */
1829 /* Radeon R740 HD4700 - midend */
1830 else if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1831 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1833 gl_info->gl_card = CARD_ATI_RADEON_HD4700;
1834 vidmem = 512;
1836 /* Radeon R730 HD4600 - midend */
1837 else if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1838 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1839 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1841 gl_info->gl_card = CARD_ATI_RADEON_HD4600;
1842 vidmem = 512;
1844 /* Radeon R710 HD4500/HD4350 - lowend */
1845 else if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1846 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1848 gl_info->gl_card = CARD_ATI_RADEON_HD4350;
1849 vidmem = 256;
1851 /* Radeon R6xx HD2900/HD3800 - highend */
1852 else if (strstr(gl_renderer, "HD 2900")
1853 || strstr(gl_renderer, "HD 3870")
1854 || strstr(gl_renderer, "HD 3850"))
1856 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1857 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1859 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1860 else if (strstr(gl_renderer, "HD 2600")
1861 || strstr(gl_renderer, "HD 3830")
1862 || strstr(gl_renderer, "HD 3690")
1863 || strstr(gl_renderer, "HD 3650"))
1865 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1866 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1868 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1869 else if (strstr(gl_renderer, "HD 2300")
1870 || strstr(gl_renderer, "HD 2400")
1871 || strstr(gl_renderer, "HD 3470")
1872 || strstr(gl_renderer, "HD 3450")
1873 || strstr(gl_renderer, "HD 3430")
1874 || strstr(gl_renderer, "HD 3400"))
1876 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1877 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1879 /* Radeon R6xx/R7xx integrated */
1880 else if (strstr(gl_renderer, "HD 3100")
1881 || strstr(gl_renderer, "HD 3200")
1882 || strstr(gl_renderer, "HD 3300"))
1884 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1885 vidmem = 128; /* 128MB */
1887 /* Radeon R5xx */
1888 else if (strstr(gl_renderer, "X1600")
1889 || strstr(gl_renderer, "X1650")
1890 || strstr(gl_renderer, "X1800")
1891 || strstr(gl_renderer, "X1900")
1892 || strstr(gl_renderer, "X1950"))
1894 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1895 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1897 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1898 else if(strstr(gl_renderer, "X700")
1899 || strstr(gl_renderer, "X800")
1900 || strstr(gl_renderer, "X850")
1901 || strstr(gl_renderer, "X1300")
1902 || strstr(gl_renderer, "X1400")
1903 || strstr(gl_renderer, "X1450")
1904 || strstr(gl_renderer, "X1550"))
1906 gl_info->gl_card = CARD_ATI_RADEON_X700;
1907 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1909 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1910 else if(strstr(gl_renderer, "Radeon Xpress"))
1912 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1913 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1915 /* Radeon R3xx */
1916 else {
1917 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1918 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1920 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1921 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1922 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1923 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1924 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1925 vidmem = 32; /* There are models with up to 64MB */
1926 } else {
1927 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1928 vidmem = 16; /* There are 16-32MB models */
1930 break;
1931 case VENDOR_INTEL:
1932 if(strstr(gl_renderer, "X3100"))
1934 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1935 gl_info->gl_card = CARD_INTEL_X3100;
1936 vidmem = 128;
1938 else if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1940 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1941 gl_info->gl_card = CARD_INTEL_I945GM;
1942 vidmem = 64;
1944 else if (strstr(gl_renderer, "915GM"))
1946 gl_info->gl_card = CARD_INTEL_I915GM;
1948 else if (strstr(gl_renderer, "915G"))
1950 gl_info->gl_card = CARD_INTEL_I915G;
1952 else if (strstr(gl_renderer, "865G"))
1954 gl_info->gl_card = CARD_INTEL_I865G;
1956 else if (strstr(gl_renderer, "855G"))
1958 gl_info->gl_card = CARD_INTEL_I855G;
1960 else if (strstr(gl_renderer, "830G"))
1962 gl_info->gl_card = CARD_INTEL_I830G;
1963 } else {
1964 gl_info->gl_card = CARD_INTEL_I915G;
1966 break;
1967 case VENDOR_MESA:
1968 case VENDOR_WINE:
1969 default:
1970 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1971 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1972 * them a good generic choice.
1974 gl_info->gl_vendor = VENDOR_NVIDIA;
1975 if(WINE_D3D9_CAPABLE(gl_info))
1976 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1977 else if(WINE_D3D8_CAPABLE(gl_info))
1978 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1979 else if(WINE_D3D7_CAPABLE(gl_info))
1980 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1981 else if(WINE_D3D6_CAPABLE(gl_info))
1982 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1983 else
1984 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1986 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1988 /* If we have an estimate use it, else default to 64MB; */
1989 if(vidmem)
1990 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1991 else
1992 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1994 /* Load all the lookup tables */
1995 for (i = 0; i < MAX_LOOKUPS; i++) {
1996 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1999 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
2000 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
2001 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
2002 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2003 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
2004 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
2005 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
2006 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
2007 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
2008 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
2010 /* Make sure there's an active HDC else the WGL extensions will fail */
2011 hdc = pwglGetCurrentDC();
2012 if (hdc) {
2013 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2014 if(GL_EXTCALL(wglGetExtensionsStringARB))
2015 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2017 if (NULL == WGL_Extensions) {
2018 ERR(" WGL_Extensions returns NULL\n");
2019 } else {
2020 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2021 while (*WGL_Extensions != 0x00) {
2022 const char *Start;
2023 char ThisExtn[256];
2025 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2026 Start = WGL_Extensions;
2027 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2028 WGL_Extensions++;
2031 len = WGL_Extensions - Start;
2032 if (len == 0 || len >= sizeof(ThisExtn))
2033 continue;
2035 memcpy(ThisExtn, Start, len);
2036 ThisExtn[len] = '\0';
2037 TRACE_(d3d_caps)("- %s\n", ThisExtn);
2039 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2040 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
2041 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2043 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2044 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2045 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2047 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2048 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2049 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2054 LEAVE_GL();
2056 fixup_extensions(gl_info, gl_renderer);
2057 add_gl_compat_wrappers(gl_info);
2059 HeapFree(GetProcessHeap(), 0, gl_renderer);
2060 return TRUE;
2063 /**********************************************************
2064 * IWineD3D implementation follows
2065 **********************************************************/
2067 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2068 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2070 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2072 return This->adapter_count;
2075 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
2076 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2077 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
2078 return WINED3D_OK;
2081 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2082 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2084 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2086 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2087 return NULL;
2090 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2093 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2094 of the same bpp but different resolutions */
2096 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2097 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2098 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2099 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2101 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2102 return 0;
2105 /* TODO: Store modes per adapter and read it from the adapter structure */
2106 if (Adapter == 0) { /* Display */
2107 unsigned int i = 0;
2108 unsigned int j = 0;
2109 DEVMODEW mode;
2111 memset(&mode, 0, sizeof(mode));
2112 mode.dmSize = sizeof(mode);
2114 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2116 ++j;
2117 switch (Format)
2119 case WINED3DFMT_UNKNOWN:
2120 /* This is for D3D8, do not enumerate P8 here */
2121 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2122 break;
2124 case WINED3DFMT_X8R8G8B8:
2125 if (mode.dmBitsPerPel == 32) ++i;
2126 break;
2128 case WINED3DFMT_R5G6B5:
2129 if (mode.dmBitsPerPel == 16) ++i;
2130 break;
2132 case WINED3DFMT_P8:
2133 if (mode.dmBitsPerPel == 8) ++i;
2134 break;
2136 default:
2137 /* Skip other modes as they do not match the requested format */
2138 break;
2142 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2143 return i;
2144 } else {
2145 FIXME_(d3d_caps)("Adapter not primary display\n");
2147 return 0;
2150 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2151 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2152 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2153 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2155 /* Validate the parameters as much as possible */
2156 if (NULL == pMode ||
2157 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2158 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2159 return WINED3DERR_INVALIDCALL;
2162 /* TODO: Store modes per adapter and read it from the adapter structure */
2163 if (Adapter == 0)
2165 DEVMODEW DevModeW;
2166 int ModeIdx = 0;
2167 UINT i = 0;
2168 int j = 0;
2170 ZeroMemory(&DevModeW, sizeof(DevModeW));
2171 DevModeW.dmSize = sizeof(DevModeW);
2173 /* If we are filtering to a specific format (D3D9), then need to skip
2174 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2175 just count through the ones with valid bit depths */
2176 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
2177 switch (Format)
2179 case WINED3DFMT_UNKNOWN:
2180 /* This is D3D8. Do not enumerate P8 here */
2181 if (DevModeW.dmBitsPerPel == 32 ||
2182 DevModeW.dmBitsPerPel == 16) i++;
2183 break;
2184 case WINED3DFMT_X8R8G8B8:
2185 if (DevModeW.dmBitsPerPel == 32) i++;
2186 break;
2187 case WINED3DFMT_R5G6B5:
2188 if (DevModeW.dmBitsPerPel == 16) i++;
2189 break;
2190 case WINED3DFMT_P8:
2191 if (DevModeW.dmBitsPerPel == 8) i++;
2192 break;
2193 default:
2194 /* Modes that don't match what we support can get an early-out */
2195 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
2196 return WINED3DERR_INVALIDCALL;
2200 if (i == 0) {
2201 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2202 return WINED3DERR_INVALIDCALL;
2204 ModeIdx = j - 1;
2206 /* Now get the display mode via the calculated index */
2207 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2208 pMode->Width = DevModeW.dmPelsWidth;
2209 pMode->Height = DevModeW.dmPelsHeight;
2210 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
2211 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2212 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2214 if (Format == WINED3DFMT_UNKNOWN) {
2215 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2216 } else {
2217 pMode->Format = Format;
2219 } else {
2220 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2221 return WINED3DERR_INVALIDCALL;
2224 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2225 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2226 DevModeW.dmBitsPerPel);
2229 else
2231 FIXME_(d3d_caps)("Adapter not primary display\n");
2234 return WINED3D_OK;
2237 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2238 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2239 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
2241 if (NULL == pMode ||
2242 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2243 return WINED3DERR_INVALIDCALL;
2246 if (Adapter == 0) { /* Display */
2247 int bpp = 0;
2248 DEVMODEW DevModeW;
2250 ZeroMemory(&DevModeW, sizeof(DevModeW));
2251 DevModeW.dmSize = sizeof(DevModeW);
2253 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2254 pMode->Width = DevModeW.dmPelsWidth;
2255 pMode->Height = DevModeW.dmPelsHeight;
2256 bpp = DevModeW.dmBitsPerPel;
2257 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
2258 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2260 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2263 pMode->Format = pixelformat_for_depth(bpp);
2264 } else {
2265 FIXME_(d3d_caps)("Adapter not primary display\n");
2268 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2269 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2270 return WINED3D_OK;
2273 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2274 and fields being inserted in the middle, a new structure is used in place */
2275 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2276 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2277 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2278 size_t len;
2280 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2282 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2283 return WINED3DERR_INVALIDCALL;
2286 /* Return the information requested */
2287 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2289 if (pIdentifier->driver_size)
2291 len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1);
2292 memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len);
2293 pIdentifier->driver[len] = '\0';
2296 if (pIdentifier->description_size)
2298 const char *description;
2300 if (This->adapters[Adapter].gl_info.driver_description)
2301 description = This->adapters[Adapter].gl_info.driver_description;
2302 else
2303 description = This->adapters[Adapter].description;
2305 len = min(strlen(description), pIdentifier->description_size - 1);
2306 memcpy(pIdentifier->description, description, len);
2307 pIdentifier->description[len] = '\0';
2310 /* Note that d3d8 doesn't supply a device name. */
2311 if (pIdentifier->device_name_size)
2313 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2315 len = strlen(device_name);
2316 if (len >= pIdentifier->device_name_size)
2318 ERR("Device name size too small.\n");
2319 return WINED3DERR_INVALIDCALL;
2322 memcpy(pIdentifier->device_name, device_name, len);
2323 pIdentifier->device_name[len] = '\0';
2326 pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
2327 pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version;
2328 pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor;
2329 pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card;
2330 pIdentifier->subsystem_id = 0;
2331 pIdentifier->revision = 0;
2332 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2334 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
2336 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
2337 pIdentifier->device_id = wined3d_settings.pci_device_id;
2340 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
2342 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
2343 pIdentifier->vendor_id = wined3d_settings.pci_vendor_id;
2346 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2348 return WINED3D_OK;
2351 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2352 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2354 short redSize, greenSize, blueSize, alphaSize, colorBits;
2356 if(!cfg)
2357 return FALSE;
2359 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2360 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2362 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2363 return FALSE;
2366 if(cfg->redSize < redSize)
2367 return FALSE;
2369 if(cfg->greenSize < greenSize)
2370 return FALSE;
2372 if(cfg->blueSize < blueSize)
2373 return FALSE;
2375 if(cfg->alphaSize < alphaSize)
2376 return FALSE;
2378 return TRUE;
2379 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2380 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2381 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2382 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2383 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2384 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2385 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2386 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2387 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2388 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2389 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2390 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2391 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2392 } else {
2393 /* Probably a color index mode */
2394 return FALSE;
2397 return FALSE;
2400 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2401 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2403 short depthSize, stencilSize;
2404 BOOL lockable = FALSE;
2406 if(!cfg)
2407 return FALSE;
2409 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2411 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2412 return FALSE;
2415 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
2416 lockable = TRUE;
2418 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2419 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2420 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2421 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2422 return FALSE;
2424 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2425 * allow more stencil bits than requested. */
2426 if(cfg->stencilSize < stencilSize)
2427 return FALSE;
2429 return TRUE;
2432 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2433 WINED3DFORMAT AdapterFormat,
2434 WINED3DFORMAT RenderTargetFormat,
2435 WINED3DFORMAT DepthStencilFormat) {
2436 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2437 int nCfgs;
2438 const WineD3D_PixelFormat *cfgs;
2439 const struct WineD3DAdapter *adapter;
2440 const struct GlPixelFormatDesc *rt_format_desc;
2441 const struct GlPixelFormatDesc *ds_format_desc;
2442 int it;
2444 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2445 This, Adapter,
2446 DeviceType, debug_d3ddevicetype(DeviceType),
2447 AdapterFormat, debug_d3dformat(AdapterFormat),
2448 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2449 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2451 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2452 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2453 return WINED3DERR_INVALIDCALL;
2456 adapter = &This->adapters[Adapter];
2457 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2458 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2459 cfgs = adapter->cfgs;
2460 nCfgs = adapter->nCfgs;
2461 for (it = 0; it < nCfgs; ++it) {
2462 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2464 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2466 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2467 return WINED3D_OK;
2471 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2473 return WINED3DERR_NOTAVAILABLE;
2476 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2477 WINED3DFORMAT SurfaceFormat,
2478 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
2480 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2481 const struct GlPixelFormatDesc *glDesc;
2482 const struct WineD3DAdapter *adapter;
2484 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2485 This,
2486 Adapter,
2487 DeviceType, debug_d3ddevicetype(DeviceType),
2488 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2489 Windowed,
2490 MultiSampleType,
2491 pQualityLevels);
2493 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2494 return WINED3DERR_INVALIDCALL;
2497 /* TODO: handle Windowed, add more quality levels */
2499 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2500 if(pQualityLevels) *pQualityLevels = 1;
2501 return WINED3D_OK;
2504 /* By default multisampling is disabled right now as it causes issues
2505 * on some Nvidia driver versions and it doesn't work well in combination
2506 * with FBOs yet. */
2507 if(!wined3d_settings.allow_multisampling)
2508 return WINED3DERR_NOTAVAILABLE;
2510 adapter = &This->adapters[Adapter];
2511 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2512 if (!glDesc) return WINED3DERR_INVALIDCALL;
2514 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2515 int i, nCfgs;
2516 const WineD3D_PixelFormat *cfgs;
2518 cfgs = adapter->cfgs;
2519 nCfgs = adapter->nCfgs;
2520 for(i=0; i<nCfgs; i++) {
2521 if(cfgs[i].numSamples != MultiSampleType)
2522 continue;
2524 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2525 continue;
2527 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2529 if(pQualityLevels)
2530 *pQualityLevels = 1; /* Guess at a value! */
2531 return WINED3D_OK;
2534 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2535 short redSize, greenSize, blueSize, alphaSize, colorBits;
2536 int i, nCfgs;
2537 const WineD3D_PixelFormat *cfgs;
2539 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2541 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2542 return WINED3DERR_NOTAVAILABLE;
2545 cfgs = adapter->cfgs;
2546 nCfgs = adapter->nCfgs;
2547 for(i=0; i<nCfgs; i++) {
2548 if(cfgs[i].numSamples != MultiSampleType)
2549 continue;
2550 if(cfgs[i].redSize != redSize)
2551 continue;
2552 if(cfgs[i].greenSize != greenSize)
2553 continue;
2554 if(cfgs[i].blueSize != blueSize)
2555 continue;
2556 if(cfgs[i].alphaSize != alphaSize)
2557 continue;
2559 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2561 if(pQualityLevels)
2562 *pQualityLevels = 1; /* Guess at a value! */
2563 return WINED3D_OK;
2566 return WINED3DERR_NOTAVAILABLE;
2569 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2570 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2572 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2573 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2574 UINT nmodes;
2576 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2577 This,
2578 Adapter,
2579 DeviceType, debug_d3ddevicetype(DeviceType),
2580 DisplayFormat, debug_d3dformat(DisplayFormat),
2581 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2582 Windowed);
2584 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2585 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2586 return WINED3DERR_INVALIDCALL;
2589 /* The task of this function is to check whether a certain display / backbuffer format
2590 * combination is available on the given adapter. In fullscreen mode microsoft specified
2591 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2592 * and display format should match exactly.
2593 * In windowed mode format conversion can occur and this depends on the driver. When format
2594 * conversion is done, this function should nevertheless fail and applications need to use
2595 * CheckDeviceFormatConversion.
2596 * At the moment we assume that fullscreen and windowed have the same capabilities */
2598 /* There are only 4 display formats */
2599 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2600 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2601 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2602 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2604 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2605 return WINED3DERR_NOTAVAILABLE;
2608 /* If the requested DisplayFormat is not available, don't continue */
2609 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2610 if(!nmodes) {
2611 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2612 return WINED3DERR_NOTAVAILABLE;
2615 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2616 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2617 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2618 return WINED3DERR_NOTAVAILABLE;
2621 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2622 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
2623 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2624 return WINED3DERR_NOTAVAILABLE;
2627 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2628 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2629 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2630 return WINED3DERR_NOTAVAILABLE;
2633 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2634 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2635 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2636 return WINED3DERR_NOTAVAILABLE;
2639 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2640 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2641 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2642 return WINED3DERR_NOTAVAILABLE;
2645 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2646 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2647 if(FAILED(hr))
2648 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2650 return hr;
2654 /* Check if we support bumpmapping for a format */
2655 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2656 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2658 const struct fragment_pipeline *fp;
2660 switch(format_desc->format)
2662 case WINED3DFMT_R8G8_SNORM:
2663 case WINED3DFMT_R16G16_SNORM:
2664 case WINED3DFMT_L6V5U5:
2665 case WINED3DFMT_X8L8V8U8:
2666 case WINED3DFMT_R8G8B8A8_SNORM:
2667 /* Ask the fixed function pipeline implementation if it can deal
2668 * with the conversion. If we've got a GL extension giving native
2669 * support this will be an identity conversion. */
2670 fp = select_fragment_implementation(adapter, DeviceType);
2671 if (fp->color_fixup_supported(format_desc->color_fixup))
2673 TRACE_(d3d_caps)("[OK]\n");
2674 return TRUE;
2676 TRACE_(d3d_caps)("[FAILED]\n");
2677 return FALSE;
2679 default:
2680 TRACE_(d3d_caps)("[FAILED]\n");
2681 return FALSE;
2685 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2686 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2687 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2689 int it=0;
2691 /* Only allow depth/stencil formats */
2692 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2694 /* Walk through all WGL pixel formats to find a match */
2695 for (it = 0; it < adapter->nCfgs; ++it)
2697 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2698 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2700 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2702 return TRUE;
2707 return FALSE;
2710 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2712 /* The flags entry of a format contains the filtering capability */
2713 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2715 return FALSE;
2718 /* Check the render target capabilities of a format */
2719 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2720 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2722 /* Filter out non-RT formats */
2723 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2725 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2726 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2727 int it;
2728 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2729 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2731 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2732 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2734 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2735 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2736 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2737 TRACE_(d3d_caps)("[FAILED]\n");
2738 return FALSE;
2741 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2742 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2743 for (it = 0; it < adapter->nCfgs; ++it)
2745 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2746 &cfgs[it], check_format_desc))
2748 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2749 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2750 return TRUE;
2753 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2754 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2755 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2756 int it;
2758 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2759 for (it = 0; it < adapter->nCfgs; ++it)
2761 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2762 &cfgs[it], check_format_desc))
2764 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2765 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2766 return TRUE;
2769 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2770 /* For now return TRUE for FBOs until we have some proper checks.
2771 * Note that this function will only be called when the format is around for texturing. */
2772 return TRUE;
2774 return FALSE;
2777 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2779 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2781 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2782 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2783 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2784 return FALSE;
2787 switch (format_desc->format)
2789 case WINED3DFMT_A8R8G8B8:
2790 case WINED3DFMT_X8R8G8B8:
2791 case WINED3DFMT_A4R4G4B4:
2792 case WINED3DFMT_L8:
2793 case WINED3DFMT_A8L8:
2794 case WINED3DFMT_DXT1:
2795 case WINED3DFMT_DXT2:
2796 case WINED3DFMT_DXT3:
2797 case WINED3DFMT_DXT4:
2798 case WINED3DFMT_DXT5:
2799 TRACE_(d3d_caps)("[OK]\n");
2800 return TRUE;
2802 default:
2803 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2804 return FALSE;
2806 return FALSE;
2809 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2810 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2812 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2813 * doing the color fixup in shaders.
2814 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2815 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2817 int vs_selected_mode;
2818 int ps_selected_mode;
2819 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2821 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2822 TRACE_(d3d_caps)("[OK]\n");
2823 return TRUE;
2827 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2828 return FALSE;
2831 /* Check if a format support blending in combination with pixel shaders */
2832 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2833 const struct GlPixelFormatDesc *format_desc)
2835 /* The flags entry of a format contains the post pixel shader blending capability */
2836 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2838 return FALSE;
2841 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2843 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2844 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2845 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2846 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2847 * capability anyway.
2849 * For now lets report this on all formats, but in the future we may want to
2850 * restrict it to some should games need that
2852 return TRUE;
2855 /* Check if a texture format is supported on the given adapter */
2856 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2857 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2859 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2860 const shader_backend_t *shader_backend;
2861 const struct fragment_pipeline *fp;
2863 switch (format_desc->format)
2865 /*****
2866 * supported: RGB(A) formats
2868 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2869 case WINED3DFMT_A8R8G8B8:
2870 case WINED3DFMT_X8R8G8B8:
2871 case WINED3DFMT_R5G6B5:
2872 case WINED3DFMT_X1R5G5B5:
2873 case WINED3DFMT_A1R5G5B5:
2874 case WINED3DFMT_A4R4G4B4:
2875 case WINED3DFMT_A8_UNORM:
2876 case WINED3DFMT_X4R4G4B4:
2877 case WINED3DFMT_R8G8B8A8_UNORM:
2878 case WINED3DFMT_X8B8G8R8:
2879 case WINED3DFMT_A2R10G10B10:
2880 case WINED3DFMT_R10G10B10A2_UNORM:
2881 case WINED3DFMT_R16G16_UNORM:
2882 case WINED3DFMT_R16G16B16A16_UNORM:
2883 TRACE_(d3d_caps)("[OK]\n");
2884 return TRUE;
2886 case WINED3DFMT_R3G3B2:
2887 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2888 return FALSE;
2890 /*****
2891 * supported: Palettized
2893 case WINED3DFMT_P8:
2894 TRACE_(d3d_caps)("[OK]\n");
2895 return TRUE;
2896 /* No Windows driver offers A8P8, so don't offer it either */
2897 case WINED3DFMT_A8P8:
2898 return FALSE;
2900 /*****
2901 * Supported: (Alpha)-Luminance
2903 case WINED3DFMT_L8:
2904 case WINED3DFMT_A8L8:
2905 case WINED3DFMT_L16:
2906 TRACE_(d3d_caps)("[OK]\n");
2907 return TRUE;
2909 /* Not supported on Windows, thus disabled */
2910 case WINED3DFMT_A4L4:
2911 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2912 return FALSE;
2914 /*****
2915 * Supported: Depth/Stencil formats
2917 case WINED3DFMT_D16_LOCKABLE:
2918 case WINED3DFMT_D16_UNORM:
2919 case WINED3DFMT_D15S1:
2920 case WINED3DFMT_D24X8:
2921 case WINED3DFMT_D24X4S4:
2922 case WINED3DFMT_D24S8:
2923 case WINED3DFMT_D24FS8:
2924 case WINED3DFMT_D32:
2925 case WINED3DFMT_D32F_LOCKABLE:
2926 return TRUE;
2928 /*****
2929 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2930 * GL_NV_texture_shader). Emulated by shaders
2932 case WINED3DFMT_R8G8_SNORM:
2933 case WINED3DFMT_X8L8V8U8:
2934 case WINED3DFMT_L6V5U5:
2935 case WINED3DFMT_R8G8B8A8_SNORM:
2936 case WINED3DFMT_R16G16_SNORM:
2937 /* Ask the shader backend if it can deal with the conversion. If
2938 * we've got a GL extension giving native support this will be an
2939 * identity conversion. */
2940 shader_backend = select_shader_backend(adapter, DeviceType);
2941 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2943 TRACE_(d3d_caps)("[OK]\n");
2944 return TRUE;
2946 TRACE_(d3d_caps)("[FAILED]\n");
2947 return FALSE;
2949 case WINED3DFMT_DXT1:
2950 case WINED3DFMT_DXT2:
2951 case WINED3DFMT_DXT3:
2952 case WINED3DFMT_DXT4:
2953 case WINED3DFMT_DXT5:
2954 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2955 TRACE_(d3d_caps)("[OK]\n");
2956 return TRUE;
2958 TRACE_(d3d_caps)("[FAILED]\n");
2959 return FALSE;
2962 /*****
2963 * Odd formats - not supported
2965 case WINED3DFMT_VERTEXDATA:
2966 case WINED3DFMT_R16_UINT:
2967 case WINED3DFMT_R32_UINT:
2968 case WINED3DFMT_R16G16B16A16_SNORM:
2969 case WINED3DFMT_A2W10V10U10:
2970 case WINED3DFMT_W11V11U10:
2971 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2972 return FALSE;
2974 /*****
2975 * WINED3DFMT_CxV8U8: Not supported right now
2977 case WINED3DFMT_CxV8U8:
2978 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2979 return FALSE;
2981 /* YUV formats */
2982 case WINED3DFMT_UYVY:
2983 case WINED3DFMT_YUY2:
2984 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2985 TRACE_(d3d_caps)("[OK]\n");
2986 return TRUE;
2988 TRACE_(d3d_caps)("[FAILED]\n");
2989 return FALSE;
2990 case WINED3DFMT_YV12:
2991 TRACE_(d3d_caps)("[FAILED]\n");
2992 return FALSE;
2994 /* Not supported */
2995 case WINED3DFMT_A8R3G3B2:
2996 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2997 return FALSE;
2999 /* Floating point formats */
3000 case WINED3DFMT_R16_FLOAT:
3001 case WINED3DFMT_R16G16_FLOAT:
3002 case WINED3DFMT_R16G16B16A16_FLOAT:
3003 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
3004 TRACE_(d3d_caps)("[OK]\n");
3005 return TRUE;
3007 TRACE_(d3d_caps)("[FAILED]\n");
3008 return FALSE;
3010 case WINED3DFMT_R32_FLOAT:
3011 case WINED3DFMT_R32G32_FLOAT:
3012 case WINED3DFMT_R32G32B32A32_FLOAT:
3013 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3014 TRACE_(d3d_caps)("[OK]\n");
3015 return TRUE;
3017 TRACE_(d3d_caps)("[FAILED]\n");
3018 return FALSE;
3020 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3021 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3022 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3023 * We can do instancing with all shader versions, but we need vertex shaders.
3025 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3026 * to enable instancing. WineD3D doesn't need that and just ignores it.
3028 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3030 case WINEMAKEFOURCC('I','N','S','T'):
3031 TRACE("ATI Instancing check hack\n");
3032 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
3033 TRACE_(d3d_caps)("[OK]\n");
3034 return TRUE;
3036 TRACE_(d3d_caps)("[FAILED]\n");
3037 return FALSE;
3039 /* Some weird FOURCC formats */
3040 case WINED3DFMT_R8G8_B8G8:
3041 case WINED3DFMT_G8R8_G8B8:
3042 case WINED3DFMT_MULTI2_ARGB8:
3043 TRACE_(d3d_caps)("[FAILED]\n");
3044 return FALSE;
3046 /* Vendor specific formats */
3047 case WINED3DFMT_ATI2N:
3048 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
3049 shader_backend = select_shader_backend(adapter, DeviceType);
3050 fp = select_fragment_implementation(adapter, DeviceType);
3051 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3052 && fp->color_fixup_supported(format_desc->color_fixup))
3054 TRACE_(d3d_caps)("[OK]\n");
3055 return TRUE;
3058 TRACE_(d3d_caps)("[OK]\n");
3059 return TRUE;
3061 TRACE_(d3d_caps)("[FAILED]\n");
3062 return FALSE;
3064 case WINED3DFMT_NVHU:
3065 case WINED3DFMT_NVHS:
3066 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3067 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3068 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3069 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3070 * Applications have to deal with not having NVHS and NVHU.
3072 TRACE_(d3d_caps)("[FAILED]\n");
3073 return FALSE;
3075 case WINED3DFMT_UNKNOWN:
3076 return FALSE;
3078 default:
3079 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3080 break;
3082 return FALSE;
3085 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3086 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3088 const struct blit_shader *blitter;
3090 if(SurfaceType == SURFACE_GDI) {
3091 switch(check_format_desc->format)
3093 case WINED3DFMT_R8G8B8:
3094 case WINED3DFMT_A8R8G8B8:
3095 case WINED3DFMT_X8R8G8B8:
3096 case WINED3DFMT_R5G6B5:
3097 case WINED3DFMT_X1R5G5B5:
3098 case WINED3DFMT_A1R5G5B5:
3099 case WINED3DFMT_A4R4G4B4:
3100 case WINED3DFMT_R3G3B2:
3101 case WINED3DFMT_A8_UNORM:
3102 case WINED3DFMT_A8R3G3B2:
3103 case WINED3DFMT_X4R4G4B4:
3104 case WINED3DFMT_R10G10B10A2_UNORM:
3105 case WINED3DFMT_R8G8B8A8_UNORM:
3106 case WINED3DFMT_X8B8G8R8:
3107 case WINED3DFMT_R16G16_UNORM:
3108 case WINED3DFMT_A2R10G10B10:
3109 case WINED3DFMT_R16G16B16A16_UNORM:
3110 case WINED3DFMT_P8:
3111 TRACE_(d3d_caps)("[OK]\n");
3112 return TRUE;
3113 default:
3114 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3115 return FALSE;
3119 /* All format that are supported for textures are supported for surfaces as well */
3120 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3121 /* All depth stencil formats are supported on surfaces */
3122 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3124 /* If opengl can't process the format natively, the blitter may be able to convert it */
3125 blitter = select_blit_implementation(adapter, DeviceType);
3126 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3128 TRACE_(d3d_caps)("[OK]\n");
3129 return TRUE;
3132 /* Reject other formats */
3133 TRACE_(d3d_caps)("[FAILED]\n");
3134 return FALSE;
3137 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
3139 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3141 if (!GL_LIMITS(vertex_samplers)) {
3142 TRACE_(d3d_caps)("[FAILED]\n");
3143 return FALSE;
3146 switch (format_desc->format)
3148 case WINED3DFMT_R32G32B32A32_FLOAT:
3149 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3150 TRACE_(d3d_caps)("[FAILED]\n");
3151 return FALSE;
3153 TRACE_(d3d_caps)("[OK]\n");
3154 return TRUE;
3156 default:
3157 TRACE_(d3d_caps)("[FAILED]\n");
3158 return FALSE;
3160 return FALSE;
3163 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3164 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3165 WINED3DSURFTYPE SurfaceType) {
3166 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3167 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3168 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3169 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3170 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3171 DWORD UsageCaps = 0;
3173 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3174 This,
3175 Adapter,
3176 DeviceType, debug_d3ddevicetype(DeviceType),
3177 AdapterFormat, debug_d3dformat(AdapterFormat),
3178 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3179 RType, debug_d3dresourcetype(RType),
3180 CheckFormat, debug_d3dformat(CheckFormat));
3182 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3183 return WINED3DERR_INVALIDCALL;
3186 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3188 if(SurfaceType != SURFACE_OPENGL) {
3189 TRACE("[FAILED]\n");
3190 return WINED3DERR_NOTAVAILABLE;
3193 /* Cubetexture allows:
3194 * - D3DUSAGE_AUTOGENMIPMAP
3195 * - D3DUSAGE_DEPTHSTENCIL
3196 * - D3DUSAGE_DYNAMIC
3197 * - D3DUSAGE_NONSECURE (d3d9ex)
3198 * - D3DUSAGE_RENDERTARGET
3199 * - D3DUSAGE_SOFTWAREPROCESSING
3200 * - D3DUSAGE_QUERY_WRAPANDMIP
3202 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3203 /* Check if the texture format is around */
3204 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3206 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3207 /* Check for automatic mipmap generation support */
3208 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3209 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3210 } else {
3211 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3212 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3216 /* Always report dynamic locking */
3217 if(Usage & WINED3DUSAGE_DYNAMIC)
3218 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3220 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3221 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3223 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3224 } else {
3225 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3226 return WINED3DERR_NOTAVAILABLE;
3230 /* Always report software processing */
3231 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3232 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3234 /* Check QUERY_FILTER support */
3235 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3236 if (CheckFilterCapability(adapter, format_desc))
3238 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3239 } else {
3240 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3241 return WINED3DERR_NOTAVAILABLE;
3245 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3246 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3247 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3249 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3250 } else {
3251 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3252 return WINED3DERR_NOTAVAILABLE;
3256 /* Check QUERY_SRGBREAD support */
3257 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3258 if (CheckSrgbReadCapability(adapter, format_desc))
3260 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3261 } else {
3262 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3263 return WINED3DERR_NOTAVAILABLE;
3267 /* Check QUERY_SRGBWRITE support */
3268 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3269 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3271 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3272 } else {
3273 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3274 return WINED3DERR_NOTAVAILABLE;
3278 /* Check QUERY_VERTEXTEXTURE support */
3279 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3280 if (CheckVertexTextureCapability(adapter, format_desc))
3282 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3283 } else {
3284 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3285 return WINED3DERR_NOTAVAILABLE;
3289 /* Check QUERY_WRAPANDMIP support */
3290 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3291 if (CheckWrapAndMipCapability(adapter, format_desc))
3293 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3294 } else {
3295 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3296 return WINED3DERR_NOTAVAILABLE;
3299 } else {
3300 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3301 return WINED3DERR_NOTAVAILABLE;
3303 } else {
3304 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3305 return WINED3DERR_NOTAVAILABLE;
3307 } else if(RType == WINED3DRTYPE_SURFACE) {
3308 /* Surface allows:
3309 * - D3DUSAGE_DEPTHSTENCIL
3310 * - D3DUSAGE_NONSECURE (d3d9ex)
3311 * - D3DUSAGE_RENDERTARGET
3314 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3316 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3317 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3319 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3320 } else {
3321 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3322 return WINED3DERR_NOTAVAILABLE;
3326 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3327 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3329 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3330 } else {
3331 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3332 return WINED3DERR_NOTAVAILABLE;
3336 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3337 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3338 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3340 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3341 } else {
3342 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3343 return WINED3DERR_NOTAVAILABLE;
3346 } else {
3347 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3348 return WINED3DERR_NOTAVAILABLE;
3351 } else if(RType == WINED3DRTYPE_TEXTURE) {
3352 /* Texture allows:
3353 * - D3DUSAGE_AUTOGENMIPMAP
3354 * - D3DUSAGE_DEPTHSTENCIL
3355 * - D3DUSAGE_DMAP
3356 * - D3DUSAGE_DYNAMIC
3357 * - D3DUSAGE_NONSECURE (d3d9ex)
3358 * - D3DUSAGE_RENDERTARGET
3359 * - D3DUSAGE_SOFTWAREPROCESSING
3360 * - D3DUSAGE_TEXTAPI (d3d9ex)
3361 * - D3DUSAGE_QUERY_WRAPANDMIP
3364 if(SurfaceType != SURFACE_OPENGL) {
3365 TRACE("[FAILED]\n");
3366 return WINED3DERR_NOTAVAILABLE;
3369 /* Check if the texture format is around */
3370 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3372 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3373 /* Check for automatic mipmap generation support */
3374 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3375 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3376 } else {
3377 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3378 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3382 /* Always report dynamic locking */
3383 if(Usage & WINED3DUSAGE_DYNAMIC)
3384 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3386 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3387 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3389 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3390 } else {
3391 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3392 return WINED3DERR_NOTAVAILABLE;
3396 /* Always report software processing */
3397 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3398 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3400 /* Check QUERY_FILTER support */
3401 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3402 if (CheckFilterCapability(adapter, format_desc))
3404 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3405 } else {
3406 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3407 return WINED3DERR_NOTAVAILABLE;
3411 /* Check QUERY_LEGACYBUMPMAP support */
3412 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3413 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3415 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3416 } else {
3417 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3418 return WINED3DERR_NOTAVAILABLE;
3422 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3423 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3424 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3426 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3427 } else {
3428 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3429 return WINED3DERR_NOTAVAILABLE;
3433 /* Check QUERY_SRGBREAD support */
3434 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3435 if (CheckSrgbReadCapability(adapter, format_desc))
3437 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3438 } else {
3439 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3440 return WINED3DERR_NOTAVAILABLE;
3444 /* Check QUERY_SRGBWRITE support */
3445 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3446 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3448 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3449 } else {
3450 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3451 return WINED3DERR_NOTAVAILABLE;
3455 /* Check QUERY_VERTEXTEXTURE support */
3456 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3457 if (CheckVertexTextureCapability(adapter, format_desc))
3459 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3460 } else {
3461 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3462 return WINED3DERR_NOTAVAILABLE;
3466 /* Check QUERY_WRAPANDMIP support */
3467 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3468 if (CheckWrapAndMipCapability(adapter, format_desc))
3470 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3471 } else {
3472 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3473 return WINED3DERR_NOTAVAILABLE;
3477 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3478 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3480 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3481 } else {
3482 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3483 return WINED3DERR_NOTAVAILABLE;
3486 } else {
3487 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3488 return WINED3DERR_NOTAVAILABLE;
3490 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3491 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3492 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3494 * Volumetexture allows:
3495 * - D3DUSAGE_DYNAMIC
3496 * - D3DUSAGE_NONSECURE (d3d9ex)
3497 * - D3DUSAGE_SOFTWAREPROCESSING
3498 * - D3DUSAGE_QUERY_WRAPANDMIP
3501 if(SurfaceType != SURFACE_OPENGL) {
3502 TRACE("[FAILED]\n");
3503 return WINED3DERR_NOTAVAILABLE;
3506 /* Check volume texture and volume usage caps */
3507 if(GL_SUPPORT(EXT_TEXTURE3D)) {
3508 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3510 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3511 return WINED3DERR_NOTAVAILABLE;
3514 /* Always report dynamic locking */
3515 if(Usage & WINED3DUSAGE_DYNAMIC)
3516 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3518 /* Always report software processing */
3519 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3520 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3522 /* Check QUERY_FILTER support */
3523 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3524 if (CheckFilterCapability(adapter, format_desc))
3526 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3527 } else {
3528 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3529 return WINED3DERR_NOTAVAILABLE;
3533 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3534 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3535 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3537 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3538 } else {
3539 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3540 return WINED3DERR_NOTAVAILABLE;
3544 /* Check QUERY_SRGBREAD support */
3545 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3546 if (CheckSrgbReadCapability(adapter, format_desc))
3548 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3549 } else {
3550 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3551 return WINED3DERR_NOTAVAILABLE;
3555 /* Check QUERY_SRGBWRITE support */
3556 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3557 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3559 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3560 } else {
3561 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3562 return WINED3DERR_NOTAVAILABLE;
3566 /* Check QUERY_VERTEXTEXTURE support */
3567 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3568 if (CheckVertexTextureCapability(adapter, format_desc))
3570 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3571 } else {
3572 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3573 return WINED3DERR_NOTAVAILABLE;
3577 /* Check QUERY_WRAPANDMIP support */
3578 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3579 if (CheckWrapAndMipCapability(adapter, format_desc))
3581 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3582 } else {
3583 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3584 return WINED3DERR_NOTAVAILABLE;
3587 } else {
3588 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3589 return WINED3DERR_NOTAVAILABLE;
3592 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3593 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3594 * app needing one of those formats, don't advertize them to avoid leading apps into
3595 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3596 * except of R32F.
3598 switch(CheckFormat) {
3599 case WINED3DFMT_P8:
3600 case WINED3DFMT_A4L4:
3601 case WINED3DFMT_R32_FLOAT:
3602 case WINED3DFMT_R16_FLOAT:
3603 case WINED3DFMT_X8L8V8U8:
3604 case WINED3DFMT_L6V5U5:
3605 case WINED3DFMT_R16G16_UNORM:
3606 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3607 return WINED3DERR_NOTAVAILABLE;
3609 case WINED3DFMT_R8G8B8A8_SNORM:
3610 case WINED3DFMT_R16G16_SNORM:
3611 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3612 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3613 return WINED3DERR_NOTAVAILABLE;
3615 break;
3617 case WINED3DFMT_R8G8_SNORM:
3618 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3619 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3620 return WINED3DERR_NOTAVAILABLE;
3622 break;
3624 case WINED3DFMT_DXT1:
3625 case WINED3DFMT_DXT2:
3626 case WINED3DFMT_DXT3:
3627 case WINED3DFMT_DXT4:
3628 case WINED3DFMT_DXT5:
3629 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3630 * compressed texture results in an error. While the D3D refrast does
3631 * support s3tc volumes, at least the nvidia windows driver does not, so
3632 * we're free not to support this format.
3634 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3635 return WINED3DERR_NOTAVAILABLE;
3637 default:
3638 /* Do nothing, continue with checking the format below */
3639 break;
3641 } else if(RType == WINED3DRTYPE_BUFFER){
3642 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3643 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3644 return WINED3DERR_NOTAVAILABLE;
3647 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3648 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3649 * usage flags match. */
3650 if(UsageCaps == Usage) {
3651 return WINED3D_OK;
3652 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3653 return WINED3DOK_NOAUTOGEN;
3654 } else {
3655 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);
3656 return WINED3DERR_NOTAVAILABLE;
3660 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3661 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3662 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3664 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3665 This,
3666 Adapter,
3667 DeviceType, debug_d3ddevicetype(DeviceType),
3668 SourceFormat, debug_d3dformat(SourceFormat),
3669 TargetFormat, debug_d3dformat(TargetFormat));
3670 return WINED3D_OK;
3673 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3675 const shader_backend_t *ret;
3676 int vs_selected_mode;
3677 int ps_selected_mode;
3679 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3680 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3681 ret = &glsl_shader_backend;
3682 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3683 ret = &arb_program_shader_backend;
3684 } else {
3685 ret = &none_shader_backend;
3687 return ret;
3690 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3691 WINED3DDEVTYPE DeviceType)
3693 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3694 int vs_selected_mode;
3695 int ps_selected_mode;
3697 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3698 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3699 return &arbfp_fragment_pipeline;
3700 } else if(ps_selected_mode == SHADER_ATI) {
3701 return &atifs_fragment_pipeline;
3702 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3703 return &nvts_fragment_pipeline;
3704 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3705 return &nvrc_fragment_pipeline;
3706 } else {
3707 return &ffp_fragment_pipeline;
3711 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3713 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3714 int vs_selected_mode;
3715 int ps_selected_mode;
3717 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3718 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3719 return &arbfp_blit;
3720 } else {
3721 return &ffp_blit;
3725 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3726 subset of a D3DCAPS9 structure. However, it has to come via a void *
3727 as the d3d8 interface cannot import the d3d9 header */
3728 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3730 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3731 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3732 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3733 int vs_selected_mode;
3734 int ps_selected_mode;
3735 struct shader_caps shader_caps;
3736 struct fragment_caps fragment_caps;
3737 const shader_backend_t *shader_backend;
3738 const struct fragment_pipeline *frag_pipeline = NULL;
3739 DWORD ckey_caps, blit_caps, fx_caps;
3741 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3743 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3744 return WINED3DERR_INVALIDCALL;
3747 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3749 /* This function should *not* be modifying GL caps
3750 * TODO: move the functionality where it belongs */
3751 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3753 /* ------------------------------------------------
3754 The following fields apply to both d3d8 and d3d9
3755 ------------------------------------------------ */
3756 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3757 pCaps->AdapterOrdinal = Adapter;
3759 pCaps->Caps = 0;
3760 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3761 WINED3DCAPS2_FULLSCREENGAMMA |
3762 WINED3DCAPS2_DYNAMICTEXTURES;
3763 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3764 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3767 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3768 WINED3DCAPS3_COPY_TO_VIDMEM |
3769 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3771 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3772 WINED3DPRESENT_INTERVAL_ONE;
3774 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3775 WINED3DCURSORCAPS_LOWRES;
3777 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3778 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3779 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3780 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3781 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3782 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3783 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3784 WINED3DDEVCAPS_PUREDEVICE |
3785 WINED3DDEVCAPS_HWRASTERIZATION |
3786 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3787 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3788 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3789 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3790 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3791 WINED3DDEVCAPS_RTPATCHES;
3793 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3794 WINED3DPMISCCAPS_CULLCCW |
3795 WINED3DPMISCCAPS_CULLCW |
3796 WINED3DPMISCCAPS_COLORWRITEENABLE |
3797 WINED3DPMISCCAPS_CLIPTLVERTS |
3798 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3799 WINED3DPMISCCAPS_MASKZ |
3800 WINED3DPMISCCAPS_BLENDOP |
3801 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3802 /* TODO:
3803 WINED3DPMISCCAPS_NULLREFERENCE
3804 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3805 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3806 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3807 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3809 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3810 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3812 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3813 WINED3DPRASTERCAPS_PAT |
3814 WINED3DPRASTERCAPS_WFOG |
3815 WINED3DPRASTERCAPS_ZFOG |
3816 WINED3DPRASTERCAPS_FOGVERTEX |
3817 WINED3DPRASTERCAPS_FOGTABLE |
3818 WINED3DPRASTERCAPS_STIPPLE |
3819 WINED3DPRASTERCAPS_SUBPIXEL |
3820 WINED3DPRASTERCAPS_ZTEST |
3821 WINED3DPRASTERCAPS_SCISSORTEST |
3822 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3823 WINED3DPRASTERCAPS_DEPTHBIAS;
3825 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3826 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3827 WINED3DPRASTERCAPS_ZBIAS |
3828 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3830 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3831 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3833 /* FIXME Add:
3834 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3835 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3836 WINED3DPRASTERCAPS_ANTIALIASEDGES
3837 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3838 WINED3DPRASTERCAPS_WBUFFER */
3840 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3841 WINED3DPCMPCAPS_EQUAL |
3842 WINED3DPCMPCAPS_GREATER |
3843 WINED3DPCMPCAPS_GREATEREQUAL |
3844 WINED3DPCMPCAPS_LESS |
3845 WINED3DPCMPCAPS_LESSEQUAL |
3846 WINED3DPCMPCAPS_NEVER |
3847 WINED3DPCMPCAPS_NOTEQUAL;
3849 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3850 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3851 WINED3DPBLENDCAPS_DESTALPHA |
3852 WINED3DPBLENDCAPS_DESTCOLOR |
3853 WINED3DPBLENDCAPS_INVDESTALPHA |
3854 WINED3DPBLENDCAPS_INVDESTCOLOR |
3855 WINED3DPBLENDCAPS_INVSRCALPHA |
3856 WINED3DPBLENDCAPS_INVSRCCOLOR |
3857 WINED3DPBLENDCAPS_ONE |
3858 WINED3DPBLENDCAPS_SRCALPHA |
3859 WINED3DPBLENDCAPS_SRCALPHASAT |
3860 WINED3DPBLENDCAPS_SRCCOLOR |
3861 WINED3DPBLENDCAPS_ZERO;
3863 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3864 WINED3DPBLENDCAPS_DESTCOLOR |
3865 WINED3DPBLENDCAPS_INVDESTALPHA |
3866 WINED3DPBLENDCAPS_INVDESTCOLOR |
3867 WINED3DPBLENDCAPS_INVSRCALPHA |
3868 WINED3DPBLENDCAPS_INVSRCCOLOR |
3869 WINED3DPBLENDCAPS_ONE |
3870 WINED3DPBLENDCAPS_SRCALPHA |
3871 WINED3DPBLENDCAPS_SRCCOLOR |
3872 WINED3DPBLENDCAPS_ZERO;
3873 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3874 * according to the glBlendFunc manpage
3876 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3877 * legacy settings for srcblend only
3880 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3881 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3882 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3886 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3887 WINED3DPCMPCAPS_EQUAL |
3888 WINED3DPCMPCAPS_GREATER |
3889 WINED3DPCMPCAPS_GREATEREQUAL |
3890 WINED3DPCMPCAPS_LESS |
3891 WINED3DPCMPCAPS_LESSEQUAL |
3892 WINED3DPCMPCAPS_NEVER |
3893 WINED3DPCMPCAPS_NOTEQUAL;
3895 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3896 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3897 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3898 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3899 WINED3DPSHADECAPS_COLORFLATRGB |
3900 WINED3DPSHADECAPS_FOGFLAT |
3901 WINED3DPSHADECAPS_FOGGOURAUD |
3902 WINED3DPSHADECAPS_SPECULARFLATRGB;
3904 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3905 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3906 WINED3DPTEXTURECAPS_TRANSPARENCY |
3907 WINED3DPTEXTURECAPS_BORDER |
3908 WINED3DPTEXTURECAPS_MIPMAP |
3909 WINED3DPTEXTURECAPS_PROJECTED |
3910 WINED3DPTEXTURECAPS_PERSPECTIVE;
3912 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3913 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3914 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3917 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3918 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3919 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3920 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3923 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3924 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3925 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3926 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3930 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3931 WINED3DPTFILTERCAPS_MAGFPOINT |
3932 WINED3DPTFILTERCAPS_MINFLINEAR |
3933 WINED3DPTFILTERCAPS_MINFPOINT |
3934 WINED3DPTFILTERCAPS_MIPFLINEAR |
3935 WINED3DPTFILTERCAPS_MIPFPOINT |
3936 WINED3DPTFILTERCAPS_LINEAR |
3937 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3938 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3939 WINED3DPTFILTERCAPS_MIPLINEAR |
3940 WINED3DPTFILTERCAPS_MIPNEAREST |
3941 WINED3DPTFILTERCAPS_NEAREST;
3943 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3944 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3945 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3948 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3949 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3950 WINED3DPTFILTERCAPS_MAGFPOINT |
3951 WINED3DPTFILTERCAPS_MINFLINEAR |
3952 WINED3DPTFILTERCAPS_MINFPOINT |
3953 WINED3DPTFILTERCAPS_MIPFLINEAR |
3954 WINED3DPTFILTERCAPS_MIPFPOINT |
3955 WINED3DPTFILTERCAPS_LINEAR |
3956 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3957 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3958 WINED3DPTFILTERCAPS_MIPLINEAR |
3959 WINED3DPTFILTERCAPS_MIPNEAREST |
3960 WINED3DPTFILTERCAPS_NEAREST;
3962 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3963 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3964 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3966 } else
3967 pCaps->CubeTextureFilterCaps = 0;
3969 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3970 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3971 WINED3DPTFILTERCAPS_MAGFPOINT |
3972 WINED3DPTFILTERCAPS_MINFLINEAR |
3973 WINED3DPTFILTERCAPS_MINFPOINT |
3974 WINED3DPTFILTERCAPS_MIPFLINEAR |
3975 WINED3DPTFILTERCAPS_MIPFPOINT |
3976 WINED3DPTFILTERCAPS_LINEAR |
3977 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3978 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3979 WINED3DPTFILTERCAPS_MIPLINEAR |
3980 WINED3DPTFILTERCAPS_MIPNEAREST |
3981 WINED3DPTFILTERCAPS_NEAREST;
3982 } else
3983 pCaps->VolumeTextureFilterCaps = 0;
3985 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3986 WINED3DPTADDRESSCAPS_CLAMP |
3987 WINED3DPTADDRESSCAPS_WRAP;
3989 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3990 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3992 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3993 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3995 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3996 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3999 if (GL_SUPPORT(EXT_TEXTURE3D)) {
4000 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4001 WINED3DPTADDRESSCAPS_CLAMP |
4002 WINED3DPTADDRESSCAPS_WRAP;
4003 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
4004 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4006 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
4007 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4009 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
4010 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4012 } else
4013 pCaps->VolumeTextureAddressCaps = 0;
4015 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4016 WINED3DLINECAPS_ZTEST |
4017 WINED3DLINECAPS_BLEND |
4018 WINED3DLINECAPS_ALPHACMP |
4019 WINED3DLINECAPS_FOG;
4020 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4021 * idea how generating the smoothing alpha values works; the result is different
4024 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
4025 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
4027 if(GL_SUPPORT(EXT_TEXTURE3D))
4028 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
4029 else
4030 pCaps->MaxVolumeExtent = 0;
4032 pCaps->MaxTextureRepeat = 32768;
4033 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
4034 pCaps->MaxVertexW = 1.0f;
4036 pCaps->GuardBandLeft = 0.0f;
4037 pCaps->GuardBandTop = 0.0f;
4038 pCaps->GuardBandRight = 0.0f;
4039 pCaps->GuardBandBottom = 0.0f;
4041 pCaps->ExtentsAdjust = 0.0f;
4043 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4044 WINED3DSTENCILCAPS_INCRSAT |
4045 WINED3DSTENCILCAPS_INVERT |
4046 WINED3DSTENCILCAPS_KEEP |
4047 WINED3DSTENCILCAPS_REPLACE |
4048 WINED3DSTENCILCAPS_ZERO;
4049 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
4050 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4051 WINED3DSTENCILCAPS_INCR;
4053 if (GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
4054 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4057 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4059 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
4060 pCaps->MaxActiveLights = GL_LIMITS(lights);
4062 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
4063 pCaps->MaxVertexBlendMatrixIndex = 0;
4065 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
4066 pCaps->MaxPointSize = GL_LIMITS(pointsize);
4069 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4070 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4071 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4072 WINED3DVTXPCAPS_LOCALVIEWER |
4073 WINED3DVTXPCAPS_VERTEXFOG |
4074 WINED3DVTXPCAPS_TEXGEN;
4075 /* FIXME: Add
4076 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4078 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4079 pCaps->MaxVertexIndex = 0xFFFFF;
4080 pCaps->MaxStreams = MAX_STREAMS;
4081 pCaps->MaxStreamStride = 1024;
4083 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4084 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4085 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4086 pCaps->MaxNpatchTessellationLevel = 0;
4087 pCaps->MasterAdapterOrdinal = 0;
4088 pCaps->AdapterOrdinalInGroup = 0;
4089 pCaps->NumberOfAdaptersInGroup = 1;
4091 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
4093 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4094 WINED3DPTFILTERCAPS_MAGFPOINT |
4095 WINED3DPTFILTERCAPS_MINFLINEAR |
4096 WINED3DPTFILTERCAPS_MAGFLINEAR;
4097 pCaps->VertexTextureFilterCaps = 0;
4099 memset(&shader_caps, 0, sizeof(shader_caps));
4100 shader_backend = select_shader_backend(adapter, DeviceType);
4101 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4103 memset(&fragment_caps, 0, sizeof(fragment_caps));
4104 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4105 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4107 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4108 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4110 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4111 * Ignore shader model capabilities if disabled in config
4113 if(vs_selected_mode == SHADER_NONE) {
4114 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4115 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4116 pCaps->MaxVertexShaderConst = 0;
4117 } else {
4118 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4119 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4122 if(ps_selected_mode == SHADER_NONE) {
4123 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4124 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4125 pCaps->PixelShader1xMaxValue = 0.0f;
4126 } else {
4127 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4128 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4131 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4132 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4133 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4135 pCaps->VS20Caps = shader_caps.VS20Caps;
4136 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4137 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4138 pCaps->PS20Caps = shader_caps.PS20Caps;
4139 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4140 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4142 /* The following caps are shader specific, but they are things we cannot detect, or which
4143 * are the same among all shader models. So to avoid code duplication set the shader version
4144 * specific, but otherwise constant caps here
4146 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4147 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4148 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4149 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4150 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4151 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
4152 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4154 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4155 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
4156 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
4157 pCaps->VS20Caps.Caps = 0;
4158 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4159 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
4160 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4162 pCaps->MaxVShaderInstructionsExecuted = 65535;
4163 pCaps->MaxVertexShader30InstructionSlots = 0;
4164 } else { /* VS 1.x */
4165 pCaps->VS20Caps.Caps = 0;
4166 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4167 pCaps->VS20Caps.NumTemps = 0;
4168 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4170 pCaps->MaxVShaderInstructionsExecuted = 0;
4171 pCaps->MaxVertexShader30InstructionSlots = 0;
4174 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4175 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4176 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4178 /* 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 */
4179 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4180 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4181 WINED3DPS20CAPS_PREDICATION |
4182 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4183 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4184 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4185 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
4186 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4187 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4189 pCaps->MaxPShaderInstructionsExecuted = 65535;
4190 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
4191 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
4192 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4193 pCaps->PS20Caps.Caps = 0;
4194 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4195 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
4196 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4197 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4199 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4200 pCaps->MaxPixelShader30InstructionSlots = 0;
4201 } else { /* PS 1.x */
4202 pCaps->PS20Caps.Caps = 0;
4203 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4204 pCaps->PS20Caps.NumTemps = 0;
4205 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4206 pCaps->PS20Caps.NumInstructionSlots = 0;
4208 pCaps->MaxPShaderInstructionsExecuted = 0;
4209 pCaps->MaxPixelShader30InstructionSlots = 0;
4212 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4213 /* OpenGL supports all the formats below, perhaps not always
4214 * without conversion, but it supports them.
4215 * Further GLSL doesn't seem to have an official unsigned type so
4216 * don't advertise it yet as I'm not sure how we handle it.
4217 * We might need to add some clamping in the shader engine to
4218 * support it.
4219 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4220 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4221 WINED3DDTCAPS_UBYTE4N |
4222 WINED3DDTCAPS_SHORT2N |
4223 WINED3DDTCAPS_SHORT4N;
4224 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
4225 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4226 WINED3DDTCAPS_FLOAT16_4;
4228 } else
4229 pCaps->DeclTypes = 0;
4231 /* Set DirectDraw helper Caps */
4232 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4233 WINEDDCKEYCAPS_SRCBLT;
4234 fx_caps = WINEDDFXCAPS_BLTALPHA |
4235 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4236 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4237 WINEDDFXCAPS_BLTROTATION90 |
4238 WINEDDFXCAPS_BLTSHRINKX |
4239 WINEDDFXCAPS_BLTSHRINKXN |
4240 WINEDDFXCAPS_BLTSHRINKY |
4241 WINEDDFXCAPS_BLTSHRINKXN |
4242 WINEDDFXCAPS_BLTSTRETCHX |
4243 WINEDDFXCAPS_BLTSTRETCHXN |
4244 WINEDDFXCAPS_BLTSTRETCHY |
4245 WINEDDFXCAPS_BLTSTRETCHYN;
4246 blit_caps = WINEDDCAPS_BLT |
4247 WINEDDCAPS_BLTCOLORFILL |
4248 WINEDDCAPS_BLTDEPTHFILL |
4249 WINEDDCAPS_BLTSTRETCH |
4250 WINEDDCAPS_CANBLTSYSMEM |
4251 WINEDDCAPS_CANCLIP |
4252 WINEDDCAPS_CANCLIPSTRETCHED |
4253 WINEDDCAPS_COLORKEY |
4254 WINEDDCAPS_COLORKEYHWASSIST |
4255 WINEDDCAPS_ALIGNBOUNDARYSRC;
4257 /* Fill the ddraw caps structure */
4258 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4259 WINEDDCAPS_PALETTE |
4260 blit_caps;
4261 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4262 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4263 WINEDDCAPS2_PRIMARYGAMMA |
4264 WINEDDCAPS2_WIDESURFACES |
4265 WINEDDCAPS2_CANRENDERWINDOWED;
4266 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4267 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4268 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4269 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4270 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4271 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4272 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4273 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4274 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4276 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4277 WINEDDSCAPS_BACKBUFFER |
4278 WINEDDSCAPS_FLIP |
4279 WINEDDSCAPS_FRONTBUFFER |
4280 WINEDDSCAPS_OFFSCREENPLAIN |
4281 WINEDDSCAPS_PALETTE |
4282 WINEDDSCAPS_PRIMARYSURFACE |
4283 WINEDDSCAPS_SYSTEMMEMORY |
4284 WINEDDSCAPS_VIDEOMEMORY |
4285 WINEDDSCAPS_VISIBLE;
4286 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4288 /* Set D3D caps if OpenGL is available. */
4289 if (adapter->opengl)
4291 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4292 WINEDDSCAPS_MIPMAP |
4293 WINEDDSCAPS_TEXTURE |
4294 WINEDDSCAPS_ZBUFFER;
4295 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4298 return WINED3D_OK;
4301 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
4302 and fields being inserted in the middle, a new structure is used in place */
4303 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
4304 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
4305 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
4307 IWineD3DDeviceImpl *object = NULL;
4308 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4309 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
4310 WINED3DDISPLAYMODE mode;
4311 const struct fragment_pipeline *frag_pipeline = NULL;
4312 int i;
4313 struct fragment_caps ffp_caps;
4314 struct shader_caps shader_caps;
4315 HRESULT hr;
4317 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4318 * number and create a device without a 3D adapter for 2D only operation.
4320 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4321 return WINED3DERR_INVALIDCALL;
4324 /* Create a WineD3DDevice object */
4325 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
4326 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4327 TRACE("Created WineD3DDevice object @ %p\n", object);
4328 if (NULL == object) {
4329 return WINED3DERR_OUTOFVIDEOMEMORY;
4332 /* Set up initial COM information */
4333 object->lpVtbl = &IWineD3DDevice_Vtbl;
4334 object->ref = 1;
4335 object->wineD3D = iface;
4336 object->adapter = This->adapter_count ? adapter : NULL;
4337 IWineD3D_AddRef(object->wineD3D);
4338 object->parent = parent;
4339 object->device_parent = device_parent;
4340 list_init(&object->resources);
4341 list_init(&object->shaders);
4343 if(This->dxVersion == 7) {
4344 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
4345 } else {
4346 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4348 object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4350 /* Set the state up as invalid until the device is fully created */
4351 object->state = WINED3DERR_DRIVERINTERNALERROR;
4353 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
4354 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4356 /* Save the creation parameters */
4357 object->createParms.AdapterOrdinal = Adapter;
4358 object->createParms.DeviceType = DeviceType;
4359 object->createParms.hFocusWindow = hFocusWindow;
4360 object->createParms.BehaviorFlags = BehaviourFlags;
4362 /* Initialize other useful values */
4363 object->adapterNo = Adapter;
4364 object->devType = DeviceType;
4366 select_shader_mode(&adapter->gl_info, DeviceType,
4367 &object->ps_selected_mode, &object->vs_selected_mode);
4368 object->shader_backend = select_shader_backend(adapter, DeviceType);
4370 memset(&shader_caps, 0, sizeof(shader_caps));
4371 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4372 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
4373 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
4374 object->vs_clipping = shader_caps.VSClipping;
4376 memset(&ffp_caps, 0, sizeof(ffp_caps));
4377 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4378 object->frag_pipe = frag_pipeline;
4379 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
4380 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
4381 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
4382 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
4383 ffp_vertexstate_template, frag_pipeline, misc_state_template);
4385 if (FAILED(hr)) {
4386 IWineD3D_Release(object->wineD3D);
4387 HeapFree(GetProcessHeap(), 0, object);
4389 return hr;
4392 object->blitter = select_blit_implementation(adapter, DeviceType);
4394 /* set the state of the device to valid */
4395 object->state = WINED3D_OK;
4397 /* Get the initial screen setup for ddraw */
4398 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4400 object->ddraw_width = mode.Width;
4401 object->ddraw_height = mode.Height;
4402 object->ddraw_format = mode.Format;
4404 for(i = 0; i < PATCHMAP_SIZE; i++) {
4405 list_init(&object->patches[i]);
4408 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4410 return WINED3D_OK;
4413 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4414 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4415 IUnknown_AddRef(This->parent);
4416 *pParent = This->parent;
4417 return WINED3D_OK;
4420 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
4421 IUnknown* surfaceParent;
4422 TRACE("(%p) call back\n", pSurface);
4424 /* Now, release the parent, which will take care of cleaning up the surface for us */
4425 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
4426 IUnknown_Release(surfaceParent);
4427 return IUnknown_Release(surfaceParent);
4430 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
4431 IUnknown* volumeParent;
4432 TRACE("(%p) call back\n", pVolume);
4434 /* Now, release the parent, which will take care of cleaning up the volume for us */
4435 IWineD3DVolume_GetParent(pVolume, &volumeParent);
4436 IUnknown_Release(volumeParent);
4437 return IUnknown_Release(volumeParent);
4440 static void WINE_GLAPI invalid_func(const void *data)
4442 ERR("Invalid vertex attribute function called\n");
4443 DebugBreak();
4446 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4448 ERR("Invalid texcoord function called\n");
4449 DebugBreak();
4452 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4453 * the extension detection and are used in drawStridedSlow
4455 static void WINE_GLAPI position_d3dcolor(const void *data)
4457 DWORD pos = *((const DWORD *)data);
4459 FIXME("Add a test for fixed function position from d3dcolor type\n");
4460 glVertex4s(D3DCOLOR_B_R(pos),
4461 D3DCOLOR_B_G(pos),
4462 D3DCOLOR_B_B(pos),
4463 D3DCOLOR_B_A(pos));
4466 static void WINE_GLAPI position_float4(const void *data)
4468 const GLfloat *pos = data;
4470 if (pos[3] != 0.0f && pos[3] != 1.0f)
4472 float w = 1.0f / pos[3];
4474 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4476 else
4478 glVertex3fv(pos);
4482 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4484 DWORD diffuseColor = *((const DWORD *)data);
4486 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4487 D3DCOLOR_B_G(diffuseColor),
4488 D3DCOLOR_B_B(diffuseColor),
4489 D3DCOLOR_B_A(diffuseColor));
4492 static void WINE_GLAPI specular_d3dcolor(const void *data)
4494 DWORD specularColor = *((const DWORD *)data);
4495 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4496 D3DCOLOR_B_G(specularColor),
4497 D3DCOLOR_B_B(specularColor)};
4499 specular_func_3ubv(d);
4502 static void WINE_GLAPI warn_no_specular_func(const void *data)
4504 WARN("GL_EXT_secondary_color not supported\n");
4507 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4509 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4510 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4511 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4512 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4513 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4514 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4515 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4516 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4517 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4518 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4519 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4520 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4521 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4522 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4523 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4524 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4525 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4527 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4528 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4529 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4530 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4531 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4532 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4533 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4534 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4535 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4536 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4537 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4538 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4539 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4540 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4541 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4542 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4543 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4545 /* No 4 component entry points here */
4546 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4547 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4548 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4549 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4550 } else {
4551 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4553 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4554 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4555 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4556 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4557 } else {
4558 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4560 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4561 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4562 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4563 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4564 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4565 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4566 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4567 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4568 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4569 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4570 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4571 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4573 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4574 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4576 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4577 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4578 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4579 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4580 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4581 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4582 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4583 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4584 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4585 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4586 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4587 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4588 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4589 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4590 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4591 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4592 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4594 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4595 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4596 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4597 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4598 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4599 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4600 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4601 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4602 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4603 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4604 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4605 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4606 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4607 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4608 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4609 if (GL_SUPPORT(NV_HALF_FLOAT))
4611 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4612 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4613 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4614 } else {
4615 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4616 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4620 BOOL InitAdapters(IWineD3DImpl *This)
4622 static HMODULE mod_gl;
4623 BOOL ret;
4624 int ps_selected_mode, vs_selected_mode;
4626 /* No need to hold any lock. The calling library makes sure only one thread calls
4627 * wined3d simultaneously
4630 TRACE("Initializing adapters\n");
4632 if(!mod_gl) {
4633 #ifdef USE_WIN32_OPENGL
4634 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4635 mod_gl = LoadLibraryA("opengl32.dll");
4636 if(!mod_gl) {
4637 ERR("Can't load opengl32.dll!\n");
4638 goto nogl_adapter;
4640 #else
4641 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4642 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4643 mod_gl = GetModuleHandleA("gdi32.dll");
4644 #endif
4647 /* Load WGL core functions from opengl32.dll */
4648 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4649 WGL_FUNCS_GEN;
4650 #undef USE_WGL_FUNC
4652 if(!pwglGetProcAddress) {
4653 ERR("Unable to load wglGetProcAddress!\n");
4654 goto nogl_adapter;
4657 /* Dynamically load all GL core functions */
4658 GL_FUNCS_GEN;
4659 #undef USE_GL_FUNC
4661 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4662 * otherwise because we have to use winex11.drv's override
4664 #ifdef USE_WIN32_OPENGL
4665 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4666 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4667 #else
4668 glFinish = (void*)pwglGetProcAddress("wglFinish");
4669 glFlush = (void*)pwglGetProcAddress("wglFlush");
4670 #endif
4672 glEnableWINE = glEnable;
4673 glDisableWINE = glDisable;
4675 /* For now only one default adapter */
4677 struct WineD3DAdapter *adapter = &This->adapters[0];
4678 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4679 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4680 int iPixelFormat;
4681 int res;
4682 int i;
4683 WineD3D_PixelFormat *cfgs;
4684 DISPLAY_DEVICEW DisplayDevice;
4685 HDC hdc;
4687 TRACE("Initializing default adapter\n");
4688 adapter->num = 0;
4689 adapter->monitorPoint.x = -1;
4690 adapter->monitorPoint.y = -1;
4692 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4694 ERR("Failed to get a gl context for default adapter\n");
4695 goto nogl_adapter;
4698 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4699 if(!ret) {
4700 ERR("Failed to initialize gl caps for default adapter\n");
4701 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4702 goto nogl_adapter;
4704 ret = initPixelFormats(&adapter->gl_info);
4705 if(!ret) {
4706 ERR("Failed to init gl formats\n");
4707 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4708 goto nogl_adapter;
4711 hdc = fake_gl_ctx.dc;
4713 adapter->driver = "Display";
4714 adapter->description = "Direct3D HAL";
4716 /* Use the VideoRamSize registry setting when set */
4717 if(wined3d_settings.emulated_textureram)
4718 adapter->TextureRam = wined3d_settings.emulated_textureram;
4719 else
4720 adapter->TextureRam = adapter->gl_info.vidmem;
4721 adapter->UsedTextureRam = 0;
4722 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4724 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4725 DisplayDevice.cb = sizeof(DisplayDevice);
4726 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4727 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4728 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4730 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4732 int attribute;
4733 int attribs[10];
4734 int values[10];
4735 int nAttribs = 0;
4737 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4738 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4740 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4741 cfgs = adapter->cfgs;
4742 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4743 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4744 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4745 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4746 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4747 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4748 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4749 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4750 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4751 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4753 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4755 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4757 if(!res)
4758 continue;
4760 /* Cache the pixel format */
4761 cfgs->iPixelFormat = iPixelFormat;
4762 cfgs->redSize = values[0];
4763 cfgs->greenSize = values[1];
4764 cfgs->blueSize = values[2];
4765 cfgs->alphaSize = values[3];
4766 cfgs->depthSize = values[4];
4767 cfgs->stencilSize = values[5];
4768 cfgs->windowDrawable = values[6];
4769 cfgs->iPixelType = values[7];
4770 cfgs->doubleBuffer = values[8];
4771 cfgs->auxBuffers = values[9];
4773 cfgs->pbufferDrawable = FALSE;
4774 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4775 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4776 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4777 int value;
4778 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4779 cfgs->pbufferDrawable = value;
4782 cfgs->numSamples = 0;
4783 /* Check multisample support */
4784 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4785 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4786 int value[2];
4787 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4788 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4789 * value[1] = number of multi sample buffers*/
4790 if(value[0])
4791 cfgs->numSamples = value[1];
4795 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);
4796 cfgs++;
4799 else
4801 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4802 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4803 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4805 cfgs = adapter->cfgs;
4806 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4808 PIXELFORMATDESCRIPTOR ppfd;
4810 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4811 if(!res)
4812 continue;
4814 /* We only want HW acceleration using an OpenGL ICD driver.
4815 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4816 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4818 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4820 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4821 continue;
4824 cfgs->iPixelFormat = iPixelFormat;
4825 cfgs->redSize = ppfd.cRedBits;
4826 cfgs->greenSize = ppfd.cGreenBits;
4827 cfgs->blueSize = ppfd.cBlueBits;
4828 cfgs->alphaSize = ppfd.cAlphaBits;
4829 cfgs->depthSize = ppfd.cDepthBits;
4830 cfgs->stencilSize = ppfd.cStencilBits;
4831 cfgs->pbufferDrawable = 0;
4832 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4833 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4834 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4835 cfgs->auxBuffers = ppfd.cAuxBuffers;
4836 cfgs->numSamples = 0;
4838 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);
4839 cfgs++;
4840 adapter->nCfgs++;
4843 /* 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 */
4844 if(!adapter->nCfgs)
4846 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4848 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4849 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4850 goto nogl_adapter;
4854 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4855 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4856 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4857 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4858 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4859 * driver is allowed to consume more bits EXCEPT for stencil bits.
4861 * Mark an adapter with this broken stencil behavior.
4863 adapter->brokenStencil = TRUE;
4864 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4866 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4867 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4868 adapter->brokenStencil = FALSE;
4869 break;
4873 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4875 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4876 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4877 fillGLAttribFuncs(&adapter->gl_info);
4878 adapter->opengl = TRUE;
4880 This->adapter_count = 1;
4881 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4883 return TRUE;
4885 nogl_adapter:
4886 /* Initialize an adapter for ddraw-only memory counting */
4887 memset(This->adapters, 0, sizeof(This->adapters));
4888 This->adapters[0].num = 0;
4889 This->adapters[0].opengl = FALSE;
4890 This->adapters[0].monitorPoint.x = -1;
4891 This->adapters[0].monitorPoint.y = -1;
4893 This->adapters[0].driver = "Display";
4894 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4895 if(wined3d_settings.emulated_textureram) {
4896 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4897 } else {
4898 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4901 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4903 This->adapter_count = 1;
4904 return FALSE;
4907 /**********************************************************
4908 * IWineD3D VTbl follows
4909 **********************************************************/
4911 const IWineD3DVtbl IWineD3D_Vtbl =
4913 /* IUnknown */
4914 IWineD3DImpl_QueryInterface,
4915 IWineD3DImpl_AddRef,
4916 IWineD3DImpl_Release,
4917 /* IWineD3D */
4918 IWineD3DImpl_GetParent,
4919 IWineD3DImpl_GetAdapterCount,
4920 IWineD3DImpl_RegisterSoftwareDevice,
4921 IWineD3DImpl_GetAdapterMonitor,
4922 IWineD3DImpl_GetAdapterModeCount,
4923 IWineD3DImpl_EnumAdapterModes,
4924 IWineD3DImpl_GetAdapterDisplayMode,
4925 IWineD3DImpl_GetAdapterIdentifier,
4926 IWineD3DImpl_CheckDeviceMultiSampleType,
4927 IWineD3DImpl_CheckDepthStencilMatch,
4928 IWineD3DImpl_CheckDeviceType,
4929 IWineD3DImpl_CheckDeviceFormat,
4930 IWineD3DImpl_CheckDeviceFormatConversion,
4931 IWineD3DImpl_GetDeviceCaps,
4932 IWineD3DImpl_CreateDevice