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_float") == 0) {
580 TRACE_(d3d_caps)(" FOUND: ARB Float texture support\n");
581 gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
582 } else if (strcmp(ThisExtn, "GL_ARB_half_float_pixel") == 0) {
583 TRACE_(d3d_caps)(" FOUND: ARB Half-float pixel support\n");
584 gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
585 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
586 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
587 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
588 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
589 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
590 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
591 } else if (strcmp(ThisExtn, "GLX_ARB_multisample") == 0) {
592 TRACE_(d3d_caps)(" FOUND: ARB multisample support\n");
593 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
594 } else if (strcmp(ThisExtn, "GL_ARB_pixel_buffer_object") == 0) {
595 TRACE_(d3d_caps)(" FOUND: ARB Pixel Buffer support\n");
596 gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = TRUE;
597 } else if (strcmp(ThisExtn, "GL_ARB_point_sprite") == 0) {
598 TRACE_(d3d_caps)(" FOUND: ARB point sprite support\n");
599 gl_info->supported[ARB_POINT_SPRITE] = TRUE;
600 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
601 gl_info->vs_arb_version = VS_VERSION_11;
602 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
603 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
604 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &gl_max));
605 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max);
606 gl_info->vs_arb_constantsF = gl_max;
607 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &gl_max));
608 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max);
609 gl_info->vs_arb_max_temps = gl_max;
610 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &gl_max));
611 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max);
612 gl_info->vs_arb_max_instructions = gl_max;
613 } else if (strcmp(ThisExtn, "GL_ARB_vertex_shader") == 0) {
614 gl_info->supported[ARB_VERTEX_SHADER] = TRUE;
615 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &gl_max);
616 TRACE_(d3d_caps)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max);
617 gl_info->vs_glsl_constantsF = gl_max;
618 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
619 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
620 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max);
621 gl_info->max_blends = gl_max;
622 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
623 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
624 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
625 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
626 } else if (strcmp(ThisExtn, "GL_ARB_occlusion_query") == 0) {
627 TRACE_(d3d_caps)(" FOUND: ARB Occlusion Query support\n");
628 gl_info->supported[ARB_OCCLUSION_QUERY] = TRUE;
629 } else if (strcmp(ThisExtn, "GL_ARB_point_parameters") == 0) {
630 TRACE_(d3d_caps)(" FOUND: ARB Point parameters support\n");
631 gl_info->supported[ARB_POINT_PARAMETERS] = TRUE;
635 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
636 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
637 gl_info->supported[EXT_FOG_COORD] = TRUE;
638 } else if (strcmp(ThisExtn, "GL_EXT_framebuffer_object") == 0) {
639 TRACE_(d3d_caps)(" FOUND: EXT Frame Buffer Object support\n");
640 gl_info->supported[EXT_FRAMEBUFFER_OBJECT] = TRUE;
641 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
642 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
643 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
644 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
645 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
646 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
647 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
648 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
649 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
650 } else if (strcmp(ThisExtn, "GL_EXT_stencil_two_side") == 0) {
651 TRACE_(d3d_caps)(" FOUND: EXT Stencil two side support\n");
652 gl_info->supported[EXT_STENCIL_TWO_SIDE] = TRUE;
653 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
654 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
655 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
656 } else if (strcmp(ThisExtn, "GL_EXT_texture3D") == 0) {
657 TRACE_(d3d_caps)(" FOUND: EXT_texture3D support\n");
658 gl_info->supported[EXT_TEXTURE3D] = TRUE;
659 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT, &gl_max);
660 TRACE_(d3d_caps)("Max texture3D size: %d\n", gl_max);
661 gl_info->max_texture3d_size = gl_max;
662 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
663 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
664 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
665 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
666 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
667 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
668 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
669 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
670 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
671 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
672 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
673 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
674 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
675 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
676 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
677 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max);
678 gl_info->max_anisotropy = gl_max;
679 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
680 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
681 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
682 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
683 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
684 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
685 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
686 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
687 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
692 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
693 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
694 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
695 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
696 gl_info->ps_nv_version = (strcmp(ThisExtn, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30 : PS_VERSION_20;
697 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
698 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
699 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &gl_max);
700 gl_info->max_texture_stages = min(MAX_TEXTURES, gl_max);
701 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max);
702 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
703 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
704 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
705 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
706 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
707 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
708 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
709 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
710 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
711 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
712 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
713 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
714 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
715 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
716 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
717 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
718 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
719 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
720 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
721 } else if (strcmp(ThisExtn, "GL_NV_occlusion_query") == 0) {
722 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
723 gl_info->supported[NV_OCCLUSION_QUERY] = TRUE;
724 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
725 if(strcmp(ThisExtn, "GL_NV_vertex_program3") == 0)
726 gl_info->vs_nv_version = VS_VERSION_30;
727 else if(strcmp(ThisExtn, "GL_NV_vertex_program2") == 0)
728 gl_info->vs_nv_version = VS_VERSION_20;
729 else if(strcmp(ThisExtn, "GL_NV_vertex_program1_1") == 0)
730 gl_info->vs_nv_version = VS_VERSION_11;
732 gl_info->vs_nv_version = VS_VERSION_10;
733 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
734 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
740 } else if (strcmp(ThisExtn, "GL_ATI_separate_stencil") == 0) {
741 TRACE_(d3d_caps)(" FOUND: ATI Separate stencil support\n");
742 gl_info->supported[ATI_SEPARATE_STENCIL] = TRUE;
743 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
744 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
745 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
746 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
747 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
748 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
749 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
750 gl_info->vs_ati_version = VS_VERSION_11;
751 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
752 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
756 if (*GL_Extensions == ' ') GL_Extensions++;
759 checkGLcall("extension detection\n");
761 gl_info->max_sampler_stages = max(gl_info->max_samplers, gl_info->max_texture_stages);
763 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
764 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
765 * in case of the latest videocards in the number of pixel/vertex pipelines.
767 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
768 * rendering. Various games use this information to get a rough estimation of the features of the card
769 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
770 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
771 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
774 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
775 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
776 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
777 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
778 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
779 * is used for rendering which doesn't allways the case). This would work but it is not very portable. Second
780 * it would not work well in lets say a remote X situation in which the amount of 3d features which can be used
783 * As said most games only use the PCI id to get an indication of the capabilities of the card.
784 * It doesn't really matter if the given id is the correct one if we return the id of a card with
785 * similar 3d features.
787 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
788 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
789 * is atleast a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
790 * won't pass we return a default card. This way is better than maintaining a full card database as even
791 * without a full database we can return a card with similar features. Second the size of the database
792 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
793 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
794 * to distinguishes between different models from that family.
796 switch (gl_info->gl_vendor) {
798 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two typs have more
799 * shader capabilities, so we use the shader capabilities to distinct between FX and 6xxx/7xxx.
801 if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
802 if (strstr(gl_info->gl_renderer, "7800") ||
803 strstr(gl_info->gl_renderer, "7900") ||
804 strstr(gl_info->gl_renderer, "7950") ||
805 strstr(gl_info->gl_renderer, "Quadro FX 4") ||
806 strstr(gl_info->gl_renderer, "Quadro FX 5"))
807 gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
808 else if(strstr(gl_info->gl_renderer, "6800") ||
809 strstr(gl_info->gl_renderer, "7600"))
810 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
811 else if(strstr(gl_info->gl_renderer, "6600") ||
812 strstr(gl_info->gl_renderer, "6610") ||
813 strstr(gl_info->gl_renderer, "6700"))
814 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6600GT;
816 gl_info->gl_card = CARD_NVIDIA_GEFORCE_6200; /* Geforce 6100/6150/6200/7300/7400 */
817 } else if(WINE_D3D9_CAPABLE(gl_info)) {
818 if (strstr(gl_info->gl_renderer, "5800") ||
819 strstr(gl_info->gl_renderer, "5900") ||
820 strstr(gl_info->gl_renderer, "5950") ||
821 strstr(gl_info->gl_renderer, "Quadro FX"))
822 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5800;
823 else if(strstr(gl_info->gl_renderer, "5600") ||
824 strstr(gl_info->gl_renderer, "5650") ||
825 strstr(gl_info->gl_renderer, "5700") ||
826 strstr(gl_info->gl_renderer, "5750"))
827 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
829 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5200; /* GeforceFX 5100/5200/5250/5300/5500 */
830 } else if(WINE_D3D8_CAPABLE(gl_info)) {
831 if (strstr(gl_info->gl_renderer, "GeForce4 Ti") || strstr(gl_info->gl_renderer, "Quadro4"))
832 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4200; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
834 gl_info->gl_card = CARD_NVIDIA_GEFORCE3; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
835 } else if(WINE_D3D7_CAPABLE(gl_info)) {
836 if (strstr(gl_info->gl_renderer, "GeForce4 MX"))
837 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_MX; /* MX420/MX440/MX460/MX4000 */
838 else if(strstr(gl_info->gl_renderer, "GeForce2 MX") || strstr(gl_info->gl_renderer, "Quadro2 MXR"))
839 gl_info->gl_card = CARD_NVIDIA_GEFORCE2_MX; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
840 else if(strstr(gl_info->gl_renderer, "GeForce2") || strstr(gl_info->gl_renderer, "Quadro2"))
841 gl_info->gl_card = CARD_NVIDIA_GEFORCE2; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
843 gl_info->gl_card = CARD_NVIDIA_GEFORCE; /* Geforce 256/DDR, Quadro */
845 if (strstr(gl_info->gl_renderer, "TNT2"))
846 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT2; /* Riva TNT2 standard/M64/Pro/Ultra */
848 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT; /* Riva TNT, Vanta */
852 if(WINE_D3D9_CAPABLE(gl_info)) {
854 if (strstr(gl_info->gl_renderer, "X1600") ||
855 strstr(gl_info->gl_renderer, "X1800") ||
856 strstr(gl_info->gl_renderer, "X1900") ||
857 strstr(gl_info->gl_renderer, "X1950"))
858 gl_info->gl_card = CARD_ATI_RADEON_X1600;
859 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
860 else if(strstr(gl_info->gl_renderer, "X700") ||
861 strstr(gl_info->gl_renderer, "X800") ||
862 strstr(gl_info->gl_renderer, "X850") ||
863 strstr(gl_info->gl_renderer, "X1300") ||
864 strstr(gl_info->gl_renderer, "X1400"))
865 gl_info->gl_card = CARD_ATI_RADEON_X700;
868 gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
869 } else if(WINE_D3D8_CAPABLE(gl_info)) {
870 gl_info->gl_card = CARD_ATI_RADEON_8500; /* Radeon 8500/9000/9100/9200/9300 */
871 } else if(WINE_D3D7_CAPABLE(gl_info)) {
872 gl_info->gl_card = CARD_ATI_RADEON_7200; /* Radeon 7000/7100/7200/7500 */
874 gl_info->gl_card = CARD_ATI_RAGE_128PRO;
877 if (strstr(gl_info->gl_renderer, "915GM")) {
878 gl_info->gl_card = CARD_INTEL_I915GM;
879 } else if (strstr(gl_info->gl_renderer, "915G")) {
880 gl_info->gl_card = CARD_INTEL_I915G;
881 } else if (strstr(gl_info->gl_renderer, "865G")) {
882 gl_info->gl_card = CARD_INTEL_I865G;
883 } else if (strstr(gl_info->gl_renderer, "855G")) {
884 gl_info->gl_card = CARD_INTEL_I855G;
885 } else if (strstr(gl_info->gl_renderer, "830G")) {
886 gl_info->gl_card = CARD_INTEL_I830G;
888 gl_info->gl_card = CARD_INTEL_I915G;
894 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
895 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
896 * them a good generic choice.
898 gl_info->gl_vendor = VENDOR_NVIDIA;
899 if(WINE_D3D9_CAPABLE(gl_info))
900 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5600;
901 else if(WINE_D3D8_CAPABLE(gl_info))
902 gl_info->gl_card = CARD_NVIDIA_GEFORCE3;
903 else if(WINE_D3D7_CAPABLE(gl_info))
904 gl_info->gl_card = CARD_NVIDIA_GEFORCE;
905 else if(WINE_D3D6_CAPABLE(gl_info))
906 gl_info->gl_card = CARD_NVIDIA_RIVA_TNT;
908 gl_info->gl_card = CARD_NVIDIA_RIVA_128;
910 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
912 /* Load all the lookup tables
913 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
914 minLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_WRAP;
915 maxLookup[WINELOOKUP_WARPPARAM] = D3DTADDRESS_MIRRORONCE;
917 minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
918 maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
921 for (i = 0; i < MAX_LOOKUPS; i++) {
922 stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
925 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_WRAP - minLookup[WINELOOKUP_WARPPARAM]] = GL_REPEAT;
926 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_CLAMP - minLookup[WINELOOKUP_WARPPARAM]] = GL_CLAMP_TO_EDGE;
927 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
928 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
929 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_BORDER - minLookup[WINELOOKUP_WARPPARAM]] =
930 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] ? GL_CLAMP_TO_BORDER_ARB : GL_REPEAT;
931 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRROR - minLookup[WINELOOKUP_WARPPARAM]] =
932 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] ? GL_MIRRORED_REPEAT_ARB : GL_REPEAT;
933 stateLookup[WINELOOKUP_WARPPARAM][D3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
934 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
936 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
937 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
938 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
939 stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
940 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
943 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
944 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
945 minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
946 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
947 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
948 minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
949 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
950 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
951 minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
952 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
953 GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
954 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
955 minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
957 /* TODO: config lookups */
959 if (display != NULL) {
960 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
961 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
963 if (NULL == GLX_Extensions) {
964 ERR(" GLX_Extensions returns NULL\n");
966 while (*GLX_Extensions != 0x00) {
967 const char *Start = GLX_Extensions;
970 memset(ThisExtn, 0x00, sizeof(ThisExtn));
971 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
974 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
975 TRACE_(d3d_caps)("- %s\n", ThisExtn);
976 if (*GLX_Extensions == ' ') GLX_Extensions++;
981 /* If we created a dummy context, throw it away */
982 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
984 /* Only save the values obtained when a display is provided */
985 if (fake_ctx == NULL) {
992 /**********************************************************
993 * IWineD3D implementation follows
994 **********************************************************/
996 static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
997 IWineD3DImpl *This = (IWineD3DImpl *)iface;
999 /* FIXME: Set to one for now to imply the display */
1000 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
1004 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
1005 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1006 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
1010 static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
1011 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1012 POINT pt = { -1, -1 };
1014 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
1018 FIXME_(d3d_caps)("(%p): returning the primary monitor for adapter %d\n", This, Adapter);
1019 return MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
1022 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1023 of the same bpp but different resolutions */
1025 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1026 static UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
1027 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1028 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
1030 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1034 if (Adapter == 0) { /* Display */
1037 #if !defined( DEBUG_SINGLE_MODE )
1040 /* Work out the current screen bpp */
1041 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1042 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1045 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
1049 case D3DFMT_UNKNOWN:
1052 case D3DFMT_X8R8G8B8:
1053 case D3DFMT_A8R8G8B8:
1054 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
1055 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
1057 case D3DFMT_X1R5G5B5:
1058 case D3DFMT_A1R5G5B5:
1060 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
1063 /* Skip other modes as they do not match requested format */
1071 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
1074 FIXME_(d3d_caps)("Adapter not primary display\n");
1079 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
1080 static HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, WINED3DDISPLAYMODE* pMode) {
1081 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1082 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
1084 /* Validate the parameters as much as possible */
1085 if (NULL == pMode ||
1086 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
1087 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
1088 return WINED3DERR_INVALIDCALL;
1091 if (Adapter == 0) { /* Display */
1092 #if !defined( DEBUG_SINGLE_MODE )
1096 /* Work out the current screen bpp */
1097 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1098 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
1101 /* If we are filtering to a specific format, then need to skip all unrelated
1102 modes, but if mode is irrelevant, then we can use the index directly */
1103 if (Format == D3DFMT_UNKNOWN)
1109 DEVMODEW DevModeWtmp;
1112 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1116 case D3DFMT_UNKNOWN:
1119 case D3DFMT_X8R8G8B8:
1120 case D3DFMT_A8R8G8B8:
1121 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1122 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1124 case D3DFMT_X1R5G5B5:
1125 case D3DFMT_A1R5G5B5:
1127 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1130 /* Skip other modes as they do not match requested format */
1137 /* Now get the display mode via the calculated index */
1138 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
1140 pMode->Width = DevModeW.dmPelsWidth;
1141 pMode->Height = DevModeW.dmPelsHeight;
1142 bpp = min(DevModeW.dmBitsPerPel, bpp);
1143 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1144 if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
1146 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1149 if (Format == D3DFMT_UNKNOWN)
1152 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1153 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1154 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1155 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
1156 default: pMode->Format = D3DFMT_UNKNOWN;
1159 pMode->Format = Format;
1164 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1165 return WINED3DERR_INVALIDCALL;
1169 /* Return one setting of the format requested */
1170 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1172 pMode->Height = 600;
1173 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1174 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1177 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
1178 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
1181 FIXME_(d3d_caps)("Adapter not primary display\n");
1187 static HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, WINED3DDISPLAYMODE* pMode) {
1188 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1189 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
1191 if (NULL == pMode ||
1192 Adapter >= IWineD3D_GetAdapterCount(iface)) {
1193 return WINED3DERR_INVALIDCALL;
1196 if (Adapter == 0) { /* Display */
1200 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
1201 pMode->Width = DevModeW.dmPelsWidth;
1202 pMode->Height = DevModeW.dmPelsHeight;
1203 bpp = DevModeW.dmBitsPerPel;
1204 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1205 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
1207 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
1211 case 8: pMode->Format = D3DFMT_R3G3B2; break;
1212 case 16: pMode->Format = D3DFMT_R5G6B5; break;
1213 case 24: pMode->Format = D3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
1214 case 32: pMode->Format = D3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1215 default: pMode->Format = D3DFMT_UNKNOWN;
1219 FIXME_(d3d_caps)("Adapter not primary display\n");
1222 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
1223 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1227 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1230 /* only works with one adapter at the moment... */
1232 /* Get the display */
1233 device_context = GetDC(0);
1234 display = get_display(device_context);
1235 ReleaseDC(0, device_context);
1239 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1240 and fields being inserted in the middle, a new structure is used in place */
1241 static HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
1242 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
1243 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1245 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
1247 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1248 return WINED3DERR_INVALIDCALL;
1251 if (Adapter == 0) { /* Display - only device supported for now */
1253 BOOL isGLInfoValid = This->isGLInfoValid;
1255 /* FillGLCaps updates gl_info, but we only want to store and
1256 reuse the values once we have a context which is valid. Values from
1257 a temporary context may differ from the final ones */
1258 if (isGLInfoValid == FALSE) {
1259 WineD3D_Context *fake_ctx = NULL;
1260 if (glXGetCurrentContext() == NULL) fake_ctx = WineD3D_CreateFakeGLContext();
1261 /* If we don't know the device settings, go query them now */
1262 isGLInfoValid = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1263 if (fake_ctx != NULL) WineD3D_ReleaseFakeGLContext(fake_ctx);
1266 /* If it worked, return the information requested */
1267 if (isGLInfoValid) {
1268 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
1269 strcpy(pIdentifier->Driver, "Display");
1270 strcpy(pIdentifier->Description, "Direct3D HAL");
1272 /* Note dx8 doesn't supply a DeviceName */
1273 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1274 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1275 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1276 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
1277 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
1278 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
1279 *(pIdentifier->SubSysId) = 0;
1280 *(pIdentifier->Revision) = 0;
1284 /* If it failed, return dummy values from an NVidia driver */
1285 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1286 strcpy(pIdentifier->Driver, "Display");
1287 strcpy(pIdentifier->Description, "Direct3D HAL");
1288 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1289 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1290 pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
1291 /* 71.74 is a current Linux Nvidia driver version */
1292 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(10, (71*100+74));
1293 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
1294 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4200;
1295 *(pIdentifier->SubSysId) = 0;
1296 *(pIdentifier->Revision) = 0;
1299 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1300 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
1301 *(pIdentifier->WHQLLevel) = 0;
1303 *(pIdentifier->WHQLLevel) = 1;
1307 FIXME_(d3d_caps)("Adapter not primary display\n");
1313 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1314 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1316 int rb, gb, bb, ab, type, buf_sz;
1318 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
1319 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
1320 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
1321 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
1322 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
1323 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
1326 case WINED3DFMT_X8R8G8B8:
1327 case WINED3DFMT_R8G8B8:
1328 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1330 case WINED3DFMT_A8R8G8B8:
1331 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1333 case WINED3DFMT_A2R10G10B10:
1334 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1336 case WINED3DFMT_X1R5G5B5:
1337 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1339 case WINED3DFMT_A1R5G5B5:
1340 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1342 case WINED3DFMT_X4R4G4B4:
1343 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1345 case WINED3DFMT_R5G6B5:
1346 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1348 case WINED3DFMT_R3G3B2:
1349 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1351 case WINED3DFMT_A8P8:
1352 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1355 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1358 ERR("unsupported format %s\n", debug_d3dformat(Format));
1362 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1364 case WINED3DFMT_X8R8G8B8:
1365 case WINED3DFMT_R8G8B8:
1366 case WINED3DFMT_A8R8G8B8:
1367 case WINED3DFMT_A2R10G10B10:
1368 case WINED3DFMT_X1R5G5B5:
1369 case WINED3DFMT_A1R5G5B5:
1370 case WINED3DFMT_R5G6B5:
1371 case WINED3DFMT_R3G3B2:
1372 case WINED3DFMT_A8P8:
1376 ERR("unsupported format %s\n", debug_d3dformat(Format));
1383 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
1384 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1388 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1389 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1392 case WINED3DFMT_D16:
1393 case WINED3DFMT_D16_LOCKABLE:
1394 if (16 == db) return TRUE;
1396 case WINED3DFMT_D32:
1397 if (32 == db) return TRUE;
1399 case WINED3DFMT_D15S1:
1400 if (15 == db) return TRUE;
1402 case WINED3DFMT_D24S8:
1403 if (24 == db && 8 == sb) return TRUE;
1405 case WINED3DFMT_D24FS8:
1406 if (24 == db && 8 == sb) return TRUE;
1408 case WINED3DFMT_D24X8:
1409 if (24 == db) return TRUE;
1411 case WINED3DFMT_D24X4S4:
1412 if (24 == db && 4 == sb) return TRUE;
1414 case WINED3DFMT_D32F_LOCKABLE:
1415 if (32 == db) return TRUE;
1418 ERR("unsupported format %s\n", debug_d3dformat(Format));
1422 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1424 case WINED3DFMT_D16:
1425 case WINED3DFMT_D16_LOCKABLE:
1426 case WINED3DFMT_D32:
1427 case WINED3DFMT_D15S1:
1428 case WINED3DFMT_D24S8:
1429 case WINED3DFMT_D24FS8:
1430 case WINED3DFMT_D24X8:
1431 case WINED3DFMT_D24X4S4:
1432 case WINED3DFMT_D32F_LOCKABLE:
1435 ERR("unsupported format %s\n", debug_d3dformat(Format));
1442 static HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1443 WINED3DFORMAT AdapterFormat,
1444 WINED3DFORMAT RenderTargetFormat,
1445 WINED3DFORMAT DepthStencilFormat) {
1446 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1447 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1448 WineD3D_Context* ctx = NULL;
1449 GLXFBConfig* cfgs = NULL;
1453 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1455 DeviceType, debug_d3ddevicetype(DeviceType),
1456 AdapterFormat, debug_d3dformat(AdapterFormat),
1457 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
1458 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
1460 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1461 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This, Adapter, IWineD3D_GetAdapterCount(iface));
1462 return WINED3DERR_INVALIDCALL;
1464 /* TODO: use the real context if it's available */
1465 ctx = WineD3D_CreateFakeGLContext();
1467 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1469 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1473 for (it = 0; it < nCfgs; ++it) {
1474 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1475 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1484 /* If there's a corrent context then we cannot create a fake one so pass everything */
1489 WineD3D_ReleaseFakeGLContext(ctx);
1491 if (hr != WINED3D_OK)
1492 TRACE_(d3d_caps)("Failed to match stencil format to device\b");
1494 TRACE_(d3d_caps)("(%p) : Returning %lx\n", This, hr);
1498 static HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1499 WINED3DFORMAT SurfaceFormat,
1500 BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
1502 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1503 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1506 DeviceType, debug_d3ddevicetype(DeviceType),
1507 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1512 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1513 return WINED3DERR_INVALIDCALL;
1516 if (pQualityLevels != NULL) {
1517 static int s_single_shot = 0;
1518 if (!s_single_shot) {
1519 FIXME("Quality levels unsupported at present\n");
1522 *pQualityLevels = 1; /* Guess at a value! */
1525 if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
1526 return WINED3DERR_NOTAVAILABLE;
1529 static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
1530 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1532 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1533 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1536 CheckType, debug_d3ddevicetype(CheckType),
1537 DisplayFormat, debug_d3dformat(DisplayFormat),
1538 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1541 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1542 return WINED3DERR_INVALIDCALL;
1546 GLXFBConfig* cfgs = NULL;
1549 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1551 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1553 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1554 for (it = 0; it < nCfgs; ++it) {
1555 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1562 WineD3D_ReleaseFakeGLContext(ctx);
1567 return WINED3DERR_NOTAVAILABLE;
1570 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1571 WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1572 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1573 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1576 DeviceType, debug_d3ddevicetype(DeviceType),
1577 AdapterFormat, debug_d3dformat(AdapterFormat),
1578 Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
1579 RType, debug_d3dresourcetype(RType),
1580 CheckFormat, debug_d3dformat(CheckFormat));
1582 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1583 return WINED3DERR_INVALIDCALL;
1586 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1587 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1588 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1589 if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
1590 TRACE_(d3d_caps)("[FAILED]\n");
1591 return WINED3DERR_NOTAVAILABLE; /* Enable when fully supported */
1594 if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
1595 switch (CheckFormat) {
1596 case WINED3DFMT_D16_LOCKABLE:
1597 case WINED3DFMT_D32:
1598 case WINED3DFMT_D15S1:
1599 case WINED3DFMT_D24S8:
1600 case WINED3DFMT_D24X8:
1601 case WINED3DFMT_D24X4S4:
1602 case WINED3DFMT_D16:
1603 case WINED3DFMT_L16:
1604 case WINED3DFMT_D32F_LOCKABLE:
1605 case WINED3DFMT_D24FS8:
1606 TRACE_(d3d_caps)("[OK]\n");
1609 TRACE_(d3d_caps)("[FAILED]\n");
1610 return WINED3DERR_NOTAVAILABLE;
1612 } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
1613 switch (CheckFormat) {
1614 case WINED3DFMT_R8G8B8:
1615 case WINED3DFMT_A8R8G8B8:
1616 case WINED3DFMT_X8R8G8B8:
1617 case WINED3DFMT_R5G6B5:
1618 case WINED3DFMT_X1R5G5B5:
1619 case WINED3DFMT_A1R5G5B5:
1620 case WINED3DFMT_A4R4G4B4:
1621 case WINED3DFMT_R3G3B2:
1622 case WINED3DFMT_X4R4G4B4:
1623 case WINED3DFMT_A8B8G8R8:
1624 case WINED3DFMT_X8B8G8R8:
1626 TRACE_(d3d_caps)("[OK]\n");
1629 TRACE_(d3d_caps)("[FAILED]\n");
1630 return WINED3DERR_NOTAVAILABLE;
1634 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1635 switch (CheckFormat) {
1641 TRACE_(d3d_caps)("[OK]\n");
1644 break; /* Avoid compiler warnings */
1648 if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
1650 BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
1652 switch (CheckFormat) {
1653 case D3DFMT_A16B16G16R16F:
1654 if (!half_pixel_support) break;
1655 case D3DFMT_A32B32G32R32F:
1656 TRACE_(d3d_caps)("[OK]\n");
1659 break; /* Avoid compiler warnings */
1663 /* This format is nothing special and it is supported perfectly.
1664 * However, ati and nvidia driver on windows do not mark this format
1665 * supported(tested with the dxCapsViewer) and pretending to
1666 * support this format uncovers a bug in Battlefield 1942(fonts are missing)
1667 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1668 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1670 if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
1671 TRACE_(d3d_caps)("[FAILED]\n");
1672 return WINED3DERR_NOTAVAILABLE;
1675 switch (CheckFormat) {
1678 * supported: RGB(A) formats
1680 case WINED3DFMT_R8G8B8: /* Enable for dx7, blacklisted for 8 and 9 above */
1681 case WINED3DFMT_A8R8G8B8:
1682 case WINED3DFMT_X8R8G8B8:
1683 case WINED3DFMT_R5G6B5:
1684 case WINED3DFMT_X1R5G5B5:
1685 case WINED3DFMT_A1R5G5B5:
1686 case WINED3DFMT_A4R4G4B4:
1687 case WINED3DFMT_R3G3B2:
1689 case WINED3DFMT_A8R3G3B2:
1690 case WINED3DFMT_X4R4G4B4:
1691 case WINED3DFMT_A8B8G8R8:
1692 case WINED3DFMT_X8B8G8R8:
1693 case WINED3DFMT_A2R10G10B10:
1694 case WINED3DFMT_A2B10G10R10:
1695 TRACE_(d3d_caps)("[OK]\n");
1699 * supported: Palettized
1702 TRACE_(d3d_caps)("[OK]\n");
1706 * Supported: (Alpha)-Luminance
1709 case WINED3DFMT_A8L8:
1710 case WINED3DFMT_A4L4:
1711 TRACE_(d3d_caps)("[OK]\n");
1715 * Not supported for now: Bump mapping formats
1716 * Enable some because games often fail when they are not available
1717 * and are still playable even without bump mapping
1719 case WINED3DFMT_V8U8:
1720 case WINED3DFMT_V16U16:
1721 case WINED3DFMT_L6V5U5:
1722 case WINED3DFMT_X8L8V8U8:
1723 case WINED3DFMT_Q8W8V8U8:
1724 case WINED3DFMT_W11V11U10:
1725 case WINED3DFMT_A2W10V10U10:
1726 WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
1730 * DXTN Formats: Handled above
1739 * Odd formats - not supported
1741 case WINED3DFMT_VERTEXDATA:
1742 case WINED3DFMT_INDEX16:
1743 case WINED3DFMT_INDEX32:
1744 case WINED3DFMT_Q16W16V16U16:
1745 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1746 return WINED3DERR_NOTAVAILABLE;
1749 * Float formats: Not supported right now
1751 case WINED3DFMT_R16F:
1752 case WINED3DFMT_G16R16F:
1753 case WINED3DFMT_R32F:
1754 case WINED3DFMT_G32R32F:
1755 case WINED3DFMT_CxV8U8:
1756 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1757 return WINED3DERR_NOTAVAILABLE;
1760 case WINED3DFMT_G16R16:
1761 case WINED3DFMT_A16B16G16R16:
1762 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1763 return WINED3DERR_NOTAVAILABLE;
1769 TRACE_(d3d_caps)("[FAILED]\n");
1770 return WINED3DERR_NOTAVAILABLE;
1773 static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
1774 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1775 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1777 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1780 DeviceType, debug_d3ddevicetype(DeviceType),
1781 SourceFormat, debug_d3dformat(SourceFormat),
1782 TargetFormat, debug_d3dformat(TargetFormat));
1786 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1787 subset of a D3DCAPS9 structure. However, it has to come via a void *
1788 as the d3d8 interface cannot import the d3d9 header */
1789 static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1791 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1793 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1795 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1796 return WINED3DERR_INVALIDCALL;
1799 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1801 /* If we don't know the device settings, go query them now */
1802 if (This->isGLInfoValid == FALSE) {
1803 /* use the desktop window to fill gl caps */
1804 BOOL rc = IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
1806 /* We are running off a real context, save the values */
1807 if (rc) This->isGLInfoValid = TRUE;
1809 select_shader_mode(&This->gl_info, DeviceType,
1810 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
1811 select_shader_max_constants(&This->gl_info);
1813 /* ------------------------------------------------
1814 The following fields apply to both d3d8 and d3d9
1815 ------------------------------------------------ */
1816 *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1817 *pCaps->AdapterOrdinal = Adapter;
1820 *pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
1821 *pCaps->Caps3 = WINED3DDEVCAPS_HWTRANSFORMANDLIGHT;
1822 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1824 *pCaps->CursorCaps = 0;
1827 *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
1828 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
1829 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
1830 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
1831 WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
1832 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
1833 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
1834 WINED3DDEVCAPS_PUREDEVICE |
1835 WINED3DDEVCAPS_HWRASTERIZATION |
1836 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
1837 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
1838 WINED3DDEVCAPS_CANRENDERAFTERFLIP |
1839 WINED3DDEVCAPS_DRAWPRIMITIVES2 |
1840 WINED3DDEVCAPS_DRAWPRIMITIVES2EX;
1842 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLNONE |
1843 D3DPMISCCAPS_CULLCCW |
1844 D3DPMISCCAPS_CULLCW |
1845 D3DPMISCCAPS_COLORWRITEENABLE |
1846 D3DPMISCCAPS_CLIPTLVERTS |
1847 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1848 D3DPMISCCAPS_MASKZ |
1849 D3DPMISCCAPS_BLENDOP;
1851 D3DPMISCCAPS_NULLREFERENCE
1852 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1853 D3DPMISCCAPS_FOGANDSPECULARALPHA
1854 D3DPMISCCAPS_SEPARATEALPHABLEND
1855 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1856 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1857 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1859 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1861 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1862 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1863 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1864 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1867 *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
1868 WINED3DPRASTERCAPS_PAT |
1869 WINED3DPRASTERCAPS_WFOG |
1870 WINED3DPRASTERCAPS_ZFOG |
1871 WINED3DPRASTERCAPS_FOGVERTEX |
1872 WINED3DPRASTERCAPS_FOGTABLE |
1873 WINED3DPRASTERCAPS_FOGRANGE |
1874 WINED3DPRASTERCAPS_STIPPLE |
1875 WINED3DPRASTERCAPS_SUBPIXEL |
1876 WINED3DPRASTERCAPS_ZTEST |
1877 WINED3DPRASTERCAPS_SCISSORTEST |
1878 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
1879 WINED3DPRASTERCAPS_DEPTHBIAS;
1881 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1882 *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
1883 WINED3DPRASTERCAPS_ZBIAS |
1884 WINED3DPRASTERCAPS_MIPMAPLODBIAS;
1887 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1888 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1889 WINED3DPRASTERCAPS_ANTIALIASEDGES
1890 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1891 WINED3DPRASTERCAPS_WBUFFER */
1893 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1895 D3DPCMPCAPS_GREATER |
1896 D3DPCMPCAPS_GREATEREQUAL |
1898 D3DPCMPCAPS_LESSEQUAL |
1900 D3DPCMPCAPS_NOTEQUAL;
1902 *pCaps->SrcBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1903 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1904 D3DPBLENDCAPS_BOTHSRCALPHA |
1905 D3DPBLENDCAPS_DESTALPHA |
1906 D3DPBLENDCAPS_DESTCOLOR |
1907 D3DPBLENDCAPS_INVDESTALPHA |
1908 D3DPBLENDCAPS_INVDESTCOLOR |
1909 D3DPBLENDCAPS_INVSRCALPHA |
1910 D3DPBLENDCAPS_INVSRCCOLOR |
1912 D3DPBLENDCAPS_SRCALPHA |
1913 D3DPBLENDCAPS_SRCALPHASAT |
1914 D3DPBLENDCAPS_SRCCOLOR |
1917 *pCaps->DestBlendCaps = D3DPBLENDCAPS_BLENDFACTOR |
1918 D3DPBLENDCAPS_BOTHINVSRCALPHA |
1919 D3DPBLENDCAPS_BOTHSRCALPHA |
1920 D3DPBLENDCAPS_DESTALPHA |
1921 D3DPBLENDCAPS_DESTCOLOR |
1922 D3DPBLENDCAPS_INVDESTALPHA |
1923 D3DPBLENDCAPS_INVDESTCOLOR |
1924 D3DPBLENDCAPS_INVSRCALPHA |
1925 D3DPBLENDCAPS_INVSRCCOLOR |
1927 D3DPBLENDCAPS_SRCALPHA |
1928 D3DPBLENDCAPS_SRCALPHASAT |
1929 D3DPBLENDCAPS_SRCCOLOR |
1932 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1934 D3DPCMPCAPS_GREATER |
1935 D3DPCMPCAPS_GREATEREQUAL |
1937 D3DPCMPCAPS_LESSEQUAL |
1939 D3DPCMPCAPS_NOTEQUAL;
1941 *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
1942 WINED3DPSHADECAPS_COLORGOURAUDRGB |
1943 WINED3DPSHADECAPS_ALPHAFLATBLEND |
1944 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
1945 WINED3DPSHADECAPS_COLORFLATRGB |
1946 WINED3DPSHADECAPS_FOGFLAT |
1947 WINED3DPSHADECAPS_FOGGOURAUD |
1948 WINED3DPSHADECAPS_SPECULARFLATRGB;
1950 *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
1951 WINED3DPTEXTURECAPS_ALPHAPALETTE |
1952 WINED3DPTEXTURECAPS_BORDER |
1953 WINED3DPTEXTURECAPS_MIPMAP |
1954 WINED3DPTEXTURECAPS_PROJECTED |
1955 WINED3DPTEXTURECAPS_PERSPECTIVE |
1956 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1958 if( GL_SUPPORT(EXT_TEXTURE3D)) {
1959 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
1960 WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
1961 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
1964 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1965 *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
1966 WINED3DPTEXTURECAPS_MIPCUBEMAP |
1967 WINED3DPTEXTURECAPS_CUBEMAP_POW2;
1971 *pCaps->TextureFilterCaps = 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->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
1986 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
1989 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1990 *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
1991 WINED3DPTFILTERCAPS_MAGFPOINT |
1992 WINED3DPTFILTERCAPS_MINFLINEAR |
1993 WINED3DPTFILTERCAPS_MINFPOINT |
1994 WINED3DPTFILTERCAPS_MIPFLINEAR |
1995 WINED3DPTFILTERCAPS_MIPFPOINT |
1996 WINED3DPTFILTERCAPS_LINEAR |
1997 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
1998 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
1999 WINED3DPTFILTERCAPS_MIPLINEAR |
2000 WINED3DPTFILTERCAPS_MIPNEAREST |
2001 WINED3DPTFILTERCAPS_NEAREST;
2003 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2004 *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
2005 WINED3DPTFILTERCAPS_MINFANISOTROPIC;
2008 *pCaps->CubeTextureFilterCaps = 0;
2010 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2011 *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
2012 WINED3DPTFILTERCAPS_MAGFPOINT |
2013 WINED3DPTFILTERCAPS_MINFLINEAR |
2014 WINED3DPTFILTERCAPS_MINFPOINT |
2015 WINED3DPTFILTERCAPS_MIPFLINEAR |
2016 WINED3DPTFILTERCAPS_MIPFPOINT |
2017 WINED3DPTFILTERCAPS_LINEAR |
2018 WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
2019 WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
2020 WINED3DPTFILTERCAPS_MIPLINEAR |
2021 WINED3DPTFILTERCAPS_MIPNEAREST |
2022 WINED3DPTFILTERCAPS_NEAREST;
2024 *pCaps->VolumeTextureFilterCaps = 0;
2026 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2027 D3DPTADDRESSCAPS_CLAMP |
2028 D3DPTADDRESSCAPS_WRAP;
2030 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2031 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2033 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2034 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2036 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2037 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2040 if (GL_SUPPORT(EXT_TEXTURE3D)) {
2041 *pCaps->VolumeTextureAddressCaps = D3DPTADDRESSCAPS_INDEPENDENTUV |
2042 D3DPTADDRESSCAPS_CLAMP |
2043 D3DPTADDRESSCAPS_WRAP;
2044 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2045 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
2047 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2048 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
2050 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2051 *pCaps->VolumeTextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
2054 *pCaps->VolumeTextureAddressCaps = 0;
2056 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
2060 D3DLINECAPS_ALPHACMP
2063 *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
2064 *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
2066 if(GL_SUPPORT(EXT_TEXTURE3D))
2067 *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
2069 *pCaps->MaxVolumeExtent = 0;
2071 *pCaps->MaxTextureRepeat = 32768;
2072 *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
2073 *pCaps->MaxVertexW = 1.0;
2075 *pCaps->GuardBandLeft = 0;
2076 *pCaps->GuardBandTop = 0;
2077 *pCaps->GuardBandRight = 0;
2078 *pCaps->GuardBandBottom = 0;
2080 *pCaps->ExtentsAdjust = 0;
2082 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
2083 D3DSTENCILCAPS_INCRSAT |
2084 D3DSTENCILCAPS_INVERT |
2085 D3DSTENCILCAPS_KEEP |
2086 D3DSTENCILCAPS_REPLACE |
2087 D3DSTENCILCAPS_ZERO;
2088 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
2089 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
2090 D3DSTENCILCAPS_INCR;
2092 if ( This->dxVersion > 8 &&
2093 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
2094 GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
2095 *pCaps->StencilCaps |= D3DSTENCILCAPS_TWOSIDED;
2098 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
2100 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
2101 D3DTEXOPCAPS_ADDSIGNED |
2102 D3DTEXOPCAPS_ADDSIGNED2X |
2103 D3DTEXOPCAPS_MODULATE |
2104 D3DTEXOPCAPS_MODULATE2X |
2105 D3DTEXOPCAPS_MODULATE4X |
2106 D3DTEXOPCAPS_SELECTARG1 |
2107 D3DTEXOPCAPS_SELECTARG2 |
2108 D3DTEXOPCAPS_DISABLE;
2110 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
2111 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
2112 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2113 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
2114 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
2115 D3DTEXOPCAPS_BLENDFACTORALPHA |
2116 D3DTEXOPCAPS_BLENDCURRENTALPHA |
2118 D3DTEXOPCAPS_SUBTRACT;
2120 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2121 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
2122 D3DTEXOPCAPS_MULTIPLYADD |
2123 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
2124 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
2125 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
2127 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
2128 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3;
2130 if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2131 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
2132 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
2137 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2139 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2140 D3DTEXOPCAPS_PREMODULATE */
2143 *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
2144 *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
2145 *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
2146 *pCaps->MaxActiveLights = GL_LIMITS(lights);
2150 #if 0 /* TODO: Blends support in drawprim */
2151 *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
2153 *pCaps->MaxVertexBlendMatrices = 0;
2155 *pCaps->MaxVertexBlendMatrixIndex = 1;
2157 *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
2158 *pCaps->MaxPointSize = GL_LIMITS(pointsize);
2161 *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
2162 WINED3DVTXPCAPS_MATERIALSOURCE7 |
2163 WINED3DVTXPCAPS_POSITIONALLIGHTS |
2164 WINED3DVTXPCAPS_LOCALVIEWER |
2165 WINED3DVTXPCAPS_VERTEXFOG |
2166 WINED3DVTXPCAPS_TEXGEN;
2168 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2170 *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2171 *pCaps->MaxVertexIndex = 0xFFFFF;
2172 *pCaps->MaxStreams = MAX_STREAMS;
2173 *pCaps->MaxStreamStride = 1024;
2175 /* FIXME: the shader mode should be per adapter */
2176 if (wined3d_settings.vs_selected_mode == SHADER_GLSL) {
2177 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2178 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2179 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2180 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2181 if(This->gl_info.vs_nv_version == VS_VERSION_20)
2182 *pCaps->VertexShaderVersion = D3DVS_VERSION(2,0);
2184 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2185 TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2186 } else if (wined3d_settings.vs_selected_mode == SHADER_ARB) {
2187 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
2188 TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2189 } else if (wined3d_settings.vs_selected_mode == SHADER_SW) {
2190 *pCaps->VertexShaderVersion = D3DVS_VERSION(3,0);
2191 TRACE_(d3d_caps)("Software vertex shader version 3.0 enabled\n");
2193 *pCaps->VertexShaderVersion = 0;
2194 TRACE_(d3d_caps)("Vertex shader functionality not available\n");
2197 *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
2199 /* FIXME: the shader mode should be per adapter */
2200 if (wined3d_settings.ps_selected_mode == SHADER_GLSL) {
2201 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2202 in case of GeforceFX cards. */
2203 if(This->gl_info.ps_nv_version == PS_VERSION_20)
2204 *pCaps->PixelShaderVersion = D3DPS_VERSION(2,0);
2206 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2207 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2208 *pCaps->PixelShader1xMaxValue = 1.0;
2209 TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2210 } else if (wined3d_settings.ps_selected_mode == SHADER_ARB) {
2211 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
2212 *pCaps->PixelShader1xMaxValue = 1.0;
2213 TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2214 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2215 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2216 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2217 *pCaps->PixelShader1xMaxValue = 1.0;
2218 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2220 *pCaps->PixelShaderVersion = 0;
2221 *pCaps->PixelShader1xMaxValue = 0.0;
2222 TRACE_(d3d_caps)("Pixel shader functionality not available\n");
2225 /* ------------------------------------------------
2226 The following fields apply to d3d9 only
2227 ------------------------------------------------ */
2228 if (This->dxVersion > 8) {
2229 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2230 *pCaps->DevCaps2 = 0;
2231 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs atleast D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2232 *pCaps->MaxNpatchTessellationLevel = 0;
2233 *pCaps->MasterAdapterOrdinal = 0;
2234 *pCaps->AdapterOrdinalInGroup = 0;
2235 *pCaps->NumberOfAdaptersInGroup = 1;
2237 if(*pCaps->VertexShaderVersion >= D3DVS_VERSION(2,0)) {
2238 /* OpenGL supports all formats below, perhaps not always without conversion but it supports them.
2239 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2240 don't advertise it yet. We might need to add some clamping in the shader engine to support it.
2241 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2242 *pCaps->DeclTypes = D3DDTCAPS_UBYTE4 |
2246 D3DDTCAPS_FLOAT16_2 |
2247 D3DDTCAPS_FLOAT16_4;
2250 *pCaps->DeclTypes = 0;
2252 #if 0 /* We don't properly support multiple render targets yet, so disable this for now */
2253 if (GL_SUPPORT(ARB_DRAWBUFFERS)) {
2254 *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
2257 *pCaps->NumSimultaneousRTs = 1;
2259 *pCaps->StretchRectFilterCaps = 0;
2260 *pCaps->VertexTextureFilterCaps = 0;
2262 if(*pCaps->VertexShaderVersion == D3DVS_VERSION(3,0)) {
2263 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2264 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2265 *pCaps->VS20Caps.Caps = D3DVS20CAPS_PREDICATION;
2266 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2267 *pCaps->VS20Caps.NumTemps = max(32, This->gl_info.vs_arb_max_temps);
2268 *pCaps->VS20Caps.StaticFlowControlDepth = D3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2270 *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs atleast 65535, some cards even use 2^32-1 */
2271 *pCaps->MaxVertexShader30InstructionSlots = max(512, This->gl_info.vs_arb_max_instructions);
2272 } else if(*pCaps->VertexShaderVersion == D3DVS_VERSION(2,0)) {
2273 *pCaps->VS20Caps.Caps = 0;
2274 *pCaps->VS20Caps.DynamicFlowControlDepth = D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
2275 *pCaps->VS20Caps.NumTemps = max(12, This->gl_info.vs_arb_max_temps);
2276 *pCaps->VS20Caps.StaticFlowControlDepth = 1;
2278 *pCaps->MaxVShaderInstructionsExecuted = 65535;
2279 *pCaps->MaxVertexShader30InstructionSlots = 0;
2280 } else { /* VS 1.x */
2281 *pCaps->VS20Caps.Caps = 0;
2282 *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
2283 *pCaps->VS20Caps.NumTemps = 0;
2284 *pCaps->VS20Caps.StaticFlowControlDepth = 0;
2286 *pCaps->MaxVShaderInstructionsExecuted = 0;
2287 *pCaps->MaxVertexShader30InstructionSlots = 0;
2290 if(*pCaps->PixelShaderVersion == D3DPS_VERSION(3,0)) {
2291 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2292 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2294 /* 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 */
2295 *pCaps->PS20Caps.Caps = D3DPS20CAPS_ARBITRARYSWIZZLE |
2296 D3DPS20CAPS_GRADIENTINSTRUCTIONS |
2297 D3DPS20CAPS_PREDICATION |
2298 D3DPS20CAPS_NODEPENDENTREADLIMIT |
2299 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
2300 *pCaps->PS20Caps.DynamicFlowControlDepth = D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2301 *pCaps->PS20Caps.NumTemps = max(32, This->gl_info.ps_arb_max_temps);
2302 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2303 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2305 *pCaps->MaxPShaderInstructionsExecuted = 65535;
2306 *pCaps->MaxPixelShader30InstructionSlots = max(D3DMIN30SHADERINSTRUCTIONS, This->gl_info.ps_arb_max_instructions);
2307 } else if(*pCaps->PixelShaderVersion == D3DPS_VERSION(2,0)) {
2308 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2309 *pCaps->PS20Caps.Caps = 0;
2310 *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2311 *pCaps->PS20Caps.NumTemps = max(12, This->gl_info.ps_arb_max_temps);
2312 *pCaps->PS20Caps.StaticFlowControlDepth = D3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
2313 *pCaps->PS20Caps.NumInstructionSlots = D3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2315 *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
2316 *pCaps->MaxPixelShader30InstructionSlots = 0;
2317 } else { /* PS 1.x */
2318 *pCaps->PS20Caps.Caps = 0;
2319 *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
2320 *pCaps->PS20Caps.NumTemps = 0;
2321 *pCaps->PS20Caps.StaticFlowControlDepth = 0;
2322 *pCaps->PS20Caps.NumInstructionSlots = 0;
2324 *pCaps->MaxPShaderInstructionsExecuted = 0;
2325 *pCaps->MaxPixelShader30InstructionSlots = 0;
2333 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2334 and fields being inserted in the middle, a new structure is used in place */
2335 static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
2336 DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
2339 IWineD3DDeviceImpl *object = NULL;
2340 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2342 HRESULT temp_result;
2344 /* Validate the adapter number */
2345 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
2346 return WINED3DERR_INVALIDCALL;
2349 /* Create a WineD3DDevice object */
2350 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
2351 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
2352 TRACE("Created WineD3DDevice object @ %p\n", object);
2353 if (NULL == object) {
2354 return WINED3DERR_OUTOFVIDEOMEMORY;
2357 /* Set up initial COM information */
2358 object->lpVtbl = &IWineD3DDevice_Vtbl;
2360 object->wineD3D = iface;
2361 IWineD3D_AddRef(object->wineD3D);
2362 object->parent = parent;
2364 /* Set the state up as invalid until the device is fully created */
2365 object->state = WINED3DERR_DRIVERINTERNALERROR;
2367 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This, Adapter, DeviceType,
2368 hFocusWindow, BehaviourFlags, ppReturnedDeviceInterface);
2370 /* Save the creation parameters */
2371 object->createParms.AdapterOrdinal = Adapter;
2372 object->createParms.DeviceType = DeviceType;
2373 object->createParms.hFocusWindow = hFocusWindow;
2374 object->createParms.BehaviorFlags = BehaviourFlags;
2376 /* Initialize other useful values */
2377 object->adapterNo = Adapter;
2378 object->devType = DeviceType;
2380 TRACE("(%p) : Creating stateblock\n", This);
2381 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2382 if (WINED3D_OK != IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
2384 (IWineD3DStateBlock **)&object->stateBlock,
2385 NULL) || NULL == object->stateBlock) { /* Note: No parent needed for initial internal stateblock */
2386 WARN("Failed to create stateblock\n");
2387 goto create_device_error;
2389 TRACE("(%p) : Created stateblock (%p)\n", This, object->stateBlock);
2390 object->updateStateBlock = object->stateBlock;
2391 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
2392 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2394 /* Setup some defaults for creating the implicit swapchain */
2396 /* FIXME: both of those should be made per adapter */
2397 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2399 select_shader_mode(&This->gl_info, DeviceType,
2400 &wined3d_settings.ps_selected_mode, &wined3d_settings.vs_selected_mode);
2401 select_shader_max_constants(&This->gl_info);
2403 temp_result = allocate_shader_constants(object->updateStateBlock);
2404 if (WINED3D_OK != temp_result)
2407 /* set the state of the device to valid */
2408 object->state = WINED3D_OK;
2410 /* Get the initial screen setup for ddraw */
2411 object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
2412 object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
2413 hDC = CreateDCA("DISPLAY", NULL, NULL, NULL);
2414 object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
2418 create_device_error:
2420 /* Set the device state to error */
2421 object->state = WINED3DERR_DRIVERINTERNALERROR;
2423 if (object->updateStateBlock != NULL) {
2424 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
2425 object->updateStateBlock = NULL;
2427 if (object->stateBlock != NULL) {
2428 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
2429 object->stateBlock = NULL;
2431 if (object->renderTarget != NULL) {
2432 IWineD3DSurface_Release(object->renderTarget);
2433 object->renderTarget = NULL;
2435 if (object->stencilBufferTarget != NULL) {
2436 IWineD3DSurface_Release(object->stencilBufferTarget);
2437 object->stencilBufferTarget = NULL;
2439 if (object->stencilBufferTarget != NULL) {
2440 IWineD3DSurface_Release(object->stencilBufferTarget);
2441 object->stencilBufferTarget = NULL;
2443 HeapFree(GetProcessHeap(), 0, object);
2444 *ppReturnedDeviceInterface = NULL;
2445 return WINED3DERR_INVALIDCALL;
2449 static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
2450 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2451 IUnknown_AddRef(This->parent);
2452 *pParent = This->parent;
2456 /**********************************************************
2457 * IWineD3D VTbl follows
2458 **********************************************************/
2460 const IWineD3DVtbl IWineD3D_Vtbl =
2463 IWineD3DImpl_QueryInterface,
2464 IWineD3DImpl_AddRef,
2465 IWineD3DImpl_Release,
2467 IWineD3DImpl_GetParent,
2468 IWineD3DImpl_GetAdapterCount,
2469 IWineD3DImpl_RegisterSoftwareDevice,
2470 IWineD3DImpl_GetAdapterMonitor,
2471 IWineD3DImpl_GetAdapterModeCount,
2472 IWineD3DImpl_EnumAdapterModes,
2473 IWineD3DImpl_GetAdapterDisplayMode,
2474 IWineD3DImpl_GetAdapterIdentifier,
2475 IWineD3DImpl_CheckDeviceMultiSampleType,
2476 IWineD3DImpl_CheckDepthStencilMatch,
2477 IWineD3DImpl_CheckDeviceType,
2478 IWineD3DImpl_CheckDeviceFormat,
2479 IWineD3DImpl_CheckDeviceFormatConversion,
2480 IWineD3DImpl_GetDeviceCaps,
2481 IWineD3DImpl_CreateDevice