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
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 /* Uncomment this to force only a single display mode to be exposed: */
27 /*#define DEBUG_SINGLE_MODE*/
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
35 #define GLINFO_LOCATION This->gl_info
37 /**********************************************************
38 * Utility functions follow
39 **********************************************************/
41 /* x11drv GDI escapes */
42 #define X11DRV_ESCAPE 6789
43 enum x11drv_escape_codes
45 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
46 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
47 X11DRV_GET_FONT, /* get current X font for a DC */
50 /* retrieve the X display to use on a given DC */
51 inline static Display *get_display( HDC hdc )
54 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
56 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
57 sizeof(display), (LPSTR)&display )) display = NULL;
62 int minLookup[MAX_LOOKUPS];
63 int maxLookup[MAX_LOOKUPS];
64 DWORD *stateLookup[MAX_LOOKUPS];
66 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
71 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
72 * ie there is no GL Context - Get a default rendering context to enable the
73 * function query some info from GL
75 static WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
76 static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
77 WineD3D_Context* ret = NULL;
79 if (glXGetCurrentContext() == NULL) {
80 BOOL gotContext = FALSE;
87 XWindowAttributes win_attr;
88 TRACE_(d3d_caps)("Creating Fake GL Context\n");
90 ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
93 device_context = GetDC(0);
94 ctx.display = get_display(device_context);
95 ReleaseDC(0, device_context);
97 /* Get the X visual */
99 if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
100 visual = win_attr.visual;
102 visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
104 template.visualid = XVisualIDFromVisual(visual);
105 ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
106 if (ctx.visInfo == NULL) {
108 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
112 /* Create a GL context */
114 ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
116 if (ctx.glCtx == NULL) {
118 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
123 /* Make it the current GL context */
124 if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
125 glXDestroyContext(ctx.display, ctx.glCtx);
127 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
131 /* It worked! Wow... */
141 if (ctx.ref > 0) ret = &ctx;
144 if (NULL != ret) InterlockedIncrement(&ret->ref);
148 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
149 /* If we created a dummy context, throw it away */
151 if (0 == InterlockedDecrement(&ctx->ref)) {
152 glXMakeCurrent(ctx->display, None, NULL);
153 glXDestroyContext(ctx->display, ctx->glCtx);
161 /**********************************************************
162 * IUnknown parts follows
163 **********************************************************/
165 static HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
169 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
170 if (IsEqualGUID(riid, &IID_IUnknown)
171 || IsEqualGUID(riid, &IID_IWineD3DBase)
172 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
173 IUnknown_AddRef(iface);
178 return E_NOINTERFACE;
181 static ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
182 IWineD3DImpl *This = (IWineD3DImpl *)iface;
183 ULONG refCount = InterlockedIncrement(&This->ref);
185 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
189 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
190 IWineD3DImpl *This = (IWineD3DImpl *)iface;
192 TRACE("(%p) : Releasing from %d\n", This, This->ref);
193 ref = InterlockedDecrement(&This->ref);
195 HeapFree(GetProcessHeap(), 0, This);
201 /* Set the shader type for this device, depending on the given capabilities,
202 * the device type, and the user preferences in wined3d_settings */
204 static void select_shader_mode(
205 WineD3D_GL_Info *gl_info,
206 WINED3DDEVTYPE DeviceType,
210 /* Give priority to user disable/emulation request.
211 * Then respect REF device for software.
212 * Then check capabilities for hardware, and fallback to software */
214 if (wined3d_settings.vs_mode == VS_NONE) {
215 *vs_selected = SHADER_NONE;
216 } else if (DeviceType == WINED3DDEVTYPE_REF || wined3d_settings.vs_mode == VS_SW) {
217 *vs_selected = SHADER_SW;
218 } else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
219 *vs_selected = SHADER_GLSL;
220 } else if (gl_info->supported[ARB_VERTEX_PROGRAM]) {
221 *vs_selected = SHADER_ARB;
223 *vs_selected = SHADER_SW;
226 /* Fallback to SHADER_NONE where software pixel shaders should be used */
227 if (wined3d_settings.ps_mode == PS_NONE) {
228 *ps_selected = SHADER_NONE;
229 } else if (DeviceType == WINED3DDEVTYPE_REF) {
230 *ps_selected = SHADER_NONE;
231 } else if (gl_info->supported[ARB_FRAGMENT_SHADER] && wined3d_settings.glslRequested) {
232 *ps_selected = SHADER_GLSL;
233 } else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
234 *ps_selected = SHADER_ARB;
236 *ps_selected = SHADER_NONE;
240 /** Select the number of report maximum shader constants based on the selected shader modes */
241 void select_shader_max_constants(WineD3D_GL_Info *gl_info) {
243 switch (wined3d_settings.vs_selected_mode) {
245 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
246 gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - MAX_CONST_B - MAX_CONST_I - 1;
249 /* We have to subtract any other PARAMs that we might use in our shader programs.
250 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
251 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
252 gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
255 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
258 gl_info->max_vshader_constantsF = 0;
262 switch (wined3d_settings.ps_selected_mode) {
264 /* Subtract the other potential uniforms from the max available (bools & ints) */
265 gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - MAX_CONST_B - MAX_CONST_I;
268 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
271 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
274 gl_info->max_pshader_constantsF = 0;
279 /**********************************************************
280 * IWineD3D parts follows
281 **********************************************************/
283 BOOL IWineD3DImpl_FillGLCaps(IWineD3D *iface, Display* display) {
284 IWineD3DImpl *This = (IWineD3DImpl *)iface;
285 WineD3D_GL_Info *gl_info = &This->gl_info;
287 const char *GL_Extensions = NULL;
288 const char *GLX_Extensions = NULL;
289 const char *gl_string = NULL;
290 const char *gl_string_cursor = NULL;
292 GLfloat gl_floatv[2];
295 WineD3D_Context *fake_ctx = NULL;
296 BOOL gotContext = FALSE;
299 /* Make sure that we've got a context */
300 if (glXGetCurrentContext() == NULL) {
301 /* TODO: CreateFakeGLContext should really take a display as a parameter */
302 fake_ctx = WineD3D_CreateFakeGLContext();
303 if (NULL != fake_ctx) gotContext = TRUE;
308 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
310 gl_string = (const char *) glGetString(GL_RENDERER);
311 if (NULL == gl_string)
313 strcpy(gl_info->gl_renderer, gl_string);
315 /* Fill in the GL info retrievable depending on the display */
316 if (NULL != display) {
317 test = glXQueryVersion(display, &major, &minor);
318 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
320 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
322 gl_string = (const char *) glGetString(GL_VENDOR);
324 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
325 if (gl_string != NULL) {
326 /* Fill in the GL vendor */
327 if (strstr(gl_string, "NVIDIA")) {
328 gl_info->gl_vendor = VENDOR_NVIDIA;
329 } else if (strstr(gl_string, "ATI")) {
330 gl_info->gl_vendor = VENDOR_ATI;
331 } else if (strstr(gl_string, "Intel(R)") ||
332 strstr(gl_info->gl_renderer, "Intel(R)")) {
333 gl_info->gl_vendor = VENDOR_INTEL;
334 } else if (strstr(gl_string, "Mesa")) {
335 gl_info->gl_vendor = VENDOR_MESA;
337 gl_info->gl_vendor = VENDOR_WINE;
340 gl_info->gl_vendor = VENDOR_WINE;
344 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
346 /* Parse the GL_VERSION field into major and minor information */
347 gl_string = (const char *) glGetString(GL_VERSION);
348 if (gl_string != NULL) {
350 switch (gl_info->gl_vendor) {
352 gl_string_cursor = strstr(gl_string, "NVIDIA");
353 if (!gl_string_cursor) {
354 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
358 gl_string_cursor = strstr(gl_string_cursor, " ");
359 if (!gl_string_cursor) {
360 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
364 while (*gl_string_cursor == ' ') {
368 if (!*gl_string_cursor) {
369 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
373 major = atoi(gl_string_cursor);
374 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
378 if (*gl_string_cursor++ != '.') {
379 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
383 minor = atoi(gl_string_cursor);
384 minor = major*100+minor;
391 gl_string_cursor = strchr(gl_string, '-');
392 if (gl_string_cursor) {
396 /* Check if version number is of the form x.y.z */
397 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
399 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
401 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
403 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
406 /* Mark version number as malformed */
408 gl_string_cursor = 0;
411 if (!gl_string_cursor)
412 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
414 major = *gl_string_cursor - '0';
415 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
421 gl_string_cursor = strstr(gl_string, "Mesa");
422 gl_string_cursor = strstr(gl_string_cursor, " ");
423 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
424 if (*gl_string_cursor) {
428 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
429 tmp[cursor++] = *gl_string_cursor;
435 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
439 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
440 tmp[cursor++] = *gl_string_cursor;
452 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
453 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
456 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
459 * Initialize openGL extension related variables
460 * with Default values
462 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
463 gl_info->max_buffers = 1;
464 gl_info->max_textures = 1;
465 gl_info->max_texture_stages = 1;
466 gl_info->max_samplers = 1;
467 gl_info->max_sampler_stages = 1;
468 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
469 gl_info->ps_arb_max_temps = 0;
470 gl_info->ps_arb_max_instructions = 0;
471 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
472 gl_info->vs_arb_max_temps = 0;
473 gl_info->vs_arb_max_instructions = 0;
474 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
475 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
476 gl_info->vs_glsl_constantsF = 0;
477 gl_info->ps_glsl_constantsF = 0;
478 gl_info->vs_arb_constantsF = 0;
479 gl_info->ps_arb_constantsF = 0;
481 /* Now work out what GL support this card really has */
482 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
487 /* Retrieve opengl defaults */
488 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
489 gl_info->max_clipplanes = min(D3DMAXUSERCLIPPLANES, gl_max);
490 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
492 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
493 gl_info->max_lights = gl_max;
494 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
496 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
497 gl_info->max_texture_size = gl_max;
498 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
500 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
501 gl_info->max_pointsize = gl_floatv[1];
502 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
504 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
505 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
506 TRACE_(d3d_caps)("GL_Extensions reported:\n");
508 if (NULL == GL_Extensions) {
509 ERR(" GL_Extensions returns NULL\n");
511 while (*GL_Extensions != 0x00) {
512 const char *Start = GL_Extensions;
515 memset(ThisExtn, 0x00, sizeof(ThisExtn));
516 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
519 memcpy(ThisExtn, Start, (GL_Extensions - Start));
520 TRACE_(d3d_caps)("- %s\n", ThisExtn);
525 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
526 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
527 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
528 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
529 gl_info->max_buffers = gl_max;
530 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
531 gl_info->ps_arb_version = PS_VERSION_11;
532 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
533 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
534 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
535 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
536 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
537 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
538 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
539 gl_info->ps_arb_constantsF = gl_max;
540 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
541 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
542 gl_info->ps_arb_max_temps = gl_max;
543 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
544 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
545 gl_info->ps_arb_max_instructions = gl_max;
546 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
547 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
548 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
550 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
551 gl_info->ps_glsl_constantsF = gl_max;
552 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
553 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
554 gl_info->supported[ARB_IMAGING] = TRUE;
555 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
556 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
557 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
558 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
559 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
560 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
561 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
562 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
563 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
564 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
565 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
566 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
567 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
568 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
569 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
570 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
571 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
572 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
573 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
574 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
575 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
576 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
577 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
578 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
579 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
580 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
581 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
582 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
583 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
584 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
585 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
586 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
587 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
588 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
589 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
590 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
591 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
592 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
593 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
594 } else if (strcmp(ThisExtn, "GL_ARB_texture_non_power_of_two") == 0) {
595 TRACE_(d3d_caps)(" FOUND: ARB NPOT texture support\n");
596 gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = TRUE;
597 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
598 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
599 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
600 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
601 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
602 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
603 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
604 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
605 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
606 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
607 gl_info->vs_arb_version = VS_VERSION_11;
608 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
609 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
610 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
611 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
612 gl_info->vs_arb_constantsF = gl_max;
613 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
614 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
615 gl_info->vs_arb_max_temps = gl_max;
616 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
617 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
618 gl_info->vs_arb_max_instructions = gl_max;
619 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
620 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
621 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
623 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
624 gl_info->vs_glsl_constantsF = gl_max;
625 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
626 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
627 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
628 gl_info->max_blends = gl_max;
629 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
630 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
631 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
632 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
633 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
634 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
635 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
636 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
637 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
638 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
642 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
643 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
644 gl_info->supported[EXT_FOG_COORD] = TRUE;
645 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
646 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
647 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
648 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
649 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
650 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
651 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
652 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
653 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
654 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
655 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
656 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
657 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
658 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
659 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
660 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
661 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
662 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
663 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
664 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
665 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
666 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
667 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
668 gl_info->supported[EXT_TEXTURE3D] = TRUE;
669 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
670 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
671 gl_info->max_texture3d_size = gl_max;
672 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
673 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
674 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
675 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
676 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
677 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
678 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
679 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
680 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
681 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
682 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
683 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
684 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
685 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
686 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
687 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
688 gl_info->max_anisotropy = gl_max;
689 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
690 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
691 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
692 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
693 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
694 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
695 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
696 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
697 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
702 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
703 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
704 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
705 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
706 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
707 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
708 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
709 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
710 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
711 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
712 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
713 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
714 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
715 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
716 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
717 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
718 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
719 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
720 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
721 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
722 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
723 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
724 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
725 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
726 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
727 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
728 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
729 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
730 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
731 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
732 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
733 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
734 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
735 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
736 gl_info->vs_nv_version = VS_VERSION_30;
737 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
738 gl_info->vs_nv_version = VS_VERSION_20;
739 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
740 gl_info->vs_nv_version = VS_VERSION_11;
742 gl_info->vs_nv_version = VS_VERSION_10;
743 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
744 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
750 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
751 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
752 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
753 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
754 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
755 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
756 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
757 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
758 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
759 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
760 gl_info->vs_ati_version = VS_VERSION_11;
761 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
762 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
766 if (*GL_Extensions == ' ') GL_Extensions++;
769 checkGLcall("extension detection\n");
771 /* In some cases the number of texture stages can be larger than the number
772 * of samplers. The GF4 for example can use only 2 samplers (no fragment
773 * shaders), but 8 texture stages (register combiners). */
774 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
776 /* We can only use NP2_NATIVE when the hardware supports it. */
777 if (wined3d_settings.nonpower2_mode == NP2_NATIVE && !gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
778 WARN_(d3d_caps)("GL_ARB_texture_non_power_of_two not supported, falling back to NP2_NONE NPOT mode.\n");
779 wined3d_settings.nonpower2_mode = NP2_NONE;
782 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
783 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
784 * in case of the latest videocards in the number of pixel/vertex pipelines.
786 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
787 * rendering. Various games use this information to get a rough estimation of the features of the card
788 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
789 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
790 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
793 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
794 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
795 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
796 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
797 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
798 * is used for rendering which is not always the case). This would work but it is not very portable. Second
799 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
802 * As said most games only use the PCI id to get an indication of the capabilities of the card.
803 * It doesn't really matter if the given id is the correct one if we return the id of a card with
804 * similar 3d features.
806 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
807 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
808 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
809 * won't pass we return a default card. This way is better than maintaining a full card database as even
810 * without a full database we can return a card with similar features. Second the size of the database
811 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
812 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
813 * to distinguishes between different models from that family.
815 switch (gl_info->gl_vendor) {
817 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
818 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
820 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
821 if (strstr(gl_info->gl_renderer, "7800") ||
822 strstr(gl_info->gl_renderer, "7900") ||
823 strstr(gl_info->gl_renderer, "7950") ||
824 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
825 strstr(gl_info->gl_renderer, "Quadro FX 5"))
826 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
827 else if(strstr(gl_info->gl_renderer, "6800") ||
828 strstr(gl_info->gl_renderer, "7600"))
829 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
830 else if(strstr(gl_info->gl_renderer, "6600") ||
831 strstr(gl_info->gl_renderer, "6610") ||
832 strstr(gl_info->gl_renderer, "6700"))
833 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
835 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
836 } else if(WINE_D3D9_CAPABLE(gl_info)) {
837 if (strstr(gl_info->gl_renderer, "5800") ||
838 strstr(gl_info->gl_renderer, "5900") ||
839 strstr(gl_info->gl_renderer, "5950") ||
840 strstr(gl_info->gl_renderer, "Quadro FX"))
841 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
842 else if(strstr(gl_info->gl_renderer, "5600") ||
843 strstr(gl_info->gl_renderer, "5650") ||
844 strstr(gl_info->gl_renderer, "5700") ||
845 strstr(gl_info->gl_renderer, "5750"))
846 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
848 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
849 } else if(WINE_D3D8_CAPABLE(gl_info)) {
850 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
851 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
853 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
854 } else if(WINE_D3D7_CAPABLE(gl_info)) {
855 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
856 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
857 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
858 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
859 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
860 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
862 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
864 if (strstr(gl_info->gl_renderer, "TNT2"))
865 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
867 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
871 if(WINE_D3D9_CAPABLE(gl_info)) {
873 if (strstr(gl_info->gl_renderer, "X1600") ||
874 strstr(gl_info->gl_renderer, "X1800") ||
875 strstr(gl_info->gl_renderer, "X1900") ||
876 strstr(gl_info->gl_renderer, "X1950"))
877 gl_info->gl_card = CARD_ATI_RADEON_X1600;
878 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
879 else if(strstr(gl_info->gl_renderer, "X700") ||
880 strstr(gl_info->gl_renderer, "X800") ||
881 strstr(gl_info->gl_renderer, "X850") ||
882 strstr(gl_info->gl_renderer, "X1300") ||
883 strstr(gl_info->gl_renderer, "X1400"))
884 gl_info->gl_card = CARD_ATI_RADEON_X700;
887 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
888 } else if(WINE_D3D8_CAPABLE(gl_info)) {
889 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
890 } else if(WINE_D3D7_CAPABLE(gl_info)) {
891 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
893 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
896 if (strstr(gl_info->gl_renderer, "915GM")) {
897 gl_info->gl_card = CARD_INTEL_I915GM;
898 } else if (strstr(gl_info->gl_renderer, "915G")) {
899 gl_info->gl_card = CARD_INTEL_I915G;
900 } else if (strstr(gl_info->gl_renderer, "865G")) {
901 gl_info->gl_card = CARD_INTEL_I865G;
902 } else if (strstr(gl_info->gl_renderer, "855G")) {
903 gl_info->gl_card = CARD_INTEL_I855G;
904 } else if (strstr(gl_info->gl_renderer, "830G")) {
905 gl_info->gl_card = CARD_INTEL_I830G;
907 gl_info->gl_card = CARD_INTEL_I915G;
913 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
914 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
915 * them a good generic choice.
917 gl_info->gl_vendor = VENDOR_NVIDIA;
918 if(WINE_D3D9_CAPABLE(gl_info))
919 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
920 else if(WINE_D3D8_CAPABLE(gl_info))
921 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
922 else if(WINE_D3D7_CAPABLE(gl_info))
923 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
924 else if(WINE_D3D6_CAPABLE(gl_info))
925 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
927 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
929 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
931 /* Load all the lookup tables
932 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
933 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
934 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
936 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
937 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
940 for (i = 0; i < MAX_LOOKUPS; i++) {
941 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
944 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
945 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
946 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
947 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
948 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
949 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
950 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
951 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
952 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
953 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
955 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
956 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
957 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
958 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
959 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
962 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
963 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
964 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
965 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
966 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
967 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
968 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
969 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
970 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
971 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
972 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
973 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
974 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
976 /* TODO: config lookups */
978 if (display != NULL) {
979 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
980 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
982 if (NULL == GLX_Extensions) {
983 ERR(" GLX_Extensions returns NULL\n");
985 while (*GLX_Extensions != 0x00) {
986 const char *Start = GLX_Extensions;
989 memset(ThisExtn, 0x00, sizeof(ThisExtn));
990 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
993 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
994 TRACE_(d3d_caps)("- %s\n", ThisExtn);
995 if (*GLX_Extensions == ' ') GLX_Extensions++;
1000 /* If we created a dummy context, throw it away */
1001 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
1003 /* Only save the values obtained when a display is provided */
1004 if (fake_ctx == NULL) {
1011 /**********************************************************
1012 * IWineD3D implementation follows
1013 **********************************************************/
1015 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1016 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1018 /* FIXME: Set to one for now to imply the display */
1019 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1023 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1024 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1025 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1029 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1030 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1031 POINT pt = { -1, -1 };
1033 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1037 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1038 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1041 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1042 of the same bpp but different resolutions */
1044 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1045 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1046 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1047 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1049 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1053 if (Adapter == 0) { /* Display */
1056 #if !defined( DEBUG_SINGLE_MODE )
1059 /* Work out the current screen bpp */
1060 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1061 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1064 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1068 case D3DFMT_UNKNOWN:
1071 case D3DFMT_X8R8G8B8:
1072 case D3DFMT_A8R8G8B8:
1073 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1074 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1076 case D3DFMT_X1R5G5B5:
1077 case D3DFMT_A1R5G5B5:
1079 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1082 /* Skip other modes as they do not match the requested format */
1090 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1093 FIXME_(d3d_caps)("Adapter not primary display\n");
1098 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1099 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1100 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1101 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1103 /* Validate the parameters as much as possible */
1104 if (NULL == pMode ||
1105 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1106 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1107 return WINED3DERR_INVALIDCALL;
1110 if (Adapter == 0) { /* Display */
1111 #if !defined( DEBUG_SINGLE_MODE )
1115 /* Work out the current screen bpp */
1116 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1117 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1120 /* If we are filtering to a specific format, then need to skip all unrelated
1121 modes, but if mode is irrelevant, then we can use the index directly */
1122 if (Format == D3DFMT_UNKNOWN)
1128 DEVMODEW DevModeWtmp;
1131 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1135 case D3DFMT_UNKNOWN:
1138 case D3DFMT_X8R8G8B8:
1139 case D3DFMT_A8R8G8B8:
1140 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1141 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1143 case D3DFMT_X1R5G5B5:
1144 case D3DFMT_A1R5G5B5:
1146 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1149 /* Skip other modes as they do not match requested format */
1156 /* Now get the display mode via the calculated index */
1157 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1159 pMode->Width = DevModeW.dmPelsWidth;
1160 pMode->Height = DevModeW.dmPelsHeight;
1161 bpp = min(DevModeW.dmBitsPerPel, bpp);
1162 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1163 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1165 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1168 if (Format == D3DFMT_UNKNOWN)
1171 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1172 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1173 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1174 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1175 default: pMode->Format = D3DFMT_UNKNOWN;
1178 pMode->Format = Format;
1183 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1184 return WINED3DERR_INVALIDCALL;
1188 /* Return one setting of the format requested */
1189 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1191 pMode->Height = 600;
1192 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1193 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1196 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1197 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1200 FIXME_(d3d_caps)("Adapter not primary display\n");
1206 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1207 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1208 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1210 if (NULL == pMode ||
1211 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1212 return WINED3DERR_INVALIDCALL;
1215 if (Adapter == 0) { /* Display */
1219 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1220 pMode->Width = DevModeW.dmPelsWidth;
1221 pMode->Height = DevModeW.dmPelsHeight;
1222 bpp = DevModeW.dmBitsPerPel;
1223 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1224 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1226 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1230 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1231 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1232 case 24: pMode->Format = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1233 case 32: pMode->Format = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1234 default: pMode->Format = D3DFMT_UNKNOWN;
1238 FIXME_(d3d_caps)("Adapter not primary display\n");
1241 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1242 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1246 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1249 /* only works with one adapter at the moment... */
1251 /* Get the display */
1252 device_context = GetDC(0);
1253 display = get_display(device_context);
1254 ReleaseDC(0, device_context);
1258 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1259 and fields being inserted in the middle, a new structure is used in place */
1260 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1261 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1262 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1264 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1266 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1267 return WINED3DERR_INVALIDCALL;
1270 if (Adapter == 0) { /* Display - only device supported for now */
1272 BOOL isGLInfoValid = This->isGLInfoValid;
1274 /* FillGLCaps updates gl_info, but we only want to store and
1275 reuse the values once we have a context which is valid. Values from
1276 a temporary context may differ from the final ones */
1277 if (!isGLInfoValid) {
1278 WineD3D_Context *fake_ctx = NULL;
1279 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1280 /* If we don't know the device settings, go query them now */
1281 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1282 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1285 /* If it worked, return the information requested */
1286 if (isGLInfoValid) {
1287 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1288 strcpy(pIdentifier->Driver, "Display");
1289 strcpy(pIdentifier->Description, "Direct3D HAL");
1291 /* Note dx8 doesn't supply a DeviceName */
1292 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1293 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1294 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1295 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1296 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1297 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1298 *(pIdentifier->SubSysId) = 0;
1299 *(pIdentifier->Revision) = 0;
1303 /* If it failed, return dummy values from an NVidia driver */
1304 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1305 strcpy(pIdentifier->Driver, "Display");
1306 strcpy(pIdentifier->Description, "Direct3D HAL");
1307 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1308 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1309 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1310 /* 71.74 is a current Linux Nvidia driver version */
1311 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1312 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1313 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1314 *(pIdentifier->SubSysId) = 0;
1315 *(pIdentifier->Revision) = 0;
1318 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1319 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1320 *(pIdentifier->WHQLLevel) = 0;
1322 *(pIdentifier->WHQLLevel) = 1;
1326 FIXME_(d3d_caps)("Adapter not primary display\n");
1332 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1333 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1335 int rb, gb, bb, ab, type, buf_sz;
1337 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1338 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1339 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1340 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1341 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1342 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1345 case WINED3DFMT_X8R8G8B8:
1346 case WINED3DFMT_R8G8B8:
1347 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1349 case WINED3DFMT_A8R8G8B8:
1350 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1352 case WINED3DFMT_A2R10G10B10:
1353 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1355 case WINED3DFMT_X1R5G5B5:
1356 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1358 case WINED3DFMT_A1R5G5B5:
1359 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1361 case WINED3DFMT_X4R4G4B4:
1362 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1364 case WINED3DFMT_R5G6B5:
1365 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1367 case WINED3DFMT_R3G3B2:
1368 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1370 case WINED3DFMT_A8P8:
1371 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1374 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1377 ERR("unsupported format %s\n", debug_d3dformat(Format));
1381 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1383 case WINED3DFMT_X8R8G8B8:
1384 case WINED3DFMT_R8G8B8:
1385 case WINED3DFMT_A8R8G8B8:
1386 case WINED3DFMT_A2R10G10B10:
1387 case WINED3DFMT_X1R5G5B5:
1388 case WINED3DFMT_A1R5G5B5:
1389 case WINED3DFMT_R5G6B5:
1390 case WINED3DFMT_R3G3B2:
1391 case WINED3DFMT_A8P8:
1395 ERR("unsupported format %s\n", debug_d3dformat(Format));
1402 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1403 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1407 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1408 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1411 case WINED3DFMT_D16:
1412 case WINED3DFMT_D16_LOCKABLE:
1413 if (16 == db) return TRUE;
1415 case WINED3DFMT_D32:
1416 if (32 == db) return TRUE;
1418 case WINED3DFMT_D15S1:
1419 if (15 == db) return TRUE;
1421 case WINED3DFMT_D24S8:
1422 if (24 == db && 8 == sb) return TRUE;
1424 case WINED3DFMT_D24FS8:
1425 if (24 == db && 8 == sb) return TRUE;
1427 case WINED3DFMT_D24X8:
1428 if (24 == db) return TRUE;
1430 case WINED3DFMT_D24X4S4:
1431 if (24 == db && 4 == sb) return TRUE;
1433 case WINED3DFMT_D32F_LOCKABLE:
1434 if (32 == db) return TRUE;
1437 ERR("unsupported format %s\n", debug_d3dformat(Format));
1441 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1443 case WINED3DFMT_D16:
1444 case WINED3DFMT_D16_LOCKABLE:
1445 case WINED3DFMT_D32:
1446 case WINED3DFMT_D15S1:
1447 case WINED3DFMT_D24S8:
1448 case WINED3DFMT_D24FS8:
1449 case WINED3DFMT_D24X8:
1450 case WINED3DFMT_D24X4S4:
1451 case WINED3DFMT_D32F_LOCKABLE:
1454 ERR("unsupported format %s\n", debug_d3dformat(Format));
1461 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1462 WINED3DFORMAT AdapterFormat,
1463 WINED3DFORMAT RenderTargetFormat,
1464 WINED3DFORMAT DepthStencilFormat) {
1465 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1466 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1467 WineD3D_Context* ctx = NULL;
1468 GLXFBConfig* cfgs = NULL;
1472 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1474 DeviceType, debug_d3ddevicetype(DeviceType),
1475 AdapterFormat, debug_d3dformat(AdapterFormat),
1476 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1477 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1479 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1480 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1481 return WINED3DERR_INVALIDCALL;
1483 /* TODO: use the real context if it's available */
1484 ctx = WineD3D_CreateFakeGLContext();
1486 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1488 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1492 for (it = 0; it < nCfgs; ++it) {
1493 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1494 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1503 /* If there's a current context then we cannot create a fake one so pass everything */
1508 WineD3D_ReleaseFakeGLContext(ctx);
1510 if (hr != WINED3D_OK)
1511 TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1513 TRACE_(d3d_caps)("(%p) : Returning %x\n", This, hr);
1517 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1518 WINED3DFORMAT SurfaceFormat,
1519 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1521 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1522 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1525 DeviceType, debug_d3ddevicetype(DeviceType),
1526 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1531 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1532 return WINED3DERR_INVALIDCALL;
1535 if (pQualityLevels != NULL) {
1536 static int s_single_shot = 0;
1537 if (!s_single_shot) {
1538 FIXME("Quality levels unsupported at present\n");
1541 *pQualityLevels = 1; /* Guess at a value! */
1544 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1545 return WINED3DERR_NOTAVAILABLE;
1548 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1549 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1551 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1552 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1555 CheckType, debug_d3ddevicetype(CheckType),
1556 DisplayFormat, debug_d3dformat(DisplayFormat),
1557 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1560 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1561 return WINED3DERR_INVALIDCALL;
1565 GLXFBConfig* cfgs = NULL;
1568 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1570 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1572 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1573 for (it = 0; it < nCfgs; ++it) {
1574 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1581 WineD3D_ReleaseFakeGLContext(ctx);
1586 return WINED3DERR_NOTAVAILABLE;
1589 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1590 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1591 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1592 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1595 DeviceType, debug_d3ddevicetype(DeviceType),
1596 AdapterFormat, debug_d3dformat(AdapterFormat),
1597 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1598 RType, debug_d3dresourcetype(RType),
1599 CheckFormat, debug_d3dformat(CheckFormat));
1601 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1602 return WINED3DERR_INVALIDCALL;
1605 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1606 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1607 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1608 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1609 TRACE_(d3d_caps)("[FAILED]\n");
1610 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1613 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1614 switch (CheckFormat) {
1615 case WINED3DFMT_D16_LOCKABLE:
1616 case WINED3DFMT_D32:
1617 case WINED3DFMT_D15S1:
1618 case WINED3DFMT_D24S8:
1619 case WINED3DFMT_D24X8:
1620 case WINED3DFMT_D24X4S4:
1621 case WINED3DFMT_D16:
1622 case WINED3DFMT_L16:
1623 case WINED3DFMT_D32F_LOCKABLE:
1624 case WINED3DFMT_D24FS8:
1625 TRACE_(d3d_caps)("[OK]\n");
1628 TRACE_(d3d_caps)("[FAILED]\n");
1629 return WINED3DERR_NOTAVAILABLE;
1631 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1632 switch (CheckFormat) {
1633 case WINED3DFMT_R8G8B8:
1634 case WINED3DFMT_A8R8G8B8:
1635 case WINED3DFMT_X8R8G8B8:
1636 case WINED3DFMT_R5G6B5:
1637 case WINED3DFMT_X1R5G5B5:
1638 case WINED3DFMT_A1R5G5B5:
1639 case WINED3DFMT_A4R4G4B4:
1640 case WINED3DFMT_R3G3B2:
1641 case WINED3DFMT_X4R4G4B4:
1642 case WINED3DFMT_A8B8G8R8:
1643 case WINED3DFMT_X8B8G8R8:
1645 TRACE_(d3d_caps)("[OK]\n");
1648 TRACE_(d3d_caps)("[FAILED]\n");
1649 return WINED3DERR_NOTAVAILABLE;
1653 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1654 switch (CheckFormat) {
1660 TRACE_(d3d_caps)("[OK]\n");
1663 break; /* Avoid compiler warnings */
1667 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1669 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1671 switch (CheckFormat) {
1673 case D3DFMT_A16B16G16R16F:
1674 if (!half_pixel_support) break;
1676 case D3DFMT_A32B32G32R32F:
1677 TRACE_(d3d_caps)("[OK]\n");
1680 break; /* Avoid compiler warnings */
1684 /* This format is nothing special and it is supported perfectly.
1685 * However, ati and nvidia driver on windows do not mark this format as
1686 * supported (tested with the dxCapsViewer) and pretending to
1687 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1688 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1689 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1691 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1692 TRACE_(d3d_caps)("[FAILED]\n");
1693 return WINED3DERR_NOTAVAILABLE;
1696 switch (CheckFormat) {
1699 * supported: RGB(A) formats
1701 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1702 case WINED3DFMT_A8R8G8B8:
1703 case WINED3DFMT_X8R8G8B8:
1704 case WINED3DFMT_R5G6B5:
1705 case WINED3DFMT_X1R5G5B5:
1706 case WINED3DFMT_A1R5G5B5:
1707 case WINED3DFMT_A4R4G4B4:
1708 case WINED3DFMT_R3G3B2:
1710 case WINED3DFMT_A8R3G3B2:
1711 case WINED3DFMT_X4R4G4B4:
1712 case WINED3DFMT_A8B8G8R8:
1713 case WINED3DFMT_X8B8G8R8:
1714 case WINED3DFMT_A2R10G10B10:
1715 case WINED3DFMT_A2B10G10R10:
1716 TRACE_(d3d_caps)("[OK]\n");
1720 * supported: Palettized
1723 TRACE_(d3d_caps)("[OK]\n");
1727 * Supported: (Alpha)-Luminance
1730 case WINED3DFMT_A8L8:
1731 case WINED3DFMT_A4L4:
1732 TRACE_(d3d_caps)("[OK]\n");
1736 * Not supported for now: Bump mapping formats
1737 * Enable some because games often fail when they are not available
1738 * and are still playable even without bump mapping
1740 case WINED3DFMT_V8U8:
1741 case WINED3DFMT_V16U16:
1742 case WINED3DFMT_L6V5U5:
1743 case WINED3DFMT_X8L8V8U8:
1744 case WINED3DFMT_Q8W8V8U8:
1745 case WINED3DFMT_W11V11U10:
1746 case WINED3DFMT_A2W10V10U10:
1747 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1751 * DXTN Formats: Handled above
1760 * Odd formats - not supported
1762 case WINED3DFMT_VERTEXDATA:
1763 case WINED3DFMT_INDEX16:
1764 case WINED3DFMT_INDEX32:
1765 case WINED3DFMT_Q16W16V16U16:
1766 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1767 return WINED3DERR_NOTAVAILABLE;
1770 * Float formats: Not supported right now
1772 case WINED3DFMT_G16R16F:
1773 case WINED3DFMT_G32R32F:
1774 case WINED3DFMT_CxV8U8:
1775 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1776 return WINED3DERR_NOTAVAILABLE;
1779 case WINED3DFMT_G16R16:
1780 case WINED3DFMT_A16B16G16R16:
1781 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1782 return WINED3DERR_NOTAVAILABLE;
1788 TRACE_(d3d_caps)("[FAILED]\n");
1789 return WINED3DERR_NOTAVAILABLE;
1792 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1793 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1794 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1796 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1799 DeviceType, debug_d3ddevicetype(DeviceType),
1800 SourceFormat, debug_d3dformat(SourceFormat),
1801 TargetFormat, debug_d3dformat(TargetFormat));
1805 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1806 subset of a D3DCAPS9 structure. However, it has to come via a void *
1807 as the d3d8 interface cannot import the d3d9 header */
1808 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1810 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1812 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1814 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1815 return WINED3DERR_INVALIDCALL;
1818 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1820 /* If we don't know the device settings, go query them now */
1821 if (!This->isGLInfoValid) {
1822 /* use the desktop window to fill gl caps */
1823 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1825 /* We are running off a real context, save the values */
1826 if (rc) This->isGLInfoValid = TRUE;
1828 select_shader_mode(&This->gl_info, DeviceType,
1829 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1830 select_shader_max_constants(&This->gl_info);
1832 /* ------------------------------------------------
1833 The following fields apply to both d3d8 and d3d9
1834 ------------------------------------------------ */
1835 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1836 *pCaps->AdapterOrdinal = Adapter;
1839 *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
1840 WINED3DCAPS2_FULLSCREENGAMMA;
1842 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1844 *pCaps->CursorCaps = 0;
1847 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1848 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1849 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1850 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1851 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1852 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1853 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1854 WINED3DDEVCAPS_PUREDEVICE |
1855 WINED3DDEVCAPS_HWRASTERIZATION |
1856 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1857 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1858 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1859 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1860 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1862 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1863 D3DPMISCCAPS_CULLCCW |
1864 D3DPMISCCAPS_CULLCW |
1865 D3DPMISCCAPS_COLORWRITEENABLE |
1866 D3DPMISCCAPS_CLIPTLVERTS |
1867 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1868 D3DPMISCCAPS_MASKZ |
1869 D3DPMISCCAPS_BLENDOP;
1871 D3DPMISCCAPS_NULLREFERENCE
1872 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1873 D3DPMISCCAPS_FOGANDSPECULARALPHA
1874 D3DPMISCCAPS_SEPARATEALPHABLEND
1875 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1876 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1877 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1879 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1881 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1882 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1883 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1884 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1887 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1888 WINED3DPRASTERCAPS_PAT |
1889 WINED3DPRASTERCAPS_WFOG |
1890 WINED3DPRASTERCAPS_ZFOG |
1891 WINED3DPRASTERCAPS_FOGVERTEX |
1892 WINED3DPRASTERCAPS_FOGTABLE |
1893 WINED3DPRASTERCAPS_FOGRANGE |
1894 WINED3DPRASTERCAPS_STIPPLE |
1895 WINED3DPRASTERCAPS_SUBPIXEL |
1896 WINED3DPRASTERCAPS_ZTEST |
1897 WINED3DPRASTERCAPS_SCISSORTEST |
1898 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1899 WINED3DPRASTERCAPS_DEPTHBIAS;
1901 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1902 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1903 WINED3DPRASTERCAPS_ZBIAS |
1904 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1907 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1908 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1909 WINED3DPRASTERCAPS_ANTIALIASEDGES
1910 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1911 WINED3DPRASTERCAPS_WBUFFER */
1913 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1915 D3DPCMPCAPS_GREATER |
1916 D3DPCMPCAPS_GREATEREQUAL |
1918 D3DPCMPCAPS_LESSEQUAL |
1920 D3DPCMPCAPS_NOTEQUAL;
1922 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1923 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1924 D3DPBLENDCAPS_BOTHSRCALPHA |
1925 D3DPBLENDCAPS_DESTALPHA |
1926 D3DPBLENDCAPS_DESTCOLOR |
1927 D3DPBLENDCAPS_INVDESTALPHA |
1928 D3DPBLENDCAPS_INVDESTCOLOR |
1929 D3DPBLENDCAPS_INVSRCALPHA |
1930 D3DPBLENDCAPS_INVSRCCOLOR |
1932 D3DPBLENDCAPS_SRCALPHA |
1933 D3DPBLENDCAPS_SRCALPHASAT |
1934 D3DPBLENDCAPS_SRCCOLOR |
1937 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1938 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1939 D3DPBLENDCAPS_BOTHSRCALPHA |
1940 D3DPBLENDCAPS_DESTALPHA |
1941 D3DPBLENDCAPS_DESTCOLOR |
1942 D3DPBLENDCAPS_INVDESTALPHA |
1943 D3DPBLENDCAPS_INVDESTCOLOR |
1944 D3DPBLENDCAPS_INVSRCALPHA |
1945 D3DPBLENDCAPS_INVSRCCOLOR |
1947 D3DPBLENDCAPS_SRCALPHA |
1948 D3DPBLENDCAPS_SRCALPHASAT |
1949 D3DPBLENDCAPS_SRCCOLOR |
1952 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1954 D3DPCMPCAPS_GREATER |
1955 D3DPCMPCAPS_GREATEREQUAL |
1957 D3DPCMPCAPS_LESSEQUAL |
1959 D3DPCMPCAPS_NOTEQUAL;
1961 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1962 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1963 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1964 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1965 WINED3DPSHADECAPS_COLORFLATRGB |
1966 WINED3DPSHADECAPS_FOGFLAT |
1967 WINED3DPSHADECAPS_FOGGOURAUD |
1968 WINED3DPSHADECAPS_SPECULARFLATRGB;
1970 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1971 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1972 WINED3DPTEXTURECAPS_BORDER |
1973 WINED3DPTEXTURECAPS_MIPMAP |
1974 WINED3DPTEXTURECAPS_PROJECTED |
1975 WINED3DPTEXTURECAPS_PERSPECTIVE |
1976 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1978 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1979 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1980 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1981 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1984 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1985 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1986 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1987 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1991 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1992 WINED3DPTFILTERCAPS_MAGFPOINT |
1993 WINED3DPTFILTERCAPS_MINFLINEAR |
1994 WINED3DPTFILTERCAPS_MINFPOINT |
1995 WINED3DPTFILTERCAPS_MIPFLINEAR |
1996 WINED3DPTFILTERCAPS_MIPFPOINT |
1997 WINED3DPTFILTERCAPS_LINEAR |
1998 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1999 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2000 WINED3DPTFILTERCAPS_MIPLINEAR |
2001 WINED3DPTFILTERCAPS_MIPNEAREST |
2002 WINED3DPTFILTERCAPS_NEAREST;
2004 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2005 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2006 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2009 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2010 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2011 WINED3DPTFILTERCAPS_MAGFPOINT |
2012 WINED3DPTFILTERCAPS_MINFLINEAR |
2013 WINED3DPTFILTERCAPS_MINFPOINT |
2014 WINED3DPTFILTERCAPS_MIPFLINEAR |
2015 WINED3DPTFILTERCAPS_MIPFPOINT |
2016 WINED3DPTFILTERCAPS_LINEAR |
2017 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2018 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2019 WINED3DPTFILTERCAPS_MIPLINEAR |
2020 WINED3DPTFILTERCAPS_MIPNEAREST |
2021 WINED3DPTFILTERCAPS_NEAREST;
2023 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2024 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2025 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2028 *pCaps->CubeTextureFilterCaps = 0;
2030 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2031 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2032 WINED3DPTFILTERCAPS_MAGFPOINT |
2033 WINED3DPTFILTERCAPS_MINFLINEAR |
2034 WINED3DPTFILTERCAPS_MINFPOINT |
2035 WINED3DPTFILTERCAPS_MIPFLINEAR |
2036 WINED3DPTFILTERCAPS_MIPFPOINT |
2037 WINED3DPTFILTERCAPS_LINEAR |
2038 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2039 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2040 WINED3DPTFILTERCAPS_MIPLINEAR |
2041 WINED3DPTFILTERCAPS_MIPNEAREST |
2042 WINED3DPTFILTERCAPS_NEAREST;
2044 *pCaps->VolumeTextureFilterCaps = 0;
2046 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2047 D3DPTADDRESSCAPS_CLAMP |
2048 D3DPTADDRESSCAPS_WRAP;
2050 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2051 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2053 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2054 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2056 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2057 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2060 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2061 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2062 D3DPTADDRESSCAPS_CLAMP |
2063 D3DPTADDRESSCAPS_WRAP;
2064 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2065 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2067 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2068 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2070 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2071 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2074 *pCaps->VolumeTextureAddressCaps = 0;
2076 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2080 D3DLINECAPS_ALPHACMP
2083 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2084 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2086 if(GL_SUPPORT(EXT_TEXTURE3D))
2087 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2089 *pCaps->MaxVolumeExtent = 0;
2091 *pCaps->MaxTextureRepeat = 32768;
2092 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2093 *pCaps->MaxVertexW = 1.0;
2095 *pCaps->GuardBandLeft = 0;
2096 *pCaps->GuardBandTop = 0;
2097 *pCaps->GuardBandRight = 0;
2098 *pCaps->GuardBandBottom = 0;
2100 *pCaps->ExtentsAdjust = 0;
2102 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2103 D3DSTENCILCAPS_INCRSAT |
2104 D3DSTENCILCAPS_INVERT |
2105 D3DSTENCILCAPS_KEEP |
2106 D3DSTENCILCAPS_REPLACE |
2107 D3DSTENCILCAPS_ZERO;
2108 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2109 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2110 D3DSTENCILCAPS_INCR;
2112 if ( This->dxVersion > 8 &&
2113 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2114 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2115 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2118 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2120 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2121 D3DTEXOPCAPS_ADDSIGNED |
2122 D3DTEXOPCAPS_ADDSIGNED2X |
2123 D3DTEXOPCAPS_MODULATE |
2124 D3DTEXOPCAPS_MODULATE2X |
2125 D3DTEXOPCAPS_MODULATE4X |
2126 D3DTEXOPCAPS_SELECTARG1 |
2127 D3DTEXOPCAPS_SELECTARG2 |
2128 D3DTEXOPCAPS_DISABLE;
2130 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2131 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2132 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2133 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2134 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2135 D3DTEXOPCAPS_BLENDFACTORALPHA |
2136 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2138 D3DTEXOPCAPS_SUBTRACT;
2140 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2141 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2142 D3DTEXOPCAPS_MULTIPLYADD |
2143 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2144 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2145 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2147 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2148 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2150 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2151 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2152 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2157 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2159 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2160 D3DTEXOPCAPS_PREMODULATE */
2163 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2164 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2165 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2166 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2170 #if 0 /* TODO: Blends support in drawprim */
2171 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2173 *pCaps->MaxVertexBlendMatrices = 0;
2175 *pCaps->MaxVertexBlendMatrixIndex = 1;
2177 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2178 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2181 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2182 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2183 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2184 WINED3DVTXPCAPS_LOCALVIEWER |
2185 WINED3DVTXPCAPS_VERTEXFOG |
2186 WINED3DVTXPCAPS_TEXGEN;
2188 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2190 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2191 *pCaps->MaxVertexIndex = 0xFFFFF;
2192 *pCaps->MaxStreams = MAX_STREAMS;
2193 *pCaps->MaxStreamStride = 1024;
2195 /* FIXME: the shader mode should be per adapter */
2196 if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
2197 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2198 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2199 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2200 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2201 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2202 *pCaps->VertexShaderVersion = D3DVS_VERSION(2,0);
2204 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2205 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2206 } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
2207 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
2208 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2209 } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
2210 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2211 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2213 *pCaps->VertexShaderVersion = 0;
2214 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2217 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2219 /* FIXME: the shader mode should be per adapter */
2220 if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
2221 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2222 in case of GeforceFX cards. */
2223 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2224 *pCaps->PixelShaderVersion = D3DPS_VERSION(2,0);
2226 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2227 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2228 *pCaps->PixelShader1xMaxValue = 1.0;
2229 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2230 } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
2231 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
2232 *pCaps->PixelShader1xMaxValue = 1.0;
2233 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2234 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2235 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2236 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2237 *pCaps->PixelShader1xMaxValue = 1.0;
2238 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2240 *pCaps->PixelShaderVersion = 0;
2241 *pCaps->PixelShader1xMaxValue = 0.0;
2242 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2245 /* ------------------------------------------------
2246 The following fields apply to d3d9 only
2247 ------------------------------------------------ */
2248 if (This->dxVersion > 8) {
2249 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2250 *pCaps->DevCaps2 = 0;
2251 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2252 *pCaps->MaxNpatchTessellationLevel = 0;
2253 *pCaps->MasterAdapterOrdinal = 0;
2254 *pCaps->AdapterOrdinalInGroup = 0;
2255 *pCaps->NumberOfAdaptersInGroup = 1;
2257 if(*pCaps->VertexShaderVersion >= D3DVS_VERSION(2,0)) {
2258 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2259 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2260 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2261 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2262 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2266 D3DDTCAPS_FLOAT16_2 |
2267 D3DDTCAPS_FLOAT16_4;
2270 *pCaps->DeclTypes = 0;
2272 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2273 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2274 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2277 *pCaps->NumSimultaneousRTs = 1;
2279 *pCaps->StretchRectFilterCaps = 0;
2280 *pCaps->VertexTextureFilterCaps = 0;
2282 if(*pCaps->VertexShaderVersion == D3DVS_VERSION(3,0)) {
2283 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2284 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2285 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2286 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2287 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2288 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2290 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2291 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2292 } else if(*pCaps->VertexShaderVersion == D3DVS_VERSION(2,0)) {
2293 *pCaps->VS20Caps.Caps = 0;
2294 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2295 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2296 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2298 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2299 *pCaps->MaxVertexShader30InstructionSlots = 0;
2300 } else { /* VS 1.x */
2301 *pCaps->VS20Caps.Caps = 0;
2302 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2303 *pCaps->VS20Caps.NumTemps = 0;
2304 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2306 *pCaps->MaxVShaderInstructionsExecuted = 0;
2307 *pCaps->MaxVertexShader30InstructionSlots = 0;
2310 if(*pCaps->PixelShaderVersion == D3DPS_VERSION(3,0)) {
2311 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2312 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2314 /* 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 */
2315 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2316 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2317 D3DPS20CAPS_PREDICATION |
2318 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2319 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2320 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2321 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2322 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2323 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2325 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2326 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2327 } else if(*pCaps->PixelShaderVersion == D3DPS_VERSION(2,0)) {
2328 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2329 *pCaps->PS20Caps.Caps = 0;
2330 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2331 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2332 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2333 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2335 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2336 *pCaps->MaxPixelShader30InstructionSlots = 0;
2337 } else { /* PS 1.x */
2338 *pCaps->PS20Caps.Caps = 0;
2339 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2340 *pCaps->PS20Caps.NumTemps = 0;
2341 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2342 *pCaps->PS20Caps.NumInstructionSlots = 0;
2344 *pCaps->MaxPShaderInstructionsExecuted = 0;
2345 *pCaps->MaxPixelShader30InstructionSlots = 0;
2353 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2354 and fields being inserted in the middle, a new structure is used in place */
2355 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2356 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2359 IWineD3DDeviceImpl *object = NULL;
2360 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2362 HRESULT temp_result;
2364 /* Validate the adapter number */
2365 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2366 return WINED3DERR_INVALIDCALL;
2369 /* Create a WineD3DDevice object */
2370 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2371 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2372 TRACE("Created WineD3DDevice object @ %p\n", object);
2373 if (NULL == object) {
2374 return WINED3DERR_OUTOFVIDEOMEMORY;
2377 /* Set up initial COM information */
2378 object->lpVtbl = &IWineD3DDevice_Vtbl;
2380 object->wineD3D = iface;
2381 IWineD3D_AddRef(object->wineD3D);
2382 object->parent = parent;
2384 /* Set the state up as invalid until the device is fully created */
2385 object->state = WINED3DERR_DRIVERINTERNALERROR;
2387 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This, Adapter, DeviceType,
2388 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2390 /* Save the creation parameters */
2391 object->createParms.AdapterOrdinal = Adapter;
2392 object->createParms.DeviceType = DeviceType;
2393 object->createParms.hFocusWindow = hFocusWindow;
2394 object->createParms.BehaviorFlags = BehaviourFlags;
2396 /* Initialize other useful values */
2397 object->adapterNo = Adapter;
2398 object->devType = DeviceType;
2400 TRACE("(%p) : Creating stateblock\n", This);
2401 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2402 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2404 (IWineD3DStateBlock **)&object->stateBlock,
2405 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2406 WARN("Failed to create stateblock\n");
2407 goto create_device_error;
2409 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2410 object->updateStateBlock = object->stateBlock;
2411 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2412 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2414 /* Setup some defaults for creating the implicit swapchain */
2416 /* FIXME: both of those should be made per adapter */
2417 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2419 select_shader_mode(&This->gl_info, DeviceType,
2420 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
2421 select_shader_max_constants(&This->gl_info);
2423 temp_result = allocate_shader_constants(object->updateStateBlock);
2424 if (WINED3D_OK != temp_result)
2427 /* set the state of the device to valid */
2428 object->state = WINED3D_OK;
2430 /* Get the initial screen setup for ddraw */
2431 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2432 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2433 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2434 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2438 create_device_error:
2440 /* Set the device state to error */
2441 object->state = WINED3DERR_DRIVERINTERNALERROR;
2443 if (object->updateStateBlock != NULL) {
2444 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2445 object->updateStateBlock = NULL;
2447 if (object->stateBlock != NULL) {
2448 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2449 object->stateBlock = NULL;
2451 if (object->renderTarget != NULL) {
2452 IWineD3DSurface_Release(object->renderTarget);
2453 object->renderTarget = NULL;
2455 if (object->stencilBufferTarget != NULL) {
2456 IWineD3DSurface_Release(object->stencilBufferTarget);
2457 object->stencilBufferTarget = NULL;
2459 if (object->stencilBufferTarget != NULL) {
2460 IWineD3DSurface_Release(object->stencilBufferTarget);
2461 object->stencilBufferTarget = NULL;
2463 HeapFree(GetProcessHeap(), 0, object);
2464 *ppReturnedDeviceInterface = NULL;
2465 return WINED3DERR_INVALIDCALL;
2469 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2470 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2471 IUnknown_AddRef(This->parent);
2472 *pParent = This->parent;
2476 /**********************************************************
2477 * IWineD3D VTbl follows
2478 **********************************************************/
2480 const IWineD3DVtbl IWineD3D_Vtbl =
2483 IWineD3DImpl_QueryInterface,
2484 IWineD3DImpl_AddRef,
2485 IWineD3DImpl_Release,
2487 IWineD3DImpl_GetParent,
2488 IWineD3DImpl_GetAdapterCount,
2489 IWineD3DImpl_RegisterSoftwareDevice,
2490 IWineD3DImpl_GetAdapterMonitor,
2491 IWineD3DImpl_GetAdapterModeCount,
2492 IWineD3DImpl_EnumAdapterModes,
2493 IWineD3DImpl_GetAdapterDisplayMode,
2494 IWineD3DImpl_GetAdapterIdentifier,
2495 IWineD3DImpl_CheckDeviceMultiSampleType,
2496 IWineD3DImpl_CheckDepthStencilMatch,
2497 IWineD3DImpl_CheckDeviceType,
2498 IWineD3DImpl_CheckDeviceFormat,
2499 IWineD3DImpl_CheckDeviceFormatConversion,
2500 IWineD3DImpl_GetDeviceCaps,
2501 IWineD3DImpl_CreateDevice