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 #ifndef DEBUG_SINGLE_MODE
27 /* Set to 1 to force only a single display mode to be exposed: */
28 #define DEBUG_SINGLE_MODE 0
34 #include "wined3d_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
37 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps
);
39 /**********************************************************
40 * Utility functions follow
41 **********************************************************/
43 /* x11drv GDI escapes */
44 #define X11DRV_ESCAPE 6789
45 enum x11drv_escape_codes
47 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
48 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
49 X11DRV_GET_FONT
, /* get current X font for a DC */
52 /* retrieve the X display to use on a given DC */
53 static inline Display
*get_display( HDC hdc
)
56 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
58 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
59 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
64 static int numAdapters
= 0;
65 static struct WineD3DAdapter Adapters
[1];
68 int minLookup
[MAX_LOOKUPS
];
69 int maxLookup
[MAX_LOOKUPS
];
70 DWORD
*stateLookup
[MAX_LOOKUPS
];
72 DWORD minMipLookup
[WINED3DTEXF_ANISOTROPIC
+ 1][WINED3DTEXF_LINEAR
+ 1];
76 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
77 * ie there is no GL Context - Get a default rendering context to enable the
78 * function query some info from GL
81 static int wined3d_fake_gl_context_ref
= 0;
82 static BOOL wined3d_fake_gl_context_foreign
;
83 static BOOL wined3d_fake_gl_context_available
= FALSE
;
84 static Display
* wined3d_fake_gl_context_display
= NULL
;
86 static CRITICAL_SECTION wined3d_fake_gl_context_cs
;
87 static CRITICAL_SECTION_DEBUG wined3d_fake_gl_context_cs_debug
=
89 0, 0, &wined3d_fake_gl_context_cs
,
90 { &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
,
91 &wined3d_fake_gl_context_cs_debug
.ProcessLocksList
},
92 0, 0, { (DWORD_PTR
)(__FILE__
": wined3d_fake_gl_context_cs") }
94 static CRITICAL_SECTION wined3d_fake_gl_context_cs
= { &wined3d_fake_gl_context_cs_debug
, -1, 0, 0, 0, 0 };
96 static void WineD3D_ReleaseFakeGLContext(void) {
99 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
101 if(!wined3d_fake_gl_context_available
) {
102 TRACE_(d3d_caps
)("context not available\n");
103 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
107 glCtx
= glXGetCurrentContext();
109 TRACE_(d3d_caps
)("decrementing ref from %i\n", wined3d_fake_gl_context_ref
);
110 if (0 == (--wined3d_fake_gl_context_ref
) ) {
111 if(!wined3d_fake_gl_context_foreign
&& glCtx
) {
112 TRACE_(d3d_caps
)("destroying fake GL context\n");
113 glXMakeCurrent(wined3d_fake_gl_context_display
, None
, NULL
);
114 glXDestroyContext(wined3d_fake_gl_context_display
, glCtx
);
116 wined3d_fake_gl_context_available
= FALSE
;
118 assert(wined3d_fake_gl_context_ref
>= 0);
120 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
124 static BOOL
WineD3D_CreateFakeGLContext(void) {
125 XVisualInfo
* visInfo
;
129 EnterCriticalSection(&wined3d_fake_gl_context_cs
);
131 TRACE_(d3d_caps
)("getting context...\n");
132 if(wined3d_fake_gl_context_ref
> 0) goto ret
;
133 assert(0 == wined3d_fake_gl_context_ref
);
135 wined3d_fake_gl_context_foreign
= TRUE
;
137 if(!wined3d_fake_gl_context_display
) {
138 HDC device_context
= GetDC(0);
140 wined3d_fake_gl_context_display
= get_display(device_context
);
141 ReleaseDC(0, device_context
);
145 glCtx
= glXGetCurrentContext();
149 XVisualInfo
template;
152 XWindowAttributes win_attr
;
154 wined3d_fake_gl_context_foreign
= FALSE
;
155 drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
157 TRACE_(d3d_caps
)("Creating Fake GL Context\n");
159 /* Get the X visual */
160 if (XGetWindowAttributes(wined3d_fake_gl_context_display
, drawable
, &win_attr
)) {
161 visual
= win_attr
.visual
;
163 visual
= DefaultVisual(wined3d_fake_gl_context_display
, DefaultScreen(wined3d_fake_gl_context_display
));
165 template.visualid
= XVisualIDFromVisual(visual
);
166 visInfo
= XGetVisualInfo(wined3d_fake_gl_context_display
, VisualIDMask
, &template, &num
);
168 WARN_(d3d_caps
)("Error creating visual info for capabilities initialization\n");
172 /* Create a GL context */
173 glCtx
= glXCreateContext(wined3d_fake_gl_context_display
, visInfo
, NULL
, GL_TRUE
);
175 WARN_(d3d_caps
)("Error creating default context for capabilities initialization\n");
179 /* Make it the current GL context */
180 if (!glXMakeCurrent(wined3d_fake_gl_context_display
, drawable
, glCtx
)) {
181 WARN_(d3d_caps
)("Error setting default context as current for capabilities initialization\n");
190 TRACE_(d3d_caps
)("incrementing ref from %i\n", wined3d_fake_gl_context_ref
);
191 wined3d_fake_gl_context_ref
++;
192 wined3d_fake_gl_context_available
= TRUE
;
193 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
196 if(visInfo
) XFree(visInfo
);
197 if(glCtx
) glXDestroyContext(wined3d_fake_gl_context_display
, glCtx
);
198 LeaveCriticalSection(&wined3d_fake_gl_context_cs
);
203 /**********************************************************
204 * IUnknown parts follows
205 **********************************************************/
207 static HRESULT WINAPI
IWineD3DImpl_QueryInterface(IWineD3D
*iface
,REFIID riid
,LPVOID
*ppobj
)
209 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
211 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
212 if (IsEqualGUID(riid
, &IID_IUnknown
)
213 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
214 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
215 IUnknown_AddRef(iface
);
220 return E_NOINTERFACE
;
223 static ULONG WINAPI
IWineD3DImpl_AddRef(IWineD3D
*iface
) {
224 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
225 ULONG refCount
= InterlockedIncrement(&This
->ref
);
227 TRACE("(%p) : AddRef increasing from %d\n", This
, refCount
- 1);
231 static ULONG WINAPI
IWineD3DImpl_Release(IWineD3D
*iface
) {
232 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
234 TRACE("(%p) : Releasing from %d\n", This
, This
->ref
);
235 ref
= InterlockedDecrement(&This
->ref
);
237 HeapFree(GetProcessHeap(), 0, This
);
243 /* Set the shader type for this device, depending on the given capabilities,
244 * the device type, and the user preferences in wined3d_settings */
246 static void select_shader_mode(
247 WineD3D_GL_Info
*gl_info
,
248 WINED3DDEVTYPE DeviceType
,
252 if (wined3d_settings
.vs_mode
== VS_NONE
) {
253 *vs_selected
= SHADER_NONE
;
254 } else if (gl_info
->supported
[ARB_VERTEX_SHADER
] && wined3d_settings
.glslRequested
) {
255 *vs_selected
= SHADER_GLSL
;
256 } else if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
257 *vs_selected
= SHADER_ARB
;
259 *vs_selected
= SHADER_NONE
;
262 if (wined3d_settings
.ps_mode
== PS_NONE
) {
263 *ps_selected
= SHADER_NONE
;
264 } else if (gl_info
->supported
[ARB_FRAGMENT_SHADER
] && wined3d_settings
.glslRequested
) {
265 *ps_selected
= SHADER_GLSL
;
266 } else if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
267 *ps_selected
= SHADER_ARB
;
269 *ps_selected
= SHADER_NONE
;
273 /** Select the number of report maximum shader constants based on the selected shader modes */
274 static void select_shader_max_constants(
275 int ps_selected_mode
,
276 int vs_selected_mode
,
277 WineD3D_GL_Info
*gl_info
) {
279 switch (vs_selected_mode
) {
281 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
282 gl_info
->max_vshader_constantsF
= gl_info
->vs_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 1;
285 /* We have to subtract any other PARAMs that we might use in our shader programs.
286 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
287 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
288 gl_info
->max_vshader_constantsF
= gl_info
->vs_arb_constantsF
- 3;
291 gl_info
->max_vshader_constantsF
= 0;
295 switch (ps_selected_mode
) {
297 /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
298 * In theory the texbem instruction may need one more shader constant too. But lets assume
299 * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
300 * and lets not take away a uniform needlessly from all other shaders.
302 gl_info
->max_pshader_constantsF
= gl_info
->ps_glsl_constantsF
- (MAX_CONST_B
/ 4) - MAX_CONST_I
- 2;
305 /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
306 * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
308 gl_info
->max_pshader_constantsF
= gl_info
->ps_arb_constantsF
- 2;
311 gl_info
->max_pshader_constantsF
= 0;
316 /**********************************************************
317 * IWineD3D parts follows
318 **********************************************************/
320 #define GLINFO_LOCATION (*gl_info)
321 BOOL
IWineD3DImpl_FillGLCaps(WineD3D_GL_Info
*gl_info
, Display
* display
) {
322 const char *GL_Extensions
= NULL
;
323 const char *GLX_Extensions
= NULL
;
324 const char *gl_string
= NULL
;
325 const char *gl_string_cursor
= NULL
;
327 GLfloat gl_floatv
[2];
330 BOOL return_value
= TRUE
;
333 /* Make sure that we've got a context */
334 /* TODO: CreateFakeGLContext should really take a display as a parameter */
335 /* Only save the values obtained when a display is provided */
336 if (!WineD3D_CreateFakeGLContext() || wined3d_fake_gl_context_foreign
)
337 return_value
= FALSE
;
339 TRACE_(d3d_caps
)("(%p, %p)\n", gl_info
, display
);
341 gl_string
= (const char *) glGetString(GL_RENDERER
);
342 if (NULL
== gl_string
)
344 strcpy(gl_info
->gl_renderer
, gl_string
);
346 /* Fill in the GL info retrievable depending on the display */
347 if (NULL
!= display
) {
348 test
= glXQueryVersion(display
, &major
, &minor
);
349 gl_info
->glx_version
= ((major
& 0x0000FFFF) << 16) | (minor
& 0x0000FFFF);
351 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
353 gl_string
= (const char *) glGetString(GL_VENDOR
);
355 TRACE_(d3d_caps
)("Filling vendor string %s\n", gl_string
);
356 if (gl_string
!= NULL
) {
357 /* Fill in the GL vendor */
358 if (strstr(gl_string
, "NVIDIA")) {
359 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
360 } else if (strstr(gl_string
, "ATI")) {
361 gl_info
->gl_vendor
= VENDOR_ATI
;
362 } else if (strstr(gl_string
, "Intel(R)") ||
363 strstr(gl_info
->gl_renderer
, "Intel(R)")) {
364 gl_info
->gl_vendor
= VENDOR_INTEL
;
365 } else if (strstr(gl_string
, "Mesa")) {
366 gl_info
->gl_vendor
= VENDOR_MESA
;
368 gl_info
->gl_vendor
= VENDOR_WINE
;
371 gl_info
->gl_vendor
= VENDOR_WINE
;
375 TRACE_(d3d_caps
)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string
), gl_info
->gl_vendor
);
377 /* Parse the GL_VERSION field into major and minor information */
378 gl_string
= (const char *) glGetString(GL_VERSION
);
379 if (gl_string
!= NULL
) {
381 switch (gl_info
->gl_vendor
) {
383 gl_string_cursor
= strstr(gl_string
, "NVIDIA");
384 if (!gl_string_cursor
) {
385 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
389 gl_string_cursor
= strstr(gl_string_cursor
, " ");
390 if (!gl_string_cursor
) {
391 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
395 while (*gl_string_cursor
== ' ') {
399 if (!*gl_string_cursor
) {
400 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
404 major
= atoi(gl_string_cursor
);
405 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
409 if (*gl_string_cursor
++ != '.') {
410 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
414 minor
= atoi(gl_string_cursor
);
415 minor
= major
*100+minor
;
422 gl_string_cursor
= strchr(gl_string
, '-');
423 if (gl_string_cursor
) {
427 /* Check if version number is of the form x.y.z */
428 if (*gl_string_cursor
> '9' && *gl_string_cursor
< '0')
430 if (!error
&& *(gl_string_cursor
+2) > '9' && *(gl_string_cursor
+2) < '0')
432 if (!error
&& *(gl_string_cursor
+4) > '9' && *(gl_string_cursor
+4) < '0')
434 if (!error
&& *(gl_string_cursor
+1) != '.' && *(gl_string_cursor
+3) != '.')
437 /* Mark version number as malformed */
439 gl_string_cursor
= 0;
442 if (!gl_string_cursor
)
443 WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
445 major
= *gl_string_cursor
- '0';
446 minor
= (*(gl_string_cursor
+2) - '0') * 256 + (*(gl_string_cursor
+4) - '0');
452 gl_string_cursor
= strstr(gl_string
, "Mesa");
453 gl_string_cursor
= strstr(gl_string_cursor
, " ");
454 while (*gl_string_cursor
&& ' ' == *gl_string_cursor
) ++gl_string_cursor
;
455 if (*gl_string_cursor
) {
459 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
460 tmp
[cursor
++] = *gl_string_cursor
;
466 if (*gl_string_cursor
!= '.') WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
470 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
471 tmp
[cursor
++] = *gl_string_cursor
;
483 gl_info
->gl_driver_version
= MAKEDWORD_VERSION(major
, minor
);
484 TRACE_(d3d_caps
)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string
), major
, minor
, gl_info
->gl_driver_version
);
487 TRACE_(d3d_caps
)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info
->gl_renderer
), gl_info
->gl_card
);
490 * Initialize openGL extension related variables
491 * with Default values
493 memset(&gl_info
->supported
, 0, sizeof(gl_info
->supported
));
494 gl_info
->max_buffers
= 1;
495 gl_info
->max_textures
= 1;
496 gl_info
->max_texture_stages
= 1;
497 gl_info
->max_samplers
= 1;
498 gl_info
->max_sampler_stages
= 1;
499 gl_info
->ps_arb_version
= PS_VERSION_NOT_SUPPORTED
;
500 gl_info
->ps_arb_max_temps
= 0;
501 gl_info
->ps_arb_max_instructions
= 0;
502 gl_info
->vs_arb_version
= VS_VERSION_NOT_SUPPORTED
;
503 gl_info
->vs_arb_max_temps
= 0;
504 gl_info
->vs_arb_max_instructions
= 0;
505 gl_info
->vs_nv_version
= VS_VERSION_NOT_SUPPORTED
;
506 gl_info
->vs_ati_version
= VS_VERSION_NOT_SUPPORTED
;
507 gl_info
->vs_glsl_constantsF
= 0;
508 gl_info
->ps_glsl_constantsF
= 0;
509 gl_info
->vs_arb_constantsF
= 0;
510 gl_info
->ps_arb_constantsF
= 0;
512 /* Now work out what GL support this card really has */
513 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
518 /* Retrieve opengl defaults */
519 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
520 gl_info
->max_clipplanes
= min(WINED3DMAXUSERCLIPPLANES
, gl_max
);
521 TRACE_(d3d_caps
)("ClipPlanes support - num Planes=%d\n", gl_max
);
523 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
524 gl_info
->max_lights
= gl_max
;
525 TRACE_(d3d_caps
)("Lights support - max lights=%d\n", gl_max
);
527 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &gl_max
);
528 gl_info
->max_texture_size
= gl_max
;
529 TRACE_(d3d_caps
)("Maximum texture size support - max texture size=%d\n", gl_max
);
531 glGetFloatv(GL_POINT_SIZE_RANGE
, gl_floatv
);
532 gl_info
->max_pointsize
= gl_floatv
[1];
533 TRACE_(d3d_caps
)("Maximum point size support - max point size=%f\n", gl_floatv
[1]);
535 glGetIntegerv(GL_AUX_BUFFERS
, &gl_max
);
536 gl_info
->max_aux_buffers
= gl_max
;
537 TRACE_(d3d_caps
)("Offscreen rendering support - number of aux buffers=%d\n", gl_max
);
539 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
540 GL_Extensions
= (const char *) glGetString(GL_EXTENSIONS
);
541 TRACE_(d3d_caps
)("GL_Extensions reported:\n");
543 if (NULL
== GL_Extensions
) {
544 ERR(" GL_Extensions returns NULL\n");
546 while (*GL_Extensions
!= 0x00) {
547 const char *Start
= GL_Extensions
;
550 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
551 while (*GL_Extensions
!= ' ' && *GL_Extensions
!= 0x00) {
554 memcpy(ThisExtn
, Start
, (GL_Extensions
- Start
));
555 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
560 if (strcmp(ThisExtn
, "GL_ARB_draw_buffers") == 0) {
561 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB
, &gl_max
);
562 TRACE_(d3d_caps
)(" FOUND: ARB_draw_buffers support - max buffers=%u\n", gl_max
);
563 gl_info
->supported
[ARB_DRAW_BUFFERS
] = TRUE
;
564 gl_info
->max_buffers
= gl_max
;
565 } else if (strcmp(ThisExtn
, "GL_ARB_fragment_program") == 0) {
566 gl_info
->ps_arb_version
= PS_VERSION_11
;
567 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info
->ps_arb_version
);
568 gl_info
->supported
[ARB_FRAGMENT_PROGRAM
] = TRUE
;
569 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB
, &gl_max
);
570 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max
);
571 gl_info
->max_samplers
= min(MAX_SAMPLERS
, gl_max
);
572 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
573 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max
);
574 gl_info
->ps_arb_constantsF
= gl_max
;
575 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
576 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max
);
577 gl_info
->ps_arb_max_temps
= gl_max
;
578 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
579 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max
);
580 gl_info
->ps_arb_max_instructions
= gl_max
;
581 } else if (strcmp(ThisExtn
, "GL_ARB_fragment_shader") == 0) {
582 gl_info
->supported
[ARB_FRAGMENT_SHADER
] = TRUE
;
583 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB
, &gl_max
);
585 TRACE_(d3d_caps
)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max
);
586 gl_info
->ps_glsl_constantsF
= gl_max
;
587 } else if (strcmp(ThisExtn
, "GL_ARB_imaging") == 0) {
588 TRACE_(d3d_caps
)(" FOUND: ARB imaging support\n");
589 gl_info
->supported
[ARB_IMAGING
] = TRUE
;
590 } else if (strcmp(ThisExtn
, "GL_ARB_multisample") == 0) {
591 TRACE_(d3d_caps
)(" FOUND: ARB Multisample support\n");
592 gl_info
->supported
[ARB_MULTISAMPLE
] = TRUE
;
593 } else if (strcmp(ThisExtn
, "GL_ARB_multitexture") == 0) {
594 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
595 TRACE_(d3d_caps
)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max
);
596 gl_info
->supported
[ARB_MULTITEXTURE
] = TRUE
;
597 gl_info
->max_textures
= min(MAX_TEXTURES
, gl_max
);
598 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
599 gl_info
->max_samplers
= max(gl_info
->max_samplers
, gl_max
);
600 } else if (strcmp(ThisExtn
, "GL_ARB_texture_cube_map") == 0) {
601 TRACE_(d3d_caps
)(" FOUND: ARB Texture Cube Map support\n");
602 gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
] = TRUE
;
603 TRACE_(d3d_caps
)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
604 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
605 } else if (strcmp(ThisExtn
, "GL_ARB_texture_compression") == 0) {
606 TRACE_(d3d_caps
)(" FOUND: ARB Texture Compression support\n");
607 gl_info
->supported
[ARB_TEXTURE_COMPRESSION
] = TRUE
;
608 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_add") == 0) {
609 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env Add support\n");
610 gl_info
->supported
[ARB_TEXTURE_ENV_ADD
] = TRUE
;
611 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_combine") == 0) {
612 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env combine support\n");
613 gl_info
->supported
[ARB_TEXTURE_ENV_COMBINE
] = TRUE
;
614 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_dot3") == 0) {
615 TRACE_(d3d_caps
)(" FOUND: ARB Dot3 support\n");
616 gl_info
->supported
[ARB_TEXTURE_ENV_DOT3
] = TRUE
;
617 } else if (strcmp(ThisExtn
, "GL_ARB_texture_float") == 0) {
618 TRACE_(d3d_caps
)(" FOUND: ARB Float texture support\n");
619 gl_info
->supported
[ARB_TEXTURE_FLOAT
] = TRUE
;
620 } else if (strcmp(ThisExtn
, "GL_ARB_half_float_pixel") == 0) {
621 TRACE_(d3d_caps
)(" FOUND: ARB Half-float pixel support\n");
622 gl_info
->supported
[ARB_HALF_FLOAT_PIXEL
] = TRUE
;
623 } else if (strcmp(ThisExtn
, "GL_ARB_texture_border_clamp") == 0) {
624 TRACE_(d3d_caps
)(" FOUND: ARB Texture border clamp support\n");
625 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] = TRUE
;
626 } else if (strcmp(ThisExtn
, "GL_ARB_texture_mirrored_repeat") == 0) {
627 TRACE_(d3d_caps
)(" FOUND: ARB Texture mirrored repeat support\n");
628 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] = TRUE
;
629 } else if (strcmp(ThisExtn
, "GL_ARB_texture_non_power_of_two") == 0) {
630 TRACE_(d3d_caps
)(" FOUND: ARB NPOT texture support\n");
631 gl_info
->supported
[ARB_TEXTURE_NON_POWER_OF_TWO
] = TRUE
;
632 } else if (strcmp(ThisExtn
, "GLX_ARB_multisample") == 0) {
633 TRACE_(d3d_caps
)(" FOUND: ARB multisample support\n");
634 gl_info
->supported
[ARB_MULTISAMPLE
] = TRUE
;
635 } else if (strcmp(ThisExtn
, "GL_ARB_pixel_buffer_object") == 0) {
636 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Buffer support\n");
637 gl_info
->supported
[ARB_PIXEL_BUFFER_OBJECT
] = TRUE
;
638 } else if (strcmp(ThisExtn
, "GL_ARB_point_sprite") == 0) {
639 TRACE_(d3d_caps
)(" FOUND: ARB point sprite support\n");
640 gl_info
->supported
[ARB_POINT_SPRITE
] = TRUE
;
641 } else if (strstr(ThisExtn
, "GL_ARB_vertex_program")) {
642 gl_info
->vs_arb_version
= VS_VERSION_11
;
643 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info
->vs_arb_version
);
644 gl_info
->supported
[ARB_VERTEX_PROGRAM
] = TRUE
;
645 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
646 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max
);
647 gl_info
->vs_arb_constantsF
= gl_max
;
648 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
649 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max
);
650 gl_info
->vs_arb_max_temps
= gl_max
;
651 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
652 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max
);
653 gl_info
->vs_arb_max_instructions
= gl_max
;
654 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_shader") == 0) {
655 gl_info
->supported
[ARB_VERTEX_SHADER
] = TRUE
;
656 glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB
, &gl_max
);
658 TRACE_(d3d_caps
)(" FOUND: ARB_vertex_shader (GLSL) support - max float vs constants=%u\n", gl_max
);
659 gl_info
->vs_glsl_constantsF
= gl_max
;
660 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_blend") == 0) {
661 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB
, &gl_max
);
662 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Blend support GL_MAX_VERTEX_UNITS_ARB %d\n", gl_max
);
663 gl_info
->max_blends
= gl_max
;
664 gl_info
->supported
[ARB_VERTEX_BLEND
] = TRUE
;
665 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_buffer_object") == 0) {
666 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Buffer support\n");
667 gl_info
->supported
[ARB_VERTEX_BUFFER_OBJECT
] = TRUE
;
668 } else if (strcmp(ThisExtn
, "GL_ARB_occlusion_query") == 0) {
669 TRACE_(d3d_caps
)(" FOUND: ARB Occlusion Query support\n");
670 gl_info
->supported
[ARB_OCCLUSION_QUERY
] = TRUE
;
671 } else if (strcmp(ThisExtn
, "GL_ARB_point_parameters") == 0) {
672 TRACE_(d3d_caps
)(" FOUND: ARB Point parameters support\n");
673 gl_info
->supported
[ARB_POINT_PARAMETERS
] = TRUE
;
677 } else if (strcmp(ThisExtn
, "GL_EXT_fog_coord") == 0) {
678 TRACE_(d3d_caps
)(" FOUND: EXT Fog coord support\n");
679 gl_info
->supported
[EXT_FOG_COORD
] = TRUE
;
680 } else if (strcmp(ThisExtn
, "GL_EXT_framebuffer_object") == 0) {
681 TRACE_(d3d_caps
)(" FOUND: EXT Frame Buffer Object support\n");
682 gl_info
->supported
[EXT_FRAMEBUFFER_OBJECT
] = TRUE
;
683 } else if (strcmp(ThisExtn
, "GL_EXT_framebuffer_blit") == 0) {
684 TRACE_(d3d_caps
)(" FOUND: EXT Frame Buffer Blit support\n");
685 gl_info
->supported
[EXT_FRAMEBUFFER_BLIT
] = TRUE
;
686 } else if (strcmp(ThisExtn
, "GL_EXT_blend_minmax") == 0) {
687 TRACE_(d3d_caps
)(" FOUND: EXT Blend minmax support\n");
688 gl_info
->supported
[EXT_BLEND_MINMAX
] = TRUE
;
689 } else if (strcmp(ThisExtn
, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
690 TRACE_(d3d_caps
)(" FOUND: EXT Paletted texture support\n");
691 gl_info
->supported
[EXT_PALETTED_TEXTURE
] = TRUE
;
692 } else if (strcmp(ThisExtn
, "GL_EXT_point_parameters") == 0) {
693 TRACE_(d3d_caps
)(" FOUND: EXT Point parameters support\n");
694 gl_info
->supported
[EXT_POINT_PARAMETERS
] = TRUE
;
695 } else if (strcmp(ThisExtn
, "GL_EXT_secondary_color") == 0) {
696 TRACE_(d3d_caps
)(" FOUND: EXT Secondary color support\n");
697 gl_info
->supported
[EXT_SECONDARY_COLOR
] = TRUE
;
698 } else if (strcmp(ThisExtn
, "GL_EXT_stencil_two_side") == 0) {
699 TRACE_(d3d_caps
)(" FOUND: EXT Stencil two side support\n");
700 gl_info
->supported
[EXT_STENCIL_TWO_SIDE
] = TRUE
;
701 } else if (strcmp(ThisExtn
, "GL_EXT_stencil_wrap") == 0) {
702 TRACE_(d3d_caps
)(" FOUND: EXT Stencil wrap support\n");
703 gl_info
->supported
[EXT_STENCIL_WRAP
] = TRUE
;
704 } else if (strcmp(ThisExtn
, "GL_EXT_texture3D") == 0) {
705 TRACE_(d3d_caps
)(" FOUND: EXT_texture3D support\n");
706 gl_info
->supported
[EXT_TEXTURE3D
] = TRUE
;
707 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT
, &gl_max
);
708 TRACE_(d3d_caps
)("Max texture3D size: %d\n", gl_max
);
709 gl_info
->max_texture3d_size
= gl_max
;
710 } else if (strcmp(ThisExtn
, "GL_EXT_texture_compression_s3tc") == 0) {
711 TRACE_(d3d_caps
)(" FOUND: EXT Texture S3TC compression support\n");
712 gl_info
->supported
[EXT_TEXTURE_COMPRESSION_S3TC
] = TRUE
;
713 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_add") == 0) {
714 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env Add support\n");
715 gl_info
->supported
[EXT_TEXTURE_ENV_ADD
] = TRUE
;
716 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_combine") == 0) {
717 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env combine support\n");
718 gl_info
->supported
[EXT_TEXTURE_ENV_COMBINE
] = TRUE
;
719 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_dot3") == 0) {
720 TRACE_(d3d_caps
)(" FOUND: EXT Dot3 support\n");
721 gl_info
->supported
[EXT_TEXTURE_ENV_DOT3
] = TRUE
;
722 } else if (strcmp(ThisExtn
, "GL_EXT_texture_sRGB") == 0) {
723 TRACE_(d3d_caps
)(" FOUND: EXT sRGB support\n");
724 gl_info
->supported
[EXT_TEXTURE_SRGB
] = TRUE
;
725 } else if (strcmp(ThisExtn
, "GL_EXT_texture_filter_anisotropic") == 0) {
726 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] = TRUE
;
727 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &gl_max
);
728 TRACE_(d3d_caps
)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max
);
729 gl_info
->max_anisotropy
= gl_max
;
730 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod") == 0) {
731 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD support\n");
732 gl_info
->supported
[EXT_TEXTURE_LOD
] = TRUE
;
733 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod_bias") == 0) {
734 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD bias support\n");
735 gl_info
->supported
[EXT_TEXTURE_LOD_BIAS
] = TRUE
;
736 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_weighting") == 0) {
737 TRACE_(d3d_caps
)(" FOUND: EXT Vertex weighting support\n");
738 gl_info
->supported
[EXT_VERTEX_WEIGHTING
] = TRUE
;
743 } else if (strstr(ThisExtn
, "GL_NV_fog_distance")) {
744 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Fog Distance support\n");
745 gl_info
->supported
[NV_FOG_DISTANCE
] = TRUE
;
746 } else if (strstr(ThisExtn
, "GL_NV_fragment_program")) {
747 gl_info
->ps_nv_version
= (strcmp(ThisExtn
, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30
: PS_VERSION_20
;
748 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info
->ps_nv_version
);
749 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners") == 0) {
750 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV
, &gl_max
);
751 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
752 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max
);
753 gl_info
->supported
[NV_REGISTER_COMBINERS
] = TRUE
;
754 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners2") == 0) {
755 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
756 gl_info
->supported
[NV_REGISTER_COMBINERS2
] = TRUE
;
757 } else if (strcmp(ThisExtn
, "GL_NV_texgen_reflection") == 0) {
758 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
759 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
760 } else if (strcmp(ThisExtn
, "GL_NV_texture_env_combine4") == 0) {
761 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
762 gl_info
->supported
[NV_TEXTURE_ENV_COMBINE4
] = TRUE
;
763 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader") == 0) {
764 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
765 gl_info
->supported
[NV_TEXTURE_SHADER
] = TRUE
;
766 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader2") == 0) {
767 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
768 gl_info
->supported
[NV_TEXTURE_SHADER2
] = TRUE
;
769 /* Prevent both extensions to be used at the same time. I don't expect them to play nice together */
770 gl_info
->supported
[ATI_ENVMAP_BUMPMAP
] = FALSE
;
771 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader3") == 0) {
772 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
773 gl_info
->supported
[NV_TEXTURE_SHADER3
] = TRUE
;
774 } else if (strcmp(ThisExtn
, "GL_NV_occlusion_query") == 0) {
775 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
776 gl_info
->supported
[NV_OCCLUSION_QUERY
] = TRUE
;
777 } else if (strstr(ThisExtn
, "GL_NV_vertex_program")) {
778 if(strcmp(ThisExtn
, "GL_NV_vertex_program3") == 0)
779 gl_info
->vs_nv_version
= VS_VERSION_30
;
780 else if(strcmp(ThisExtn
, "GL_NV_vertex_program2") == 0)
781 gl_info
->vs_nv_version
= VS_VERSION_20
;
782 else if(strcmp(ThisExtn
, "GL_NV_vertex_program1_1") == 0)
783 gl_info
->vs_nv_version
= VS_VERSION_11
;
785 gl_info
->vs_nv_version
= VS_VERSION_10
;
786 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info
->vs_nv_version
);
787 gl_info
->supported
[NV_VERTEX_PROGRAM
] = TRUE
;
788 } else if (strstr(ThisExtn
, "GL_NV_fence")) {
789 if(!gl_info
->supported
[APPLE_FENCE
]) {
790 gl_info
->supported
[NV_FENCE
] = TRUE
;
797 } else if (strcmp(ThisExtn
, "GL_ATI_separate_stencil") == 0) {
798 TRACE_(d3d_caps
)(" FOUND: ATI Separate stencil support\n");
799 gl_info
->supported
[ATI_SEPARATE_STENCIL
] = TRUE
;
800 } else if (strcmp(ThisExtn
, "GL_ATI_texture_env_combine3") == 0) {
801 TRACE_(d3d_caps
)(" FOUND: ATI Texture Env combine (3) support\n");
802 gl_info
->supported
[ATI_TEXTURE_ENV_COMBINE3
] = TRUE
;
803 } else if (strcmp(ThisExtn
, "GL_ATI_texture_mirror_once") == 0) {
804 TRACE_(d3d_caps
)(" FOUND: ATI Texture Mirror Once support\n");
805 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] = TRUE
;
806 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_shader") == 0) {
807 gl_info
->vs_ati_version
= VS_VERSION_11
;
808 TRACE_(d3d_caps
)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info
->vs_ati_version
);
809 gl_info
->supported
[EXT_VERTEX_SHADER
] = TRUE
;
810 } else if (strcmp(ThisExtn
, "GL_ATI_envmap_bumpmap") == 0) {
811 TRACE_(d3d_caps
)(" FOUND: ATI Environment Bump Mapping support\n");
812 /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
813 * Won't occur in any real world situation though
815 if(!gl_info
->supported
[NV_TEXTURE_SHADER2
]) {
816 gl_info
->supported
[ATI_ENVMAP_BUMPMAP
] = TRUE
;
821 } else if (strstr(ThisExtn
, "GL_APPLE_fence")) {
822 /* GL_NV_fence and GL_APPLE_fence provide the same functionality basically.
823 * The apple extension interacts with some other apple exts. Disable the NV
824 * extension if the apple one is support to prevent confusion in other parts
827 gl_info
->supported
[NV_FENCE
] = FALSE
;
828 gl_info
->supported
[APPLE_FENCE
] = TRUE
;
829 } else if (strstr(ThisExtn
, "GL_APPLE_client_storage")) {
830 gl_info
->supported
[APPLE_CLIENT_STORAGE
] = TRUE
;
833 if (*GL_Extensions
== ' ') GL_Extensions
++;
836 checkGLcall("extension detection\n");
838 /* In some cases the number of texture stages can be larger than the number
839 * of samplers. The GF4 for example can use only 2 samplers (no fragment
840 * shaders), but 8 texture stages (register combiners). */
841 gl_info
->max_sampler_stages
= max(gl_info
->max_samplers
, gl_info
->max_texture_stages
);
843 /* We can only use ORM_FBO when the hardware supports it. */
844 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
&& !gl_info
->supported
[EXT_FRAMEBUFFER_OBJECT
]) {
845 WARN_(d3d_caps
)("GL_EXT_framebuffer_object not supported, falling back to PBuffer offscreen rendering mode.\n");
846 wined3d_settings
.offscreen_rendering_mode
= ORM_PBUFFER
;
849 /* MRTs are currently only supported when FBOs are used. */
850 if (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) {
851 gl_info
->max_buffers
= 1;
854 /* Below is a list of Nvidia and ATI GPUs. Both vendors have dozens of different GPUs with roughly the same
855 * features. In most cases GPUs from a certain family differ in clockspeeds, the amount of video memory and
856 * in case of the latest videocards in the number of pixel/vertex pipelines.
858 * A Direct3D device object contains the PCI id (vendor + device) of the videocard which is used for
859 * rendering. Various games use this information to get a rough estimation of the features of the card
860 * and some might use it for enabling 3d effects only on certain types of videocards. In some cases
861 * games might even use it to work around bugs which happen on certain videocards/driver combinations.
862 * The problem is that OpenGL only exposes a rendering string containing the name of the videocard and
865 * Various games depend on the PCI id, so somehow we need to provide one. A simple option is to parse
866 * the renderer string and translate this to the right PCI id. This is a lot of work because there are more
867 * than 200 GPUs just for Nvidia. Various cards share the same renderer string, so the amount of code might
868 * be 'small' but there are quite a number of exceptions which would make this a pain to maintain.
869 * Another way would be to query the PCI id from the operating system (assuming this is the videocard which
870 * is used for rendering which is not always the case). This would work but it is not very portable. Second
871 * it would not work well in, let's say, a remote X situation in which the amount of 3d features which can be used
874 * As said most games only use the PCI id to get an indication of the capabilities of the card.
875 * It doesn't really matter if the given id is the correct one if we return the id of a card with
876 * similar 3d features.
878 * The code below checks the OpenGL capabilities of a videocard and matches that to a certain level of
879 * Direct3D functionality. Once a card passes the Direct3D9 check, we know that the card (in case of Nvidia)
880 * is at least a GeforceFX. To give a better estimate we do a basic check on the renderer string but if that
881 * won't pass we return a default card. This way is better than maintaining a full card database as even
882 * without a full database we can return a card with similar features. Second the size of the database
883 * can be made quite small because when you know what type of 3d functionality a card has, you know to which
884 * GPU family the GPU must belong. Because of this you only have to check a small part of the renderer string
885 * to distinguishes between different models from that family.
887 switch (gl_info
->gl_vendor
) {
889 /* Both the GeforceFX, 6xxx and 7xxx series support D3D9. The last two types have more
890 * shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
892 if(WINE_D3D9_CAPABLE(gl_info
) && (gl_info
->vs_nv_version
== VS_VERSION_30
)) {
893 if (strstr(gl_info
->gl_renderer
, "7800") ||
894 strstr(gl_info
->gl_renderer
, "7900") ||
895 strstr(gl_info
->gl_renderer
, "7950") ||
896 strstr(gl_info
->gl_renderer
, "Quadro FX 4") ||
897 strstr(gl_info
->gl_renderer
, "Quadro FX 5"))
898 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_7800GT
;
899 else if(strstr(gl_info
->gl_renderer
, "6800") ||
900 strstr(gl_info
->gl_renderer
, "7600"))
901 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6800
;
902 else if(strstr(gl_info
->gl_renderer
, "6600") ||
903 strstr(gl_info
->gl_renderer
, "6610") ||
904 strstr(gl_info
->gl_renderer
, "6700"))
905 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6600GT
;
907 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6200
; /* Geforce 6100/6150/6200/7300/7400 */
908 } else if(WINE_D3D9_CAPABLE(gl_info
)) {
909 if (strstr(gl_info
->gl_renderer
, "5800") ||
910 strstr(gl_info
->gl_renderer
, "5900") ||
911 strstr(gl_info
->gl_renderer
, "5950") ||
912 strstr(gl_info
->gl_renderer
, "Quadro FX"))
913 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5800
;
914 else if(strstr(gl_info
->gl_renderer
, "5600") ||
915 strstr(gl_info
->gl_renderer
, "5650") ||
916 strstr(gl_info
->gl_renderer
, "5700") ||
917 strstr(gl_info
->gl_renderer
, "5750"))
918 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
920 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5200
; /* GeforceFX 5100/5200/5250/5300/5500 */
921 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
922 if (strstr(gl_info
->gl_renderer
, "GeForce4 Ti") || strstr(gl_info
->gl_renderer
, "Quadro4"))
923 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4200
; /* Geforce4 Ti4200/Ti4400/Ti4600/Ti4800, Quadro4 */
925 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
; /* Geforce3 standard/Ti200/Ti500, Quadro DCC */
926 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
927 if (strstr(gl_info
->gl_renderer
, "GeForce4 MX"))
928 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_MX
; /* MX420/MX440/MX460/MX4000 */
929 else if(strstr(gl_info
->gl_renderer
, "GeForce2 MX") || strstr(gl_info
->gl_renderer
, "Quadro2 MXR"))
930 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2_MX
; /* Geforce2 standard/MX100/MX200/MX400, Quadro2 MXR */
931 else if(strstr(gl_info
->gl_renderer
, "GeForce2") || strstr(gl_info
->gl_renderer
, "Quadro2"))
932 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE2
; /* Geforce2 GTS/Pro/Ti/Ultra, Quadro2 */
934 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
; /* Geforce 256/DDR, Quadro */
936 if (strstr(gl_info
->gl_renderer
, "TNT2"))
937 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT2
; /* Riva TNT2 standard/M64/Pro/Ultra */
939 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
; /* Riva TNT, Vanta */
943 if(WINE_D3D9_CAPABLE(gl_info
)) {
945 if (strstr(gl_info
->gl_renderer
, "X1600") ||
946 strstr(gl_info
->gl_renderer
, "X1800") ||
947 strstr(gl_info
->gl_renderer
, "X1900") ||
948 strstr(gl_info
->gl_renderer
, "X1950"))
949 gl_info
->gl_card
= CARD_ATI_RADEON_X1600
;
950 /* Radeon R4xx + X1300/X1400 (lowend R5xx) */
951 else if(strstr(gl_info
->gl_renderer
, "X700") ||
952 strstr(gl_info
->gl_renderer
, "X800") ||
953 strstr(gl_info
->gl_renderer
, "X850") ||
954 strstr(gl_info
->gl_renderer
, "X1300") ||
955 strstr(gl_info
->gl_renderer
, "X1400"))
956 gl_info
->gl_card
= CARD_ATI_RADEON_X700
;
959 gl_info
->gl_card
= CARD_ATI_RADEON_9500
; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
960 } else if(WINE_D3D8_CAPABLE(gl_info
)) {
961 gl_info
->gl_card
= CARD_ATI_RADEON_8500
; /* Radeon 8500/9000/9100/9200/9300 */
962 } else if(WINE_D3D7_CAPABLE(gl_info
)) {
963 gl_info
->gl_card
= CARD_ATI_RADEON_7200
; /* Radeon 7000/7100/7200/7500 */
965 gl_info
->gl_card
= CARD_ATI_RAGE_128PRO
;
968 if (strstr(gl_info
->gl_renderer
, "915GM")) {
969 gl_info
->gl_card
= CARD_INTEL_I915GM
;
970 } else if (strstr(gl_info
->gl_renderer
, "915G")) {
971 gl_info
->gl_card
= CARD_INTEL_I915G
;
972 } else if (strstr(gl_info
->gl_renderer
, "865G")) {
973 gl_info
->gl_card
= CARD_INTEL_I865G
;
974 } else if (strstr(gl_info
->gl_renderer
, "855G")) {
975 gl_info
->gl_card
= CARD_INTEL_I855G
;
976 } else if (strstr(gl_info
->gl_renderer
, "830G")) {
977 gl_info
->gl_card
= CARD_INTEL_I830G
;
979 gl_info
->gl_card
= CARD_INTEL_I915G
;
985 /* Default to generic Nvidia hardware based on the supported OpenGL extensions. The choice
986 * for Nvidia was because the hardware and drivers they make are of good quality. This makes
987 * them a good generic choice.
989 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
990 if(WINE_D3D9_CAPABLE(gl_info
))
991 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5600
;
992 else if(WINE_D3D8_CAPABLE(gl_info
))
993 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE3
;
994 else if(WINE_D3D7_CAPABLE(gl_info
))
995 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE
;
996 else if(WINE_D3D6_CAPABLE(gl_info
))
997 gl_info
->gl_card
= CARD_NVIDIA_RIVA_TNT
;
999 gl_info
->gl_card
= CARD_NVIDIA_RIVA_128
;
1001 TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info
->gl_vendor
, gl_info
->gl_card
);
1003 /* Load all the lookup tables
1004 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
1005 minLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_WRAP
;
1006 maxLookup
[WINELOOKUP_WARPPARAM
] = WINED3DTADDRESS_MIRRORONCE
;
1008 minLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_NONE
;
1009 maxLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_ANISOTROPIC
;
1012 for (i
= 0; i
< MAX_LOOKUPS
; i
++) {
1013 stateLookup
[i
] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup
[i
]) * (1 + maxLookup
[i
] - minLookup
[i
]) );
1016 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_WRAP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_REPEAT
;
1017 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_CLAMP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_CLAMP_TO_EDGE
;
1018 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1019 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
1020 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1021 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
1022 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRROR
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1023 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] ? GL_MIRRORED_REPEAT_ARB
: GL_REPEAT
;
1024 stateLookup
[WINELOOKUP_WARPPARAM
][WINED3DTADDRESS_MIRRORONCE
- minLookup
[WINELOOKUP_WARPPARAM
]] =
1025 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] ? GL_MIRROR_CLAMP_TO_EDGE_ATI
: GL_REPEAT
;
1027 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_NONE
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
1028 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_POINT
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
1029 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_LINEAR
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_LINEAR
;
1030 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_ANISOTROPIC
- minLookup
[WINELOOKUP_MAGFILTER
]] =
1031 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR
: GL_NEAREST
;
1034 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_NONE
] = GL_LINEAR
;
1035 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_POINT
] = GL_LINEAR
;
1036 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_LINEAR
] = GL_LINEAR
;
1037 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_NONE
] = GL_NEAREST
;
1038 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_POINT
] = GL_NEAREST_MIPMAP_NEAREST
;
1039 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_LINEAR
] = GL_NEAREST_MIPMAP_LINEAR
;
1040 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_NONE
] = GL_LINEAR
;
1041 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_POINT
] = GL_LINEAR_MIPMAP_NEAREST
;
1042 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_LINEAR
] = GL_LINEAR_MIPMAP_LINEAR
;
1043 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_NONE
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ?
1044 GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
1045 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_POINT
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_NEAREST
: GL_LINEAR
;
1046 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_LINEAR
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
1048 /* TODO: config lookups */
1050 if (display
!= NULL
) {
1051 GLX_Extensions
= glXQueryExtensionsString(display
, DefaultScreen(display
));
1052 TRACE_(d3d_caps
)("GLX_Extensions reported:\n");
1054 if (NULL
== GLX_Extensions
) {
1055 ERR(" GLX_Extensions returns NULL\n");
1057 while (*GLX_Extensions
!= 0x00) {
1058 const char *Start
= GLX_Extensions
;
1061 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
1062 while (*GLX_Extensions
!= ' ' && *GLX_Extensions
!= 0x00) {
1065 memcpy(ThisExtn
, Start
, (GLX_Extensions
- Start
));
1066 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
1067 if (strstr(ThisExtn
, "GLX_SGI_video_sync")) {
1068 gl_info
->supported
[SGI_VIDEO_SYNC
] = TRUE
;
1071 if (*GLX_Extensions
== ' ') GLX_Extensions
++;
1077 WineD3D_ReleaseFakeGLContext();
1078 return return_value
;
1080 #undef GLINFO_LOCATION
1082 /**********************************************************
1083 * IWineD3D implementation follows
1084 **********************************************************/
1086 static UINT WINAPI
IWineD3DImpl_GetAdapterCount (IWineD3D
*iface
) {
1087 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1089 TRACE_(d3d_caps
)("(%p): Reporting %d adapters\n", This
, numAdapters
);
1093 static HRESULT WINAPI
IWineD3DImpl_RegisterSoftwareDevice(IWineD3D
*iface
, void* pInitializeFunction
) {
1094 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1095 FIXME("(%p)->(%p): stub\n", This
, pInitializeFunction
);
1099 static HMONITOR WINAPI
IWineD3DImpl_GetAdapterMonitor(IWineD3D
*iface
, UINT Adapter
) {
1100 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1102 if (Adapter
>= IWineD3DImpl_GetAdapterCount(iface
)) {
1106 TRACE_(d3d_caps
)("(%p)->(%d)\n", This
, Adapter
);
1107 return MonitorFromPoint(Adapters
[Adapter
].monitorPoint
, MONITOR_DEFAULTTOPRIMARY
);
1110 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
1111 of the same bpp but different resolutions */
1113 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1114 static UINT WINAPI
IWineD3DImpl_GetAdapterModeCount(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
) {
1115 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1116 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Format: %s)\n", This
, Adapter
, debug_d3dformat(Format
));
1118 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1122 /* TODO: Store modes per adapter and read it from the adapter structure */
1123 if (Adapter
== 0) { /* Display */
1127 if (!DEBUG_SINGLE_MODE
) {
1130 while (EnumDisplaySettingsExW(NULL
, j
, &DevModeW
, 0)) {
1134 case WINED3DFMT_UNKNOWN
:
1135 /* This is for D3D8, do not enumerate P8 here */
1136 if (DevModeW
.dmBitsPerPel
== 32 ||
1137 DevModeW
.dmBitsPerPel
== 16) i
++;
1139 case WINED3DFMT_X8R8G8B8
:
1140 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1142 case WINED3DFMT_R5G6B5
:
1143 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1146 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1149 /* Skip other modes as they do not match the requested format */
1158 TRACE_(d3d_caps
)("(%p}->(Adapter: %d) => %d (out of %d)\n", This
, Adapter
, i
, j
);
1161 FIXME_(d3d_caps
)("Adapter not primary display\n");
1166 /* Note: dx9 supplies a format. Calls from d3d8 supply WINED3DFMT_UNKNOWN */
1167 static HRESULT WINAPI
IWineD3DImpl_EnumAdapterModes(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
, UINT Mode
, WINED3DDISPLAYMODE
* pMode
) {
1168 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1169 TRACE_(d3d_caps
)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This
, Adapter
, Mode
, pMode
, debug_d3dformat(Format
));
1171 /* Validate the parameters as much as possible */
1172 if (NULL
== pMode
||
1173 Adapter
>= IWineD3DImpl_GetAdapterCount(iface
) ||
1174 Mode
>= IWineD3DImpl_GetAdapterModeCount(iface
, Adapter
, Format
)) {
1175 return WINED3DERR_INVALIDCALL
;
1178 /* TODO: Store modes per adapter and read it from the adapter structure */
1179 if (Adapter
== 0 && !DEBUG_SINGLE_MODE
) { /* Display */
1185 /* If we are filtering to a specific format (D3D9), then need to skip
1186 all unrelated modes, but if mode is irrelevant (D3D8), then we can
1187 just count through the ones with valid bit depths */
1188 while ((i
<=Mode
) && EnumDisplaySettingsExW(NULL
, j
++, &DevModeW
, 0)) {
1191 case WINED3DFMT_UNKNOWN
:
1192 /* This is D3D8. Do not enumerate P8 here */
1193 if (DevModeW
.dmBitsPerPel
== 32 ||
1194 DevModeW
.dmBitsPerPel
== 16) i
++;
1196 case WINED3DFMT_X8R8G8B8
:
1197 if (DevModeW
.dmBitsPerPel
== 32) i
++;
1199 case WINED3DFMT_R5G6B5
:
1200 if (DevModeW
.dmBitsPerPel
== 16) i
++;
1203 if (DevModeW
.dmBitsPerPel
== 8) i
++;
1206 /* Modes that don't match what we support can get an early-out */
1207 TRACE_(d3d_caps
)("Searching for %s, returning D3DERR_INVALIDCALL\n", debug_d3dformat(Format
));
1208 return WINED3DERR_INVALIDCALL
;
1213 TRACE_(d3d_caps
)("No modes found for format (%x - %s)\n", Format
, debug_d3dformat(Format
));
1214 return WINED3DERR_INVALIDCALL
;
1218 /* Now get the display mode via the calculated index */
1219 if (EnumDisplaySettingsExW(NULL
, ModeIdx
, &DevModeW
, 0)) {
1220 pMode
->Width
= DevModeW
.dmPelsWidth
;
1221 pMode
->Height
= DevModeW
.dmPelsHeight
;
1222 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1223 if (DevModeW
.dmFields
& DM_DISPLAYFREQUENCY
)
1224 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1226 if (Format
== WINED3DFMT_UNKNOWN
)
1228 switch (DevModeW
.dmBitsPerPel
)
1231 pMode
->Format
= WINED3DFMT_P8
;
1234 pMode
->Format
= WINED3DFMT_R5G6B5
;
1237 pMode
->Format
= WINED3DFMT_X8R8G8B8
;
1240 pMode
->Format
= WINED3DFMT_UNKNOWN
;
1241 ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW
.dmBitsPerPel
);
1244 pMode
->Format
= Format
;
1247 TRACE_(d3d_caps
)("Requested mode out of range %d\n", Mode
);
1248 return WINED3DERR_INVALIDCALL
;
1251 TRACE_(d3d_caps
)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode
->Width
, pMode
->Height
,
1252 pMode
->RefreshRate
, pMode
->Format
, debug_d3dformat(pMode
->Format
),
1253 DevModeW
.dmBitsPerPel
);
1255 } else if (DEBUG_SINGLE_MODE
) {
1256 /* Return one setting of the format requested */
1257 if (Mode
> 0) return WINED3DERR_INVALIDCALL
;
1259 pMode
->Height
= 600;
1260 pMode
->RefreshRate
= 60;
1261 pMode
->Format
= (Format
== WINED3DFMT_UNKNOWN
) ? WINED3DFMT_X8R8G8B8
: Format
;
1263 FIXME_(d3d_caps
)("Adapter not primary display\n");
1269 static HRESULT WINAPI
IWineD3DImpl_GetAdapterDisplayMode(IWineD3D
*iface
, UINT Adapter
, WINED3DDISPLAYMODE
* pMode
) {
1270 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1271 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, pMode: %p)\n", This
, Adapter
, pMode
);
1273 if (NULL
== pMode
||
1274 Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1275 return WINED3DERR_INVALIDCALL
;
1278 if (Adapter
== 0) { /* Display */
1282 EnumDisplaySettingsExW(NULL
, (DWORD
)-1, &DevModeW
, 0);
1283 pMode
->Width
= DevModeW
.dmPelsWidth
;
1284 pMode
->Height
= DevModeW
.dmPelsHeight
;
1285 bpp
= DevModeW
.dmBitsPerPel
;
1286 pMode
->RefreshRate
= WINED3DADAPTER_DEFAULT
;
1287 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
1289 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1293 case 8: pMode
->Format
= WINED3DFMT_R3G3B2
; break;
1294 case 16: pMode
->Format
= WINED3DFMT_R5G6B5
; break;
1295 case 24: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* Robots needs 24bit to be X8R8G8B8 */
1296 case 32: pMode
->Format
= WINED3DFMT_X8R8G8B8
; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1297 default: pMode
->Format
= WINED3DFMT_UNKNOWN
;
1301 FIXME_(d3d_caps
)("Adapter not primary display\n");
1304 TRACE_(d3d_caps
)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode
->Width
,
1305 pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1309 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1310 and fields being inserted in the middle, a new structure is used in place */
1311 static HRESULT WINAPI
IWineD3DImpl_GetAdapterIdentifier(IWineD3D
*iface
, UINT Adapter
, DWORD Flags
,
1312 WINED3DADAPTER_IDENTIFIER
* pIdentifier
) {
1313 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1315 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Flags: %x, pId=%p)\n", This
, Adapter
, Flags
, pIdentifier
);
1317 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1318 return WINED3DERR_INVALIDCALL
;
1321 /* Return the information requested */
1322 TRACE_(d3d_caps
)("device/Vendor Name and Version detection using FillGLCaps\n");
1323 strcpy(pIdentifier
->Driver
, Adapters
[Adapter
].driver
);
1324 strcpy(pIdentifier
->Description
, Adapters
[Adapter
].description
);
1326 /* Note dx8 doesn't supply a DeviceName */
1327 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1328 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1329 pIdentifier
->DriverVersion
->u
.HighPart
= MAKEDWORD_VERSION(6, 14);
1330 pIdentifier
->DriverVersion
->u
.LowPart
= Adapters
[Adapter
].gl_info
.gl_driver_version
;
1331 *(pIdentifier
->VendorId
) = Adapters
[Adapter
].gl_info
.gl_vendor
;
1332 *(pIdentifier
->DeviceId
) = Adapters
[Adapter
].gl_info
.gl_card
;
1333 *(pIdentifier
->SubSysId
) = 0;
1334 *(pIdentifier
->Revision
) = 0;
1336 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1337 if (Flags
& WINED3DENUM_NO_WHQL_LEVEL
) {
1338 *(pIdentifier
->WHQLLevel
) = 0;
1340 *(pIdentifier
->WHQLLevel
) = 1;
1346 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Display
*display
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
1347 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1349 int rb
, gb
, bb
, ab
, type
, buf_sz
;
1351 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_RED_SIZE
, &rb
);
1352 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_GREEN_SIZE
, &gb
);
1353 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_BLUE_SIZE
, &bb
);
1354 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_ALPHA_SIZE
, &ab
);
1355 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_RENDER_TYPE
, &type
);
1356 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_BUFFER_SIZE
, &buf_sz
);
1359 case WINED3DFMT_X8R8G8B8
:
1360 case WINED3DFMT_R8G8B8
:
1361 if (8 == rb
&& 8 == gb
&& 8 == bb
) return TRUE
;
1363 case WINED3DFMT_A8R8G8B8
:
1364 if (8 == rb
&& 8 == gb
&& 8 == bb
&& 8 == ab
) return TRUE
;
1366 case WINED3DFMT_A2R10G10B10
:
1367 if (10 == rb
&& 10 == gb
&& 10 == bb
&& 2 == ab
) return TRUE
;
1369 case WINED3DFMT_X1R5G5B5
:
1370 if (5 == rb
&& 5 == gb
&& 5 == bb
) return TRUE
;
1372 case WINED3DFMT_A1R5G5B5
:
1373 if (5 == rb
&& 5 == gb
&& 5 == bb
&& 1 == ab
) return TRUE
;
1375 case WINED3DFMT_X4R4G4B4
:
1376 if (16 == buf_sz
&& 4 == rb
&& 4 == gb
&& 4 == bb
) return TRUE
;
1378 case WINED3DFMT_R5G6B5
:
1379 if (5 == rb
&& 6 == gb
&& 5 == bb
) return TRUE
;
1381 case WINED3DFMT_R3G3B2
:
1382 if (3 == rb
&& 3 == gb
&& 2 == bb
) return TRUE
;
1384 case WINED3DFMT_A8P8
:
1385 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
&& 8 == ab
) return TRUE
;
1388 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
) return TRUE
;
1394 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1396 case WINED3DFMT_X8R8G8B8
:
1397 case WINED3DFMT_R8G8B8
:
1398 case WINED3DFMT_A8R8G8B8
:
1399 case WINED3DFMT_A2R10G10B10
:
1400 case WINED3DFMT_X1R5G5B5
:
1401 case WINED3DFMT_A1R5G5B5
:
1402 case WINED3DFMT_R5G6B5
:
1403 case WINED3DFMT_R3G3B2
:
1404 case WINED3DFMT_A8P8
:
1414 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Display
*display
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
1415 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1419 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_DEPTH_SIZE
, &db
);
1420 gl_test
= glXGetFBConfigAttrib(display
, cfgs
, GLX_STENCIL_SIZE
, &sb
);
1423 case WINED3DFMT_D16
:
1424 case WINED3DFMT_D16_LOCKABLE
:
1425 if (16 == db
) return TRUE
;
1427 case WINED3DFMT_D32
:
1428 if (32 == db
) return TRUE
;
1430 case WINED3DFMT_D15S1
:
1431 if (15 == db
) return TRUE
;
1433 case WINED3DFMT_D24S8
:
1434 if (24 == db
&& 8 == sb
) return TRUE
;
1436 case WINED3DFMT_D24FS8
:
1437 if (24 == db
&& 8 == sb
) return TRUE
;
1439 case WINED3DFMT_D24X8
:
1440 if (24 == db
) return TRUE
;
1442 case WINED3DFMT_D24X4S4
:
1443 if (24 == db
&& 4 == sb
) return TRUE
;
1445 case WINED3DFMT_D32F_LOCKABLE
:
1446 if (32 == db
) return TRUE
;
1452 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1454 case WINED3DFMT_D16
:
1455 case WINED3DFMT_D16_LOCKABLE
:
1456 case WINED3DFMT_D32
:
1457 case WINED3DFMT_D15S1
:
1458 case WINED3DFMT_D24S8
:
1459 case WINED3DFMT_D24FS8
:
1460 case WINED3DFMT_D24X8
:
1461 case WINED3DFMT_D24X4S4
:
1462 case WINED3DFMT_D32F_LOCKABLE
:
1471 static HRESULT WINAPI
IWineD3DImpl_CheckDepthStencilMatch(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1472 WINED3DFORMAT AdapterFormat
,
1473 WINED3DFORMAT RenderTargetFormat
,
1474 WINED3DFORMAT DepthStencilFormat
) {
1475 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1478 WARN_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1480 DeviceType
, debug_d3ddevicetype(DeviceType
),
1481 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1482 RenderTargetFormat
, debug_d3dformat(RenderTargetFormat
),
1483 DepthStencilFormat
, debug_d3dformat(DepthStencilFormat
));
1485 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1486 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This
, Adapter
, IWineD3D_GetAdapterCount(iface
));
1487 return WINED3DERR_INVALIDCALL
;
1490 for (it
= 0; it
< Adapters
[Adapter
].nCfgs
; ++it
) {
1491 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(Adapters
[Adapter
].display
, Adapters
[Adapter
].cfgs
[it
], RenderTargetFormat
)) {
1492 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(Adapters
[Adapter
].display
, Adapters
[Adapter
].cfgs
[it
], DepthStencilFormat
)) {
1493 TRACE_(d3d_caps
)("(%p) : Formats matched\n", This
);
1498 WARN_(d3d_caps
)("unsupported format pair: %s and %s\n", debug_d3dformat(RenderTargetFormat
), debug_d3dformat(DepthStencilFormat
));
1500 return WINED3DERR_NOTAVAILABLE
;
1503 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1504 WINED3DFORMAT SurfaceFormat
,
1505 BOOL Windowed
, WINED3DMULTISAMPLE_TYPE MultiSampleType
, DWORD
* pQualityLevels
) {
1507 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1508 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1511 DeviceType
, debug_d3ddevicetype(DeviceType
),
1512 SurfaceFormat
, debug_d3dformat(SurfaceFormat
),
1517 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1518 return WINED3DERR_INVALIDCALL
;
1521 /* TODO: Store in Adapter structure */
1522 if (pQualityLevels
!= NULL
) {
1523 static int s_single_shot
= 0;
1524 if (!s_single_shot
) {
1525 FIXME("Quality levels unsupported at present\n");
1528 *pQualityLevels
= 1; /* Guess at a value! */
1531 if (WINED3DMULTISAMPLE_NONE
== MultiSampleType
) return WINED3D_OK
;
1532 return WINED3DERR_NOTAVAILABLE
;
1535 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE CheckType
,
1536 WINED3DFORMAT DisplayFormat
, WINED3DFORMAT BackBufferFormat
, BOOL Windowed
) {
1538 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1539 GLXFBConfig
* cfgs
= NULL
;
1542 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1544 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1547 CheckType
, debug_d3ddevicetype(CheckType
),
1548 DisplayFormat
, debug_d3dformat(DisplayFormat
),
1549 BackBufferFormat
, debug_d3dformat(BackBufferFormat
),
1552 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1553 WARN_(d3d_caps
)("Adapter >= IWineD3D_GetAdapterCount(iface), returning WINED3DERR_INVALIDCALL\n");
1554 return WINED3DERR_INVALIDCALL
;
1557 /* TODO: Store in adapter structure */
1558 if (WineD3D_CreateFakeGLContext()) {
1559 cfgs
= glXGetFBConfigs(wined3d_fake_gl_context_display
, DefaultScreen(wined3d_fake_gl_context_display
), &nCfgs
);
1560 for (it
= 0; it
< nCfgs
; ++it
) {
1561 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(wined3d_fake_gl_context_display
, cfgs
[it
], DisplayFormat
)) {
1563 TRACE_(d3d_caps
)("OK\n");
1567 if(cfgs
) XFree(cfgs
);
1568 if(hr
!= WINED3D_OK
)
1569 ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat
));
1570 WineD3D_ReleaseFakeGLContext();
1573 if(hr
!= WINED3D_OK
)
1574 TRACE_(d3d_caps
)("returning something different from WINED3D_OK\n");
1579 #define GLINFO_LOCATION Adapters[Adapter].gl_info
1580 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormat(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1581 WINED3DFORMAT AdapterFormat
, DWORD Usage
, WINED3DRESOURCETYPE RType
, WINED3DFORMAT CheckFormat
) {
1582 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1583 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
1586 DeviceType
, debug_d3ddevicetype(DeviceType
),
1587 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1588 Usage
, debug_d3dusage(Usage
), debug_d3dusagequery(Usage
),
1589 RType
, debug_d3dresourcetype(RType
),
1590 CheckFormat
, debug_d3dformat(CheckFormat
));
1592 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1593 return WINED3DERR_INVALIDCALL
;
1596 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1597 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1598 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1599 if (Usage
& WINED3DUSAGE_QUERY_VERTEXTEXTURE
) {
1600 TRACE_(d3d_caps
)("[FAILED]\n");
1601 return WINED3DERR_NOTAVAILABLE
; /* Enable when fully supported */
1604 if(Usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
1605 switch (CheckFormat
) {
1606 /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
1607 * Windows supports only those 3, and enumerating the other formats confuses applications
1609 case WINED3DFMT_D24S8
:
1610 case WINED3DFMT_D24X8
:
1611 case WINED3DFMT_D16
:
1612 TRACE_(d3d_caps
)("[OK]\n");
1614 case WINED3DFMT_D16_LOCKABLE
:
1615 case WINED3DFMT_D24FS8
:
1616 case WINED3DFMT_D32F_LOCKABLE
:
1617 case WINED3DFMT_D24X4S4
:
1618 case WINED3DFMT_D15S1
:
1619 case WINED3DFMT_D32
:
1620 TRACE_(d3d_caps
)("[FAILED]. Disabled because not enumerated on windows\n");
1621 return WINED3DERR_NOTAVAILABLE
;
1623 TRACE_(d3d_caps
)("[FAILED]\n");
1624 return WINED3DERR_NOTAVAILABLE
;
1626 } else if(Usage
& WINED3DUSAGE_RENDERTARGET
) {
1627 switch (CheckFormat
) {
1628 case WINED3DFMT_R8G8B8
:
1629 case WINED3DFMT_A8R8G8B8
:
1630 case WINED3DFMT_X8R8G8B8
:
1631 case WINED3DFMT_R5G6B5
:
1632 case WINED3DFMT_X1R5G5B5
:
1633 case WINED3DFMT_A1R5G5B5
:
1634 case WINED3DFMT_A4R4G4B4
:
1635 case WINED3DFMT_R3G3B2
:
1636 case WINED3DFMT_X4R4G4B4
:
1637 case WINED3DFMT_A8B8G8R8
:
1638 case WINED3DFMT_X8B8G8R8
:
1640 TRACE_(d3d_caps
)("[OK]\n");
1642 case WINED3DFMT_R16F
:
1643 case WINED3DFMT_A16B16G16R16F
:
1644 if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
) || !GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1645 TRACE_(d3d_caps
)("[FAILED]\n");
1646 return WINED3DERR_NOTAVAILABLE
;
1648 TRACE_(d3d_caps
)("[OK]\n");
1651 TRACE_(d3d_caps
)("[FAILED]\n");
1652 return WINED3DERR_NOTAVAILABLE
;
1654 } else if(Usage
& WINED3DUSAGE_QUERY_LEGACYBUMPMAP
) {
1655 if(GL_SUPPORT(NV_REGISTER_COMBINERS
) && GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
1656 switch (CheckFormat
) {
1657 case WINED3DFMT_V8U8
:
1658 TRACE_(d3d_caps
)("[OK]\n");
1660 /* TODO: Other bump map formats */
1662 TRACE_(d3d_caps
)("[FAILED]\n");
1663 return WINED3DERR_NOTAVAILABLE
;
1666 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
1667 switch (CheckFormat
) {
1668 case WINED3DFMT_V8U8
:
1669 TRACE_(d3d_caps
)("[OK]\n");
1672 TRACE_(d3d_caps
)("[FAILED]\n");
1673 return WINED3DERR_NOTAVAILABLE
;
1676 TRACE_(d3d_caps
)("[FAILED]\n");
1677 return WINED3DERR_NOTAVAILABLE
;
1680 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1681 switch (CheckFormat
) {
1682 case WINED3DFMT_DXT1
:
1683 case WINED3DFMT_DXT2
:
1684 case WINED3DFMT_DXT3
:
1685 case WINED3DFMT_DXT4
:
1686 case WINED3DFMT_DXT5
:
1687 TRACE_(d3d_caps
)("[OK]\n");
1690 break; /* Avoid compiler warnings */
1694 /* Check for supported sRGB formats (Texture loading and framebuffer) */
1695 if (GL_SUPPORT(EXT_TEXTURE_SRGB
) && (Usage
& WINED3DUSAGE_QUERY_SRGBREAD
)) {
1696 switch (CheckFormat
) {
1697 case WINED3DFMT_A8R8G8B8
:
1698 case WINED3DFMT_X8R8G8B8
:
1699 case WINED3DFMT_A4R4G4B4
:
1701 case WINED3DFMT_A8L8
:
1702 case WINED3DFMT_DXT1
:
1703 case WINED3DFMT_DXT2
:
1704 case WINED3DFMT_DXT3
:
1705 case WINED3DFMT_DXT4
:
1706 case WINED3DFMT_DXT5
:
1707 TRACE_(d3d_caps
)("[OK]\n");
1711 TRACE_(d3d_caps
)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat
));
1712 return WINED3DERR_NOTAVAILABLE
;
1716 if (GL_SUPPORT(ARB_TEXTURE_FLOAT
)) {
1718 BOOL half_pixel_support
= GL_SUPPORT(ARB_HALF_FLOAT_PIXEL
);
1720 switch (CheckFormat
) {
1721 case WINED3DFMT_R16F
:
1722 case WINED3DFMT_A16B16G16R16F
:
1723 if (!half_pixel_support
) break;
1724 case WINED3DFMT_R32F
:
1725 case WINED3DFMT_A32B32G32R32F
:
1726 TRACE_(d3d_caps
)("[OK]\n");
1729 break; /* Avoid compiler warnings */
1733 /* This format is nothing special and it is supported perfectly.
1734 * However, ati and nvidia driver on windows do not mark this format as
1735 * supported (tested with the dxCapsViewer) and pretending to
1736 * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
1737 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1738 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1740 if(This
->dxVersion
> 7 && CheckFormat
== WINED3DFMT_R8G8B8
) {
1741 TRACE_(d3d_caps
)("[FAILED]\n");
1742 return WINED3DERR_NOTAVAILABLE
;
1745 switch (CheckFormat
) {
1748 * supported: RGB(A) formats
1750 case WINED3DFMT_R8G8B8
: /* Enable for dx7, blacklisted for 8 and 9 above */
1751 case WINED3DFMT_A8R8G8B8
:
1752 case WINED3DFMT_X8R8G8B8
:
1753 case WINED3DFMT_R5G6B5
:
1754 case WINED3DFMT_X1R5G5B5
:
1755 case WINED3DFMT_A1R5G5B5
:
1756 case WINED3DFMT_A4R4G4B4
:
1757 case WINED3DFMT_R3G3B2
:
1759 case WINED3DFMT_A8R3G3B2
:
1760 case WINED3DFMT_X4R4G4B4
:
1761 case WINED3DFMT_A8B8G8R8
:
1762 case WINED3DFMT_X8B8G8R8
:
1763 case WINED3DFMT_A2R10G10B10
:
1764 case WINED3DFMT_A2B10G10R10
:
1765 TRACE_(d3d_caps
)("[OK]\n");
1769 * supported: Palettized
1772 TRACE_(d3d_caps
)("[OK]\n");
1776 * Supported: (Alpha)-Luminance
1779 case WINED3DFMT_A8L8
:
1780 case WINED3DFMT_A4L4
:
1781 TRACE_(d3d_caps
)("[OK]\n");
1785 * Not supported for now: Bump mapping formats
1786 * Enable some because games often fail when they are not available
1787 * and are still playable even without bump mapping
1789 case WINED3DFMT_V8U8
:
1790 case WINED3DFMT_V16U16
:
1791 case WINED3DFMT_L6V5U5
:
1792 case WINED3DFMT_X8L8V8U8
:
1793 case WINED3DFMT_Q8W8V8U8
:
1794 case WINED3DFMT_W11V11U10
:
1795 case WINED3DFMT_A2W10V10U10
:
1796 WARN_(d3d_caps
)("[Not supported, but pretended to do]\n");
1800 * DXTN Formats: Handled above
1809 * Odd formats - not supported
1811 case WINED3DFMT_VERTEXDATA
:
1812 case WINED3DFMT_INDEX16
:
1813 case WINED3DFMT_INDEX32
:
1814 case WINED3DFMT_Q16W16V16U16
:
1815 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1816 return WINED3DERR_NOTAVAILABLE
;
1819 * Float formats: Not supported right now
1821 case WINED3DFMT_G16R16F
:
1822 case WINED3DFMT_G32R32F
:
1823 case WINED3DFMT_CxV8U8
:
1824 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1825 return WINED3DERR_NOTAVAILABLE
;
1828 case WINED3DFMT_G16R16
:
1829 case WINED3DFMT_A16B16G16R16
:
1830 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1831 return WINED3DERR_NOTAVAILABLE
;
1833 /* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
1834 * instancing. To query if the card supports instancing CheckDeviceFormat with the special format
1835 * MAKEFOURCC('I','N','S','T') is used. Should a (broken) app check for this provide a proper return value.
1836 * We can do instancing with all shader versions, but we need vertex shaders.
1838 * Additionally applications have to set the D3DRS_POINTSIZE render state to MAKEFOURCC('I','N','S','T') once
1839 * to enable instancing. WineD3D doesn't need that and just ignores it.
1841 * With Shader Model 3.0 capable cards Instancing 'just works' in Windows.
1843 case WINEMAKEFOURCC('I','N','S','T'):
1844 TRACE("ATI Instancing check hack\n");
1845 if(GL_SUPPORT(ARB_VERTEX_PROGRAM
) || GL_SUPPORT(ARB_VERTEX_SHADER
)) {
1846 TRACE_(d3d_caps
)("[OK]\n");
1849 TRACE_(d3d_caps
)("[FAILED]\n");
1850 return WINED3DERR_NOTAVAILABLE
;
1857 TRACE_(d3d_caps
)("[FAILED]\n");
1858 return WINED3DERR_NOTAVAILABLE
;
1861 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1862 WINED3DFORMAT SourceFormat
, WINED3DFORMAT TargetFormat
) {
1863 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1865 FIXME_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1868 DeviceType
, debug_d3ddevicetype(DeviceType
),
1869 SourceFormat
, debug_d3dformat(SourceFormat
),
1870 TargetFormat
, debug_d3dformat(TargetFormat
));
1874 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1875 subset of a D3DCAPS9 structure. However, it has to come via a void *
1876 as the d3d8 interface cannot import the d3d9 header */
1877 static HRESULT WINAPI
IWineD3DImpl_GetDeviceCaps(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, WINED3DCAPS
* pCaps
) {
1879 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1880 int vs_selected_mode
;
1881 int ps_selected_mode
;
1883 TRACE_(d3d_caps
)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This
, Adapter
, DeviceType
, pCaps
);
1885 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1886 return WINED3DERR_INVALIDCALL
;
1889 select_shader_mode(&Adapters
[Adapter
].gl_info
, DeviceType
, &ps_selected_mode
, &vs_selected_mode
);
1891 /* This function should *not* be modifying GL caps
1892 * TODO: move the functionality where it belongs */
1893 select_shader_max_constants(ps_selected_mode
, vs_selected_mode
, &Adapters
[Adapter
].gl_info
);
1895 /* ------------------------------------------------
1896 The following fields apply to both d3d8 and d3d9
1897 ------------------------------------------------ */
1898 *pCaps
->DeviceType
= (DeviceType
== WINED3DDEVTYPE_HAL
) ? WINED3DDEVTYPE_HAL
: WINED3DDEVTYPE_REF
; /* Not quite true, but use h/w supported by opengl I suppose */
1899 *pCaps
->AdapterOrdinal
= Adapter
;
1902 *pCaps
->Caps2
= WINED3DCAPS2_CANRENDERWINDOWED
|
1903 WINED3DCAPS2_FULLSCREENGAMMA
|
1904 WINED3DCAPS2_DYNAMICTEXTURES
;
1905 *pCaps
->Caps3
= WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
;
1906 *pCaps
->PresentationIntervals
= WINED3DPRESENT_INTERVAL_IMMEDIATE
;
1908 *pCaps
->CursorCaps
= WINED3DCURSORCAPS_COLOR
|
1909 WINED3DCURSORCAPS_LOWRES
;
1911 *pCaps
->DevCaps
= WINED3DDEVCAPS_FLOATTLVERTEX
|
1912 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY
|
1913 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY
|
1914 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
1915 WINED3DDEVCAPS_DRAWPRIMTLVERTEX
|
1916 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT
|
1917 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY
|
1918 WINED3DDEVCAPS_PUREDEVICE
|
1919 WINED3DDEVCAPS_HWRASTERIZATION
|
1920 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY
|
1921 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY
|
1922 WINED3DDEVCAPS_CANRENDERAFTERFLIP
|
1923 WINED3DDEVCAPS_DRAWPRIMITIVES2
|
1924 WINED3DDEVCAPS_DRAWPRIMITIVES2EX
;
1926 *pCaps
->PrimitiveMiscCaps
= WINED3DPMISCCAPS_CULLNONE
|
1927 WINED3DPMISCCAPS_CULLCCW
|
1928 WINED3DPMISCCAPS_CULLCW
|
1929 WINED3DPMISCCAPS_COLORWRITEENABLE
|
1930 WINED3DPMISCCAPS_CLIPTLVERTS
|
1931 WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
1932 WINED3DPMISCCAPS_MASKZ
|
1933 WINED3DPMISCCAPS_BLENDOP
;
1935 WINED3DPMISCCAPS_NULLREFERENCE
1936 WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
1937 WINED3DPMISCCAPS_FOGANDSPECULARALPHA
1938 WINED3DPMISCCAPS_SEPARATEALPHABLEND
1939 WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1940 WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1941 WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
1943 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1945 if (GL_SUPPORT(NV_REGISTER_COMBINERS
))
1946 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_TSSARGTEMP
;
1947 if (GL_SUPPORT(NV_REGISTER_COMBINERS2
))
1948 *pCaps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_PERSTAGECONSTANT
;
1951 *pCaps
->RasterCaps
= WINED3DPRASTERCAPS_DITHER
|
1952 WINED3DPRASTERCAPS_PAT
|
1953 WINED3DPRASTERCAPS_WFOG
|
1954 WINED3DPRASTERCAPS_ZFOG
|
1955 WINED3DPRASTERCAPS_FOGVERTEX
|
1956 WINED3DPRASTERCAPS_FOGTABLE
|
1957 WINED3DPRASTERCAPS_FOGRANGE
|
1958 WINED3DPRASTERCAPS_STIPPLE
|
1959 WINED3DPRASTERCAPS_SUBPIXEL
|
1960 WINED3DPRASTERCAPS_ZTEST
|
1961 WINED3DPRASTERCAPS_SCISSORTEST
|
1962 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
|
1963 WINED3DPRASTERCAPS_DEPTHBIAS
;
1965 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1966 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_ANISOTROPY
|
1967 WINED3DPRASTERCAPS_ZBIAS
|
1968 WINED3DPRASTERCAPS_MIPMAPLODBIAS
;
1971 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1972 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1973 WINED3DPRASTERCAPS_ANTIALIASEDGES
1974 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1975 WINED3DPRASTERCAPS_WBUFFER */
1977 *pCaps
->ZCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
1978 WINED3DPCMPCAPS_EQUAL
|
1979 WINED3DPCMPCAPS_GREATER
|
1980 WINED3DPCMPCAPS_GREATEREQUAL
|
1981 WINED3DPCMPCAPS_LESS
|
1982 WINED3DPCMPCAPS_LESSEQUAL
|
1983 WINED3DPCMPCAPS_NEVER
|
1984 WINED3DPCMPCAPS_NOTEQUAL
;
1986 *pCaps
->SrcBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
1987 WINED3DPBLENDCAPS_BOTHINVSRCALPHA
|
1988 WINED3DPBLENDCAPS_BOTHSRCALPHA
|
1989 WINED3DPBLENDCAPS_DESTALPHA
|
1990 WINED3DPBLENDCAPS_DESTCOLOR
|
1991 WINED3DPBLENDCAPS_INVDESTALPHA
|
1992 WINED3DPBLENDCAPS_INVDESTCOLOR
|
1993 WINED3DPBLENDCAPS_INVSRCALPHA
|
1994 WINED3DPBLENDCAPS_INVSRCCOLOR
|
1995 WINED3DPBLENDCAPS_ONE
|
1996 WINED3DPBLENDCAPS_SRCALPHA
|
1997 WINED3DPBLENDCAPS_SRCALPHASAT
|
1998 WINED3DPBLENDCAPS_SRCCOLOR
|
1999 WINED3DPBLENDCAPS_ZERO
;
2001 *pCaps
->DestBlendCaps
= WINED3DPBLENDCAPS_BLENDFACTOR
|
2002 WINED3DPBLENDCAPS_BOTHINVSRCALPHA
|
2003 WINED3DPBLENDCAPS_BOTHSRCALPHA
|
2004 WINED3DPBLENDCAPS_DESTALPHA
|
2005 WINED3DPBLENDCAPS_DESTCOLOR
|
2006 WINED3DPBLENDCAPS_INVDESTALPHA
|
2007 WINED3DPBLENDCAPS_INVDESTCOLOR
|
2008 WINED3DPBLENDCAPS_INVSRCALPHA
|
2009 WINED3DPBLENDCAPS_INVSRCCOLOR
|
2010 WINED3DPBLENDCAPS_ONE
|
2011 WINED3DPBLENDCAPS_SRCALPHA
|
2012 WINED3DPBLENDCAPS_SRCALPHASAT
|
2013 WINED3DPBLENDCAPS_SRCCOLOR
|
2014 WINED3DPBLENDCAPS_ZERO
;
2016 *pCaps
->AlphaCmpCaps
= WINED3DPCMPCAPS_ALWAYS
|
2017 WINED3DPCMPCAPS_EQUAL
|
2018 WINED3DPCMPCAPS_GREATER
|
2019 WINED3DPCMPCAPS_GREATEREQUAL
|
2020 WINED3DPCMPCAPS_LESS
|
2021 WINED3DPCMPCAPS_LESSEQUAL
|
2022 WINED3DPCMPCAPS_NEVER
|
2023 WINED3DPCMPCAPS_NOTEQUAL
;
2025 *pCaps
->ShadeCaps
= WINED3DPSHADECAPS_SPECULARGOURAUDRGB
|
2026 WINED3DPSHADECAPS_COLORGOURAUDRGB
|
2027 WINED3DPSHADECAPS_ALPHAFLATBLEND
|
2028 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND
|
2029 WINED3DPSHADECAPS_COLORFLATRGB
|
2030 WINED3DPSHADECAPS_FOGFLAT
|
2031 WINED3DPSHADECAPS_FOGGOURAUD
|
2032 WINED3DPSHADECAPS_SPECULARFLATRGB
;
2034 *pCaps
->TextureCaps
= WINED3DPTEXTURECAPS_ALPHA
|
2035 WINED3DPTEXTURECAPS_ALPHAPALETTE
|
2036 WINED3DPTEXTURECAPS_BORDER
|
2037 WINED3DPTEXTURECAPS_MIPMAP
|
2038 WINED3DPTEXTURECAPS_PROJECTED
|
2039 WINED3DPTEXTURECAPS_PERSPECTIVE
|
2040 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL
;
2042 if( GL_SUPPORT(EXT_TEXTURE3D
)) {
2043 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_VOLUMEMAP
|
2044 WINED3DPTEXTURECAPS_MIPVOLUMEMAP
|
2045 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2
;
2048 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2049 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_CUBEMAP
|
2050 WINED3DPTEXTURECAPS_MIPCUBEMAP
|
2051 WINED3DPTEXTURECAPS_CUBEMAP_POW2
;
2055 *pCaps
->TextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2056 WINED3DPTFILTERCAPS_MAGFPOINT
|
2057 WINED3DPTFILTERCAPS_MINFLINEAR
|
2058 WINED3DPTFILTERCAPS_MINFPOINT
|
2059 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2060 WINED3DPTFILTERCAPS_MIPFPOINT
|
2061 WINED3DPTFILTERCAPS_LINEAR
|
2062 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2063 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2064 WINED3DPTFILTERCAPS_MIPLINEAR
|
2065 WINED3DPTFILTERCAPS_MIPNEAREST
|
2066 WINED3DPTFILTERCAPS_NEAREST
;
2068 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2069 *pCaps
->TextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2070 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2073 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
2074 *pCaps
->CubeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2075 WINED3DPTFILTERCAPS_MAGFPOINT
|
2076 WINED3DPTFILTERCAPS_MINFLINEAR
|
2077 WINED3DPTFILTERCAPS_MINFPOINT
|
2078 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2079 WINED3DPTFILTERCAPS_MIPFPOINT
|
2080 WINED3DPTFILTERCAPS_LINEAR
|
2081 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2082 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2083 WINED3DPTFILTERCAPS_MIPLINEAR
|
2084 WINED3DPTFILTERCAPS_MIPNEAREST
|
2085 WINED3DPTFILTERCAPS_NEAREST
;
2087 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
2088 *pCaps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
2089 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
2092 *pCaps
->CubeTextureFilterCaps
= 0;
2094 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2095 *pCaps
->VolumeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
2096 WINED3DPTFILTERCAPS_MAGFPOINT
|
2097 WINED3DPTFILTERCAPS_MINFLINEAR
|
2098 WINED3DPTFILTERCAPS_MINFPOINT
|
2099 WINED3DPTFILTERCAPS_MIPFLINEAR
|
2100 WINED3DPTFILTERCAPS_MIPFPOINT
|
2101 WINED3DPTFILTERCAPS_LINEAR
|
2102 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
2103 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
2104 WINED3DPTFILTERCAPS_MIPLINEAR
|
2105 WINED3DPTFILTERCAPS_MIPNEAREST
|
2106 WINED3DPTFILTERCAPS_NEAREST
;
2108 *pCaps
->VolumeTextureFilterCaps
= 0;
2110 *pCaps
->TextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2111 WINED3DPTADDRESSCAPS_CLAMP
|
2112 WINED3DPTADDRESSCAPS_WRAP
;
2114 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2115 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2117 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2118 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2120 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2121 *pCaps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2124 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
2125 *pCaps
->VolumeTextureAddressCaps
= WINED3DPTADDRESSCAPS_INDEPENDENTUV
|
2126 WINED3DPTADDRESSCAPS_CLAMP
|
2127 WINED3DPTADDRESSCAPS_WRAP
;
2128 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
2129 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
;
2131 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
2132 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRROR
;
2134 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
2135 *pCaps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
2138 *pCaps
->VolumeTextureAddressCaps
= 0;
2140 *pCaps
->LineCaps
= WINED3DLINECAPS_TEXTURE
|
2141 WINED3DLINECAPS_ZTEST
;
2143 WINED3DLINECAPS_BLEND
2144 WINED3DLINECAPS_ALPHACMP
2145 WINED3DLINECAPS_FOG */
2147 *pCaps
->MaxTextureWidth
= GL_LIMITS(texture_size
);
2148 *pCaps
->MaxTextureHeight
= GL_LIMITS(texture_size
);
2150 if(GL_SUPPORT(EXT_TEXTURE3D
))
2151 *pCaps
->MaxVolumeExtent
= GL_LIMITS(texture3d_size
);
2153 *pCaps
->MaxVolumeExtent
= 0;
2155 *pCaps
->MaxTextureRepeat
= 32768;
2156 *pCaps
->MaxTextureAspectRatio
= GL_LIMITS(texture_size
);
2157 *pCaps
->MaxVertexW
= 1.0;
2159 *pCaps
->GuardBandLeft
= 0;
2160 *pCaps
->GuardBandTop
= 0;
2161 *pCaps
->GuardBandRight
= 0;
2162 *pCaps
->GuardBandBottom
= 0;
2164 *pCaps
->ExtentsAdjust
= 0;
2166 *pCaps
->StencilCaps
= WINED3DSTENCILCAPS_DECRSAT
|
2167 WINED3DSTENCILCAPS_INCRSAT
|
2168 WINED3DSTENCILCAPS_INVERT
|
2169 WINED3DSTENCILCAPS_KEEP
|
2170 WINED3DSTENCILCAPS_REPLACE
|
2171 WINED3DSTENCILCAPS_ZERO
;
2172 if (GL_SUPPORT(EXT_STENCIL_WRAP
)) {
2173 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_DECR
|
2174 WINED3DSTENCILCAPS_INCR
;
2176 if ( This
->dxVersion
> 8 &&
2177 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE
) ||
2178 GL_SUPPORT(ATI_SEPARATE_STENCIL
) ) ) {
2179 *pCaps
->StencilCaps
|= WINED3DSTENCILCAPS_TWOSIDED
;
2182 *pCaps
->FVFCaps
= WINED3DFVFCAPS_PSIZE
| 0x0008; /* 8 texture coords */
2184 *pCaps
->TextureOpCaps
= WINED3DTEXOPCAPS_ADD
|
2185 WINED3DTEXOPCAPS_ADDSIGNED
|
2186 WINED3DTEXOPCAPS_ADDSIGNED2X
|
2187 WINED3DTEXOPCAPS_MODULATE
|
2188 WINED3DTEXOPCAPS_MODULATE2X
|
2189 WINED3DTEXOPCAPS_MODULATE4X
|
2190 WINED3DTEXOPCAPS_SELECTARG1
|
2191 WINED3DTEXOPCAPS_SELECTARG2
|
2192 WINED3DTEXOPCAPS_DISABLE
;
2194 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE
) ||
2195 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE
) ||
2196 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2197 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
2198 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
|
2199 WINED3DTEXOPCAPS_BLENDFACTORALPHA
|
2200 WINED3DTEXOPCAPS_BLENDCURRENTALPHA
|
2201 WINED3DTEXOPCAPS_LERP
|
2202 WINED3DTEXOPCAPS_SUBTRACT
;
2204 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3
) ||
2205 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
2206 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_ADDSMOOTH
|
2207 WINED3DTEXOPCAPS_MULTIPLYADD
|
2208 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
2209 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
2210 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
;
2212 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3
))
2213 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_DOTPRODUCT3
;
2215 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
2216 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
|
2217 WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
;
2220 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP
)) {
2221 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2222 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2
)) {
2223 /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
2224 * not support 3D textures. This asks for trouble if an app uses both bump mapping
2225 * and 3D textures. It also allows us to keep the code simpler by having texture
2226 * shaders constantly enabled.
2228 *pCaps
->TextureOpCaps
|= WINED3DTEXOPCAPS_BUMPENVMAP
;
2229 /* TODO: Luminance bump map? */
2233 *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2234 WINED3DTEXOPCAPS_PREMODULATE */
2237 *pCaps
->MaxTextureBlendStages
= GL_LIMITS(texture_stages
);
2238 *pCaps
->MaxSimultaneousTextures
= GL_LIMITS(textures
);
2239 *pCaps
->MaxUserClipPlanes
= GL_LIMITS(clipplanes
);
2240 *pCaps
->MaxActiveLights
= GL_LIMITS(lights
);
2242 *pCaps
->MaxVertexBlendMatrices
= GL_LIMITS(blends
);
2243 *pCaps
->MaxVertexBlendMatrixIndex
= 0;
2245 *pCaps
->MaxAnisotropy
= GL_LIMITS(anisotropy
);
2246 *pCaps
->MaxPointSize
= GL_LIMITS(pointsize
);
2249 *pCaps
->VertexProcessingCaps
= WINED3DVTXPCAPS_DIRECTIONALLIGHTS
|
2250 WINED3DVTXPCAPS_MATERIALSOURCE7
|
2251 WINED3DVTXPCAPS_POSITIONALLIGHTS
|
2252 WINED3DVTXPCAPS_LOCALVIEWER
|
2253 WINED3DVTXPCAPS_VERTEXFOG
|
2254 WINED3DVTXPCAPS_TEXGEN
;
2256 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2258 *pCaps
->MaxPrimitiveCount
= 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2259 *pCaps
->MaxVertexIndex
= 0xFFFFF;
2260 *pCaps
->MaxStreams
= MAX_STREAMS
;
2261 *pCaps
->MaxStreamStride
= 1024;
2263 if (vs_selected_mode
== SHADER_GLSL
) {
2264 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2265 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2266 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2267 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2268 if(GLINFO_LOCATION
.vs_nv_version
== VS_VERSION_20
)
2269 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(2,0);
2271 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(3,0);
2272 TRACE_(d3d_caps
)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2273 } else if (vs_selected_mode
== SHADER_ARB
) {
2274 *pCaps
->VertexShaderVersion
= WINED3DVS_VERSION(1,1);
2275 TRACE_(d3d_caps
)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2277 *pCaps
->VertexShaderVersion
= 0;
2278 TRACE_(d3d_caps
)("Vertex shader functionality not available\n");
2281 *pCaps
->MaxVertexShaderConst
= GL_LIMITS(vshader_constantsF
);
2283 if (ps_selected_mode
== SHADER_GLSL
) {
2284 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2285 in case of GeforceFX cards. */
2286 if(GLINFO_LOCATION
.ps_nv_version
== PS_VERSION_20
)
2287 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(2,0);
2289 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(3,0);
2290 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2291 *pCaps
->PixelShader1xMaxValue
= 1.0;
2292 TRACE_(d3d_caps
)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2293 } else if (ps_selected_mode
== SHADER_ARB
) {
2294 *pCaps
->PixelShaderVersion
= WINED3DPS_VERSION(1,4);
2295 *pCaps
->PixelShader1xMaxValue
= 1.0;
2296 TRACE_(d3d_caps
)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2298 *pCaps
->PixelShaderVersion
= 0;
2299 *pCaps
->PixelShader1xMaxValue
= 0.0;
2300 TRACE_(d3d_caps
)("Pixel shader functionality not available\n");
2303 /* ------------------------------------------------
2304 The following fields apply to d3d9 only
2305 ------------------------------------------------ */
2306 if (This
->dxVersion
> 8) {
2307 /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
2308 *pCaps
->DevCaps2
= WINED3DDEVCAPS2_STREAMOFFSET
;
2309 /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2310 *pCaps
->MaxNpatchTessellationLevel
= 0;
2311 *pCaps
->MasterAdapterOrdinal
= 0;
2312 *pCaps
->AdapterOrdinalInGroup
= 0;
2313 *pCaps
->NumberOfAdaptersInGroup
= 1;
2315 if(*pCaps
->VertexShaderVersion
>= WINED3DVS_VERSION(2,0)) {
2316 /* OpenGL supports all the formats below, perhaps not always
2317 * without conversion, but it supports them.
2318 * Further GLSL doesn't seem to have an official unsigned type so
2319 * don't advertise it yet as I'm not sure how we handle it.
2320 * We might need to add some clamping in the shader engine to
2322 * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
2323 *pCaps
->DeclTypes
= WINED3DDTCAPS_UBYTE4
|
2324 WINED3DDTCAPS_UBYTE4N
|
2325 WINED3DDTCAPS_SHORT2N
|
2326 WINED3DDTCAPS_SHORT4N
|
2327 WINED3DDTCAPS_FLOAT16_2
|
2328 WINED3DDTCAPS_FLOAT16_4
;
2331 *pCaps
->DeclTypes
= 0;
2333 *pCaps
->NumSimultaneousRTs
= GL_LIMITS(buffers
);
2336 *pCaps
->StretchRectFilterCaps
= WINED3DPTFILTERCAPS_MINFPOINT
|
2337 WINED3DPTFILTERCAPS_MAGFPOINT
|
2338 WINED3DPTFILTERCAPS_MINFLINEAR
|
2339 WINED3DPTFILTERCAPS_MAGFLINEAR
;
2340 *pCaps
->VertexTextureFilterCaps
= 0;
2342 if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(3,0)) {
2343 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2344 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2345 *pCaps
->VS20Caps
.Caps
= WINED3DVS20CAPS_PREDICATION
;
2346 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2347 *pCaps
->VS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.vs_arb_max_temps
);
2348 *pCaps
->VS20Caps
.StaticFlowControlDepth
= WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH
; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2350 *pCaps
->MaxVShaderInstructionsExecuted
= 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
2351 *pCaps
->MaxVertexShader30InstructionSlots
= max(512, GLINFO_LOCATION
.vs_arb_max_instructions
);
2352 } else if(*pCaps
->VertexShaderVersion
== WINED3DVS_VERSION(2,0)) {
2353 *pCaps
->VS20Caps
.Caps
= 0;
2354 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH
;
2355 *pCaps
->VS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.vs_arb_max_temps
);
2356 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 1;
2358 *pCaps
->MaxVShaderInstructionsExecuted
= 65535;
2359 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2360 } else { /* VS 1.x */
2361 *pCaps
->VS20Caps
.Caps
= 0;
2362 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= 0;
2363 *pCaps
->VS20Caps
.NumTemps
= 0;
2364 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 0;
2366 *pCaps
->MaxVShaderInstructionsExecuted
= 0;
2367 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2370 if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(3,0)) {
2371 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2372 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2374 /* 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 */
2375 *pCaps
->PS20Caps
.Caps
= WINED3DPS20CAPS_ARBITRARYSWIZZLE
|
2376 WINED3DPS20CAPS_GRADIENTINSTRUCTIONS
|
2377 WINED3DPS20CAPS_PREDICATION
|
2378 WINED3DPS20CAPS_NODEPENDENTREADLIMIT
|
2379 WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
;
2380 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2381 *pCaps
->PS20Caps
.NumTemps
= max(32, GLINFO_LOCATION
.ps_arb_max_temps
);
2382 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2383 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS
; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2385 *pCaps
->MaxPShaderInstructionsExecuted
= 65535;
2386 *pCaps
->MaxPixelShader30InstructionSlots
= max(WINED3DMIN30SHADERINSTRUCTIONS
, GLINFO_LOCATION
.ps_arb_max_instructions
);
2387 } else if(*pCaps
->PixelShaderVersion
== WINED3DPS_VERSION(2,0)) {
2388 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2389 *pCaps
->PS20Caps
.Caps
= 0;
2390 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2391 *pCaps
->PS20Caps
.NumTemps
= max(12, GLINFO_LOCATION
.ps_arb_max_temps
);
2392 *pCaps
->PS20Caps
.StaticFlowControlDepth
= WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH
; /* Minumum: 1 */
2393 *pCaps
->PS20Caps
.NumInstructionSlots
= WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS
; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2395 *pCaps
->MaxPShaderInstructionsExecuted
= 512; /* Minimum value, a GeforceFX uses 1024 */
2396 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2397 } else { /* PS 1.x */
2398 *pCaps
->PS20Caps
.Caps
= 0;
2399 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0;
2400 *pCaps
->PS20Caps
.NumTemps
= 0;
2401 *pCaps
->PS20Caps
.StaticFlowControlDepth
= 0;
2402 *pCaps
->PS20Caps
.NumInstructionSlots
= 0;
2404 *pCaps
->MaxPShaderInstructionsExecuted
= 0;
2405 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2412 static unsigned int glsl_program_key_hash(void *key
) {
2413 glsl_program_key_t
*k
= (glsl_program_key_t
*)key
;
2415 unsigned int hash
= k
->vshader
| k
->pshader
<< 16;
2416 hash
+= ~(hash
<< 15);
2417 hash
^= (hash
>> 10);
2418 hash
+= (hash
<< 3);
2419 hash
^= (hash
>> 6);
2420 hash
+= ~(hash
<< 11);
2421 hash
^= (hash
>> 16);
2426 static BOOL
glsl_program_key_compare(void *keya
, void *keyb
) {
2427 glsl_program_key_t
*ka
= (glsl_program_key_t
*)keya
;
2428 glsl_program_key_t
*kb
= (glsl_program_key_t
*)keyb
;
2430 return ka
->vshader
== kb
->vshader
&& ka
->pshader
== kb
->pshader
;
2433 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2434 and fields being inserted in the middle, a new structure is used in place */
2435 static HRESULT WINAPI
IWineD3DImpl_CreateDevice(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, HWND hFocusWindow
,
2436 DWORD BehaviourFlags
, IWineD3DDevice
** ppReturnedDeviceInterface
,
2439 IWineD3DDeviceImpl
*object
= NULL
;
2440 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2442 HRESULT temp_result
;
2444 /* Validate the adapter number */
2445 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
2446 return WINED3DERR_INVALIDCALL
;
2449 /* Create a WineD3DDevice object */
2450 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DDeviceImpl
));
2451 *ppReturnedDeviceInterface
= (IWineD3DDevice
*)object
;
2452 TRACE("Created WineD3DDevice object @ %p\n", object
);
2453 if (NULL
== object
) {
2454 return WINED3DERR_OUTOFVIDEOMEMORY
;
2457 /* Set up initial COM information */
2458 object
->lpVtbl
= &IWineD3DDevice_Vtbl
;
2460 object
->wineD3D
= iface
;
2461 object
->adapter
= &Adapters
[Adapter
];
2462 IWineD3D_AddRef(object
->wineD3D
);
2463 object
->parent
= parent
;
2465 if(This
->dxVersion
== 7) {
2466 object
->surface_alignment
= 8;
2468 object
->surface_alignment
= 4;
2471 /* Set the state up as invalid until the device is fully created */
2472 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2474 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %x, RetDevInt: %p)\n", This
, Adapter
, DeviceType
,
2475 hFocusWindow
, BehaviourFlags
, ppReturnedDeviceInterface
);
2477 /* Save the creation parameters */
2478 object
->createParms
.AdapterOrdinal
= Adapter
;
2479 object
->createParms
.DeviceType
= DeviceType
;
2480 object
->createParms
.hFocusWindow
= hFocusWindow
;
2481 object
->createParms
.BehaviorFlags
= BehaviourFlags
;
2483 /* Initialize other useful values */
2484 object
->adapterNo
= Adapter
;
2485 object
->devType
= DeviceType
;
2487 TRACE("(%p) : Creating stateblock\n", This
);
2488 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2489 if (WINED3D_OK
!= IWineD3DDevice_CreateStateBlock((IWineD3DDevice
*)object
,
2491 (IWineD3DStateBlock
**)&object
->stateBlock
,
2492 NULL
) || NULL
== object
->stateBlock
) { /* Note: No parent needed for initial internal stateblock */
2493 WARN("Failed to create stateblock\n");
2494 goto create_device_error
;
2496 TRACE("(%p) : Created stateblock (%p)\n", This
, object
->stateBlock
);
2497 object
->updateStateBlock
= object
->stateBlock
;
2498 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)object
->updateStateBlock
);
2499 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2501 select_shader_mode(&GLINFO_LOCATION
, DeviceType
, &object
->ps_selected_mode
, &object
->vs_selected_mode
);
2502 if (object
->ps_selected_mode
== SHADER_GLSL
|| object
->vs_selected_mode
== SHADER_GLSL
) {
2503 object
->shader_backend
= &glsl_shader_backend
;
2504 object
->glsl_program_lookup
= hash_table_create(&glsl_program_key_hash
, &glsl_program_key_compare
);
2505 } else if (object
->ps_selected_mode
== SHADER_ARB
|| object
->vs_selected_mode
== SHADER_ARB
) {
2506 object
->shader_backend
= &arb_program_shader_backend
;
2508 object
->shader_backend
= &none_shader_backend
;
2511 /* This function should *not* be modifying GL caps
2512 * TODO: move the functionality where it belongs */
2513 select_shader_max_constants(object
->ps_selected_mode
, object
->vs_selected_mode
, &GLINFO_LOCATION
);
2515 temp_result
= allocate_shader_constants(object
->updateStateBlock
);
2516 if (WINED3D_OK
!= temp_result
)
2519 object
->render_targets
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*) * GL_LIMITS(buffers
));
2520 object
->fbo_color_attachments
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DSurface
*) * GL_LIMITS(buffers
));
2521 object
->draw_buffers
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(GLenum
) * GL_LIMITS(buffers
));
2523 /* set the state of the device to valid */
2524 object
->state
= WINED3D_OK
;
2526 /* Get the initial screen setup for ddraw */
2527 object
->ddraw_width
= GetSystemMetrics(SM_CXSCREEN
);
2528 object
->ddraw_height
= GetSystemMetrics(SM_CYSCREEN
);
2530 object
->ddraw_format
= pixelformat_for_depth(GetDeviceCaps(hDC
, BITSPIXEL
) * GetDeviceCaps(hDC
, PLANES
));
2534 create_device_error
:
2536 /* Set the device state to error */
2537 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2539 if (object
->updateStateBlock
!= NULL
) {
2540 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)object
->updateStateBlock
);
2541 object
->updateStateBlock
= NULL
;
2543 if (object
->stateBlock
!= NULL
) {
2544 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)object
->stateBlock
);
2545 object
->stateBlock
= NULL
;
2547 if (object
->render_targets
[0] != NULL
) {
2548 IWineD3DSurface_Release(object
->render_targets
[0]);
2549 object
->render_targets
[0] = NULL
;
2551 if (object
->stencilBufferTarget
!= NULL
) {
2552 IWineD3DSurface_Release(object
->stencilBufferTarget
);
2553 object
->stencilBufferTarget
= NULL
;
2555 HeapFree(GetProcessHeap(), 0, object
);
2556 *ppReturnedDeviceInterface
= NULL
;
2557 return WINED3DERR_INVALIDCALL
;
2560 #undef GLINFO_LOCATION
2562 static HRESULT WINAPI
IWineD3DImpl_GetParent(IWineD3D
*iface
, IUnknown
**pParent
) {
2563 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2564 IUnknown_AddRef(This
->parent
);
2565 *pParent
= This
->parent
;
2569 ULONG WINAPI
D3DCB_DefaultDestroySurface(IWineD3DSurface
*pSurface
) {
2570 IUnknown
* surfaceParent
;
2571 TRACE("(%p) call back\n", pSurface
);
2573 /* Now, release the parent, which will take care of cleaning up the surface for us */
2574 IWineD3DSurface_GetParent(pSurface
, &surfaceParent
);
2575 IUnknown_Release(surfaceParent
);
2576 return IUnknown_Release(surfaceParent
);
2579 ULONG WINAPI
D3DCB_DefaultDestroyVolume(IWineD3DVolume
*pVolume
) {
2580 IUnknown
* volumeParent
;
2581 TRACE("(%p) call back\n", pVolume
);
2583 /* Now, release the parent, which will take care of cleaning up the volume for us */
2584 IWineD3DVolume_GetParent(pVolume
, &volumeParent
);
2585 IUnknown_Release(volumeParent
);
2586 return IUnknown_Release(volumeParent
);
2589 BOOL
InitAdapters(void) {
2593 /* No need to hold any lock. The calling library makes sure only one thread calls
2594 * wined3d simultaneously
2596 if(numAdapters
> 0) return TRUE
;
2598 TRACE("Initializing adapters\n");
2599 /* For now only one default adapter */
2601 TRACE("Initializing default adapter\n");
2602 Adapters
[0].monitorPoint
.x
= -1;
2603 Adapters
[0].monitorPoint
.y
= -1;
2605 device_context
= GetDC(0);
2606 Adapters
[0].display
= get_display(device_context
);
2607 ReleaseDC(0, device_context
);
2610 if(WineD3D_CreateFakeGLContext()) {
2611 Adapters
[0].cfgs
= glXGetFBConfigs(Adapters
[0].display
, DefaultScreen(Adapters
[0].display
), &Adapters
[0].nCfgs
);
2612 WineD3D_ReleaseFakeGLContext();
2614 ERR("Failed to create a fake opengl context to find fbconfigs formats\n");
2620 ret
= IWineD3DImpl_FillGLCaps(&Adapters
[0].gl_info
, Adapters
[0].display
);
2622 ERR("Failed to initialize gl caps for default adapter\n");
2623 XFree(Adapters
[0].cfgs
);
2624 HeapFree(GetProcessHeap(), 0, Adapters
);
2627 Adapters
[0].driver
= "Display";
2628 Adapters
[0].description
= "Direct3D HAL";
2631 TRACE("%d adapters successfully initialized\n", numAdapters
);
2637 /**********************************************************
2638 * IWineD3D VTbl follows
2639 **********************************************************/
2641 const IWineD3DVtbl IWineD3D_Vtbl
=
2644 IWineD3DImpl_QueryInterface
,
2645 IWineD3DImpl_AddRef
,
2646 IWineD3DImpl_Release
,
2648 IWineD3DImpl_GetParent
,
2649 IWineD3DImpl_GetAdapterCount
,
2650 IWineD3DImpl_RegisterSoftwareDevice
,
2651 IWineD3DImpl_GetAdapterMonitor
,
2652 IWineD3DImpl_GetAdapterModeCount
,
2653 IWineD3DImpl_EnumAdapterModes
,
2654 IWineD3DImpl_GetAdapterDisplayMode
,
2655 IWineD3DImpl_GetAdapterIdentifier
,
2656 IWineD3DImpl_CheckDeviceMultiSampleType
,
2657 IWineD3DImpl_CheckDepthStencilMatch
,
2658 IWineD3DImpl_CheckDeviceType
,
2659 IWineD3DImpl_CheckDeviceFormat
,
2660 IWineD3DImpl_CheckDeviceFormatConversion
,
2661 IWineD3DImpl_GetDeviceCaps
,
2662 IWineD3DImpl_CreateDevice