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 %ld\n", This, refCount - 1);
189 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
190 IWineD3DImpl *This = (IWineD3DImpl *)iface;
192 TRACE("(%p) : Releasing from %ld\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%08lx)\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);
549 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
550 gl_info->ps_glsl_constantsF = gl_max;
551 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
552 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
553 gl_info->supported[ARB_IMAGING] = TRUE;
554 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
555 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
556 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
557 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
558 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
559 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
560 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
561 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
562 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
563 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
564 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
565 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
566 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
567 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
568 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
569 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
570 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
571 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
572 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
573 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
574 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
575 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
576 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
577 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
578 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
579 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
580 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
581 } else if (strcmp(ThisExtn, "GL_ARB_texture_float") == 0) {
582 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
583 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
584 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
585 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
586 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
587 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
588 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
589 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
590 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
591 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
592 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
593 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
594 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
595 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
596 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
597 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
598 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
599 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
600 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
601 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
602 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
603 gl_info->vs_arb_version = VS_VERSION_11;
604 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
605 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
606 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
607 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
608 gl_info->vs_arb_constantsF = gl_max;
609 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
610 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
611 gl_info->vs_arb_max_temps = gl_max;
612 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
613 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
614 gl_info->vs_arb_max_instructions = gl_max;
615 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
616 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
617 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
618 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
619 gl_info->vs_glsl_constantsF = gl_max;
620 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
621 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
622 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
623 gl_info->max_blends = gl_max;
624 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
625 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
626 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
627 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
628 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
629 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
630 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
631 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
632 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
633 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
637 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
638 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
639 gl_info->supported[EXT_FOG_COORD] = TRUE;
640 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
641 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
642 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
643 } else if (strcmp(ThisExtn, "GL_EXT_blend_minmax") == 0) {
644 TRACE_(d3d_caps)(" FOUND: EXT Blend minmax support\n");
645 gl_info->supported[EXT_BLEND_MINMAX] = TRUE;
646 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
647 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
648 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
649 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
650 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
651 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
652 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
653 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
654 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
655 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
656 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
657 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
658 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
659 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
660 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
661 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
662 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
663 gl_info->supported[EXT_TEXTURE3D] = TRUE;
664 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
665 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
666 gl_info->max_texture3d_size = gl_max;
667 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
668 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
669 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
670 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
671 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
672 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
673 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
674 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
675 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
676 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
678 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
680 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
681 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
682 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
683 gl_info->max_anisotropy = gl_max;
684 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
685 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
686 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
687 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
688 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
689 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
690 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
691 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
692 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
697 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
698 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
699 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
700 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
701 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
702 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
703 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
704 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
705 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
706 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
707 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
708 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
709 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
710 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
711 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
712 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
713 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
714 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
715 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
716 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
717 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
718 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
719 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
720 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
721 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
722 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
723 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
724 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
725 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
726 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
727 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
728 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
729 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
730 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
731 gl_info->vs_nv_version = VS_VERSION_30;
732 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
733 gl_info->vs_nv_version = VS_VERSION_20;
734 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
735 gl_info->vs_nv_version = VS_VERSION_11;
737 gl_info->vs_nv_version = VS_VERSION_10;
738 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
739 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
745 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
746 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
747 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
748 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
749 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
750 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
751 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
752 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
753 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
754 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
755 gl_info->vs_ati_version = VS_VERSION_11;
756 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
757 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
761 if (*GL_Extensions == ' ') GL_Extensions++;
764 checkGLcall("extension detection\n");
766 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
768 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
769 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
770 * in case of the latest videocards in the number of pixel/vertex pipelines.
772 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
773 * rendering. Various games use this information to get a rough estimation of the features of the card
774 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
775 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
776 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
779 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
780 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
781 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
782 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
783 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
784 * is used for rendering which is not always the case). This would work but it is not very portable. Second
785 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
788 * As said most games only use the PCI id to get an indication of the capabilities of the card.
789 * It doesn't really matter if the given id is the correct one if we return the id of a card with
790 * similar 3d features.
792 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
793 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
794 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
795 * won't pass we return a default card. This way is better than maintaining a full card database as even
796 * without a full database we can return a card with similar features. Second the size of the database
797 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
798 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
799 * to distinguishes between different models from that family.
801 switch (gl_info->gl_vendor) {
803 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
804 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
806 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
807 if (strstr(gl_info->gl_renderer, "7800") ||
808 strstr(gl_info->gl_renderer, "7900") ||
809 strstr(gl_info->gl_renderer, "7950") ||
810 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
811 strstr(gl_info->gl_renderer, "Quadro FX 5"))
812 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
813 else if(strstr(gl_info->gl_renderer, "6800") ||
814 strstr(gl_info->gl_renderer, "7600"))
815 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
816 else if(strstr(gl_info->gl_renderer, "6600") ||
817 strstr(gl_info->gl_renderer, "6610") ||
818 strstr(gl_info->gl_renderer, "6700"))
819 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
821 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
822 } else if(WINE_D3D9_CAPABLE(gl_info)) {
823 if (strstr(gl_info->gl_renderer, "5800") ||
824 strstr(gl_info->gl_renderer, "5900") ||
825 strstr(gl_info->gl_renderer, "5950") ||
826 strstr(gl_info->gl_renderer, "Quadro FX"))
827 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
828 else if(strstr(gl_info->gl_renderer, "5600") ||
829 strstr(gl_info->gl_renderer, "5650") ||
830 strstr(gl_info->gl_renderer, "5700") ||
831 strstr(gl_info->gl_renderer, "5750"))
832 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
834 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
835 } else if(WINE_D3D8_CAPABLE(gl_info)) {
836 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
837 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
839 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
840 } else if(WINE_D3D7_CAPABLE(gl_info)) {
841 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
842 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
843 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
844 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
845 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
846 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
848 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
850 if (strstr(gl_info->gl_renderer, "TNT2"))
851 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
853 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
857 if(WINE_D3D9_CAPABLE(gl_info)) {
859 if (strstr(gl_info->gl_renderer, "X1600") ||
860 strstr(gl_info->gl_renderer, "X1800") ||
861 strstr(gl_info->gl_renderer, "X1900") ||
862 strstr(gl_info->gl_renderer, "X1950"))
863 gl_info->gl_card = CARD_ATI_RADEON_X1600;
864 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
865 else if(strstr(gl_info->gl_renderer, "X700") ||
866 strstr(gl_info->gl_renderer, "X800") ||
867 strstr(gl_info->gl_renderer, "X850") ||
868 strstr(gl_info->gl_renderer, "X1300") ||
869 strstr(gl_info->gl_renderer, "X1400"))
870 gl_info->gl_card = CARD_ATI_RADEON_X700;
873 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
874 } else if(WINE_D3D8_CAPABLE(gl_info)) {
875 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
876 } else if(WINE_D3D7_CAPABLE(gl_info)) {
877 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
879 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
882 if (strstr(gl_info->gl_renderer, "915GM")) {
883 gl_info->gl_card = CARD_INTEL_I915GM;
884 } else if (strstr(gl_info->gl_renderer, "915G")) {
885 gl_info->gl_card = CARD_INTEL_I915G;
886 } else if (strstr(gl_info->gl_renderer, "865G")) {
887 gl_info->gl_card = CARD_INTEL_I865G;
888 } else if (strstr(gl_info->gl_renderer, "855G")) {
889 gl_info->gl_card = CARD_INTEL_I855G;
890 } else if (strstr(gl_info->gl_renderer, "830G")) {
891 gl_info->gl_card = CARD_INTEL_I830G;
893 gl_info->gl_card = CARD_INTEL_I915G;
899 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
900 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
901 * them a good generic choice.
903 gl_info->gl_vendor = VENDOR_NVIDIA;
904 if(WINE_D3D9_CAPABLE(gl_info))
905 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
906 else if(WINE_D3D8_CAPABLE(gl_info))
907 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
908 else if(WINE_D3D7_CAPABLE(gl_info))
909 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
910 else if(WINE_D3D6_CAPABLE(gl_info))
911 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
913 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
915 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
917 /* Load all the lookup tables
918 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
919 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
920 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
922 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
923 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
926 for (i = 0; i < MAX_LOOKUPS; i++) {
927 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
930 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
931 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
932 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
933 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
934 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
935 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
936 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
937 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
938 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
939 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
941 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
942 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
943 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
944 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
945 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
948 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
949 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
950 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
951 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
952 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
953 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
954 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
955 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
956 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
957 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
958 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
959 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
960 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
962 /* TODO: config lookups */
964 if (display != NULL) {
965 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
966 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
968 if (NULL == GLX_Extensions) {
969 ERR(" GLX_Extensions returns NULL\n");
971 while (*GLX_Extensions != 0x00) {
972 const char *Start = GLX_Extensions;
975 memset(ThisExtn, 0x00, sizeof(ThisExtn));
976 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
979 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
980 TRACE_(d3d_caps)("- %s\n", ThisExtn);
981 if (*GLX_Extensions == ' ') GLX_Extensions++;
986 /* If we created a dummy context, throw it away */
987 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
989 /* Only save the values obtained when a display is provided */
990 if (fake_ctx == NULL) {
997 /**********************************************************
998 * IWineD3D implementation follows
999 **********************************************************/
1001 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
1002 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1004 /* FIXME: Set to one for now to imply the display */
1005 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1009 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1010 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1011 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1015 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1016 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1017 POINT pt = { -1, -1 };
1019 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1023 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1024 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1027 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1028 of the same bpp but different resolutions */
1030 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1031 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1032 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1033 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1035 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1039 if (Adapter == 0) { /* Display */
1042 #if !defined( DEBUG_SINGLE_MODE )
1045 /* Work out the current screen bpp */
1046 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1047 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1050 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1054 case D3DFMT_UNKNOWN:
1057 case D3DFMT_X8R8G8B8:
1058 case D3DFMT_A8R8G8B8:
1059 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1060 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1062 case D3DFMT_X1R5G5B5:
1063 case D3DFMT_A1R5G5B5:
1065 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1068 /* Skip other modes as they do not match the requested format */
1076 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1079 FIXME_(d3d_caps)("Adapter not primary display\n");
1084 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1085 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1086 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1087 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1089 /* Validate the parameters as much as possible */
1090 if (NULL == pMode ||
1091 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1092 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1093 return WINED3DERR_INVALIDCALL;
1096 if (Adapter == 0) { /* Display */
1097 #if !defined( DEBUG_SINGLE_MODE )
1101 /* Work out the current screen bpp */
1102 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1103 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1106 /* If we are filtering to a specific format, then need to skip all unrelated
1107 modes, but if mode is irrelevant, then we can use the index directly */
1108 if (Format == D3DFMT_UNKNOWN)
1114 DEVMODEW DevModeWtmp;
1117 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1121 case D3DFMT_UNKNOWN:
1124 case D3DFMT_X8R8G8B8:
1125 case D3DFMT_A8R8G8B8:
1126 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1127 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1129 case D3DFMT_X1R5G5B5:
1130 case D3DFMT_A1R5G5B5:
1132 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1135 /* Skip other modes as they do not match requested format */
1142 /* Now get the display mode via the calculated index */
1143 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1145 pMode->Width = DevModeW.dmPelsWidth;
1146 pMode->Height = DevModeW.dmPelsHeight;
1147 bpp = min(DevModeW.dmBitsPerPel, bpp);
1148 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1149 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1151 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1154 if (Format == D3DFMT_UNKNOWN)
1157 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1158 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1159 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1160 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1161 default: pMode->Format = D3DFMT_UNKNOWN;
1164 pMode->Format = Format;
1169 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1170 return WINED3DERR_INVALIDCALL;
1174 /* Return one setting of the format requested */
1175 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1177 pMode->Height = 600;
1178 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1179 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1182 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1183 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1186 FIXME_(d3d_caps)("Adapter not primary display\n");
1192 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1193 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1194 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1196 if (NULL == pMode ||
1197 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1198 return WINED3DERR_INVALIDCALL;
1201 if (Adapter == 0) { /* Display */
1205 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1206 pMode->Width = DevModeW.dmPelsWidth;
1207 pMode->Height = DevModeW.dmPelsHeight;
1208 bpp = DevModeW.dmBitsPerPel;
1209 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1210 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1212 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1216 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1217 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1218 case 24: pMode->Format = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1219 case 32: pMode->Format = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1220 default: pMode->Format = D3DFMT_UNKNOWN;
1224 FIXME_(d3d_caps)("Adapter not primary display\n");
1227 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1228 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1232 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1235 /* only works with one adapter at the moment... */
1237 /* Get the display */
1238 device_context = GetDC(0);
1239 display = get_display(device_context);
1240 ReleaseDC(0, device_context);
1244 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1245 and fields being inserted in the middle, a new structure is used in place */
1246 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1247 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1248 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1250 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1252 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1253 return WINED3DERR_INVALIDCALL;
1256 if (Adapter == 0) { /* Display - only device supported for now */
1258 BOOL isGLInfoValid = This->isGLInfoValid;
1260 /* FillGLCaps updates gl_info, but we only want to store and
1261 reuse the values once we have a context which is valid. Values from
1262 a temporary context may differ from the final ones */
1263 if (isGLInfoValid == FALSE) {
1264 WineD3D_Context *fake_ctx = NULL;
1265 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1266 /* If we don't know the device settings, go query them now */
1267 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1268 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1271 /* If it worked, return the information requested */
1272 if (isGLInfoValid) {
1273 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1274 strcpy(pIdentifier->Driver, "Display");
1275 strcpy(pIdentifier->Description, "Direct3D HAL");
1277 /* Note dx8 doesn't supply a DeviceName */
1278 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1279 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1280 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1281 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1282 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1283 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1284 *(pIdentifier->SubSysId) = 0;
1285 *(pIdentifier->Revision) = 0;
1289 /* If it failed, return dummy values from an NVidia driver */
1290 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1291 strcpy(pIdentifier->Driver, "Display");
1292 strcpy(pIdentifier->Description, "Direct3D HAL");
1293 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1294 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1295 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1296 /* 71.74 is a current Linux Nvidia driver version */
1297 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1298 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1299 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1300 *(pIdentifier->SubSysId) = 0;
1301 *(pIdentifier->Revision) = 0;
1304 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1305 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1306 *(pIdentifier->WHQLLevel) = 0;
1308 *(pIdentifier->WHQLLevel) = 1;
1312 FIXME_(d3d_caps)("Adapter not primary display\n");
1318 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1319 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1321 int rb, gb, bb, ab, type, buf_sz;
1323 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1324 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1325 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1326 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1327 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1328 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1331 case WINED3DFMT_X8R8G8B8:
1332 case WINED3DFMT_R8G8B8:
1333 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1335 case WINED3DFMT_A8R8G8B8:
1336 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1338 case WINED3DFMT_A2R10G10B10:
1339 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1341 case WINED3DFMT_X1R5G5B5:
1342 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1344 case WINED3DFMT_A1R5G5B5:
1345 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1347 case WINED3DFMT_X4R4G4B4:
1348 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1350 case WINED3DFMT_R5G6B5:
1351 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1353 case WINED3DFMT_R3G3B2:
1354 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1356 case WINED3DFMT_A8P8:
1357 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1360 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1363 ERR("unsupported format %s\n", debug_d3dformat(Format));
1367 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1369 case WINED3DFMT_X8R8G8B8:
1370 case WINED3DFMT_R8G8B8:
1371 case WINED3DFMT_A8R8G8B8:
1372 case WINED3DFMT_A2R10G10B10:
1373 case WINED3DFMT_X1R5G5B5:
1374 case WINED3DFMT_A1R5G5B5:
1375 case WINED3DFMT_R5G6B5:
1376 case WINED3DFMT_R3G3B2:
1377 case WINED3DFMT_A8P8:
1381 ERR("unsupported format %s\n", debug_d3dformat(Format));
1388 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1389 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1393 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1394 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1397 case WINED3DFMT_D16:
1398 case WINED3DFMT_D16_LOCKABLE:
1399 if (16 == db) return TRUE;
1401 case WINED3DFMT_D32:
1402 if (32 == db) return TRUE;
1404 case WINED3DFMT_D15S1:
1405 if (15 == db) return TRUE;
1407 case WINED3DFMT_D24S8:
1408 if (24 == db && 8 == sb) return TRUE;
1410 case WINED3DFMT_D24FS8:
1411 if (24 == db && 8 == sb) return TRUE;
1413 case WINED3DFMT_D24X8:
1414 if (24 == db) return TRUE;
1416 case WINED3DFMT_D24X4S4:
1417 if (24 == db && 4 == sb) return TRUE;
1419 case WINED3DFMT_D32F_LOCKABLE:
1420 if (32 == db) return TRUE;
1423 ERR("unsupported format %s\n", debug_d3dformat(Format));
1427 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1429 case WINED3DFMT_D16:
1430 case WINED3DFMT_D16_LOCKABLE:
1431 case WINED3DFMT_D32:
1432 case WINED3DFMT_D15S1:
1433 case WINED3DFMT_D24S8:
1434 case WINED3DFMT_D24FS8:
1435 case WINED3DFMT_D24X8:
1436 case WINED3DFMT_D24X4S4:
1437 case WINED3DFMT_D32F_LOCKABLE:
1440 ERR("unsupported format %s\n", debug_d3dformat(Format));
1447 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1448 WINED3DFORMAT AdapterFormat,
1449 WINED3DFORMAT RenderTargetFormat,
1450 WINED3DFORMAT DepthStencilFormat) {
1451 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1452 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1453 WineD3D_Context* ctx = NULL;
1454 GLXFBConfig* cfgs = NULL;
1458 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1460 DeviceType, debug_d3ddevicetype(DeviceType),
1461 AdapterFormat, debug_d3dformat(AdapterFormat),
1462 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1463 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1465 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1466 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1467 return WINED3DERR_INVALIDCALL;
1469 /* TODO: use the real context if it's available */
1470 ctx = WineD3D_CreateFakeGLContext();
1472 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1474 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1478 for (it = 0; it < nCfgs; ++it) {
1479 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1480 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1489 /* If there's a current context then we cannot create a fake one so pass everything */
1494 WineD3D_ReleaseFakeGLContext(ctx);
1496 if (hr != WINED3D_OK)
1497 TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1499 TRACE_(d3d_caps)("(%p) : Returning %lx\n", This, hr);
1503 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1504 WINED3DFORMAT SurfaceFormat,
1505 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1507 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1508 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1511 DeviceType, debug_d3ddevicetype(DeviceType),
1512 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1517 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1518 return WINED3DERR_INVALIDCALL;
1521 if (pQualityLevels != NULL) {
1522 static int s_single_shot = 0;
1523 if (!s_single_shot) {
1524 FIXME("Quality levels unsupported at present\n");
1527 *pQualityLevels = 1; /* Guess at a value! */
1530 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1531 return WINED3DERR_NOTAVAILABLE;
1534 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1535 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1537 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1538 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1541 CheckType, debug_d3ddevicetype(CheckType),
1542 DisplayFormat, debug_d3dformat(DisplayFormat),
1543 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1546 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1547 return WINED3DERR_INVALIDCALL;
1551 GLXFBConfig* cfgs = NULL;
1554 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1556 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1558 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1559 for (it = 0; it < nCfgs; ++it) {
1560 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1567 WineD3D_ReleaseFakeGLContext(ctx);
1572 return WINED3DERR_NOTAVAILABLE;
1575 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1576 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1577 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1578 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1581 DeviceType, debug_d3ddevicetype(DeviceType),
1582 AdapterFormat, debug_d3dformat(AdapterFormat),
1583 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1584 RType, debug_d3dresourcetype(RType),
1585 CheckFormat, debug_d3dformat(CheckFormat));
1587 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1588 return WINED3DERR_INVALIDCALL;
1591 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1592 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1593 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1594 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1595 TRACE_(d3d_caps)("[FAILED]\n");
1596 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1599 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1600 switch (CheckFormat) {
1601 case WINED3DFMT_D16_LOCKABLE:
1602 case WINED3DFMT_D32:
1603 case WINED3DFMT_D15S1:
1604 case WINED3DFMT_D24S8:
1605 case WINED3DFMT_D24X8:
1606 case WINED3DFMT_D24X4S4:
1607 case WINED3DFMT_D16:
1608 case WINED3DFMT_L16:
1609 case WINED3DFMT_D32F_LOCKABLE:
1610 case WINED3DFMT_D24FS8:
1611 TRACE_(d3d_caps)("[OK]\n");
1614 TRACE_(d3d_caps)("[FAILED]\n");
1615 return WINED3DERR_NOTAVAILABLE;
1617 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1618 switch (CheckFormat) {
1619 case WINED3DFMT_R8G8B8:
1620 case WINED3DFMT_A8R8G8B8:
1621 case WINED3DFMT_X8R8G8B8:
1622 case WINED3DFMT_R5G6B5:
1623 case WINED3DFMT_X1R5G5B5:
1624 case WINED3DFMT_A1R5G5B5:
1625 case WINED3DFMT_A4R4G4B4:
1626 case WINED3DFMT_R3G3B2:
1627 case WINED3DFMT_X4R4G4B4:
1628 case WINED3DFMT_A8B8G8R8:
1629 case WINED3DFMT_X8B8G8R8:
1631 TRACE_(d3d_caps)("[OK]\n");
1634 TRACE_(d3d_caps)("[FAILED]\n");
1635 return WINED3DERR_NOTAVAILABLE;
1639 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1640 switch (CheckFormat) {
1646 TRACE_(d3d_caps)("[OK]\n");
1649 break; /* Avoid compiler warnings */
1653 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1655 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1657 switch (CheckFormat) {
1659 case D3DFMT_A16B16G16R16F:
1660 if (!half_pixel_support) break;
1662 case D3DFMT_A32B32G32R32F:
1663 TRACE_(d3d_caps)("[OK]\n");
1666 break; /* Avoid compiler warnings */
1670 /* This format is nothing special and it is supported perfectly.
1671 * However, ati and nvidia driver on windows do not mark this format as
1672 * supported (tested with the dxCapsViewer) and pretending to
1673 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1674 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1675 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1677 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1678 TRACE_(d3d_caps)("[FAILED]\n");
1679 return WINED3DERR_NOTAVAILABLE;
1682 switch (CheckFormat) {
1685 * supported: RGB(A) formats
1687 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1688 case WINED3DFMT_A8R8G8B8:
1689 case WINED3DFMT_X8R8G8B8:
1690 case WINED3DFMT_R5G6B5:
1691 case WINED3DFMT_X1R5G5B5:
1692 case WINED3DFMT_A1R5G5B5:
1693 case WINED3DFMT_A4R4G4B4:
1694 case WINED3DFMT_R3G3B2:
1696 case WINED3DFMT_A8R3G3B2:
1697 case WINED3DFMT_X4R4G4B4:
1698 case WINED3DFMT_A8B8G8R8:
1699 case WINED3DFMT_X8B8G8R8:
1700 case WINED3DFMT_A2R10G10B10:
1701 case WINED3DFMT_A2B10G10R10:
1702 TRACE_(d3d_caps)("[OK]\n");
1706 * supported: Palettized
1709 TRACE_(d3d_caps)("[OK]\n");
1713 * Supported: (Alpha)-Luminance
1716 case WINED3DFMT_A8L8:
1717 case WINED3DFMT_A4L4:
1718 TRACE_(d3d_caps)("[OK]\n");
1722 * Not supported for now: Bump mapping formats
1723 * Enable some because games often fail when they are not available
1724 * and are still playable even without bump mapping
1726 case WINED3DFMT_V8U8:
1727 case WINED3DFMT_V16U16:
1728 case WINED3DFMT_L6V5U5:
1729 case WINED3DFMT_X8L8V8U8:
1730 case WINED3DFMT_Q8W8V8U8:
1731 case WINED3DFMT_W11V11U10:
1732 case WINED3DFMT_A2W10V10U10:
1733 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1737 * DXTN Formats: Handled above
1746 * Odd formats - not supported
1748 case WINED3DFMT_VERTEXDATA:
1749 case WINED3DFMT_INDEX16:
1750 case WINED3DFMT_INDEX32:
1751 case WINED3DFMT_Q16W16V16U16:
1752 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1753 return WINED3DERR_NOTAVAILABLE;
1756 * Float formats: Not supported right now
1758 case WINED3DFMT_G16R16F:
1759 case WINED3DFMT_G32R32F:
1760 case WINED3DFMT_CxV8U8:
1761 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1762 return WINED3DERR_NOTAVAILABLE;
1765 case WINED3DFMT_G16R16:
1766 case WINED3DFMT_A16B16G16R16:
1767 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1768 return WINED3DERR_NOTAVAILABLE;
1774 TRACE_(d3d_caps)("[FAILED]\n");
1775 return WINED3DERR_NOTAVAILABLE;
1778 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1779 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1780 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1782 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1785 DeviceType, debug_d3ddevicetype(DeviceType),
1786 SourceFormat, debug_d3dformat(SourceFormat),
1787 TargetFormat, debug_d3dformat(TargetFormat));
1791 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1792 subset of a D3DCAPS9 structure. However, it has to come via a void *
1793 as the d3d8 interface cannot import the d3d9 header */
1794 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1796 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1798 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1800 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1801 return WINED3DERR_INVALIDCALL;
1804 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1806 /* If we don't know the device settings, go query them now */
1807 if (This->isGLInfoValid == FALSE) {
1808 /* use the desktop window to fill gl caps */
1809 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1811 /* We are running off a real context, save the values */
1812 if (rc) This->isGLInfoValid = TRUE;
1814 select_shader_mode(&This->gl_info, DeviceType,
1815 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1816 select_shader_max_constants(&This->gl_info);
1818 /* ------------------------------------------------
1819 The following fields apply to both d3d8 and d3d9
1820 ------------------------------------------------ */
1821 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1822 *pCaps->AdapterOrdinal = Adapter;
1825 *pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
1826 *pCaps->Caps3 = WINED3DDEVCAPS_HWTRANSFORMANDLIGHT;
1827 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1829 *pCaps->CursorCaps = 0;
1832 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1833 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1834 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1835 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1836 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1837 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1838 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1839 WINED3DDEVCAPS_PUREDEVICE |
1840 WINED3DDEVCAPS_HWRASTERIZATION |
1841 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1842 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1843 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1844 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1845 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1847 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1848 D3DPMISCCAPS_CULLCCW |
1849 D3DPMISCCAPS_CULLCW |
1850 D3DPMISCCAPS_COLORWRITEENABLE |
1851 D3DPMISCCAPS_CLIPTLVERTS |
1852 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1853 D3DPMISCCAPS_MASKZ |
1854 D3DPMISCCAPS_BLENDOP;
1856 D3DPMISCCAPS_NULLREFERENCE
1857 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1858 D3DPMISCCAPS_FOGANDSPECULARALPHA
1859 D3DPMISCCAPS_SEPARATEALPHABLEND
1860 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1861 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1862 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1864 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1866 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1867 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1868 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1869 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1872 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1873 WINED3DPRASTERCAPS_PAT |
1874 WINED3DPRASTERCAPS_WFOG |
1875 WINED3DPRASTERCAPS_ZFOG |
1876 WINED3DPRASTERCAPS_FOGVERTEX |
1877 WINED3DPRASTERCAPS_FOGTABLE |
1878 WINED3DPRASTERCAPS_FOGRANGE |
1879 WINED3DPRASTERCAPS_STIPPLE |
1880 WINED3DPRASTERCAPS_SUBPIXEL |
1881 WINED3DPRASTERCAPS_ZTEST |
1882 WINED3DPRASTERCAPS_SCISSORTEST |
1883 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1884 WINED3DPRASTERCAPS_DEPTHBIAS;
1886 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1887 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1888 WINED3DPRASTERCAPS_ZBIAS |
1889 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1892 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1893 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1894 WINED3DPRASTERCAPS_ANTIALIASEDGES
1895 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1896 WINED3DPRASTERCAPS_WBUFFER */
1898 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1900 D3DPCMPCAPS_GREATER |
1901 D3DPCMPCAPS_GREATEREQUAL |
1903 D3DPCMPCAPS_LESSEQUAL |
1905 D3DPCMPCAPS_NOTEQUAL;
1907 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1908 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1909 D3DPBLENDCAPS_BOTHSRCALPHA |
1910 D3DPBLENDCAPS_DESTALPHA |
1911 D3DPBLENDCAPS_DESTCOLOR |
1912 D3DPBLENDCAPS_INVDESTALPHA |
1913 D3DPBLENDCAPS_INVDESTCOLOR |
1914 D3DPBLENDCAPS_INVSRCALPHA |
1915 D3DPBLENDCAPS_INVSRCCOLOR |
1917 D3DPBLENDCAPS_SRCALPHA |
1918 D3DPBLENDCAPS_SRCALPHASAT |
1919 D3DPBLENDCAPS_SRCCOLOR |
1922 *pCaps->DestBlendCaps = 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->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1939 D3DPCMPCAPS_GREATER |
1940 D3DPCMPCAPS_GREATEREQUAL |
1942 D3DPCMPCAPS_LESSEQUAL |
1944 D3DPCMPCAPS_NOTEQUAL;
1946 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1947 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1948 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1949 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1950 WINED3DPSHADECAPS_COLORFLATRGB |
1951 WINED3DPSHADECAPS_FOGFLAT |
1952 WINED3DPSHADECAPS_FOGGOURAUD |
1953 WINED3DPSHADECAPS_SPECULARFLATRGB;
1955 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1956 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1957 WINED3DPTEXTURECAPS_BORDER |
1958 WINED3DPTEXTURECAPS_MIPMAP |
1959 WINED3DPTEXTURECAPS_PROJECTED |
1960 WINED3DPTEXTURECAPS_PERSPECTIVE |
1961 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1963 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1964 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1965 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1966 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1969 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1970 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1971 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1972 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1976 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1977 WINED3DPTFILTERCAPS_MAGFPOINT |
1978 WINED3DPTFILTERCAPS_MINFLINEAR |
1979 WINED3DPTFILTERCAPS_MINFPOINT |
1980 WINED3DPTFILTERCAPS_MIPFLINEAR |
1981 WINED3DPTFILTERCAPS_MIPFPOINT |
1982 WINED3DPTFILTERCAPS_LINEAR |
1983 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1984 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1985 WINED3DPTFILTERCAPS_MIPLINEAR |
1986 WINED3DPTFILTERCAPS_MIPNEAREST |
1987 WINED3DPTFILTERCAPS_NEAREST;
1989 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1990 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1991 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1994 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1995 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1996 WINED3DPTFILTERCAPS_MAGFPOINT |
1997 WINED3DPTFILTERCAPS_MINFLINEAR |
1998 WINED3DPTFILTERCAPS_MINFPOINT |
1999 WINED3DPTFILTERCAPS_MIPFLINEAR |
2000 WINED3DPTFILTERCAPS_MIPFPOINT |
2001 WINED3DPTFILTERCAPS_LINEAR |
2002 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2003 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2004 WINED3DPTFILTERCAPS_MIPLINEAR |
2005 WINED3DPTFILTERCAPS_MIPNEAREST |
2006 WINED3DPTFILTERCAPS_NEAREST;
2008 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2009 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2010 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2013 *pCaps->CubeTextureFilterCaps = 0;
2015 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2016 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2017 WINED3DPTFILTERCAPS_MAGFPOINT |
2018 WINED3DPTFILTERCAPS_MINFLINEAR |
2019 WINED3DPTFILTERCAPS_MINFPOINT |
2020 WINED3DPTFILTERCAPS_MIPFLINEAR |
2021 WINED3DPTFILTERCAPS_MIPFPOINT |
2022 WINED3DPTFILTERCAPS_LINEAR |
2023 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2024 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2025 WINED3DPTFILTERCAPS_MIPLINEAR |
2026 WINED3DPTFILTERCAPS_MIPNEAREST |
2027 WINED3DPTFILTERCAPS_NEAREST;
2029 *pCaps->VolumeTextureFilterCaps = 0;
2031 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2032 D3DPTADDRESSCAPS_CLAMP |
2033 D3DPTADDRESSCAPS_WRAP;
2035 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2036 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2038 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2039 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2041 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2042 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2045 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2046 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2047 D3DPTADDRESSCAPS_CLAMP |
2048 D3DPTADDRESSCAPS_WRAP;
2049 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2050 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2052 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2053 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2055 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2056 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2059 *pCaps->VolumeTextureAddressCaps = 0;
2061 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2065 D3DLINECAPS_ALPHACMP
2068 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2069 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2071 if(GL_SUPPORT(EXT_TEXTURE3D))
2072 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2074 *pCaps->MaxVolumeExtent = 0;
2076 *pCaps->MaxTextureRepeat = 32768;
2077 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2078 *pCaps->MaxVertexW = 1.0;
2080 *pCaps->GuardBandLeft = 0;
2081 *pCaps->GuardBandTop = 0;
2082 *pCaps->GuardBandRight = 0;
2083 *pCaps->GuardBandBottom = 0;
2085 *pCaps->ExtentsAdjust = 0;
2087 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2088 D3DSTENCILCAPS_INCRSAT |
2089 D3DSTENCILCAPS_INVERT |
2090 D3DSTENCILCAPS_KEEP |
2091 D3DSTENCILCAPS_REPLACE |
2092 D3DSTENCILCAPS_ZERO;
2093 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2094 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2095 D3DSTENCILCAPS_INCR;
2097 if ( This->dxVersion > 8 &&
2098 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2099 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2100 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2103 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2105 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2106 D3DTEXOPCAPS_ADDSIGNED |
2107 D3DTEXOPCAPS_ADDSIGNED2X |
2108 D3DTEXOPCAPS_MODULATE |
2109 D3DTEXOPCAPS_MODULATE2X |
2110 D3DTEXOPCAPS_MODULATE4X |
2111 D3DTEXOPCAPS_SELECTARG1 |
2112 D3DTEXOPCAPS_SELECTARG2 |
2113 D3DTEXOPCAPS_DISABLE;
2115 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2116 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2117 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2118 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2119 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2120 D3DTEXOPCAPS_BLENDFACTORALPHA |
2121 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2123 D3DTEXOPCAPS_SUBTRACT;
2125 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2126 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2127 D3DTEXOPCAPS_MULTIPLYADD |
2128 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2129 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2130 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2132 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2133 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2135 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2136 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2137 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2142 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2144 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2145 D3DTEXOPCAPS_PREMODULATE */
2148 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2149 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2150 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2151 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2155 #if 0 /* TODO: Blends support in drawprim */
2156 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2158 *pCaps->MaxVertexBlendMatrices = 0;
2160 *pCaps->MaxVertexBlendMatrixIndex = 1;
2162 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2163 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2166 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2167 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2168 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2169 WINED3DVTXPCAPS_LOCALVIEWER |
2170 WINED3DVTXPCAPS_VERTEXFOG |
2171 WINED3DVTXPCAPS_TEXGEN;
2173 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2175 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2176 *pCaps->MaxVertexIndex = 0xFFFFF;
2177 *pCaps->MaxStreams = MAX_STREAMS;
2178 *pCaps->MaxStreamStride = 1024;
2180 /* FIXME: the shader mode should be per adapter */
2181 if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
2182 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2183 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2184 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2185 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2186 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2187 *pCaps->VertexShaderVersion = D3DVS_VERSION(2,0);
2189 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2190 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2191 } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
2192 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
2193 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2194 } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
2195 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2196 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2198 *pCaps->VertexShaderVersion = 0;
2199 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2202 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2204 /* FIXME: the shader mode should be per adapter */
2205 if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
2206 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2207 in case of GeforceFX cards. */
2208 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2209 *pCaps->PixelShaderVersion = D3DPS_VERSION(2,0);
2211 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2212 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2213 *pCaps->PixelShader1xMaxValue = 1.0;
2214 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2215 } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
2216 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
2217 *pCaps->PixelShader1xMaxValue = 1.0;
2218 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2219 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2220 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2221 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2222 *pCaps->PixelShader1xMaxValue = 1.0;
2223 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2225 *pCaps->PixelShaderVersion = 0;
2226 *pCaps->PixelShader1xMaxValue = 0.0;
2227 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2230 /* ------------------------------------------------
2231 The following fields apply to d3d9 only
2232 ------------------------------------------------ */
2233 if (This->dxVersion > 8) {
2234 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2235 *pCaps->DevCaps2 = 0;
2236 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2237 *pCaps->MaxNpatchTessellationLevel = 0;
2238 *pCaps->MasterAdapterOrdinal = 0;
2239 *pCaps->AdapterOrdinalInGroup = 0;
2240 *pCaps->NumberOfAdaptersInGroup = 1;
2242 if(*pCaps->VertexShaderVersion >= D3DVS_VERSION(2,0)) {
2243 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2244 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2245 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2246 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2247 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2251 D3DDTCAPS_FLOAT16_2 |
2252 D3DDTCAPS_FLOAT16_4;
2255 *pCaps->DeclTypes = 0;
2257 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2258 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2259 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2262 *pCaps->NumSimultaneousRTs = 1;
2264 *pCaps->StretchRectFilterCaps = 0;
2265 *pCaps->VertexTextureFilterCaps = 0;
2267 if(*pCaps->VertexShaderVersion == D3DVS_VERSION(3,0)) {
2268 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2269 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2270 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2271 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2272 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2273 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2275 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2276 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2277 } else if(*pCaps->VertexShaderVersion == D3DVS_VERSION(2,0)) {
2278 *pCaps->VS20Caps.Caps = 0;
2279 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2280 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2281 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2283 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2284 *pCaps->MaxVertexShader30InstructionSlots = 0;
2285 } else { /* VS 1.x */
2286 *pCaps->VS20Caps.Caps = 0;
2287 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2288 *pCaps->VS20Caps.NumTemps = 0;
2289 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2291 *pCaps->MaxVShaderInstructionsExecuted = 0;
2292 *pCaps->MaxVertexShader30InstructionSlots = 0;
2295 if(*pCaps->PixelShaderVersion == D3DPS_VERSION(3,0)) {
2296 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2297 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2299 /* 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 */
2300 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2301 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2302 D3DPS20CAPS_PREDICATION |
2303 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2304 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2305 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2306 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2307 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2308 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2310 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2311 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2312 } else if(*pCaps->PixelShaderVersion == D3DPS_VERSION(2,0)) {
2313 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2314 *pCaps->PS20Caps.Caps = 0;
2315 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2316 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2317 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2318 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2320 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2321 *pCaps->MaxPixelShader30InstructionSlots = 0;
2322 } else { /* PS 1.x */
2323 *pCaps->PS20Caps.Caps = 0;
2324 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2325 *pCaps->PS20Caps.NumTemps = 0;
2326 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2327 *pCaps->PS20Caps.NumInstructionSlots = 0;
2329 *pCaps->MaxPShaderInstructionsExecuted = 0;
2330 *pCaps->MaxPixelShader30InstructionSlots = 0;
2338 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2339 and fields being inserted in the middle, a new structure is used in place */
2340 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2341 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2344 IWineD3DDeviceImpl *object = NULL;
2345 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2347 HRESULT temp_result;
2349 /* Validate the adapter number */
2350 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2351 return WINED3DERR_INVALIDCALL;
2354 /* Create a WineD3DDevice object */
2355 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2356 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2357 TRACE("Created WineD3DDevice object @ %p\n", object);
2358 if (NULL == object) {
2359 return WINED3DERR_OUTOFVIDEOMEMORY;
2362 /* Set up initial COM information */
2363 object->lpVtbl = &IWineD3DDevice_Vtbl;
2365 object->wineD3D = iface;
2366 IWineD3D_AddRef(object->wineD3D);
2367 object->parent = parent;
2369 /* Set the state up as invalid until the device is fully created */
2370 object->state = WINED3DERR_DRIVERINTERNALERROR;
2372 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This, Adapter, DeviceType,
2373 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2375 /* Save the creation parameters */
2376 object->createParms.AdapterOrdinal = Adapter;
2377 object->createParms.DeviceType = DeviceType;
2378 object->createParms.hFocusWindow = hFocusWindow;
2379 object->createParms.BehaviorFlags = BehaviourFlags;
2381 /* Initialize other useful values */
2382 object->adapterNo = Adapter;
2383 object->devType = DeviceType;
2385 TRACE("(%p) : Creating stateblock\n", This);
2386 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2387 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2389 (IWineD3DStateBlock **)&object->stateBlock,
2390 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2391 WARN("Failed to create stateblock\n");
2392 goto create_device_error;
2394 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2395 object->updateStateBlock = object->stateBlock;
2396 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2397 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2399 /* Setup some defaults for creating the implicit swapchain */
2401 /* FIXME: both of those should be made per adapter */
2402 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2404 select_shader_mode(&This->gl_info, DeviceType,
2405 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
2406 select_shader_max_constants(&This->gl_info);
2408 temp_result = allocate_shader_constants(object->updateStateBlock);
2409 if (WINED3D_OK != temp_result)
2412 /* set the state of the device to valid */
2413 object->state = WINED3D_OK;
2415 /* Get the initial screen setup for ddraw */
2416 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2417 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2418 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2419 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2423 create_device_error:
2425 /* Set the device state to error */
2426 object->state = WINED3DERR_DRIVERINTERNALERROR;
2428 if (object->updateStateBlock != NULL) {
2429 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2430 object->updateStateBlock = NULL;
2432 if (object->stateBlock != NULL) {
2433 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2434 object->stateBlock = NULL;
2436 if (object->renderTarget != NULL) {
2437 IWineD3DSurface_Release(object->renderTarget);
2438 object->renderTarget = NULL;
2440 if (object->stencilBufferTarget != NULL) {
2441 IWineD3DSurface_Release(object->stencilBufferTarget);
2442 object->stencilBufferTarget = NULL;
2444 if (object->stencilBufferTarget != NULL) {
2445 IWineD3DSurface_Release(object->stencilBufferTarget);
2446 object->stencilBufferTarget = NULL;
2448 HeapFree(GetProcessHeap(), 0, object);
2449 *ppReturnedDeviceInterface = NULL;
2450 return WINED3DERR_INVALIDCALL;
2454 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2455 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2456 IUnknown_AddRef(This->parent);
2457 *pParent = This->parent;
2461 /**********************************************************
2462 * IWineD3D VTbl follows
2463 **********************************************************/
2465 const IWineD3DVtbl IWineD3D_Vtbl =
2468 IWineD3DImpl_QueryInterface,
2469 IWineD3DImpl_AddRef,
2470 IWineD3DImpl_Release,
2472 IWineD3DImpl_GetParent,
2473 IWineD3DImpl_GetAdapterCount,
2474 IWineD3DImpl_RegisterSoftwareDevice,
2475 IWineD3DImpl_GetAdapterMonitor,
2476 IWineD3DImpl_GetAdapterModeCount,
2477 IWineD3DImpl_EnumAdapterModes,
2478 IWineD3DImpl_GetAdapterDisplayMode,
2479 IWineD3DImpl_GetAdapterIdentifier,
2480 IWineD3DImpl_CheckDeviceMultiSampleType,
2481 IWineD3DImpl_CheckDepthStencilMatch,
2482 IWineD3DImpl_CheckDeviceType,
2483 IWineD3DImpl_CheckDeviceFormat,
2484 IWineD3DImpl_CheckDeviceFormatConversion,
2485 IWineD3DImpl_GetDeviceCaps,
2486 IWineD3DImpl_CreateDevice