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 strcpy(gl_info->gl_renderer, gl_string);
313 /* Fill in the GL info retrievable depending on the display */
314 if (NULL != display) {
315 test = glXQueryVersion(display, &major, &minor);
316 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
318 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
320 gl_string = (const char *) glGetString(GL_VENDOR);
322 TRACE_(d3d_caps)("Filling vendor string %s\n", gl_string);
323 if (gl_string != NULL) {
324 /* Fill in the GL vendor */
325 if (strstr(gl_string, "NVIDIA")) {
326 gl_info->gl_vendor = VENDOR_NVIDIA;
327 } else if (strstr(gl_string, "ATI")) {
328 gl_info->gl_vendor = VENDOR_ATI;
329 } else if (strstr(gl_string, "Intel(R)") ||
330 strstr(gl_info->gl_renderer, "Intel(R)")) {
331 gl_info->gl_vendor = VENDOR_INTEL;
332 } else if (strstr(gl_string, "Mesa")) {
333 gl_info->gl_vendor = VENDOR_MESA;
335 gl_info->gl_vendor = VENDOR_WINE;
338 gl_info->gl_vendor = VENDOR_WINE;
342 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
344 /* Parse the GL_VERSION field into major and minor information */
345 gl_string = (const char *) glGetString(GL_VERSION);
346 if (gl_string != NULL) {
348 switch (gl_info->gl_vendor) {
350 gl_string_cursor = strstr(gl_string, "NVIDIA");
351 if (!gl_string_cursor) {
352 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
356 gl_string_cursor = strstr(gl_string_cursor, " ");
357 if (!gl_string_cursor) {
358 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
362 while (*gl_string_cursor == ' ') {
366 if (!*gl_string_cursor) {
367 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
371 major = atoi(gl_string_cursor);
372 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
376 if (*gl_string_cursor++ != '.') {
377 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
381 minor = atoi(gl_string_cursor);
382 minor = major*100+minor;
389 gl_string_cursor = strchr(gl_string, '-');
390 if (gl_string_cursor) {
394 /* Check if version number is of the form x.y.z */
395 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
397 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
399 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
401 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
404 /* Mark version number as malformed */
406 gl_string_cursor = 0;
409 if (!gl_string_cursor)
410 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
412 major = *gl_string_cursor - '0';
413 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
419 gl_string_cursor = strstr(gl_string, "Mesa");
420 gl_string_cursor = strstr(gl_string_cursor, " ");
421 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
422 if (*gl_string_cursor) {
426 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
427 tmp[cursor++] = *gl_string_cursor;
433 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
437 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
438 tmp[cursor++] = *gl_string_cursor;
450 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
451 TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08lx)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
454 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
457 * Initialize openGL extension related variables
458 * with Default values
460 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
461 gl_info->max_buffers = 1;
462 gl_info->max_textures = 1;
463 gl_info->max_texture_stages = 1;
464 gl_info->max_samplers = 1;
465 gl_info->max_sampler_stages = 1;
466 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
467 gl_info->ps_arb_max_temps = 0;
468 gl_info->ps_arb_max_instructions = 0;
469 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
470 gl_info->vs_arb_max_temps = 0;
471 gl_info->vs_arb_max_instructions = 0;
472 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
473 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
474 gl_info->vs_glsl_constantsF = 0;
475 gl_info->ps_glsl_constantsF = 0;
476 gl_info->vs_arb_constantsF = 0;
477 gl_info->ps_arb_constantsF = 0;
479 /* Now work out what GL support this card really has */
480 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
485 /* Retrieve opengl defaults */
486 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
487 gl_info->max_clipplanes = min(D3DMAXUSERCLIPPLANES, gl_max);
488 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
490 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
491 gl_info->max_lights = gl_max;
492 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
494 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_max);
495 gl_info->max_texture_size = gl_max;
496 TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
498 glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
499 gl_info->max_pointsize = gl_floatv[1];
500 TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
502 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
503 GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
504 TRACE_(d3d_caps)("GL_Extensions reported:\n");
506 if (NULL == GL_Extensions) {
507 ERR(" GL_Extensions returns NULL\n");
509 while (*GL_Extensions != 0x00) {
510 const char *Start = GL_Extensions;
513 memset(ThisExtn, 0x00, sizeof(ThisExtn));
514 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
517 memcpy(ThisExtn, Start, (GL_Extensions - Start));
518 TRACE_(d3d_caps)("- %s\n", ThisExtn);
523 if (strcmp(ThisExtn, "GL_ARB_draw_buffers") == 0) {
524 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
525 TRACE_(d3d_caps)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max);
526 gl_info->supported[ARB_DRAW_BUFFERS] = TRUE;
527 gl_info->max_buffers = gl_max;
528 } else if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
529 gl_info->ps_arb_version = PS_VERSION_11;
530 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
531 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
532 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
533 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
534 gl_info->max_samplers = min(MAX_SAMPLERS, gl_max);
535 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
536 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max);
537 gl_info->ps_arb_constantsF = gl_max;
538 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
539 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max);
540 gl_info->ps_arb_max_temps = gl_max;
541 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
542 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max);
543 gl_info->ps_arb_max_instructions = gl_max;
544 } else if (strcmp(ThisExtn, "GL_ARB_fragment_shader") == 0) {
545 gl_info->supported[ARB_FRAGMENT_SHADER] = TRUE;
546 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &gl_max);
547 TRACE_(d3d_caps)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max);
548 gl_info->ps_glsl_constantsF = gl_max;
549 } else if (strcmp(ThisExtn, "GL_ARB_imaging") == 0) {
550 TRACE_(d3d_caps)(" FOUND: ARB imaging support\n");
551 gl_info->supported[ARB_IMAGING] = TRUE;
552 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
553 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
554 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
555 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
556 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
557 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
558 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
559 gl_info->max_textures = min(MAX_TEXTURES, gl_max);
560 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
561 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
562 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
563 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
564 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
565 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
566 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
567 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
568 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
569 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
570 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
571 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
572 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
573 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
574 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
575 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
576 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
577 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
578 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
579 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
580 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
581 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
582 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
583 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
584 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
585 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
586 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
587 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
588 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
589 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
590 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
591 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
592 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
593 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
594 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
595 gl_info->vs_arb_version = VS_VERSION_11;
596 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
597 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
598 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
599 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
600 gl_info->vs_arb_constantsF = gl_max;
601 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
602 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
603 gl_info->vs_arb_max_temps = gl_max;
604 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
605 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
606 gl_info->vs_arb_max_instructions = gl_max;
607 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
608 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
609 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
610 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
611 gl_info->vs_glsl_constantsF = gl_max;
612 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
613 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
614 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
615 gl_info->max_blends = gl_max;
616 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
617 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
618 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
619 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
620 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
621 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
622 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
623 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
624 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
625 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
629 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
630 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
631 gl_info->supported[EXT_FOG_COORD] = TRUE;
632 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
633 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
634 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
635 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
636 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
637 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
638 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
639 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
640 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
641 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
642 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
643 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
644 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
645 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
646 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
647 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
648 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
649 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
650 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
651 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
652 gl_info->supported[EXT_TEXTURE3D] = TRUE;
653 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
654 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
655 gl_info->max_texture3d_size = gl_max;
656 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
657 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
658 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
659 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
660 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
661 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
662 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
663 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
664 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
665 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
666 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
667 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
668 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
669 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
670 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
671 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
672 gl_info->max_anisotropy = gl_max;
673 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
674 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
675 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
676 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
677 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
678 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
679 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
681 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
686 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
687 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
688 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
689 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
690 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
691 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
692 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
693 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
694 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
695 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
696 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
697 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
698 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
699 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
700 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
701 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
702 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
703 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
704 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
705 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
706 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
707 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
708 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
709 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
710 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
711 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
713 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
714 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
716 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
717 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
718 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
719 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
720 gl_info->vs_nv_version = VS_VERSION_30;
721 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
722 gl_info->vs_nv_version = VS_VERSION_20;
723 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
724 gl_info->vs_nv_version = VS_VERSION_11;
726 gl_info->vs_nv_version = VS_VERSION_10;
727 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
728 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
734 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
735 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
736 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
737 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
738 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
739 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
740 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
741 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
742 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
743 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
744 gl_info->vs_ati_version = VS_VERSION_11;
745 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
746 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
750 if (*GL_Extensions == ' ') GL_Extensions++;
753 checkGLcall("extension detection\n");
755 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
757 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
758 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
759 * in case of the latest videocards in the number of pixel/vertex pipelines.
761 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
762 * rendering. Various games use this information to get a rough estimation of the features of the card
763 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
764 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
765 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
768 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
769 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
770 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
771 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
772 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
773 * is used for rendering which doesn't allways the case). This would work but it is not very portable. Second
774 * it would not work well in lets say a remote X situation in which the amount of 3d features which can be used
777 * As said most games only use the PCI id to get an indication of the capabilities of the card.
778 * It doesn't really matter if the given id is the correct one if we return the id of a card with
779 * similar 3d features.
781 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
782 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
783 * is atleast a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
784 * won't pass we return a default card. This way is better than maintaining a full card database as even
785 * without a full database we can return a card with similar features. Second the size of the database
786 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
787 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
788 * to distinguishes between different models from that family.
790 switch (gl_info->gl_vendor) {
792 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two typs have more
793 * shader capabilities, so we use the shader capabilities to distinct between FX and 6xxx/7xxx.
795 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
796 if (strstr(gl_info->gl_renderer, "7800") ||
797 strstr(gl_info->gl_renderer, "7900") ||
798 strstr(gl_info->gl_renderer, "7950") ||
799 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
800 strstr(gl_info->gl_renderer, "Quadro FX 5"))
801 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
802 else if(strstr(gl_info->gl_renderer, "6800") ||
803 strstr(gl_info->gl_renderer, "7600"))
804 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
805 else if(strstr(gl_info->gl_renderer, "6600") ||
806 strstr(gl_info->gl_renderer, "6610") ||
807 strstr(gl_info->gl_renderer, "6700"))
808 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
810 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
811 } else if(WINE_D3D9_CAPABLE(gl_info)) {
812 if (strstr(gl_info->gl_renderer, "5800") ||
813 strstr(gl_info->gl_renderer, "5900") ||
814 strstr(gl_info->gl_renderer, "5950") ||
815 strstr(gl_info->gl_renderer, "Quadro FX"))
816 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
817 else if(strstr(gl_info->gl_renderer, "5600") ||
818 strstr(gl_info->gl_renderer, "5650") ||
819 strstr(gl_info->gl_renderer, "5700") ||
820 strstr(gl_info->gl_renderer, "5750"))
821 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
823 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
824 } else if(WINE_D3D8_CAPABLE(gl_info)) {
825 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
826 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
828 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
829 } else if(WINE_D3D7_CAPABLE(gl_info)) {
830 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
831 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
832 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
833 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
834 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
835 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
837 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
839 if (strstr(gl_info->gl_renderer, "TNT2"))
840 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
842 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
846 if(WINE_D3D9_CAPABLE(gl_info)) {
848 if (strstr(gl_info->gl_renderer, "X1600") ||
849 strstr(gl_info->gl_renderer, "X1800") ||
850 strstr(gl_info->gl_renderer, "X1900") ||
851 strstr(gl_info->gl_renderer, "X1950"))
852 gl_info->gl_card = CARD_ATI_RADEON_X1600;
853 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
854 else if(strstr(gl_info->gl_renderer, "X700") ||
855 strstr(gl_info->gl_renderer, "X800") ||
856 strstr(gl_info->gl_renderer, "X850") ||
857 strstr(gl_info->gl_renderer, "X1300") ||
858 strstr(gl_info->gl_renderer, "X1400"))
859 gl_info->gl_card = CARD_ATI_RADEON_X700;
862 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
863 } else if(WINE_D3D8_CAPABLE(gl_info)) {
864 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
865 } else if(WINE_D3D7_CAPABLE(gl_info)) {
866 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
868 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
871 if (strstr(gl_info->gl_renderer, "915GM")) {
872 gl_info->gl_card = CARD_INTEL_I915GM;
873 } else if (strstr(gl_info->gl_renderer, "915G")) {
874 gl_info->gl_card = CARD_INTEL_I915G;
875 } else if (strstr(gl_info->gl_renderer, "865G")) {
876 gl_info->gl_card = CARD_INTEL_I865G;
877 } else if (strstr(gl_info->gl_renderer, "855G")) {
878 gl_info->gl_card = CARD_INTEL_I855G;
879 } else if (strstr(gl_info->gl_renderer, "830G")) {
880 gl_info->gl_card = CARD_INTEL_I830G;
882 gl_info->gl_card = CARD_INTEL_I915G;
888 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
889 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
890 * them a good generic choice.
892 gl_info->gl_vendor = VENDOR_NVIDIA;
893 if(WINE_D3D9_CAPABLE(gl_info))
894 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
895 else if(WINE_D3D8_CAPABLE(gl_info))
896 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
897 else if(WINE_D3D7_CAPABLE(gl_info))
898 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
899 else if(WINE_D3D6_CAPABLE(gl_info))
900 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
902 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
904 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
906 /* Load all the lookup tables
907 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
908 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
909 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
911 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
912 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
915 for (i = 0; i < MAX_LOOKUPS; i++) {
916 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
919 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
920 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
921 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
922 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
923 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
924 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
925 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
926 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
927 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
928 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
930 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
931 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
932 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
933 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
934 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
937 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
938 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
939 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
940 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
941 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
942 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
943 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
944 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
945 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
946 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
947 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
948 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
949 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
951 /* TODO: config lookups */
953 if (display != NULL) {
954 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
955 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
957 if (NULL == GLX_Extensions) {
958 ERR(" GLX_Extensions returns NULL\n");
960 while (*GLX_Extensions != 0x00) {
961 const char *Start = GLX_Extensions;
964 memset(ThisExtn, 0x00, sizeof(ThisExtn));
965 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
968 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
969 TRACE_(d3d_caps)("- %s\n", ThisExtn);
970 if (*GLX_Extensions == ' ') GLX_Extensions++;
975 /* If we created a dummy context, throw it away */
976 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
978 /* Only save the values obtained when a display is provided */
979 if (fake_ctx == NULL) {
986 /**********************************************************
987 * IWineD3D implementation follows
988 **********************************************************/
990 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
991 IWineD3DImpl *This = (IWineD3DImpl *)iface;
993 /* FIXME: Set to one for now to imply the display */
994 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
998 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
999 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1000 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1004 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1005 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1006 POINT pt = { -1, -1 };
1008 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1012 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1013 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1016 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1017 of the same bpp but different resolutions */
1019 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1020 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1021 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1022 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1024 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1028 if (Adapter == 0) { /* Display */
1031 #if !defined( DEBUG_SINGLE_MODE )
1034 /* Work out the current screen bpp */
1035 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1036 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1039 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1043 case D3DFMT_UNKNOWN:
1046 case D3DFMT_X8R8G8B8:
1047 case D3DFMT_A8R8G8B8:
1048 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1049 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1051 case D3DFMT_X1R5G5B5:
1052 case D3DFMT_A1R5G5B5:
1054 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1057 /* Skip other modes as they do not match requested format */
1065 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1068 FIXME_(d3d_caps)("Adapter not primary display\n");
1073 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1074 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1075 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1076 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1078 /* Validate the parameters as much as possible */
1079 if (NULL == pMode ||
1080 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1081 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1082 return WINED3DERR_INVALIDCALL;
1085 if (Adapter == 0) { /* Display */
1086 #if !defined( DEBUG_SINGLE_MODE )
1090 /* Work out the current screen bpp */
1091 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1092 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1095 /* If we are filtering to a specific format, then need to skip all unrelated
1096 modes, but if mode is irrelevant, then we can use the index directly */
1097 if (Format == D3DFMT_UNKNOWN)
1103 DEVMODEW DevModeWtmp;
1106 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1110 case D3DFMT_UNKNOWN:
1113 case D3DFMT_X8R8G8B8:
1114 case D3DFMT_A8R8G8B8:
1115 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1116 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1118 case D3DFMT_X1R5G5B5:
1119 case D3DFMT_A1R5G5B5:
1121 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1124 /* Skip other modes as they do not match requested format */
1131 /* Now get the display mode via the calculated index */
1132 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1134 pMode->Width = DevModeW.dmPelsWidth;
1135 pMode->Height = DevModeW.dmPelsHeight;
1136 bpp = min(DevModeW.dmBitsPerPel, bpp);
1137 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1138 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1140 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1143 if (Format == D3DFMT_UNKNOWN)
1146 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1147 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1148 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1149 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1150 default: pMode->Format = D3DFMT_UNKNOWN;
1153 pMode->Format = Format;
1158 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1159 return WINED3DERR_INVALIDCALL;
1163 /* Return one setting of the format requested */
1164 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1166 pMode->Height = 600;
1167 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1168 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1171 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1172 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1175 FIXME_(d3d_caps)("Adapter not primary display\n");
1181 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1182 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1183 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1185 if (NULL == pMode ||
1186 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1187 return WINED3DERR_INVALIDCALL;
1190 if (Adapter == 0) { /* Display */
1194 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1195 pMode->Width = DevModeW.dmPelsWidth;
1196 pMode->Height = DevModeW.dmPelsHeight;
1197 bpp = DevModeW.dmBitsPerPel;
1198 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1199 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1201 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1205 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1206 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1207 case 24: pMode->Format = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1208 case 32: pMode->Format = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1209 default: pMode->Format = D3DFMT_UNKNOWN;
1213 FIXME_(d3d_caps)("Adapter not primary display\n");
1216 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1217 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1221 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1224 /* only works with one adapter at the moment... */
1226 /* Get the display */
1227 device_context = GetDC(0);
1228 display = get_display(device_context);
1229 ReleaseDC(0, device_context);
1233 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1234 and fields being inserted in the middle, a new structure is used in place */
1235 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1236 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1237 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1239 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1241 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1242 return WINED3DERR_INVALIDCALL;
1245 if (Adapter == 0) { /* Display - only device supported for now */
1247 BOOL isGLInfoValid = This->isGLInfoValid;
1249 /* FillGLCaps updates gl_info, but we only want to store and
1250 reuse the values once we have a context which is valid. Values from
1251 a temporary context may differ from the final ones */
1252 if (isGLInfoValid == FALSE) {
1253 WineD3D_Context *fake_ctx = NULL;
1254 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1255 /* If we don't know the device settings, go query them now */
1256 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1257 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1260 /* If it worked, return the information requested */
1261 if (isGLInfoValid) {
1262 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1263 strcpy(pIdentifier->Driver, "Display");
1264 strcpy(pIdentifier->Description, "Direct3D HAL");
1266 /* Note dx8 doesn't supply a DeviceName */
1267 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1268 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1269 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1270 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1271 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1272 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1273 *(pIdentifier->SubSysId) = 0;
1274 *(pIdentifier->Revision) = 0;
1278 /* If it failed, return dummy values from an NVidia driver */
1279 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1280 strcpy(pIdentifier->Driver, "Display");
1281 strcpy(pIdentifier->Description, "Direct3D HAL");
1282 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1283 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1284 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1285 /* 71.74 is a current Linux Nvidia driver version */
1286 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1287 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1288 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1289 *(pIdentifier->SubSysId) = 0;
1290 *(pIdentifier->Revision) = 0;
1293 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1294 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1295 *(pIdentifier->WHQLLevel) = 0;
1297 *(pIdentifier->WHQLLevel) = 1;
1301 FIXME_(d3d_caps)("Adapter not primary display\n");
1307 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1308 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1310 int rb, gb, bb, ab, type, buf_sz;
1312 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1313 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1314 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1315 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1316 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1317 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1320 case WINED3DFMT_X8R8G8B8:
1321 case WINED3DFMT_R8G8B8:
1322 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1324 case WINED3DFMT_A8R8G8B8:
1325 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1327 case WINED3DFMT_A2R10G10B10:
1328 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1330 case WINED3DFMT_X1R5G5B5:
1331 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1333 case WINED3DFMT_A1R5G5B5:
1334 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1336 case WINED3DFMT_X4R4G4B4:
1337 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1339 case WINED3DFMT_R5G6B5:
1340 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1342 case WINED3DFMT_R3G3B2:
1343 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1345 case WINED3DFMT_A8P8:
1346 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1349 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1352 ERR("unsupported format %s\n", debug_d3dformat(Format));
1356 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1358 case WINED3DFMT_X8R8G8B8:
1359 case WINED3DFMT_R8G8B8:
1360 case WINED3DFMT_A8R8G8B8:
1361 case WINED3DFMT_A2R10G10B10:
1362 case WINED3DFMT_X1R5G5B5:
1363 case WINED3DFMT_A1R5G5B5:
1364 case WINED3DFMT_R5G6B5:
1365 case WINED3DFMT_R3G3B2:
1366 case WINED3DFMT_A8P8:
1370 ERR("unsupported format %s\n", debug_d3dformat(Format));
1377 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1378 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1382 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1383 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1386 case WINED3DFMT_D16:
1387 case WINED3DFMT_D16_LOCKABLE:
1388 if (16 == db) return TRUE;
1390 case WINED3DFMT_D32:
1391 if (32 == db) return TRUE;
1393 case WINED3DFMT_D15S1:
1394 if (15 == db) return TRUE;
1396 case WINED3DFMT_D24S8:
1397 if (24 == db && 8 == sb) return TRUE;
1399 case WINED3DFMT_D24FS8:
1400 if (24 == db && 8 == sb) return TRUE;
1402 case WINED3DFMT_D24X8:
1403 if (24 == db) return TRUE;
1405 case WINED3DFMT_D24X4S4:
1406 if (24 == db && 4 == sb) return TRUE;
1408 case WINED3DFMT_D32F_LOCKABLE:
1409 if (32 == db) return TRUE;
1412 ERR("unsupported format %s\n", debug_d3dformat(Format));
1416 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1418 case WINED3DFMT_D16:
1419 case WINED3DFMT_D16_LOCKABLE:
1420 case WINED3DFMT_D32:
1421 case WINED3DFMT_D15S1:
1422 case WINED3DFMT_D24S8:
1423 case WINED3DFMT_D24FS8:
1424 case WINED3DFMT_D24X8:
1425 case WINED3DFMT_D24X4S4:
1426 case WINED3DFMT_D32F_LOCKABLE:
1429 ERR("unsupported format %s\n", debug_d3dformat(Format));
1436 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1437 WINED3DFORMAT AdapterFormat,
1438 WINED3DFORMAT RenderTargetFormat,
1439 WINED3DFORMAT DepthStencilFormat) {
1440 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1441 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1442 WineD3D_Context* ctx = NULL;
1443 GLXFBConfig* cfgs = NULL;
1447 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1449 DeviceType, debug_d3ddevicetype(DeviceType),
1450 AdapterFormat, debug_d3dformat(AdapterFormat),
1451 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1452 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1454 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1455 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1456 return WINED3DERR_INVALIDCALL;
1458 /* TODO: use the real context if it's available */
1459 ctx = WineD3D_CreateFakeGLContext();
1461 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1463 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1467 for (it = 0; it < nCfgs; ++it) {
1468 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1469 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1478 /* If there's a corrent context then we cannot create a fake one so pass everything */
1483 WineD3D_ReleaseFakeGLContext(ctx);
1485 if (hr != WINED3D_OK)
1486 TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1488 TRACE_(d3d_caps)("(%p) : Returning %lx\n", This, hr);
1492 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1493 WINED3DFORMAT SurfaceFormat,
1494 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1496 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1497 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1500 DeviceType, debug_d3ddevicetype(DeviceType),
1501 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1506 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1507 return WINED3DERR_INVALIDCALL;
1510 if (pQualityLevels != NULL) {
1511 static int s_single_shot = 0;
1512 if (!s_single_shot) {
1513 FIXME("Quality levels unsupported at present\n");
1516 *pQualityLevels = 1; /* Guess at a value! */
1519 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1520 return WINED3DERR_NOTAVAILABLE;
1523 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1524 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1526 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1527 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1530 CheckType, debug_d3ddevicetype(CheckType),
1531 DisplayFormat, debug_d3dformat(DisplayFormat),
1532 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1535 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1536 return WINED3DERR_INVALIDCALL;
1540 GLXFBConfig* cfgs = NULL;
1543 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1545 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1547 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1548 for (it = 0; it < nCfgs; ++it) {
1549 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1556 WineD3D_ReleaseFakeGLContext(ctx);
1561 return WINED3DERR_NOTAVAILABLE;
1564 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1565 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1566 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1567 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1570 DeviceType, debug_d3ddevicetype(DeviceType),
1571 AdapterFormat, debug_d3dformat(AdapterFormat),
1572 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1573 RType, debug_d3dresourcetype(RType),
1574 CheckFormat, debug_d3dformat(CheckFormat));
1576 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1577 return WINED3DERR_INVALIDCALL;
1580 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1581 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1582 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1583 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1584 TRACE_(d3d_caps)("[FAILED]\n");
1585 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1588 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1589 switch (CheckFormat) {
1590 case WINED3DFMT_D16_LOCKABLE:
1591 case WINED3DFMT_D32:
1592 case WINED3DFMT_D15S1:
1593 case WINED3DFMT_D24S8:
1594 case WINED3DFMT_D24X8:
1595 case WINED3DFMT_D24X4S4:
1596 case WINED3DFMT_D16:
1597 case WINED3DFMT_L16:
1598 case WINED3DFMT_D32F_LOCKABLE:
1599 case WINED3DFMT_D24FS8:
1600 TRACE_(d3d_caps)("[OK]\n");
1603 TRACE_(d3d_caps)("[FAILED]\n");
1604 return WINED3DERR_NOTAVAILABLE;
1606 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1607 switch (CheckFormat) {
1608 case WINED3DFMT_R8G8B8:
1609 case WINED3DFMT_A8R8G8B8:
1610 case WINED3DFMT_X8R8G8B8:
1611 case WINED3DFMT_R5G6B5:
1612 case WINED3DFMT_X1R5G5B5:
1613 case WINED3DFMT_A1R5G5B5:
1614 case WINED3DFMT_A4R4G4B4:
1615 case WINED3DFMT_R3G3B2:
1616 case WINED3DFMT_X4R4G4B4:
1617 case WINED3DFMT_A8B8G8R8:
1618 case WINED3DFMT_X8B8G8R8:
1620 TRACE_(d3d_caps)("[OK]\n");
1623 TRACE_(d3d_caps)("[FAILED]\n");
1624 return WINED3DERR_NOTAVAILABLE;
1628 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1629 switch (CheckFormat) {
1635 TRACE_(d3d_caps)("[OK]\n");
1638 break; /* Avoid compiler warnings */
1642 /* This format is nothing special and it is supported perfectly.
1643 * However, ati and nvidia driver on windows do not mark this format
1644 * supported(tested with the dxCapsViewer) and pretending to
1645 * support this format uncovers a bug in Battlefield 1942(fonts are missing)
1646 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1647 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1649 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1650 TRACE_(d3d_caps)("[FAILED]\n");
1651 return WINED3DERR_NOTAVAILABLE;
1654 switch (CheckFormat) {
1657 * supported: RGB(A) formats
1659 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1660 case WINED3DFMT_A8R8G8B8:
1661 case WINED3DFMT_X8R8G8B8:
1662 case WINED3DFMT_R5G6B5:
1663 case WINED3DFMT_X1R5G5B5:
1664 case WINED3DFMT_A1R5G5B5:
1665 case WINED3DFMT_A4R4G4B4:
1666 case WINED3DFMT_R3G3B2:
1668 case WINED3DFMT_A8R3G3B2:
1669 case WINED3DFMT_X4R4G4B4:
1670 case WINED3DFMT_A8B8G8R8:
1671 case WINED3DFMT_X8B8G8R8:
1672 case WINED3DFMT_A2R10G10B10:
1673 case WINED3DFMT_A2B10G10R10:
1674 TRACE_(d3d_caps)("[OK]\n");
1678 * supported: Palettized
1681 TRACE_(d3d_caps)("[OK]\n");
1685 * Supported: (Alpha)-Luminance
1688 case WINED3DFMT_A8L8:
1689 case WINED3DFMT_A4L4:
1690 TRACE_(d3d_caps)("[OK]\n");
1694 * Not supported for now: Bump mapping formats
1695 * Enable some because games often fail when they are not available
1696 * and are still playable even without bump mapping
1698 case WINED3DFMT_V8U8:
1699 case WINED3DFMT_V16U16:
1700 case WINED3DFMT_L6V5U5:
1701 case WINED3DFMT_X8L8V8U8:
1702 case WINED3DFMT_Q8W8V8U8:
1703 case WINED3DFMT_W11V11U10:
1704 case WINED3DFMT_A2W10V10U10:
1705 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1709 * DXTN Formats: Handled above
1718 * Odd formats - not supported
1720 case WINED3DFMT_VERTEXDATA:
1721 case WINED3DFMT_INDEX16:
1722 case WINED3DFMT_INDEX32:
1723 case WINED3DFMT_Q16W16V16U16:
1724 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1725 return WINED3DERR_NOTAVAILABLE;
1728 * Float formats: Not supported right now
1730 case WINED3DFMT_R16F:
1731 case WINED3DFMT_G16R16F:
1732 case WINED3DFMT_A16B16G16R16F:
1733 case WINED3DFMT_R32F:
1734 case WINED3DFMT_G32R32F:
1735 case WINED3DFMT_A32B32G32R32F:
1736 case WINED3DFMT_CxV8U8:
1737 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1738 return WINED3DERR_NOTAVAILABLE;
1741 case WINED3DFMT_G16R16:
1742 case WINED3DFMT_A16B16G16R16:
1743 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1744 return WINED3DERR_NOTAVAILABLE;
1750 TRACE_(d3d_caps)("[FAILED]\n");
1751 return WINED3DERR_NOTAVAILABLE;
1754 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1755 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1756 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1758 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1761 DeviceType, debug_d3ddevicetype(DeviceType),
1762 SourceFormat, debug_d3dformat(SourceFormat),
1763 TargetFormat, debug_d3dformat(TargetFormat));
1767 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1768 subset of a D3DCAPS9 structure. However, it has to come via a void *
1769 as the d3d8 interface cannot import the d3d9 header */
1770 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1772 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1774 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1776 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1777 return WINED3DERR_INVALIDCALL;
1780 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1782 /* If we don't know the device settings, go query them now */
1783 if (This->isGLInfoValid == FALSE) {
1784 /* use the desktop window to fill gl caps */
1785 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1787 /* We are running off a real context, save the values */
1788 if (rc) This->isGLInfoValid = TRUE;
1790 select_shader_mode(&This->gl_info, DeviceType,
1791 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1792 select_shader_max_constants(&This->gl_info);
1794 /* ------------------------------------------------
1795 The following fields apply to both d3d8 and d3d9
1796 ------------------------------------------------ */
1797 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1798 *pCaps->AdapterOrdinal = Adapter;
1801 *pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
1802 *pCaps->Caps3 = WINED3DDEVCAPS_HWTRANSFORMANDLIGHT;
1803 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1805 *pCaps->CursorCaps = 0;
1808 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1809 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1810 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1811 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1812 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1813 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1814 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1815 WINED3DDEVCAPS_PUREDEVICE |
1816 WINED3DDEVCAPS_HWRASTERIZATION |
1817 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1818 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1819 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1820 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1821 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1823 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1824 D3DPMISCCAPS_CULLCCW |
1825 D3DPMISCCAPS_CULLCW |
1826 D3DPMISCCAPS_COLORWRITEENABLE |
1827 D3DPMISCCAPS_CLIPTLVERTS |
1828 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1829 D3DPMISCCAPS_MASKZ |
1830 D3DPMISCCAPS_BLENDOP;
1832 D3DPMISCCAPS_NULLREFERENCE
1833 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1834 D3DPMISCCAPS_FOGANDSPECULARALPHA
1835 D3DPMISCCAPS_SEPARATEALPHABLEND
1836 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1837 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1838 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1840 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1842 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1843 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1844 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1845 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1848 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1849 WINED3DPRASTERCAPS_PAT |
1850 WINED3DPRASTERCAPS_WFOG |
1851 WINED3DPRASTERCAPS_ZFOG |
1852 WINED3DPRASTERCAPS_FOGVERTEX |
1853 WINED3DPRASTERCAPS_FOGTABLE |
1854 WINED3DPRASTERCAPS_FOGRANGE |
1855 WINED3DPRASTERCAPS_STIPPLE |
1856 WINED3DPRASTERCAPS_SUBPIXEL |
1857 WINED3DPRASTERCAPS_ZTEST |
1858 WINED3DPRASTERCAPS_SCISSORTEST |
1859 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1860 WINED3DPRASTERCAPS_DEPTHBIAS;
1862 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1863 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1864 WINED3DPRASTERCAPS_ZBIAS |
1865 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1868 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1869 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1870 WINED3DPRASTERCAPS_ANTIALIASEDGES
1871 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1872 WINED3DPRASTERCAPS_WBUFFER */
1874 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1876 D3DPCMPCAPS_GREATER |
1877 D3DPCMPCAPS_GREATEREQUAL |
1879 D3DPCMPCAPS_LESSEQUAL |
1881 D3DPCMPCAPS_NOTEQUAL;
1883 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1884 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1885 D3DPBLENDCAPS_BOTHSRCALPHA |
1886 D3DPBLENDCAPS_DESTALPHA |
1887 D3DPBLENDCAPS_DESTCOLOR |
1888 D3DPBLENDCAPS_INVDESTALPHA |
1889 D3DPBLENDCAPS_INVDESTCOLOR |
1890 D3DPBLENDCAPS_INVSRCALPHA |
1891 D3DPBLENDCAPS_INVSRCCOLOR |
1893 D3DPBLENDCAPS_SRCALPHA |
1894 D3DPBLENDCAPS_SRCALPHASAT |
1895 D3DPBLENDCAPS_SRCCOLOR |
1898 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1899 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1900 D3DPBLENDCAPS_BOTHSRCALPHA |
1901 D3DPBLENDCAPS_DESTALPHA |
1902 D3DPBLENDCAPS_DESTCOLOR |
1903 D3DPBLENDCAPS_INVDESTALPHA |
1904 D3DPBLENDCAPS_INVDESTCOLOR |
1905 D3DPBLENDCAPS_INVSRCALPHA |
1906 D3DPBLENDCAPS_INVSRCCOLOR |
1908 D3DPBLENDCAPS_SRCALPHA |
1909 D3DPBLENDCAPS_SRCALPHASAT |
1910 D3DPBLENDCAPS_SRCCOLOR |
1913 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1915 D3DPCMPCAPS_GREATER |
1916 D3DPCMPCAPS_GREATEREQUAL |
1918 D3DPCMPCAPS_LESSEQUAL |
1920 D3DPCMPCAPS_NOTEQUAL;
1922 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1923 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1924 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1925 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1926 WINED3DPSHADECAPS_COLORFLATRGB |
1927 WINED3DPSHADECAPS_FOGFLAT |
1928 WINED3DPSHADECAPS_FOGGOURAUD |
1929 WINED3DPSHADECAPS_SPECULARFLATRGB;
1931 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1932 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1933 WINED3DPTEXTURECAPS_BORDER |
1934 WINED3DPTEXTURECAPS_MIPMAP |
1935 WINED3DPTEXTURECAPS_PROJECTED |
1936 WINED3DPTEXTURECAPS_PERSPECTIVE |
1937 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1939 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1940 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1941 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1942 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1945 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1946 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1947 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1948 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1952 *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1953 WINED3DPTFILTERCAPS_MAGFPOINT |
1954 WINED3DPTFILTERCAPS_MINFLINEAR |
1955 WINED3DPTFILTERCAPS_MINFPOINT |
1956 WINED3DPTFILTERCAPS_MIPFLINEAR |
1957 WINED3DPTFILTERCAPS_MIPFPOINT |
1958 WINED3DPTFILTERCAPS_LINEAR |
1959 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1960 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1961 WINED3DPTFILTERCAPS_MIPLINEAR |
1962 WINED3DPTFILTERCAPS_MIPNEAREST |
1963 WINED3DPTFILTERCAPS_NEAREST;
1965 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1966 *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1967 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1970 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1971 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1972 WINED3DPTFILTERCAPS_MAGFPOINT |
1973 WINED3DPTFILTERCAPS_MINFLINEAR |
1974 WINED3DPTFILTERCAPS_MINFPOINT |
1975 WINED3DPTFILTERCAPS_MIPFLINEAR |
1976 WINED3DPTFILTERCAPS_MIPFPOINT |
1977 WINED3DPTFILTERCAPS_LINEAR |
1978 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1979 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1980 WINED3DPTFILTERCAPS_MIPLINEAR |
1981 WINED3DPTFILTERCAPS_MIPNEAREST |
1982 WINED3DPTFILTERCAPS_NEAREST;
1984 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1985 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1986 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1989 *pCaps->CubeTextureFilterCaps = 0;
1991 if (GL_SUPPORT(EXT_TEXTURE3D)) {
1992 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1993 WINED3DPTFILTERCAPS_MAGFPOINT |
1994 WINED3DPTFILTERCAPS_MINFLINEAR |
1995 WINED3DPTFILTERCAPS_MINFPOINT |
1996 WINED3DPTFILTERCAPS_MIPFLINEAR |
1997 WINED3DPTFILTERCAPS_MIPFPOINT |
1998 WINED3DPTFILTERCAPS_LINEAR |
1999 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2000 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2001 WINED3DPTFILTERCAPS_MIPLINEAR |
2002 WINED3DPTFILTERCAPS_MIPNEAREST |
2003 WINED3DPTFILTERCAPS_NEAREST;
2005 *pCaps->VolumeTextureFilterCaps = 0;
2007 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2008 D3DPTADDRESSCAPS_CLAMP |
2009 D3DPTADDRESSCAPS_WRAP;
2011 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2012 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2014 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2015 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2017 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2018 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2021 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2022 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2023 D3DPTADDRESSCAPS_CLAMP |
2024 D3DPTADDRESSCAPS_WRAP;
2025 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2026 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2028 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2029 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2031 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2032 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2035 *pCaps->VolumeTextureAddressCaps = 0;
2037 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2041 D3DLINECAPS_ALPHACMP
2044 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2045 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2047 if(GL_SUPPORT(EXT_TEXTURE3D))
2048 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2050 *pCaps->MaxVolumeExtent = 0;
2052 *pCaps->MaxTextureRepeat = 32768;
2053 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2054 *pCaps->MaxVertexW = 1.0;
2056 *pCaps->GuardBandLeft = 0;
2057 *pCaps->GuardBandTop = 0;
2058 *pCaps->GuardBandRight = 0;
2059 *pCaps->GuardBandBottom = 0;
2061 *pCaps->ExtentsAdjust = 0;
2063 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2064 D3DSTENCILCAPS_INCRSAT |
2065 D3DSTENCILCAPS_INVERT |
2066 D3DSTENCILCAPS_KEEP |
2067 D3DSTENCILCAPS_REPLACE |
2068 D3DSTENCILCAPS_ZERO;
2069 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2070 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2071 D3DSTENCILCAPS_INCR;
2073 if ( This->dxVersion > 8 &&
2074 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2075 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2076 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2079 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2081 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2082 D3DTEXOPCAPS_ADDSIGNED |
2083 D3DTEXOPCAPS_ADDSIGNED2X |
2084 D3DTEXOPCAPS_MODULATE |
2085 D3DTEXOPCAPS_MODULATE2X |
2086 D3DTEXOPCAPS_MODULATE4X |
2087 D3DTEXOPCAPS_SELECTARG1 |
2088 D3DTEXOPCAPS_SELECTARG2 |
2089 D3DTEXOPCAPS_DISABLE;
2091 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2092 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2093 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2094 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2095 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2096 D3DTEXOPCAPS_BLENDFACTORALPHA |
2097 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2099 D3DTEXOPCAPS_SUBTRACT;
2101 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2102 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2103 D3DTEXOPCAPS_MULTIPLYADD |
2104 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2105 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2106 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2108 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2109 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2111 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2112 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2113 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2118 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2120 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2121 D3DTEXOPCAPS_PREMODULATE */
2124 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2125 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2126 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2127 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2131 #if 0 /* TODO: Blends support in drawprim */
2132 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2134 *pCaps->MaxVertexBlendMatrices = 0;
2136 *pCaps->MaxVertexBlendMatrixIndex = 1;
2138 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2139 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2142 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2143 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2144 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2145 WINED3DVTXPCAPS_LOCALVIEWER |
2146 WINED3DVTXPCAPS_VERTEXFOG |
2147 WINED3DVTXPCAPS_TEXGEN;
2149 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2151 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2152 *pCaps->MaxVertexIndex = 0xFFFFF;
2153 *pCaps->MaxStreams = MAX_STREAMS;
2154 *pCaps->MaxStreamStride = 1024;
2156 /* FIXME: the shader mode should be per adapter */
2157 if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
2158 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2159 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2160 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2161 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2162 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2163 *pCaps->VertexShaderVersion = D3DVS_VERSION(2,0);
2165 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2166 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2167 } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
2168 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
2169 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2170 } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
2171 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2172 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2174 *pCaps->VertexShaderVersion = 0;
2175 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2178 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2180 /* FIXME: the shader mode should be per adapter */
2181 if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
2182 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2183 in case of GeforceFX cards. */
2184 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2185 *pCaps->PixelShaderVersion = D3DPS_VERSION(2,0);
2187 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2188 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2189 *pCaps->PixelShader1xMaxValue = 1.0;
2190 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2191 } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
2192 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
2193 *pCaps->PixelShader1xMaxValue = 1.0;
2194 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2195 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2196 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2197 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2198 *pCaps->PixelShader1xMaxValue = 1.0;
2199 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2201 *pCaps->PixelShaderVersion = 0;
2202 *pCaps->PixelShader1xMaxValue = 0.0;
2203 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2206 /* ------------------------------------------------
2207 The following fields apply to d3d9 only
2208 ------------------------------------------------ */
2209 if (This->dxVersion > 8) {
2210 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2211 *pCaps->DevCaps2 = 0;
2212 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs atleast D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2213 *pCaps->MaxNpatchTessellationLevel = 0;
2214 *pCaps->MasterAdapterOrdinal = 0;
2215 *pCaps->AdapterOrdinalInGroup = 0;
2216 *pCaps->NumberOfAdaptersInGroup = 1;
2218 if(*pCaps->VertexShaderVersion >= D3DVS_VERSION(2,0)) {
2219 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2220 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2221 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2222 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2223 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2227 D3DDTCAPS_FLOAT16_2 |
2228 D3DDTCAPS_FLOAT16_4;
2231 *pCaps->DeclTypes = 0;
2233 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2234 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2235 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2238 *pCaps->NumSimultaneousRTs = 1;
2240 *pCaps->StretchRectFilterCaps = 0;
2241 *pCaps->VertexTextureFilterCaps = 0;
2243 if(*pCaps->VertexShaderVersion == D3DVS_VERSION(3,0)) {
2244 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2245 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2246 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2247 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2248 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2249 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2251 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs atleast 65535, some cards even use 2^32-1 */
2252 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2253 } else if(*pCaps->VertexShaderVersion == D3DVS_VERSION(2,0)) {
2254 *pCaps->VS20Caps.Caps = 0;
2255 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2256 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2257 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2259 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2260 *pCaps->MaxVertexShader30InstructionSlots = 0;
2261 } else { /* VS 1.x */
2262 *pCaps->VS20Caps.Caps = 0;
2263 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2264 *pCaps->VS20Caps.NumTemps = 0;
2265 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2267 *pCaps->MaxVShaderInstructionsExecuted = 0;
2268 *pCaps->MaxVertexShader30InstructionSlots = 0;
2271 if(*pCaps->PixelShaderVersion == D3DPS_VERSION(3,0)) {
2272 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2273 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2275 /* 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 */
2276 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2277 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2278 D3DPS20CAPS_PREDICATION |
2279 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2280 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2281 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2282 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2283 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2284 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2286 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2287 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2288 } else if(*pCaps->PixelShaderVersion == D3DPS_VERSION(2,0)) {
2289 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2290 *pCaps->PS20Caps.Caps = 0;
2291 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2292 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2293 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2294 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2296 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2297 *pCaps->MaxPixelShader30InstructionSlots = 0;
2298 } else { /* PS 1.x */
2299 *pCaps->PS20Caps.Caps = 0;
2300 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2301 *pCaps->PS20Caps.NumTemps = 0;
2302 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2303 *pCaps->PS20Caps.NumInstructionSlots = 0;
2305 *pCaps->MaxPShaderInstructionsExecuted = 0;
2306 *pCaps->MaxPixelShader30InstructionSlots = 0;
2314 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2315 and fields being inserted in the middle, a new structure is used in place */
2316 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2317 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2320 IWineD3DDeviceImpl *object = NULL;
2321 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2323 HRESULT temp_result;
2325 /* Validate the adapter number */
2326 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2327 return WINED3DERR_INVALIDCALL;
2330 /* Create a WineD3DDevice object */
2331 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2332 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2333 TRACE("Created WineD3DDevice object @ %p\n", object);
2334 if (NULL == object) {
2335 return WINED3DERR_OUTOFVIDEOMEMORY;
2338 /* Set up initial COM information */
2339 object->lpVtbl = &IWineD3DDevice_Vtbl;
2341 object->wineD3D = iface;
2342 IWineD3D_AddRef(object->wineD3D);
2343 object->parent = parent;
2345 /* Set the state up as invalid until the device is fully created */
2346 object->state = WINED3DERR_DRIVERINTERNALERROR;
2348 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This, Adapter, DeviceType,
2349 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2351 /* Save the creation parameters */
2352 object->createParms.AdapterOrdinal = Adapter;
2353 object->createParms.DeviceType = DeviceType;
2354 object->createParms.hFocusWindow = hFocusWindow;
2355 object->createParms.BehaviorFlags = BehaviourFlags;
2357 /* Initialize other useful values */
2358 object->adapterNo = Adapter;
2359 object->devType = DeviceType;
2361 TRACE("(%p) : Creating stateblock\n", This);
2362 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2363 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2365 (IWineD3DStateBlock **)&object->stateBlock,
2366 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2367 WARN("Failed to create stateblock\n");
2368 goto create_device_error;
2370 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2371 object->updateStateBlock = object->stateBlock;
2372 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2373 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2375 /* Setup some defaults for creating the implicit swapchain */
2377 /* FIXME: both of those should be made per adapter */
2378 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2380 select_shader_mode(&This->gl_info, DeviceType,
2381 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
2382 select_shader_max_constants(&This->gl_info);
2384 temp_result = allocate_shader_constants(object->updateStateBlock);
2385 if (WINED3D_OK != temp_result)
2388 /* set the state of the device to valid */
2389 object->state = WINED3D_OK;
2391 /* Get the initial screen setup for ddraw */
2392 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2393 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2394 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2395 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2399 create_device_error:
2401 /* Set the device state to error */
2402 object->state = WINED3DERR_DRIVERINTERNALERROR;
2404 if (object->updateStateBlock != NULL) {
2405 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2406 object->updateStateBlock = NULL;
2408 if (object->stateBlock != NULL) {
2409 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2410 object->stateBlock = NULL;
2412 if (object->renderTarget != NULL) {
2413 IWineD3DSurface_Release(object->renderTarget);
2414 object->renderTarget = NULL;
2416 if (object->stencilBufferTarget != NULL) {
2417 IWineD3DSurface_Release(object->stencilBufferTarget);
2418 object->stencilBufferTarget = NULL;
2420 if (object->stencilBufferTarget != NULL) {
2421 IWineD3DSurface_Release(object->stencilBufferTarget);
2422 object->stencilBufferTarget = NULL;
2424 HeapFree(GetProcessHeap(), 0, object);
2425 *ppReturnedDeviceInterface = NULL;
2426 return WINED3DERR_INVALIDCALL;
2430 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2431 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2432 IUnknown_AddRef(This->parent);
2433 *pParent = This->parent;
2437 /**********************************************************
2438 * IWineD3D VTbl follows
2439 **********************************************************/
2441 const IWineD3DVtbl IWineD3D_Vtbl =
2444 IWineD3DImpl_QueryInterface,
2445 IWineD3DImpl_AddRef,
2446 IWineD3DImpl_Release,
2448 IWineD3DImpl_GetParent,
2449 IWineD3DImpl_GetAdapterCount,
2450 IWineD3DImpl_RegisterSoftwareDevice,
2451 IWineD3DImpl_GetAdapterMonitor,
2452 IWineD3DImpl_GetAdapterModeCount,
2453 IWineD3DImpl_EnumAdapterModes,
2454 IWineD3DImpl_GetAdapterDisplayMode,
2455 IWineD3DImpl_GetAdapterIdentifier,
2456 IWineD3DImpl_CheckDeviceMultiSampleType,
2457 IWineD3DImpl_CheckDepthStencilMatch,
2458 IWineD3DImpl_CheckDeviceType,
2459 IWineD3DImpl_CheckDeviceFormat,
2460 IWineD3DImpl_CheckDeviceFormatConversion,
2461 IWineD3DImpl_GetDeviceCaps,
2462 IWineD3DImpl_CreateDevice