push 6377a023768d7480eb1b17e57456824888936b43
[wine/hacks.git] / dlls / wined3d / directx.c
blobe6fb1c73d5cdb24bede8ce7ecf3735df55687366
1 /*
2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
31 #define GLINFO_LOCATION (*gl_info)
33 /* The d3d device ID */
34 static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
36 /* Extension detection */
37 static const struct {
38 const char *extension_string;
39 GL_SupportedExt extension;
40 DWORD version;
41 } EXTENSION_MAP[] = {
42 /* APPLE */
43 {"GL_APPLE_client_storage", APPLE_CLIENT_STORAGE, 0 },
44 {"GL_APPLE_fence", APPLE_FENCE, 0 },
45 {"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
46 {"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
47 {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
49 /* ATI */
50 {"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
51 {"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
52 {"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
53 {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
54 {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
56 /* ARB */
57 {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
58 {"GL_ARB_depth_buffer_float", ARB_DEPTH_BUFFER_FLOAT, 0 },
59 {"GL_ARB_depth_texture", ARB_DEPTH_TEXTURE, 0 },
60 {"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
61 {"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
62 {"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
63 {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
64 {"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
65 {"GL_ARB_imaging", ARB_IMAGING, 0 },
66 {"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
67 {"GL_ARB_multitexture", ARB_MULTITEXTURE, 0 },
68 {"GL_ARB_occlusion_query", ARB_OCCLUSION_QUERY, 0 },
69 {"GL_ARB_pixel_buffer_object", ARB_PIXEL_BUFFER_OBJECT, 0 },
70 {"GL_ARB_point_parameters", ARB_POINT_PARAMETERS, 0 },
71 {"GL_ARB_point_sprite", ARB_POINT_SPRITE, 0 },
72 {"GL_ARB_texture_border_clamp", ARB_TEXTURE_BORDER_CLAMP, 0 },
73 {"GL_ARB_texture_compression", ARB_TEXTURE_COMPRESSION, 0 },
74 {"GL_ARB_texture_cube_map", ARB_TEXTURE_CUBE_MAP, 0 },
75 {"GL_ARB_texture_env_add", ARB_TEXTURE_ENV_ADD, 0 },
76 {"GL_ARB_texture_env_combine", ARB_TEXTURE_ENV_COMBINE, 0 },
77 {"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
78 {"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
79 {"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
80 {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
81 {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
82 {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
83 {"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
84 {"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
85 {"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
86 {"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
87 {"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
88 {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
89 {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
91 /* EXT */
92 {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
93 {"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
94 {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
95 {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
96 {"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
97 {"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
98 {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
99 {"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
100 {"GL_EXT_packed_depth_stencil", EXT_PACKED_DEPTH_STENCIL, 0 },
101 {"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
102 {"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
103 {"GL_EXT_secondary_color", EXT_SECONDARY_COLOR, 0 },
104 {"GL_EXT_stencil_two_side", EXT_STENCIL_TWO_SIDE, 0 },
105 {"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
106 {"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
107 {"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
108 {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
109 {"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
110 {"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
111 {"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
112 {"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
113 {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
114 {"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
115 {"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
116 {"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
117 {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
118 {"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
119 {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
121 /* NV */
122 {"GL_NV_half_float", NV_HALF_FLOAT, 0 },
123 {"GL_NV_fence", NV_FENCE, 0 },
124 {"GL_NV_fog_distance", NV_FOG_DISTANCE, 0 },
125 {"GL_NV_fragment_program", NV_FRAGMENT_PROGRAM, 0 },
126 {"GL_NV_fragment_program2", NV_FRAGMENT_PROGRAM2, 0 },
127 {"GL_NV_register_combiners", NV_REGISTER_COMBINERS, 0 },
128 {"GL_NV_register_combiners2", NV_REGISTER_COMBINERS2, 0 },
129 {"GL_NV_texgen_reflection", NV_TEXGEN_REFLECTION, 0 },
130 {"GL_NV_texture_env_combine4", NV_TEXTURE_ENV_COMBINE4, 0 },
131 {"GL_NV_texture_shader", NV_TEXTURE_SHADER, 0 },
132 {"GL_NV_texture_shader2", NV_TEXTURE_SHADER2, 0 },
133 {"GL_NV_texture_shader3", NV_TEXTURE_SHADER3, 0 },
134 {"GL_NV_occlusion_query", NV_OCCLUSION_QUERY, 0 },
135 {"GL_NV_vertex_program", NV_VERTEX_PROGRAM, 0 },
136 {"GL_NV_vertex_program1_1", NV_VERTEX_PROGRAM1_1, 0 },
137 {"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
138 {"GL_NV_vertex_program2_option", NV_VERTEX_PROGRAM2_OPTION, 0 },
139 {"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
140 {"GL_NV_fragment_program_option", NV_FRAGMENT_PROGRAM_OPTION, 0 },
141 {"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
142 {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
144 /* SGI */
145 {"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
148 /**********************************************************
149 * Utility functions follow
150 **********************************************************/
152 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
153 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
154 WINED3DDEVTYPE DeviceType);
155 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
156 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
158 /* lookup tables */
159 const int minLookup[MAX_LOOKUPS] =
161 WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
164 const int maxLookup[MAX_LOOKUPS] =
166 WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
169 DWORD *stateLookup[MAX_LOOKUPS];
171 struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
172 const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
174 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
175 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
176 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
177 {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
180 GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
181 const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
183 GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
186 /* drawStridedSlow attributes */
187 glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
188 glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
189 glAttribFunc specular_func_3ubv;
190 glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
191 glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
192 glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
195 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
196 * i.e., there is no GL Context - Get a default rendering context to enable the
197 * function query some info from GL.
200 struct wined3d_fake_gl_ctx
202 HDC dc;
203 HWND wnd;
204 HGLRC gl_ctx;
207 static void WineD3D_ReleaseFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
209 TRACE_(d3d_caps)("Destroying fake GL context.\n");
211 if (!pwglMakeCurrent(NULL, NULL))
213 ERR_(d3d_caps)("Failed to disable fake GL context.\n");
216 if (!pwglDeleteContext(ctx->gl_ctx))
218 DWORD err = GetLastError();
219 ERR("wglDeleteContext(%p) failed, last error %#x.\n", ctx->gl_ctx, err);
222 ReleaseDC(ctx->wnd, ctx->dc);
223 DestroyWindow(ctx->wnd);
226 static BOOL WineD3D_CreateFakeGLContext(struct wined3d_fake_gl_ctx *ctx)
228 PIXELFORMATDESCRIPTOR pfd;
229 int iPixelFormat;
231 TRACE("getting context...\n");
233 /* We need a fake window as a hdc retrieved using GetDC(0) can't be used for much GL purposes. */
234 ctx->wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
235 WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL);
236 if (!ctx->wnd)
238 ERR_(d3d_caps)("Failed to create a window.\n");
239 goto fail;
242 ctx->dc = GetDC(ctx->wnd);
243 if (!ctx->dc)
245 ERR_(d3d_caps)("Failed to get a DC.\n");
246 goto fail;
249 /* PixelFormat selection */
250 ZeroMemory(&pfd, sizeof(pfd));
251 pfd.nSize = sizeof(pfd);
252 pfd.nVersion = 1;
253 pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW; /* PFD_GENERIC_ACCELERATED */
254 pfd.iPixelType = PFD_TYPE_RGBA;
255 pfd.cColorBits = 32;
256 pfd.iLayerType = PFD_MAIN_PLANE;
258 iPixelFormat = ChoosePixelFormat(ctx->dc, &pfd);
259 if (!iPixelFormat)
261 /* If this happens something is very wrong as ChoosePixelFormat barely fails. */
262 ERR_(d3d_caps)("Can't find a suitable iPixelFormat.\n");
263 goto fail;
265 DescribePixelFormat(ctx->dc, iPixelFormat, sizeof(pfd), &pfd);
266 SetPixelFormat(ctx->dc, iPixelFormat, &pfd);
268 /* Create a GL context. */
269 ctx->gl_ctx = pwglCreateContext(ctx->dc);
270 if (!ctx->gl_ctx)
272 WARN_(d3d_caps)("Error creating default context for capabilities initialization.\n");
273 goto fail;
276 /* Make it the current GL context. */
277 if (!context_set_current(NULL))
279 ERR_(d3d_caps)("Failed to clear current D3D context.\n");
282 if (!pwglMakeCurrent(ctx->dc, ctx->gl_ctx))
284 ERR_(d3d_caps)("Failed to make fake GL context current.\n");
285 goto fail;
288 return TRUE;
290 fail:
291 if (ctx->gl_ctx) pwglDeleteContext(ctx->gl_ctx);
292 ctx->gl_ctx = NULL;
293 if (ctx->dc) ReleaseDC(ctx->wnd, ctx->dc);
294 ctx->dc = NULL;
295 if (ctx->wnd) DestroyWindow(ctx->wnd);
296 ctx->wnd = NULL;
298 return FALSE;
301 /* Adjust the amount of used texture memory */
302 long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
303 struct WineD3DAdapter *adapter = D3DDevice->adapter;
305 adapter->UsedTextureRam += glram;
306 TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
307 return adapter->UsedTextureRam;
310 /**********************************************************
311 * IUnknown parts follows
312 **********************************************************/
314 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
316 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
318 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
319 if (IsEqualGUID(riid, &IID_IUnknown)
320 || IsEqualGUID(riid, &IID_IWineD3DBase)
321 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
322 IUnknown_AddRef(iface);
323 *ppobj = This;
324 return S_OK;
326 *ppobj = NULL;
327 return E_NOINTERFACE;
330 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
331 IWineD3DImpl *This = (IWineD3DImpl *)iface;
332 ULONG refCount = InterlockedIncrement(&This->ref);
334 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
335 return refCount;
338 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
339 IWineD3DImpl *This = (IWineD3DImpl *)iface;
340 ULONG ref;
341 TRACE("(%p) : Releasing from %d\n", This, This->ref);
342 ref = InterlockedDecrement(&This->ref);
343 if (ref == 0) {
344 unsigned int i;
346 for (i = 0; i < This->adapter_count; ++i)
348 HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
350 HeapFree(GetProcessHeap(), 0, This);
353 return ref;
356 /* Set the shader type for this device, depending on the given capabilities,
357 * the device type, and the user preferences in wined3d_settings */
359 static void select_shader_mode(const struct wined3d_gl_info *gl_info,
360 WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
362 if (wined3d_settings.vs_mode == VS_NONE) {
363 *vs_selected = SHADER_NONE;
364 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
365 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
366 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
367 * shaders only on this card. */
368 if(gl_info->vs_nv_version && gl_info->vs_nv_version < VS_VERSION_20)
369 *vs_selected = SHADER_ARB;
370 else
371 *vs_selected = SHADER_GLSL;
372 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
373 *vs_selected = SHADER_ARB;
374 } else {
375 *vs_selected = SHADER_NONE;
378 if (wined3d_settings.ps_mode == PS_NONE) {
379 *ps_selected = SHADER_NONE;
380 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
381 *ps_selected = SHADER_GLSL;
382 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
383 *ps_selected = SHADER_ARB;
384 } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
385 *ps_selected = SHADER_ATI;
386 } else {
387 *ps_selected = SHADER_NONE;
391 /** Select the number of report maximum shader constants based on the selected shader modes */
392 static void select_shader_max_constants(int ps_selected_mode, int vs_selected_mode, struct wined3d_gl_info *gl_info)
394 switch (vs_selected_mode) {
395 case SHADER_GLSL:
396 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
397 break;
398 case SHADER_ARB:
399 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
400 break;
401 default:
402 gl_info->max_vshader_constantsF = 0;
403 break;
406 switch (ps_selected_mode) {
407 case SHADER_GLSL:
408 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
409 break;
410 case SHADER_ARB:
411 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
412 break;
413 default:
414 gl_info->max_pshader_constantsF = 0;
415 break;
419 /**********************************************************
420 * IWineD3D parts follows
421 **********************************************************/
423 /* GL locking is done by the caller */
424 static inline BOOL test_arb_vs_offset_limit(const struct wined3d_gl_info *gl_info)
426 GLuint prog;
427 BOOL ret = FALSE;
428 const char *testcode =
429 "!!ARBvp1.0\n"
430 "PARAM C[66] = { program.env[0..65] };\n"
431 "ADDRESS A0;"
432 "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
433 "ARL A0.x, zero.x;\n"
434 "MOV result.position, C[A0.x + 65];\n"
435 "END\n";
437 while(glGetError());
438 GL_EXTCALL(glGenProgramsARB(1, &prog));
439 if(!prog) {
440 ERR("Failed to create an ARB offset limit test program\n");
442 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog));
443 GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
444 strlen(testcode), testcode));
445 if(glGetError() != 0) {
446 TRACE("OpenGL implementation does not allow indirect addressing offsets > 63\n");
447 TRACE("error: %s\n", debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
448 ret = TRUE;
449 } else TRACE("OpenGL implementation allows offsets > 63\n");
451 GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, 0));
452 GL_EXTCALL(glDeleteProgramsARB(1, &prog));
453 checkGLcall("ARB vp offset limit test cleanup");
455 return ret;
458 static DWORD ver_for_ext(GL_SupportedExt ext)
460 unsigned int i;
461 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
462 if(EXTENSION_MAP[i].extension == ext) {
463 return EXTENSION_MAP[i].version;
466 return 0;
469 static BOOL match_ati_r300_to_500(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
471 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
472 if (gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
473 if (gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
474 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
475 return FALSE;
478 static BOOL match_geforce5(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
480 if (gl_info->gl_vendor == VENDOR_NVIDIA)
482 if (gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600)
484 return TRUE;
487 return FALSE;
490 static BOOL match_apple(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
492 /* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
493 * the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
494 * detect the Apple OpenGL implementation to apply some extension fixups afterwards.
496 * Detecting this isn't really easy. The vendor string doesn't mention Apple. Compile-time checks
497 * aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
498 * So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
499 * like client storage might be supported on other implementations too, but GL_APPLE_flush_render
500 * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
501 * the chance that other implementations support them is rather small since Win32 QuickTime uses
502 * DirectDraw, not OpenGL. */
503 if (gl_info->supported[APPLE_FENCE]
504 && gl_info->supported[APPLE_CLIENT_STORAGE]
505 && gl_info->supported[APPLE_FLUSH_RENDER]
506 && gl_info->supported[APPLE_YCBCR_422])
508 TRACE_(d3d_caps)("GL_APPLE_fence, GL_APPLE_client_storage, GL_APPLE_flush_render and GL_ycbcr_422 are supported.\n");
509 TRACE_(d3d_caps)("Activating MacOS fixups.\n");
510 return TRUE;
512 else
514 TRACE_(d3d_caps)("Apple extensions are not supported.\n");
515 TRACE_(d3d_caps)("Not activating MacOS fixups.\n");
516 return FALSE;
520 /* Context activation is done by the caller. */
521 static void test_pbo_functionality(struct wined3d_gl_info *gl_info)
523 /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
524 * but glTexSubImage from a PBO fails miserably, with the first line repeated over
525 * all the texture. This function detects this bug by its symptom and disables PBOs
526 * if the test fails.
528 * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
529 * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
530 * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
531 * read back is compared to the original. If they are equal PBOs are assumed to work,
532 * otherwise the PBO extension is disabled. */
533 GLuint texture, pbo;
534 static const unsigned int pattern[] =
536 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
537 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
538 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
539 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
541 unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
543 /* No PBO -> No point in testing them. */
544 if (!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) return;
546 ENTER_GL();
548 while (glGetError());
549 glGenTextures(1, &texture);
550 glBindTexture(GL_TEXTURE_2D, texture);
552 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
553 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
554 checkGLcall("Specifying the PBO test texture");
556 GL_EXTCALL(glGenBuffersARB(1, &pbo));
557 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
558 GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
559 checkGLcall("Specifying the PBO test pbo");
561 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
562 checkGLcall("Loading the PBO test texture");
564 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
565 glFinish(); /* just to be sure */
567 memset(check, 0, sizeof(check));
568 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
569 checkGLcall("Reading back the PBO test texture");
571 glDeleteTextures(1, &texture);
572 GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
573 checkGLcall("PBO test cleanup");
575 LEAVE_GL();
577 if (memcmp(check, pattern, sizeof(check)))
579 WARN_(d3d_caps)("PBO test failed, read back data doesn't match original.\n");
580 WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance.\n");
581 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
583 else
585 TRACE_(d3d_caps)("PBO test successful.\n");
589 static BOOL match_apple_intel(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
591 return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info, gl_renderer);
594 static BOOL match_apple_nonr500ati(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
596 if (!match_apple(gl_info, gl_renderer)) return FALSE;
597 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
598 if (gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
599 return TRUE;
602 static BOOL match_fglrx(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
604 if (gl_info->gl_vendor != VENDOR_ATI) return FALSE;
605 if (match_apple(gl_info, gl_renderer)) return FALSE;
606 if (strstr(gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers. */
607 return TRUE;
610 static BOOL match_dx10_capable(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
612 /* DX9 cards support 40 single float varyings in hardware, most drivers report 32. ATI misreports
613 * 44 varyings. So assume that if we have more than 44 varyings we have a dx10 card.
614 * This detection is for the gl_ClipPos varying quirk. If a d3d9 card really supports more than 44
615 * varyings and we subtract one in dx9 shaders its not going to hurt us because the dx9 limit is
616 * hardcoded
618 * dx10 cards usually have 64 varyings */
619 return gl_info->max_glsl_varyings > 44;
622 /* A GL context is provided by the caller */
623 static BOOL match_allows_spec_alpha(const struct wined3d_gl_info *gl_info, const char *gl_renderer)
625 GLenum error;
626 DWORD data[16];
628 if(!GL_SUPPORT(EXT_SECONDARY_COLOR)) return FALSE;
630 ENTER_GL();
631 while(glGetError());
632 GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE, 4, data);
633 error = glGetError();
634 LEAVE_GL();
636 if(error == GL_NO_ERROR)
638 TRACE("GL Implementation accepts 4 component specular color pointers\n");
639 return TRUE;
641 else
643 TRACE("GL implementation does not accept 4 component specular colors, error %s\n",
644 debug_glerror(error));
645 return FALSE;
649 static void quirk_arb_constants(struct wined3d_gl_info *gl_info)
651 TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL.\n", gl_info->vs_arb_constantsF);
652 gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
653 TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL.\n", gl_info->ps_arb_constantsF);
654 gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
657 static void quirk_apple_glsl_constants(struct wined3d_gl_info *gl_info)
659 quirk_arb_constants(gl_info);
660 /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
661 * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
662 * allow 48 different offsets or other helper immediate values. */
663 TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use.\n");
664 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
667 /* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
668 * on more than one texture unit. This means that the d3d9 visual point size test will cause a
669 * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
670 * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
671 * most games, but avoids the crash
673 * A more sophisticated way would be to find all units that need texture coordinates and enable
674 * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
675 * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
677 * Note that disabling the extension entirely does not gain predictability because there is no point
678 * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension. */
679 static void quirk_one_point_sprite(struct wined3d_gl_info *gl_info)
681 if (gl_info->supported[ARB_POINT_SPRITE])
683 TRACE("Limiting point sprites to one texture unit.\n");
684 gl_info->max_point_sprite_units = 1;
688 static void quirk_ati_dx9(struct wined3d_gl_info *gl_info)
690 quirk_arb_constants(gl_info);
692 /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
693 * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
694 * If real NP2 textures are used, the driver falls back to software. We could just remove the
695 * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
696 * due to the non-normalized texture coordinates. Thus set an internal extension flag,
697 * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
698 * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
700 * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
701 * has this extension promoted to core. The extension loading code sets this extension supported
702 * due to that, so this code works on fglrx as well. */
703 TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing.\n");
704 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
705 gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
707 /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
708 * it is generally more efficient. Reserve just 8 constants. */
709 TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use.\n");
710 gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
713 static void quirk_no_np2(struct wined3d_gl_info *gl_info)
715 /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
716 * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
717 * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
718 * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
719 * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
720 * We therefore completely remove ARB_tex_npot from the list of supported extensions.
722 * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
723 * triggering the software fallback. There is not much we can do here apart from disabling the
724 * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
725 * in IWineD3DImpl_FillGLCaps).
726 * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
727 * post-processing effects in the game "Max Payne 2").
728 * The behaviour can be verified through a simple test app attached in bugreport #14724. */
729 TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing.\n");
730 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
731 gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
734 static void quirk_texcoord_w(struct wined3d_gl_info *gl_info)
736 /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
737 * with fixed function fragment processing. Ideally this flag should be detected with a test shader
738 * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
739 * do not like vertex shaders in feedback mode and return an error, even though it should be valid
740 * according to the spec.
742 * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
743 * makes the shader slower and eats instruction slots which should be available to the d3d app.
745 * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
746 * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
747 * this workaround is activated on cards that do not need it, it won't break things, just affect
748 * performance negatively. */
749 TRACE("Enabling vertex texture coord fixes in vertex shaders.\n");
750 gl_info->quirks |= WINED3D_QUIRK_SET_TEXCOORD_W;
753 static void quirk_clip_varying(struct wined3d_gl_info *gl_info)
755 gl_info->quirks |= WINED3D_QUIRK_GLSL_CLIP_VARYING;
758 static void quirk_allows_specular_alpha(struct wined3d_gl_info *gl_info)
760 gl_info->quirks |= WINED3D_QUIRK_ALLOWS_SPECULAR_ALPHA;
763 struct driver_quirk
765 BOOL (*match)(const struct wined3d_gl_info *gl_info, const char *gl_renderer);
766 void (*apply)(struct wined3d_gl_info *gl_info);
767 const char *description;
770 struct driver_quirk quirk_table[] =
773 match_ati_r300_to_500,
774 quirk_ati_dx9,
775 "ATI GLSL constant and normalized texrect quirk"
777 /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
778 * used it falls back to software. While the compiler can detect if the shader uses all declared
779 * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
780 * using relative addressing falls back to software.
782 * ARB vp gives the correct amount of uniforms, so use it instead of GLSL. */
784 match_apple,
785 quirk_apple_glsl_constants,
786 "Apple GLSL uniform override"
789 match_geforce5,
790 quirk_no_np2,
791 "Geforce 5 NP2 disable"
794 match_apple_intel,
795 quirk_texcoord_w,
796 "Init texcoord .w for Apple Intel GPU driver"
799 match_apple_nonr500ati,
800 quirk_texcoord_w,
801 "Init texcoord .w for Apple ATI >= r600 GPU driver"
804 match_fglrx,
805 quirk_one_point_sprite,
806 "Fglrx point sprite crash workaround"
809 match_dx10_capable,
810 quirk_clip_varying,
811 "Reserved varying for gl_ClipPos"
814 /* GL_EXT_secondary_color does not allow 4 component secondary colors, but most
815 * GL implementations accept it. The Mac GL is the only implementation known to
816 * reject it.
818 * If we can pass 4 component specular colors, do it, because (a) we don't have
819 * to screw around with the data, and (b) the D3D fixed function vertex pipeline
820 * passes specular alpha to the pixel shader if any is used. Otherwise the
821 * specular alpha is used to pass the fog coordinate, which we pass to opengl
822 * via GL_EXT_fog_coord.
824 match_allows_spec_alpha,
825 quirk_allows_specular_alpha,
826 "Allow specular alpha quirk"
830 /* Certain applications (Steam) complain if we report an outdated driver version. In general,
831 * reporting a driver version is moot because we are not the Windows driver, and we have different
832 * bugs, features, etc.
834 * If a card is not found in this table, the GL driver version is reported. */
835 struct driver_version_information
837 WORD vendor; /* reported PCI card vendor ID */
838 WORD card; /* reported PCI card device ID */
839 const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
840 WORD hipart_hi, hipart_lo; /* driver hiword to report */
841 WORD lopart_hi, lopart_lo; /* driver loword to report */
844 static const struct driver_version_information driver_version_table[] =
846 /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
847 * 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
848 * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
849 * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
851 * All version numbers used below are from the Linux nvidia drivers. */
852 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
853 {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
854 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
855 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
856 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
857 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 10, 9371 },
858 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 10, 9371 },
859 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 10, 9371 },
860 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7516 },
861 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7516 },
862 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7516 },
863 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8618 },
864 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8618 },
865 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8618 },
866 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8585 },
867 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8585 },
868 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8618 },
869 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8618 },
870 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8618 },
871 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8618 },
872 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8585 },
873 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8618 },
874 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8618 },
875 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8618 },
876 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8618 },
877 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8618 },
878 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8618 },
879 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8618 },
880 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8618 },
881 {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8618 },
883 /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode. */
884 {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
885 {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
886 {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
887 {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
888 {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
889 {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
890 {VENDOR_ATI, CARD_ATI_RADEON_HD4350, "ATI Radeon HD 4350", 6, 14, 10, 6764 },
891 {VENDOR_ATI, CARD_ATI_RADEON_HD4600, "ATI Radeon HD 4600 Series", 6, 14, 10, 6764 },
892 {VENDOR_ATI, CARD_ATI_RADEON_HD4700, "ATI Radeon HD 4700 Series", 6, 14, 10, 6764 },
893 {VENDOR_ATI, CARD_ATI_RADEON_HD4800, "ATI Radeon HD 4800 Series", 6, 14, 10, 6764 },
895 /* TODO: Add information about legacy ATI hardware, Intel and other cards. */
898 /* Context activation is done by the caller. */
899 static void fixup_extensions(struct wined3d_gl_info *gl_info, const char *gl_renderer)
901 unsigned int i;
903 for (i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); ++i)
905 if (!quirk_table[i].match(gl_info, gl_renderer)) continue;
906 TRACE_(d3d_caps)("Applying driver quirk \"%s\".\n", quirk_table[i].description);
907 quirk_table[i].apply(gl_info);
910 /* Find out if PBOs work as they are supposed to. */
911 test_pbo_functionality(gl_info);
913 /* Fixup the driver version */
914 for (i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); ++i)
916 if (gl_info->gl_vendor == driver_version_table[i].vendor
917 && gl_info->gl_card == driver_version_table[i].card)
919 TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB.\n",
920 gl_info->gl_vendor, gl_info->gl_card);
922 gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
923 driver_version_table[i].lopart_lo);
924 gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
925 driver_version_table[i].hipart_lo);
926 gl_info->driver_description = driver_version_table[i].description;
927 break;
932 /* Context activation is done by the caller. */
933 static BOOL IWineD3DImpl_FillGLCaps(struct wined3d_gl_info *gl_info)
935 const char *GL_Extensions = NULL;
936 const char *WGL_Extensions = NULL;
937 const char *gl_string = NULL;
938 const char *gl_string_cursor = NULL;
939 GLint gl_max;
940 GLfloat gl_floatv[2];
941 int major = 1, minor = 0;
942 unsigned i;
943 HDC hdc;
944 unsigned int vidmem=0;
945 char *gl_renderer;
946 DWORD gl_version;
947 size_t len;
949 TRACE_(d3d_caps)("(%p)\n", gl_info);
951 ENTER_GL();
953 gl_string = (const char *)glGetString(GL_RENDERER);
954 TRACE_(d3d_caps)("GL_RENDERER: %s.\n", gl_string);
955 if (!gl_string)
957 ERR_(d3d_caps)("Received a NULL GL_RENDERER.\n");
958 return FALSE;
961 len = strlen(gl_string) + 1;
962 gl_renderer = HeapAlloc(GetProcessHeap(), 0, len);
963 if (!gl_renderer)
965 ERR_(d3d_caps)("Failed to allocate gl_renderer memory.\n");
966 return FALSE;
968 memcpy(gl_renderer, gl_string, len);
970 gl_string = (const char *)glGetString(GL_VENDOR);
971 TRACE_(d3d_caps)("GL_VENDOR: %s.\n", gl_string);
972 if (!gl_string)
974 ERR_(d3d_caps)("Received a NULL GL_VENDOR.\n");
975 HeapFree(GetProcessHeap(), 0, gl_renderer);
976 return FALSE;
979 /* Fill in the GL vendor */
980 if (strstr(gl_string, "NVIDIA"))
982 gl_info->gl_vendor = VENDOR_NVIDIA;
984 else if (strstr(gl_string, "ATI"))
986 gl_info->gl_vendor = VENDOR_ATI;
988 else if (strstr(gl_string, "Intel(R)")
989 || strstr(gl_renderer, "Intel(R)")
990 || strstr(gl_string, "Intel Inc."))
992 gl_info->gl_vendor = VENDOR_INTEL;
994 else if (strstr(gl_string, "Mesa"))
996 gl_info->gl_vendor = VENDOR_MESA;
998 else
1000 FIXME_(d3d_caps)("Received unrecognized GL_VENDOR %s. Setting VENDOR_WINE.\n", gl_string);
1001 gl_info->gl_vendor = VENDOR_WINE;
1003 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
1005 /* Parse the GL_VERSION field into major and minor information */
1006 gl_string = (const char *)glGetString(GL_VERSION);
1007 TRACE_(d3d_caps)("GL_VERSION: %s.\n", gl_string);
1008 if (!gl_string)
1010 ERR_(d3d_caps)("Received a NULL GL_VERSION.\n");
1011 HeapFree(GetProcessHeap(), 0, gl_renderer);
1012 return FALSE;
1015 /* First, parse the generic opengl version. This is supposed not to be
1016 * convoluted with driver specific information. */
1017 gl_string_cursor = gl_string;
1019 major = atoi(gl_string_cursor);
1020 if (major <= 0) ERR_(d3d_caps)("Invalid opengl major version: %d.\n", major);
1021 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1022 if (*gl_string_cursor++ != '.') ERR_(d3d_caps)("Invalid opengl version string: %s.\n", debugstr_a(gl_string));
1024 minor = atoi(gl_string_cursor);
1025 TRACE_(d3d_caps)("Found OpenGL version: %d.%d.\n", major, minor);
1026 gl_version = MAKEDWORD_VERSION(major, minor);
1028 /* Now parse the driver specific string which we'll report to the app. */
1029 switch (gl_info->gl_vendor)
1031 case VENDOR_NVIDIA:
1032 gl_string_cursor = strstr(gl_string, "NVIDIA");
1033 if (!gl_string_cursor)
1035 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1036 break;
1039 gl_string_cursor = strstr(gl_string_cursor, " ");
1040 if (!gl_string_cursor)
1042 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1043 break;
1046 while (*gl_string_cursor == ' ') ++gl_string_cursor;
1048 if (!*gl_string_cursor)
1050 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1051 break;
1054 major = atoi(gl_string_cursor);
1055 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1057 if (*gl_string_cursor++ != '.')
1059 ERR_(d3d_caps)("Invalid nVidia version string: %s.\n", debugstr_a(gl_string));
1060 break;
1063 minor = atoi(gl_string_cursor);
1064 minor = major * 100 + minor;
1065 major = 10;
1066 break;
1068 case VENDOR_ATI:
1069 major = minor = 0;
1070 gl_string_cursor = strchr(gl_string, '-');
1071 if (gl_string_cursor)
1073 ++gl_string_cursor;
1075 /* Check if version number is of the form x.y.z. */
1076 if (*gl_string_cursor < '0' || *gl_string_cursor > '9'
1077 || gl_string_cursor[1] != '.'
1078 || gl_string_cursor[2] < '0' || gl_string_cursor[2] > '9'
1079 || gl_string_cursor[3] != '.'
1080 || gl_string_cursor[4] < '0' || gl_string_cursor[4] > '9')
1081 /* Mark version number as malformed. */
1082 gl_string_cursor = 0;
1085 if (!gl_string_cursor)
1087 WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
1089 else
1091 major = *gl_string_cursor - '0';
1092 minor = (gl_string_cursor[2] - '0') * 256 + (gl_string_cursor[4] - '0');
1094 break;
1096 case VENDOR_INTEL:
1097 /* Apple and Mesa version strings look differently, but both provide intel drivers. */
1098 if (strstr(gl_string, "APPLE"))
1100 /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
1101 * We only need the first part, and use the APPLE as identification
1102 * "1.2 APPLE-1.4.56". */
1103 gl_string_cursor = gl_string;
1104 major = atoi(gl_string_cursor);
1105 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') ++gl_string_cursor;
1107 if (*gl_string_cursor++ != '.')
1109 ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s.\n", debugstr_a(gl_string));
1110 break;
1113 minor = atoi(gl_string_cursor);
1114 break;
1116 /* Fallthrough */
1118 case VENDOR_MESA:
1119 gl_string_cursor = strstr(gl_string, "Mesa");
1120 gl_string_cursor = strstr(gl_string_cursor, " ");
1121 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
1122 if (*gl_string_cursor)
1124 char tmp[16];
1125 int cursor = 0;
1127 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
1129 tmp[cursor++] = *gl_string_cursor;
1130 ++gl_string_cursor;
1132 tmp[cursor] = 0;
1133 major = atoi(tmp);
1135 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s).\n", debugstr_a(gl_string));
1136 ++gl_string_cursor;
1138 cursor = 0;
1139 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0')
1141 tmp[cursor++] = *gl_string_cursor;
1142 ++gl_string_cursor;
1144 tmp[cursor] = 0;
1145 minor = atoi(tmp);
1147 break;
1149 default:
1150 major = 0;
1151 minor = 9;
1152 break;
1155 gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
1156 TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x).\n",
1157 debugstr_a(gl_string), major, minor, gl_info->driver_version);
1158 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version). */
1159 gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
1162 * Initialize openGL extension related variables
1163 * with Default values
1165 memset(gl_info->supported, 0, sizeof(gl_info->supported));
1166 gl_info->max_buffers = 1;
1167 gl_info->max_textures = 1;
1168 gl_info->max_texture_stages = 1;
1169 gl_info->max_fragment_samplers = 1;
1170 gl_info->max_vertex_samplers = 0;
1171 gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
1172 gl_info->max_sampler_stages = 1;
1173 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
1174 gl_info->ps_arb_max_temps = 0;
1175 gl_info->ps_arb_max_instructions = 0;
1176 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
1177 gl_info->vs_arb_max_temps = 0;
1178 gl_info->vs_arb_max_instructions = 0;
1179 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
1180 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
1181 gl_info->vs_glsl_constantsF = 0;
1182 gl_info->ps_glsl_constantsF = 0;
1183 gl_info->vs_arb_constantsF = 0;
1184 gl_info->ps_arb_constantsF = 0;
1185 gl_info->ps_arb_max_local_constants = 0;
1187 /* Retrieve opengl defaults */
1188 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1189 gl_info->max_clipplanes = min(WINED3DMAXUSERCLIPPLANES, gl_max);
1190 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
1192 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1193 gl_info->max_lights = gl_max;
1194 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
1196 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
1197 gl_info->max_texture_size = gl_max;
1198 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
1200 glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
1201 gl_info->max_pointsizemin = gl_floatv[0];
1202 gl_info->max_pointsize = gl_floatv[1];
1203 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
1205 /* Parse the gl supported features, in theory enabling parts of our code appropriately. */
1206 GL_Extensions = (const char *)glGetString(GL_EXTENSIONS);
1207 if (!GL_Extensions)
1209 ERR_(d3d_caps)("Received a NULL GL_EXTENSIONS.\n");
1210 HeapFree(GetProcessHeap(), 0, gl_renderer);
1211 return FALSE;
1214 TRACE_(d3d_caps)("GL_Extensions reported:\n");
1216 gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE;
1218 while (*GL_Extensions)
1220 const char *start;
1221 char current_ext[256];
1223 while (isspace(*GL_Extensions)) ++GL_Extensions;
1224 start = GL_Extensions;
1225 while (!isspace(*GL_Extensions) && *GL_Extensions) ++GL_Extensions;
1227 len = GL_Extensions - start;
1228 if (!len || len >= sizeof(current_ext)) continue;
1230 memcpy(current_ext, start, len);
1231 current_ext[len] = '\0';
1232 TRACE_(d3d_caps)("- %s\n", current_ext);
1234 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1236 if (!strcmp(current_ext, EXTENSION_MAP[i].extension_string))
1238 TRACE_(d3d_caps)(" FOUND: %s support.\n", EXTENSION_MAP[i].extension_string);
1239 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1240 break;
1245 LEAVE_GL();
1247 /* Now work out what GL support this card really has */
1248 #define USE_GL_FUNC(type, pfn, ext, replace) \
1250 DWORD ver = ver_for_ext(ext); \
1251 if (gl_info->supported[ext]) gl_info->pfn = (type)pwglGetProcAddress(#pfn); \
1252 else if (ver && ver <= gl_version) gl_info->pfn = (type)pwglGetProcAddress(#replace); \
1253 else gl_info->pfn = NULL; \
1255 GL_EXT_FUNCS_GEN;
1256 #undef USE_GL_FUNC
1258 #define USE_GL_FUNC(type, pfn, ext, replace) gl_info->pfn = (type)pwglGetProcAddress(#pfn);
1259 WGL_EXT_FUNCS_GEN;
1260 #undef USE_GL_FUNC
1262 ENTER_GL();
1264 /* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
1265 * loading the functions, otherwise the code above will load the extension entry points instead of the
1266 * core functions, which may not work. */
1267 for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i)
1269 if (!gl_info->supported[EXTENSION_MAP[i].extension]
1270 && EXTENSION_MAP[i].version <= gl_version && EXTENSION_MAP[i].version)
1272 TRACE_(d3d_caps)(" GL CORE: %s support.\n", EXTENSION_MAP[i].extension_string);
1273 gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
1277 if (gl_info->supported[APPLE_FENCE])
1279 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
1280 * The apple extension interacts with some other apple exts. Disable the NV
1281 * extension if the apple one is support to prevent confusion in other parts
1282 * of the code. */
1283 gl_info->supported[NV_FENCE] = FALSE;
1285 if (gl_info->supported[APPLE_FLOAT_PIXELS])
1287 /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
1289 * The enums are the same:
1290 * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
1291 * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
1292 * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
1293 * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
1294 * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
1296 if (!gl_info->supported[ARB_TEXTURE_FLOAT])
1298 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels.\n");
1299 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
1301 if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
1303 TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels.\n");
1304 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
1307 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
1309 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support.\n");
1310 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
1312 if (gl_info->supported[NV_TEXTURE_SHADER2])
1314 if (gl_info->supported[NV_REGISTER_COMBINERS])
1316 /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
1317 * are supported. The nv extensions provide the same functionality as the
1318 * ATI one, and a bit more(signed pixelformats). */
1319 gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
1322 if (gl_info->supported[ARB_DRAW_BUFFERS])
1324 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
1325 gl_info->max_buffers = gl_max;
1326 TRACE_(d3d_caps)("Max draw buffers: %u.\n", gl_max);
1328 if (gl_info->supported[ARB_MULTITEXTURE])
1330 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1331 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
1332 TRACE_(d3d_caps)("Max textures: %d.\n", gl_info->max_textures);
1334 if (gl_info->supported[NV_REGISTER_COMBINERS])
1336 GLint tmp;
1337 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &tmp);
1338 gl_info->max_texture_stages = min(MAX_TEXTURES, tmp);
1340 else
1342 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
1344 TRACE_(d3d_caps)("Max texture stages: %d.\n", gl_info->max_texture_stages);
1346 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1348 GLint tmp;
1349 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1350 gl_info->max_fragment_samplers = min(MAX_FRAGMENT_SAMPLERS, tmp);
1352 else
1354 gl_info->max_fragment_samplers = max(gl_info->max_fragment_samplers, gl_max);
1356 TRACE_(d3d_caps)("Max fragment samplers: %d.\n", gl_info->max_fragment_samplers);
1358 if (gl_info->supported[ARB_VERTEX_SHADER])
1360 GLint tmp;
1361 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1362 gl_info->max_vertex_samplers = tmp;
1363 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, &tmp);
1364 gl_info->max_combined_samplers = tmp;
1366 /* Loading GLSL sampler uniforms is much simpler if we can assume that the sampler setup
1367 * is known at shader link time. In a vertex shader + pixel shader combination this isn't
1368 * an issue because then the sampler setup only depends on the two shaders. If a pixel
1369 * shader is used with fixed function vertex processing we're fine too because fixed function
1370 * vertex processing doesn't use any samplers. If fixed function fragment processing is
1371 * used we have to make sure that all vertex sampler setups are valid together with all
1372 * possible fixed function fragment processing setups. This is true if vsamplers + MAX_TEXTURES
1373 * <= max_samplers. This is true on all d3d9 cards that support vtf(gf 6 and gf7 cards).
1374 * dx9 radeon cards do not support vertex texture fetch. DX10 cards have 128 samplers, and
1375 * dx9 is limited to 8 fixed function texture stages and 4 vertex samplers. DX10 does not have
1376 * a fixed function pipeline anymore.
1378 * So this is just a check to check that our assumption holds true. If not, write a warning
1379 * and reduce the number of vertex samplers or probably disable vertex texture fetch. */
1380 if (gl_info->max_vertex_samplers && gl_info->max_combined_samplers < 12
1381 && MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers)
1383 FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers.\n",
1384 gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
1385 FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers.\n");
1386 if (gl_info->max_combined_samplers > MAX_TEXTURES)
1387 gl_info->max_vertex_samplers = gl_info->max_combined_samplers - MAX_TEXTURES;
1388 else
1389 gl_info->max_vertex_samplers = 0;
1392 else
1394 gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
1396 TRACE_(d3d_caps)("Max vertex samplers: %u.\n", gl_info->max_vertex_samplers);
1397 TRACE_(d3d_caps)("Max combined samplers: %u.\n", gl_info->max_combined_samplers);
1399 if (gl_info->supported[ARB_VERTEX_BLEND])
1401 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1402 gl_info->max_blends = gl_max;
1403 TRACE_(d3d_caps)("Max blends: %u.\n", gl_info->max_blends);
1405 if (gl_info->supported[EXT_TEXTURE3D])
1407 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
1408 gl_info->max_texture3d_size = gl_max;
1409 TRACE_(d3d_caps)("Max texture3D size: %d.\n", gl_info->max_texture3d_size);
1411 if (gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC])
1413 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1414 gl_info->max_anisotropy = gl_max;
1415 TRACE_(d3d_caps)("Max anisotropy: %d.\n", gl_info->max_anisotropy);
1417 if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
1419 gl_info->ps_arb_version = PS_VERSION_11;
1420 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1421 gl_info->ps_arb_constantsF = gl_max;
1422 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM float constants: %d.\n", gl_info->ps_arb_constantsF);
1423 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1424 gl_info->ps_arb_max_temps = gl_max;
1425 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native temporaries: %d.\n", gl_info->ps_arb_max_temps);
1426 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1427 gl_info->ps_arb_max_instructions = gl_max;
1428 TRACE_(d3d_caps)("Max ARB_FRAGMENT_PROGRAM native instructions: %d.\n", gl_info->ps_arb_max_instructions);
1430 if (gl_info->supported[ARB_VERTEX_PROGRAM])
1432 gl_info->vs_arb_version = VS_VERSION_11;
1433 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
1434 gl_info->vs_arb_constantsF = gl_max;
1435 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM float constants: %d.\n", gl_info->vs_arb_constantsF);
1436 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, &gl_max));
1437 gl_info->vs_arb_max_temps = gl_max;
1438 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native temporaries: %d.\n", gl_info->vs_arb_max_temps);
1439 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, &gl_max));
1440 gl_info->vs_arb_max_instructions = gl_max;
1441 TRACE_(d3d_caps)("Max ARB_VERTEX_PROGRAM native instructions: %d.\n", gl_info->vs_arb_max_instructions);
1443 if (test_arb_vs_offset_limit(gl_info)) gl_info->quirks |= WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT;
1445 if (gl_info->supported[ARB_VERTEX_SHADER])
1447 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
1448 gl_info->vs_glsl_constantsF = gl_max / 4;
1449 TRACE_(d3d_caps)("Max ARB_VERTEX_SHADER float constants: %u.\n", gl_info->vs_glsl_constantsF);
1451 if (gl_info->supported[ARB_FRAGMENT_SHADER])
1453 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
1454 gl_info->ps_glsl_constantsF = gl_max / 4;
1455 TRACE_(d3d_caps)("Max ARB_FRAGMENT_SHADER float constants: %u.\n", gl_info->ps_glsl_constantsF);
1456 glGetIntegerv(GL_MAX_VARYING_FLOATS_ARB, &gl_max);
1457 gl_info->max_glsl_varyings = gl_max;
1458 TRACE_(d3d_caps)("Max GLSL varyings: %u (%u 4 component varyings).\n", gl_max, gl_max / 4);
1460 if (gl_info->supported[EXT_VERTEX_SHADER])
1462 gl_info->vs_ati_version = VS_VERSION_11;
1464 if (gl_info->supported[NV_VERTEX_PROGRAM3])
1466 gl_info->vs_nv_version = VS_VERSION_30;
1468 else if (gl_info->supported[NV_VERTEX_PROGRAM2])
1470 gl_info->vs_nv_version = VS_VERSION_20;
1472 else if (gl_info->supported[NV_VERTEX_PROGRAM1_1])
1474 gl_info->vs_nv_version = VS_VERSION_11;
1476 else if (gl_info->supported[NV_VERTEX_PROGRAM])
1478 gl_info->vs_nv_version = VS_VERSION_10;
1480 if (gl_info->supported[NV_FRAGMENT_PROGRAM2])
1482 gl_info->ps_nv_version = PS_VERSION_30;
1484 else if (gl_info->supported[NV_FRAGMENT_PROGRAM])
1486 gl_info->ps_nv_version = PS_VERSION_20;
1488 if (gl_info->supported[NV_LIGHT_MAX_EXPONENT])
1490 glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
1492 else
1494 gl_info->max_shininess = 128.0f;
1496 if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO])
1498 /* If we have full NP2 texture support, disable
1499 * GL_ARB_texture_rectangle because we will never use it.
1500 * This saves a few redundant glDisable calls. */
1501 gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
1503 if (gl_info->supported[ATI_FRAGMENT_SHADER])
1505 /* Disable NV_register_combiners and fragment shader if this is supported.
1506 * generally the NV extensions are preferred over the ATI ones, and this
1507 * extension is disabled if register_combiners and texture_shader2 are both
1508 * supported. So we reach this place only if we have incomplete NV dxlevel 8
1509 * fragment processing support. */
1510 gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
1511 gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
1512 gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
1513 gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
1514 gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
1516 if (gl_info->supported[NV_HALF_FLOAT])
1518 /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float. */
1519 gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
1521 if (gl_info->supported[ARB_POINT_SPRITE])
1523 gl_info->max_point_sprite_units = gl_info->max_textures;
1525 else
1527 gl_info->max_point_sprite_units = 0;
1529 checkGLcall("extension detection");
1531 /* In some cases the number of texture stages can be larger than the number
1532 * of samplers. The GF4 for example can use only 2 samplers (no fragment
1533 * shaders), but 8 texture stages (register combiners). */
1534 gl_info->max_sampler_stages = max(gl_info->max_fragment_samplers, gl_info->max_texture_stages);
1536 /* We can only use ORM_FBO when the hardware supports it. */
1537 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !gl_info->supported[EXT_FRAMEBUFFER_OBJECT]) {
1538 WARN_(d3d_caps)("GL_EXT_framebuffer_object not supported, falling back to backbuffer offscreen rendering mode.\n");
1539 wined3d_settings.offscreen_rendering_mode = ORM_BACKBUFFER;
1542 /* MRTs are currently only supported when FBOs are used. */
1543 if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
1544 gl_info->max_buffers = 1;
1547 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
1548 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
1549 * in case of the latest videocards in the number of pixel/vertex pipelines.
1551 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
1552 * rendering. Various games use this information to get a rough estimation of the features of the card
1553 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
1554 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
1555 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
1556 * not the PCI id.
1558 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
1559 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
1560 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
1561 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
1562 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
1563 * is used for rendering which is not always the case). This would work but it is not very portable. Second
1564 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
1565 * is limited.
1567 * As said most games only use the PCI id to get an indication of the capabilities of the card.
1568 * It doesn't really matter if the given id is the correct one if we return the id of a card with
1569 * similar 3d features.
1571 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
1572 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
1573 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
1574 * won't pass we return a default card. This way is better than maintaining a full card database as even
1575 * without a full database we can return a card with similar features. Second the size of the database
1576 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
1577 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
1578 * to distinguishes between different models from that family.
1580 * The code also selects a default amount of video memory which we will use for an estimation of the amount
1581 * of free texture memory. In case of real D3D the amount of texture memory includes video memory and system
1582 * memory (to be specific AGP memory or in case of PCIE TurboCache/HyperMemory). We don't know how much
1583 * system memory can be addressed by the system but we can make a reasonable estimation about the amount of
1584 * video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
1585 * makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
1586 * memory behind our backs if really needed.
1587 * Note that the amount of video memory can be overruled using a registry setting.
1589 switch (gl_info->gl_vendor) {
1590 case VENDOR_NVIDIA:
1591 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
1592 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
1594 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
1595 /* Geforce 200 - highend */
1596 if (strstr(gl_renderer, "GTX 280")
1597 || strstr(gl_renderer, "GTX 285")
1598 || strstr(gl_renderer, "GTX 295"))
1600 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
1601 vidmem = 1024;
1603 /* Geforce 200 - midend high */
1604 else if (strstr(gl_renderer, "GTX 275"))
1606 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
1607 vidmem = 896;
1609 /* Geforce 200 - midend */
1610 else if (strstr(gl_renderer, "GTX 260"))
1612 gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
1613 vidmem = 1024;
1615 /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
1616 else if (strstr(gl_renderer, "9800")
1617 || strstr(gl_renderer, "GTS 150")
1618 || strstr(gl_renderer, "GTS 250"))
1620 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
1621 vidmem = 512;
1623 /* Geforce9 - midend */
1624 else if (strstr(gl_renderer, "9600"))
1626 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
1627 vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
1629 /* Geforce9 - midend low / Geforce 200 - low*/
1630 else if (strstr(gl_renderer, "9500")
1631 || strstr(gl_renderer, "GT 120")
1632 || strstr(gl_renderer, "GT 130"))
1634 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
1635 vidmem = 256; /* The 9500GT has 256-1024MB */
1637 /* Geforce9 - lowend */
1638 else if (strstr(gl_renderer, "9400"))
1640 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
1641 vidmem = 256; /* The 9400GT has 256-1024MB */
1643 /* Geforce9 - lowend low */
1644 else if (strstr(gl_renderer, "9100")
1645 || strstr(gl_renderer, "9200")
1646 || strstr(gl_renderer, "9300")
1647 || strstr(gl_renderer, "G 100"))
1649 gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
1650 vidmem = 256; /* The 9100-9300 cards have 256MB */
1652 /* Geforce8 - highend */
1653 else if (strstr(gl_renderer, "8800"))
1655 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
1656 vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
1658 /* Geforce8 - midend mobile */
1659 else if (strstr(gl_renderer, "8600 M"))
1661 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
1662 vidmem = 512;
1664 /* Geforce8 - midend */
1665 else if (strstr(gl_renderer, "8600")
1666 || strstr(gl_renderer, "8700"))
1668 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600GT;
1669 vidmem = 256;
1671 /* Geforce8 - lowend */
1672 else if (strstr(gl_renderer, "8300")
1673 || strstr(gl_renderer, "8400")
1674 || strstr(gl_renderer, "8500"))
1676 gl_info->gl_card = CARD_NVIDIA_GEFORCE_8300GS;
1677 vidmem = 128; /* 128-256MB for a 8300, 256-512MB for a 8400 */
1679 /* Geforce7 - highend */
1680 else if (strstr(gl_renderer, "7800")
1681 || strstr(gl_renderer, "7900")
1682 || strstr(gl_renderer, "7950")
1683 || strstr(gl_renderer, "Quadro FX 4")
1684 || strstr(gl_renderer, "Quadro FX 5"))
1686 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
1687 vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
1689 /* Geforce7 midend */
1690 else if (strstr(gl_renderer, "7600")
1691 || strstr(gl_renderer, "7700"))
1693 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
1694 vidmem = 256; /* The 7600 uses 256-512MB */
1695 /* Geforce7 lower medium */
1697 else if (strstr(gl_renderer, "7400"))
1699 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
1700 vidmem = 256; /* The 7400 uses 256-512MB */
1702 /* Geforce7 lowend */
1703 else if (strstr(gl_renderer, "7300"))
1705 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
1706 vidmem = 256; /* Mac Pros with this card have 256 MB */
1708 /* Geforce6 highend */
1709 else if (strstr(gl_renderer, "6800"))
1711 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
1712 vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
1714 /* Geforce6 - midend */
1715 else if (strstr(gl_renderer, "6600")
1716 || strstr(gl_renderer, "6610")
1717 || strstr(gl_renderer, "6700"))
1719 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
1720 vidmem = 128; /* A 6600GT has 128-256MB */
1722 /* Geforce6/7 lowend */
1723 else {
1724 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400/7500 */
1725 vidmem = 64; /* */
1727 } else if(WINE_D3D9_CAPABLE(gl_info)) {
1728 /* GeforceFX - highend */
1729 if (strstr(gl_renderer, "5800")
1730 || strstr(gl_renderer, "5900")
1731 || strstr(gl_renderer, "5950")
1732 || strstr(gl_renderer, "Quadro FX"))
1734 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
1735 vidmem = 256; /* 5800-5900 cards use 256MB */
1737 /* GeforceFX - midend */
1738 else if (strstr(gl_renderer, "5600")
1739 || strstr(gl_renderer, "5650")
1740 || strstr(gl_renderer, "5700")
1741 || strstr(gl_renderer, "5750"))
1743 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1744 vidmem = 128; /* A 5600 uses 128-256MB */
1746 /* GeforceFX - lowend */
1747 else {
1748 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
1749 vidmem = 64; /* Normal FX5200 cards use 64-256MB; laptop (non-standard) can have less */
1751 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1752 if (strstr(gl_renderer, "GeForce4 Ti") || strstr(gl_renderer, "Quadro4"))
1754 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
1755 vidmem = 64; /* Geforce4 Ti cards have 64-128MB */
1757 else
1759 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
1760 vidmem = 64; /* Geforce3 cards have 64-128MB */
1762 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1763 if (strstr(gl_renderer, "GeForce4 MX"))
1765 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
1766 vidmem = 64; /* Most Geforce4MX GPUs have at least 64MB of memory, some early models had 32MB but most have 64MB or even 128MB */
1768 else if(strstr(gl_renderer, "GeForce2 MX") || strstr(gl_renderer, "Quadro2 MXR"))
1770 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
1771 vidmem = 32; /* Geforce2MX GPUs have 32-64MB of video memory */
1773 else if(strstr(gl_renderer, "GeForce2") || strstr(gl_renderer, "Quadro2"))
1775 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
1776 vidmem = 32; /* Geforce2 GPUs have 32-64MB of video memory */
1778 else
1780 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
1781 vidmem = 32; /* Most Geforce1 cards have 32MB, there are also some rare 16 and 64MB (Dell) models */
1783 } else {
1784 if (strstr(gl_renderer, "TNT2"))
1786 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
1787 vidmem = 32; /* Most TNT2 boards have 32MB, though there are 16MB boards too */
1789 else
1791 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
1792 vidmem = 16; /* Most TNT boards have 16MB, some rare models have 8MB */
1795 break;
1796 case VENDOR_ATI:
1797 /* See http://developer.amd.com/drivers/pc_vendor_id/Pages/default.aspx
1799 * beware: renderer string do not match exact card model,
1800 * eg HD 4800 is returned for multiple card, even for RV790 based one
1802 if(WINE_D3D9_CAPABLE(gl_info)) {
1803 /* Radeon R7xx HD4800 - highend */
1804 if (strstr(gl_renderer, "HD 4800") /* Radeon RV7xx HD48xx generic renderer string */
1805 || strstr(gl_renderer, "HD 4830") /* Radeon RV770 */
1806 || strstr(gl_renderer, "HD 4850") /* Radeon RV770 */
1807 || strstr(gl_renderer, "HD 4870") /* Radeon RV770 */
1808 || strstr(gl_renderer, "HD 4890")) /* Radeon RV790 */
1810 gl_info->gl_card = CARD_ATI_RADEON_HD4800;
1811 vidmem = 512; /* note: HD4890 cards use 1024MB */
1813 /* Radeon R740 HD4700 - midend */
1814 else if (strstr(gl_renderer, "HD 4700") /* Radeon RV770 */
1815 || strstr(gl_renderer, "HD 4770")) /* Radeon RV740 */
1817 gl_info->gl_card = CARD_ATI_RADEON_HD4700;
1818 vidmem = 512;
1820 /* Radeon R730 HD4600 - midend */
1821 else if (strstr(gl_renderer, "HD 4600") /* Radeon RV730 */
1822 || strstr(gl_renderer, "HD 4650") /* Radeon RV730 */
1823 || strstr(gl_renderer, "HD 4670")) /* Radeon RV730 */
1825 gl_info->gl_card = CARD_ATI_RADEON_HD4600;
1826 vidmem = 512;
1828 /* Radeon R710 HD4500/HD4350 - lowend */
1829 else if (strstr(gl_renderer, "HD 4350") /* Radeon RV710 */
1830 || strstr(gl_renderer, "HD 4550")) /* Radeon RV710 */
1832 gl_info->gl_card = CARD_ATI_RADEON_HD4350;
1833 vidmem = 256;
1835 /* Radeon R6xx HD2900/HD3800 - highend */
1836 else if (strstr(gl_renderer, "HD 2900")
1837 || strstr(gl_renderer, "HD 3870")
1838 || strstr(gl_renderer, "HD 3850"))
1840 gl_info->gl_card = CARD_ATI_RADEON_HD2900;
1841 vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
1843 /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
1844 else if (strstr(gl_renderer, "HD 2600")
1845 || strstr(gl_renderer, "HD 3830")
1846 || strstr(gl_renderer, "HD 3690")
1847 || strstr(gl_renderer, "HD 3650"))
1849 gl_info->gl_card = CARD_ATI_RADEON_HD2600;
1850 vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
1852 /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
1853 else if (strstr(gl_renderer, "HD 2300")
1854 || strstr(gl_renderer, "HD 2400")
1855 || strstr(gl_renderer, "HD 3470")
1856 || strstr(gl_renderer, "HD 3450")
1857 || strstr(gl_renderer, "HD 3430")
1858 || strstr(gl_renderer, "HD 3400"))
1860 gl_info->gl_card = CARD_ATI_RADEON_HD2300;
1861 vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
1863 /* Radeon R6xx/R7xx integrated */
1864 else if (strstr(gl_renderer, "HD 3100")
1865 || strstr(gl_renderer, "HD 3200")
1866 || strstr(gl_renderer, "HD 3300"))
1868 gl_info->gl_card = CARD_ATI_RADEON_HD3200;
1869 vidmem = 128; /* 128MB */
1871 /* Radeon R5xx */
1872 else if (strstr(gl_renderer, "X1600")
1873 || strstr(gl_renderer, "X1650")
1874 || strstr(gl_renderer, "X1800")
1875 || strstr(gl_renderer, "X1900")
1876 || strstr(gl_renderer, "X1950"))
1878 gl_info->gl_card = CARD_ATI_RADEON_X1600;
1879 vidmem = 128; /* X1600 uses 128-256MB, >=X1800 uses 256MB */
1881 /* Radeon R4xx + X1300/X1400/X1450/X1550/X2300 (lowend R5xx) */
1882 else if(strstr(gl_renderer, "X700")
1883 || strstr(gl_renderer, "X800")
1884 || strstr(gl_renderer, "X850")
1885 || strstr(gl_renderer, "X1300")
1886 || strstr(gl_renderer, "X1400")
1887 || strstr(gl_renderer, "X1450")
1888 || strstr(gl_renderer, "X1550"))
1890 gl_info->gl_card = CARD_ATI_RADEON_X700;
1891 vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
1893 /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
1894 else if(strstr(gl_renderer, "Radeon Xpress"))
1896 gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
1897 vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
1899 /* Radeon R3xx */
1900 else {
1901 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
1902 vidmem = 64; /* Radeon 9500 uses 64MB, higher models use up to 256MB */
1904 } else if(WINE_D3D8_CAPABLE(gl_info)) {
1905 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
1906 vidmem = 64; /* 8500/9000 cards use mostly 64MB, though there are 32MB and 128MB models */
1907 } else if(WINE_D3D7_CAPABLE(gl_info)) {
1908 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
1909 vidmem = 32; /* There are models with up to 64MB */
1910 } else {
1911 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
1912 vidmem = 16; /* There are 16-32MB models */
1914 break;
1915 case VENDOR_INTEL:
1916 if(strstr(gl_renderer, "X3100"))
1918 /* MacOS calls the card GMA X3100, Google findings also suggest the name GM965 */
1919 gl_info->gl_card = CARD_INTEL_X3100;
1920 vidmem = 128;
1922 else if (strstr(gl_renderer, "GMA 950") || strstr(gl_renderer, "945GM"))
1924 /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
1925 gl_info->gl_card = CARD_INTEL_I945GM;
1926 vidmem = 64;
1928 else if (strstr(gl_renderer, "915GM"))
1930 gl_info->gl_card = CARD_INTEL_I915GM;
1932 else if (strstr(gl_renderer, "915G"))
1934 gl_info->gl_card = CARD_INTEL_I915G;
1936 else if (strstr(gl_renderer, "865G"))
1938 gl_info->gl_card = CARD_INTEL_I865G;
1940 else if (strstr(gl_renderer, "855G"))
1942 gl_info->gl_card = CARD_INTEL_I855G;
1944 else if (strstr(gl_renderer, "830G"))
1946 gl_info->gl_card = CARD_INTEL_I830G;
1947 } else {
1948 gl_info->gl_card = CARD_INTEL_I915G;
1950 break;
1951 case VENDOR_MESA:
1952 case VENDOR_WINE:
1953 default:
1954 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
1955 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
1956 * them a good generic choice.
1958 gl_info->gl_vendor = VENDOR_NVIDIA;
1959 if(WINE_D3D9_CAPABLE(gl_info))
1960 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
1961 else if(WINE_D3D8_CAPABLE(gl_info))
1962 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
1963 else if(WINE_D3D7_CAPABLE(gl_info))
1964 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
1965 else if(WINE_D3D6_CAPABLE(gl_info))
1966 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
1967 else
1968 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
1970 TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
1972 /* If we have an estimate use it, else default to 64MB; */
1973 if(vidmem)
1974 gl_info->vidmem = vidmem*1024*1024; /* convert from MBs to bytes */
1975 else
1976 gl_info->vidmem = WINE_DEFAULT_VIDMEM;
1978 /* Load all the lookup tables */
1979 for (i = 0; i < MAX_LOOKUPS; i++) {
1980 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
1983 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
1984 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
1985 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1986 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1987 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
1988 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
1989 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
1990 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
1991 stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
1992 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
1994 magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
1995 magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
1996 magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
1997 magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
1998 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
2001 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
2002 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
2003 minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
2004 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
2005 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
2006 minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
2007 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
2008 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
2009 minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
2010 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
2011 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
2012 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
2013 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
2014 minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
2015 = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
2017 /* TODO: config lookups */
2019 /* Make sure there's an active HDC else the WGL extensions will fail */
2020 hdc = pwglGetCurrentDC();
2021 if (hdc) {
2022 /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
2023 if(GL_EXTCALL(wglGetExtensionsStringARB))
2024 WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
2026 if (NULL == WGL_Extensions) {
2027 ERR(" WGL_Extensions returns NULL\n");
2028 } else {
2029 TRACE_(d3d_caps)("WGL_Extensions reported:\n");
2030 while (*WGL_Extensions != 0x00) {
2031 const char *Start;
2032 char ThisExtn[256];
2034 while (isspace(*WGL_Extensions)) WGL_Extensions++;
2035 Start = WGL_Extensions;
2036 while (!isspace(*WGL_Extensions) && *WGL_Extensions != 0x00) {
2037 WGL_Extensions++;
2040 len = WGL_Extensions - Start;
2041 if (len == 0 || len >= sizeof(ThisExtn))
2042 continue;
2044 memcpy(ThisExtn, Start, len);
2045 ThisExtn[len] = '\0';
2046 TRACE_(d3d_caps)("- %s\n", ThisExtn);
2048 if (!strcmp(ThisExtn, "WGL_ARB_pbuffer")) {
2049 gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
2050 TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
2052 if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
2053 gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
2054 TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
2056 if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
2057 gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
2058 TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
2063 LEAVE_GL();
2065 fixup_extensions(gl_info, gl_renderer);
2066 add_gl_compat_wrappers(gl_info);
2068 HeapFree(GetProcessHeap(), 0, gl_renderer);
2069 return TRUE;
2072 /**********************************************************
2073 * IWineD3D implementation follows
2074 **********************************************************/
2076 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
2077 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2079 TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
2081 return This->adapter_count;
2084 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
2085 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2086 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
2087 return WINED3D_OK;
2090 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
2091 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2093 TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
2095 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
2096 return NULL;
2099 return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
2102 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
2103 of the same bpp but different resolutions */
2105 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2106 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
2107 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2108 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
2110 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2111 return 0;
2114 /* TODO: Store modes per adapter and read it from the adapter structure */
2115 if (Adapter == 0) { /* Display */
2116 unsigned int i = 0;
2117 unsigned int j = 0;
2118 DEVMODEW mode;
2120 memset(&mode, 0, sizeof(mode));
2121 mode.dmSize = sizeof(mode);
2123 while (EnumDisplaySettingsExW(NULL, j, &mode, 0))
2125 ++j;
2126 switch (Format)
2128 case WINED3DFMT_UNKNOWN:
2129 /* This is for D3D8, do not enumerate P8 here */
2130 if (mode.dmBitsPerPel == 32 || mode.dmBitsPerPel == 16) ++i;
2131 break;
2133 case WINED3DFMT_X8R8G8B8:
2134 if (mode.dmBitsPerPel == 32) ++i;
2135 break;
2137 case WINED3DFMT_R5G6B5:
2138 if (mode.dmBitsPerPel == 16) ++i;
2139 break;
2141 case WINED3DFMT_P8:
2142 if (mode.dmBitsPerPel == 8) ++i;
2143 break;
2145 default:
2146 /* Skip other modes as they do not match the requested format */
2147 break;
2151 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
2152 return i;
2153 } else {
2154 FIXME_(d3d_caps)("Adapter not primary display\n");
2156 return 0;
2159 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
2160 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
2161 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2162 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
2164 /* Validate the parameters as much as possible */
2165 if (NULL == pMode ||
2166 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
2167 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
2168 return WINED3DERR_INVALIDCALL;
2171 /* TODO: Store modes per adapter and read it from the adapter structure */
2172 if (Adapter == 0)
2174 DEVMODEW DevModeW;
2175 int ModeIdx = 0;
2176 UINT i = 0;
2177 int j = 0;
2179 ZeroMemory(&DevModeW, sizeof(DevModeW));
2180 DevModeW.dmSize = sizeof(DevModeW);
2182 /* If we are filtering to a specific format (D3D9), then need to skip
2183 all unrelated modes, but if mode is irrelevant (D3D8), then we can
2184 just count through the ones with valid bit depths */
2185 while ((i<=Mode) && EnumDisplaySettingsExW(NULL, j++, &DevModeW, 0)) {
2186 switch (Format)
2188 case WINED3DFMT_UNKNOWN:
2189 /* This is D3D8. Do not enumerate P8 here */
2190 if (DevModeW.dmBitsPerPel == 32 ||
2191 DevModeW.dmBitsPerPel == 16) i++;
2192 break;
2193 case WINED3DFMT_X8R8G8B8:
2194 if (DevModeW.dmBitsPerPel == 32) i++;
2195 break;
2196 case WINED3DFMT_R5G6B5:
2197 if (DevModeW.dmBitsPerPel == 16) i++;
2198 break;
2199 case WINED3DFMT_P8:
2200 if (DevModeW.dmBitsPerPel == 8) i++;
2201 break;
2202 default:
2203 /* Modes that don't match what we support can get an early-out */
2204 TRACE_(d3d_caps)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format));
2205 return WINED3DERR_INVALIDCALL;
2209 if (i == 0) {
2210 TRACE_(d3d_caps)("No modes found for format (%x - %s)\n", Format, debug_d3dformat(Format));
2211 return WINED3DERR_INVALIDCALL;
2213 ModeIdx = j - 1;
2215 /* Now get the display mode via the calculated index */
2216 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0)) {
2217 pMode->Width = DevModeW.dmPelsWidth;
2218 pMode->Height = DevModeW.dmPelsHeight;
2219 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
2220 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
2221 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2223 if (Format == WINED3DFMT_UNKNOWN) {
2224 pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
2225 } else {
2226 pMode->Format = Format;
2228 } else {
2229 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
2230 return WINED3DERR_INVALIDCALL;
2233 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
2234 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format),
2235 DevModeW.dmBitsPerPel);
2238 else
2240 FIXME_(d3d_caps)("Adapter not primary display\n");
2243 return WINED3D_OK;
2246 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
2247 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2248 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
2250 if (NULL == pMode ||
2251 Adapter >= IWineD3D_GetAdapterCount(iface)) {
2252 return WINED3DERR_INVALIDCALL;
2255 if (Adapter == 0) { /* Display */
2256 int bpp = 0;
2257 DEVMODEW DevModeW;
2259 ZeroMemory(&DevModeW, sizeof(DevModeW));
2260 DevModeW.dmSize = sizeof(DevModeW);
2262 EnumDisplaySettingsExW(NULL, ENUM_CURRENT_SETTINGS, &DevModeW, 0);
2263 pMode->Width = DevModeW.dmPelsWidth;
2264 pMode->Height = DevModeW.dmPelsHeight;
2265 bpp = DevModeW.dmBitsPerPel;
2266 pMode->RefreshRate = WINED3DADAPTER_DEFAULT;
2267 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
2269 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
2272 pMode->Format = pixelformat_for_depth(bpp);
2273 } else {
2274 FIXME_(d3d_caps)("Adapter not primary display\n");
2277 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
2278 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
2279 return WINED3D_OK;
2282 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
2283 and fields being inserted in the middle, a new structure is used in place */
2284 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
2285 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
2286 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2287 size_t len;
2289 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
2291 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2292 return WINED3DERR_INVALIDCALL;
2295 /* Return the information requested */
2296 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
2298 if (pIdentifier->driver_size)
2300 len = min(strlen(This->adapters[Adapter].driver), pIdentifier->driver_size - 1);
2301 memcpy(pIdentifier->driver, This->adapters[Adapter].driver, len);
2302 pIdentifier->driver[len] = '\0';
2305 if (pIdentifier->description_size)
2307 const char *description;
2309 if (This->adapters[Adapter].gl_info.driver_description)
2310 description = This->adapters[Adapter].gl_info.driver_description;
2311 else
2312 description = This->adapters[Adapter].description;
2314 len = min(strlen(description), pIdentifier->description_size - 1);
2315 memcpy(pIdentifier->description, description, len);
2316 pIdentifier->description[len] = '\0';
2319 /* Note that d3d8 doesn't supply a device name. */
2320 if (pIdentifier->device_name_size)
2322 static const char *device_name = "\\\\.\\DISPLAY1"; /* FIXME: May depend on desktop? */
2324 len = strlen(device_name);
2325 if (len >= pIdentifier->device_name_size)
2327 ERR("Device name size too small.\n");
2328 return WINED3DERR_INVALIDCALL;
2331 memcpy(pIdentifier->device_name, device_name, len);
2332 pIdentifier->device_name[len] = '\0';
2335 pIdentifier->driver_version.u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
2336 pIdentifier->driver_version.u.LowPart = This->adapters[Adapter].gl_info.driver_version;
2337 pIdentifier->vendor_id = This->adapters[Adapter].gl_info.gl_vendor;
2338 pIdentifier->device_id = This->adapters[Adapter].gl_info.gl_card;
2339 pIdentifier->subsystem_id = 0;
2340 pIdentifier->revision = 0;
2341 memcpy(&pIdentifier->device_identifier, &IID_D3DDEVICE_D3DUID, sizeof(pIdentifier->device_identifier));
2343 if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
2345 TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
2346 pIdentifier->device_id = wined3d_settings.pci_device_id;
2349 if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
2351 TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
2352 pIdentifier->vendor_id = wined3d_settings.pci_vendor_id;
2355 pIdentifier->whql_level = (Flags & WINED3DENUM_NO_WHQL_LEVEL) ? 0 : 1;
2357 return WINED3D_OK;
2360 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const struct wined3d_gl_info *gl_info,
2361 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2363 short redSize, greenSize, blueSize, alphaSize, colorBits;
2365 if(!cfg)
2366 return FALSE;
2368 if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
2369 if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2371 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2372 return FALSE;
2375 if(cfg->redSize < redSize)
2376 return FALSE;
2378 if(cfg->greenSize < greenSize)
2379 return FALSE;
2381 if(cfg->blueSize < blueSize)
2382 return FALSE;
2384 if(cfg->alphaSize < alphaSize)
2385 return FALSE;
2387 return TRUE;
2388 } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
2389 if (format_desc->format == WINED3DFMT_R16_FLOAT)
2390 return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2391 if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
2392 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2393 if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
2394 return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
2395 if (format_desc->format == WINED3DFMT_R32_FLOAT)
2396 return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2397 if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
2398 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
2399 if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
2400 return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
2401 } else {
2402 /* Probably a color index mode */
2403 return FALSE;
2406 return FALSE;
2409 static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const struct wined3d_gl_info *gl_info,
2410 const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
2412 short depthSize, stencilSize;
2413 BOOL lockable = FALSE;
2415 if(!cfg)
2416 return FALSE;
2418 if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
2420 ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
2421 return FALSE;
2424 if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
2425 lockable = TRUE;
2427 /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
2428 * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
2429 * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
2430 if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
2431 return FALSE;
2433 /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
2434 * allow more stencil bits than requested. */
2435 if(cfg->stencilSize < stencilSize)
2436 return FALSE;
2438 return TRUE;
2441 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2442 WINED3DFORMAT AdapterFormat,
2443 WINED3DFORMAT RenderTargetFormat,
2444 WINED3DFORMAT DepthStencilFormat) {
2445 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2446 int nCfgs;
2447 const WineD3D_PixelFormat *cfgs;
2448 const struct WineD3DAdapter *adapter;
2449 const struct GlPixelFormatDesc *rt_format_desc;
2450 const struct GlPixelFormatDesc *ds_format_desc;
2451 int it;
2453 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
2454 This, Adapter,
2455 DeviceType, debug_d3ddevicetype(DeviceType),
2456 AdapterFormat, debug_d3dformat(AdapterFormat),
2457 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
2458 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
2460 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2461 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
2462 return WINED3DERR_INVALIDCALL;
2465 adapter = &This->adapters[Adapter];
2466 rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
2467 ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
2468 cfgs = adapter->cfgs;
2469 nCfgs = adapter->nCfgs;
2470 for (it = 0; it < nCfgs; ++it) {
2471 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
2473 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
2475 TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
2476 return WINED3D_OK;
2480 WARN_(d3d_caps)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat), debug_d3dformat(DepthStencilFormat));
2482 return WINED3DERR_NOTAVAILABLE;
2485 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2486 WINED3DFORMAT SurfaceFormat,
2487 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
2489 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2490 const struct GlPixelFormatDesc *glDesc;
2491 const struct WineD3DAdapter *adapter;
2493 TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
2494 This,
2495 Adapter,
2496 DeviceType, debug_d3ddevicetype(DeviceType),
2497 SurfaceFormat, debug_d3dformat(SurfaceFormat),
2498 Windowed,
2499 MultiSampleType,
2500 pQualityLevels);
2502 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2503 return WINED3DERR_INVALIDCALL;
2506 /* TODO: handle Windowed, add more quality levels */
2508 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) {
2509 if(pQualityLevels) *pQualityLevels = 1;
2510 return WINED3D_OK;
2513 /* By default multisampling is disabled right now as it causes issues
2514 * on some Nvidia driver versions and it doesn't work well in combination
2515 * with FBOs yet. */
2516 if(!wined3d_settings.allow_multisampling)
2517 return WINED3DERR_NOTAVAILABLE;
2519 adapter = &This->adapters[Adapter];
2520 glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
2521 if (!glDesc) return WINED3DERR_INVALIDCALL;
2523 if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
2524 int i, nCfgs;
2525 const WineD3D_PixelFormat *cfgs;
2527 cfgs = adapter->cfgs;
2528 nCfgs = adapter->nCfgs;
2529 for(i=0; i<nCfgs; i++) {
2530 if(cfgs[i].numSamples != MultiSampleType)
2531 continue;
2533 if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
2534 continue;
2536 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2538 if(pQualityLevels)
2539 *pQualityLevels = 1; /* Guess at a value! */
2540 return WINED3D_OK;
2543 else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
2544 short redSize, greenSize, blueSize, alphaSize, colorBits;
2545 int i, nCfgs;
2546 const WineD3D_PixelFormat *cfgs;
2548 if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
2550 ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
2551 return WINED3DERR_NOTAVAILABLE;
2554 cfgs = adapter->cfgs;
2555 nCfgs = adapter->nCfgs;
2556 for(i=0; i<nCfgs; i++) {
2557 if(cfgs[i].numSamples != MultiSampleType)
2558 continue;
2559 if(cfgs[i].redSize != redSize)
2560 continue;
2561 if(cfgs[i].greenSize != greenSize)
2562 continue;
2563 if(cfgs[i].blueSize != blueSize)
2564 continue;
2565 if(cfgs[i].alphaSize != alphaSize)
2566 continue;
2568 TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
2570 if(pQualityLevels)
2571 *pQualityLevels = 1; /* Guess at a value! */
2572 return WINED3D_OK;
2575 return WINED3DERR_NOTAVAILABLE;
2578 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
2579 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
2581 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2582 HRESULT hr = WINED3DERR_NOTAVAILABLE;
2583 UINT nmodes;
2585 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
2586 This,
2587 Adapter,
2588 DeviceType, debug_d3ddevicetype(DeviceType),
2589 DisplayFormat, debug_d3dformat(DisplayFormat),
2590 BackBufferFormat, debug_d3dformat(BackBufferFormat),
2591 Windowed);
2593 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2594 WARN_(d3d_caps)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
2595 return WINED3DERR_INVALIDCALL;
2598 /* The task of this function is to check whether a certain display / backbuffer format
2599 * combination is available on the given adapter. In fullscreen mode microsoft specified
2600 * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
2601 * and display format should match exactly.
2602 * In windowed mode format conversion can occur and this depends on the driver. When format
2603 * conversion is done, this function should nevertheless fail and applications need to use
2604 * CheckDeviceFormatConversion.
2605 * At the moment we assume that fullscreen and windowed have the same capabilities */
2607 /* There are only 4 display formats */
2608 if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
2609 (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
2610 (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
2611 (DisplayFormat == WINED3DFMT_A2R10G10B10)))
2613 TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
2614 return WINED3DERR_NOTAVAILABLE;
2617 /* If the requested DisplayFormat is not available, don't continue */
2618 nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
2619 if(!nmodes) {
2620 TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
2621 return WINED3DERR_NOTAVAILABLE;
2624 /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
2625 if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
2626 TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
2627 return WINED3DERR_NOTAVAILABLE;
2630 /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
2631 if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
2632 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2633 return WINED3DERR_NOTAVAILABLE;
2636 /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
2637 if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
2638 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2639 return WINED3DERR_NOTAVAILABLE;
2642 /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
2643 if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
2644 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2645 return WINED3DERR_NOTAVAILABLE;
2648 /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
2649 if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
2650 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2651 return WINED3DERR_NOTAVAILABLE;
2654 /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
2655 hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
2656 if(FAILED(hr))
2657 TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
2659 return hr;
2663 /* Check if we support bumpmapping for a format */
2664 static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
2665 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2667 const struct fragment_pipeline *fp;
2669 switch(format_desc->format)
2671 case WINED3DFMT_R8G8_SNORM:
2672 case WINED3DFMT_R16G16_SNORM:
2673 case WINED3DFMT_L6V5U5:
2674 case WINED3DFMT_X8L8V8U8:
2675 case WINED3DFMT_R8G8B8A8_SNORM:
2676 /* Ask the fixed function pipeline implementation if it can deal
2677 * with the conversion. If we've got a GL extension giving native
2678 * support this will be an identity conversion. */
2679 fp = select_fragment_implementation(adapter, DeviceType);
2680 if (fp->color_fixup_supported(format_desc->color_fixup))
2682 TRACE_(d3d_caps)("[OK]\n");
2683 return TRUE;
2685 TRACE_(d3d_caps)("[FAILED]\n");
2686 return FALSE;
2688 default:
2689 TRACE_(d3d_caps)("[FAILED]\n");
2690 return FALSE;
2694 /* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
2695 static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
2696 const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
2698 int it=0;
2700 /* Only allow depth/stencil formats */
2701 if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE;
2703 /* Walk through all WGL pixel formats to find a match */
2704 for (it = 0; it < adapter->nCfgs; ++it)
2706 WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
2707 if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
2709 if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
2711 return TRUE;
2716 return FALSE;
2719 static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2721 /* The flags entry of a format contains the filtering capability */
2722 if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
2724 return FALSE;
2727 /* Check the render target capabilities of a format */
2728 static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
2729 const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
2731 /* Filter out non-RT formats */
2732 if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
2734 if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
2735 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2736 int it;
2737 short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
2738 short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
2740 getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
2741 getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
2743 /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
2744 * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
2745 if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
2746 TRACE_(d3d_caps)("[FAILED]\n");
2747 return FALSE;
2750 /* Check if there is a WGL pixel format matching the requirements, the format should also be window
2751 * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
2752 for (it = 0; it < adapter->nCfgs; ++it)
2754 if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2755 &cfgs[it], check_format_desc))
2757 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2758 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2759 return TRUE;
2762 } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
2763 /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
2764 WineD3D_PixelFormat *cfgs = adapter->cfgs;
2765 int it;
2767 /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
2768 for (it = 0; it < adapter->nCfgs; ++it)
2770 if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
2771 &cfgs[it], check_format_desc))
2773 TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
2774 cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
2775 return TRUE;
2778 } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
2779 /* For now return TRUE for FBOs until we have some proper checks.
2780 * Note that this function will only be called when the format is around for texturing. */
2781 return TRUE;
2783 return FALSE;
2786 static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2788 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2790 /* Check for supported sRGB formats (Texture loading and framebuffer) */
2791 if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
2792 TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
2793 return FALSE;
2796 switch (format_desc->format)
2798 case WINED3DFMT_A8R8G8B8:
2799 case WINED3DFMT_X8R8G8B8:
2800 case WINED3DFMT_A4R4G4B4:
2801 case WINED3DFMT_L8:
2802 case WINED3DFMT_A8L8:
2803 case WINED3DFMT_DXT1:
2804 case WINED3DFMT_DXT2:
2805 case WINED3DFMT_DXT3:
2806 case WINED3DFMT_DXT4:
2807 case WINED3DFMT_DXT5:
2808 TRACE_(d3d_caps)("[OK]\n");
2809 return TRUE;
2811 default:
2812 TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
2813 return FALSE;
2815 return FALSE;
2818 static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
2819 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2821 /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
2822 * doing the color fixup in shaders.
2823 * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
2824 if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
2826 int vs_selected_mode;
2827 int ps_selected_mode;
2828 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
2830 if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
2831 TRACE_(d3d_caps)("[OK]\n");
2832 return TRUE;
2836 TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
2837 return FALSE;
2840 /* Check if a format support blending in combination with pixel shaders */
2841 static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
2842 const struct GlPixelFormatDesc *format_desc)
2844 /* The flags entry of a format contains the post pixel shader blending capability */
2845 if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
2847 return FALSE;
2850 static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
2852 /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
2853 * but we have to report mipmapping so we cannot reject this flag. Tests show that
2854 * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
2855 * that wrapping is supported. The lack of filtering will sort out the mipmapping
2856 * capability anyway.
2858 * For now lets report this on all formats, but in the future we may want to
2859 * restrict it to some should games need that
2861 return TRUE;
2864 /* Check if a texture format is supported on the given adapter */
2865 static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
2866 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
2868 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
2869 const shader_backend_t *shader_backend;
2870 const struct fragment_pipeline *fp;
2872 switch (format_desc->format)
2874 /*****
2875 * supported: RGB(A) formats
2877 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
2878 case WINED3DFMT_A8R8G8B8:
2879 case WINED3DFMT_X8R8G8B8:
2880 case WINED3DFMT_R5G6B5:
2881 case WINED3DFMT_X1R5G5B5:
2882 case WINED3DFMT_A1R5G5B5:
2883 case WINED3DFMT_A4R4G4B4:
2884 case WINED3DFMT_A8_UNORM:
2885 case WINED3DFMT_X4R4G4B4:
2886 case WINED3DFMT_R8G8B8A8_UNORM:
2887 case WINED3DFMT_X8B8G8R8:
2888 case WINED3DFMT_A2R10G10B10:
2889 case WINED3DFMT_R10G10B10A2_UNORM:
2890 case WINED3DFMT_R16G16_UNORM:
2891 TRACE_(d3d_caps)("[OK]\n");
2892 return TRUE;
2894 case WINED3DFMT_R3G3B2:
2895 TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
2896 return FALSE;
2898 /*****
2899 * supported: Palettized
2901 case WINED3DFMT_P8:
2902 TRACE_(d3d_caps)("[OK]\n");
2903 return TRUE;
2904 /* No Windows driver offers A8P8, so don't offer it either */
2905 case WINED3DFMT_A8P8:
2906 return FALSE;
2908 /*****
2909 * Supported: (Alpha)-Luminance
2911 case WINED3DFMT_L8:
2912 case WINED3DFMT_A8L8:
2913 case WINED3DFMT_L16:
2914 TRACE_(d3d_caps)("[OK]\n");
2915 return TRUE;
2917 /* Not supported on Windows, thus disabled */
2918 case WINED3DFMT_A4L4:
2919 TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
2920 return FALSE;
2922 /*****
2923 * Supported: Depth/Stencil formats
2925 case WINED3DFMT_D16_LOCKABLE:
2926 case WINED3DFMT_D16_UNORM:
2927 case WINED3DFMT_D15S1:
2928 case WINED3DFMT_D24X8:
2929 case WINED3DFMT_D24X4S4:
2930 case WINED3DFMT_D24S8:
2931 case WINED3DFMT_D24FS8:
2932 case WINED3DFMT_D32:
2933 case WINED3DFMT_D32F_LOCKABLE:
2934 return TRUE;
2936 /*****
2937 * Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
2938 * GL_NV_texture_shader). Emulated by shaders
2940 case WINED3DFMT_R8G8_SNORM:
2941 case WINED3DFMT_X8L8V8U8:
2942 case WINED3DFMT_L6V5U5:
2943 case WINED3DFMT_R8G8B8A8_SNORM:
2944 case WINED3DFMT_R16G16_SNORM:
2945 /* Ask the shader backend if it can deal with the conversion. If
2946 * we've got a GL extension giving native support this will be an
2947 * identity conversion. */
2948 shader_backend = select_shader_backend(adapter, DeviceType);
2949 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
2951 TRACE_(d3d_caps)("[OK]\n");
2952 return TRUE;
2954 TRACE_(d3d_caps)("[FAILED]\n");
2955 return FALSE;
2957 case WINED3DFMT_DXT1:
2958 case WINED3DFMT_DXT2:
2959 case WINED3DFMT_DXT3:
2960 case WINED3DFMT_DXT4:
2961 case WINED3DFMT_DXT5:
2962 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
2963 TRACE_(d3d_caps)("[OK]\n");
2964 return TRUE;
2966 TRACE_(d3d_caps)("[FAILED]\n");
2967 return FALSE;
2970 /*****
2971 * Odd formats - not supported
2973 case WINED3DFMT_VERTEXDATA:
2974 case WINED3DFMT_R16_UINT:
2975 case WINED3DFMT_R32_UINT:
2976 case WINED3DFMT_R16G16B16A16_SNORM:
2977 case WINED3DFMT_A2W10V10U10:
2978 case WINED3DFMT_W11V11U10:
2979 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2980 return FALSE;
2982 /*****
2983 * WINED3DFMT_CxV8U8: Not supported right now
2985 case WINED3DFMT_CxV8U8:
2986 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
2987 return FALSE;
2989 /* YUV formats */
2990 case WINED3DFMT_UYVY:
2991 case WINED3DFMT_YUY2:
2992 if(GL_SUPPORT(APPLE_YCBCR_422)) {
2993 TRACE_(d3d_caps)("[OK]\n");
2994 return TRUE;
2996 TRACE_(d3d_caps)("[FAILED]\n");
2997 return FALSE;
2998 case WINED3DFMT_YV12:
2999 TRACE_(d3d_caps)("[FAILED]\n");
3000 return FALSE;
3002 /* Not supported */
3003 case WINED3DFMT_R16G16B16A16_UNORM:
3004 case WINED3DFMT_A8R3G3B2:
3005 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
3006 return FALSE;
3008 /* Floating point formats */
3009 case WINED3DFMT_R16_FLOAT:
3010 case WINED3DFMT_R16G16_FLOAT:
3011 case WINED3DFMT_R16G16B16A16_FLOAT:
3012 if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
3013 TRACE_(d3d_caps)("[OK]\n");
3014 return TRUE;
3016 TRACE_(d3d_caps)("[FAILED]\n");
3017 return FALSE;
3019 case WINED3DFMT_R32_FLOAT:
3020 case WINED3DFMT_R32G32_FLOAT:
3021 case WINED3DFMT_R32G32B32A32_FLOAT:
3022 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3023 TRACE_(d3d_caps)("[OK]\n");
3024 return TRUE;
3026 TRACE_(d3d_caps)("[FAILED]\n");
3027 return FALSE;
3029 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
3030 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
3031 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
3032 * We can do instancing with all shader versions, but we need vertex shaders.
3034 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
3035 * to enable instancing. WineD3D doesn't need that and just ignores it.
3037 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
3039 case WINEMAKEFOURCC('I','N','S','T'):
3040 TRACE("ATI Instancing check hack\n");
3041 if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
3042 TRACE_(d3d_caps)("[OK]\n");
3043 return TRUE;
3045 TRACE_(d3d_caps)("[FAILED]\n");
3046 return FALSE;
3048 /* Some weird FOURCC formats */
3049 case WINED3DFMT_R8G8_B8G8:
3050 case WINED3DFMT_G8R8_G8B8:
3051 case WINED3DFMT_MULTI2_ARGB8:
3052 TRACE_(d3d_caps)("[FAILED]\n");
3053 return FALSE;
3055 /* Vendor specific formats */
3056 case WINED3DFMT_ATI2N:
3057 if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
3058 shader_backend = select_shader_backend(adapter, DeviceType);
3059 fp = select_fragment_implementation(adapter, DeviceType);
3060 if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
3061 && fp->color_fixup_supported(format_desc->color_fixup))
3063 TRACE_(d3d_caps)("[OK]\n");
3064 return TRUE;
3067 TRACE_(d3d_caps)("[OK]\n");
3068 return TRUE;
3070 TRACE_(d3d_caps)("[FAILED]\n");
3071 return FALSE;
3073 case WINED3DFMT_NVHU:
3074 case WINED3DFMT_NVHS:
3075 /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
3076 * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
3077 * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
3078 * ATI refused to support formats which can easilly be emulated with pixel shaders, so
3079 * Applications have to deal with not having NVHS and NVHU.
3081 TRACE_(d3d_caps)("[FAILED]\n");
3082 return FALSE;
3084 case WINED3DFMT_UNKNOWN:
3085 return FALSE;
3087 default:
3088 ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
3089 break;
3091 return FALSE;
3094 static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
3095 WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
3097 const struct blit_shader *blitter;
3099 if(SurfaceType == SURFACE_GDI) {
3100 switch(check_format_desc->format)
3102 case WINED3DFMT_R8G8B8:
3103 case WINED3DFMT_A8R8G8B8:
3104 case WINED3DFMT_X8R8G8B8:
3105 case WINED3DFMT_R5G6B5:
3106 case WINED3DFMT_X1R5G5B5:
3107 case WINED3DFMT_A1R5G5B5:
3108 case WINED3DFMT_A4R4G4B4:
3109 case WINED3DFMT_R3G3B2:
3110 case WINED3DFMT_A8_UNORM:
3111 case WINED3DFMT_A8R3G3B2:
3112 case WINED3DFMT_X4R4G4B4:
3113 case WINED3DFMT_R10G10B10A2_UNORM:
3114 case WINED3DFMT_R8G8B8A8_UNORM:
3115 case WINED3DFMT_X8B8G8R8:
3116 case WINED3DFMT_R16G16_UNORM:
3117 case WINED3DFMT_A2R10G10B10:
3118 case WINED3DFMT_R16G16B16A16_UNORM:
3119 case WINED3DFMT_P8:
3120 TRACE_(d3d_caps)("[OK]\n");
3121 return TRUE;
3122 default:
3123 TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
3124 return FALSE;
3128 /* All format that are supported for textures are supported for surfaces as well */
3129 if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
3130 /* All depth stencil formats are supported on surfaces */
3131 if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
3133 /* If opengl can't process the format natively, the blitter may be able to convert it */
3134 blitter = select_blit_implementation(adapter, DeviceType);
3135 if (blitter->color_fixup_supported(check_format_desc->color_fixup))
3137 TRACE_(d3d_caps)("[OK]\n");
3138 return TRUE;
3141 /* Reject other formats */
3142 TRACE_(d3d_caps)("[FAILED]\n");
3143 return FALSE;
3146 static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
3148 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3150 if (!GL_LIMITS(vertex_samplers)) {
3151 TRACE_(d3d_caps)("[FAILED]\n");
3152 return FALSE;
3155 switch (format_desc->format)
3157 case WINED3DFMT_R32G32B32A32_FLOAT:
3158 if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
3159 TRACE_(d3d_caps)("[FAILED]\n");
3160 return FALSE;
3162 TRACE_(d3d_caps)("[OK]\n");
3163 return TRUE;
3165 default:
3166 TRACE_(d3d_caps)("[FAILED]\n");
3167 return FALSE;
3169 return FALSE;
3172 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3173 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
3174 WINED3DSURFTYPE SurfaceType) {
3175 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3176 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3177 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3178 const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
3179 const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
3180 DWORD UsageCaps = 0;
3182 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
3183 This,
3184 Adapter,
3185 DeviceType, debug_d3ddevicetype(DeviceType),
3186 AdapterFormat, debug_d3dformat(AdapterFormat),
3187 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
3188 RType, debug_d3dresourcetype(RType),
3189 CheckFormat, debug_d3dformat(CheckFormat));
3191 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3192 return WINED3DERR_INVALIDCALL;
3195 if(RType == WINED3DRTYPE_CUBETEXTURE) {
3197 if(SurfaceType != SURFACE_OPENGL) {
3198 TRACE("[FAILED]\n");
3199 return WINED3DERR_NOTAVAILABLE;
3202 /* Cubetexture allows:
3203 * - D3DUSAGE_AUTOGENMIPMAP
3204 * - D3DUSAGE_DEPTHSTENCIL
3205 * - D3DUSAGE_DYNAMIC
3206 * - D3DUSAGE_NONSECURE (d3d9ex)
3207 * - D3DUSAGE_RENDERTARGET
3208 * - D3DUSAGE_SOFTWAREPROCESSING
3209 * - D3DUSAGE_QUERY_WRAPANDMIP
3211 if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3212 /* Check if the texture format is around */
3213 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3215 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3216 /* Check for automatic mipmap generation support */
3217 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3218 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3219 } else {
3220 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3221 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3225 /* Always report dynamic locking */
3226 if(Usage & WINED3DUSAGE_DYNAMIC)
3227 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3229 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3230 if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3232 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3233 } else {
3234 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3235 return WINED3DERR_NOTAVAILABLE;
3239 /* Always report software processing */
3240 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3241 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3243 /* Check QUERY_FILTER support */
3244 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3245 if (CheckFilterCapability(adapter, format_desc))
3247 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3248 } else {
3249 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3250 return WINED3DERR_NOTAVAILABLE;
3254 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3255 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3256 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3258 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3259 } else {
3260 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3261 return WINED3DERR_NOTAVAILABLE;
3265 /* Check QUERY_SRGBREAD support */
3266 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3267 if (CheckSrgbReadCapability(adapter, format_desc))
3269 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3270 } else {
3271 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3272 return WINED3DERR_NOTAVAILABLE;
3276 /* Check QUERY_SRGBWRITE support */
3277 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3278 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3280 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3281 } else {
3282 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3283 return WINED3DERR_NOTAVAILABLE;
3287 /* Check QUERY_VERTEXTEXTURE support */
3288 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3289 if (CheckVertexTextureCapability(adapter, format_desc))
3291 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3292 } else {
3293 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3294 return WINED3DERR_NOTAVAILABLE;
3298 /* Check QUERY_WRAPANDMIP support */
3299 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3300 if (CheckWrapAndMipCapability(adapter, format_desc))
3302 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3303 } else {
3304 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3305 return WINED3DERR_NOTAVAILABLE;
3308 } else {
3309 TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
3310 return WINED3DERR_NOTAVAILABLE;
3312 } else {
3313 TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
3314 return WINED3DERR_NOTAVAILABLE;
3316 } else if(RType == WINED3DRTYPE_SURFACE) {
3317 /* Surface allows:
3318 * - D3DUSAGE_DEPTHSTENCIL
3319 * - D3DUSAGE_NONSECURE (d3d9ex)
3320 * - D3DUSAGE_RENDERTARGET
3323 if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
3325 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3326 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3328 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3329 } else {
3330 TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
3331 return WINED3DERR_NOTAVAILABLE;
3335 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3336 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3338 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3339 } else {
3340 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3341 return WINED3DERR_NOTAVAILABLE;
3345 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3346 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3347 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3349 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3350 } else {
3351 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3352 return WINED3DERR_NOTAVAILABLE;
3355 } else {
3356 TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
3357 return WINED3DERR_NOTAVAILABLE;
3360 } else if(RType == WINED3DRTYPE_TEXTURE) {
3361 /* Texture allows:
3362 * - D3DUSAGE_AUTOGENMIPMAP
3363 * - D3DUSAGE_DEPTHSTENCIL
3364 * - D3DUSAGE_DMAP
3365 * - D3DUSAGE_DYNAMIC
3366 * - D3DUSAGE_NONSECURE (d3d9ex)
3367 * - D3DUSAGE_RENDERTARGET
3368 * - D3DUSAGE_SOFTWAREPROCESSING
3369 * - D3DUSAGE_TEXTAPI (d3d9ex)
3370 * - D3DUSAGE_QUERY_WRAPANDMIP
3373 if(SurfaceType != SURFACE_OPENGL) {
3374 TRACE("[FAILED]\n");
3375 return WINED3DERR_NOTAVAILABLE;
3378 /* Check if the texture format is around */
3379 if (CheckTextureCapability(adapter, DeviceType, format_desc))
3381 if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
3382 /* Check for automatic mipmap generation support */
3383 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3384 UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
3385 } else {
3386 /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
3387 TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
3391 /* Always report dynamic locking */
3392 if(Usage & WINED3DUSAGE_DYNAMIC)
3393 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3395 if(Usage & WINED3DUSAGE_RENDERTARGET) {
3396 if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
3398 UsageCaps |= WINED3DUSAGE_RENDERTARGET;
3399 } else {
3400 TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
3401 return WINED3DERR_NOTAVAILABLE;
3405 /* Always report software processing */
3406 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3407 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3409 /* Check QUERY_FILTER support */
3410 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3411 if (CheckFilterCapability(adapter, format_desc))
3413 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3414 } else {
3415 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3416 return WINED3DERR_NOTAVAILABLE;
3420 /* Check QUERY_LEGACYBUMPMAP support */
3421 if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
3422 if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
3424 UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
3425 } else {
3426 TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
3427 return WINED3DERR_NOTAVAILABLE;
3431 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3432 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3433 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3435 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3436 } else {
3437 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3438 return WINED3DERR_NOTAVAILABLE;
3442 /* Check QUERY_SRGBREAD support */
3443 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3444 if (CheckSrgbReadCapability(adapter, format_desc))
3446 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3447 } else {
3448 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3449 return WINED3DERR_NOTAVAILABLE;
3453 /* Check QUERY_SRGBWRITE support */
3454 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3455 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3457 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3458 } else {
3459 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3460 return WINED3DERR_NOTAVAILABLE;
3464 /* Check QUERY_VERTEXTEXTURE support */
3465 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3466 if (CheckVertexTextureCapability(adapter, format_desc))
3468 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3469 } else {
3470 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3471 return WINED3DERR_NOTAVAILABLE;
3475 /* Check QUERY_WRAPANDMIP support */
3476 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3477 if (CheckWrapAndMipCapability(adapter, format_desc))
3479 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3480 } else {
3481 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3482 return WINED3DERR_NOTAVAILABLE;
3486 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
3487 if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
3489 UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
3490 } else {
3491 TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
3492 return WINED3DERR_NOTAVAILABLE;
3495 } else {
3496 TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
3497 return WINED3DERR_NOTAVAILABLE;
3499 } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
3500 /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
3501 * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
3503 * Volumetexture allows:
3504 * - D3DUSAGE_DYNAMIC
3505 * - D3DUSAGE_NONSECURE (d3d9ex)
3506 * - D3DUSAGE_SOFTWAREPROCESSING
3507 * - D3DUSAGE_QUERY_WRAPANDMIP
3510 if(SurfaceType != SURFACE_OPENGL) {
3511 TRACE("[FAILED]\n");
3512 return WINED3DERR_NOTAVAILABLE;
3515 /* Check volume texture and volume usage caps */
3516 if(GL_SUPPORT(EXT_TEXTURE3D)) {
3517 if (!CheckTextureCapability(adapter, DeviceType, format_desc))
3519 TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
3520 return WINED3DERR_NOTAVAILABLE;
3523 /* Always report dynamic locking */
3524 if(Usage & WINED3DUSAGE_DYNAMIC)
3525 UsageCaps |= WINED3DUSAGE_DYNAMIC;
3527 /* Always report software processing */
3528 if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
3529 UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
3531 /* Check QUERY_FILTER support */
3532 if(Usage & WINED3DUSAGE_QUERY_FILTER) {
3533 if (CheckFilterCapability(adapter, format_desc))
3535 UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
3536 } else {
3537 TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
3538 return WINED3DERR_NOTAVAILABLE;
3542 /* Check QUERY_POSTPIXELSHADER_BLENDING support */
3543 if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
3544 if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
3546 UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
3547 } else {
3548 TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
3549 return WINED3DERR_NOTAVAILABLE;
3553 /* Check QUERY_SRGBREAD support */
3554 if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
3555 if (CheckSrgbReadCapability(adapter, format_desc))
3557 UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
3558 } else {
3559 TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
3560 return WINED3DERR_NOTAVAILABLE;
3564 /* Check QUERY_SRGBWRITE support */
3565 if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
3566 if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
3568 UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
3569 } else {
3570 TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
3571 return WINED3DERR_NOTAVAILABLE;
3575 /* Check QUERY_VERTEXTEXTURE support */
3576 if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
3577 if (CheckVertexTextureCapability(adapter, format_desc))
3579 UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
3580 } else {
3581 TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
3582 return WINED3DERR_NOTAVAILABLE;
3586 /* Check QUERY_WRAPANDMIP support */
3587 if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
3588 if (CheckWrapAndMipCapability(adapter, format_desc))
3590 UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
3591 } else {
3592 TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
3593 return WINED3DERR_NOTAVAILABLE;
3596 } else {
3597 TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
3598 return WINED3DERR_NOTAVAILABLE;
3601 /* Filter formats that need conversion; For one part, this conversion is unimplemented,
3602 * and volume textures are huge, so it would be a big performance hit. Unless we hit an
3603 * app needing one of those formats, don't advertize them to avoid leading apps into
3604 * temptation. The windows drivers don't support most of those formats on volumes anyway,
3605 * except of R32F.
3607 switch(CheckFormat) {
3608 case WINED3DFMT_P8:
3609 case WINED3DFMT_A4L4:
3610 case WINED3DFMT_R32_FLOAT:
3611 case WINED3DFMT_R16_FLOAT:
3612 case WINED3DFMT_X8L8V8U8:
3613 case WINED3DFMT_L6V5U5:
3614 case WINED3DFMT_R16G16_UNORM:
3615 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3616 return WINED3DERR_NOTAVAILABLE;
3618 case WINED3DFMT_R8G8B8A8_SNORM:
3619 case WINED3DFMT_R16G16_SNORM:
3620 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3621 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3622 return WINED3DERR_NOTAVAILABLE;
3624 break;
3626 case WINED3DFMT_R8G8_SNORM:
3627 if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
3628 TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
3629 return WINED3DERR_NOTAVAILABLE;
3631 break;
3633 case WINED3DFMT_DXT1:
3634 case WINED3DFMT_DXT2:
3635 case WINED3DFMT_DXT3:
3636 case WINED3DFMT_DXT4:
3637 case WINED3DFMT_DXT5:
3638 /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
3639 * compressed texture results in an error. While the D3D refrast does
3640 * support s3tc volumes, at least the nvidia windows driver does not, so
3641 * we're free not to support this format.
3643 TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
3644 return WINED3DERR_NOTAVAILABLE;
3646 default:
3647 /* Do nothing, continue with checking the format below */
3648 break;
3650 } else if(RType == WINED3DRTYPE_BUFFER){
3651 /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
3652 TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
3653 return WINED3DERR_NOTAVAILABLE;
3656 /* This format is nothing special and it is supported perfectly.
3657 * However, ati and nvidia driver on windows do not mark this format as
3658 * supported (tested with the dxCapsViewer) and pretending to
3659 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
3660 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
3661 * Enable it on dx7. It will need additional checking on dx10 when we support it.
3663 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
3664 TRACE_(d3d_caps)("[FAILED]\n");
3665 return WINED3DERR_NOTAVAILABLE;
3668 /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
3669 * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
3670 * usage flags match. */
3671 if(UsageCaps == Usage) {
3672 return WINED3D_OK;
3673 } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
3674 return WINED3DOK_NOAUTOGEN;
3675 } else {
3676 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);
3677 return WINED3DERR_NOTAVAILABLE;
3681 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
3682 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
3683 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3685 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
3686 This,
3687 Adapter,
3688 DeviceType, debug_d3ddevicetype(DeviceType),
3689 SourceFormat, debug_d3dformat(SourceFormat),
3690 TargetFormat, debug_d3dformat(TargetFormat));
3691 return WINED3D_OK;
3694 static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3696 const shader_backend_t *ret;
3697 int vs_selected_mode;
3698 int ps_selected_mode;
3700 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3701 if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
3702 ret = &glsl_shader_backend;
3703 } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
3704 ret = &arb_program_shader_backend;
3705 } else {
3706 ret = &none_shader_backend;
3708 return ret;
3711 static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
3712 WINED3DDEVTYPE DeviceType)
3714 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3715 int vs_selected_mode;
3716 int ps_selected_mode;
3718 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3719 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3720 return &arbfp_fragment_pipeline;
3721 } else if(ps_selected_mode == SHADER_ATI) {
3722 return &atifs_fragment_pipeline;
3723 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
3724 return &nvts_fragment_pipeline;
3725 } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3726 return &nvrc_fragment_pipeline;
3727 } else {
3728 return &ffp_fragment_pipeline;
3732 static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
3734 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3735 int vs_selected_mode;
3736 int ps_selected_mode;
3738 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3739 if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
3740 return &arbfp_blit;
3741 } else {
3742 return &ffp_blit;
3746 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
3747 subset of a D3DCAPS9 structure. However, it has to come via a void *
3748 as the d3d8 interface cannot import the d3d9 header */
3749 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
3751 IWineD3DImpl *This = (IWineD3DImpl *)iface;
3752 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
3753 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
3754 int vs_selected_mode;
3755 int ps_selected_mode;
3756 struct shader_caps shader_caps;
3757 struct fragment_caps fragment_caps;
3758 const shader_backend_t *shader_backend;
3759 const struct fragment_pipeline *frag_pipeline = NULL;
3760 DWORD ckey_caps, blit_caps, fx_caps;
3762 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
3764 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
3765 return WINED3DERR_INVALIDCALL;
3768 select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
3770 /* This function should *not* be modifying GL caps
3771 * TODO: move the functionality where it belongs */
3772 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
3774 /* ------------------------------------------------
3775 The following fields apply to both d3d8 and d3d9
3776 ------------------------------------------------ */
3777 pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
3778 pCaps->AdapterOrdinal = Adapter;
3780 pCaps->Caps = 0;
3781 pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
3782 WINED3DCAPS2_FULLSCREENGAMMA |
3783 WINED3DCAPS2_DYNAMICTEXTURES;
3784 if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
3785 pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
3788 pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
3789 WINED3DCAPS3_COPY_TO_VIDMEM |
3790 WINED3DCAPS3_COPY_TO_SYSTEMMEM;
3792 pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
3793 WINED3DPRESENT_INTERVAL_ONE;
3795 pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
3796 WINED3DCURSORCAPS_LOWRES;
3798 pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
3799 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
3800 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
3801 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3802 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
3803 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
3804 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
3805 WINED3DDEVCAPS_PUREDEVICE |
3806 WINED3DDEVCAPS_HWRASTERIZATION |
3807 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
3808 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
3809 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
3810 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
3811 WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
3812 WINED3DDEVCAPS_RTPATCHES;
3814 pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
3815 WINED3DPMISCCAPS_CULLCCW |
3816 WINED3DPMISCCAPS_CULLCW |
3817 WINED3DPMISCCAPS_COLORWRITEENABLE |
3818 WINED3DPMISCCAPS_CLIPTLVERTS |
3819 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
3820 WINED3DPMISCCAPS_MASKZ |
3821 WINED3DPMISCCAPS_BLENDOP |
3822 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
3823 /* TODO:
3824 WINED3DPMISCCAPS_NULLREFERENCE
3825 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
3826 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
3827 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
3828 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
3830 if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
3831 pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
3833 pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
3834 WINED3DPRASTERCAPS_PAT |
3835 WINED3DPRASTERCAPS_WFOG |
3836 WINED3DPRASTERCAPS_ZFOG |
3837 WINED3DPRASTERCAPS_FOGVERTEX |
3838 WINED3DPRASTERCAPS_FOGTABLE |
3839 WINED3DPRASTERCAPS_STIPPLE |
3840 WINED3DPRASTERCAPS_SUBPIXEL |
3841 WINED3DPRASTERCAPS_ZTEST |
3842 WINED3DPRASTERCAPS_SCISSORTEST |
3843 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
3844 WINED3DPRASTERCAPS_DEPTHBIAS;
3846 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3847 pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
3848 WINED3DPRASTERCAPS_ZBIAS |
3849 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
3851 if(GL_SUPPORT(NV_FOG_DISTANCE)) {
3852 pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
3854 /* FIXME Add:
3855 WINED3DPRASTERCAPS_COLORPERSPECTIVE
3856 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
3857 WINED3DPRASTERCAPS_ANTIALIASEDGES
3858 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
3859 WINED3DPRASTERCAPS_WBUFFER */
3861 pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3862 WINED3DPCMPCAPS_EQUAL |
3863 WINED3DPCMPCAPS_GREATER |
3864 WINED3DPCMPCAPS_GREATEREQUAL |
3865 WINED3DPCMPCAPS_LESS |
3866 WINED3DPCMPCAPS_LESSEQUAL |
3867 WINED3DPCMPCAPS_NEVER |
3868 WINED3DPCMPCAPS_NOTEQUAL;
3870 pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
3871 WINED3DPBLENDCAPS_BOTHSRCALPHA |
3872 WINED3DPBLENDCAPS_DESTALPHA |
3873 WINED3DPBLENDCAPS_DESTCOLOR |
3874 WINED3DPBLENDCAPS_INVDESTALPHA |
3875 WINED3DPBLENDCAPS_INVDESTCOLOR |
3876 WINED3DPBLENDCAPS_INVSRCALPHA |
3877 WINED3DPBLENDCAPS_INVSRCCOLOR |
3878 WINED3DPBLENDCAPS_ONE |
3879 WINED3DPBLENDCAPS_SRCALPHA |
3880 WINED3DPBLENDCAPS_SRCALPHASAT |
3881 WINED3DPBLENDCAPS_SRCCOLOR |
3882 WINED3DPBLENDCAPS_ZERO;
3884 pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
3885 WINED3DPBLENDCAPS_DESTCOLOR |
3886 WINED3DPBLENDCAPS_INVDESTALPHA |
3887 WINED3DPBLENDCAPS_INVDESTCOLOR |
3888 WINED3DPBLENDCAPS_INVSRCALPHA |
3889 WINED3DPBLENDCAPS_INVSRCCOLOR |
3890 WINED3DPBLENDCAPS_ONE |
3891 WINED3DPBLENDCAPS_SRCALPHA |
3892 WINED3DPBLENDCAPS_SRCCOLOR |
3893 WINED3DPBLENDCAPS_ZERO;
3894 /* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
3895 * according to the glBlendFunc manpage
3897 * WINED3DPBLENDCAPS_BOTHINVSRCALPHA and WINED3DPBLENDCAPS_BOTHSRCALPHA are
3898 * legacy settings for srcblend only
3901 if( GL_SUPPORT(EXT_BLEND_COLOR)) {
3902 pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3903 pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
3907 pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
3908 WINED3DPCMPCAPS_EQUAL |
3909 WINED3DPCMPCAPS_GREATER |
3910 WINED3DPCMPCAPS_GREATEREQUAL |
3911 WINED3DPCMPCAPS_LESS |
3912 WINED3DPCMPCAPS_LESSEQUAL |
3913 WINED3DPCMPCAPS_NEVER |
3914 WINED3DPCMPCAPS_NOTEQUAL;
3916 pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
3917 WINED3DPSHADECAPS_COLORGOURAUDRGB |
3918 WINED3DPSHADECAPS_ALPHAFLATBLEND |
3919 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
3920 WINED3DPSHADECAPS_COLORFLATRGB |
3921 WINED3DPSHADECAPS_FOGFLAT |
3922 WINED3DPSHADECAPS_FOGGOURAUD |
3923 WINED3DPSHADECAPS_SPECULARFLATRGB;
3925 pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
3926 WINED3DPTEXTURECAPS_ALPHAPALETTE |
3927 WINED3DPTEXTURECAPS_TRANSPARENCY |
3928 WINED3DPTEXTURECAPS_BORDER |
3929 WINED3DPTEXTURECAPS_MIPMAP |
3930 WINED3DPTEXTURECAPS_PROJECTED |
3931 WINED3DPTEXTURECAPS_PERSPECTIVE;
3933 if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
3934 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
3935 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
3938 if( GL_SUPPORT(EXT_TEXTURE3D)) {
3939 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
3940 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
3941 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
3944 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3945 pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
3946 WINED3DPTEXTURECAPS_MIPCUBEMAP |
3947 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
3951 pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3952 WINED3DPTFILTERCAPS_MAGFPOINT |
3953 WINED3DPTFILTERCAPS_MINFLINEAR |
3954 WINED3DPTFILTERCAPS_MINFPOINT |
3955 WINED3DPTFILTERCAPS_MIPFLINEAR |
3956 WINED3DPTFILTERCAPS_MIPFPOINT |
3957 WINED3DPTFILTERCAPS_LINEAR |
3958 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3959 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3960 WINED3DPTFILTERCAPS_MIPLINEAR |
3961 WINED3DPTFILTERCAPS_MIPNEAREST |
3962 WINED3DPTFILTERCAPS_NEAREST;
3964 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3965 pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3966 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3969 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
3970 pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3971 WINED3DPTFILTERCAPS_MAGFPOINT |
3972 WINED3DPTFILTERCAPS_MINFLINEAR |
3973 WINED3DPTFILTERCAPS_MINFPOINT |
3974 WINED3DPTFILTERCAPS_MIPFLINEAR |
3975 WINED3DPTFILTERCAPS_MIPFPOINT |
3976 WINED3DPTFILTERCAPS_LINEAR |
3977 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3978 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
3979 WINED3DPTFILTERCAPS_MIPLINEAR |
3980 WINED3DPTFILTERCAPS_MIPNEAREST |
3981 WINED3DPTFILTERCAPS_NEAREST;
3983 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3984 pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
3985 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
3987 } else
3988 pCaps->CubeTextureFilterCaps = 0;
3990 if (GL_SUPPORT(EXT_TEXTURE3D)) {
3991 pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
3992 WINED3DPTFILTERCAPS_MAGFPOINT |
3993 WINED3DPTFILTERCAPS_MINFLINEAR |
3994 WINED3DPTFILTERCAPS_MINFPOINT |
3995 WINED3DPTFILTERCAPS_MIPFLINEAR |
3996 WINED3DPTFILTERCAPS_MIPFPOINT |
3997 WINED3DPTFILTERCAPS_LINEAR |
3998 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
3999 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
4000 WINED3DPTFILTERCAPS_MIPLINEAR |
4001 WINED3DPTFILTERCAPS_MIPNEAREST |
4002 WINED3DPTFILTERCAPS_NEAREST;
4003 } else
4004 pCaps->VolumeTextureFilterCaps = 0;
4006 pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4007 WINED3DPTADDRESSCAPS_CLAMP |
4008 WINED3DPTADDRESSCAPS_WRAP;
4010 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
4011 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4013 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
4014 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4016 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
4017 pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4020 if (GL_SUPPORT(EXT_TEXTURE3D)) {
4021 pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
4022 WINED3DPTADDRESSCAPS_CLAMP |
4023 WINED3DPTADDRESSCAPS_WRAP;
4024 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
4025 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
4027 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
4028 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
4030 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
4031 pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
4033 } else
4034 pCaps->VolumeTextureAddressCaps = 0;
4036 pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
4037 WINED3DLINECAPS_ZTEST |
4038 WINED3DLINECAPS_BLEND |
4039 WINED3DLINECAPS_ALPHACMP |
4040 WINED3DLINECAPS_FOG;
4041 /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
4042 * idea how generating the smoothing alpha values works; the result is different
4045 pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
4046 pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
4048 if(GL_SUPPORT(EXT_TEXTURE3D))
4049 pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
4050 else
4051 pCaps->MaxVolumeExtent = 0;
4053 pCaps->MaxTextureRepeat = 32768;
4054 pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
4055 pCaps->MaxVertexW = 1.0f;
4057 pCaps->GuardBandLeft = 0.0f;
4058 pCaps->GuardBandTop = 0.0f;
4059 pCaps->GuardBandRight = 0.0f;
4060 pCaps->GuardBandBottom = 0.0f;
4062 pCaps->ExtentsAdjust = 0.0f;
4064 pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
4065 WINED3DSTENCILCAPS_INCRSAT |
4066 WINED3DSTENCILCAPS_INVERT |
4067 WINED3DSTENCILCAPS_KEEP |
4068 WINED3DSTENCILCAPS_REPLACE |
4069 WINED3DSTENCILCAPS_ZERO;
4070 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
4071 pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
4072 WINED3DSTENCILCAPS_INCR;
4074 if ( This->dxVersion > 8 &&
4075 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
4076 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
4077 pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
4080 pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
4082 pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
4083 pCaps->MaxActiveLights = GL_LIMITS(lights);
4085 pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
4086 pCaps->MaxVertexBlendMatrixIndex = 0;
4088 pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
4089 pCaps->MaxPointSize = GL_LIMITS(pointsize);
4092 pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
4093 WINED3DVTXPCAPS_MATERIALSOURCE7 |
4094 WINED3DVTXPCAPS_POSITIONALLIGHTS |
4095 WINED3DVTXPCAPS_LOCALVIEWER |
4096 WINED3DVTXPCAPS_VERTEXFOG |
4097 WINED3DVTXPCAPS_TEXGEN;
4098 /* FIXME: Add
4099 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
4101 pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
4102 pCaps->MaxVertexIndex = 0xFFFFF;
4103 pCaps->MaxStreams = MAX_STREAMS;
4104 pCaps->MaxStreamStride = 1024;
4106 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
4107 pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
4108 WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
4109 pCaps->MaxNpatchTessellationLevel = 0;
4110 pCaps->MasterAdapterOrdinal = 0;
4111 pCaps->AdapterOrdinalInGroup = 0;
4112 pCaps->NumberOfAdaptersInGroup = 1;
4114 pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
4116 pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
4117 WINED3DPTFILTERCAPS_MAGFPOINT |
4118 WINED3DPTFILTERCAPS_MINFLINEAR |
4119 WINED3DPTFILTERCAPS_MAGFLINEAR;
4120 pCaps->VertexTextureFilterCaps = 0;
4122 memset(&shader_caps, 0, sizeof(shader_caps));
4123 shader_backend = select_shader_backend(adapter, DeviceType);
4124 shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4126 memset(&fragment_caps, 0, sizeof(fragment_caps));
4127 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4128 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
4130 /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
4131 pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
4133 /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
4134 * Ignore shader model capabilities if disabled in config
4136 if(vs_selected_mode == SHADER_NONE) {
4137 TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
4138 pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
4139 pCaps->MaxVertexShaderConst = 0;
4140 } else {
4141 pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
4142 pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
4145 if(ps_selected_mode == SHADER_NONE) {
4146 TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
4147 pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
4148 pCaps->PixelShader1xMaxValue = 0.0f;
4149 } else {
4150 pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
4151 pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
4154 pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
4155 pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
4156 pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
4158 pCaps->VS20Caps = shader_caps.VS20Caps;
4159 pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
4160 pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
4161 pCaps->PS20Caps = shader_caps.PS20Caps;
4162 pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
4163 pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
4165 /* The following caps are shader specific, but they are things we cannot detect, or which
4166 * are the same among all shader models. So to avoid code duplication set the shader version
4167 * specific, but otherwise constant caps here
4169 if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
4170 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4171 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
4172 pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
4173 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4174 pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
4175 pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
4177 pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
4178 pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
4179 } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
4180 pCaps->VS20Caps.Caps = 0;
4181 pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
4182 pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
4183 pCaps->VS20Caps.StaticFlowControlDepth = 1;
4185 pCaps->MaxVShaderInstructionsExecuted = 65535;
4186 pCaps->MaxVertexShader30InstructionSlots = 0;
4187 } else { /* VS 1.x */
4188 pCaps->VS20Caps.Caps = 0;
4189 pCaps->VS20Caps.DynamicFlowControlDepth = 0;
4190 pCaps->VS20Caps.NumTemps = 0;
4191 pCaps->VS20Caps.StaticFlowControlDepth = 0;
4193 pCaps->MaxVShaderInstructionsExecuted = 0;
4194 pCaps->MaxVertexShader30InstructionSlots = 0;
4197 if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
4198 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
4199 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
4201 /* 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 */
4202 pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
4203 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
4204 WINED3DPS20CAPS_PREDICATION |
4205 WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
4206 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
4207 pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
4208 pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
4209 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
4210 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
4212 pCaps->MaxPShaderInstructionsExecuted = 65535;
4213 pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
4214 } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
4215 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
4216 pCaps->PS20Caps.Caps = 0;
4217 pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
4218 pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
4219 pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
4220 pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
4222 pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
4223 pCaps->MaxPixelShader30InstructionSlots = 0;
4224 } else { /* PS 1.x */
4225 pCaps->PS20Caps.Caps = 0;
4226 pCaps->PS20Caps.DynamicFlowControlDepth = 0;
4227 pCaps->PS20Caps.NumTemps = 0;
4228 pCaps->PS20Caps.StaticFlowControlDepth = 0;
4229 pCaps->PS20Caps.NumInstructionSlots = 0;
4231 pCaps->MaxPShaderInstructionsExecuted = 0;
4232 pCaps->MaxPixelShader30InstructionSlots = 0;
4235 if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
4236 /* OpenGL supports all the formats below, perhaps not always
4237 * without conversion, but it supports them.
4238 * Further GLSL doesn't seem to have an official unsigned type so
4239 * don't advertise it yet as I'm not sure how we handle it.
4240 * We might need to add some clamping in the shader engine to
4241 * support it.
4242 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
4243 pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
4244 WINED3DDTCAPS_UBYTE4N |
4245 WINED3DDTCAPS_SHORT2N |
4246 WINED3DDTCAPS_SHORT4N;
4247 if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
4248 pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
4249 WINED3DDTCAPS_FLOAT16_4;
4251 } else
4252 pCaps->DeclTypes = 0;
4254 /* Set DirectDraw helper Caps */
4255 ckey_caps = WINEDDCKEYCAPS_DESTBLT |
4256 WINEDDCKEYCAPS_SRCBLT;
4257 fx_caps = WINEDDFXCAPS_BLTALPHA |
4258 WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
4259 WINEDDFXCAPS_BLTMIRRORUPDOWN |
4260 WINEDDFXCAPS_BLTROTATION90 |
4261 WINEDDFXCAPS_BLTSHRINKX |
4262 WINEDDFXCAPS_BLTSHRINKXN |
4263 WINEDDFXCAPS_BLTSHRINKY |
4264 WINEDDFXCAPS_BLTSHRINKXN |
4265 WINEDDFXCAPS_BLTSTRETCHX |
4266 WINEDDFXCAPS_BLTSTRETCHXN |
4267 WINEDDFXCAPS_BLTSTRETCHY |
4268 WINEDDFXCAPS_BLTSTRETCHYN;
4269 blit_caps = WINEDDCAPS_BLT |
4270 WINEDDCAPS_BLTCOLORFILL |
4271 WINEDDCAPS_BLTDEPTHFILL |
4272 WINEDDCAPS_BLTSTRETCH |
4273 WINEDDCAPS_CANBLTSYSMEM |
4274 WINEDDCAPS_CANCLIP |
4275 WINEDDCAPS_CANCLIPSTRETCHED |
4276 WINEDDCAPS_COLORKEY |
4277 WINEDDCAPS_COLORKEYHWASSIST |
4278 WINEDDCAPS_ALIGNBOUNDARYSRC;
4280 /* Fill the ddraw caps structure */
4281 pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
4282 WINEDDCAPS_PALETTE |
4283 blit_caps;
4284 pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
4285 WINEDDCAPS2_NOPAGELOCKREQUIRED |
4286 WINEDDCAPS2_PRIMARYGAMMA |
4287 WINEDDCAPS2_WIDESURFACES |
4288 WINEDDCAPS2_CANRENDERWINDOWED;
4289 pCaps->DirectDrawCaps.SVBCaps = blit_caps;
4290 pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
4291 pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
4292 pCaps->DirectDrawCaps.VSBCaps = blit_caps;
4293 pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
4294 pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
4295 pCaps->DirectDrawCaps.SSBCaps = blit_caps;
4296 pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
4297 pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
4299 pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
4300 WINEDDSCAPS_BACKBUFFER |
4301 WINEDDSCAPS_FLIP |
4302 WINEDDSCAPS_FRONTBUFFER |
4303 WINEDDSCAPS_OFFSCREENPLAIN |
4304 WINEDDSCAPS_PALETTE |
4305 WINEDDSCAPS_PRIMARYSURFACE |
4306 WINEDDSCAPS_SYSTEMMEMORY |
4307 WINEDDSCAPS_VIDEOMEMORY |
4308 WINEDDSCAPS_VISIBLE;
4309 pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
4311 /* Set D3D caps if OpenGL is available. */
4312 if (adapter->opengl)
4314 pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
4315 WINEDDSCAPS_MIPMAP |
4316 WINEDDSCAPS_TEXTURE |
4317 WINEDDSCAPS_ZBUFFER;
4318 pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
4321 return WINED3D_OK;
4324 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
4325 and fields being inserted in the middle, a new structure is used in place */
4326 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
4327 WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
4328 IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
4330 IWineD3DDeviceImpl *object = NULL;
4331 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4332 struct WineD3DAdapter *adapter = &This->adapters[Adapter];
4333 WINED3DDISPLAYMODE mode;
4334 const struct fragment_pipeline *frag_pipeline = NULL;
4335 int i;
4336 struct fragment_caps ffp_caps;
4337 struct shader_caps shader_caps;
4338 HRESULT hr;
4340 /* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
4341 * number and create a device without a 3D adapter for 2D only operation.
4343 if (IWineD3D_GetAdapterCount(iface) && Adapter >= IWineD3D_GetAdapterCount(iface)) {
4344 return WINED3DERR_INVALIDCALL;
4347 /* Create a WineD3DDevice object */
4348 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
4349 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
4350 TRACE("Created WineD3DDevice object @ %p\n", object);
4351 if (NULL == object) {
4352 return WINED3DERR_OUTOFVIDEOMEMORY;
4355 /* Set up initial COM information */
4356 object->lpVtbl = &IWineD3DDevice_Vtbl;
4357 object->ref = 1;
4358 object->wineD3D = iface;
4359 object->adapter = This->adapter_count ? adapter : NULL;
4360 IWineD3D_AddRef(object->wineD3D);
4361 object->parent = parent;
4362 object->device_parent = device_parent;
4363 list_init(&object->resources);
4364 list_init(&object->shaders);
4366 if(This->dxVersion == 7) {
4367 object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
4368 } else {
4369 object->surface_alignment = D3D8_PITCH_ALIGNMENT;
4371 object->posFixup[0] = 1.0f; /* This is needed to get the x coord unmodified through a MAD. */
4373 /* Set the state up as invalid until the device is fully created */
4374 object->state = WINED3DERR_DRIVERINTERNALERROR;
4376 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
4377 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
4379 /* Save the creation parameters */
4380 object->createParms.AdapterOrdinal = Adapter;
4381 object->createParms.DeviceType = DeviceType;
4382 object->createParms.hFocusWindow = hFocusWindow;
4383 object->createParms.BehaviorFlags = BehaviourFlags;
4385 /* Initialize other useful values */
4386 object->adapterNo = Adapter;
4387 object->devType = DeviceType;
4389 select_shader_mode(&adapter->gl_info, DeviceType,
4390 &object->ps_selected_mode, &object->vs_selected_mode);
4391 object->shader_backend = select_shader_backend(adapter, DeviceType);
4393 memset(&shader_caps, 0, sizeof(shader_caps));
4394 object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
4395 object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
4396 object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
4397 object->vs_clipping = shader_caps.VSClipping;
4399 memset(&ffp_caps, 0, sizeof(ffp_caps));
4400 frag_pipeline = select_fragment_implementation(adapter, DeviceType);
4401 object->frag_pipe = frag_pipeline;
4402 frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
4403 object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
4404 object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
4405 hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
4406 ffp_vertexstate_template, frag_pipeline, misc_state_template);
4408 if (FAILED(hr)) {
4409 IWineD3D_Release(object->wineD3D);
4410 HeapFree(GetProcessHeap(), 0, object);
4412 return hr;
4415 object->blitter = select_blit_implementation(adapter, DeviceType);
4417 /* set the state of the device to valid */
4418 object->state = WINED3D_OK;
4420 /* Get the initial screen setup for ddraw */
4421 IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
4423 object->ddraw_width = mode.Width;
4424 object->ddraw_height = mode.Height;
4425 object->ddraw_format = mode.Format;
4427 for(i = 0; i < PATCHMAP_SIZE; i++) {
4428 list_init(&object->patches[i]);
4431 IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
4433 return WINED3D_OK;
4436 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
4437 IWineD3DImpl *This = (IWineD3DImpl *)iface;
4438 IUnknown_AddRef(This->parent);
4439 *pParent = This->parent;
4440 return WINED3D_OK;
4443 ULONG WINAPI D3DCB_DefaultDestroySurface(IWineD3DSurface *pSurface) {
4444 IUnknown* surfaceParent;
4445 TRACE("(%p) call back\n", pSurface);
4447 /* Now, release the parent, which will take care of cleaning up the surface for us */
4448 IWineD3DSurface_GetParent(pSurface, &surfaceParent);
4449 IUnknown_Release(surfaceParent);
4450 return IUnknown_Release(surfaceParent);
4453 ULONG WINAPI D3DCB_DefaultDestroyVolume(IWineD3DVolume *pVolume) {
4454 IUnknown* volumeParent;
4455 TRACE("(%p) call back\n", pVolume);
4457 /* Now, release the parent, which will take care of cleaning up the volume for us */
4458 IWineD3DVolume_GetParent(pVolume, &volumeParent);
4459 IUnknown_Release(volumeParent);
4460 return IUnknown_Release(volumeParent);
4463 static void WINE_GLAPI invalid_func(const void *data)
4465 ERR("Invalid vertex attribute function called\n");
4466 DebugBreak();
4469 static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
4471 ERR("Invalid texcoord function called\n");
4472 DebugBreak();
4475 /* Helper functions for providing vertex data to opengl. The arrays are initialized based on
4476 * the extension detection and are used in drawStridedSlow
4478 static void WINE_GLAPI position_d3dcolor(const void *data)
4480 DWORD pos = *((const DWORD *)data);
4482 FIXME("Add a test for fixed function position from d3dcolor type\n");
4483 glVertex4s(D3DCOLOR_B_R(pos),
4484 D3DCOLOR_B_G(pos),
4485 D3DCOLOR_B_B(pos),
4486 D3DCOLOR_B_A(pos));
4489 static void WINE_GLAPI position_float4(const void *data)
4491 const GLfloat *pos = data;
4493 if (pos[3] != 0.0f && pos[3] != 1.0f)
4495 float w = 1.0f / pos[3];
4497 glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
4499 else
4501 glVertex3fv(pos);
4505 static void WINE_GLAPI diffuse_d3dcolor(const void *data)
4507 DWORD diffuseColor = *((const DWORD *)data);
4509 glColor4ub(D3DCOLOR_B_R(diffuseColor),
4510 D3DCOLOR_B_G(diffuseColor),
4511 D3DCOLOR_B_B(diffuseColor),
4512 D3DCOLOR_B_A(diffuseColor));
4515 static void WINE_GLAPI specular_d3dcolor(const void *data)
4517 DWORD specularColor = *((const DWORD *)data);
4518 GLbyte d[] = {D3DCOLOR_B_R(specularColor),
4519 D3DCOLOR_B_G(specularColor),
4520 D3DCOLOR_B_B(specularColor)};
4522 specular_func_3ubv(d);
4525 static void WINE_GLAPI warn_no_specular_func(const void *data)
4527 WARN("GL_EXT_secondary_color not supported\n");
4530 static void fillGLAttribFuncs(const struct wined3d_gl_info *gl_info)
4532 position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4533 position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4534 position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
4535 position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
4536 position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
4537 position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4538 position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4539 position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
4540 position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4541 position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4542 position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4543 position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4544 position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4545 position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4546 position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4547 position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4548 position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4550 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4551 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4552 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
4553 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
4554 diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
4555 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4556 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4557 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4558 diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
4559 diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4560 diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
4561 diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4562 diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
4563 diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4564 diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4565 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4566 diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4568 /* No 4 component entry points here */
4569 specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4570 specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4571 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4572 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
4573 } else {
4574 specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
4576 specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
4577 if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4578 specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
4579 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
4580 } else {
4581 specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
4583 specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4584 specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4585 specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4586 specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4587 specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4588 specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4589 specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4590 specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4591 specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4592 specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4593 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4594 specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4596 /* Only 3 component entry points here. Test how others behave. Float4 normals are used
4597 * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
4599 normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
4600 normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
4601 normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
4602 normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
4603 normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
4604 normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
4605 normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
4606 normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
4607 normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
4608 normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
4609 normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
4610 normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
4611 normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
4612 normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
4613 normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
4614 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
4615 normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
4617 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
4618 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
4619 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
4620 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
4621 multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
4622 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
4623 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
4624 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
4625 multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
4626 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
4627 multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
4628 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
4629 multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
4630 multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
4631 multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
4632 if (GL_SUPPORT(NV_HALF_FLOAT))
4634 /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
4635 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
4636 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
4637 } else {
4638 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
4639 multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
4643 BOOL InitAdapters(IWineD3DImpl *This)
4645 static HMODULE mod_gl;
4646 BOOL ret;
4647 int ps_selected_mode, vs_selected_mode;
4649 /* No need to hold any lock. The calling library makes sure only one thread calls
4650 * wined3d simultaneously
4653 TRACE("Initializing adapters\n");
4655 if(!mod_gl) {
4656 #ifdef USE_WIN32_OPENGL
4657 #define USE_GL_FUNC(pfn) pfn = (void*)GetProcAddress(mod_gl, #pfn);
4658 mod_gl = LoadLibraryA("opengl32.dll");
4659 if(!mod_gl) {
4660 ERR("Can't load opengl32.dll!\n");
4661 goto nogl_adapter;
4663 #else
4664 #define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
4665 /* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
4666 mod_gl = GetModuleHandleA("gdi32.dll");
4667 #endif
4670 /* Load WGL core functions from opengl32.dll */
4671 #define USE_WGL_FUNC(pfn) p##pfn = (void*)GetProcAddress(mod_gl, #pfn);
4672 WGL_FUNCS_GEN;
4673 #undef USE_WGL_FUNC
4675 if(!pwglGetProcAddress) {
4676 ERR("Unable to load wglGetProcAddress!\n");
4677 goto nogl_adapter;
4680 /* Dynamically load all GL core functions */
4681 GL_FUNCS_GEN;
4682 #undef USE_GL_FUNC
4684 /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
4685 * otherwise because we have to use winex11.drv's override
4687 #ifdef USE_WIN32_OPENGL
4688 glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
4689 glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
4690 #else
4691 glFinish = (void*)pwglGetProcAddress("wglFinish");
4692 glFlush = (void*)pwglGetProcAddress("wglFlush");
4693 #endif
4695 glEnableWINE = glEnable;
4696 glDisableWINE = glDisable;
4698 /* For now only one default adapter */
4700 struct WineD3DAdapter *adapter = &This->adapters[0];
4701 const struct wined3d_gl_info *gl_info = &adapter->gl_info;
4702 struct wined3d_fake_gl_ctx fake_gl_ctx = {0};
4703 int iPixelFormat;
4704 int res;
4705 int i;
4706 WineD3D_PixelFormat *cfgs;
4707 DISPLAY_DEVICEW DisplayDevice;
4708 HDC hdc;
4710 TRACE("Initializing default adapter\n");
4711 adapter->num = 0;
4712 adapter->monitorPoint.x = -1;
4713 adapter->monitorPoint.y = -1;
4715 if (!WineD3D_CreateFakeGLContext(&fake_gl_ctx))
4717 ERR("Failed to get a gl context for default adapter\n");
4718 goto nogl_adapter;
4721 ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
4722 if(!ret) {
4723 ERR("Failed to initialize gl caps for default adapter\n");
4724 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4725 goto nogl_adapter;
4727 ret = initPixelFormats(&adapter->gl_info);
4728 if(!ret) {
4729 ERR("Failed to init gl formats\n");
4730 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4731 goto nogl_adapter;
4734 hdc = fake_gl_ctx.dc;
4736 adapter->driver = "Display";
4737 adapter->description = "Direct3D HAL";
4739 /* Use the VideoRamSize registry setting when set */
4740 if(wined3d_settings.emulated_textureram)
4741 adapter->TextureRam = wined3d_settings.emulated_textureram;
4742 else
4743 adapter->TextureRam = adapter->gl_info.vidmem;
4744 adapter->UsedTextureRam = 0;
4745 TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
4747 /* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
4748 DisplayDevice.cb = sizeof(DisplayDevice);
4749 EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
4750 TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
4751 strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
4753 if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
4755 int attribute;
4756 int attribs[10];
4757 int values[10];
4758 int nAttribs = 0;
4760 attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
4761 GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
4763 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
4764 cfgs = adapter->cfgs;
4765 attribs[nAttribs++] = WGL_RED_BITS_ARB;
4766 attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
4767 attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
4768 attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
4769 attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
4770 attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
4771 attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
4772 attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
4773 attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
4774 attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
4776 for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
4778 res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
4780 if(!res)
4781 continue;
4783 /* Cache the pixel format */
4784 cfgs->iPixelFormat = iPixelFormat;
4785 cfgs->redSize = values[0];
4786 cfgs->greenSize = values[1];
4787 cfgs->blueSize = values[2];
4788 cfgs->alphaSize = values[3];
4789 cfgs->depthSize = values[4];
4790 cfgs->stencilSize = values[5];
4791 cfgs->windowDrawable = values[6];
4792 cfgs->iPixelType = values[7];
4793 cfgs->doubleBuffer = values[8];
4794 cfgs->auxBuffers = values[9];
4796 cfgs->pbufferDrawable = FALSE;
4797 /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
4798 if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
4799 int attrib = WGL_DRAW_TO_PBUFFER_ARB;
4800 int value;
4801 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
4802 cfgs->pbufferDrawable = value;
4805 cfgs->numSamples = 0;
4806 /* Check multisample support */
4807 if(GL_SUPPORT(ARB_MULTISAMPLE)) {
4808 int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
4809 int value[2];
4810 if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
4811 /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
4812 * value[1] = number of multi sample buffers*/
4813 if(value[0])
4814 cfgs->numSamples = value[1];
4818 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);
4819 cfgs++;
4822 else
4824 int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
4825 adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
4826 adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
4828 cfgs = adapter->cfgs;
4829 for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
4831 PIXELFORMATDESCRIPTOR ppfd;
4833 res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
4834 if(!res)
4835 continue;
4837 /* We only want HW acceleration using an OpenGL ICD driver.
4838 * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
4839 * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
4841 if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
4843 TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
4844 continue;
4847 cfgs->iPixelFormat = iPixelFormat;
4848 cfgs->redSize = ppfd.cRedBits;
4849 cfgs->greenSize = ppfd.cGreenBits;
4850 cfgs->blueSize = ppfd.cBlueBits;
4851 cfgs->alphaSize = ppfd.cAlphaBits;
4852 cfgs->depthSize = ppfd.cDepthBits;
4853 cfgs->stencilSize = ppfd.cStencilBits;
4854 cfgs->pbufferDrawable = 0;
4855 cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
4856 cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
4857 cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
4858 cfgs->auxBuffers = ppfd.cAuxBuffers;
4859 cfgs->numSamples = 0;
4861 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);
4862 cfgs++;
4863 adapter->nCfgs++;
4866 /* 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 */
4867 if(!adapter->nCfgs)
4869 ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
4871 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4872 HeapFree(GetProcessHeap(), 0, adapter->cfgs);
4873 goto nogl_adapter;
4877 /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
4878 * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
4879 * but just fake it using D24(X8?) which is fine. D3D also allows that.
4880 * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
4881 * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
4882 * driver is allowed to consume more bits EXCEPT for stencil bits.
4884 * Mark an adapter with this broken stencil behavior.
4886 adapter->brokenStencil = TRUE;
4887 for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
4889 /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
4890 if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
4891 adapter->brokenStencil = FALSE;
4892 break;
4896 WineD3D_ReleaseFakeGLContext(&fake_gl_ctx);
4898 select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
4899 select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
4900 fillGLAttribFuncs(&adapter->gl_info);
4901 adapter->opengl = TRUE;
4903 This->adapter_count = 1;
4904 TRACE("%u adapters successfully initialized\n", This->adapter_count);
4906 return TRUE;
4908 nogl_adapter:
4909 /* Initialize an adapter for ddraw-only memory counting */
4910 memset(This->adapters, 0, sizeof(This->adapters));
4911 This->adapters[0].num = 0;
4912 This->adapters[0].opengl = FALSE;
4913 This->adapters[0].monitorPoint.x = -1;
4914 This->adapters[0].monitorPoint.y = -1;
4916 This->adapters[0].driver = "Display";
4917 This->adapters[0].description = "WineD3D DirectDraw Emulation";
4918 if(wined3d_settings.emulated_textureram) {
4919 This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
4920 } else {
4921 This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
4924 initPixelFormatsNoGL(&This->adapters[0].gl_info);
4926 This->adapter_count = 1;
4927 return FALSE;
4930 /**********************************************************
4931 * IWineD3D VTbl follows
4932 **********************************************************/
4934 const IWineD3DVtbl IWineD3D_Vtbl =
4936 /* IUnknown */
4937 IWineD3DImpl_QueryInterface,
4938 IWineD3DImpl_AddRef,
4939 IWineD3DImpl_Release,
4940 /* IWineD3D */
4941 IWineD3DImpl_GetParent,
4942 IWineD3DImpl_GetAdapterCount,
4943 IWineD3DImpl_RegisterSoftwareDevice,
4944 IWineD3DImpl_GetAdapterMonitor,
4945 IWineD3DImpl_GetAdapterModeCount,
4946 IWineD3DImpl_EnumAdapterModes,
4947 IWineD3DImpl_GetAdapterDisplayMode,
4948 IWineD3DImpl_GetAdapterIdentifier,
4949 IWineD3DImpl_CheckDeviceMultiSampleType,
4950 IWineD3DImpl_CheckDepthStencilMatch,
4951 IWineD3DImpl_CheckDeviceType,
4952 IWineD3DImpl_CheckDeviceFormat,
4953 IWineD3DImpl_CheckDeviceFormatConversion,
4954 IWineD3DImpl_GetDeviceCaps,
4955 IWineD3DImpl_CreateDevice