dplayx: Adjust GetCaps behaviour to documentation
[wine/gsoc_dplay.git] / dlls / wined3d / directx.c
blob5e66f340b207072e65f2e09890f4ce262b107db9
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_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
104 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
105 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
106 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
107 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
108 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
109 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
110 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
111 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
112 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
113 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
114 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
115 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
116 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
117 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
118 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
119 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
120 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
122 /* NV */
123 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
124 {"GL_NV_fence", NV_FENCE, 0 },
125 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
126 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
127 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
128 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
129 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
130 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
131 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
132 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
133 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
134 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
135 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
136 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
137 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
138 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
139 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
140 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
141 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
142 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
143 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
145 /* SGI */
146 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
149 /**********************************************************
150 * Utility functions follow
151 **********************************************************/
153 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
154 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
155 WINED3DDEVTYPE DeviceType);
156 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
157 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
159 /* lookup tables */
160 const int minLookup[MAX_LOOKUPS] =
162 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
165 const int maxLookup[MAX_LOOKUPS] =
167 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
170 DWORD *stateLookup[MAX_LOOKUPS];
172 const struct min_lookup minMipLookup[] =
174 /* NONE POINT LINEAR */
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
176 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
177 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
180 const struct min_lookup minMipLookup_noFilter[] =
182 /* NONE POINT LINEAR */
183 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
185 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
188 const struct min_lookup minMipLookup_noMip[] =
190 /* NONE POINT LINEAR */
191 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
192 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
193 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
196 const GLenum magLookup[] =
198 /* NONE POINT LINEAR */
199 GL_NEAREST, GL_NEAREST, GL_LINEAR,
202 const GLenum magLookup_noFilter[] =
204 /* NONE POINT LINEAR */
205 GL_NEAREST, GL_NEAREST, GL_NEAREST,
208 /* drawStridedSlow attributes */
209 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
210 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
211 glAttribFunc specular_func_3ubv;
212 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
213 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
214 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
217 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
218 * i.e., there is no GL Context - Get a default rendering context to enable the
219 * function query some info from GL.
222 struct wined3d_fake_gl_ctx
224 HDC dc;
225 HWND wnd;
226 HGLRC gl_ctx;
229 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
231 TRACE_(d3d_caps)("Destroying fake GL context.\n");
233 if (!pwglMakeCurrent(NULL, NULL))
235 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
238 if (!pwglDeleteContext(ctx->gl_ctx))
240 DWORD err = GetLastError();
241 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
244 ReleaseDC(ctx->wnd, ctx->dc);
245 DestroyWindow(ctx->wnd);
248 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
250 PIXELFORMATDESCRIPTOR pfd;
251 int iPixelFormat;
253 TRACE("getting context...\n");
255 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
256 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
257 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
258 if (!ctx->wnd)
260 ERR_(d3d_caps)("Failed to create a window.\n");
261 goto fail;
264 ctx->dc = GetDC(ctx->wnd);
265 if (!ctx->dc)
267 ERR_(d3d_caps)("Failed to get a DC.\n");
268 goto fail;
271 /* PixelFormat selection */
272 ZeroMemory(&pfd, sizeof(pfd));
273 pfd.nSize = sizeof(pfd);
274 pfd.nVersion = 1;
275 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
276 pfd.iPixelType = PFD_TYPE_RGBA;
277 pfd.cColorBits = 32;
278 pfd.iLayerType = PFD_MAIN_PLANE;
280 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
281 if (!iPixelFormat)
283 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
284 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
285 goto fail;
287 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
288 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
290 /* Create a GL context. */
291 ctx->gl_ctx = pwglCreateContext(ctx->dc);
292 if (!ctx->gl_ctx)
294 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
295 goto fail;
298 /* Make it the current GL context. */
299 if (!context_set_current(NULL))
301 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
304 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
306 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
307 goto fail;
310 return TRUE;
312 fail:
313 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
314 ctx->gl_ctx = NULL;
315 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
316 ctx->dc = NULL;
317 if (ctx->wnd) DestroyWindow(ctx->wnd);
318 ctx->wnd = NULL;
320 return FALSE;
323 /* Adjust the amount of used texture memory */
324 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
325 struct WineD3DAdapter *adapter = D3DDevice->adapter;
327 adapter->UsedTextureRam += glram;
328 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
329 return adapter->UsedTextureRam;
332 /**********************************************************
333 * IUnknown parts follows
334 **********************************************************/
336 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
340 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
341 if (IsEqualGUID(riid, &IID_IUnknown)
342 || IsEqualGUID(riid, &IID_IWineD3DBase)
343 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
344 IUnknown_AddRef(iface);
345 *ppobj = This;
346 return S_OK;
348 *ppobj = NULL;
349 return E_NOINTERFACE;
352 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
353 IWineD3DImpl *This = (IWineD3DImpl *)iface;
354 ULONG refCount = InterlockedIncrement(&This->ref);
356 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
357 return refCount;
360 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
361 IWineD3DImpl *This = (IWineD3DImpl *)iface;
362 ULONG ref;
363 TRACE("(%p) : Releasing from %d\n", This, This->ref);
364 ref = InterlockedDecrement(&This->ref);
365 if (ref == 0) {
366 unsigned int i;
368 for (i = 0; i < This->adapter_count; ++i)
370 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
372 HeapFree(GetProcessHeap(), 0, This);
375 return ref;
378 /* Set the shader type for this device, depending on the given capabilities,
379 * the device type, and the user preferences in wined3d_settings */
381 static void select_shader_mode(const struct wined3d_gl_info *gl_info,
382 WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
384 if (wined3d_settings.vs_mode == VS_NONE) {
385 *vs_selected = SHADER_NONE;
386 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
387 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
388 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
389 * shaders only on this card. */
390 if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2])
391 *vs_selected = SHADER_ARB;
392 else
393 *vs_selected = SHADER_GLSL;
394 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
395 *vs_selected = SHADER_ARB;
396 } else {
397 *vs_selected = SHADER_NONE;
400 if (wined3d_settings.ps_mode == PS_NONE) {
401 *ps_selected = SHADER_NONE;
402 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
403 *ps_selected = SHADER_GLSL;
404 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
405 *ps_selected = SHADER_ARB;
406 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
407 *ps_selected = SHADER_ATI;
408 } else {
409 *ps_selected = SHADER_NONE;
413 /** Select the number of report maximum shader constants based on the selected shader modes */
414 static void select_shader_max_constants(int ps_selected_mode, int vs_selected_mode, struct wined3d_gl_info *gl_info)
416 switch (vs_selected_mode) {
417 case SHADER_GLSL:
418 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
419 break;
420 case SHADER_ARB:
421 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
422 break;
423 default:
424 gl_info->max_vshader_constantsF = 0;
425 break;
428 switch (ps_selected_mode) {
429 case SHADER_GLSL:
430 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
431 break;
432 case SHADER_ARB:
433 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
434 break;
435 default:
436 gl_info->max_pshader_constantsF = 0;
437 break;
441 /**********************************************************
442 * IWineD3D parts follows
443 **********************************************************/
445 /* GL locking is done by the caller */
446 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
448 GLuint prog;
449 BOOL ret = FALSE;
450 const char *testcode =
451 "!!ARBvp1.0\n"
452 "PARAM C[66] = { program.env[0..65] };\n"
453 "ADDRESS A0;"
454 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
455 "ARL A0.x, zero.x;\n"
456 "MOV result.position, C[A0.x + 65];\n"
457 "END\n";
459 while(glGetError());
460 GL_EXTCALL(glGenProgramsARB(1, &prog));
461 if(!prog) {
462 ERR("Failed to create an ARB offset limit test program\n");
464 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
465 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
466 strlen(testcode), testcode));
467 if(glGetError() != 0) {
468 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
469 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
470 ret = TRUE;
471 } else TRACE("OpenGL implementation allows offsets > 63\n");
473 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
474 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
475 checkGLcall("ARB vp offset limit test cleanup");
477 return ret;
480 static DWORD ver_for_ext(GL_SupportedExt ext)
482 unsigned int i;
483 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
484 if(EXTENSION_MAP[i].extension == ext) {
485 return EXTENSION_MAP[i].version;
488 return 0;
491 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
493 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
494 if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
495 if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
496 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
497 return FALSE;
500 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
502 if (gl_info->gl_vendor == VENDOR_NVIDIA)
504 if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600)
506 return TRUE;
509 return FALSE;
512 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
514 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
515 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
516 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
518 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
519 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
520 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
521 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
522 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
523 * the chance that other implementations support them is rather small since Win32 QuickTime uses
524 * DirectDraw, not OpenGL. */
525 if (gl_info->supported[APPLE_FENCE]
526 && gl_info->supported[APPLE_CLIENT_STORAGE]
527 && gl_info->supported[APPLE_FLUSH_RENDER]
528 && gl_info->supported[APPLE_YCBCR_422])
530 return TRUE;
532 else
534 return FALSE;
538 /* Context activation is done by the caller. */
539 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
541 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
542 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
543 * all the texture. This function detects this bug by its symptom and disables PBOs
544 * if the test fails.
546 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
547 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
548 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
549 * read back is compared to the original. If they are equal PBOs are assumed to work,
550 * otherwise the PBO extension is disabled. */
551 GLuint texture, pbo;
552 static const unsigned int pattern[] =
554 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
555 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
556 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
557 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
559 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
561 /* No PBO -> No point in testing them. */
562 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
564 ENTER_GL();
566 while (glGetError());
567 glGenTextures(1, &texture);
568 glBindTexture(GL_TEXTURE_2D, texture);
570 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
571 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
572 checkGLcall("Specifying the PBO test texture");
574 GL_EXTCALL(glGenBuffersARB(1, &pbo));
575 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
576 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
577 checkGLcall("Specifying the PBO test pbo");
579 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
580 checkGLcall("Loading the PBO test texture");
582 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
583 wglFinish(); /* just to be sure */
585 memset(check, 0, sizeof(check));
586 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
587 checkGLcall("Reading back the PBO test texture");
589 glDeleteTextures(1, &texture);
590 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
591 checkGLcall("PBO test cleanup");
593 LEAVE_GL();
595 if (memcmp(check, pattern, sizeof(check)))
597 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
598 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
599 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
601 else
603 TRACE_(d3d_caps)("PBO test successful.\n");
607 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
609 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer);
612 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
614 if (!match_apple(gl_info, gl_renderer)) return FALSE;
615 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
616 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
617 return TRUE;
620 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
622 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
623 if (match_apple(gl_info, gl_renderer)) return FALSE;
624 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
625 return TRUE;
628 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
630 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
631 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
632 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
633 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
634 * hardcoded
636 * dx10 cards usually have 64 varyings */
637 return gl_info->max_glsl_varyings > 44;
640 /* A GL context is provided by the caller */
641 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
643 GLenum error;
644 DWORD data[16];
646 if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE;
648 ENTER_GL();
649 while(glGetError());
650 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
651 error = glGetError();
652 LEAVE_GL();
654 if(error == GL_NO_ERROR)
656 TRACE("GL Implementation accepts 4 component specular color pointers\n");
657 return TRUE;
659 else
661 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
662 debug_glerror(error));
663 return FALSE;
667 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
669 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF);
670 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
671 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF);
672 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
675 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
677 quirk_arb_constants(gl_info);
678 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
679 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
680 * allow 48 different offsets or other helper immediate values. */
681 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
682 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
685 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
686 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
687 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
688 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
689 * most games, but avoids the crash
691 * A more sophisticated way would be to find all units that need texture coordinates and enable
692 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
693 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
695 * Note that disabling the extension entirely does not gain predictability because there is no point
696 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
697 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
699 if (gl_info->supported[ARB_POINT_SPRITE])
701 TRACE("Limiting point sprites to one texture unit.\n");
702 gl_info->max_point_sprite_units = 1;
706 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
708 quirk_arb_constants(gl_info);
710 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
711 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
712 * If real NP2 textures are used, the driver falls back to software. We could just remove the
713 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
714 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
715 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
716 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
718 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
719 * has this extension promoted to core. The extension loading code sets this extension supported
720 * due to that, so this code works on fglrx as well. */
721 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
723 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
724 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
725 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
728 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
729 * it is generally more efficient. Reserve just 8 constants. */
730 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
731 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
734 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
736 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
737 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
738 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
739 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
740 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
741 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
743 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
744 * triggering the software fallback. There is not much we can do here apart from disabling the
745 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
746 * in IWineD3DImpl_FillGLCaps).
747 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
748 * post-processing effects in the game "Max Payne 2").
749 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
750 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
751 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
752 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
755 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
757 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
758 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
759 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
760 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
761 * according to the spec.
763 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
764 * makes the shader slower and eats instruction slots which should be available to the d3d app.
766 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
767 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
768 * this workaround is activated on cards that do not need it, it won't break things, just affect
769 * performance negatively. */
770 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
771 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
774 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
776 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
779 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
781 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
784 struct driver_quirk
786 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
787 void (*apply)(struct wined3d_gl_info *gl_info);
788 const char *description;
791 struct driver_quirk quirk_table[] =
794 match_ati_r300_to_500,
795 quirk_ati_dx9,
796 "ATI GLSL constant and normalized texrect quirk"
798 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
799 * used it falls back to software. While the compiler can detect if the shader uses all declared
800 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
801 * using relative addressing falls back to software.
803 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
805 match_apple,
806 quirk_apple_glsl_constants,
807 "Apple GLSL uniform override"
810 match_geforce5,
811 quirk_no_np2,
812 "Geforce 5 NP2 disable"
815 match_apple_intel,
816 quirk_texcoord_w,
817 "Init texcoord .w for Apple Intel GPU driver"
820 match_apple_nonr500ati,
821 quirk_texcoord_w,
822 "Init texcoord .w for Apple ATI >= r600 GPU driver"
825 match_fglrx,
826 quirk_one_point_sprite,
827 "Fglrx point sprite crash workaround"
830 match_dx10_capable,
831 quirk_clip_varying,
832 "Reserved varying for gl_ClipPos"
835 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
836 * GL implementations accept it. The Mac GL is the only implementation known to
837 * reject it.
839 * If we can pass 4 component specular colors, do it, because (a) we don't have
840 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
841 * passes specular alpha to the pixel shader if any is used. Otherwise the
842 * specular alpha is used to pass the fog coordinate, which we pass to opengl
843 * via GL_EXT_fog_coord.
845 match_allows_spec_alpha,
846 quirk_allows_specular_alpha,
847 "Allow specular alpha quirk"
851 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
852 * reporting a driver version is moot because we are not the Windows driver, and we have different
853 * bugs, features, etc.
855 * If a card is not found in this table, the GL driver version is reported. */
856 struct driver_version_information
858 WORD vendor; /* reported PCI card vendor ID */
859 WORD card; /* reported PCI card device ID */
860 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
861 WORD hipart_hi, hipart_lo; /* driver hiword to report */
862 WORD lopart_hi, lopart_lo; /* driver loword to report */
865 static const struct driver_version_information driver_version_table[] =
867 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
868 * 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
869 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
870 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
872 * All version numbers used below are from the Linux nvidia drivers. */
873 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
874 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
875 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
876 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
877 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
878 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 },
879 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 },
880 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 },
881 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 },
882 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 },
883 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 },
884 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 },
885 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 },
886 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 },
887 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 },
888 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 },
889 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 },
890 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 },
891 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 },
892 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 },
893 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 },
894 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 },
895 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 },
896 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 },
897 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 },
898 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 },
899 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 },
900 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 },
901 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 },
902 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 },
904 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
905 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
906 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
907 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
908 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
909 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
910 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
911 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
912 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
913 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
914 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
916 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
919 /* Context activation is done by the caller. */
920 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer)
922 unsigned int i;
924 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
926 if (!quirk_table[i].match(gl_info, gl_renderer)) continue;
927 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
928 quirk_table[i].apply(gl_info);
931 /* Find out if PBOs work as they are supposed to. */
932 test_pbo_functionality(gl_info);
934 /* Fixup the driver version we'll report to the app. */
935 gl_info->driver_version = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
936 gl_info->driver_version_hipart = MAKEDWORD_VERSION(7, 1);
937 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
939 if (gl_info->gl_vendor == driver_version_table[i].vendor
940 && gl_info->gl_card == driver_version_table[i].card)
942 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB.\n",
943 gl_info->gl_vendor, gl_info->gl_card);
945 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
946 driver_version_table[i].lopart_lo);
947 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
948 driver_version_table[i].hipart_lo);
949 gl_info->driver_description = driver_version_table[i].description;
950 break;
953 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08X-0x%08X.\n",
954 gl_info->driver_version_hipart, gl_info->driver_version);
957 static DWORD wined3d_parse_gl_version(const char *gl_version)
959 const char *ptr = gl_version;
960 int major, minor;
962 major = atoi(ptr);
963 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
965 while (isdigit(*ptr)) ++ptr;
966 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
968 minor = atoi(ptr);
970 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
972 return MAKEDWORD_VERSION(major, minor);
975 static GL_Vendors wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer)
977 if (strstr(gl_vendor, "NVIDIA"))
978 return VENDOR_NVIDIA;
980 if (strstr(gl_vendor, "ATI"))
981 return VENDOR_ATI;
983 if (strstr(gl_vendor, "Intel(R)")
984 || strstr(gl_renderer, "Intel(R)")
985 || strstr(gl_vendor, "Intel Inc."))
986 return VENDOR_INTEL;
988 if (strstr(gl_vendor, "Mesa")
989 || strstr(gl_vendor, "Tungsten Graphics, Inc."))
990 return VENDOR_MESA;
992 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor));
994 return VENDOR_WINE;
997 static GL_Cards wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
998 GL_Vendors *vendor, unsigned int *vidmem)
1000 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1001 * different GPUs with roughly the same features. In most cases GPUs from a
1002 * certain family differ in clockspeeds, the amount of video memory and the
1003 * number of shader pipelines.
1005 * A Direct3D device object contains the PCI id (vendor + device) of the
1006 * videocard which is used for rendering. Various applications use this
1007 * information to get a rough estimation of the features of the card and
1008 * some might use it for enabling 3d effects only on certain types of
1009 * videocards. In some cases games might even use it to work around bugs
1010 * which happen on certain videocards/driver combinations. The problem is
1011 * that OpenGL only exposes a rendering string containing the name of the
1012 * videocard and not the PCI id.
1014 * Various games depend on the PCI id, so somehow we need to provide one.
1015 * A simple option is to parse the renderer string and translate this to
1016 * the right PCI id. This is a lot of work because there are more than 200
1017 * GPUs just for Nvidia. Various cards share the same renderer string, so
1018 * the amount of code might be 'small' but there are quite a number of
1019 * exceptions which would make this a pain to maintain. Another way would
1020 * be to query the PCI id from the operating system (assuming this is the
1021 * videocard which is used for rendering which is not always the case).
1022 * This would work but it is not very portable. Second it would not work
1023 * well in, let's say, a remote X situation in which the amount of 3d
1024 * features which can be used is limited.
1026 * As said most games only use the PCI id to get an indication of the
1027 * capabilities of the card. It doesn't really matter if the given id is
1028 * the correct one if we return the id of a card with similar 3d features.
1030 * The code below checks the OpenGL capabilities of a videocard and matches
1031 * that to a certain level of Direct3D functionality. Once a card passes
1032 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1033 * least a GeforceFX. To give a better estimate we do a basic check on the
1034 * renderer string but if that won't pass we return a default card. This
1035 * way is better than maintaining a full card database as even without a
1036 * full database we can return a card with similar features. Second the
1037 * size of the database can be made quite small because when you know what
1038 * type of 3d functionality a card has, you know to which GPU family the
1039 * GPU must belong. Because of this you only have to check a small part of
1040 * the renderer string to distinguishes between different models from that
1041 * family.
1043 * The code also selects a default amount of video memory which we will
1044 * use for an estimation of the amount of free texture memory. In case of
1045 * real D3D the amount of texture memory includes video memory and system
1046 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1047 * HyperMemory). We don't know how much system memory can be addressed by
1048 * the system but we can make a reasonable estimation about the amount of
1049 * video memory. If the value is slightly wrong it doesn't matter as we
1050 * didn't include AGP-like memory which makes the amount of addressable
1051 * memory higher and second OpenGL isn't that critical it moves to system
1052 * memory behind our backs if really needed. Note that the amount of video
1053 * memory can be overruled using a registry setting. */
1055 switch (*vendor)
1057 case VENDOR_NVIDIA:
1058 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1059 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1061 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1063 /* Geforce 200 - highend */
1064 if (strstr(gl_renderer, "GTX 280")
1065 || strstr(gl_renderer, "GTX 285")
1066 || strstr(gl_renderer, "GTX 295"))
1068 *vidmem = 1024;
1069 return CARD_NVIDIA_GEFORCE_GTX280;
1072 /* Geforce 200 - midend high */
1073 if (strstr(gl_renderer, "GTX 275"))
1075 *vidmem = 896;
1076 return CARD_NVIDIA_GEFORCE_GTX275;
1079 /* Geforce 200 - midend */
1080 if (strstr(gl_renderer, "GTX 260"))
1082 *vidmem = 1024;
1083 return CARD_NVIDIA_GEFORCE_GTX260;
1086 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1087 if (strstr(gl_renderer, "9800")
1088 || strstr(gl_renderer, "GTS 150")
1089 || strstr(gl_renderer, "GTS 250"))
1091 *vidmem = 512;
1092 return CARD_NVIDIA_GEFORCE_9800GT;
1095 /* Geforce9 - midend */
1096 if (strstr(gl_renderer, "9600"))
1098 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1099 return CARD_NVIDIA_GEFORCE_9600GT;
1102 /* Geforce9 - midend low / Geforce 200 - low */
1103 if (strstr(gl_renderer, "9500")
1104 || strstr(gl_renderer, "GT 120")
1105 || strstr(gl_renderer, "GT 130"))
1107 *vidmem = 256; /* The 9500GT has 256-1024MB */
1108 return CARD_NVIDIA_GEFORCE_9500GT;
1111 /* Geforce9 - lowend */
1112 if (strstr(gl_renderer, "9400"))
1114 *vidmem = 256; /* The 9400GT has 256-1024MB */
1115 return CARD_NVIDIA_GEFORCE_9400GT;
1118 /* Geforce9 - lowend low */
1119 if (strstr(gl_renderer, "9100")
1120 || strstr(gl_renderer, "9200")
1121 || strstr(gl_renderer, "9300")
1122 || strstr(gl_renderer, "G 100"))
1124 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1125 return CARD_NVIDIA_GEFORCE_9200;
1128 /* Geforce8 - highend */
1129 if (strstr(gl_renderer, "8800"))
1131 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1132 return CARD_NVIDIA_GEFORCE_8800GTS;
1135 /* Geforce8 - midend mobile */
1136 if (strstr(gl_renderer, "8600 M"))
1138 *vidmem = 512;
1139 return CARD_NVIDIA_GEFORCE_8600MGT;
1142 /* Geforce8 - midend */
1143 if (strstr(gl_renderer, "8600")
1144 || strstr(gl_renderer, "8700"))
1146 *vidmem = 256;
1147 return CARD_NVIDIA_GEFORCE_8600GT;
1150 /* Geforce8 - lowend */
1151 if (strstr(gl_renderer, "8300")
1152 || strstr(gl_renderer, "8400")
1153 || strstr(gl_renderer, "8500"))
1155 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1156 return CARD_NVIDIA_GEFORCE_8300GS;
1159 /* Geforce7 - highend */
1160 if (strstr(gl_renderer, "7800")
1161 || strstr(gl_renderer, "7900")
1162 || strstr(gl_renderer, "7950")
1163 || strstr(gl_renderer, "Quadro FX 4")
1164 || strstr(gl_renderer, "Quadro FX 5"))
1166 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1167 return CARD_NVIDIA_GEFORCE_7800GT;
1170 /* Geforce7 midend */
1171 if (strstr(gl_renderer, "7600")
1172 || strstr(gl_renderer, "7700"))
1174 *vidmem = 256; /* The 7600 uses 256-512MB */
1175 return CARD_NVIDIA_GEFORCE_7600;
1178 /* Geforce7 lower medium */
1179 if (strstr(gl_renderer, "7400"))
1181 *vidmem = 256; /* The 7400 uses 256-512MB */
1182 return CARD_NVIDIA_GEFORCE_7400;
1185 /* Geforce7 lowend */
1186 if (strstr(gl_renderer, "7300"))
1188 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1189 return CARD_NVIDIA_GEFORCE_7300;
1192 /* Geforce6 highend */
1193 if (strstr(gl_renderer, "6800"))
1195 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1196 return CARD_NVIDIA_GEFORCE_6800;
1199 /* Geforce6 - midend */
1200 if (strstr(gl_renderer, "6600")
1201 || strstr(gl_renderer, "6610")
1202 || strstr(gl_renderer, "6700"))
1204 *vidmem = 128; /* A 6600GT has 128-256MB */
1205 return CARD_NVIDIA_GEFORCE_6600GT;
1208 /* Geforce6/7 lowend */
1209 *vidmem = 64; /* */
1210 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1213 if (WINE_D3D9_CAPABLE(gl_info))
1215 /* GeforceFX - highend */
1216 if (strstr(gl_renderer, "5800")
1217 || strstr(gl_renderer, "5900")
1218 || strstr(gl_renderer, "5950")
1219 || strstr(gl_renderer, "Quadro FX"))
1221 *vidmem = 256; /* 5800-5900 cards use 256MB */
1222 return CARD_NVIDIA_GEFORCEFX_5800;
1225 /* GeforceFX - midend */
1226 if (strstr(gl_renderer, "5600")
1227 || strstr(gl_renderer, "5650")
1228 || strstr(gl_renderer, "5700")
1229 || strstr(gl_renderer, "5750"))
1231 *vidmem = 128; /* A 5600 uses 128-256MB */
1232 return CARD_NVIDIA_GEFORCEFX_5600;
1235 /* GeforceFX - lowend */
1236 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1237 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1240 if (WINE_D3D8_CAPABLE(gl_info))
1242 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1244 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1245 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1248 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1249 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1252 if (WINE_D3D7_CAPABLE(gl_info))
1254 if (strstr(gl_renderer, "GeForce4 MX"))
1256 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1257 * early models had 32MB but most have 64MB or even 128MB. */
1258 *vidmem = 64;
1259 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1262 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1264 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1265 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1268 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1270 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1271 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1274 /* Most Geforce1 cards have 32MB, there are also some rare 16
1275 * and 64MB (Dell) models. */
1276 *vidmem = 32;
1277 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1280 if (strstr(gl_renderer, "TNT2"))
1282 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1283 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1286 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1287 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1289 case VENDOR_ATI:
1290 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1292 * Beware: renderer string do not match exact card model,
1293 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1294 if (WINE_D3D9_CAPABLE(gl_info))
1296 /* Radeon R7xx HD4800 - highend */
1297 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1298 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1299 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1300 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1301 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1303 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1304 return CARD_ATI_RADEON_HD4800;
1307 /* Radeon R740 HD4700 - midend */
1308 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1309 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1311 *vidmem = 512;
1312 return CARD_ATI_RADEON_HD4700;
1315 /* Radeon R730 HD4600 - midend */
1316 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1317 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1318 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1320 *vidmem = 512;
1321 return CARD_ATI_RADEON_HD4600;
1324 /* Radeon R710 HD4500/HD4350 - lowend */
1325 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1326 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1328 *vidmem = 256;
1329 return CARD_ATI_RADEON_HD4350;
1332 /* Radeon R6xx HD2900/HD3800 - highend */
1333 if (strstr(gl_renderer, "HD 2900")
1334 || strstr(gl_renderer, "HD 3870")
1335 || strstr(gl_renderer, "HD 3850"))
1337 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1338 return CARD_ATI_RADEON_HD2900;
1341 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1342 if (strstr(gl_renderer, "HD 2600")
1343 || strstr(gl_renderer, "HD 3830")
1344 || strstr(gl_renderer, "HD 3690")
1345 || strstr(gl_renderer, "HD 3650"))
1347 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1348 return CARD_ATI_RADEON_HD2600;
1351 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1352 if (strstr(gl_renderer, "HD 2300")
1353 || strstr(gl_renderer, "HD 2400")
1354 || strstr(gl_renderer, "HD 3470")
1355 || strstr(gl_renderer, "HD 3450")
1356 || strstr(gl_renderer, "HD 3430")
1357 || strstr(gl_renderer, "HD 3400"))
1359 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1360 return CARD_ATI_RADEON_HD2300;
1363 /* Radeon R6xx/R7xx integrated */
1364 if (strstr(gl_renderer, "HD 3100")
1365 || strstr(gl_renderer, "HD 3200")
1366 || strstr(gl_renderer, "HD 3300"))
1368 *vidmem = 128; /* 128MB */
1369 return CARD_ATI_RADEON_HD3200;
1372 /* Radeon R5xx */
1373 if (strstr(gl_renderer, "X1600")
1374 || strstr(gl_renderer, "X1650")
1375 || strstr(gl_renderer, "X1800")
1376 || strstr(gl_renderer, "X1900")
1377 || strstr(gl_renderer, "X1950"))
1379 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1380 return CARD_ATI_RADEON_X1600;
1383 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1384 if (strstr(gl_renderer, "X700")
1385 || strstr(gl_renderer, "X800")
1386 || strstr(gl_renderer, "X850")
1387 || strstr(gl_renderer, "X1300")
1388 || strstr(gl_renderer, "X1400")
1389 || strstr(gl_renderer, "X1450")
1390 || strstr(gl_renderer, "X1550"))
1392 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1393 return CARD_ATI_RADEON_X700;
1396 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1397 if (strstr(gl_renderer, "Radeon Xpress"))
1399 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1400 return CARD_ATI_RADEON_XPRESS_200M;
1403 /* Radeon R3xx */
1404 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1405 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1408 if (WINE_D3D8_CAPABLE(gl_info))
1410 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1411 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1414 if (WINE_D3D7_CAPABLE(gl_info))
1416 *vidmem = 32; /* There are models with up to 64MB */
1417 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1420 *vidmem = 16; /* There are 16-32MB models */
1421 return CARD_ATI_RAGE_128PRO;
1423 case VENDOR_INTEL:
1424 if (strstr(gl_renderer, "X3100"))
1426 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1427 *vidmem = 128;
1428 return CARD_INTEL_X3100;
1431 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1433 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1434 *vidmem = 64;
1435 return CARD_INTEL_I945GM;
1438 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1439 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1440 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1441 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1442 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1443 return CARD_INTEL_I915G;
1445 case VENDOR_MESA:
1446 case VENDOR_WINE:
1447 default:
1448 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1449 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1450 * them a good generic choice. */
1451 *vendor = VENDOR_NVIDIA;
1452 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1453 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1454 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1455 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1456 return CARD_NVIDIA_RIVA_128;
1460 /* Context activation is done by the caller. */
1461 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_gl_info *gl_info)
1463 const char *GL_Extensions = NULL;
1464 const char *WGL_Extensions = NULL;
1465 const char *gl_string = NULL;
1466 GLint gl_max;
1467 GLfloat gl_floatv[2];
1468 unsigned i;
1469 HDC hdc;
1470 unsigned int vidmem=0;
1471 char *gl_renderer;
1472 DWORD gl_version;
1473 size_t len;
1475 TRACE_(d3d_caps)("(%p)\n", gl_info);
1477 ENTER_GL();
1479 gl_string = (const char *)glGetString(GL_RENDERER);
1480 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string));
1481 if (!gl_string)
1483 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
1484 return FALSE;
1487 len = strlen(gl_string) + 1;
1488 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
1489 if (!gl_renderer)
1491 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
1492 return FALSE;
1494 memcpy(gl_renderer, gl_string, len);
1496 gl_string = (const char *)glGetString(GL_VENDOR);
1497 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string));
1498 if (!gl_string)
1500 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
1501 HeapFree(GetProcessHeap(), 0, gl_renderer);
1502 return FALSE;
1504 gl_info->gl_vendor = wined3d_guess_vendor(gl_string, gl_renderer);
1505 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
1507 /* Parse the GL_VERSION field into major and minor information */
1508 gl_string = (const char *)glGetString(GL_VERSION);
1509 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string));
1510 if (!gl_string)
1512 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1513 HeapFree(GetProcessHeap(), 0, gl_renderer);
1514 return FALSE;
1516 gl_version = wined3d_parse_gl_version(gl_string);
1519 * Initialize openGL extension related variables
1520 * with Default values
1522 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1523 gl_info->max_buffers = 1;
1524 gl_info->max_textures = 1;
1525 gl_info->max_texture_stages = 1;
1526 gl_info->max_fragment_samplers = 1;
1527 gl_info->max_vertex_samplers = 0;
1528 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
1529 gl_info->max_sampler_stages = 1;
1530 gl_info->ps_arb_max_temps = 0;
1531 gl_info->ps_arb_max_instructions = 0;
1532 gl_info->vs_arb_max_temps = 0;
1533 gl_info->vs_arb_max_instructions = 0;
1534 gl_info->vs_glsl_constantsF = 0;
1535 gl_info->ps_glsl_constantsF = 0;
1536 gl_info->vs_arb_constantsF = 0;
1537 gl_info->ps_arb_constantsF = 0;
1538 gl_info->ps_arb_max_local_constants = 0;
1540 /* Retrieve opengl defaults */
1541 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1542 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1543 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1545 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1546 gl_info->max_lights = gl_max;
1547 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1549 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1550 gl_info->max_texture_size = gl_max;
1551 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1553 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1554 gl_info->max_pointsizemin = gl_floatv[0];
1555 gl_info->max_pointsize = gl_floatv[1];
1556 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1558 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1559 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1560 if (!GL_Extensions)
1562 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1563 HeapFree(GetProcessHeap(), 0, gl_renderer);
1564 return FALSE;
1567 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1569 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1571 while (*GL_Extensions)
1573 const char *start;
1574 char current_ext[256];
1576 while (isspace(*GL_Extensions)) ++GL_Extensions;
1577 start = GL_Extensions;
1578 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1580 len = GL_Extensions - start;
1581 if (!len || len >= sizeof(current_ext)) continue;
1583 memcpy(current_ext, start, len);
1584 current_ext[len] = '\0';
1585 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
1587 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1589 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1591 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1592 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1593 break;
1598 LEAVE_GL();
1600 /* Now work out what GL support this card really has */
1601 #define USE_GL_FUNC(type, pfn, ext, replace) \
1603 DWORD ver = ver_for_ext(ext); \
1604 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1605 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1606 else gl_info->pfn = NULL; \
1608 GL_EXT_FUNCS_GEN;
1609 #undef USE_GL_FUNC
1611 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1612 WGL_EXT_FUNCS_GEN;
1613 #undef USE_GL_FUNC
1615 ENTER_GL();
1617 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1618 * loading the functions, otherwise the code above will load the extension entry points instead of the
1619 * core functions, which may not work. */
1620 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1622 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1623 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1625 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1626 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1630 if (gl_info->supported[APPLE_FENCE])
1632 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1633 * The apple extension interacts with some other apple exts. Disable the NV
1634 * extension if the apple one is support to prevent confusion in other parts
1635 * of the code. */
1636 gl_info->supported[NV_FENCE] = FALSE;
1638 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1640 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1642 * The enums are the same:
1643 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1644 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1645 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1646 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1647 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1649 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1651 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1652 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1654 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1656 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1657 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1660 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1662 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1663 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1665 if (gl_info->supported[NV_TEXTURE_SHADER2])
1667 if (gl_info->supported[NV_REGISTER_COMBINERS])
1669 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1670 * are supported. The nv extensions provide the same functionality as the
1671 * ATI one, and a bit more(signed pixelformats). */
1672 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1675 if (gl_info->supported[ARB_DRAW_BUFFERS])
1677 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1678 gl_info->max_buffers = gl_max;
1679 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1681 if (gl_info->supported[ARB_MULTITEXTURE])
1683 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1684 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
1685 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures);
1687 if (gl_info->supported[NV_REGISTER_COMBINERS])
1689 GLint tmp;
1690 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1691 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
1693 else
1695 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
1697 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages);
1699 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1701 GLint tmp;
1702 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1703 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1705 else
1707 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
1709 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers);
1711 if (gl_info->supported[ARB_VERTEX_SHADER])
1713 GLint tmp;
1714 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1715 gl_info->max_vertex_samplers = tmp;
1716 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1717 gl_info->max_combined_samplers = tmp;
1719 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1720 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1721 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1722 * shader is used with fixed function vertex processing we're fine too because fixed function
1723 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1724 * used we have to make sure that all vertex sampler setups are valid together with all
1725 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1726 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1727 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1728 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1729 * a fixed function pipeline anymore.
1731 * So this is just a check to check that our assumption holds true. If not, write a warning
1732 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1733 if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12
1734 && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers)
1736 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1737 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
1738 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1739 if (gl_info->max_combined_samplers > MAX_TEXTURES)
1740 gl_info->max_vertex_samplers = gl_info->max_combined_samplers - MAX_TEXTURES;
1741 else
1742 gl_info->max_vertex_samplers = 0;
1745 else
1747 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
1749 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers);
1750 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers);
1752 if (gl_info->supported[ARB_VERTEX_BLEND])
1754 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1755 gl_info->max_blends = gl_max;
1756 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends);
1758 if (gl_info->supported[EXT_TEXTURE3D])
1760 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1761 gl_info->max_texture3d_size = gl_max;
1762 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size);
1764 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1766 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1767 gl_info->max_anisotropy = gl_max;
1768 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy);
1770 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1772 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1773 gl_info->ps_arb_constantsF = gl_max;
1774 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF);
1775 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1776 gl_info->ps_arb_max_temps = gl_max;
1777 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps);
1778 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1779 gl_info->ps_arb_max_instructions = gl_max;
1780 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions);
1781 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
1782 gl_info->ps_arb_max_local_constants = gl_max;
1783 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->ps_arb_max_instructions);
1785 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1787 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1788 gl_info->vs_arb_constantsF = gl_max;
1789 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF);
1790 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1791 gl_info->vs_arb_max_temps = gl_max;
1792 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps);
1793 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1794 gl_info->vs_arb_max_instructions = gl_max;
1795 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions);
1797 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1799 if (gl_info->supported[ARB_VERTEX_SHADER])
1801 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1802 gl_info->vs_glsl_constantsF = gl_max / 4;
1803 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF);
1805 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1807 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1808 gl_info->ps_glsl_constantsF = gl_max / 4;
1809 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF);
1810 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1811 gl_info->max_glsl_varyings = gl_max;
1812 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
1814 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
1816 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
1818 else
1820 gl_info->max_shininess = 128.0f;
1822 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1824 /* If we have full NP2 texture support, disable
1825 * GL_ARB_texture_rectangle because we will never use it.
1826 * This saves a few redundant glDisable calls. */
1827 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1829 if (gl_info->supported[ATI_FRAGMENT_SHADER])
1831 /* Disable NV_register_combiners and fragment shader if this is supported.
1832 * generally the NV extensions are preferred over the ATI ones, and this
1833 * extension is disabled if register_combiners and texture_shader2 are both
1834 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1835 * fragment processing support. */
1836 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1837 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1838 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1839 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1840 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1842 if (gl_info->supported[NV_HALF_FLOAT])
1844 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
1845 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1847 if (gl_info->supported[ARB_POINT_SPRITE])
1849 gl_info->max_point_sprite_units = gl_info->max_textures;
1851 else
1853 gl_info->max_point_sprite_units = 0;
1855 checkGLcall("extension detection");
1857 LEAVE_GL();
1859 /* In some cases the number of texture stages can be larger than the number
1860 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1861 * shaders), but 8 texture stages (register combiners). */
1862 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1864 /* We can only use ORM_FBO when the hardware supports it. */
1865 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1866 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
1867 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1870 /* MRTs are currently only supported when FBOs are used. */
1871 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1872 gl_info->max_buffers = 1;
1875 gl_info->gl_card = wined3d_guess_card(gl_info, gl_renderer, &gl_info->gl_vendor, &vidmem);
1876 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1878 /* If we have an estimate use it, else default to 64MB; */
1879 if(vidmem)
1880 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1881 else
1882 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1884 /* Load all the lookup tables */
1885 for (i = 0; i < MAX_LOOKUPS; i++) {
1886 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1889 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1890 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1891 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1892 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1893 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1894 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1895 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1896 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1897 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1898 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1900 /* Make sure there's an active HDC else the WGL extensions will fail */
1901 hdc = pwglGetCurrentDC();
1902 if (hdc) {
1903 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
1904 if(GL_EXTCALL(wglGetExtensionsStringARB))
1905 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1907 if (NULL == WGL_Extensions) {
1908 ERR(" WGL_Extensions returns NULL\n");
1909 } else {
1910 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1911 while (*WGL_Extensions != 0x00) {
1912 const char *Start;
1913 char ThisExtn[256];
1915 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1916 Start = WGL_Extensions;
1917 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1918 WGL_Extensions++;
1921 len = WGL_Extensions - Start;
1922 if (len == 0 || len >= sizeof(ThisExtn))
1923 continue;
1925 memcpy(ThisExtn, Start, len);
1926 ThisExtn[len] = '\0';
1927 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
1929 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1930 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1931 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1933 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
1934 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
1935 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
1937 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1938 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1939 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1945 fixup_extensions(gl_info, gl_renderer);
1946 add_gl_compat_wrappers(gl_info);
1948 HeapFree(GetProcessHeap(), 0, gl_renderer);
1949 return TRUE;
1952 /**********************************************************
1953 * IWineD3D implementation follows
1954 **********************************************************/
1956 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1957 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1959 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
1961 return This->adapter_count;
1964 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1965 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1966 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1967 return WINED3D_OK;
1970 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1971 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1973 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1975 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1976 return NULL;
1979 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1982 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1983 of the same bpp but different resolutions */
1985 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1986 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1987 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1988 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1990 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1991 return 0;
1994 /* TODO: Store modes per adapter and read it from the adapter structure */
1995 if (Adapter == 0) { /* Display */
1996 unsigned int i = 0;
1997 unsigned int j = 0;
1998 DEVMODEW mode;
2000 memset(&mode, 0, sizeof(mode));
2001 mode.dmSize = sizeof(mode);
2003 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2005 ++j;
2006 switch (Format)
2008 case WINED3DFMT_UNKNOWN:
2009 /* This is for D3D8, do not enumerate P8 here */
2010 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2011 break;
2013 case WINED3DFMT_X8R8G8B8:
2014 if (mode.dmBitsPerPel == 32) ++i;
2015 break;
2017 case WINED3DFMT_R5G6B5:
2018 if (mode.dmBitsPerPel == 16) ++i;
2019 break;
2021 case WINED3DFMT_P8:
2022 if (mode.dmBitsPerPel == 8) ++i;
2023 break;
2025 default:
2026 /* Skip other modes as they do not match the requested format */
2027 break;
2031 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2032 return i;
2033 } else {
2034 FIXME_(d3d_caps)("Adapter not primary display\n");
2036 return 0;
2039 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2040 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2041 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2042 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2044 /* Validate the parameters as much as possible */
2045 if (NULL == pMode ||
2046 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2047 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2048 return WINED3DERR_INVALIDCALL;
2051 /* TODO: Store modes per adapter and read it from the adapter structure */
2052 if (Adapter == 0)
2054 DEVMODEW DevModeW;
2055 int ModeIdx = 0;
2056 UINT i = 0;
2057 int j = 0;
2059 ZeroMemory(&DevModeW, sizeof(DevModeW));
2060 DevModeW.dmSize = sizeof(DevModeW);
2062 /* If we are filtering to a specific format (D3D9), then need to skip
2063 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2064 just count through the ones with valid bit depths */
2065 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
2066 switch (Format)
2068 case WINED3DFMT_UNKNOWN:
2069 /* This is D3D8. Do not enumerate P8 here */
2070 if (DevModeW.dmBitsPerPel == 32 ||
2071 DevModeW.dmBitsPerPel == 16) i++;
2072 break;
2073 case WINED3DFMT_X8R8G8B8:
2074 if (DevModeW.dmBitsPerPel == 32) i++;
2075 break;
2076 case WINED3DFMT_R5G6B5:
2077 if (DevModeW.dmBitsPerPel == 16) i++;
2078 break;
2079 case WINED3DFMT_P8:
2080 if (DevModeW.dmBitsPerPel == 8) i++;
2081 break;
2082 default:
2083 /* Modes that don't match what we support can get an early-out */
2084 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
2085 return WINED3DERR_INVALIDCALL;
2089 if (i == 0) {
2090 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2091 return WINED3DERR_INVALIDCALL;
2093 ModeIdx = j - 1;
2095 /* Now get the display mode via the calculated index */
2096 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2097 pMode->Width = DevModeW.dmPelsWidth;
2098 pMode->Height = DevModeW.dmPelsHeight;
2099 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2100 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2101 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2103 if (Format == WINED3DFMT_UNKNOWN) {
2104 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2105 } else {
2106 pMode->Format = Format;
2108 } else {
2109 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2110 return WINED3DERR_INVALIDCALL;
2113 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2114 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2115 DevModeW.dmBitsPerPel);
2118 else
2120 FIXME_(d3d_caps)("Adapter not primary display\n");
2123 return WINED3D_OK;
2126 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2127 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2128 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
2130 if (NULL == pMode ||
2131 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2132 return WINED3DERR_INVALIDCALL;
2135 if (Adapter == 0) { /* Display */
2136 int bpp = 0;
2137 DEVMODEW DevModeW;
2139 ZeroMemory(&DevModeW, sizeof(DevModeW));
2140 DevModeW.dmSize = sizeof(DevModeW);
2142 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2143 pMode->Width = DevModeW.dmPelsWidth;
2144 pMode->Height = DevModeW.dmPelsHeight;
2145 bpp = DevModeW.dmBitsPerPel;
2146 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2147 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2149 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2152 pMode->Format = pixelformat_for_depth(bpp);
2153 } else {
2154 FIXME_(d3d_caps)("Adapter not primary display\n");
2157 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2158 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2159 return WINED3D_OK;
2162 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2163 and fields being inserted in the middle, a new structure is used in place */
2164 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2165 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2166 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2167 size_t len;
2169 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2171 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2172 return WINED3DERR_INVALIDCALL;
2175 /* Return the information requested */
2176 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2178 if (pIdentifier->driver_size)
2180 len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1);
2181 memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len);
2182 pIdentifier->driver[len] = '\0';
2185 if (pIdentifier->description_size)
2187 const char *description;
2189 if (This->adapters[Adapter].gl_info.driver_description)
2190 description = This->adapters[Adapter].gl_info.driver_description;
2191 else
2192 description = This->adapters[Adapter].description;
2194 len = min(strlen(description), pIdentifier->description_size - 1);
2195 memcpy(pIdentifier->description, description, len);
2196 pIdentifier->description[len] = '\0';
2199 /* Note that d3d8 doesn't supply a device name. */
2200 if (pIdentifier->device_name_size)
2202 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2204 len = strlen(device_name);
2205 if (len >= pIdentifier->device_name_size)
2207 ERR("Device name size too small.\n");
2208 return WINED3DERR_INVALIDCALL;
2211 memcpy(pIdentifier->device_name, device_name, len);
2212 pIdentifier->device_name[len] = '\0';
2215 pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
2216 pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version;
2217 pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor;
2218 pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card;
2219 pIdentifier->subsystem_id = 0;
2220 pIdentifier->revision = 0;
2221 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2223 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
2225 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
2226 pIdentifier->device_id = wined3d_settings.pci_device_id;
2229 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
2231 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
2232 pIdentifier->vendor_id = wined3d_settings.pci_vendor_id;
2235 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2237 return WINED3D_OK;
2240 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2241 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2243 short redSize, greenSize, blueSize, alphaSize, colorBits;
2245 if(!cfg)
2246 return FALSE;
2248 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2249 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2251 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2252 return FALSE;
2255 if(cfg->redSize < redSize)
2256 return FALSE;
2258 if(cfg->greenSize < greenSize)
2259 return FALSE;
2261 if(cfg->blueSize < blueSize)
2262 return FALSE;
2264 if(cfg->alphaSize < alphaSize)
2265 return FALSE;
2267 return TRUE;
2268 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2269 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2270 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2271 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2272 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2273 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2274 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2275 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2276 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2277 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2278 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2279 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2280 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2281 } else {
2282 /* Probably a color index mode */
2283 return FALSE;
2286 return FALSE;
2289 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2290 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2292 short depthSize, stencilSize;
2293 BOOL lockable = FALSE;
2295 if(!cfg)
2296 return FALSE;
2298 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2300 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2301 return FALSE;
2304 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
2305 lockable = TRUE;
2307 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2308 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2309 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2310 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2311 return FALSE;
2313 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2314 * allow more stencil bits than requested. */
2315 if(cfg->stencilSize < stencilSize)
2316 return FALSE;
2318 return TRUE;
2321 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2322 WINED3DFORMAT AdapterFormat,
2323 WINED3DFORMAT RenderTargetFormat,
2324 WINED3DFORMAT DepthStencilFormat) {
2325 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2326 int nCfgs;
2327 const WineD3D_PixelFormat *cfgs;
2328 const struct WineD3DAdapter *adapter;
2329 const struct GlPixelFormatDesc *rt_format_desc;
2330 const struct GlPixelFormatDesc *ds_format_desc;
2331 int it;
2333 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2334 This, Adapter,
2335 DeviceType, debug_d3ddevicetype(DeviceType),
2336 AdapterFormat, debug_d3dformat(AdapterFormat),
2337 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2338 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2340 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2341 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2342 return WINED3DERR_INVALIDCALL;
2345 adapter = &This->adapters[Adapter];
2346 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2347 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2348 cfgs = adapter->cfgs;
2349 nCfgs = adapter->nCfgs;
2350 for (it = 0; it < nCfgs; ++it) {
2351 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2353 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2355 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2356 return WINED3D_OK;
2360 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2362 return WINED3DERR_NOTAVAILABLE;
2365 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2366 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2368 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2369 const struct GlPixelFormatDesc *glDesc;
2370 const struct WineD3DAdapter *adapter;
2372 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2373 This,
2374 Adapter,
2375 DeviceType, debug_d3ddevicetype(DeviceType),
2376 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2377 Windowed,
2378 MultiSampleType,
2379 pQualityLevels);
2381 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2382 return WINED3DERR_INVALIDCALL;
2385 /* TODO: handle Windowed, add more quality levels */
2387 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2388 if(pQualityLevels) *pQualityLevels = 1;
2389 return WINED3D_OK;
2392 /* By default multisampling is disabled right now as it causes issues
2393 * on some Nvidia driver versions and it doesn't work well in combination
2394 * with FBOs yet. */
2395 if(!wined3d_settings.allow_multisampling)
2396 return WINED3DERR_NOTAVAILABLE;
2398 adapter = &This->adapters[Adapter];
2399 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2400 if (!glDesc) return WINED3DERR_INVALIDCALL;
2402 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2403 int i, nCfgs;
2404 const WineD3D_PixelFormat *cfgs;
2406 cfgs = adapter->cfgs;
2407 nCfgs = adapter->nCfgs;
2408 for(i=0; i<nCfgs; i++) {
2409 if(cfgs[i].numSamples != MultiSampleType)
2410 continue;
2412 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2413 continue;
2415 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2417 if(pQualityLevels)
2418 *pQualityLevels = 1; /* Guess at a value! */
2419 return WINED3D_OK;
2422 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2423 short redSize, greenSize, blueSize, alphaSize, colorBits;
2424 int i, nCfgs;
2425 const WineD3D_PixelFormat *cfgs;
2427 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2429 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2430 return WINED3DERR_NOTAVAILABLE;
2433 cfgs = adapter->cfgs;
2434 nCfgs = adapter->nCfgs;
2435 for(i=0; i<nCfgs; i++) {
2436 if(cfgs[i].numSamples != MultiSampleType)
2437 continue;
2438 if(cfgs[i].redSize != redSize)
2439 continue;
2440 if(cfgs[i].greenSize != greenSize)
2441 continue;
2442 if(cfgs[i].blueSize != blueSize)
2443 continue;
2444 if(cfgs[i].alphaSize != alphaSize)
2445 continue;
2447 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2449 if(pQualityLevels)
2450 *pQualityLevels = 1; /* Guess at a value! */
2451 return WINED3D_OK;
2454 return WINED3DERR_NOTAVAILABLE;
2457 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2458 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2460 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2461 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2462 UINT nmodes;
2464 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2465 This,
2466 Adapter,
2467 DeviceType, debug_d3ddevicetype(DeviceType),
2468 DisplayFormat, debug_d3dformat(DisplayFormat),
2469 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2470 Windowed);
2472 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2473 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2474 return WINED3DERR_INVALIDCALL;
2477 /* The task of this function is to check whether a certain display / backbuffer format
2478 * combination is available on the given adapter. In fullscreen mode microsoft specified
2479 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2480 * and display format should match exactly.
2481 * In windowed mode format conversion can occur and this depends on the driver. When format
2482 * conversion is done, this function should nevertheless fail and applications need to use
2483 * CheckDeviceFormatConversion.
2484 * At the moment we assume that fullscreen and windowed have the same capabilities */
2486 /* There are only 4 display formats */
2487 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2488 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2489 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2490 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2492 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2493 return WINED3DERR_NOTAVAILABLE;
2496 /* If the requested DisplayFormat is not available, don't continue */
2497 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2498 if(!nmodes) {
2499 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2500 return WINED3DERR_NOTAVAILABLE;
2503 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2504 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2505 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2506 return WINED3DERR_NOTAVAILABLE;
2509 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2510 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
2511 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2512 return WINED3DERR_NOTAVAILABLE;
2515 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2516 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2517 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2518 return WINED3DERR_NOTAVAILABLE;
2521 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2522 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2523 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2524 return WINED3DERR_NOTAVAILABLE;
2527 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2528 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2529 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2530 return WINED3DERR_NOTAVAILABLE;
2533 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2534 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2535 if(FAILED(hr))
2536 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2538 return hr;
2542 /* Check if we support bumpmapping for a format */
2543 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2544 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2546 const struct fragment_pipeline *fp;
2548 switch(format_desc->format)
2550 case WINED3DFMT_R8G8_SNORM:
2551 case WINED3DFMT_R16G16_SNORM:
2552 case WINED3DFMT_L6V5U5:
2553 case WINED3DFMT_X8L8V8U8:
2554 case WINED3DFMT_R8G8B8A8_SNORM:
2555 /* Ask the fixed function pipeline implementation if it can deal
2556 * with the conversion. If we've got a GL extension giving native
2557 * support this will be an identity conversion. */
2558 fp = select_fragment_implementation(adapter, DeviceType);
2559 if (fp->color_fixup_supported(format_desc->color_fixup))
2561 TRACE_(d3d_caps)("[OK]\n");
2562 return TRUE;
2564 TRACE_(d3d_caps)("[FAILED]\n");
2565 return FALSE;
2567 default:
2568 TRACE_(d3d_caps)("[FAILED]\n");
2569 return FALSE;
2573 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2574 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2575 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2577 int it=0;
2579 /* Only allow depth/stencil formats */
2580 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2582 /* Walk through all WGL pixel formats to find a match */
2583 for (it = 0; it < adapter->nCfgs; ++it)
2585 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2586 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2588 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2590 return TRUE;
2595 return FALSE;
2598 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2600 /* The flags entry of a format contains the filtering capability */
2601 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2603 return FALSE;
2606 /* Check the render target capabilities of a format */
2607 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2608 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2610 /* Filter out non-RT formats */
2611 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2613 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2614 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2615 int it;
2616 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2617 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2619 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2620 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2622 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2623 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2624 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2625 TRACE_(d3d_caps)("[FAILED]\n");
2626 return FALSE;
2629 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2630 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2631 for (it = 0; it < adapter->nCfgs; ++it)
2633 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2634 &cfgs[it], check_format_desc))
2636 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2637 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2638 return TRUE;
2641 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2642 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2643 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2644 int it;
2646 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2647 for (it = 0; it < adapter->nCfgs; ++it)
2649 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2650 &cfgs[it], check_format_desc))
2652 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2653 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2654 return TRUE;
2657 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2658 /* For now return TRUE for FBOs until we have some proper checks.
2659 * Note that this function will only be called when the format is around for texturing. */
2660 return TRUE;
2662 return FALSE;
2665 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2667 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2669 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2670 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2671 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2672 return FALSE;
2675 switch (format_desc->format)
2677 case WINED3DFMT_A8R8G8B8:
2678 case WINED3DFMT_X8R8G8B8:
2679 case WINED3DFMT_A4R4G4B4:
2680 case WINED3DFMT_L8:
2681 case WINED3DFMT_A8L8:
2682 case WINED3DFMT_DXT1:
2683 case WINED3DFMT_DXT2:
2684 case WINED3DFMT_DXT3:
2685 case WINED3DFMT_DXT4:
2686 case WINED3DFMT_DXT5:
2687 TRACE_(d3d_caps)("[OK]\n");
2688 return TRUE;
2690 default:
2691 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2692 return FALSE;
2694 return FALSE;
2697 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2698 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2700 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2701 * doing the color fixup in shaders.
2702 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2703 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2705 int vs_selected_mode;
2706 int ps_selected_mode;
2707 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2709 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2710 TRACE_(d3d_caps)("[OK]\n");
2711 return TRUE;
2715 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2716 return FALSE;
2719 /* Check if a format support blending in combination with pixel shaders */
2720 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2721 const struct GlPixelFormatDesc *format_desc)
2723 /* The flags entry of a format contains the post pixel shader blending capability */
2724 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2726 return FALSE;
2729 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2731 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2732 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2733 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2734 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2735 * capability anyway.
2737 * For now lets report this on all formats, but in the future we may want to
2738 * restrict it to some should games need that
2740 return TRUE;
2743 /* Check if a texture format is supported on the given adapter */
2744 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2745 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2747 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2748 const shader_backend_t *shader_backend;
2749 const struct fragment_pipeline *fp;
2751 switch (format_desc->format)
2753 /*****
2754 * supported: RGB(A) formats
2756 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2757 case WINED3DFMT_A8R8G8B8:
2758 case WINED3DFMT_X8R8G8B8:
2759 case WINED3DFMT_R5G6B5:
2760 case WINED3DFMT_X1R5G5B5:
2761 case WINED3DFMT_A1R5G5B5:
2762 case WINED3DFMT_A4R4G4B4:
2763 case WINED3DFMT_A8_UNORM:
2764 case WINED3DFMT_X4R4G4B4:
2765 case WINED3DFMT_R8G8B8A8_UNORM:
2766 case WINED3DFMT_X8B8G8R8:
2767 case WINED3DFMT_A2R10G10B10:
2768 case WINED3DFMT_R10G10B10A2_UNORM:
2769 case WINED3DFMT_R16G16_UNORM:
2770 TRACE_(d3d_caps)("[OK]\n");
2771 return TRUE;
2773 case WINED3DFMT_R3G3B2:
2774 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2775 return FALSE;
2777 /*****
2778 * supported: Palettized
2780 case WINED3DFMT_P8:
2781 TRACE_(d3d_caps)("[OK]\n");
2782 return TRUE;
2783 /* No Windows driver offers A8P8, so don't offer it either */
2784 case WINED3DFMT_A8P8:
2785 return FALSE;
2787 /*****
2788 * Supported: (Alpha)-Luminance
2790 case WINED3DFMT_L8:
2791 case WINED3DFMT_A8L8:
2792 case WINED3DFMT_L16:
2793 TRACE_(d3d_caps)("[OK]\n");
2794 return TRUE;
2796 /* Not supported on Windows, thus disabled */
2797 case WINED3DFMT_A4L4:
2798 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2799 return FALSE;
2801 /*****
2802 * Supported: Depth/Stencil formats
2804 case WINED3DFMT_D16_LOCKABLE:
2805 case WINED3DFMT_D16_UNORM:
2806 case WINED3DFMT_D15S1:
2807 case WINED3DFMT_D24X8:
2808 case WINED3DFMT_D24X4S4:
2809 case WINED3DFMT_D24S8:
2810 case WINED3DFMT_D24FS8:
2811 case WINED3DFMT_D32:
2812 case WINED3DFMT_D32F_LOCKABLE:
2813 return TRUE;
2815 /*****
2816 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2817 * GL_NV_texture_shader). Emulated by shaders
2819 case WINED3DFMT_R8G8_SNORM:
2820 case WINED3DFMT_X8L8V8U8:
2821 case WINED3DFMT_L6V5U5:
2822 case WINED3DFMT_R8G8B8A8_SNORM:
2823 case WINED3DFMT_R16G16_SNORM:
2824 /* Ask the shader backend if it can deal with the conversion. If
2825 * we've got a GL extension giving native support this will be an
2826 * identity conversion. */
2827 shader_backend = select_shader_backend(adapter, DeviceType);
2828 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2830 TRACE_(d3d_caps)("[OK]\n");
2831 return TRUE;
2833 TRACE_(d3d_caps)("[FAILED]\n");
2834 return FALSE;
2836 case WINED3DFMT_DXT1:
2837 case WINED3DFMT_DXT2:
2838 case WINED3DFMT_DXT3:
2839 case WINED3DFMT_DXT4:
2840 case WINED3DFMT_DXT5:
2841 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2842 TRACE_(d3d_caps)("[OK]\n");
2843 return TRUE;
2845 TRACE_(d3d_caps)("[FAILED]\n");
2846 return FALSE;
2849 /*****
2850 * Odd formats - not supported
2852 case WINED3DFMT_VERTEXDATA:
2853 case WINED3DFMT_R16_UINT:
2854 case WINED3DFMT_R32_UINT:
2855 case WINED3DFMT_R16G16B16A16_SNORM:
2856 case WINED3DFMT_A2W10V10U10:
2857 case WINED3DFMT_W11V11U10:
2858 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2859 return FALSE;
2861 /*****
2862 * WINED3DFMT_CxV8U8: Not supported right now
2864 case WINED3DFMT_CxV8U8:
2865 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2866 return FALSE;
2868 /* YUV formats */
2869 case WINED3DFMT_UYVY:
2870 case WINED3DFMT_YUY2:
2871 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2872 TRACE_(d3d_caps)("[OK]\n");
2873 return TRUE;
2875 TRACE_(d3d_caps)("[FAILED]\n");
2876 return FALSE;
2877 case WINED3DFMT_YV12:
2878 TRACE_(d3d_caps)("[FAILED]\n");
2879 return FALSE;
2881 /* Not supported */
2882 case WINED3DFMT_R16G16B16A16_UNORM:
2883 case WINED3DFMT_A8R3G3B2:
2884 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2885 return FALSE;
2887 /* Floating point formats */
2888 case WINED3DFMT_R16_FLOAT:
2889 case WINED3DFMT_R16G16_FLOAT:
2890 case WINED3DFMT_R16G16B16A16_FLOAT:
2891 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2892 TRACE_(d3d_caps)("[OK]\n");
2893 return TRUE;
2895 TRACE_(d3d_caps)("[FAILED]\n");
2896 return FALSE;
2898 case WINED3DFMT_R32_FLOAT:
2899 case WINED3DFMT_R32G32_FLOAT:
2900 case WINED3DFMT_R32G32B32A32_FLOAT:
2901 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2902 TRACE_(d3d_caps)("[OK]\n");
2903 return TRUE;
2905 TRACE_(d3d_caps)("[FAILED]\n");
2906 return FALSE;
2908 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2909 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2910 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2911 * We can do instancing with all shader versions, but we need vertex shaders.
2913 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2914 * to enable instancing. WineD3D doesn't need that and just ignores it.
2916 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2918 case WINEMAKEFOURCC('I','N','S','T'):
2919 TRACE("ATI Instancing check hack\n");
2920 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2921 TRACE_(d3d_caps)("[OK]\n");
2922 return TRUE;
2924 TRACE_(d3d_caps)("[FAILED]\n");
2925 return FALSE;
2927 /* Some weird FOURCC formats */
2928 case WINED3DFMT_R8G8_B8G8:
2929 case WINED3DFMT_G8R8_G8B8:
2930 case WINED3DFMT_MULTI2_ARGB8:
2931 TRACE_(d3d_caps)("[FAILED]\n");
2932 return FALSE;
2934 /* Vendor specific formats */
2935 case WINED3DFMT_ATI2N:
2936 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2937 shader_backend = select_shader_backend(adapter, DeviceType);
2938 fp = select_fragment_implementation(adapter, DeviceType);
2939 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
2940 && fp->color_fixup_supported(format_desc->color_fixup))
2942 TRACE_(d3d_caps)("[OK]\n");
2943 return TRUE;
2946 TRACE_(d3d_caps)("[OK]\n");
2947 return TRUE;
2949 TRACE_(d3d_caps)("[FAILED]\n");
2950 return FALSE;
2952 case WINED3DFMT_NVHU:
2953 case WINED3DFMT_NVHS:
2954 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2955 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2956 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2957 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2958 * Applications have to deal with not having NVHS and NVHU.
2960 TRACE_(d3d_caps)("[FAILED]\n");
2961 return FALSE;
2963 case WINED3DFMT_UNKNOWN:
2964 return FALSE;
2966 default:
2967 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
2968 break;
2970 return FALSE;
2973 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
2974 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
2976 const struct blit_shader *blitter;
2978 if(SurfaceType == SURFACE_GDI) {
2979 switch(check_format_desc->format)
2981 case WINED3DFMT_R8G8B8:
2982 case WINED3DFMT_A8R8G8B8:
2983 case WINED3DFMT_X8R8G8B8:
2984 case WINED3DFMT_R5G6B5:
2985 case WINED3DFMT_X1R5G5B5:
2986 case WINED3DFMT_A1R5G5B5:
2987 case WINED3DFMT_A4R4G4B4:
2988 case WINED3DFMT_R3G3B2:
2989 case WINED3DFMT_A8_UNORM:
2990 case WINED3DFMT_A8R3G3B2:
2991 case WINED3DFMT_X4R4G4B4:
2992 case WINED3DFMT_R10G10B10A2_UNORM:
2993 case WINED3DFMT_R8G8B8A8_UNORM:
2994 case WINED3DFMT_X8B8G8R8:
2995 case WINED3DFMT_R16G16_UNORM:
2996 case WINED3DFMT_A2R10G10B10:
2997 case WINED3DFMT_R16G16B16A16_UNORM:
2998 case WINED3DFMT_P8:
2999 TRACE_(d3d_caps)("[OK]\n");
3000 return TRUE;
3001 default:
3002 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3003 return FALSE;
3007 /* All format that are supported for textures are supported for surfaces as well */
3008 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3009 /* All depth stencil formats are supported on surfaces */
3010 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3012 /* If opengl can't process the format natively, the blitter may be able to convert it */
3013 blitter = select_blit_implementation(adapter, DeviceType);
3014 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3016 TRACE_(d3d_caps)("[OK]\n");
3017 return TRUE;
3020 /* Reject other formats */
3021 TRACE_(d3d_caps)("[FAILED]\n");
3022 return FALSE;
3025 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
3027 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3029 if (!GL_LIMITS(vertex_samplers)) {
3030 TRACE_(d3d_caps)("[FAILED]\n");
3031 return FALSE;
3034 switch (format_desc->format)
3036 case WINED3DFMT_R32G32B32A32_FLOAT:
3037 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3038 TRACE_(d3d_caps)("[FAILED]\n");
3039 return FALSE;
3041 TRACE_(d3d_caps)("[OK]\n");
3042 return TRUE;
3044 default:
3045 TRACE_(d3d_caps)("[FAILED]\n");
3046 return FALSE;
3048 return FALSE;
3051 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3052 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3053 WINED3DSURFTYPE SurfaceType)
3055 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3056 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3057 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3058 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3059 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3060 DWORD UsageCaps = 0;
3062 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3063 This,
3064 Adapter,
3065 DeviceType, debug_d3ddevicetype(DeviceType),
3066 AdapterFormat, debug_d3dformat(AdapterFormat),
3067 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3068 RType, debug_d3dresourcetype(RType),
3069 CheckFormat, debug_d3dformat(CheckFormat));
3071 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3072 return WINED3DERR_INVALIDCALL;
3075 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3077 if(SurfaceType != SURFACE_OPENGL) {
3078 TRACE("[FAILED]\n");
3079 return WINED3DERR_NOTAVAILABLE;
3082 /* Cubetexture allows:
3083 * - D3DUSAGE_AUTOGENMIPMAP
3084 * - D3DUSAGE_DEPTHSTENCIL
3085 * - D3DUSAGE_DYNAMIC
3086 * - D3DUSAGE_NONSECURE (d3d9ex)
3087 * - D3DUSAGE_RENDERTARGET
3088 * - D3DUSAGE_SOFTWAREPROCESSING
3089 * - D3DUSAGE_QUERY_WRAPANDMIP
3091 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3092 /* Check if the texture format is around */
3093 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3095 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3096 /* Check for automatic mipmap generation support */
3097 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3098 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3099 } else {
3100 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3101 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3105 /* Always report dynamic locking */
3106 if(Usage & WINED3DUSAGE_DYNAMIC)
3107 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3109 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3110 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3112 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3113 } else {
3114 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3115 return WINED3DERR_NOTAVAILABLE;
3119 /* Always report software processing */
3120 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3121 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3123 /* Check QUERY_FILTER support */
3124 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3125 if (CheckFilterCapability(adapter, format_desc))
3127 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3128 } else {
3129 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3130 return WINED3DERR_NOTAVAILABLE;
3134 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3135 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3136 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3138 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3139 } else {
3140 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3141 return WINED3DERR_NOTAVAILABLE;
3145 /* Check QUERY_SRGBREAD support */
3146 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3147 if (CheckSrgbReadCapability(adapter, format_desc))
3149 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3150 } else {
3151 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3152 return WINED3DERR_NOTAVAILABLE;
3156 /* Check QUERY_SRGBWRITE support */
3157 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3158 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3160 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3161 } else {
3162 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3163 return WINED3DERR_NOTAVAILABLE;
3167 /* Check QUERY_VERTEXTEXTURE support */
3168 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3169 if (CheckVertexTextureCapability(adapter, format_desc))
3171 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3172 } else {
3173 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3174 return WINED3DERR_NOTAVAILABLE;
3178 /* Check QUERY_WRAPANDMIP support */
3179 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3180 if (CheckWrapAndMipCapability(adapter, format_desc))
3182 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3183 } else {
3184 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3185 return WINED3DERR_NOTAVAILABLE;
3188 } else {
3189 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3190 return WINED3DERR_NOTAVAILABLE;
3192 } else {
3193 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3194 return WINED3DERR_NOTAVAILABLE;
3196 } else if(RType == WINED3DRTYPE_SURFACE) {
3197 /* Surface allows:
3198 * - D3DUSAGE_DEPTHSTENCIL
3199 * - D3DUSAGE_NONSECURE (d3d9ex)
3200 * - D3DUSAGE_RENDERTARGET
3203 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3205 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3206 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3208 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3209 } else {
3210 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3211 return WINED3DERR_NOTAVAILABLE;
3215 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3216 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3218 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3219 } else {
3220 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3221 return WINED3DERR_NOTAVAILABLE;
3225 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3226 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3227 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3229 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3230 } else {
3231 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3232 return WINED3DERR_NOTAVAILABLE;
3235 } else {
3236 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3237 return WINED3DERR_NOTAVAILABLE;
3240 } else if(RType == WINED3DRTYPE_TEXTURE) {
3241 /* Texture allows:
3242 * - D3DUSAGE_AUTOGENMIPMAP
3243 * - D3DUSAGE_DEPTHSTENCIL
3244 * - D3DUSAGE_DMAP
3245 * - D3DUSAGE_DYNAMIC
3246 * - D3DUSAGE_NONSECURE (d3d9ex)
3247 * - D3DUSAGE_RENDERTARGET
3248 * - D3DUSAGE_SOFTWAREPROCESSING
3249 * - D3DUSAGE_TEXTAPI (d3d9ex)
3250 * - D3DUSAGE_QUERY_WRAPANDMIP
3253 if(SurfaceType != SURFACE_OPENGL) {
3254 TRACE("[FAILED]\n");
3255 return WINED3DERR_NOTAVAILABLE;
3258 /* Check if the texture format is around */
3259 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3261 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3262 /* Check for automatic mipmap generation support */
3263 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3264 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3265 } else {
3266 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3267 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3271 /* Always report dynamic locking */
3272 if(Usage & WINED3DUSAGE_DYNAMIC)
3273 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3275 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3276 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3278 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3279 } else {
3280 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3281 return WINED3DERR_NOTAVAILABLE;
3285 /* Always report software processing */
3286 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3287 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3289 /* Check QUERY_FILTER support */
3290 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3291 if (CheckFilterCapability(adapter, format_desc))
3293 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3294 } else {
3295 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3296 return WINED3DERR_NOTAVAILABLE;
3300 /* Check QUERY_LEGACYBUMPMAP support */
3301 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3302 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3304 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3305 } else {
3306 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3307 return WINED3DERR_NOTAVAILABLE;
3311 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3312 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3313 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3315 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3316 } else {
3317 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3318 return WINED3DERR_NOTAVAILABLE;
3322 /* Check QUERY_SRGBREAD support */
3323 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3324 if (CheckSrgbReadCapability(adapter, format_desc))
3326 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3327 } else {
3328 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3329 return WINED3DERR_NOTAVAILABLE;
3333 /* Check QUERY_SRGBWRITE support */
3334 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3335 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3337 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3338 } else {
3339 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3340 return WINED3DERR_NOTAVAILABLE;
3344 /* Check QUERY_VERTEXTEXTURE support */
3345 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3346 if (CheckVertexTextureCapability(adapter, format_desc))
3348 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3349 } else {
3350 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3351 return WINED3DERR_NOTAVAILABLE;
3355 /* Check QUERY_WRAPANDMIP support */
3356 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3357 if (CheckWrapAndMipCapability(adapter, format_desc))
3359 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3360 } else {
3361 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3362 return WINED3DERR_NOTAVAILABLE;
3366 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3367 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3369 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3370 } else {
3371 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3372 return WINED3DERR_NOTAVAILABLE;
3375 } else {
3376 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3377 return WINED3DERR_NOTAVAILABLE;
3379 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3380 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3381 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3383 * Volumetexture allows:
3384 * - D3DUSAGE_DYNAMIC
3385 * - D3DUSAGE_NONSECURE (d3d9ex)
3386 * - D3DUSAGE_SOFTWAREPROCESSING
3387 * - D3DUSAGE_QUERY_WRAPANDMIP
3390 if(SurfaceType != SURFACE_OPENGL) {
3391 TRACE("[FAILED]\n");
3392 return WINED3DERR_NOTAVAILABLE;
3395 /* Check volume texture and volume usage caps */
3396 if(GL_SUPPORT(EXT_TEXTURE3D)) {
3397 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3399 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3400 return WINED3DERR_NOTAVAILABLE;
3403 /* Always report dynamic locking */
3404 if(Usage & WINED3DUSAGE_DYNAMIC)
3405 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3407 /* Always report software processing */
3408 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3409 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3411 /* Check QUERY_FILTER support */
3412 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3413 if (CheckFilterCapability(adapter, format_desc))
3415 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3416 } else {
3417 TRACE_(d3d_caps)("[FAILED] - No query filter 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;
3476 } else {
3477 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3478 return WINED3DERR_NOTAVAILABLE;
3481 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3482 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3483 * app needing one of those formats, don't advertize them to avoid leading apps into
3484 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3485 * except of R32F.
3487 switch(CheckFormat) {
3488 case WINED3DFMT_P8:
3489 case WINED3DFMT_A4L4:
3490 case WINED3DFMT_R32_FLOAT:
3491 case WINED3DFMT_R16_FLOAT:
3492 case WINED3DFMT_X8L8V8U8:
3493 case WINED3DFMT_L6V5U5:
3494 case WINED3DFMT_R16G16_UNORM:
3495 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3496 return WINED3DERR_NOTAVAILABLE;
3498 case WINED3DFMT_R8G8B8A8_SNORM:
3499 case WINED3DFMT_R16G16_SNORM:
3500 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3501 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3502 return WINED3DERR_NOTAVAILABLE;
3504 break;
3506 case WINED3DFMT_R8G8_SNORM:
3507 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3508 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3509 return WINED3DERR_NOTAVAILABLE;
3511 break;
3513 case WINED3DFMT_DXT1:
3514 case WINED3DFMT_DXT2:
3515 case WINED3DFMT_DXT3:
3516 case WINED3DFMT_DXT4:
3517 case WINED3DFMT_DXT5:
3518 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3519 * compressed texture results in an error. While the D3D refrast does
3520 * support s3tc volumes, at least the nvidia windows driver does not, so
3521 * we're free not to support this format.
3523 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3524 return WINED3DERR_NOTAVAILABLE;
3526 default:
3527 /* Do nothing, continue with checking the format below */
3528 break;
3530 } else if(RType == WINED3DRTYPE_BUFFER){
3531 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3532 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3533 return WINED3DERR_NOTAVAILABLE;
3536 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3537 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3538 * usage flags match. */
3539 if(UsageCaps == Usage) {
3540 return WINED3D_OK;
3541 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3542 return WINED3DOK_NOAUTOGEN;
3543 } else {
3544 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);
3545 return WINED3DERR_NOTAVAILABLE;
3549 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3550 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3551 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3553 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3554 This,
3555 Adapter,
3556 DeviceType, debug_d3ddevicetype(DeviceType),
3557 SourceFormat, debug_d3dformat(SourceFormat),
3558 TargetFormat, debug_d3dformat(TargetFormat));
3559 return WINED3D_OK;
3562 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3564 const shader_backend_t *ret;
3565 int vs_selected_mode;
3566 int ps_selected_mode;
3568 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3569 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3570 ret = &glsl_shader_backend;
3571 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3572 ret = &arb_program_shader_backend;
3573 } else {
3574 ret = &none_shader_backend;
3576 return ret;
3579 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3580 WINED3DDEVTYPE DeviceType)
3582 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3583 int vs_selected_mode;
3584 int ps_selected_mode;
3586 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3587 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3588 return &arbfp_fragment_pipeline;
3589 } else if(ps_selected_mode == SHADER_ATI) {
3590 return &atifs_fragment_pipeline;
3591 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3592 return &nvts_fragment_pipeline;
3593 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3594 return &nvrc_fragment_pipeline;
3595 } else {
3596 return &ffp_fragment_pipeline;
3600 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3602 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3603 int vs_selected_mode;
3604 int ps_selected_mode;
3606 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3607 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3608 return &arbfp_blit;
3609 } else {
3610 return &ffp_blit;
3614 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3615 subset of a D3DCAPS9 structure. However, it has to come via a void *
3616 as the d3d8 interface cannot import the d3d9 header */
3617 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3619 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3620 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3621 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3622 int vs_selected_mode;
3623 int ps_selected_mode;
3624 struct shader_caps shader_caps;
3625 struct fragment_caps fragment_caps;
3626 const shader_backend_t *shader_backend;
3627 const struct fragment_pipeline *frag_pipeline = NULL;
3628 DWORD ckey_caps, blit_caps, fx_caps;
3630 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3632 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3633 return WINED3DERR_INVALIDCALL;
3636 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3638 /* This function should *not* be modifying GL caps
3639 * TODO: move the functionality where it belongs */
3640 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3642 /* ------------------------------------------------
3643 The following fields apply to both d3d8 and d3d9
3644 ------------------------------------------------ */
3645 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3646 pCaps->AdapterOrdinal = Adapter;
3648 pCaps->Caps = 0;
3649 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3650 WINED3DCAPS2_FULLSCREENGAMMA |
3651 WINED3DCAPS2_DYNAMICTEXTURES;
3652 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3653 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3656 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3657 WINED3DCAPS3_COPY_TO_VIDMEM |
3658 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3660 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3661 WINED3DPRESENT_INTERVAL_ONE;
3663 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3664 WINED3DCURSORCAPS_LOWRES;
3666 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3667 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3668 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3669 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3670 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3671 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3672 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3673 WINED3DDEVCAPS_PUREDEVICE |
3674 WINED3DDEVCAPS_HWRASTERIZATION |
3675 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3676 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3677 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3678 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3679 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3680 WINED3DDEVCAPS_RTPATCHES;
3682 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3683 WINED3DPMISCCAPS_CULLCCW |
3684 WINED3DPMISCCAPS_CULLCW |
3685 WINED3DPMISCCAPS_COLORWRITEENABLE |
3686 WINED3DPMISCCAPS_CLIPTLVERTS |
3687 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3688 WINED3DPMISCCAPS_MASKZ |
3689 WINED3DPMISCCAPS_BLENDOP |
3690 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3691 /* TODO:
3692 WINED3DPMISCCAPS_NULLREFERENCE
3693 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3694 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3695 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3696 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3698 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3699 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3701 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3702 WINED3DPRASTERCAPS_PAT |
3703 WINED3DPRASTERCAPS_WFOG |
3704 WINED3DPRASTERCAPS_ZFOG |
3705 WINED3DPRASTERCAPS_FOGVERTEX |
3706 WINED3DPRASTERCAPS_FOGTABLE |
3707 WINED3DPRASTERCAPS_STIPPLE |
3708 WINED3DPRASTERCAPS_SUBPIXEL |
3709 WINED3DPRASTERCAPS_ZTEST |
3710 WINED3DPRASTERCAPS_SCISSORTEST |
3711 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3712 WINED3DPRASTERCAPS_DEPTHBIAS;
3714 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3715 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3716 WINED3DPRASTERCAPS_ZBIAS |
3717 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3719 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3720 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3722 /* FIXME Add:
3723 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3724 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3725 WINED3DPRASTERCAPS_ANTIALIASEDGES
3726 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3727 WINED3DPRASTERCAPS_WBUFFER */
3729 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3730 WINED3DPCMPCAPS_EQUAL |
3731 WINED3DPCMPCAPS_GREATER |
3732 WINED3DPCMPCAPS_GREATEREQUAL |
3733 WINED3DPCMPCAPS_LESS |
3734 WINED3DPCMPCAPS_LESSEQUAL |
3735 WINED3DPCMPCAPS_NEVER |
3736 WINED3DPCMPCAPS_NOTEQUAL;
3738 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3739 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3740 WINED3DPBLENDCAPS_DESTALPHA |
3741 WINED3DPBLENDCAPS_DESTCOLOR |
3742 WINED3DPBLENDCAPS_INVDESTALPHA |
3743 WINED3DPBLENDCAPS_INVDESTCOLOR |
3744 WINED3DPBLENDCAPS_INVSRCALPHA |
3745 WINED3DPBLENDCAPS_INVSRCCOLOR |
3746 WINED3DPBLENDCAPS_ONE |
3747 WINED3DPBLENDCAPS_SRCALPHA |
3748 WINED3DPBLENDCAPS_SRCALPHASAT |
3749 WINED3DPBLENDCAPS_SRCCOLOR |
3750 WINED3DPBLENDCAPS_ZERO;
3752 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3753 WINED3DPBLENDCAPS_DESTCOLOR |
3754 WINED3DPBLENDCAPS_INVDESTALPHA |
3755 WINED3DPBLENDCAPS_INVDESTCOLOR |
3756 WINED3DPBLENDCAPS_INVSRCALPHA |
3757 WINED3DPBLENDCAPS_INVSRCCOLOR |
3758 WINED3DPBLENDCAPS_ONE |
3759 WINED3DPBLENDCAPS_SRCALPHA |
3760 WINED3DPBLENDCAPS_SRCCOLOR |
3761 WINED3DPBLENDCAPS_ZERO;
3762 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3763 * according to the glBlendFunc manpage
3765 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3766 * legacy settings for srcblend only
3769 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3770 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3771 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3775 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3776 WINED3DPCMPCAPS_EQUAL |
3777 WINED3DPCMPCAPS_GREATER |
3778 WINED3DPCMPCAPS_GREATEREQUAL |
3779 WINED3DPCMPCAPS_LESS |
3780 WINED3DPCMPCAPS_LESSEQUAL |
3781 WINED3DPCMPCAPS_NEVER |
3782 WINED3DPCMPCAPS_NOTEQUAL;
3784 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3785 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3786 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3787 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3788 WINED3DPSHADECAPS_COLORFLATRGB |
3789 WINED3DPSHADECAPS_FOGFLAT |
3790 WINED3DPSHADECAPS_FOGGOURAUD |
3791 WINED3DPSHADECAPS_SPECULARFLATRGB;
3793 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3794 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3795 WINED3DPTEXTURECAPS_TRANSPARENCY |
3796 WINED3DPTEXTURECAPS_BORDER |
3797 WINED3DPTEXTURECAPS_MIPMAP |
3798 WINED3DPTEXTURECAPS_PROJECTED |
3799 WINED3DPTEXTURECAPS_PERSPECTIVE;
3801 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3802 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3803 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3806 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3807 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3808 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3809 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3812 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3813 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3814 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3815 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3819 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3820 WINED3DPTFILTERCAPS_MAGFPOINT |
3821 WINED3DPTFILTERCAPS_MINFLINEAR |
3822 WINED3DPTFILTERCAPS_MINFPOINT |
3823 WINED3DPTFILTERCAPS_MIPFLINEAR |
3824 WINED3DPTFILTERCAPS_MIPFPOINT |
3825 WINED3DPTFILTERCAPS_LINEAR |
3826 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3827 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3828 WINED3DPTFILTERCAPS_MIPLINEAR |
3829 WINED3DPTFILTERCAPS_MIPNEAREST |
3830 WINED3DPTFILTERCAPS_NEAREST;
3832 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3833 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3834 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3837 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3838 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3839 WINED3DPTFILTERCAPS_MAGFPOINT |
3840 WINED3DPTFILTERCAPS_MINFLINEAR |
3841 WINED3DPTFILTERCAPS_MINFPOINT |
3842 WINED3DPTFILTERCAPS_MIPFLINEAR |
3843 WINED3DPTFILTERCAPS_MIPFPOINT |
3844 WINED3DPTFILTERCAPS_LINEAR |
3845 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3846 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3847 WINED3DPTFILTERCAPS_MIPLINEAR |
3848 WINED3DPTFILTERCAPS_MIPNEAREST |
3849 WINED3DPTFILTERCAPS_NEAREST;
3851 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3852 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3853 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3855 } else
3856 pCaps->CubeTextureFilterCaps = 0;
3858 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3859 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3860 WINED3DPTFILTERCAPS_MAGFPOINT |
3861 WINED3DPTFILTERCAPS_MINFLINEAR |
3862 WINED3DPTFILTERCAPS_MINFPOINT |
3863 WINED3DPTFILTERCAPS_MIPFLINEAR |
3864 WINED3DPTFILTERCAPS_MIPFPOINT |
3865 WINED3DPTFILTERCAPS_LINEAR |
3866 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3867 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3868 WINED3DPTFILTERCAPS_MIPLINEAR |
3869 WINED3DPTFILTERCAPS_MIPNEAREST |
3870 WINED3DPTFILTERCAPS_NEAREST;
3871 } else
3872 pCaps->VolumeTextureFilterCaps = 0;
3874 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3875 WINED3DPTADDRESSCAPS_CLAMP |
3876 WINED3DPTADDRESSCAPS_WRAP;
3878 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3879 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3881 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3882 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3884 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3885 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3888 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3889 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3890 WINED3DPTADDRESSCAPS_CLAMP |
3891 WINED3DPTADDRESSCAPS_WRAP;
3892 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3893 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3895 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3896 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3898 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3899 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3901 } else
3902 pCaps->VolumeTextureAddressCaps = 0;
3904 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3905 WINED3DLINECAPS_ZTEST |
3906 WINED3DLINECAPS_BLEND |
3907 WINED3DLINECAPS_ALPHACMP |
3908 WINED3DLINECAPS_FOG;
3909 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3910 * idea how generating the smoothing alpha values works; the result is different
3913 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3914 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3916 if(GL_SUPPORT(EXT_TEXTURE3D))
3917 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3918 else
3919 pCaps->MaxVolumeExtent = 0;
3921 pCaps->MaxTextureRepeat = 32768;
3922 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3923 pCaps->MaxVertexW = 1.0f;
3925 pCaps->GuardBandLeft = 0.0f;
3926 pCaps->GuardBandTop = 0.0f;
3927 pCaps->GuardBandRight = 0.0f;
3928 pCaps->GuardBandBottom = 0.0f;
3930 pCaps->ExtentsAdjust = 0.0f;
3932 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3933 WINED3DSTENCILCAPS_INCRSAT |
3934 WINED3DSTENCILCAPS_INVERT |
3935 WINED3DSTENCILCAPS_KEEP |
3936 WINED3DSTENCILCAPS_REPLACE |
3937 WINED3DSTENCILCAPS_ZERO;
3938 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3939 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3940 WINED3DSTENCILCAPS_INCR;
3942 if (GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3943 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3946 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3948 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3949 pCaps->MaxActiveLights = GL_LIMITS(lights);
3951 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3952 pCaps->MaxVertexBlendMatrixIndex = 0;
3954 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3955 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3958 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3959 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3960 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3961 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3962 WINED3DVTXPCAPS_LOCALVIEWER |
3963 WINED3DVTXPCAPS_VERTEXFOG |
3964 WINED3DVTXPCAPS_TEXGEN;
3966 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3967 pCaps->MaxVertexIndex = 0xFFFFF;
3968 pCaps->MaxStreams = MAX_STREAMS;
3969 pCaps->MaxStreamStride = 1024;
3971 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3972 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3973 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3974 pCaps->MaxNpatchTessellationLevel = 0;
3975 pCaps->MasterAdapterOrdinal = 0;
3976 pCaps->AdapterOrdinalInGroup = 0;
3977 pCaps->NumberOfAdaptersInGroup = 1;
3979 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3981 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3982 WINED3DPTFILTERCAPS_MAGFPOINT |
3983 WINED3DPTFILTERCAPS_MINFLINEAR |
3984 WINED3DPTFILTERCAPS_MAGFLINEAR;
3985 pCaps->VertexTextureFilterCaps = 0;
3987 memset(&shader_caps, 0, sizeof(shader_caps));
3988 shader_backend = select_shader_backend(adapter, DeviceType);
3989 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3991 memset(&fragment_caps, 0, sizeof(fragment_caps));
3992 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3993 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
3995 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
3996 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
3998 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
3999 * Ignore shader model capabilities if disabled in config
4001 if(vs_selected_mode == SHADER_NONE) {
4002 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4003 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4004 pCaps->MaxVertexShaderConst = 0;
4005 } else {
4006 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4007 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4010 if(ps_selected_mode == SHADER_NONE) {
4011 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4012 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4013 pCaps->PixelShader1xMaxValue = 0.0f;
4014 } else {
4015 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4016 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4019 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4020 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4021 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4023 pCaps->VS20Caps = shader_caps.VS20Caps;
4024 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4025 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4026 pCaps->PS20Caps = shader_caps.PS20Caps;
4027 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4028 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4030 /* The following caps are shader specific, but they are things we cannot detect, or which
4031 * are the same among all shader models. So to avoid code duplication set the shader version
4032 * specific, but otherwise constant caps here
4034 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4035 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4036 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4037 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4038 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4039 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
4040 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4042 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4043 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
4044 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
4045 pCaps->VS20Caps.Caps = 0;
4046 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4047 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
4048 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4050 pCaps->MaxVShaderInstructionsExecuted = 65535;
4051 pCaps->MaxVertexShader30InstructionSlots = 0;
4052 } else { /* VS 1.x */
4053 pCaps->VS20Caps.Caps = 0;
4054 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4055 pCaps->VS20Caps.NumTemps = 0;
4056 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4058 pCaps->MaxVShaderInstructionsExecuted = 0;
4059 pCaps->MaxVertexShader30InstructionSlots = 0;
4062 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4063 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4064 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4066 /* 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 */
4067 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4068 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4069 WINED3DPS20CAPS_PREDICATION |
4070 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4071 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4072 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4073 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
4074 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4075 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4077 pCaps->MaxPShaderInstructionsExecuted = 65535;
4078 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
4079 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
4080 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4081 pCaps->PS20Caps.Caps = 0;
4082 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4083 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
4084 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4085 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4087 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4088 pCaps->MaxPixelShader30InstructionSlots = 0;
4089 } else { /* PS 1.x */
4090 pCaps->PS20Caps.Caps = 0;
4091 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4092 pCaps->PS20Caps.NumTemps = 0;
4093 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4094 pCaps->PS20Caps.NumInstructionSlots = 0;
4096 pCaps->MaxPShaderInstructionsExecuted = 0;
4097 pCaps->MaxPixelShader30InstructionSlots = 0;
4100 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4101 /* OpenGL supports all the formats below, perhaps not always
4102 * without conversion, but it supports them.
4103 * Further GLSL doesn't seem to have an official unsigned type so
4104 * don't advertise it yet as I'm not sure how we handle it.
4105 * We might need to add some clamping in the shader engine to
4106 * support it.
4107 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4108 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4109 WINED3DDTCAPS_UBYTE4N |
4110 WINED3DDTCAPS_SHORT2N |
4111 WINED3DDTCAPS_SHORT4N;
4112 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
4113 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4114 WINED3DDTCAPS_FLOAT16_4;
4116 } else
4117 pCaps->DeclTypes = 0;
4119 /* Set DirectDraw helper Caps */
4120 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4121 WINEDDCKEYCAPS_SRCBLT;
4122 fx_caps = WINEDDFXCAPS_BLTALPHA |
4123 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4124 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4125 WINEDDFXCAPS_BLTROTATION90 |
4126 WINEDDFXCAPS_BLTSHRINKX |
4127 WINEDDFXCAPS_BLTSHRINKXN |
4128 WINEDDFXCAPS_BLTSHRINKY |
4129 WINEDDFXCAPS_BLTSHRINKXN |
4130 WINEDDFXCAPS_BLTSTRETCHX |
4131 WINEDDFXCAPS_BLTSTRETCHXN |
4132 WINEDDFXCAPS_BLTSTRETCHY |
4133 WINEDDFXCAPS_BLTSTRETCHYN;
4134 blit_caps = WINEDDCAPS_BLT |
4135 WINEDDCAPS_BLTCOLORFILL |
4136 WINEDDCAPS_BLTDEPTHFILL |
4137 WINEDDCAPS_BLTSTRETCH |
4138 WINEDDCAPS_CANBLTSYSMEM |
4139 WINEDDCAPS_CANCLIP |
4140 WINEDDCAPS_CANCLIPSTRETCHED |
4141 WINEDDCAPS_COLORKEY |
4142 WINEDDCAPS_COLORKEYHWASSIST |
4143 WINEDDCAPS_ALIGNBOUNDARYSRC;
4145 /* Fill the ddraw caps structure */
4146 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4147 WINEDDCAPS_PALETTE |
4148 blit_caps;
4149 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4150 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4151 WINEDDCAPS2_PRIMARYGAMMA |
4152 WINEDDCAPS2_WIDESURFACES |
4153 WINEDDCAPS2_CANRENDERWINDOWED;
4154 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4155 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4156 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4157 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4158 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4159 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4160 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4161 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4162 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4164 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4165 WINEDDSCAPS_BACKBUFFER |
4166 WINEDDSCAPS_FLIP |
4167 WINEDDSCAPS_FRONTBUFFER |
4168 WINEDDSCAPS_OFFSCREENPLAIN |
4169 WINEDDSCAPS_PALETTE |
4170 WINEDDSCAPS_PRIMARYSURFACE |
4171 WINEDDSCAPS_SYSTEMMEMORY |
4172 WINEDDSCAPS_VIDEOMEMORY |
4173 WINEDDSCAPS_VISIBLE;
4174 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4176 /* Set D3D caps if OpenGL is available. */
4177 if (adapter->opengl)
4179 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4180 WINEDDSCAPS_MIPMAP |
4181 WINEDDSCAPS_TEXTURE |
4182 WINEDDSCAPS_ZBUFFER;
4183 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4186 return WINED3D_OK;
4189 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
4190 and fields being inserted in the middle, a new structure is used in place */
4191 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
4192 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
4193 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
4195 IWineD3DDeviceImpl *object = NULL;
4196 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4197 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
4198 WINED3DDISPLAYMODE mode;
4199 const struct fragment_pipeline *frag_pipeline = NULL;
4200 int i;
4201 struct fragment_caps ffp_caps;
4202 struct shader_caps shader_caps;
4203 HRESULT hr;
4205 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4206 * number and create a device without a 3D adapter for 2D only operation.
4208 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4209 return WINED3DERR_INVALIDCALL;
4212 /* Create a WineD3DDevice object */
4213 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
4214 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4215 TRACE("Created WineD3DDevice object @ %p\n", object);
4216 if (NULL == object) {
4217 return WINED3DERR_OUTOFVIDEOMEMORY;
4220 /* Set up initial COM information */
4221 object->lpVtbl = &IWineD3DDevice_Vtbl;
4222 object->ref = 1;
4223 object->wineD3D = iface;
4224 object->adapter = This->adapter_count ? adapter : NULL;
4225 IWineD3D_AddRef(object->wineD3D);
4226 object->parent = parent;
4227 object->device_parent = device_parent;
4228 list_init(&object->resources);
4229 list_init(&object->shaders);
4231 if(This->dxVersion == 7) {
4232 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
4233 } else {
4234 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4236 object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4238 /* Set the state up as invalid until the device is fully created */
4239 object->state = WINED3DERR_DRIVERINTERNALERROR;
4241 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
4242 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4244 /* Save the creation parameters */
4245 object->createParms.AdapterOrdinal = Adapter;
4246 object->createParms.DeviceType = DeviceType;
4247 object->createParms.hFocusWindow = hFocusWindow;
4248 object->createParms.BehaviorFlags = BehaviourFlags;
4250 /* Initialize other useful values */
4251 object->adapterNo = Adapter;
4252 object->devType = DeviceType;
4254 select_shader_mode(&adapter->gl_info, DeviceType,
4255 &object->ps_selected_mode, &object->vs_selected_mode);
4256 object->shader_backend = select_shader_backend(adapter, DeviceType);
4258 memset(&shader_caps, 0, sizeof(shader_caps));
4259 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4260 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
4261 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
4262 object->vs_clipping = shader_caps.VSClipping;
4264 memset(&ffp_caps, 0, sizeof(ffp_caps));
4265 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4266 object->frag_pipe = frag_pipeline;
4267 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
4268 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
4269 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
4270 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
4271 ffp_vertexstate_template, frag_pipeline, misc_state_template);
4273 if (FAILED(hr)) {
4274 IWineD3D_Release(object->wineD3D);
4275 HeapFree(GetProcessHeap(), 0, object);
4277 return hr;
4280 object->blitter = select_blit_implementation(adapter, DeviceType);
4282 /* set the state of the device to valid */
4283 object->state = WINED3D_OK;
4285 /* Get the initial screen setup for ddraw */
4286 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4288 object->ddraw_width = mode.Width;
4289 object->ddraw_height = mode.Height;
4290 object->ddraw_format = mode.Format;
4292 for(i = 0; i < PATCHMAP_SIZE; i++) {
4293 list_init(&object->patches[i]);
4296 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4298 return WINED3D_OK;
4301 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4302 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4303 IUnknown_AddRef(This->parent);
4304 *pParent = This->parent;
4305 return WINED3D_OK;
4308 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
4309 IUnknown* surfaceParent;
4310 TRACE("(%p) call back\n", pSurface);
4312 /* Now, release the parent, which will take care of cleaning up the surface for us */
4313 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
4314 IUnknown_Release(surfaceParent);
4315 return IUnknown_Release(surfaceParent);
4318 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
4319 IUnknown* volumeParent;
4320 TRACE("(%p) call back\n", pVolume);
4322 /* Now, release the parent, which will take care of cleaning up the volume for us */
4323 IWineD3DVolume_GetParent(pVolume, &volumeParent);
4324 IUnknown_Release(volumeParent);
4325 return IUnknown_Release(volumeParent);
4328 static void WINE_GLAPI invalid_func(const void *data)
4330 ERR("Invalid vertex attribute function called\n");
4331 DebugBreak();
4334 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4336 ERR("Invalid texcoord function called\n");
4337 DebugBreak();
4340 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4341 * the extension detection and are used in drawStridedSlow
4343 static void WINE_GLAPI position_d3dcolor(const void *data)
4345 DWORD pos = *((const DWORD *)data);
4347 FIXME("Add a test for fixed function position from d3dcolor type\n");
4348 glVertex4s(D3DCOLOR_B_R(pos),
4349 D3DCOLOR_B_G(pos),
4350 D3DCOLOR_B_B(pos),
4351 D3DCOLOR_B_A(pos));
4354 static void WINE_GLAPI position_float4(const void *data)
4356 const GLfloat *pos = data;
4358 if (pos[3] != 0.0f && pos[3] != 1.0f)
4360 float w = 1.0f / pos[3];
4362 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4364 else
4366 glVertex3fv(pos);
4370 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4372 DWORD diffuseColor = *((const DWORD *)data);
4374 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4375 D3DCOLOR_B_G(diffuseColor),
4376 D3DCOLOR_B_B(diffuseColor),
4377 D3DCOLOR_B_A(diffuseColor));
4380 static void WINE_GLAPI specular_d3dcolor(const void *data)
4382 DWORD specularColor = *((const DWORD *)data);
4383 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4384 D3DCOLOR_B_G(specularColor),
4385 D3DCOLOR_B_B(specularColor)};
4387 specular_func_3ubv(d);
4390 static void WINE_GLAPI warn_no_specular_func(const void *data)
4392 WARN("GL_EXT_secondary_color not supported\n");
4395 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4397 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4398 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4399 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4400 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4401 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4402 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4403 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4404 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4405 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4406 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4407 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4408 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4409 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4410 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4411 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4412 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4413 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4415 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4416 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4417 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4418 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4419 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4420 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4421 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4422 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4423 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4424 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4425 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4426 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4427 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4428 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4429 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4430 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4431 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4433 /* No 4 component entry points here */
4434 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4435 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4436 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4437 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4438 } else {
4439 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4441 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4442 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4443 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4444 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4445 } else {
4446 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4448 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4449 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4450 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4451 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4452 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4453 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4454 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4455 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4456 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4457 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4458 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4459 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4461 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4462 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4464 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4465 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4466 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4467 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4468 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4469 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4470 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4471 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4472 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4473 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4474 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4475 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4476 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4477 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4478 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4479 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4480 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4482 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4483 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4484 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4485 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4486 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4487 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4488 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4489 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4490 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4491 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4492 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4493 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4494 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4495 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4496 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4497 if (GL_SUPPORT(NV_HALF_FLOAT))
4499 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4500 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4501 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4502 } else {
4503 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4504 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4508 BOOL InitAdapters(IWineD3DImpl *This)
4510 static HMODULE mod_gl;
4511 BOOL ret;
4512 int ps_selected_mode, vs_selected_mode;
4514 /* No need to hold any lock. The calling library makes sure only one thread calls
4515 * wined3d simultaneously
4518 TRACE("Initializing adapters\n");
4520 if(!mod_gl) {
4521 #ifdef USE_WIN32_OPENGL
4522 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4523 mod_gl = LoadLibraryA("opengl32.dll");
4524 if(!mod_gl) {
4525 ERR("Can't load opengl32.dll!\n");
4526 goto nogl_adapter;
4528 #else
4529 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4530 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4531 mod_gl = GetModuleHandleA("gdi32.dll");
4532 #endif
4535 /* Load WGL core functions from opengl32.dll */
4536 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4537 WGL_FUNCS_GEN;
4538 #undef USE_WGL_FUNC
4540 if(!pwglGetProcAddress) {
4541 ERR("Unable to load wglGetProcAddress!\n");
4542 goto nogl_adapter;
4545 /* Dynamically load all GL core functions */
4546 GL_FUNCS_GEN;
4547 #undef USE_GL_FUNC
4549 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4550 * otherwise because we have to use winex11.drv's override
4552 #ifdef USE_WIN32_OPENGL
4553 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4554 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4555 #else
4556 wglFinish = (void*)pwglGetProcAddress("wglFinish");
4557 wglFlush = (void*)pwglGetProcAddress("wglFlush");
4558 #endif
4560 glEnableWINE = glEnable;
4561 glDisableWINE = glDisable;
4563 /* For now only one default adapter */
4565 struct WineD3DAdapter *adapter = &This->adapters[0];
4566 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4567 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4568 int iPixelFormat;
4569 int res;
4570 int i;
4571 WineD3D_PixelFormat *cfgs;
4572 DISPLAY_DEVICEW DisplayDevice;
4573 HDC hdc;
4575 TRACE("Initializing default adapter\n");
4576 adapter->num = 0;
4577 adapter->monitorPoint.x = -1;
4578 adapter->monitorPoint.y = -1;
4580 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4582 ERR("Failed to get a gl context for default adapter\n");
4583 goto nogl_adapter;
4586 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4587 if(!ret) {
4588 ERR("Failed to initialize gl caps for default adapter\n");
4589 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4590 goto nogl_adapter;
4592 ret = initPixelFormats(&adapter->gl_info);
4593 if(!ret) {
4594 ERR("Failed to init gl formats\n");
4595 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4596 goto nogl_adapter;
4599 hdc = fake_gl_ctx.dc;
4601 adapter->driver = "Display";
4602 adapter->description = "Direct3D HAL";
4604 /* Use the VideoRamSize registry setting when set */
4605 if(wined3d_settings.emulated_textureram)
4606 adapter->TextureRam = wined3d_settings.emulated_textureram;
4607 else
4608 adapter->TextureRam = adapter->gl_info.vidmem;
4609 adapter->UsedTextureRam = 0;
4610 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4612 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4613 DisplayDevice.cb = sizeof(DisplayDevice);
4614 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4615 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4616 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4618 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4620 int attribute;
4621 int attribs[10];
4622 int values[10];
4623 int nAttribs = 0;
4625 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4626 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4628 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4629 cfgs = adapter->cfgs;
4630 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4631 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4632 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4633 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4634 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4635 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4636 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4637 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4638 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4639 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4641 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4643 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4645 if(!res)
4646 continue;
4648 /* Cache the pixel format */
4649 cfgs->iPixelFormat = iPixelFormat;
4650 cfgs->redSize = values[0];
4651 cfgs->greenSize = values[1];
4652 cfgs->blueSize = values[2];
4653 cfgs->alphaSize = values[3];
4654 cfgs->depthSize = values[4];
4655 cfgs->stencilSize = values[5];
4656 cfgs->windowDrawable = values[6];
4657 cfgs->iPixelType = values[7];
4658 cfgs->doubleBuffer = values[8];
4659 cfgs->auxBuffers = values[9];
4661 cfgs->pbufferDrawable = FALSE;
4662 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4663 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4664 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4665 int value;
4666 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4667 cfgs->pbufferDrawable = value;
4670 cfgs->numSamples = 0;
4671 /* Check multisample support */
4672 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4673 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4674 int value[2];
4675 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4676 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4677 * value[1] = number of multi sample buffers*/
4678 if(value[0])
4679 cfgs->numSamples = value[1];
4683 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);
4684 cfgs++;
4687 else
4689 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4690 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4691 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4693 cfgs = adapter->cfgs;
4694 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4696 PIXELFORMATDESCRIPTOR ppfd;
4698 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4699 if(!res)
4700 continue;
4702 /* We only want HW acceleration using an OpenGL ICD driver.
4703 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4704 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4706 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4708 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4709 continue;
4712 cfgs->iPixelFormat = iPixelFormat;
4713 cfgs->redSize = ppfd.cRedBits;
4714 cfgs->greenSize = ppfd.cGreenBits;
4715 cfgs->blueSize = ppfd.cBlueBits;
4716 cfgs->alphaSize = ppfd.cAlphaBits;
4717 cfgs->depthSize = ppfd.cDepthBits;
4718 cfgs->stencilSize = ppfd.cStencilBits;
4719 cfgs->pbufferDrawable = 0;
4720 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4721 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4722 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4723 cfgs->auxBuffers = ppfd.cAuxBuffers;
4724 cfgs->numSamples = 0;
4726 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);
4727 cfgs++;
4728 adapter->nCfgs++;
4731 /* 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 */
4732 if(!adapter->nCfgs)
4734 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4736 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4737 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4738 goto nogl_adapter;
4742 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4743 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4744 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4745 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4746 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4747 * driver is allowed to consume more bits EXCEPT for stencil bits.
4749 * Mark an adapter with this broken stencil behavior.
4751 adapter->brokenStencil = TRUE;
4752 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4754 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4755 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4756 adapter->brokenStencil = FALSE;
4757 break;
4761 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4763 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4764 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4765 fillGLAttribFuncs(&adapter->gl_info);
4766 adapter->opengl = TRUE;
4768 This->adapter_count = 1;
4769 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4771 return TRUE;
4773 nogl_adapter:
4774 /* Initialize an adapter for ddraw-only memory counting */
4775 memset(This->adapters, 0, sizeof(This->adapters));
4776 This->adapters[0].num = 0;
4777 This->adapters[0].opengl = FALSE;
4778 This->adapters[0].monitorPoint.x = -1;
4779 This->adapters[0].monitorPoint.y = -1;
4781 This->adapters[0].driver = "Display";
4782 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4783 if(wined3d_settings.emulated_textureram) {
4784 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4785 } else {
4786 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4789 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4791 This->adapter_count = 1;
4792 return FALSE;
4795 /**********************************************************
4796 * IWineD3D VTbl follows
4797 **********************************************************/
4799 const IWineD3DVtbl IWineD3D_Vtbl =
4801 /* IUnknown */
4802 IWineD3DImpl_QueryInterface,
4803 IWineD3DImpl_AddRef,
4804 IWineD3DImpl_Release,
4805 /* IWineD3D */
4806 IWineD3DImpl_GetParent,
4807 IWineD3DImpl_GetAdapterCount,
4808 IWineD3DImpl_RegisterSoftwareDevice,
4809 IWineD3DImpl_GetAdapterMonitor,
4810 IWineD3DImpl_GetAdapterModeCount,
4811 IWineD3DImpl_EnumAdapterModes,
4812 IWineD3DImpl_GetAdapterDisplayMode,
4813 IWineD3DImpl_GetAdapterIdentifier,
4814 IWineD3DImpl_CheckDeviceMultiSampleType,
4815 IWineD3DImpl_CheckDepthStencilMatch,
4816 IWineD3DImpl_CheckDeviceType,
4817 IWineD3DImpl_CheckDeviceFormat,
4818 IWineD3DImpl_CheckDeviceFormatConversion,
4819 IWineD3DImpl_GetDeviceCaps,
4820 IWineD3DImpl_CreateDevice