wined3d: Add support for ARB_depth_clamp.
[wine/multimedia.git] / dlls / wined3d / directx.c
blobd9608f517a5359eb0a3c1c3523debd77213707b7
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_clamp", ARB_DEPTH_CLAMP, 0 },
60 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
61 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
62 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
63 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
64 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
65 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
66 {"GL_ARB_imaging", ARB_IMAGING, 0 },
67 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
68 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
69 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
70 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
71 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
72 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
73 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
74 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
75 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
76 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
77 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
78 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
79 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
80 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
81 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
82 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
83 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
84 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
85 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
86 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
87 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
88 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
89 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
90 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
92 /* EXT */
93 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
94 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
95 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
96 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
97 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
98 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
99 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
100 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
101 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
102 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
103 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
104 {"GL_EXT_provoking_vertex", EXT_PROVOKING_VERTEX, 0 },
105 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
106 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
107 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
108 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
109 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
110 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
111 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
112 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
113 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
114 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
115 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
116 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
117 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
118 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
119 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
120 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
121 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
123 /* NV */
124 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
125 {"GL_NV_fence", NV_FENCE, 0 },
126 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
127 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
128 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
129 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
130 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
131 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
132 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
133 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
134 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
135 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
136 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
137 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
138 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
139 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
140 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
141 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
142 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
143 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
144 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
146 /* SGI */
147 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
150 /**********************************************************
151 * Utility functions follow
152 **********************************************************/
154 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
155 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
156 WINED3DDEVTYPE DeviceType);
157 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
158 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
160 /* lookup tables */
161 const int minLookup[MAX_LOOKUPS] =
163 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
166 const int maxLookup[MAX_LOOKUPS] =
168 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
171 DWORD *stateLookup[MAX_LOOKUPS];
173 const struct min_lookup minMipLookup[] =
175 /* NONE POINT LINEAR */
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
177 {{GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR}}, /* POINT*/
178 {{GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR}}, /* LINEAR */
181 const struct min_lookup minMipLookup_noFilter[] =
183 /* NONE POINT LINEAR */
184 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
185 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
186 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* LINEAR */
189 const struct min_lookup minMipLookup_noMip[] =
191 /* NONE POINT LINEAR */
192 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* NONE */
193 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}}, /* POINT */
194 {{GL_LINEAR, GL_LINEAR, GL_LINEAR }}, /* LINEAR */
197 const GLenum magLookup[] =
199 /* NONE POINT LINEAR */
200 GL_NEAREST, GL_NEAREST, GL_LINEAR,
203 const GLenum magLookup_noFilter[] =
205 /* NONE POINT LINEAR */
206 GL_NEAREST, GL_NEAREST, GL_NEAREST,
209 /* drawStridedSlow attributes */
210 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
211 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
212 glAttribFunc specular_func_3ubv;
213 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
214 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
215 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
218 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
219 * i.e., there is no GL Context - Get a default rendering context to enable the
220 * function query some info from GL.
223 struct wined3d_fake_gl_ctx
225 HDC dc;
226 HWND wnd;
227 HGLRC gl_ctx;
230 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
232 TRACE_(d3d_caps)("Destroying fake GL context.\n");
234 if (!pwglMakeCurrent(NULL, NULL))
236 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
239 if (!pwglDeleteContext(ctx->gl_ctx))
241 DWORD err = GetLastError();
242 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
245 ReleaseDC(ctx->wnd, ctx->dc);
246 DestroyWindow(ctx->wnd);
249 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
251 PIXELFORMATDESCRIPTOR pfd;
252 int iPixelFormat;
254 TRACE("getting context...\n");
256 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
257 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
258 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
259 if (!ctx->wnd)
261 ERR_(d3d_caps)("Failed to create a window.\n");
262 goto fail;
265 ctx->dc = GetDC(ctx->wnd);
266 if (!ctx->dc)
268 ERR_(d3d_caps)("Failed to get a DC.\n");
269 goto fail;
272 /* PixelFormat selection */
273 ZeroMemory(&pfd, sizeof(pfd));
274 pfd.nSize = sizeof(pfd);
275 pfd.nVersion = 1;
276 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
277 pfd.iPixelType = PFD_TYPE_RGBA;
278 pfd.cColorBits = 32;
279 pfd.iLayerType = PFD_MAIN_PLANE;
281 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
282 if (!iPixelFormat)
284 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
285 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
286 goto fail;
288 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
289 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
291 /* Create a GL context. */
292 ctx->gl_ctx = pwglCreateContext(ctx->dc);
293 if (!ctx->gl_ctx)
295 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
296 goto fail;
299 /* Make it the current GL context. */
300 if (!context_set_current(NULL))
302 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
305 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
307 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
308 goto fail;
311 return TRUE;
313 fail:
314 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
315 ctx->gl_ctx = NULL;
316 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
317 ctx->dc = NULL;
318 if (ctx->wnd) DestroyWindow(ctx->wnd);
319 ctx->wnd = NULL;
321 return FALSE;
324 /* Adjust the amount of used texture memory */
325 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
326 struct WineD3DAdapter *adapter = D3DDevice->adapter;
328 adapter->UsedTextureRam += glram;
329 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
330 return adapter->UsedTextureRam;
333 /**********************************************************
334 * IUnknown parts follows
335 **********************************************************/
337 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
341 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
342 if (IsEqualGUID(riid, &IID_IUnknown)
343 || IsEqualGUID(riid, &IID_IWineD3DBase)
344 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
345 IUnknown_AddRef(iface);
346 *ppobj = This;
347 return S_OK;
349 *ppobj = NULL;
350 return E_NOINTERFACE;
353 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
354 IWineD3DImpl *This = (IWineD3DImpl *)iface;
355 ULONG refCount = InterlockedIncrement(&This->ref);
357 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
358 return refCount;
361 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
362 IWineD3DImpl *This = (IWineD3DImpl *)iface;
363 ULONG ref;
364 TRACE("(%p) : Releasing from %d\n", This, This->ref);
365 ref = InterlockedDecrement(&This->ref);
366 if (ref == 0) {
367 unsigned int i;
369 for (i = 0; i < This->adapter_count; ++i)
371 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
373 HeapFree(GetProcessHeap(), 0, This);
376 return ref;
379 /* Set the shader type for this device, depending on the given capabilities,
380 * the device type, and the user preferences in wined3d_settings */
382 static void select_shader_mode(const struct wined3d_gl_info *gl_info,
383 WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
385 if (wined3d_settings.vs_mode == VS_NONE) {
386 *vs_selected = SHADER_NONE;
387 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
388 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
389 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
390 * shaders only on this card. */
391 if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2])
392 *vs_selected = SHADER_ARB;
393 else
394 *vs_selected = SHADER_GLSL;
395 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
396 *vs_selected = SHADER_ARB;
397 } else {
398 *vs_selected = SHADER_NONE;
401 if (wined3d_settings.ps_mode == PS_NONE) {
402 *ps_selected = SHADER_NONE;
403 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
404 *ps_selected = SHADER_GLSL;
405 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
406 *ps_selected = SHADER_ARB;
407 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
408 *ps_selected = SHADER_ATI;
409 } else {
410 *ps_selected = SHADER_NONE;
414 /** Select the number of report maximum shader constants based on the selected shader modes */
415 static void select_shader_max_constants(int ps_selected_mode, int vs_selected_mode, struct wined3d_gl_info *gl_info)
417 switch (vs_selected_mode) {
418 case SHADER_GLSL:
419 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
420 break;
421 case SHADER_ARB:
422 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
423 break;
424 default:
425 gl_info->max_vshader_constantsF = 0;
426 break;
429 switch (ps_selected_mode) {
430 case SHADER_GLSL:
431 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
432 break;
433 case SHADER_ARB:
434 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
435 break;
436 default:
437 gl_info->max_pshader_constantsF = 0;
438 break;
442 /**********************************************************
443 * IWineD3D parts follows
444 **********************************************************/
446 /* GL locking is done by the caller */
447 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
449 GLuint prog;
450 BOOL ret = FALSE;
451 const char *testcode =
452 "!!ARBvp1.0\n"
453 "PARAM C[66] = { program.env[0..65] };\n"
454 "ADDRESS A0;"
455 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
456 "ARL A0.x, zero.x;\n"
457 "MOV result.position, C[A0.x + 65];\n"
458 "END\n";
460 while(glGetError());
461 GL_EXTCALL(glGenProgramsARB(1, &prog));
462 if(!prog) {
463 ERR("Failed to create an ARB offset limit test program\n");
465 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
466 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
467 strlen(testcode), testcode));
468 if(glGetError() != 0) {
469 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
470 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
471 ret = TRUE;
472 } else TRACE("OpenGL implementation allows offsets > 63\n");
474 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
475 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
476 checkGLcall("ARB vp offset limit test cleanup");
478 return ret;
481 static DWORD ver_for_ext(GL_SupportedExt ext)
483 unsigned int i;
484 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
485 if(EXTENSION_MAP[i].extension == ext) {
486 return EXTENSION_MAP[i].version;
489 return 0;
492 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
494 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
495 if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
496 if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
497 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
498 return FALSE;
501 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
503 if (gl_info->gl_vendor == VENDOR_NVIDIA)
505 if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600)
507 return TRUE;
510 return FALSE;
513 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
515 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
516 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
517 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
519 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
520 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
521 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
522 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
523 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
524 * the chance that other implementations support them is rather small since Win32 QuickTime uses
525 * DirectDraw, not OpenGL. */
526 if (gl_info->supported[APPLE_FENCE]
527 && gl_info->supported[APPLE_CLIENT_STORAGE]
528 && gl_info->supported[APPLE_FLUSH_RENDER]
529 && gl_info->supported[APPLE_YCBCR_422])
531 return TRUE;
533 else
535 return FALSE;
539 /* Context activation is done by the caller. */
540 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
542 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
543 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
544 * all the texture. This function detects this bug by its symptom and disables PBOs
545 * if the test fails.
547 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
548 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
549 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
550 * read back is compared to the original. If they are equal PBOs are assumed to work,
551 * otherwise the PBO extension is disabled. */
552 GLuint texture, pbo;
553 static const unsigned int pattern[] =
555 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
556 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
557 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
558 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
560 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
562 /* No PBO -> No point in testing them. */
563 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
565 ENTER_GL();
567 while (glGetError());
568 glGenTextures(1, &texture);
569 glBindTexture(GL_TEXTURE_2D, texture);
571 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
572 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
573 checkGLcall("Specifying the PBO test texture");
575 GL_EXTCALL(glGenBuffersARB(1, &pbo));
576 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
577 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
578 checkGLcall("Specifying the PBO test pbo");
580 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
581 checkGLcall("Loading the PBO test texture");
583 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
584 wglFinish(); /* just to be sure */
586 memset(check, 0, sizeof(check));
587 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
588 checkGLcall("Reading back the PBO test texture");
590 glDeleteTextures(1, &texture);
591 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
592 checkGLcall("PBO test cleanup");
594 LEAVE_GL();
596 if (memcmp(check, pattern, sizeof(check)))
598 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
599 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
600 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
602 else
604 TRACE_(d3d_caps)("PBO test successful.\n");
608 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
610 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer);
613 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
615 if (!match_apple(gl_info, gl_renderer)) return FALSE;
616 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
617 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
618 return TRUE;
621 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
623 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
624 if (match_apple(gl_info, gl_renderer)) return FALSE;
625 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
626 return TRUE;
629 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
631 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
632 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
633 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
634 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
635 * hardcoded
637 * dx10 cards usually have 64 varyings */
638 return gl_info->max_glsl_varyings > 44;
641 /* A GL context is provided by the caller */
642 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
644 GLenum error;
645 DWORD data[16];
647 if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE;
649 ENTER_GL();
650 while(glGetError());
651 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
652 error = glGetError();
653 LEAVE_GL();
655 if(error == GL_NO_ERROR)
657 TRACE("GL Implementation accepts 4 component specular color pointers\n");
658 return TRUE;
660 else
662 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
663 debug_glerror(error));
664 return FALSE;
668 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
670 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF);
671 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
672 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF);
673 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
676 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
678 quirk_arb_constants(gl_info);
679 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
680 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
681 * allow 48 different offsets or other helper immediate values. */
682 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
683 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
686 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
687 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
688 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
689 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
690 * most games, but avoids the crash
692 * A more sophisticated way would be to find all units that need texture coordinates and enable
693 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
694 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
696 * Note that disabling the extension entirely does not gain predictability because there is no point
697 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
698 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
700 if (gl_info->supported[ARB_POINT_SPRITE])
702 TRACE("Limiting point sprites to one texture unit.\n");
703 gl_info->max_point_sprite_units = 1;
707 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
709 quirk_arb_constants(gl_info);
711 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
712 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
713 * If real NP2 textures are used, the driver falls back to software. We could just remove the
714 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
715 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
716 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
717 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
719 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
720 * has this extension promoted to core. The extension loading code sets this extension supported
721 * due to that, so this code works on fglrx as well. */
722 if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
724 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
725 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
726 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
729 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
730 * it is generally more efficient. Reserve just 8 constants. */
731 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
732 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
735 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
737 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
738 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
739 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
740 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
741 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
742 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
744 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
745 * triggering the software fallback. There is not much we can do here apart from disabling the
746 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
747 * in IWineD3DImpl_FillGLCaps).
748 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
749 * post-processing effects in the game "Max Payne 2").
750 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
751 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
752 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
753 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
756 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
758 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
759 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
760 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
761 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
762 * according to the spec.
764 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
765 * makes the shader slower and eats instruction slots which should be available to the d3d app.
767 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
768 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
769 * this workaround is activated on cards that do not need it, it won't break things, just affect
770 * performance negatively. */
771 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
772 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
775 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
777 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
780 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
782 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
785 struct driver_quirk
787 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
788 void (*apply)(struct wined3d_gl_info *gl_info);
789 const char *description;
792 struct driver_quirk quirk_table[] =
795 match_ati_r300_to_500,
796 quirk_ati_dx9,
797 "ATI GLSL constant and normalized texrect quirk"
799 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
800 * used it falls back to software. While the compiler can detect if the shader uses all declared
801 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
802 * using relative addressing falls back to software.
804 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
806 match_apple,
807 quirk_apple_glsl_constants,
808 "Apple GLSL uniform override"
811 match_geforce5,
812 quirk_no_np2,
813 "Geforce 5 NP2 disable"
816 match_apple_intel,
817 quirk_texcoord_w,
818 "Init texcoord .w for Apple Intel GPU driver"
821 match_apple_nonr500ati,
822 quirk_texcoord_w,
823 "Init texcoord .w for Apple ATI >= r600 GPU driver"
826 match_fglrx,
827 quirk_one_point_sprite,
828 "Fglrx point sprite crash workaround"
831 match_dx10_capable,
832 quirk_clip_varying,
833 "Reserved varying for gl_ClipPos"
836 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
837 * GL implementations accept it. The Mac GL is the only implementation known to
838 * reject it.
840 * If we can pass 4 component specular colors, do it, because (a) we don't have
841 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
842 * passes specular alpha to the pixel shader if any is used. Otherwise the
843 * specular alpha is used to pass the fog coordinate, which we pass to opengl
844 * via GL_EXT_fog_coord.
846 match_allows_spec_alpha,
847 quirk_allows_specular_alpha,
848 "Allow specular alpha quirk"
852 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
853 * reporting a driver version is moot because we are not the Windows driver, and we have different
854 * bugs, features, etc.
856 * If a card is not found in this table, the GL driver version is reported. */
857 struct driver_version_information
859 WORD vendor; /* reported PCI card vendor ID */
860 WORD card; /* reported PCI card device ID */
861 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
862 WORD hipart_hi, hipart_lo; /* driver hiword to report */
863 WORD lopart_hi, lopart_lo; /* driver loword to report */
866 static const struct driver_version_information driver_version_table[] =
868 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
869 * 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
870 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
871 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
873 * All version numbers used below are from the Linux nvidia drivers. */
874 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
875 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
876 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
877 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
878 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
879 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 },
880 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 },
881 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 },
882 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 },
883 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 },
884 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 },
885 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 },
886 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 },
887 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 },
888 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 },
889 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 },
890 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 },
891 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 },
892 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 },
893 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 },
894 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 },
895 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 },
896 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 },
897 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 },
898 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 },
899 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 },
900 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 },
901 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 },
902 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 },
903 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 },
905 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
906 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
907 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
908 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
909 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
910 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
911 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
912 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
913 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
914 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
915 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
917 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
920 /* Context activation is done by the caller. */
921 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer)
923 unsigned int i;
925 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
927 if (!quirk_table[i].match(gl_info, gl_renderer)) continue;
928 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
929 quirk_table[i].apply(gl_info);
932 /* Find out if PBOs work as they are supposed to. */
933 test_pbo_functionality(gl_info);
935 /* Fixup the driver version we'll report to the app. */
936 gl_info->driver_version = MAKEDWORD_VERSION(8, 6); /* Nvidia RIVA TNT, arbitrary */
937 gl_info->driver_version_hipart = MAKEDWORD_VERSION(7, 1);
938 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
940 if (gl_info->gl_vendor == driver_version_table[i].vendor
941 && gl_info->gl_card == driver_version_table[i].card)
943 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB.\n",
944 gl_info->gl_vendor, gl_info->gl_card);
946 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
947 driver_version_table[i].lopart_lo);
948 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
949 driver_version_table[i].hipart_lo);
950 gl_info->driver_description = driver_version_table[i].description;
951 break;
954 TRACE_(d3d_caps)("Reporting (fake) driver version 0x%08X-0x%08X.\n",
955 gl_info->driver_version_hipart, gl_info->driver_version);
958 static DWORD wined3d_parse_gl_version(const char *gl_version)
960 const char *ptr = gl_version;
961 int major, minor;
963 major = atoi(ptr);
964 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
966 while (isdigit(*ptr)) ++ptr;
967 if (*ptr++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_version));
969 minor = atoi(ptr);
971 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
973 return MAKEDWORD_VERSION(major, minor);
976 static GL_Vendors wined3d_guess_vendor(const char *gl_vendor, const char *gl_renderer)
978 if (strstr(gl_vendor, "NVIDIA"))
979 return VENDOR_NVIDIA;
981 if (strstr(gl_vendor, "ATI"))
982 return VENDOR_ATI;
984 if (strstr(gl_vendor, "Intel(R)")
985 || strstr(gl_renderer, "Intel(R)")
986 || strstr(gl_vendor, "Intel Inc."))
987 return VENDOR_INTEL;
989 if (strstr(gl_vendor, "Mesa")
990 || strstr(gl_vendor, "Tungsten Graphics, Inc."))
991 return VENDOR_MESA;
993 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Returning VENDOR_WINE.\n", debugstr_a(gl_vendor));
995 return VENDOR_WINE;
998 static GL_Cards wined3d_guess_card(const struct wined3d_gl_info *gl_info, const char *gl_renderer,
999 GL_Vendors *vendor, unsigned int *vidmem)
1001 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of
1002 * different GPUs with roughly the same features. In most cases GPUs from a
1003 * certain family differ in clockspeeds, the amount of video memory and the
1004 * number of shader pipelines.
1006 * A Direct3D device object contains the PCI id (vendor + device) of the
1007 * videocard which is used for rendering. Various applications use this
1008 * information to get a rough estimation of the features of the card and
1009 * some might use it for enabling 3d effects only on certain types of
1010 * videocards. In some cases games might even use it to work around bugs
1011 * which happen on certain videocards/driver combinations. The problem is
1012 * that OpenGL only exposes a rendering string containing the name of the
1013 * videocard and not the PCI id.
1015 * Various games depend on the PCI id, so somehow we need to provide one.
1016 * A simple option is to parse the renderer string and translate this to
1017 * the right PCI id. This is a lot of work because there are more than 200
1018 * GPUs just for Nvidia. Various cards share the same renderer string, so
1019 * the amount of code might be 'small' but there are quite a number of
1020 * exceptions which would make this a pain to maintain. Another way would
1021 * be to query the PCI id from the operating system (assuming this is the
1022 * videocard which is used for rendering which is not always the case).
1023 * This would work but it is not very portable. Second it would not work
1024 * well in, let's say, a remote X situation in which the amount of 3d
1025 * features which can be used is limited.
1027 * As said most games only use the PCI id to get an indication of the
1028 * capabilities of the card. It doesn't really matter if the given id is
1029 * the correct one if we return the id of a card with similar 3d features.
1031 * The code below checks the OpenGL capabilities of a videocard and matches
1032 * that to a certain level of Direct3D functionality. Once a card passes
1033 * the Direct3D9 check, we know that the card (in case of Nvidia) is at
1034 * least a GeforceFX. To give a better estimate we do a basic check on the
1035 * renderer string but if that won't pass we return a default card. This
1036 * way is better than maintaining a full card database as even without a
1037 * full database we can return a card with similar features. Second the
1038 * size of the database can be made quite small because when you know what
1039 * type of 3d functionality a card has, you know to which GPU family the
1040 * GPU must belong. Because of this you only have to check a small part of
1041 * the renderer string to distinguishes between different models from that
1042 * family.
1044 * The code also selects a default amount of video memory which we will
1045 * use for an estimation of the amount of free texture memory. In case of
1046 * real D3D the amount of texture memory includes video memory and system
1047 * memory (to be specific AGP memory or in case of PCIE TurboCache /
1048 * HyperMemory). We don't know how much system memory can be addressed by
1049 * the system but we can make a reasonable estimation about the amount of
1050 * video memory. If the value is slightly wrong it doesn't matter as we
1051 * didn't include AGP-like memory which makes the amount of addressable
1052 * memory higher and second OpenGL isn't that critical it moves to system
1053 * memory behind our backs if really needed. Note that the amount of video
1054 * memory can be overruled using a registry setting. */
1056 switch (*vendor)
1058 case VENDOR_NVIDIA:
1059 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1060 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1062 if (WINE_D3D9_CAPABLE(gl_info) && gl_info->supported[NV_VERTEX_PROGRAM3])
1064 /* Geforce 200 - highend */
1065 if (strstr(gl_renderer, "GTX 280")
1066 || strstr(gl_renderer, "GTX 285")
1067 || strstr(gl_renderer, "GTX 295"))
1069 *vidmem = 1024;
1070 return CARD_NVIDIA_GEFORCE_GTX280;
1073 /* Geforce 200 - midend high */
1074 if (strstr(gl_renderer, "GTX 275"))
1076 *vidmem = 896;
1077 return CARD_NVIDIA_GEFORCE_GTX275;
1080 /* Geforce 200 - midend */
1081 if (strstr(gl_renderer, "GTX 260"))
1083 *vidmem = 1024;
1084 return CARD_NVIDIA_GEFORCE_GTX260;
1087 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1088 if (strstr(gl_renderer, "9800")
1089 || strstr(gl_renderer, "GTS 150")
1090 || strstr(gl_renderer, "GTS 250"))
1092 *vidmem = 512;
1093 return CARD_NVIDIA_GEFORCE_9800GT;
1096 /* Geforce9 - midend */
1097 if (strstr(gl_renderer, "9600"))
1099 *vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1100 return CARD_NVIDIA_GEFORCE_9600GT;
1103 /* Geforce9 - midend low / Geforce 200 - low */
1104 if (strstr(gl_renderer, "9500")
1105 || strstr(gl_renderer, "GT 120")
1106 || strstr(gl_renderer, "GT 130"))
1108 *vidmem = 256; /* The 9500GT has 256-1024MB */
1109 return CARD_NVIDIA_GEFORCE_9500GT;
1112 /* Geforce9 - lowend */
1113 if (strstr(gl_renderer, "9400"))
1115 *vidmem = 256; /* The 9400GT has 256-1024MB */
1116 return CARD_NVIDIA_GEFORCE_9400GT;
1119 /* Geforce9 - lowend low */
1120 if (strstr(gl_renderer, "9100")
1121 || strstr(gl_renderer, "9200")
1122 || strstr(gl_renderer, "9300")
1123 || strstr(gl_renderer, "G 100"))
1125 *vidmem = 256; /* The 9100-9300 cards have 256MB */
1126 return CARD_NVIDIA_GEFORCE_9200;
1129 /* Geforce8 - highend */
1130 if (strstr(gl_renderer, "8800"))
1132 *vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1133 return CARD_NVIDIA_GEFORCE_8800GTS;
1136 /* Geforce8 - midend mobile */
1137 if (strstr(gl_renderer, "8600 M"))
1139 *vidmem = 512;
1140 return CARD_NVIDIA_GEFORCE_8600MGT;
1143 /* Geforce8 - midend */
1144 if (strstr(gl_renderer, "8600")
1145 || strstr(gl_renderer, "8700"))
1147 *vidmem = 256;
1148 return CARD_NVIDIA_GEFORCE_8600GT;
1151 /* Geforce8 - lowend */
1152 if (strstr(gl_renderer, "8300")
1153 || strstr(gl_renderer, "8400")
1154 || strstr(gl_renderer, "8500"))
1156 *vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1157 return CARD_NVIDIA_GEFORCE_8300GS;
1160 /* Geforce7 - highend */
1161 if (strstr(gl_renderer, "7800")
1162 || strstr(gl_renderer, "7900")
1163 || strstr(gl_renderer, "7950")
1164 || strstr(gl_renderer, "Quadro FX 4")
1165 || strstr(gl_renderer, "Quadro FX 5"))
1167 *vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1168 return CARD_NVIDIA_GEFORCE_7800GT;
1171 /* Geforce7 midend */
1172 if (strstr(gl_renderer, "7600")
1173 || strstr(gl_renderer, "7700"))
1175 *vidmem = 256; /* The 7600 uses 256-512MB */
1176 return CARD_NVIDIA_GEFORCE_7600;
1179 /* Geforce7 lower medium */
1180 if (strstr(gl_renderer, "7400"))
1182 *vidmem = 256; /* The 7400 uses 256-512MB */
1183 return CARD_NVIDIA_GEFORCE_7400;
1186 /* Geforce7 lowend */
1187 if (strstr(gl_renderer, "7300"))
1189 *vidmem = 256; /* Mac Pros with this card have 256 MB */
1190 return CARD_NVIDIA_GEFORCE_7300;
1193 /* Geforce6 highend */
1194 if (strstr(gl_renderer, "6800"))
1196 *vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1197 return CARD_NVIDIA_GEFORCE_6800;
1200 /* Geforce6 - midend */
1201 if (strstr(gl_renderer, "6600")
1202 || strstr(gl_renderer, "6610")
1203 || strstr(gl_renderer, "6700"))
1205 *vidmem = 128; /* A 6600GT has 128-256MB */
1206 return CARD_NVIDIA_GEFORCE_6600GT;
1209 /* Geforce6/7 lowend */
1210 *vidmem = 64; /* */
1211 return CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1214 if (WINE_D3D9_CAPABLE(gl_info))
1216 /* GeforceFX - highend */
1217 if (strstr(gl_renderer, "5800")
1218 || strstr(gl_renderer, "5900")
1219 || strstr(gl_renderer, "5950")
1220 || strstr(gl_renderer, "Quadro FX"))
1222 *vidmem = 256; /* 5800-5900 cards use 256MB */
1223 return CARD_NVIDIA_GEFORCEFX_5800;
1226 /* GeforceFX - midend */
1227 if (strstr(gl_renderer, "5600")
1228 || strstr(gl_renderer, "5650")
1229 || strstr(gl_renderer, "5700")
1230 || strstr(gl_renderer, "5750"))
1232 *vidmem = 128; /* A 5600 uses 128-256MB */
1233 return CARD_NVIDIA_GEFORCEFX_5600;
1236 /* GeforceFX - lowend */
1237 *vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1238 return CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1241 if (WINE_D3D8_CAPABLE(gl_info))
1243 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1245 *vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1246 return CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1249 *vidmem = 64; /* Geforce3 cards have 64-128MB */
1250 return CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1253 if (WINE_D3D7_CAPABLE(gl_info))
1255 if (strstr(gl_renderer, "GeForce4 MX"))
1257 /* Most Geforce4MX GPUs have at least 64MB of memory, some
1258 * early models had 32MB but most have 64MB or even 128MB. */
1259 *vidmem = 64;
1260 return CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1263 if (strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1265 *vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1266 return CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1269 if (strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1271 *vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1272 return CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1275 /* Most Geforce1 cards have 32MB, there are also some rare 16
1276 * and 64MB (Dell) models. */
1277 *vidmem = 32;
1278 return CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1281 if (strstr(gl_renderer, "TNT2"))
1283 *vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1284 return CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1287 *vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1288 return CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1290 case VENDOR_ATI:
1291 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1293 * Beware: renderer string do not match exact card model,
1294 * eg HD 4800 is returned for multiple cards, even for RV790 based ones. */
1295 if (WINE_D3D9_CAPABLE(gl_info))
1297 /* Radeon R7xx HD4800 - highend */
1298 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1299 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1300 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1301 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1302 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1304 *vidmem = 512; /* note: HD4890 cards use 1024MB */
1305 return CARD_ATI_RADEON_HD4800;
1308 /* Radeon R740 HD4700 - midend */
1309 if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1310 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1312 *vidmem = 512;
1313 return CARD_ATI_RADEON_HD4700;
1316 /* Radeon R730 HD4600 - midend */
1317 if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1318 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1319 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1321 *vidmem = 512;
1322 return CARD_ATI_RADEON_HD4600;
1325 /* Radeon R710 HD4500/HD4350 - lowend */
1326 if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1327 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1329 *vidmem = 256;
1330 return CARD_ATI_RADEON_HD4350;
1333 /* Radeon R6xx HD2900/HD3800 - highend */
1334 if (strstr(gl_renderer, "HD 2900")
1335 || strstr(gl_renderer, "HD 3870")
1336 || strstr(gl_renderer, "HD 3850"))
1338 *vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1339 return CARD_ATI_RADEON_HD2900;
1342 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1343 if (strstr(gl_renderer, "HD 2600")
1344 || strstr(gl_renderer, "HD 3830")
1345 || strstr(gl_renderer, "HD 3690")
1346 || strstr(gl_renderer, "HD 3650"))
1348 *vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1349 return CARD_ATI_RADEON_HD2600;
1352 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1353 if (strstr(gl_renderer, "HD 2300")
1354 || strstr(gl_renderer, "HD 2400")
1355 || strstr(gl_renderer, "HD 3470")
1356 || strstr(gl_renderer, "HD 3450")
1357 || strstr(gl_renderer, "HD 3430")
1358 || strstr(gl_renderer, "HD 3400"))
1360 *vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1361 return CARD_ATI_RADEON_HD2300;
1364 /* Radeon R6xx/R7xx integrated */
1365 if (strstr(gl_renderer, "HD 3100")
1366 || strstr(gl_renderer, "HD 3200")
1367 || strstr(gl_renderer, "HD 3300"))
1369 *vidmem = 128; /* 128MB */
1370 return CARD_ATI_RADEON_HD3200;
1373 /* Radeon R5xx */
1374 if (strstr(gl_renderer, "X1600")
1375 || strstr(gl_renderer, "X1650")
1376 || strstr(gl_renderer, "X1800")
1377 || strstr(gl_renderer, "X1900")
1378 || strstr(gl_renderer, "X1950"))
1380 *vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1381 return CARD_ATI_RADEON_X1600;
1384 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1385 if (strstr(gl_renderer, "X700")
1386 || strstr(gl_renderer, "X800")
1387 || strstr(gl_renderer, "X850")
1388 || strstr(gl_renderer, "X1300")
1389 || strstr(gl_renderer, "X1400")
1390 || strstr(gl_renderer, "X1450")
1391 || strstr(gl_renderer, "X1550"))
1393 *vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1394 return CARD_ATI_RADEON_X700;
1397 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1398 if (strstr(gl_renderer, "Radeon Xpress"))
1400 *vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1401 return CARD_ATI_RADEON_XPRESS_200M;
1404 /* Radeon R3xx */
1405 *vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1406 return CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1409 if (WINE_D3D8_CAPABLE(gl_info))
1411 *vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1412 return CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1415 if (WINE_D3D7_CAPABLE(gl_info))
1417 *vidmem = 32; /* There are models with up to 64MB */
1418 return CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1421 *vidmem = 16; /* There are 16-32MB models */
1422 return CARD_ATI_RAGE_128PRO;
1424 case VENDOR_INTEL:
1425 if (strstr(gl_renderer, "X3100"))
1427 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1428 *vidmem = 128;
1429 return CARD_INTEL_X3100;
1432 if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1434 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1435 *vidmem = 64;
1436 return CARD_INTEL_I945GM;
1439 if (strstr(gl_renderer, "915GM")) return CARD_INTEL_I915GM;
1440 if (strstr(gl_renderer, "915G")) return CARD_INTEL_I915G;
1441 if (strstr(gl_renderer, "865G")) return CARD_INTEL_I865G;
1442 if (strstr(gl_renderer, "855G")) return CARD_INTEL_I855G;
1443 if (strstr(gl_renderer, "830G")) return CARD_INTEL_I830G;
1444 return CARD_INTEL_I915G;
1446 case VENDOR_MESA:
1447 case VENDOR_WINE:
1448 default:
1449 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1450 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1451 * them a good generic choice. */
1452 *vendor = VENDOR_NVIDIA;
1453 if (WINE_D3D9_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCEFX_5600;
1454 if (WINE_D3D8_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE3;
1455 if (WINE_D3D7_CAPABLE(gl_info)) return CARD_NVIDIA_GEFORCE;
1456 if (WINE_D3D6_CAPABLE(gl_info)) return CARD_NVIDIA_RIVA_TNT;
1457 return CARD_NVIDIA_RIVA_128;
1461 /* Context activation is done by the caller. */
1462 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_gl_info *gl_info)
1464 const char *GL_Extensions = NULL;
1465 const char *WGL_Extensions = NULL;
1466 const char *gl_string = NULL;
1467 GLint gl_max;
1468 GLfloat gl_floatv[2];
1469 unsigned i;
1470 HDC hdc;
1471 unsigned int vidmem=0;
1472 char *gl_renderer;
1473 DWORD gl_version;
1474 size_t len;
1476 TRACE_(d3d_caps)("(%p)\n", gl_info);
1478 ENTER_GL();
1480 gl_string = (const char *)glGetString(GL_RENDERER);
1481 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", debugstr_a(gl_string));
1482 if (!gl_string)
1484 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
1485 return FALSE;
1488 len = strlen(gl_string) + 1;
1489 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
1490 if (!gl_renderer)
1492 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
1493 return FALSE;
1495 memcpy(gl_renderer, gl_string, len);
1497 gl_string = (const char *)glGetString(GL_VENDOR);
1498 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", debugstr_a(gl_string));
1499 if (!gl_string)
1501 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
1502 HeapFree(GetProcessHeap(), 0, gl_renderer);
1503 return FALSE;
1505 gl_info->gl_vendor = wined3d_guess_vendor(gl_string, gl_renderer);
1506 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
1508 /* Parse the GL_VERSION field into major and minor information */
1509 gl_string = (const char *)glGetString(GL_VERSION);
1510 TRACE_(d3d_caps)("GL_VERSION: %s.\n", debugstr_a(gl_string));
1511 if (!gl_string)
1513 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1514 HeapFree(GetProcessHeap(), 0, gl_renderer);
1515 return FALSE;
1517 gl_version = wined3d_parse_gl_version(gl_string);
1520 * Initialize openGL extension related variables
1521 * with Default values
1523 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1524 gl_info->max_buffers = 1;
1525 gl_info->max_textures = 1;
1526 gl_info->max_texture_stages = 1;
1527 gl_info->max_fragment_samplers = 1;
1528 gl_info->max_vertex_samplers = 0;
1529 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
1530 gl_info->max_sampler_stages = 1;
1531 gl_info->ps_arb_max_temps = 0;
1532 gl_info->ps_arb_max_instructions = 0;
1533 gl_info->vs_arb_max_temps = 0;
1534 gl_info->vs_arb_max_instructions = 0;
1535 gl_info->vs_glsl_constantsF = 0;
1536 gl_info->ps_glsl_constantsF = 0;
1537 gl_info->vs_arb_constantsF = 0;
1538 gl_info->ps_arb_constantsF = 0;
1539 gl_info->ps_arb_max_local_constants = 0;
1541 /* Retrieve opengl defaults */
1542 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1543 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1544 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1546 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1547 gl_info->max_lights = gl_max;
1548 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1550 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1551 gl_info->max_texture_size = gl_max;
1552 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1554 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1555 gl_info->max_pointsizemin = gl_floatv[0];
1556 gl_info->max_pointsize = gl_floatv[1];
1557 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1559 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1560 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1561 if (!GL_Extensions)
1563 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1564 HeapFree(GetProcessHeap(), 0, gl_renderer);
1565 return FALSE;
1568 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1570 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1572 while (*GL_Extensions)
1574 const char *start;
1575 char current_ext[256];
1577 while (isspace(*GL_Extensions)) ++GL_Extensions;
1578 start = GL_Extensions;
1579 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1581 len = GL_Extensions - start;
1582 if (!len || len >= sizeof(current_ext)) continue;
1584 memcpy(current_ext, start, len);
1585 current_ext[len] = '\0';
1586 TRACE_(d3d_caps)("- %s\n", debugstr_a(current_ext));
1588 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1590 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1592 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1593 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1594 break;
1599 LEAVE_GL();
1601 /* Now work out what GL support this card really has */
1602 #define USE_GL_FUNC(type, pfn, ext, replace) \
1604 DWORD ver = ver_for_ext(ext); \
1605 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1606 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1607 else gl_info->pfn = NULL; \
1609 GL_EXT_FUNCS_GEN;
1610 #undef USE_GL_FUNC
1612 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1613 WGL_EXT_FUNCS_GEN;
1614 #undef USE_GL_FUNC
1616 ENTER_GL();
1618 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1619 * loading the functions, otherwise the code above will load the extension entry points instead of the
1620 * core functions, which may not work. */
1621 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1623 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1624 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1626 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1627 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1631 if (gl_info->supported[APPLE_FENCE])
1633 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1634 * The apple extension interacts with some other apple exts. Disable the NV
1635 * extension if the apple one is support to prevent confusion in other parts
1636 * of the code. */
1637 gl_info->supported[NV_FENCE] = FALSE;
1639 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1641 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1643 * The enums are the same:
1644 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1645 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1646 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1647 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1648 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1650 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1652 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1653 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1655 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1657 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1658 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1661 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1663 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1664 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1666 if (!gl_info->supported[ARB_DEPTH_CLAMP] && gl_info->supported[NV_DEPTH_CLAMP])
1668 TRACE_(d3d_caps)(" IMPLIED: ARB_depth_clamp support (by NV_depth_clamp).\n");
1669 gl_info->supported[ARB_DEPTH_CLAMP] = TRUE;
1671 if (gl_info->supported[NV_TEXTURE_SHADER2])
1673 if (gl_info->supported[NV_REGISTER_COMBINERS])
1675 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1676 * are supported. The nv extensions provide the same functionality as the
1677 * ATI one, and a bit more(signed pixelformats). */
1678 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1681 if (gl_info->supported[ARB_DRAW_BUFFERS])
1683 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1684 gl_info->max_buffers = gl_max;
1685 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1687 if (gl_info->supported[ARB_MULTITEXTURE])
1689 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1690 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
1691 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures);
1693 if (gl_info->supported[NV_REGISTER_COMBINERS])
1695 GLint tmp;
1696 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1697 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
1699 else
1701 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
1703 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages);
1705 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1707 GLint tmp;
1708 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1709 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1711 else
1713 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
1715 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers);
1717 if (gl_info->supported[ARB_VERTEX_SHADER])
1719 GLint tmp;
1720 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1721 gl_info->max_vertex_samplers = tmp;
1722 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1723 gl_info->max_combined_samplers = tmp;
1725 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1726 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1727 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1728 * shader is used with fixed function vertex processing we're fine too because fixed function
1729 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1730 * used we have to make sure that all vertex sampler setups are valid together with all
1731 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1732 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1733 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1734 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1735 * a fixed function pipeline anymore.
1737 * So this is just a check to check that our assumption holds true. If not, write a warning
1738 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1739 if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12
1740 && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers)
1742 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1743 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
1744 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1745 if (gl_info->max_combined_samplers > MAX_TEXTURES)
1746 gl_info->max_vertex_samplers = gl_info->max_combined_samplers - MAX_TEXTURES;
1747 else
1748 gl_info->max_vertex_samplers = 0;
1751 else
1753 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
1755 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers);
1756 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers);
1758 if (gl_info->supported[ARB_VERTEX_BLEND])
1760 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1761 gl_info->max_blends = gl_max;
1762 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends);
1764 if (gl_info->supported[EXT_TEXTURE3D])
1766 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1767 gl_info->max_texture3d_size = gl_max;
1768 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size);
1770 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1772 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1773 gl_info->max_anisotropy = gl_max;
1774 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy);
1776 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1778 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1779 gl_info->ps_arb_constantsF = gl_max;
1780 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF);
1781 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1782 gl_info->ps_arb_max_temps = gl_max;
1783 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps);
1784 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1785 gl_info->ps_arb_max_instructions = gl_max;
1786 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions);
1787 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, &gl_max));
1788 gl_info->ps_arb_max_local_constants = gl_max;
1789 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM local parameters: %d.\n", gl_info->ps_arb_max_instructions);
1791 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1793 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1794 gl_info->vs_arb_constantsF = gl_max;
1795 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF);
1796 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1797 gl_info->vs_arb_max_temps = gl_max;
1798 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps);
1799 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1800 gl_info->vs_arb_max_instructions = gl_max;
1801 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions);
1803 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1805 if (gl_info->supported[ARB_VERTEX_SHADER])
1807 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1808 gl_info->vs_glsl_constantsF = gl_max / 4;
1809 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF);
1811 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1813 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1814 gl_info->ps_glsl_constantsF = gl_max / 4;
1815 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF);
1816 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1817 gl_info->max_glsl_varyings = gl_max;
1818 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
1820 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
1822 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
1824 else
1826 gl_info->max_shininess = 128.0f;
1828 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1830 /* If we have full NP2 texture support, disable
1831 * GL_ARB_texture_rectangle because we will never use it.
1832 * This saves a few redundant glDisable calls. */
1833 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1835 if (gl_info->supported[ATI_FRAGMENT_SHADER])
1837 /* Disable NV_register_combiners and fragment shader if this is supported.
1838 * generally the NV extensions are preferred over the ATI ones, and this
1839 * extension is disabled if register_combiners and texture_shader2 are both
1840 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1841 * fragment processing support. */
1842 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1843 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1844 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1845 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1846 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1848 if (gl_info->supported[NV_HALF_FLOAT])
1850 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
1851 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1853 if (gl_info->supported[ARB_POINT_SPRITE])
1855 gl_info->max_point_sprite_units = gl_info->max_textures;
1857 else
1859 gl_info->max_point_sprite_units = 0;
1861 checkGLcall("extension detection");
1863 LEAVE_GL();
1865 /* In some cases the number of texture stages can be larger than the number
1866 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1867 * shaders), but 8 texture stages (register combiners). */
1868 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1870 /* We can only use ORM_FBO when the hardware supports it. */
1871 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1872 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
1873 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1876 /* MRTs are currently only supported when FBOs are used. */
1877 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1878 gl_info->max_buffers = 1;
1881 gl_info->gl_card = wined3d_guess_card(gl_info, gl_renderer, &gl_info->gl_vendor, &vidmem);
1882 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1884 /* If we have an estimate use it, else default to 64MB; */
1885 if(vidmem)
1886 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1887 else
1888 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1890 /* Load all the lookup tables */
1891 for (i = 0; i < MAX_LOOKUPS; i++) {
1892 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1895 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1896 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1897 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1898 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1899 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1900 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1901 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1902 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1903 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1904 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1906 /* Make sure there's an active HDC else the WGL extensions will fail */
1907 hdc = pwglGetCurrentDC();
1908 if (hdc) {
1909 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
1910 if(GL_EXTCALL(wglGetExtensionsStringARB))
1911 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
1913 if (NULL == WGL_Extensions) {
1914 ERR(" WGL_Extensions returns NULL\n");
1915 } else {
1916 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
1917 while (*WGL_Extensions != 0x00) {
1918 const char *Start;
1919 char ThisExtn[256];
1921 while (isspace(*WGL_Extensions)) WGL_Extensions++;
1922 Start = WGL_Extensions;
1923 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
1924 WGL_Extensions++;
1927 len = WGL_Extensions - Start;
1928 if (len == 0 || len >= sizeof(ThisExtn))
1929 continue;
1931 memcpy(ThisExtn, Start, len);
1932 ThisExtn[len] = '\0';
1933 TRACE_(d3d_caps)("- %s\n", debugstr_a(ThisExtn));
1935 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
1936 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
1937 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
1939 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
1940 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
1941 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
1943 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
1944 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
1945 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
1951 fixup_extensions(gl_info, gl_renderer);
1952 add_gl_compat_wrappers(gl_info);
1954 HeapFree(GetProcessHeap(), 0, gl_renderer);
1955 return TRUE;
1958 /**********************************************************
1959 * IWineD3D implementation follows
1960 **********************************************************/
1962 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1963 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1965 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
1967 return This->adapter_count;
1970 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1971 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1972 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1973 return WINED3D_OK;
1976 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1977 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1979 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
1981 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1982 return NULL;
1985 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
1988 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1989 of the same bpp but different resolutions */
1991 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1992 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1993 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1994 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1996 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1997 return 0;
2000 /* TODO: Store modes per adapter and read it from the adapter structure */
2001 if (Adapter == 0) { /* Display */
2002 unsigned int i = 0;
2003 unsigned int j = 0;
2004 DEVMODEW mode;
2006 memset(&mode, 0, sizeof(mode));
2007 mode.dmSize = sizeof(mode);
2009 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2011 ++j;
2012 switch (Format)
2014 case WINED3DFMT_UNKNOWN:
2015 /* This is for D3D8, do not enumerate P8 here */
2016 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2017 break;
2019 case WINED3DFMT_X8R8G8B8:
2020 if (mode.dmBitsPerPel == 32) ++i;
2021 break;
2023 case WINED3DFMT_R5G6B5:
2024 if (mode.dmBitsPerPel == 16) ++i;
2025 break;
2027 case WINED3DFMT_P8:
2028 if (mode.dmBitsPerPel == 8) ++i;
2029 break;
2031 default:
2032 /* Skip other modes as they do not match the requested format */
2033 break;
2037 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2038 return i;
2039 } else {
2040 FIXME_(d3d_caps)("Adapter not primary display\n");
2042 return 0;
2045 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2046 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2047 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2048 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2050 /* Validate the parameters as much as possible */
2051 if (NULL == pMode ||
2052 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2053 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2054 return WINED3DERR_INVALIDCALL;
2057 /* TODO: Store modes per adapter and read it from the adapter structure */
2058 if (Adapter == 0)
2060 DEVMODEW DevModeW;
2061 int ModeIdx = 0;
2062 UINT i = 0;
2063 int j = 0;
2065 ZeroMemory(&DevModeW, sizeof(DevModeW));
2066 DevModeW.dmSize = sizeof(DevModeW);
2068 /* If we are filtering to a specific format (D3D9), then need to skip
2069 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2070 just count through the ones with valid bit depths */
2071 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
2072 switch (Format)
2074 case WINED3DFMT_UNKNOWN:
2075 /* This is D3D8. Do not enumerate P8 here */
2076 if (DevModeW.dmBitsPerPel == 32 ||
2077 DevModeW.dmBitsPerPel == 16) i++;
2078 break;
2079 case WINED3DFMT_X8R8G8B8:
2080 if (DevModeW.dmBitsPerPel == 32) i++;
2081 break;
2082 case WINED3DFMT_R5G6B5:
2083 if (DevModeW.dmBitsPerPel == 16) i++;
2084 break;
2085 case WINED3DFMT_P8:
2086 if (DevModeW.dmBitsPerPel == 8) i++;
2087 break;
2088 default:
2089 /* Modes that don't match what we support can get an early-out */
2090 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
2091 return WINED3DERR_INVALIDCALL;
2095 if (i == 0) {
2096 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2097 return WINED3DERR_INVALIDCALL;
2099 ModeIdx = j - 1;
2101 /* Now get the display mode via the calculated index */
2102 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2103 pMode->Width = DevModeW.dmPelsWidth;
2104 pMode->Height = DevModeW.dmPelsHeight;
2105 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2106 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2107 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2109 if (Format == WINED3DFMT_UNKNOWN) {
2110 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2111 } else {
2112 pMode->Format = Format;
2114 } else {
2115 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2116 return WINED3DERR_INVALIDCALL;
2119 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2120 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2121 DevModeW.dmBitsPerPel);
2124 else
2126 FIXME_(d3d_caps)("Adapter not primary display\n");
2129 return WINED3D_OK;
2132 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2133 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2134 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
2136 if (NULL == pMode ||
2137 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2138 return WINED3DERR_INVALIDCALL;
2141 if (Adapter == 0) { /* Display */
2142 int bpp = 0;
2143 DEVMODEW DevModeW;
2145 ZeroMemory(&DevModeW, sizeof(DevModeW));
2146 DevModeW.dmSize = sizeof(DevModeW);
2148 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2149 pMode->Width = DevModeW.dmPelsWidth;
2150 pMode->Height = DevModeW.dmPelsHeight;
2151 bpp = DevModeW.dmBitsPerPel;
2152 pMode->RefreshRate = DEFAULT_REFRESH_RATE;
2153 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2155 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2158 pMode->Format = pixelformat_for_depth(bpp);
2159 } else {
2160 FIXME_(d3d_caps)("Adapter not primary display\n");
2163 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2164 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2165 return WINED3D_OK;
2168 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2169 and fields being inserted in the middle, a new structure is used in place */
2170 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2171 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2172 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2173 size_t len;
2175 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2177 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2178 return WINED3DERR_INVALIDCALL;
2181 /* Return the information requested */
2182 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2184 if (pIdentifier->driver_size)
2186 len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1);
2187 memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len);
2188 pIdentifier->driver[len] = '\0';
2191 if (pIdentifier->description_size)
2193 const char *description;
2195 if (This->adapters[Adapter].gl_info.driver_description)
2196 description = This->adapters[Adapter].gl_info.driver_description;
2197 else
2198 description = This->adapters[Adapter].description;
2200 len = min(strlen(description), pIdentifier->description_size - 1);
2201 memcpy(pIdentifier->description, description, len);
2202 pIdentifier->description[len] = '\0';
2205 /* Note that d3d8 doesn't supply a device name. */
2206 if (pIdentifier->device_name_size)
2208 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2210 len = strlen(device_name);
2211 if (len >= pIdentifier->device_name_size)
2213 ERR("Device name size too small.\n");
2214 return WINED3DERR_INVALIDCALL;
2217 memcpy(pIdentifier->device_name, device_name, len);
2218 pIdentifier->device_name[len] = '\0';
2221 pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
2222 pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version;
2223 pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor;
2224 pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card;
2225 pIdentifier->subsystem_id = 0;
2226 pIdentifier->revision = 0;
2227 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2229 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
2231 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
2232 pIdentifier->device_id = wined3d_settings.pci_device_id;
2235 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
2237 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
2238 pIdentifier->vendor_id = wined3d_settings.pci_vendor_id;
2241 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2243 return WINED3D_OK;
2246 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2247 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2249 short redSize, greenSize, blueSize, alphaSize, colorBits;
2251 if(!cfg)
2252 return FALSE;
2254 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2255 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2257 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2258 return FALSE;
2261 if(cfg->redSize < redSize)
2262 return FALSE;
2264 if(cfg->greenSize < greenSize)
2265 return FALSE;
2267 if(cfg->blueSize < blueSize)
2268 return FALSE;
2270 if(cfg->alphaSize < alphaSize)
2271 return FALSE;
2273 return TRUE;
2274 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2275 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2276 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2277 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2278 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2279 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2280 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2281 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2282 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2283 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2284 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2285 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2286 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2287 } else {
2288 /* Probably a color index mode */
2289 return FALSE;
2292 return FALSE;
2295 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2296 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2298 short depthSize, stencilSize;
2299 BOOL lockable = FALSE;
2301 if(!cfg)
2302 return FALSE;
2304 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2306 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2307 return FALSE;
2310 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
2311 lockable = TRUE;
2313 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2314 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2315 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2316 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2317 return FALSE;
2319 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2320 * allow more stencil bits than requested. */
2321 if(cfg->stencilSize < stencilSize)
2322 return FALSE;
2324 return TRUE;
2327 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2328 WINED3DFORMAT AdapterFormat,
2329 WINED3DFORMAT RenderTargetFormat,
2330 WINED3DFORMAT DepthStencilFormat) {
2331 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2332 int nCfgs;
2333 const WineD3D_PixelFormat *cfgs;
2334 const struct WineD3DAdapter *adapter;
2335 const struct GlPixelFormatDesc *rt_format_desc;
2336 const struct GlPixelFormatDesc *ds_format_desc;
2337 int it;
2339 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2340 This, Adapter,
2341 DeviceType, debug_d3ddevicetype(DeviceType),
2342 AdapterFormat, debug_d3dformat(AdapterFormat),
2343 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2344 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2346 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2347 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2348 return WINED3DERR_INVALIDCALL;
2351 adapter = &This->adapters[Adapter];
2352 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2353 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2354 cfgs = adapter->cfgs;
2355 nCfgs = adapter->nCfgs;
2356 for (it = 0; it < nCfgs; ++it) {
2357 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2359 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2361 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2362 return WINED3D_OK;
2366 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2368 return WINED3DERR_NOTAVAILABLE;
2371 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2372 WINED3DFORMAT SurfaceFormat, BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels)
2374 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2375 const struct GlPixelFormatDesc *glDesc;
2376 const struct WineD3DAdapter *adapter;
2378 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2379 This,
2380 Adapter,
2381 DeviceType, debug_d3ddevicetype(DeviceType),
2382 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2383 Windowed,
2384 MultiSampleType,
2385 pQualityLevels);
2387 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2388 return WINED3DERR_INVALIDCALL;
2391 /* TODO: handle Windowed, add more quality levels */
2393 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2394 if(pQualityLevels) *pQualityLevels = 1;
2395 return WINED3D_OK;
2398 /* By default multisampling is disabled right now as it causes issues
2399 * on some Nvidia driver versions and it doesn't work well in combination
2400 * with FBOs yet. */
2401 if(!wined3d_settings.allow_multisampling)
2402 return WINED3DERR_NOTAVAILABLE;
2404 adapter = &This->adapters[Adapter];
2405 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2406 if (!glDesc) return WINED3DERR_INVALIDCALL;
2408 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2409 int i, nCfgs;
2410 const WineD3D_PixelFormat *cfgs;
2412 cfgs = adapter->cfgs;
2413 nCfgs = adapter->nCfgs;
2414 for(i=0; i<nCfgs; i++) {
2415 if(cfgs[i].numSamples != MultiSampleType)
2416 continue;
2418 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2419 continue;
2421 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2423 if(pQualityLevels)
2424 *pQualityLevels = 1; /* Guess at a value! */
2425 return WINED3D_OK;
2428 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2429 short redSize, greenSize, blueSize, alphaSize, colorBits;
2430 int i, nCfgs;
2431 const WineD3D_PixelFormat *cfgs;
2433 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2435 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2436 return WINED3DERR_NOTAVAILABLE;
2439 cfgs = adapter->cfgs;
2440 nCfgs = adapter->nCfgs;
2441 for(i=0; i<nCfgs; i++) {
2442 if(cfgs[i].numSamples != MultiSampleType)
2443 continue;
2444 if(cfgs[i].redSize != redSize)
2445 continue;
2446 if(cfgs[i].greenSize != greenSize)
2447 continue;
2448 if(cfgs[i].blueSize != blueSize)
2449 continue;
2450 if(cfgs[i].alphaSize != alphaSize)
2451 continue;
2453 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2455 if(pQualityLevels)
2456 *pQualityLevels = 1; /* Guess at a value! */
2457 return WINED3D_OK;
2460 return WINED3DERR_NOTAVAILABLE;
2463 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2464 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2466 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2467 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2468 UINT nmodes;
2470 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2471 This,
2472 Adapter,
2473 DeviceType, debug_d3ddevicetype(DeviceType),
2474 DisplayFormat, debug_d3dformat(DisplayFormat),
2475 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2476 Windowed);
2478 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2479 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2480 return WINED3DERR_INVALIDCALL;
2483 /* The task of this function is to check whether a certain display / backbuffer format
2484 * combination is available on the given adapter. In fullscreen mode microsoft specified
2485 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2486 * and display format should match exactly.
2487 * In windowed mode format conversion can occur and this depends on the driver. When format
2488 * conversion is done, this function should nevertheless fail and applications need to use
2489 * CheckDeviceFormatConversion.
2490 * At the moment we assume that fullscreen and windowed have the same capabilities */
2492 /* There are only 4 display formats */
2493 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2494 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2495 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2496 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2498 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2499 return WINED3DERR_NOTAVAILABLE;
2502 /* If the requested DisplayFormat is not available, don't continue */
2503 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2504 if(!nmodes) {
2505 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2506 return WINED3DERR_NOTAVAILABLE;
2509 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2510 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2511 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2512 return WINED3DERR_NOTAVAILABLE;
2515 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2516 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
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 X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2522 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2523 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2524 return WINED3DERR_NOTAVAILABLE;
2527 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2528 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2529 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2530 return WINED3DERR_NOTAVAILABLE;
2533 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2534 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2535 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2536 return WINED3DERR_NOTAVAILABLE;
2539 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2540 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2541 if(FAILED(hr))
2542 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2544 return hr;
2548 /* Check if we support bumpmapping for a format */
2549 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2550 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2552 const struct fragment_pipeline *fp;
2554 switch(format_desc->format)
2556 case WINED3DFMT_R8G8_SNORM:
2557 case WINED3DFMT_R16G16_SNORM:
2558 case WINED3DFMT_L6V5U5:
2559 case WINED3DFMT_X8L8V8U8:
2560 case WINED3DFMT_R8G8B8A8_SNORM:
2561 /* Ask the fixed function pipeline implementation if it can deal
2562 * with the conversion. If we've got a GL extension giving native
2563 * support this will be an identity conversion. */
2564 fp = select_fragment_implementation(adapter, DeviceType);
2565 if (fp->color_fixup_supported(format_desc->color_fixup))
2567 TRACE_(d3d_caps)("[OK]\n");
2568 return TRUE;
2570 TRACE_(d3d_caps)("[FAILED]\n");
2571 return FALSE;
2573 default:
2574 TRACE_(d3d_caps)("[FAILED]\n");
2575 return FALSE;
2579 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2580 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2581 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2583 int it=0;
2585 /* Only allow depth/stencil formats */
2586 if (!(ds_format_desc->depth_size || ds_format_desc->stencil_size)) return FALSE;
2588 /* Walk through all WGL pixel formats to find a match */
2589 for (it = 0; it < adapter->nCfgs; ++it)
2591 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2592 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2594 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2596 return TRUE;
2601 return FALSE;
2604 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2606 /* The flags entry of a format contains the filtering capability */
2607 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2609 return FALSE;
2612 /* Check the render target capabilities of a format */
2613 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2614 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2616 /* Filter out non-RT formats */
2617 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2619 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2620 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2621 int it;
2622 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2623 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2625 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2626 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2628 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2629 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2630 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2631 TRACE_(d3d_caps)("[FAILED]\n");
2632 return FALSE;
2635 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2636 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2637 for (it = 0; it < adapter->nCfgs; ++it)
2639 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2640 &cfgs[it], check_format_desc))
2642 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2643 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2644 return TRUE;
2647 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2648 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2649 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2650 int it;
2652 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2653 for (it = 0; it < adapter->nCfgs; ++it)
2655 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2656 &cfgs[it], check_format_desc))
2658 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2659 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2660 return TRUE;
2663 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2664 /* For now return TRUE for FBOs until we have some proper checks.
2665 * Note that this function will only be called when the format is around for texturing. */
2666 return TRUE;
2668 return FALSE;
2671 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2673 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2675 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2676 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2677 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2678 return FALSE;
2681 switch (format_desc->format)
2683 case WINED3DFMT_A8R8G8B8:
2684 case WINED3DFMT_X8R8G8B8:
2685 case WINED3DFMT_A4R4G4B4:
2686 case WINED3DFMT_L8:
2687 case WINED3DFMT_A8L8:
2688 case WINED3DFMT_DXT1:
2689 case WINED3DFMT_DXT2:
2690 case WINED3DFMT_DXT3:
2691 case WINED3DFMT_DXT4:
2692 case WINED3DFMT_DXT5:
2693 TRACE_(d3d_caps)("[OK]\n");
2694 return TRUE;
2696 default:
2697 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2698 return FALSE;
2700 return FALSE;
2703 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2704 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2706 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2707 * doing the color fixup in shaders.
2708 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2709 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2711 int vs_selected_mode;
2712 int ps_selected_mode;
2713 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2715 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2716 TRACE_(d3d_caps)("[OK]\n");
2717 return TRUE;
2721 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2722 return FALSE;
2725 /* Check if a format support blending in combination with pixel shaders */
2726 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2727 const struct GlPixelFormatDesc *format_desc)
2729 /* The flags entry of a format contains the post pixel shader blending capability */
2730 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2732 return FALSE;
2735 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2737 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2738 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2739 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2740 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2741 * capability anyway.
2743 * For now lets report this on all formats, but in the future we may want to
2744 * restrict it to some should games need that
2746 return TRUE;
2749 /* Check if a texture format is supported on the given adapter */
2750 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2751 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2753 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2754 const shader_backend_t *shader_backend;
2755 const struct fragment_pipeline *fp;
2757 switch (format_desc->format)
2759 /*****
2760 * supported: RGB(A) formats
2762 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2763 case WINED3DFMT_A8R8G8B8:
2764 case WINED3DFMT_X8R8G8B8:
2765 case WINED3DFMT_R5G6B5:
2766 case WINED3DFMT_X1R5G5B5:
2767 case WINED3DFMT_A1R5G5B5:
2768 case WINED3DFMT_A4R4G4B4:
2769 case WINED3DFMT_A8_UNORM:
2770 case WINED3DFMT_X4R4G4B4:
2771 case WINED3DFMT_R8G8B8A8_UNORM:
2772 case WINED3DFMT_X8B8G8R8:
2773 case WINED3DFMT_A2R10G10B10:
2774 case WINED3DFMT_R10G10B10A2_UNORM:
2775 case WINED3DFMT_R16G16_UNORM:
2776 TRACE_(d3d_caps)("[OK]\n");
2777 return TRUE;
2779 case WINED3DFMT_R3G3B2:
2780 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2781 return FALSE;
2783 /*****
2784 * supported: Palettized
2786 case WINED3DFMT_P8:
2787 TRACE_(d3d_caps)("[OK]\n");
2788 return TRUE;
2789 /* No Windows driver offers A8P8, so don't offer it either */
2790 case WINED3DFMT_A8P8:
2791 return FALSE;
2793 /*****
2794 * Supported: (Alpha)-Luminance
2796 case WINED3DFMT_L8:
2797 case WINED3DFMT_A8L8:
2798 case WINED3DFMT_L16:
2799 TRACE_(d3d_caps)("[OK]\n");
2800 return TRUE;
2802 /* Not supported on Windows, thus disabled */
2803 case WINED3DFMT_A4L4:
2804 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2805 return FALSE;
2807 /*****
2808 * Supported: Depth/Stencil formats
2810 case WINED3DFMT_D16_LOCKABLE:
2811 case WINED3DFMT_D16_UNORM:
2812 case WINED3DFMT_D15S1:
2813 case WINED3DFMT_D24X8:
2814 case WINED3DFMT_D24X4S4:
2815 case WINED3DFMT_D24S8:
2816 case WINED3DFMT_D24FS8:
2817 case WINED3DFMT_D32:
2818 case WINED3DFMT_D32F_LOCKABLE:
2819 return TRUE;
2821 /*****
2822 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2823 * GL_NV_texture_shader). Emulated by shaders
2825 case WINED3DFMT_R8G8_SNORM:
2826 case WINED3DFMT_X8L8V8U8:
2827 case WINED3DFMT_L6V5U5:
2828 case WINED3DFMT_R8G8B8A8_SNORM:
2829 case WINED3DFMT_R16G16_SNORM:
2830 /* Ask the shader backend if it can deal with the conversion. If
2831 * we've got a GL extension giving native support this will be an
2832 * identity conversion. */
2833 shader_backend = select_shader_backend(adapter, DeviceType);
2834 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2836 TRACE_(d3d_caps)("[OK]\n");
2837 return TRUE;
2839 TRACE_(d3d_caps)("[FAILED]\n");
2840 return FALSE;
2842 case WINED3DFMT_DXT1:
2843 case WINED3DFMT_DXT2:
2844 case WINED3DFMT_DXT3:
2845 case WINED3DFMT_DXT4:
2846 case WINED3DFMT_DXT5:
2847 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2848 TRACE_(d3d_caps)("[OK]\n");
2849 return TRUE;
2851 TRACE_(d3d_caps)("[FAILED]\n");
2852 return FALSE;
2855 /*****
2856 * Odd formats - not supported
2858 case WINED3DFMT_VERTEXDATA:
2859 case WINED3DFMT_R16_UINT:
2860 case WINED3DFMT_R32_UINT:
2861 case WINED3DFMT_R16G16B16A16_SNORM:
2862 case WINED3DFMT_A2W10V10U10:
2863 case WINED3DFMT_W11V11U10:
2864 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2865 return FALSE;
2867 /*****
2868 * WINED3DFMT_CxV8U8: Not supported right now
2870 case WINED3DFMT_CxV8U8:
2871 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2872 return FALSE;
2874 /* YUV formats */
2875 case WINED3DFMT_UYVY:
2876 case WINED3DFMT_YUY2:
2877 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2878 TRACE_(d3d_caps)("[OK]\n");
2879 return TRUE;
2881 TRACE_(d3d_caps)("[FAILED]\n");
2882 return FALSE;
2883 case WINED3DFMT_YV12:
2884 TRACE_(d3d_caps)("[FAILED]\n");
2885 return FALSE;
2887 /* Not supported */
2888 case WINED3DFMT_R16G16B16A16_UNORM:
2889 case WINED3DFMT_A8R3G3B2:
2890 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2891 return FALSE;
2893 /* Floating point formats */
2894 case WINED3DFMT_R16_FLOAT:
2895 case WINED3DFMT_R16G16_FLOAT:
2896 case WINED3DFMT_R16G16B16A16_FLOAT:
2897 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
2898 TRACE_(d3d_caps)("[OK]\n");
2899 return TRUE;
2901 TRACE_(d3d_caps)("[FAILED]\n");
2902 return FALSE;
2904 case WINED3DFMT_R32_FLOAT:
2905 case WINED3DFMT_R32G32_FLOAT:
2906 case WINED3DFMT_R32G32B32A32_FLOAT:
2907 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
2908 TRACE_(d3d_caps)("[OK]\n");
2909 return TRUE;
2911 TRACE_(d3d_caps)("[FAILED]\n");
2912 return FALSE;
2914 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
2915 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
2916 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
2917 * We can do instancing with all shader versions, but we need vertex shaders.
2919 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
2920 * to enable instancing. WineD3D doesn't need that and just ignores it.
2922 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
2924 case WINEMAKEFOURCC('I','N','S','T'):
2925 TRACE("ATI Instancing check hack\n");
2926 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
2927 TRACE_(d3d_caps)("[OK]\n");
2928 return TRUE;
2930 TRACE_(d3d_caps)("[FAILED]\n");
2931 return FALSE;
2933 /* Some weird FOURCC formats */
2934 case WINED3DFMT_R8G8_B8G8:
2935 case WINED3DFMT_G8R8_G8B8:
2936 case WINED3DFMT_MULTI2_ARGB8:
2937 TRACE_(d3d_caps)("[FAILED]\n");
2938 return FALSE;
2940 /* Vendor specific formats */
2941 case WINED3DFMT_ATI2N:
2942 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
2943 shader_backend = select_shader_backend(adapter, DeviceType);
2944 fp = select_fragment_implementation(adapter, DeviceType);
2945 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
2946 && fp->color_fixup_supported(format_desc->color_fixup))
2948 TRACE_(d3d_caps)("[OK]\n");
2949 return TRUE;
2952 TRACE_(d3d_caps)("[OK]\n");
2953 return TRUE;
2955 TRACE_(d3d_caps)("[FAILED]\n");
2956 return FALSE;
2958 case WINED3DFMT_NVHU:
2959 case WINED3DFMT_NVHS:
2960 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
2961 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
2962 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
2963 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
2964 * Applications have to deal with not having NVHS and NVHU.
2966 TRACE_(d3d_caps)("[FAILED]\n");
2967 return FALSE;
2969 case WINED3DFMT_UNKNOWN:
2970 return FALSE;
2972 default:
2973 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
2974 break;
2976 return FALSE;
2979 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
2980 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
2982 const struct blit_shader *blitter;
2984 if(SurfaceType == SURFACE_GDI) {
2985 switch(check_format_desc->format)
2987 case WINED3DFMT_R8G8B8:
2988 case WINED3DFMT_A8R8G8B8:
2989 case WINED3DFMT_X8R8G8B8:
2990 case WINED3DFMT_R5G6B5:
2991 case WINED3DFMT_X1R5G5B5:
2992 case WINED3DFMT_A1R5G5B5:
2993 case WINED3DFMT_A4R4G4B4:
2994 case WINED3DFMT_R3G3B2:
2995 case WINED3DFMT_A8_UNORM:
2996 case WINED3DFMT_A8R3G3B2:
2997 case WINED3DFMT_X4R4G4B4:
2998 case WINED3DFMT_R10G10B10A2_UNORM:
2999 case WINED3DFMT_R8G8B8A8_UNORM:
3000 case WINED3DFMT_X8B8G8R8:
3001 case WINED3DFMT_R16G16_UNORM:
3002 case WINED3DFMT_A2R10G10B10:
3003 case WINED3DFMT_R16G16B16A16_UNORM:
3004 case WINED3DFMT_P8:
3005 TRACE_(d3d_caps)("[OK]\n");
3006 return TRUE;
3007 default:
3008 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3009 return FALSE;
3013 /* All format that are supported for textures are supported for surfaces as well */
3014 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3015 /* All depth stencil formats are supported on surfaces */
3016 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3018 /* If opengl can't process the format natively, the blitter may be able to convert it */
3019 blitter = select_blit_implementation(adapter, DeviceType);
3020 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3022 TRACE_(d3d_caps)("[OK]\n");
3023 return TRUE;
3026 /* Reject other formats */
3027 TRACE_(d3d_caps)("[FAILED]\n");
3028 return FALSE;
3031 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
3033 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3035 if (!GL_LIMITS(vertex_samplers)) {
3036 TRACE_(d3d_caps)("[FAILED]\n");
3037 return FALSE;
3040 switch (format_desc->format)
3042 case WINED3DFMT_R32G32B32A32_FLOAT:
3043 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3044 TRACE_(d3d_caps)("[FAILED]\n");
3045 return FALSE;
3047 TRACE_(d3d_caps)("[OK]\n");
3048 return TRUE;
3050 default:
3051 TRACE_(d3d_caps)("[FAILED]\n");
3052 return FALSE;
3054 return FALSE;
3057 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3058 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3059 WINED3DSURFTYPE SurfaceType)
3061 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3062 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3063 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3064 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3065 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3066 DWORD UsageCaps = 0;
3068 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3069 This,
3070 Adapter,
3071 DeviceType, debug_d3ddevicetype(DeviceType),
3072 AdapterFormat, debug_d3dformat(AdapterFormat),
3073 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3074 RType, debug_d3dresourcetype(RType),
3075 CheckFormat, debug_d3dformat(CheckFormat));
3077 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3078 return WINED3DERR_INVALIDCALL;
3081 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3083 if(SurfaceType != SURFACE_OPENGL) {
3084 TRACE("[FAILED]\n");
3085 return WINED3DERR_NOTAVAILABLE;
3088 /* Cubetexture allows:
3089 * - D3DUSAGE_AUTOGENMIPMAP
3090 * - D3DUSAGE_DEPTHSTENCIL
3091 * - D3DUSAGE_DYNAMIC
3092 * - D3DUSAGE_NONSECURE (d3d9ex)
3093 * - D3DUSAGE_RENDERTARGET
3094 * - D3DUSAGE_SOFTWAREPROCESSING
3095 * - D3DUSAGE_QUERY_WRAPANDMIP
3097 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3098 /* Check if the texture format is around */
3099 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3101 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3102 /* Check for automatic mipmap generation support */
3103 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3104 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3105 } else {
3106 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3107 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3111 /* Always report dynamic locking */
3112 if(Usage & WINED3DUSAGE_DYNAMIC)
3113 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3115 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3116 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3118 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3119 } else {
3120 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3121 return WINED3DERR_NOTAVAILABLE;
3125 /* Always report software processing */
3126 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3127 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3129 /* Check QUERY_FILTER support */
3130 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3131 if (CheckFilterCapability(adapter, format_desc))
3133 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3134 } else {
3135 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3136 return WINED3DERR_NOTAVAILABLE;
3140 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3141 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3142 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3144 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3145 } else {
3146 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3147 return WINED3DERR_NOTAVAILABLE;
3151 /* Check QUERY_SRGBREAD support */
3152 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3153 if (CheckSrgbReadCapability(adapter, format_desc))
3155 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3156 } else {
3157 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3158 return WINED3DERR_NOTAVAILABLE;
3162 /* Check QUERY_SRGBWRITE support */
3163 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3164 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3166 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3167 } else {
3168 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3169 return WINED3DERR_NOTAVAILABLE;
3173 /* Check QUERY_VERTEXTEXTURE support */
3174 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3175 if (CheckVertexTextureCapability(adapter, format_desc))
3177 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3178 } else {
3179 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3180 return WINED3DERR_NOTAVAILABLE;
3184 /* Check QUERY_WRAPANDMIP support */
3185 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3186 if (CheckWrapAndMipCapability(adapter, format_desc))
3188 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3189 } else {
3190 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3191 return WINED3DERR_NOTAVAILABLE;
3194 } else {
3195 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3196 return WINED3DERR_NOTAVAILABLE;
3198 } else {
3199 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3200 return WINED3DERR_NOTAVAILABLE;
3202 } else if(RType == WINED3DRTYPE_SURFACE) {
3203 /* Surface allows:
3204 * - D3DUSAGE_DEPTHSTENCIL
3205 * - D3DUSAGE_NONSECURE (d3d9ex)
3206 * - D3DUSAGE_RENDERTARGET
3209 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3211 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3212 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3214 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3215 } else {
3216 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3217 return WINED3DERR_NOTAVAILABLE;
3221 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3222 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3224 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3225 } else {
3226 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3227 return WINED3DERR_NOTAVAILABLE;
3231 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3232 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3233 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3235 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3236 } else {
3237 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3238 return WINED3DERR_NOTAVAILABLE;
3241 } else {
3242 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3243 return WINED3DERR_NOTAVAILABLE;
3246 } else if(RType == WINED3DRTYPE_TEXTURE) {
3247 /* Texture allows:
3248 * - D3DUSAGE_AUTOGENMIPMAP
3249 * - D3DUSAGE_DEPTHSTENCIL
3250 * - D3DUSAGE_DMAP
3251 * - D3DUSAGE_DYNAMIC
3252 * - D3DUSAGE_NONSECURE (d3d9ex)
3253 * - D3DUSAGE_RENDERTARGET
3254 * - D3DUSAGE_SOFTWAREPROCESSING
3255 * - D3DUSAGE_TEXTAPI (d3d9ex)
3256 * - D3DUSAGE_QUERY_WRAPANDMIP
3259 if(SurfaceType != SURFACE_OPENGL) {
3260 TRACE("[FAILED]\n");
3261 return WINED3DERR_NOTAVAILABLE;
3264 /* Check if the texture format is around */
3265 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3267 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3268 /* Check for automatic mipmap generation support */
3269 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3270 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3271 } else {
3272 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3273 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3277 /* Always report dynamic locking */
3278 if(Usage & WINED3DUSAGE_DYNAMIC)
3279 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3281 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3282 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3284 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3285 } else {
3286 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3287 return WINED3DERR_NOTAVAILABLE;
3291 /* Always report software processing */
3292 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3293 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3295 /* Check QUERY_FILTER support */
3296 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3297 if (CheckFilterCapability(adapter, format_desc))
3299 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3300 } else {
3301 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3302 return WINED3DERR_NOTAVAILABLE;
3306 /* Check QUERY_LEGACYBUMPMAP support */
3307 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3308 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3310 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3311 } else {
3312 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3313 return WINED3DERR_NOTAVAILABLE;
3317 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3318 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3319 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3321 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3322 } else {
3323 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3324 return WINED3DERR_NOTAVAILABLE;
3328 /* Check QUERY_SRGBREAD support */
3329 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3330 if (CheckSrgbReadCapability(adapter, format_desc))
3332 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3333 } else {
3334 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3335 return WINED3DERR_NOTAVAILABLE;
3339 /* Check QUERY_SRGBWRITE support */
3340 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3341 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3343 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3344 } else {
3345 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3346 return WINED3DERR_NOTAVAILABLE;
3350 /* Check QUERY_VERTEXTEXTURE support */
3351 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3352 if (CheckVertexTextureCapability(adapter, format_desc))
3354 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3355 } else {
3356 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3357 return WINED3DERR_NOTAVAILABLE;
3361 /* Check QUERY_WRAPANDMIP support */
3362 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3363 if (CheckWrapAndMipCapability(adapter, format_desc))
3365 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3366 } else {
3367 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3368 return WINED3DERR_NOTAVAILABLE;
3372 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3373 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3375 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3376 } else {
3377 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3378 return WINED3DERR_NOTAVAILABLE;
3381 } else {
3382 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3383 return WINED3DERR_NOTAVAILABLE;
3385 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3386 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3387 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3389 * Volumetexture allows:
3390 * - D3DUSAGE_DYNAMIC
3391 * - D3DUSAGE_NONSECURE (d3d9ex)
3392 * - D3DUSAGE_SOFTWAREPROCESSING
3393 * - D3DUSAGE_QUERY_WRAPANDMIP
3396 if(SurfaceType != SURFACE_OPENGL) {
3397 TRACE("[FAILED]\n");
3398 return WINED3DERR_NOTAVAILABLE;
3401 /* Check volume texture and volume usage caps */
3402 if(GL_SUPPORT(EXT_TEXTURE3D)) {
3403 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3405 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3406 return WINED3DERR_NOTAVAILABLE;
3409 /* Always report dynamic locking */
3410 if(Usage & WINED3DUSAGE_DYNAMIC)
3411 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3413 /* Always report software processing */
3414 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3415 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3417 /* Check QUERY_FILTER support */
3418 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3419 if (CheckFilterCapability(adapter, format_desc))
3421 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3422 } else {
3423 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3424 return WINED3DERR_NOTAVAILABLE;
3428 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3429 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3430 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3432 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3433 } else {
3434 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3435 return WINED3DERR_NOTAVAILABLE;
3439 /* Check QUERY_SRGBREAD support */
3440 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3441 if (CheckSrgbReadCapability(adapter, format_desc))
3443 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3444 } else {
3445 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3446 return WINED3DERR_NOTAVAILABLE;
3450 /* Check QUERY_SRGBWRITE support */
3451 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3452 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3454 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3455 } else {
3456 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3457 return WINED3DERR_NOTAVAILABLE;
3461 /* Check QUERY_VERTEXTEXTURE support */
3462 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3463 if (CheckVertexTextureCapability(adapter, format_desc))
3465 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3466 } else {
3467 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3468 return WINED3DERR_NOTAVAILABLE;
3472 /* Check QUERY_WRAPANDMIP support */
3473 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3474 if (CheckWrapAndMipCapability(adapter, format_desc))
3476 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3477 } else {
3478 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3479 return WINED3DERR_NOTAVAILABLE;
3482 } else {
3483 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3484 return WINED3DERR_NOTAVAILABLE;
3487 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3488 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3489 * app needing one of those formats, don't advertize them to avoid leading apps into
3490 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3491 * except of R32F.
3493 switch(CheckFormat) {
3494 case WINED3DFMT_P8:
3495 case WINED3DFMT_A4L4:
3496 case WINED3DFMT_R32_FLOAT:
3497 case WINED3DFMT_R16_FLOAT:
3498 case WINED3DFMT_X8L8V8U8:
3499 case WINED3DFMT_L6V5U5:
3500 case WINED3DFMT_R16G16_UNORM:
3501 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3502 return WINED3DERR_NOTAVAILABLE;
3504 case WINED3DFMT_R8G8B8A8_SNORM:
3505 case WINED3DFMT_R16G16_SNORM:
3506 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3507 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3508 return WINED3DERR_NOTAVAILABLE;
3510 break;
3512 case WINED3DFMT_R8G8_SNORM:
3513 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3514 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3515 return WINED3DERR_NOTAVAILABLE;
3517 break;
3519 case WINED3DFMT_DXT1:
3520 case WINED3DFMT_DXT2:
3521 case WINED3DFMT_DXT3:
3522 case WINED3DFMT_DXT4:
3523 case WINED3DFMT_DXT5:
3524 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3525 * compressed texture results in an error. While the D3D refrast does
3526 * support s3tc volumes, at least the nvidia windows driver does not, so
3527 * we're free not to support this format.
3529 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3530 return WINED3DERR_NOTAVAILABLE;
3532 default:
3533 /* Do nothing, continue with checking the format below */
3534 break;
3536 } else if(RType == WINED3DRTYPE_BUFFER){
3537 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3538 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3539 return WINED3DERR_NOTAVAILABLE;
3542 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3543 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3544 * usage flags match. */
3545 if(UsageCaps == Usage) {
3546 return WINED3D_OK;
3547 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3548 return WINED3DOK_NOAUTOGEN;
3549 } else {
3550 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);
3551 return WINED3DERR_NOTAVAILABLE;
3555 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3556 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3557 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3559 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3560 This,
3561 Adapter,
3562 DeviceType, debug_d3ddevicetype(DeviceType),
3563 SourceFormat, debug_d3dformat(SourceFormat),
3564 TargetFormat, debug_d3dformat(TargetFormat));
3565 return WINED3D_OK;
3568 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3570 const shader_backend_t *ret;
3571 int vs_selected_mode;
3572 int ps_selected_mode;
3574 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3575 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3576 ret = &glsl_shader_backend;
3577 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3578 ret = &arb_program_shader_backend;
3579 } else {
3580 ret = &none_shader_backend;
3582 return ret;
3585 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3586 WINED3DDEVTYPE DeviceType)
3588 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3589 int vs_selected_mode;
3590 int ps_selected_mode;
3592 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3593 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3594 return &arbfp_fragment_pipeline;
3595 } else if(ps_selected_mode == SHADER_ATI) {
3596 return &atifs_fragment_pipeline;
3597 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3598 return &nvts_fragment_pipeline;
3599 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3600 return &nvrc_fragment_pipeline;
3601 } else {
3602 return &ffp_fragment_pipeline;
3606 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3608 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3609 int vs_selected_mode;
3610 int ps_selected_mode;
3612 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3613 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3614 return &arbfp_blit;
3615 } else {
3616 return &ffp_blit;
3620 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3621 subset of a D3DCAPS9 structure. However, it has to come via a void *
3622 as the d3d8 interface cannot import the d3d9 header */
3623 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3625 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3626 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3627 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3628 int vs_selected_mode;
3629 int ps_selected_mode;
3630 struct shader_caps shader_caps;
3631 struct fragment_caps fragment_caps;
3632 const shader_backend_t *shader_backend;
3633 const struct fragment_pipeline *frag_pipeline = NULL;
3634 DWORD ckey_caps, blit_caps, fx_caps;
3636 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3638 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3639 return WINED3DERR_INVALIDCALL;
3642 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3644 /* This function should *not* be modifying GL caps
3645 * TODO: move the functionality where it belongs */
3646 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3648 /* ------------------------------------------------
3649 The following fields apply to both d3d8 and d3d9
3650 ------------------------------------------------ */
3651 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3652 pCaps->AdapterOrdinal = Adapter;
3654 pCaps->Caps = 0;
3655 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3656 WINED3DCAPS2_FULLSCREENGAMMA |
3657 WINED3DCAPS2_DYNAMICTEXTURES;
3658 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3659 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3662 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3663 WINED3DCAPS3_COPY_TO_VIDMEM |
3664 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3666 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3667 WINED3DPRESENT_INTERVAL_ONE;
3669 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3670 WINED3DCURSORCAPS_LOWRES;
3672 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3673 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3674 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3675 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3676 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3677 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3678 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3679 WINED3DDEVCAPS_PUREDEVICE |
3680 WINED3DDEVCAPS_HWRASTERIZATION |
3681 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3682 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3683 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3684 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3685 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3686 WINED3DDEVCAPS_RTPATCHES;
3688 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3689 WINED3DPMISCCAPS_CULLCCW |
3690 WINED3DPMISCCAPS_CULLCW |
3691 WINED3DPMISCCAPS_COLORWRITEENABLE |
3692 WINED3DPMISCCAPS_CLIPTLVERTS |
3693 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3694 WINED3DPMISCCAPS_MASKZ |
3695 WINED3DPMISCCAPS_BLENDOP |
3696 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3697 /* TODO:
3698 WINED3DPMISCCAPS_NULLREFERENCE
3699 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3700 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3701 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3702 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3704 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3705 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3707 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3708 WINED3DPRASTERCAPS_PAT |
3709 WINED3DPRASTERCAPS_WFOG |
3710 WINED3DPRASTERCAPS_ZFOG |
3711 WINED3DPRASTERCAPS_FOGVERTEX |
3712 WINED3DPRASTERCAPS_FOGTABLE |
3713 WINED3DPRASTERCAPS_STIPPLE |
3714 WINED3DPRASTERCAPS_SUBPIXEL |
3715 WINED3DPRASTERCAPS_ZTEST |
3716 WINED3DPRASTERCAPS_SCISSORTEST |
3717 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3718 WINED3DPRASTERCAPS_DEPTHBIAS;
3720 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3721 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3722 WINED3DPRASTERCAPS_ZBIAS |
3723 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3725 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3726 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3728 /* FIXME Add:
3729 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3730 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3731 WINED3DPRASTERCAPS_ANTIALIASEDGES
3732 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3733 WINED3DPRASTERCAPS_WBUFFER */
3735 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3736 WINED3DPCMPCAPS_EQUAL |
3737 WINED3DPCMPCAPS_GREATER |
3738 WINED3DPCMPCAPS_GREATEREQUAL |
3739 WINED3DPCMPCAPS_LESS |
3740 WINED3DPCMPCAPS_LESSEQUAL |
3741 WINED3DPCMPCAPS_NEVER |
3742 WINED3DPCMPCAPS_NOTEQUAL;
3744 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3745 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3746 WINED3DPBLENDCAPS_DESTALPHA |
3747 WINED3DPBLENDCAPS_DESTCOLOR |
3748 WINED3DPBLENDCAPS_INVDESTALPHA |
3749 WINED3DPBLENDCAPS_INVDESTCOLOR |
3750 WINED3DPBLENDCAPS_INVSRCALPHA |
3751 WINED3DPBLENDCAPS_INVSRCCOLOR |
3752 WINED3DPBLENDCAPS_ONE |
3753 WINED3DPBLENDCAPS_SRCALPHA |
3754 WINED3DPBLENDCAPS_SRCALPHASAT |
3755 WINED3DPBLENDCAPS_SRCCOLOR |
3756 WINED3DPBLENDCAPS_ZERO;
3758 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3759 WINED3DPBLENDCAPS_DESTCOLOR |
3760 WINED3DPBLENDCAPS_INVDESTALPHA |
3761 WINED3DPBLENDCAPS_INVDESTCOLOR |
3762 WINED3DPBLENDCAPS_INVSRCALPHA |
3763 WINED3DPBLENDCAPS_INVSRCCOLOR |
3764 WINED3DPBLENDCAPS_ONE |
3765 WINED3DPBLENDCAPS_SRCALPHA |
3766 WINED3DPBLENDCAPS_SRCCOLOR |
3767 WINED3DPBLENDCAPS_ZERO;
3768 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3769 * according to the glBlendFunc manpage
3771 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3772 * legacy settings for srcblend only
3775 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3776 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3777 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3781 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3782 WINED3DPCMPCAPS_EQUAL |
3783 WINED3DPCMPCAPS_GREATER |
3784 WINED3DPCMPCAPS_GREATEREQUAL |
3785 WINED3DPCMPCAPS_LESS |
3786 WINED3DPCMPCAPS_LESSEQUAL |
3787 WINED3DPCMPCAPS_NEVER |
3788 WINED3DPCMPCAPS_NOTEQUAL;
3790 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3791 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3792 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3793 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3794 WINED3DPSHADECAPS_COLORFLATRGB |
3795 WINED3DPSHADECAPS_FOGFLAT |
3796 WINED3DPSHADECAPS_FOGGOURAUD |
3797 WINED3DPSHADECAPS_SPECULARFLATRGB;
3799 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3800 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3801 WINED3DPTEXTURECAPS_TRANSPARENCY |
3802 WINED3DPTEXTURECAPS_BORDER |
3803 WINED3DPTEXTURECAPS_MIPMAP |
3804 WINED3DPTEXTURECAPS_PROJECTED |
3805 WINED3DPTEXTURECAPS_PERSPECTIVE;
3807 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3808 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3809 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3812 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3813 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3814 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3815 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3818 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3819 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3820 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3821 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3825 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3826 WINED3DPTFILTERCAPS_MAGFPOINT |
3827 WINED3DPTFILTERCAPS_MINFLINEAR |
3828 WINED3DPTFILTERCAPS_MINFPOINT |
3829 WINED3DPTFILTERCAPS_MIPFLINEAR |
3830 WINED3DPTFILTERCAPS_MIPFPOINT |
3831 WINED3DPTFILTERCAPS_LINEAR |
3832 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3833 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3834 WINED3DPTFILTERCAPS_MIPLINEAR |
3835 WINED3DPTFILTERCAPS_MIPNEAREST |
3836 WINED3DPTFILTERCAPS_NEAREST;
3838 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3839 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3840 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3843 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3844 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3845 WINED3DPTFILTERCAPS_MAGFPOINT |
3846 WINED3DPTFILTERCAPS_MINFLINEAR |
3847 WINED3DPTFILTERCAPS_MINFPOINT |
3848 WINED3DPTFILTERCAPS_MIPFLINEAR |
3849 WINED3DPTFILTERCAPS_MIPFPOINT |
3850 WINED3DPTFILTERCAPS_LINEAR |
3851 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3852 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3853 WINED3DPTFILTERCAPS_MIPLINEAR |
3854 WINED3DPTFILTERCAPS_MIPNEAREST |
3855 WINED3DPTFILTERCAPS_NEAREST;
3857 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3858 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3859 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3861 } else
3862 pCaps->CubeTextureFilterCaps = 0;
3864 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3865 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3866 WINED3DPTFILTERCAPS_MAGFPOINT |
3867 WINED3DPTFILTERCAPS_MINFLINEAR |
3868 WINED3DPTFILTERCAPS_MINFPOINT |
3869 WINED3DPTFILTERCAPS_MIPFLINEAR |
3870 WINED3DPTFILTERCAPS_MIPFPOINT |
3871 WINED3DPTFILTERCAPS_LINEAR |
3872 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3873 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3874 WINED3DPTFILTERCAPS_MIPLINEAR |
3875 WINED3DPTFILTERCAPS_MIPNEAREST |
3876 WINED3DPTFILTERCAPS_NEAREST;
3877 } else
3878 pCaps->VolumeTextureFilterCaps = 0;
3880 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3881 WINED3DPTADDRESSCAPS_CLAMP |
3882 WINED3DPTADDRESSCAPS_WRAP;
3884 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3885 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3887 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3888 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3890 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3891 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3894 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3895 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
3896 WINED3DPTADDRESSCAPS_CLAMP |
3897 WINED3DPTADDRESSCAPS_WRAP;
3898 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3899 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
3901 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3902 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
3904 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3905 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
3907 } else
3908 pCaps->VolumeTextureAddressCaps = 0;
3910 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
3911 WINED3DLINECAPS_ZTEST |
3912 WINED3DLINECAPS_BLEND |
3913 WINED3DLINECAPS_ALPHACMP |
3914 WINED3DLINECAPS_FOG;
3915 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
3916 * idea how generating the smoothing alpha values works; the result is different
3919 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
3920 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
3922 if(GL_SUPPORT(EXT_TEXTURE3D))
3923 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
3924 else
3925 pCaps->MaxVolumeExtent = 0;
3927 pCaps->MaxTextureRepeat = 32768;
3928 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
3929 pCaps->MaxVertexW = 1.0f;
3931 pCaps->GuardBandLeft = 0.0f;
3932 pCaps->GuardBandTop = 0.0f;
3933 pCaps->GuardBandRight = 0.0f;
3934 pCaps->GuardBandBottom = 0.0f;
3936 pCaps->ExtentsAdjust = 0.0f;
3938 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
3939 WINED3DSTENCILCAPS_INCRSAT |
3940 WINED3DSTENCILCAPS_INVERT |
3941 WINED3DSTENCILCAPS_KEEP |
3942 WINED3DSTENCILCAPS_REPLACE |
3943 WINED3DSTENCILCAPS_ZERO;
3944 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
3945 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
3946 WINED3DSTENCILCAPS_INCR;
3948 if (GL_SUPPORT(EXT_STENCIL_TWO_SIDE) || GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
3949 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
3952 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
3954 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
3955 pCaps->MaxActiveLights = GL_LIMITS(lights);
3957 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
3958 pCaps->MaxVertexBlendMatrixIndex = 0;
3960 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
3961 pCaps->MaxPointSize = GL_LIMITS(pointsize);
3964 /* FIXME: Add D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
3965 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
3966 WINED3DVTXPCAPS_MATERIALSOURCE7 |
3967 WINED3DVTXPCAPS_POSITIONALLIGHTS |
3968 WINED3DVTXPCAPS_LOCALVIEWER |
3969 WINED3DVTXPCAPS_VERTEXFOG |
3970 WINED3DVTXPCAPS_TEXGEN;
3972 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
3973 pCaps->MaxVertexIndex = 0xFFFFF;
3974 pCaps->MaxStreams = MAX_STREAMS;
3975 pCaps->MaxStreamStride = 1024;
3977 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
3978 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
3979 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
3980 pCaps->MaxNpatchTessellationLevel = 0;
3981 pCaps->MasterAdapterOrdinal = 0;
3982 pCaps->AdapterOrdinalInGroup = 0;
3983 pCaps->NumberOfAdaptersInGroup = 1;
3985 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
3987 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
3988 WINED3DPTFILTERCAPS_MAGFPOINT |
3989 WINED3DPTFILTERCAPS_MINFLINEAR |
3990 WINED3DPTFILTERCAPS_MAGFLINEAR;
3991 pCaps->VertexTextureFilterCaps = 0;
3993 memset(&shader_caps, 0, sizeof(shader_caps));
3994 shader_backend = select_shader_backend(adapter, DeviceType);
3995 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
3997 memset(&fragment_caps, 0, sizeof(fragment_caps));
3998 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
3999 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4001 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4002 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4004 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4005 * Ignore shader model capabilities if disabled in config
4007 if(vs_selected_mode == SHADER_NONE) {
4008 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4009 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4010 pCaps->MaxVertexShaderConst = 0;
4011 } else {
4012 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4013 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4016 if(ps_selected_mode == SHADER_NONE) {
4017 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4018 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4019 pCaps->PixelShader1xMaxValue = 0.0f;
4020 } else {
4021 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4022 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4025 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4026 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4027 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4029 pCaps->VS20Caps = shader_caps.VS20Caps;
4030 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4031 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4032 pCaps->PS20Caps = shader_caps.PS20Caps;
4033 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4034 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4036 /* The following caps are shader specific, but they are things we cannot detect, or which
4037 * are the same among all shader models. So to avoid code duplication set the shader version
4038 * specific, but otherwise constant caps here
4040 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4041 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4042 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4043 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4044 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4045 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
4046 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4048 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4049 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
4050 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
4051 pCaps->VS20Caps.Caps = 0;
4052 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4053 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
4054 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4056 pCaps->MaxVShaderInstructionsExecuted = 65535;
4057 pCaps->MaxVertexShader30InstructionSlots = 0;
4058 } else { /* VS 1.x */
4059 pCaps->VS20Caps.Caps = 0;
4060 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4061 pCaps->VS20Caps.NumTemps = 0;
4062 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4064 pCaps->MaxVShaderInstructionsExecuted = 0;
4065 pCaps->MaxVertexShader30InstructionSlots = 0;
4068 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4069 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4070 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4072 /* 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 */
4073 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4074 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4075 WINED3DPS20CAPS_PREDICATION |
4076 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4077 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4078 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4079 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
4080 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4081 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4083 pCaps->MaxPShaderInstructionsExecuted = 65535;
4084 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
4085 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
4086 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4087 pCaps->PS20Caps.Caps = 0;
4088 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4089 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
4090 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4091 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4093 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4094 pCaps->MaxPixelShader30InstructionSlots = 0;
4095 } else { /* PS 1.x */
4096 pCaps->PS20Caps.Caps = 0;
4097 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4098 pCaps->PS20Caps.NumTemps = 0;
4099 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4100 pCaps->PS20Caps.NumInstructionSlots = 0;
4102 pCaps->MaxPShaderInstructionsExecuted = 0;
4103 pCaps->MaxPixelShader30InstructionSlots = 0;
4106 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4107 /* OpenGL supports all the formats below, perhaps not always
4108 * without conversion, but it supports them.
4109 * Further GLSL doesn't seem to have an official unsigned type so
4110 * don't advertise it yet as I'm not sure how we handle it.
4111 * We might need to add some clamping in the shader engine to
4112 * support it.
4113 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4114 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4115 WINED3DDTCAPS_UBYTE4N |
4116 WINED3DDTCAPS_SHORT2N |
4117 WINED3DDTCAPS_SHORT4N;
4118 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
4119 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4120 WINED3DDTCAPS_FLOAT16_4;
4122 } else
4123 pCaps->DeclTypes = 0;
4125 /* Set DirectDraw helper Caps */
4126 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4127 WINEDDCKEYCAPS_SRCBLT;
4128 fx_caps = WINEDDFXCAPS_BLTALPHA |
4129 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4130 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4131 WINEDDFXCAPS_BLTROTATION90 |
4132 WINEDDFXCAPS_BLTSHRINKX |
4133 WINEDDFXCAPS_BLTSHRINKXN |
4134 WINEDDFXCAPS_BLTSHRINKY |
4135 WINEDDFXCAPS_BLTSHRINKXN |
4136 WINEDDFXCAPS_BLTSTRETCHX |
4137 WINEDDFXCAPS_BLTSTRETCHXN |
4138 WINEDDFXCAPS_BLTSTRETCHY |
4139 WINEDDFXCAPS_BLTSTRETCHYN;
4140 blit_caps = WINEDDCAPS_BLT |
4141 WINEDDCAPS_BLTCOLORFILL |
4142 WINEDDCAPS_BLTDEPTHFILL |
4143 WINEDDCAPS_BLTSTRETCH |
4144 WINEDDCAPS_CANBLTSYSMEM |
4145 WINEDDCAPS_CANCLIP |
4146 WINEDDCAPS_CANCLIPSTRETCHED |
4147 WINEDDCAPS_COLORKEY |
4148 WINEDDCAPS_COLORKEYHWASSIST |
4149 WINEDDCAPS_ALIGNBOUNDARYSRC;
4151 /* Fill the ddraw caps structure */
4152 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4153 WINEDDCAPS_PALETTE |
4154 blit_caps;
4155 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4156 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4157 WINEDDCAPS2_PRIMARYGAMMA |
4158 WINEDDCAPS2_WIDESURFACES |
4159 WINEDDCAPS2_CANRENDERWINDOWED;
4160 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4161 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4162 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4163 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4164 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4165 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4166 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4167 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4168 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4170 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4171 WINEDDSCAPS_BACKBUFFER |
4172 WINEDDSCAPS_FLIP |
4173 WINEDDSCAPS_FRONTBUFFER |
4174 WINEDDSCAPS_OFFSCREENPLAIN |
4175 WINEDDSCAPS_PALETTE |
4176 WINEDDSCAPS_PRIMARYSURFACE |
4177 WINEDDSCAPS_SYSTEMMEMORY |
4178 WINEDDSCAPS_VIDEOMEMORY |
4179 WINEDDSCAPS_VISIBLE;
4180 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4182 /* Set D3D caps if OpenGL is available. */
4183 if (adapter->opengl)
4185 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4186 WINEDDSCAPS_MIPMAP |
4187 WINEDDSCAPS_TEXTURE |
4188 WINEDDSCAPS_ZBUFFER;
4189 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4192 return WINED3D_OK;
4195 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
4196 and fields being inserted in the middle, a new structure is used in place */
4197 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
4198 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
4199 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
4201 IWineD3DDeviceImpl *object = NULL;
4202 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4203 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
4204 WINED3DDISPLAYMODE mode;
4205 const struct fragment_pipeline *frag_pipeline = NULL;
4206 int i;
4207 struct fragment_caps ffp_caps;
4208 struct shader_caps shader_caps;
4209 HRESULT hr;
4211 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4212 * number and create a device without a 3D adapter for 2D only operation.
4214 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4215 return WINED3DERR_INVALIDCALL;
4218 /* Create a WineD3DDevice object */
4219 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
4220 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4221 TRACE("Created WineD3DDevice object @ %p\n", object);
4222 if (NULL == object) {
4223 return WINED3DERR_OUTOFVIDEOMEMORY;
4226 /* Set up initial COM information */
4227 object->lpVtbl = &IWineD3DDevice_Vtbl;
4228 object->ref = 1;
4229 object->wineD3D = iface;
4230 object->adapter = This->adapter_count ? adapter : NULL;
4231 IWineD3D_AddRef(object->wineD3D);
4232 object->parent = parent;
4233 object->device_parent = device_parent;
4234 list_init(&object->resources);
4235 list_init(&object->shaders);
4237 if(This->dxVersion == 7) {
4238 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
4239 } else {
4240 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4242 object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4244 /* Set the state up as invalid until the device is fully created */
4245 object->state = WINED3DERR_DRIVERINTERNALERROR;
4247 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
4248 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4250 /* Save the creation parameters */
4251 object->createParms.AdapterOrdinal = Adapter;
4252 object->createParms.DeviceType = DeviceType;
4253 object->createParms.hFocusWindow = hFocusWindow;
4254 object->createParms.BehaviorFlags = BehaviourFlags;
4256 /* Initialize other useful values */
4257 object->adapterNo = Adapter;
4258 object->devType = DeviceType;
4260 select_shader_mode(&adapter->gl_info, DeviceType,
4261 &object->ps_selected_mode, &object->vs_selected_mode);
4262 object->shader_backend = select_shader_backend(adapter, DeviceType);
4264 memset(&shader_caps, 0, sizeof(shader_caps));
4265 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4266 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
4267 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
4268 object->vs_clipping = shader_caps.VSClipping;
4270 memset(&ffp_caps, 0, sizeof(ffp_caps));
4271 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4272 object->frag_pipe = frag_pipeline;
4273 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
4274 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
4275 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
4276 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
4277 ffp_vertexstate_template, frag_pipeline, misc_state_template);
4279 if (FAILED(hr)) {
4280 IWineD3D_Release(object->wineD3D);
4281 HeapFree(GetProcessHeap(), 0, object);
4283 return hr;
4286 object->blitter = select_blit_implementation(adapter, DeviceType);
4288 /* set the state of the device to valid */
4289 object->state = WINED3D_OK;
4291 /* Get the initial screen setup for ddraw */
4292 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4294 object->ddraw_width = mode.Width;
4295 object->ddraw_height = mode.Height;
4296 object->ddraw_format = mode.Format;
4298 for(i = 0; i < PATCHMAP_SIZE; i++) {
4299 list_init(&object->patches[i]);
4302 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4304 return WINED3D_OK;
4307 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4308 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4309 IUnknown_AddRef(This->parent);
4310 *pParent = This->parent;
4311 return WINED3D_OK;
4314 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
4315 IUnknown* surfaceParent;
4316 TRACE("(%p) call back\n", pSurface);
4318 /* Now, release the parent, which will take care of cleaning up the surface for us */
4319 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
4320 IUnknown_Release(surfaceParent);
4321 return IUnknown_Release(surfaceParent);
4324 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
4325 IUnknown* volumeParent;
4326 TRACE("(%p) call back\n", pVolume);
4328 /* Now, release the parent, which will take care of cleaning up the volume for us */
4329 IWineD3DVolume_GetParent(pVolume, &volumeParent);
4330 IUnknown_Release(volumeParent);
4331 return IUnknown_Release(volumeParent);
4334 static void WINE_GLAPI invalid_func(const void *data)
4336 ERR("Invalid vertex attribute function called\n");
4337 DebugBreak();
4340 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4342 ERR("Invalid texcoord function called\n");
4343 DebugBreak();
4346 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4347 * the extension detection and are used in drawStridedSlow
4349 static void WINE_GLAPI position_d3dcolor(const void *data)
4351 DWORD pos = *((const DWORD *)data);
4353 FIXME("Add a test for fixed function position from d3dcolor type\n");
4354 glVertex4s(D3DCOLOR_B_R(pos),
4355 D3DCOLOR_B_G(pos),
4356 D3DCOLOR_B_B(pos),
4357 D3DCOLOR_B_A(pos));
4360 static void WINE_GLAPI position_float4(const void *data)
4362 const GLfloat *pos = data;
4364 if (pos[3] != 0.0f && pos[3] != 1.0f)
4366 float w = 1.0f / pos[3];
4368 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4370 else
4372 glVertex3fv(pos);
4376 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4378 DWORD diffuseColor = *((const DWORD *)data);
4380 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4381 D3DCOLOR_B_G(diffuseColor),
4382 D3DCOLOR_B_B(diffuseColor),
4383 D3DCOLOR_B_A(diffuseColor));
4386 static void WINE_GLAPI specular_d3dcolor(const void *data)
4388 DWORD specularColor = *((const DWORD *)data);
4389 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4390 D3DCOLOR_B_G(specularColor),
4391 D3DCOLOR_B_B(specularColor)};
4393 specular_func_3ubv(d);
4396 static void WINE_GLAPI warn_no_specular_func(const void *data)
4398 WARN("GL_EXT_secondary_color not supported\n");
4401 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4403 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4404 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4405 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4406 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4407 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4408 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4409 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4410 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4411 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4412 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4413 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4414 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4415 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4416 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4417 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4418 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4419 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4421 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4422 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4423 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4424 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4425 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4426 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4427 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4428 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4429 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4430 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4431 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4432 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4433 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4434 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4435 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4436 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4437 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4439 /* No 4 component entry points here */
4440 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4441 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4442 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4443 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4444 } else {
4445 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4447 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4448 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4449 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4450 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4451 } else {
4452 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4454 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4455 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4456 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4457 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4458 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4459 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4460 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4461 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4462 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4463 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4464 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4465 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4467 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4468 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4470 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4471 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4472 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4473 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4474 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4475 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4476 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4477 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4478 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4479 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4480 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4481 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4482 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4483 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4484 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4485 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4486 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4488 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4489 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4490 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4491 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4492 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4493 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4494 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4495 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4496 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4497 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4498 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4499 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4500 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4501 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4502 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4503 if (GL_SUPPORT(NV_HALF_FLOAT))
4505 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4506 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4507 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4508 } else {
4509 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4510 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4514 BOOL InitAdapters(IWineD3DImpl *This)
4516 static HMODULE mod_gl;
4517 BOOL ret;
4518 int ps_selected_mode, vs_selected_mode;
4520 /* No need to hold any lock. The calling library makes sure only one thread calls
4521 * wined3d simultaneously
4524 TRACE("Initializing adapters\n");
4526 if(!mod_gl) {
4527 #ifdef USE_WIN32_OPENGL
4528 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4529 mod_gl = LoadLibraryA("opengl32.dll");
4530 if(!mod_gl) {
4531 ERR("Can't load opengl32.dll!\n");
4532 goto nogl_adapter;
4534 #else
4535 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4536 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4537 mod_gl = GetModuleHandleA("gdi32.dll");
4538 #endif
4541 /* Load WGL core functions from opengl32.dll */
4542 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4543 WGL_FUNCS_GEN;
4544 #undef USE_WGL_FUNC
4546 if(!pwglGetProcAddress) {
4547 ERR("Unable to load wglGetProcAddress!\n");
4548 goto nogl_adapter;
4551 /* Dynamically load all GL core functions */
4552 GL_FUNCS_GEN;
4553 #undef USE_GL_FUNC
4555 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4556 * otherwise because we have to use winex11.drv's override
4558 #ifdef USE_WIN32_OPENGL
4559 wglFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4560 wglFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4561 #else
4562 wglFinish = (void*)pwglGetProcAddress("wglFinish");
4563 wglFlush = (void*)pwglGetProcAddress("wglFlush");
4564 #endif
4566 glEnableWINE = glEnable;
4567 glDisableWINE = glDisable;
4569 /* For now only one default adapter */
4571 struct WineD3DAdapter *adapter = &This->adapters[0];
4572 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4573 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4574 int iPixelFormat;
4575 int res;
4576 int i;
4577 WineD3D_PixelFormat *cfgs;
4578 DISPLAY_DEVICEW DisplayDevice;
4579 HDC hdc;
4581 TRACE("Initializing default adapter\n");
4582 adapter->num = 0;
4583 adapter->monitorPoint.x = -1;
4584 adapter->monitorPoint.y = -1;
4586 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4588 ERR("Failed to get a gl context for default adapter\n");
4589 goto nogl_adapter;
4592 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4593 if(!ret) {
4594 ERR("Failed to initialize gl caps for default adapter\n");
4595 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4596 goto nogl_adapter;
4598 ret = initPixelFormats(&adapter->gl_info);
4599 if(!ret) {
4600 ERR("Failed to init gl formats\n");
4601 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4602 goto nogl_adapter;
4605 hdc = fake_gl_ctx.dc;
4607 adapter->driver = "Display";
4608 adapter->description = "Direct3D HAL";
4610 /* Use the VideoRamSize registry setting when set */
4611 if(wined3d_settings.emulated_textureram)
4612 adapter->TextureRam = wined3d_settings.emulated_textureram;
4613 else
4614 adapter->TextureRam = adapter->gl_info.vidmem;
4615 adapter->UsedTextureRam = 0;
4616 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4618 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4619 DisplayDevice.cb = sizeof(DisplayDevice);
4620 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4621 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4622 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4624 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4626 int attribute;
4627 int attribs[10];
4628 int values[10];
4629 int nAttribs = 0;
4631 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4632 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4634 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4635 cfgs = adapter->cfgs;
4636 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4637 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4638 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4639 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4640 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4641 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4642 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4643 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4644 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4645 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4647 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4649 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4651 if(!res)
4652 continue;
4654 /* Cache the pixel format */
4655 cfgs->iPixelFormat = iPixelFormat;
4656 cfgs->redSize = values[0];
4657 cfgs->greenSize = values[1];
4658 cfgs->blueSize = values[2];
4659 cfgs->alphaSize = values[3];
4660 cfgs->depthSize = values[4];
4661 cfgs->stencilSize = values[5];
4662 cfgs->windowDrawable = values[6];
4663 cfgs->iPixelType = values[7];
4664 cfgs->doubleBuffer = values[8];
4665 cfgs->auxBuffers = values[9];
4667 cfgs->pbufferDrawable = FALSE;
4668 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4669 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4670 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4671 int value;
4672 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4673 cfgs->pbufferDrawable = value;
4676 cfgs->numSamples = 0;
4677 /* Check multisample support */
4678 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4679 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4680 int value[2];
4681 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4682 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4683 * value[1] = number of multi sample buffers*/
4684 if(value[0])
4685 cfgs->numSamples = value[1];
4689 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);
4690 cfgs++;
4693 else
4695 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4696 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4697 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4699 cfgs = adapter->cfgs;
4700 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4702 PIXELFORMATDESCRIPTOR ppfd;
4704 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4705 if(!res)
4706 continue;
4708 /* We only want HW acceleration using an OpenGL ICD driver.
4709 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4710 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4712 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4714 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4715 continue;
4718 cfgs->iPixelFormat = iPixelFormat;
4719 cfgs->redSize = ppfd.cRedBits;
4720 cfgs->greenSize = ppfd.cGreenBits;
4721 cfgs->blueSize = ppfd.cBlueBits;
4722 cfgs->alphaSize = ppfd.cAlphaBits;
4723 cfgs->depthSize = ppfd.cDepthBits;
4724 cfgs->stencilSize = ppfd.cStencilBits;
4725 cfgs->pbufferDrawable = 0;
4726 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4727 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4728 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4729 cfgs->auxBuffers = ppfd.cAuxBuffers;
4730 cfgs->numSamples = 0;
4732 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);
4733 cfgs++;
4734 adapter->nCfgs++;
4737 /* 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 */
4738 if(!adapter->nCfgs)
4740 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4742 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4743 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4744 goto nogl_adapter;
4748 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4749 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4750 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4751 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4752 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4753 * driver is allowed to consume more bits EXCEPT for stencil bits.
4755 * Mark an adapter with this broken stencil behavior.
4757 adapter->brokenStencil = TRUE;
4758 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4760 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4761 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4762 adapter->brokenStencil = FALSE;
4763 break;
4767 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4769 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4770 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4771 fillGLAttribFuncs(&adapter->gl_info);
4772 adapter->opengl = TRUE;
4774 This->adapter_count = 1;
4775 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4777 return TRUE;
4779 nogl_adapter:
4780 /* Initialize an adapter for ddraw-only memory counting */
4781 memset(This->adapters, 0, sizeof(This->adapters));
4782 This->adapters[0].num = 0;
4783 This->adapters[0].opengl = FALSE;
4784 This->adapters[0].monitorPoint.x = -1;
4785 This->adapters[0].monitorPoint.y = -1;
4787 This->adapters[0].driver = "Display";
4788 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4789 if(wined3d_settings.emulated_textureram) {
4790 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4791 } else {
4792 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4795 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4797 This->adapter_count = 1;
4798 return FALSE;
4801 /**********************************************************
4802 * IWineD3D VTbl follows
4803 **********************************************************/
4805 const IWineD3DVtbl IWineD3D_Vtbl =
4807 /* IUnknown */
4808 IWineD3DImpl_QueryInterface,
4809 IWineD3DImpl_AddRef,
4810 IWineD3DImpl_Release,
4811 /* IWineD3D */
4812 IWineD3DImpl_GetParent,
4813 IWineD3DImpl_GetAdapterCount,
4814 IWineD3DImpl_RegisterSoftwareDevice,
4815 IWineD3DImpl_GetAdapterMonitor,
4816 IWineD3DImpl_GetAdapterModeCount,
4817 IWineD3DImpl_EnumAdapterModes,
4818 IWineD3DImpl_GetAdapterDisplayMode,
4819 IWineD3DImpl_GetAdapterIdentifier,
4820 IWineD3DImpl_CheckDeviceMultiSampleType,
4821 IWineD3DImpl_CheckDepthStencilMatch,
4822 IWineD3DImpl_CheckDeviceType,
4823 IWineD3DImpl_CheckDeviceFormat,
4824 IWineD3DImpl_CheckDeviceFormatConversion,
4825 IWineD3DImpl_GetDeviceCaps,
4826 IWineD3DImpl_CreateDevice