2 * IWineD3D implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Compile time diagnostics: */
26 /* Uncomment this to force only a single display mode to be exposed: */
27 /*#define DEBUG_SINGLE_MODE*/
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps
);
35 #define GLINFO_LOCATION This->gl_info
37 /**********************************************************
38 * Utility functions follow
39 **********************************************************/
41 /* x11drv GDI escapes */
42 #define X11DRV_ESCAPE 6789
43 enum x11drv_escape_codes
45 X11DRV_GET_DISPLAY
, /* get X11 display for a DC */
46 X11DRV_GET_DRAWABLE
, /* get current drawable for a DC */
47 X11DRV_GET_FONT
, /* get current X font for a DC */
50 /* retrieve the X display to use on a given DC */
51 inline static Display
*get_display( HDC hdc
)
54 enum x11drv_escape_codes escape
= X11DRV_GET_DISPLAY
;
56 if (!ExtEscape( hdc
, X11DRV_ESCAPE
, sizeof(escape
), (LPCSTR
)&escape
,
57 sizeof(display
), (LPSTR
)&display
)) display
= NULL
;
62 int minLookup
[MAX_LOOKUPS
];
63 int maxLookup
[MAX_LOOKUPS
];
64 DWORD
*stateLookup
[MAX_LOOKUPS
];
66 DWORD minMipLookup
[WINED3DTEXF_ANISOTROPIC
+ 1][WINED3DTEXF_LINEAR
+ 1];
71 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
72 * ie there is no GL Context - Get a default rendering context to enable the
73 * function query some info from GL
75 static WineD3D_Context
* WineD3D_CreateFakeGLContext(void) {
76 static WineD3D_Context ctx
= { NULL
, NULL
, NULL
, 0, 0 };
77 WineD3D_Context
* ret
= NULL
;
79 if (glXGetCurrentContext() == NULL
) {
80 BOOL gotContext
= FALSE
;
87 XWindowAttributes win_attr
;
88 TRACE_(d3d_caps
)("Creating Fake GL Context\n");
90 ctx
.drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
93 device_context
= GetDC(0);
94 ctx
.display
= get_display(device_context
);
95 ReleaseDC(0, device_context
);
97 /* Get the X visual */
99 if (XGetWindowAttributes(ctx
.display
, ctx
.drawable
, &win_attr
)) {
100 visual
= win_attr
.visual
;
102 visual
= DefaultVisual(ctx
.display
, DefaultScreen(ctx
.display
));
104 template.visualid
= XVisualIDFromVisual(visual
);
105 ctx
.visInfo
= XGetVisualInfo(ctx
.display
, VisualIDMask
, &template, &num
);
106 if (ctx
.visInfo
== NULL
) {
108 WARN_(d3d_caps
)("Error creating visual info for capabilities initialization\n");
112 /* Create a GL context */
114 ctx
.glCtx
= glXCreateContext(ctx
.display
, ctx
.visInfo
, NULL
, GL_TRUE
);
116 if (ctx
.glCtx
== NULL
) {
118 WARN_(d3d_caps
)("Error creating default context for capabilities initialization\n");
123 /* Make it the current GL context */
124 if (!failed
&& glXMakeCurrent(ctx
.display
, ctx
.drawable
, ctx
.glCtx
) == False
) {
125 glXDestroyContext(ctx
.display
, ctx
.glCtx
);
127 WARN_(d3d_caps
)("Error setting default context as current for capabilities initialization\n");
131 /* It worked! Wow... */
141 if (ctx
.ref
> 0) ret
= &ctx
;
144 if (NULL
!= ret
) InterlockedIncrement(&ret
->ref
);
148 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context
* ctx
) {
149 /* If we created a dummy context, throw it away */
151 if (0 == InterlockedDecrement(&ctx
->ref
)) {
152 glXMakeCurrent(ctx
->display
, None
, NULL
);
153 glXDestroyContext(ctx
->display
, ctx
->glCtx
);
161 /**********************************************************
162 * IUnknown parts follows
163 **********************************************************/
165 static HRESULT WINAPI
IWineD3DImpl_QueryInterface(IWineD3D
*iface
,REFIID riid
,LPVOID
*ppobj
)
167 IWineD3DDeviceImpl
*This
= (IWineD3DDeviceImpl
*)iface
;
169 TRACE("(%p)->(%s,%p)\n",This
,debugstr_guid(riid
),ppobj
);
170 if (IsEqualGUID(riid
, &IID_IUnknown
)
171 || IsEqualGUID(riid
, &IID_IWineD3DBase
)
172 || IsEqualGUID(riid
, &IID_IWineD3DDevice
)) {
173 IUnknown_AddRef(iface
);
178 return E_NOINTERFACE
;
181 static ULONG WINAPI
IWineD3DImpl_AddRef(IWineD3D
*iface
) {
182 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
183 ULONG refCount
= InterlockedIncrement(&This
->ref
);
185 TRACE("(%p) : AddRef increasing from %ld\n", This
, refCount
- 1);
189 static ULONG WINAPI
IWineD3DImpl_Release(IWineD3D
*iface
) {
190 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
192 TRACE("(%p) : Releasing from %ld\n", This
, This
->ref
);
193 ref
= InterlockedDecrement(&This
->ref
);
195 HeapFree(GetProcessHeap(), 0, This
);
201 /* Set the shader type for this device, depending on the given capabilities,
202 * the device type, and the user preferences in wined3d_settings */
204 static void select_shader_mode(
205 WineD3D_GL_Info
*gl_info
,
206 WINED3DDEVTYPE DeviceType
,
210 /* Give priority to user disable/emulation request.
211 * Then respect REF device for software.
212 * Then check capabilities for hardware, and fallback to software */
214 if (wined3d_settings
.vs_mode
== VS_NONE
) {
215 *vs_selected
= SHADER_NONE
;
216 } else if (DeviceType
== WINED3DDEVTYPE_REF
|| wined3d_settings
.vs_mode
== VS_SW
) {
217 *vs_selected
= SHADER_SW
;
218 } else if (gl_info
->supported
[ARB_VERTEX_SHADER
] && wined3d_settings
.glslRequested
) {
219 *vs_selected
= SHADER_GLSL
;
220 } else if (gl_info
->supported
[ARB_VERTEX_PROGRAM
]) {
221 *vs_selected
= SHADER_ARB
;
223 *vs_selected
= SHADER_SW
;
226 /* Fallback to SHADER_NONE where software pixel shaders should be used */
227 if (wined3d_settings
.ps_mode
== PS_NONE
) {
228 *ps_selected
= SHADER_NONE
;
229 } else if (DeviceType
== WINED3DDEVTYPE_REF
) {
230 *ps_selected
= SHADER_NONE
;
231 } else if (gl_info
->supported
[ARB_FRAGMENT_SHADER
] && wined3d_settings
.glslRequested
) {
232 *ps_selected
= SHADER_GLSL
;
233 } else if (gl_info
->supported
[ARB_FRAGMENT_PROGRAM
]) {
234 *ps_selected
= SHADER_ARB
;
236 *ps_selected
= SHADER_NONE
;
240 /** Select the number of report maximum shader constants based on the selected shader modes */
241 void select_shader_max_constants(WineD3D_GL_Info
*gl_info
) {
243 switch (wined3d_settings
.vs_selected_mode
) {
245 /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
246 gl_info
->max_vshader_constantsF
= gl_info
->vs_glsl_constantsF
- MAX_CONST_B
- MAX_CONST_I
- 1;
249 /* We have to subtract any other PARAMs that we might use in our shader programs.
250 * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
251 * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
252 gl_info
->max_vshader_constantsF
= gl_info
->vs_arb_constantsF
- 3;
255 gl_info
->max_vshader_constantsF
= 96; /* TODO: Fixup software shaders */
258 gl_info
->max_vshader_constantsF
= 0;
262 switch (wined3d_settings
.ps_selected_mode
) {
264 /* Subtract the other potential uniforms from the max available (bools & ints) */
265 gl_info
->max_pshader_constantsF
= gl_info
->ps_glsl_constantsF
- MAX_CONST_B
- MAX_CONST_I
;
268 gl_info
->max_pshader_constantsF
= gl_info
->ps_arb_constantsF
;
271 gl_info
->max_pshader_constantsF
= 96; /* TODO: Fixup software shaders */
274 gl_info
->max_pshader_constantsF
= 0;
279 /**********************************************************
280 * IWineD3D parts follows
281 **********************************************************/
283 BOOL
IWineD3DImpl_FillGLCaps(IWineD3D
*iface
, Display
* display
) {
284 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
285 WineD3D_GL_Info
*gl_info
= &This
->gl_info
;
287 const char *GL_Extensions
= NULL
;
288 const char *GLX_Extensions
= NULL
;
289 const char *gl_string
= NULL
;
290 const char *gl_string_cursor
= NULL
;
292 GLfloat gl_floatv
[2];
295 WineD3D_Context
*fake_ctx
= NULL
;
296 BOOL gotContext
= FALSE
;
299 /* Make sure that we've got a context */
300 if (glXGetCurrentContext() == NULL
) {
301 /* TODO: CreateFakeGLContext should really take a display as a parameter */
302 fake_ctx
= WineD3D_CreateFakeGLContext();
303 if (NULL
!= fake_ctx
) gotContext
= TRUE
;
308 TRACE_(d3d_caps
)("(%p, %p)\n", gl_info
, display
);
310 gl_string
= (const char *) glGetString(GL_RENDERER
);
311 strcpy(gl_info
->gl_renderer
, gl_string
);
313 /* Fill in the GL info retrievable depending on the display */
314 if (NULL
!= display
) {
315 test
= glXQueryVersion(display
, &major
, &minor
);
316 gl_info
->glx_version
= ((major
& 0x0000FFFF) << 16) | (minor
& 0x0000FFFF);
318 FIXME("Display must not be NULL, use glXGetCurrentDisplay or getAdapterDisplay()\n");
320 gl_string
= (const char *) glGetString(GL_VENDOR
);
322 TRACE_(d3d_caps
)("Filling vendor string %s\n", gl_string
);
323 if (gl_string
!= NULL
) {
324 /* Fill in the GL vendor */
325 if (strstr(gl_string
, "NVIDIA")) {
326 gl_info
->gl_vendor
= VENDOR_NVIDIA
;
327 } else if (strstr(gl_string
, "ATI")) {
328 gl_info
->gl_vendor
= VENDOR_ATI
;
329 } else if (strstr(gl_string
, "Intel(R)") ||
330 strstr(gl_info
->gl_renderer
, "Intel(R)")) {
331 gl_info
->gl_vendor
= VENDOR_INTEL
;
332 } else if (strstr(gl_string
, "Mesa")) {
333 gl_info
->gl_vendor
= VENDOR_MESA
;
335 gl_info
->gl_vendor
= VENDOR_WINE
;
338 gl_info
->gl_vendor
= VENDOR_WINE
;
342 TRACE_(d3d_caps
)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string
), gl_info
->gl_vendor
);
344 /* Parse the GL_VERSION field into major and minor information */
345 gl_string
= (const char *) glGetString(GL_VERSION
);
346 if (gl_string
!= NULL
) {
348 switch (gl_info
->gl_vendor
) {
350 gl_string_cursor
= strstr(gl_string
, "NVIDIA");
351 if (!gl_string_cursor
) {
352 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
356 gl_string_cursor
= strstr(gl_string_cursor
, " ");
357 if (!gl_string_cursor
) {
358 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
362 while (*gl_string_cursor
== ' ') {
366 if (!*gl_string_cursor
) {
367 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
371 major
= atoi(gl_string_cursor
);
372 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
376 if (*gl_string_cursor
++ != '.') {
377 ERR_(d3d_caps
)("Invalid nVidia version string: %s\n", debugstr_a(gl_string
));
381 minor
= atoi(gl_string_cursor
);
382 minor
= major
*100+minor
;
389 gl_string_cursor
= strchr(gl_string
, '-');
390 if (gl_string_cursor
) {
394 /* Check if version number is of the form x.y.z */
395 if (*gl_string_cursor
> '9' && *gl_string_cursor
< '0')
397 if (!error
&& *(gl_string_cursor
+2) > '9' && *(gl_string_cursor
+2) < '0')
399 if (!error
&& *(gl_string_cursor
+4) > '9' && *(gl_string_cursor
+4) < '0')
401 if (!error
&& *(gl_string_cursor
+1) != '.' && *(gl_string_cursor
+3) != '.')
404 /* Mark version number as malformed */
406 gl_string_cursor
= 0;
409 if (!gl_string_cursor
)
410 WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
412 major
= *gl_string_cursor
- '0';
413 minor
= (*(gl_string_cursor
+2) - '0') * 256 + (*(gl_string_cursor
+4) - '0');
419 gl_string_cursor
= strstr(gl_string
, "Mesa");
420 gl_string_cursor
= strstr(gl_string_cursor
, " ");
421 while (*gl_string_cursor
&& ' ' == *gl_string_cursor
) ++gl_string_cursor
;
422 if (*gl_string_cursor
) {
426 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
427 tmp
[cursor
++] = *gl_string_cursor
;
433 if (*gl_string_cursor
!= '.') WARN_(d3d_caps
)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string
));
437 while (*gl_string_cursor
<= '9' && *gl_string_cursor
>= '0') {
438 tmp
[cursor
++] = *gl_string_cursor
;
450 gl_info
->gl_driver_version
= MAKEDWORD_VERSION(major
, minor
);
451 TRACE_(d3d_caps
)("found GL_VERSION (%s)->%i.%i->(0x%08lx)\n", debugstr_a(gl_string
), major
, minor
, gl_info
->gl_driver_version
);
453 /* Fill in the renderer information */
455 switch (gl_info
->gl_vendor
) {
457 if (strstr(gl_info
->gl_renderer
, "GeForce4 Ti")) {
458 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4600
;
459 } else if (strstr(gl_info
->gl_renderer
, "GeForceFX")) {
460 gl_info
->gl_card
= CARD_NVIDIA_GEFORCEFX_5900ULTRA
;
461 } else if (strstr(gl_info
->gl_renderer
, "Quadro FX 3000")) {
462 gl_info
->gl_card
= CARD_NVIDIA_QUADROFX_3000
;
463 } else if (strstr(gl_info
->gl_renderer
, "GeForce 6800")) {
464 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_6800ULTRA
;
465 } else if (strstr(gl_info
->gl_renderer
, "Quadro FX 4000")) {
466 gl_info
->gl_card
= CARD_NVIDIA_QUADROFX_4000
;
467 } else if (strstr(gl_info
->gl_renderer
, "GeForce 7800")) {
468 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE_7800ULTRA
;
470 gl_info
->gl_card
= CARD_NVIDIA_GEFORCE4_TI4600
;
475 if (strstr(gl_info
->gl_renderer
, "RADEON 9800 PRO")) {
476 gl_info
->gl_card
= CARD_ATI_RADEON_9800PRO
;
477 } else if (strstr(gl_info
->gl_renderer
, "RADEON 9700 PRO")) {
478 gl_info
->gl_card
= CARD_ATI_RADEON_9700PRO
;
480 gl_info
->gl_card
= CARD_ATI_RADEON_8500
;
485 if (strstr(gl_info
->gl_renderer
, "915GM")) {
486 gl_info
->gl_card
= CARD_INTEL_I915GM
;
487 } else if (strstr(gl_info
->gl_renderer
, "915G")) {
488 gl_info
->gl_card
= CARD_INTEL_I915G
;
489 } else if (strstr(gl_info
->gl_renderer
, "865G")) {
490 gl_info
->gl_card
= CARD_INTEL_I865G
;
491 } else if (strstr(gl_info
->gl_renderer
, "855G")) {
492 gl_info
->gl_card
= CARD_INTEL_I855G
;
493 } else if (strstr(gl_info
->gl_renderer
, "830G")) {
494 gl_info
->gl_card
= CARD_INTEL_I830G
;
496 gl_info
->gl_card
= CARD_INTEL_I915G
;
501 gl_info
->gl_card
= CARD_WINE
;
505 FIXME("get version string returned null\n");
508 TRACE_(d3d_caps
)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info
->gl_renderer
), gl_info
->gl_card
);
511 * Initialize openGL extension related variables
512 * with Default values
514 memset(&gl_info
->supported
, 0, sizeof(gl_info
->supported
));
515 gl_info
->max_textures
= 1;
516 gl_info
->max_texture_stages
= 1;
517 gl_info
->max_samplers
= 1;
518 gl_info
->max_sampler_stages
= 1;
519 gl_info
->ps_arb_version
= PS_VERSION_NOT_SUPPORTED
;
520 gl_info
->ps_arb_max_temps
= 0;
521 gl_info
->ps_arb_max_instructions
= 0;
522 gl_info
->vs_arb_version
= VS_VERSION_NOT_SUPPORTED
;
523 gl_info
->vs_arb_max_temps
= 0;
524 gl_info
->vs_arb_max_instructions
= 0;
525 gl_info
->vs_nv_version
= VS_VERSION_NOT_SUPPORTED
;
526 gl_info
->vs_ati_version
= VS_VERSION_NOT_SUPPORTED
;
527 gl_info
->vs_glsl_constantsF
= 0;
528 gl_info
->ps_glsl_constantsF
= 0;
529 gl_info
->vs_arb_constantsF
= 0;
530 gl_info
->ps_arb_constantsF
= 0;
532 /* Now work out what GL support this card really has */
533 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB( (const GLubyte *) #pfn);
538 /* Retrieve opengl defaults */
539 glGetIntegerv(GL_MAX_CLIP_PLANES
, &gl_max
);
540 gl_info
->max_clipplanes
= min(D3DMAXUSERCLIPPLANES
, gl_max
);
541 TRACE_(d3d_caps
)("ClipPlanes support - num Planes=%d\n", gl_max
);
543 glGetIntegerv(GL_MAX_LIGHTS
, &gl_max
);
544 gl_info
->max_lights
= gl_max
;
545 TRACE_(d3d_caps
)("Lights support - max lights=%d\n", gl_max
);
547 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, &gl_max
);
548 gl_info
->max_texture_size
= gl_max
;
549 TRACE_(d3d_caps
)("Maximum texture size support - max texture size=%d\n", gl_max
);
551 glGetFloatv(GL_POINT_SIZE_RANGE
, gl_floatv
);
552 gl_info
->max_pointsize
= gl_floatv
[1];
553 TRACE_(d3d_caps
)("Maximum point size support - max point size=%f\n", gl_floatv
[1]);
555 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
556 GL_Extensions
= (const char *) glGetString(GL_EXTENSIONS
);
557 TRACE_(d3d_caps
)("GL_Extensions reported:\n");
559 if (NULL
== GL_Extensions
) {
560 ERR(" GL_Extensions returns NULL\n");
562 while (*GL_Extensions
!= 0x00) {
563 const char *Start
= GL_Extensions
;
566 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
567 while (*GL_Extensions
!= ' ' && *GL_Extensions
!= 0x00) {
570 memcpy(ThisExtn
, Start
, (GL_Extensions
- Start
));
571 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
576 if (strcmp(ThisExtn
, "GL_ARB_fragment_program") == 0) {
577 gl_info
->ps_arb_version
= PS_VERSION_11
;
578 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info
->ps_arb_version
);
579 gl_info
->supported
[ARB_FRAGMENT_PROGRAM
] = TRUE
;
580 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB
, &gl_max
);
581 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max
);
582 gl_info
->max_samplers
= min(MAX_SAMPLERS
, gl_max
);
583 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
584 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max float constants=%u\n", gl_max
);
585 gl_info
->ps_arb_constantsF
= gl_max
;
586 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
587 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max temporaries=%u\n", gl_max
);
588 gl_info
->ps_arb_max_temps
= gl_max
;
589 GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
590 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Shader support - max instructions=%u\n", gl_max
);
591 gl_info
->ps_arb_max_instructions
= gl_max
;
592 } else if (strcmp(ThisExtn
, "GL_ARB_fragment_shader") == 0) {
593 gl_info
->supported
[ARB_FRAGMENT_SHADER
] = TRUE
;
594 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB
, &gl_max
);
595 TRACE_(d3d_caps
)(" FOUND: ARB_fragment_shader (GLSL) support - max float ps constants=%u\n", gl_max
);
596 gl_info
->ps_glsl_constantsF
= gl_max
;
597 } else if (strcmp(ThisExtn
, "GL_ARB_imaging") == 0) {
598 TRACE_(d3d_caps
)(" FOUND: ARB imaging support\n");
599 gl_info
->supported
[ARB_IMAGING
] = TRUE
;
600 } else if (strcmp(ThisExtn
, "GL_ARB_multisample") == 0) {
601 TRACE_(d3d_caps
)(" FOUND: ARB Multisample support\n");
602 gl_info
->supported
[ARB_MULTISAMPLE
] = TRUE
;
603 } else if (strcmp(ThisExtn
, "GL_ARB_multitexture") == 0) {
604 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB
, &gl_max
);
605 TRACE_(d3d_caps
)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max
);
606 gl_info
->supported
[ARB_MULTITEXTURE
] = TRUE
;
607 gl_info
->max_textures
= min(MAX_TEXTURES
, gl_max
);
608 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
609 gl_info
->max_samplers
= max(gl_info
->max_samplers
, gl_max
);
610 } else if (strcmp(ThisExtn
, "GL_ARB_texture_cube_map") == 0) {
611 TRACE_(d3d_caps
)(" FOUND: ARB Texture Cube Map support\n");
612 gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
] = TRUE
;
613 TRACE_(d3d_caps
)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
614 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
615 } else if (strcmp(ThisExtn
, "GL_ARB_texture_compression") == 0) {
616 TRACE_(d3d_caps
)(" FOUND: ARB Texture Compression support\n");
617 gl_info
->supported
[ARB_TEXTURE_COMPRESSION
] = TRUE
;
618 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_add") == 0) {
619 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env Add support\n");
620 gl_info
->supported
[ARB_TEXTURE_ENV_ADD
] = TRUE
;
621 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_combine") == 0) {
622 TRACE_(d3d_caps
)(" FOUND: ARB Texture Env combine support\n");
623 gl_info
->supported
[ARB_TEXTURE_ENV_COMBINE
] = TRUE
;
624 } else if (strcmp(ThisExtn
, "GL_ARB_texture_env_dot3") == 0) {
625 TRACE_(d3d_caps
)(" FOUND: ARB Dot3 support\n");
626 gl_info
->supported
[ARB_TEXTURE_ENV_DOT3
] = TRUE
;
627 } else if (strcmp(ThisExtn
, "GL_ARB_texture_border_clamp") == 0) {
628 TRACE_(d3d_caps
)(" FOUND: ARB Texture border clamp support\n");
629 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] = TRUE
;
630 } else if (strcmp(ThisExtn
, "GL_ARB_texture_mirrored_repeat") == 0) {
631 TRACE_(d3d_caps
)(" FOUND: ARB Texture mirrored repeat support\n");
632 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] = TRUE
;
633 } else if (strcmp(ThisExtn
, "GLX_ARB_multisample") == 0) {
634 TRACE_(d3d_caps
)(" FOUND: ARB multisample support\n");
635 gl_info
->supported
[ARB_MULTISAMPLE
] = TRUE
;
636 } else if (strcmp(ThisExtn
, "GL_ARB_pixel_buffer_object") == 0) {
637 TRACE_(d3d_caps
)(" FOUND: ARB Pixel Buffer support\n");
638 gl_info
->supported
[ARB_PIXEL_BUFFER_OBJECT
] = TRUE
;
639 } else if (strcmp(ThisExtn
, "GL_ARB_point_sprite") == 0) {
640 TRACE_(d3d_caps
)(" FOUND: ARB point sprite support\n");
641 gl_info
->supported
[ARB_POINT_SPRITE
] = TRUE
;
642 } else if (strstr(ThisExtn
, "GL_ARB_vertex_program")) {
643 gl_info
->vs_arb_version
= VS_VERSION_11
;
644 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info
->vs_arb_version
);
645 gl_info
->supported
[ARB_VERTEX_PROGRAM
] = TRUE
;
646 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB
, &gl_max
));
647 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max float constants=%u\n", gl_max
);
648 gl_info
->vs_arb_constantsF
= gl_max
;
649 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_TEMPORARIES_ARB
, &gl_max
));
650 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max temporaries=%u\n", gl_max
);
651 gl_info
->vs_arb_max_temps
= gl_max
;
652 GL_EXTCALL(glGetProgramivARB(GL_VERTEX_PROGRAM_ARB
, GL_MAX_PROGRAM_INSTRUCTIONS_ARB
, &gl_max
));
653 TRACE_(d3d_caps
)(" FOUND: ARB Vertex Shader support - max instructions=%u\n", gl_max
);
654 gl_info
->vs_arb_max_instructions
= gl_max
;
655 } else if (strcmp(ThisExtn
, "GL_ARB_vertex_shader") == 0) {
656 gl_info
->supported
[ARB_VERTEX_SHADER
] = TRUE
;
657 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_paletted_texture") == 0) { /* handle paletted texture extensions */
684 TRACE_(d3d_caps
)(" FOUND: EXT Paletted texture support\n");
685 gl_info
->supported
[EXT_PALETTED_TEXTURE
] = TRUE
;
686 } else if (strcmp(ThisExtn
, "GL_EXT_point_parameters") == 0) {
687 TRACE_(d3d_caps
)(" FOUND: EXT Point parameters support\n");
688 gl_info
->supported
[EXT_POINT_PARAMETERS
] = TRUE
;
689 } else if (strcmp(ThisExtn
, "GL_EXT_secondary_color") == 0) {
690 TRACE_(d3d_caps
)(" FOUND: EXT Secondary coord support\n");
691 gl_info
->supported
[EXT_SECONDARY_COLOR
] = TRUE
;
692 } else if (strcmp(ThisExtn
, "GL_EXT_stencil_two_side") == 0) {
693 TRACE_(d3d_caps
)(" FOUND: EXT Stencil two side support\n");
694 gl_info
->supported
[EXT_STENCIL_TWO_SIDE
] = TRUE
;
695 } else if (strcmp(ThisExtn
, "GL_EXT_stencil_wrap") == 0) {
696 TRACE_(d3d_caps
)(" FOUND: EXT Stencil wrap support\n");
697 gl_info
->supported
[EXT_STENCIL_WRAP
] = TRUE
;
698 } else if (strcmp(ThisExtn
, "GL_EXT_texture3D") == 0) {
699 TRACE_(d3d_caps
)(" FOUND: EXT_texture3D support\n");
700 gl_info
->supported
[EXT_TEXTURE3D
] = TRUE
;
701 glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE_EXT
, &gl_max
);
702 TRACE_(d3d_caps
)("Max texture3D size: %d\n", gl_max
);
703 gl_info
->max_texture3d_size
= gl_max
;
704 } else if (strcmp(ThisExtn
, "GL_EXT_texture_compression_s3tc") == 0) {
705 TRACE_(d3d_caps
)(" FOUND: EXT Texture S3TC compression support\n");
706 gl_info
->supported
[EXT_TEXTURE_COMPRESSION_S3TC
] = TRUE
;
707 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_add") == 0) {
708 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env Add support\n");
709 gl_info
->supported
[EXT_TEXTURE_ENV_ADD
] = TRUE
;
710 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_combine") == 0) {
711 TRACE_(d3d_caps
)(" FOUND: EXT Texture Env combine support\n");
712 gl_info
->supported
[EXT_TEXTURE_ENV_COMBINE
] = TRUE
;
713 } else if (strcmp(ThisExtn
, "GL_EXT_texture_env_dot3") == 0) {
714 TRACE_(d3d_caps
)(" FOUND: EXT Dot3 support\n");
715 gl_info
->supported
[EXT_TEXTURE_ENV_DOT3
] = TRUE
;
716 } else if (strcmp(ThisExtn
, "GL_EXT_texture_filter_anisotropic") == 0) {
717 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] = TRUE
;
718 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, &gl_max
);
719 TRACE_(d3d_caps
)(" FOUND: EXT Texture Anisotropic filter support. GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT %d\n", gl_max
);
720 gl_info
->max_anisotropy
= gl_max
;
721 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod") == 0) {
722 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD support\n");
723 gl_info
->supported
[EXT_TEXTURE_LOD
] = TRUE
;
724 } else if (strcmp(ThisExtn
, "GL_EXT_texture_lod_bias") == 0) {
725 TRACE_(d3d_caps
)(" FOUND: EXT Texture LOD bias support\n");
726 gl_info
->supported
[EXT_TEXTURE_LOD_BIAS
] = TRUE
;
727 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_weighting") == 0) {
728 TRACE_(d3d_caps
)(" FOUND: EXT Vertex weighting support\n");
729 gl_info
->supported
[EXT_VERTEX_WEIGHTING
] = TRUE
;
734 } else if (strstr(ThisExtn
, "GL_NV_fog_distance")) {
735 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Fog Distance support\n");
736 gl_info
->supported
[NV_FOG_DISTANCE
] = TRUE
;
737 } else if (strstr(ThisExtn
, "GL_NV_fragment_program")) {
738 gl_info
->ps_nv_version
= (strcmp(ThisExtn
, "GL_NV_fragment_program2") == 0) ? PS_VERSION_30
: PS_VERSION_20
;
739 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info
->ps_nv_version
);
740 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners") == 0) {
741 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV
, &gl_max
);
742 gl_info
->max_texture_stages
= min(MAX_TEXTURES
, gl_max
);
743 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (1) support - GL_MAX_GENERAL_COMBINERS_NV=%d\n", gl_max
);
744 gl_info
->supported
[NV_REGISTER_COMBINERS
] = TRUE
;
745 } else if (strcmp(ThisExtn
, "GL_NV_register_combiners2") == 0) {
746 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
747 gl_info
->supported
[NV_REGISTER_COMBINERS2
] = TRUE
;
748 } else if (strcmp(ThisExtn
, "GL_NV_texgen_reflection") == 0) {
749 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
750 gl_info
->supported
[NV_TEXGEN_REFLECTION
] = TRUE
;
751 } else if (strcmp(ThisExtn
, "GL_NV_texture_env_combine4") == 0) {
752 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
753 gl_info
->supported
[NV_TEXTURE_ENV_COMBINE4
] = TRUE
;
754 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader") == 0) {
755 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
756 gl_info
->supported
[NV_TEXTURE_SHADER
] = TRUE
;
757 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader2") == 0) {
758 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
759 gl_info
->supported
[NV_TEXTURE_SHADER2
] = TRUE
;
760 } else if (strcmp(ThisExtn
, "GL_NV_texture_shader3") == 0) {
761 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
762 gl_info
->supported
[NV_TEXTURE_SHADER3
] = TRUE
;
763 } else if (strcmp(ThisExtn
, "GL_NV_occlusion_query") == 0) {
764 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Occlusion Query (3) support\n");
765 gl_info
->supported
[NV_OCCLUSION_QUERY
] = TRUE
;
766 } else if (strstr(ThisExtn
, "GL_NV_vertex_program")) {
767 if(strcmp(ThisExtn
, "GL_NV_vertex_program3") == 0)
768 gl_info
->vs_nv_version
= VS_VERSION_30
;
769 else if(strcmp(ThisExtn
, "GL_NV_vertex_program2") == 0)
770 gl_info
->vs_nv_version
= VS_VERSION_20
;
771 else if(strcmp(ThisExtn
, "GL_NV_vertex_program1_1") == 0)
772 gl_info
->vs_nv_version
= VS_VERSION_11
;
774 gl_info
->vs_nv_version
= VS_VERSION_10
;
775 TRACE_(d3d_caps
)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info
->vs_nv_version
);
776 gl_info
->supported
[NV_VERTEX_PROGRAM
] = TRUE
;
782 } else if (strcmp(ThisExtn
, "GL_ATI_separate_stencil") == 0) {
783 TRACE_(d3d_caps
)(" FOUND: ATI Separate stencil support\n");
784 gl_info
->supported
[ATI_SEPARATE_STENCIL
] = TRUE
;
785 } else if (strcmp(ThisExtn
, "GL_ATI_texture_env_combine3") == 0) {
786 TRACE_(d3d_caps
)(" FOUND: ATI Texture Env combine (3) support\n");
787 gl_info
->supported
[ATI_TEXTURE_ENV_COMBINE3
] = TRUE
;
788 } else if (strcmp(ThisExtn
, "GL_ATI_texture_mirror_once") == 0) {
789 TRACE_(d3d_caps
)(" FOUND: ATI Texture Mirror Once support\n");
790 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] = TRUE
;
791 } else if (strcmp(ThisExtn
, "GL_EXT_vertex_shader") == 0) {
792 gl_info
->vs_ati_version
= VS_VERSION_11
;
793 TRACE_(d3d_caps
)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info
->vs_ati_version
);
794 gl_info
->supported
[EXT_VERTEX_SHADER
] = TRUE
;
798 if (*GL_Extensions
== ' ') GL_Extensions
++;
801 checkGLcall("extension detection\n");
803 gl_info
->max_sampler_stages
= max(gl_info
->max_samplers
, gl_info
->max_texture_stages
);
805 /* Load all the lookup tables
806 TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
807 minLookup
[WINELOOKUP_WARPPARAM
] = D3DTADDRESS_WRAP
;
808 maxLookup
[WINELOOKUP_WARPPARAM
] = D3DTADDRESS_MIRRORONCE
;
810 minLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_NONE
;
811 maxLookup
[WINELOOKUP_MAGFILTER
] = WINED3DTEXF_ANISOTROPIC
;
814 for (i
= 0; i
< MAX_LOOKUPS
; i
++) {
815 stateLookup
[i
] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup
[i
]) * (1 + maxLookup
[i
] - minLookup
[i
]) );
818 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_WRAP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_REPEAT
;
819 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_CLAMP
- minLookup
[WINELOOKUP_WARPPARAM
]] = GL_CLAMP_TO_EDGE
;
820 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
821 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
822 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_BORDER
- minLookup
[WINELOOKUP_WARPPARAM
]] =
823 gl_info
->supported
[ARB_TEXTURE_BORDER_CLAMP
] ? GL_CLAMP_TO_BORDER_ARB
: GL_REPEAT
;
824 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_MIRROR
- minLookup
[WINELOOKUP_WARPPARAM
]] =
825 gl_info
->supported
[ARB_TEXTURE_MIRRORED_REPEAT
] ? GL_MIRRORED_REPEAT_ARB
: GL_REPEAT
;
826 stateLookup
[WINELOOKUP_WARPPARAM
][D3DTADDRESS_MIRRORONCE
- minLookup
[WINELOOKUP_WARPPARAM
]] =
827 gl_info
->supported
[ATI_TEXTURE_MIRROR_ONCE
] ? GL_MIRROR_CLAMP_TO_EDGE_ATI
: GL_REPEAT
;
829 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_NONE
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
830 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_POINT
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_NEAREST
;
831 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_LINEAR
- minLookup
[WINELOOKUP_MAGFILTER
]] = GL_LINEAR
;
832 stateLookup
[WINELOOKUP_MAGFILTER
][WINED3DTEXF_ANISOTROPIC
- minLookup
[WINELOOKUP_MAGFILTER
]] =
833 gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR
: GL_NEAREST
;
836 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_NONE
] = GL_LINEAR
;
837 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_POINT
] = GL_LINEAR
;
838 minMipLookup
[WINED3DTEXF_NONE
][WINED3DTEXF_LINEAR
] = GL_LINEAR
;
839 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_NONE
] = GL_NEAREST
;
840 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_POINT
] = GL_NEAREST_MIPMAP_NEAREST
;
841 minMipLookup
[WINED3DTEXF_POINT
][WINED3DTEXF_LINEAR
] = GL_NEAREST_MIPMAP_LINEAR
;
842 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_NONE
] = GL_LINEAR
;
843 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_POINT
] = GL_LINEAR_MIPMAP_NEAREST
;
844 minMipLookup
[WINED3DTEXF_LINEAR
][WINED3DTEXF_LINEAR
] = GL_LINEAR_MIPMAP_LINEAR
;
845 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_NONE
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ?
846 GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
847 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_POINT
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_NEAREST
: GL_LINEAR
;
848 minMipLookup
[WINED3DTEXF_ANISOTROPIC
][WINED3DTEXF_LINEAR
] = gl_info
->supported
[EXT_TEXTURE_FILTER_ANISOTROPIC
] ? GL_LINEAR_MIPMAP_LINEAR
: GL_LINEAR
;
850 /* TODO: config lookups */
852 if (display
!= NULL
) {
853 GLX_Extensions
= glXQueryExtensionsString(display
, DefaultScreen(display
));
854 TRACE_(d3d_caps
)("GLX_Extensions reported:\n");
856 if (NULL
== GLX_Extensions
) {
857 ERR(" GLX_Extensions returns NULL\n");
859 while (*GLX_Extensions
!= 0x00) {
860 const char *Start
= GLX_Extensions
;
863 memset(ThisExtn
, 0x00, sizeof(ThisExtn
));
864 while (*GLX_Extensions
!= ' ' && *GLX_Extensions
!= 0x00) {
867 memcpy(ThisExtn
, Start
, (GLX_Extensions
- Start
));
868 TRACE_(d3d_caps
)("- %s\n", ThisExtn
);
869 if (*GLX_Extensions
== ' ') GLX_Extensions
++;
874 /* If we created a dummy context, throw it away */
875 if (NULL
!= fake_ctx
) WineD3D_ReleaseFakeGLContext(fake_ctx
);
877 /* Only save the values obtained when a display is provided */
878 if (fake_ctx
== NULL
) {
885 /**********************************************************
886 * IWineD3D implementation follows
887 **********************************************************/
889 static UINT WINAPI
IWineD3DImpl_GetAdapterCount (IWineD3D
*iface
) {
890 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
892 /* FIXME: Set to one for now to imply the display */
893 TRACE_(d3d_caps
)("(%p): Mostly stub, only returns primary display\n", This
);
897 static HRESULT WINAPI
IWineD3DImpl_RegisterSoftwareDevice(IWineD3D
*iface
, void* pInitializeFunction
) {
898 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
899 FIXME("(%p)->(%p): stub\n", This
, pInitializeFunction
);
903 static HMONITOR WINAPI
IWineD3DImpl_GetAdapterMonitor(IWineD3D
*iface
, UINT Adapter
) {
904 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
905 POINT pt
= { -1, -1 };
907 if (Adapter
>= IWineD3DImpl_GetAdapterCount(iface
)) {
911 FIXME_(d3d_caps
)("(%p): returning the primary monitor for adapter %d\n", This
, Adapter
);
912 return MonitorFromPoint(pt
, MONITOR_DEFAULTTOPRIMARY
);
915 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
916 of the same bpp but different resolutions */
918 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
919 static UINT WINAPI
IWineD3DImpl_GetAdapterModeCount(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
) {
920 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
921 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Format: %s)\n", This
, Adapter
, debug_d3dformat(Format
));
923 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
927 if (Adapter
== 0) { /* Display */
930 #if !defined( DEBUG_SINGLE_MODE )
933 /* Work out the current screen bpp */
934 HDC hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
935 int bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
938 while (EnumDisplaySettingsExW(NULL
, j
, &DevModeW
, 0)) {
945 case D3DFMT_X8R8G8B8
:
946 case D3DFMT_A8R8G8B8
:
947 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 32) i
++;
948 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 24) i
++;
950 case D3DFMT_X1R5G5B5
:
951 case D3DFMT_A1R5G5B5
:
953 if (min(DevModeW
.dmBitsPerPel
, bpp
) == 16) i
++;
956 /* Skip other modes as they do not match requested format */
964 TRACE_(d3d_caps
)("(%p}->(Adapter: %d) => %d (out of %d)\n", This
, Adapter
, i
, j
);
967 FIXME_(d3d_caps
)("Adapter not primary display\n");
972 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
973 static HRESULT WINAPI
IWineD3DImpl_EnumAdapterModes(IWineD3D
*iface
, UINT Adapter
, WINED3DFORMAT Format
, UINT Mode
, WINED3DDISPLAYMODE
* pMode
) {
974 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
975 TRACE_(d3d_caps
)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This
, Adapter
, Mode
, pMode
, debug_d3dformat(Format
));
977 /* Validate the parameters as much as possible */
979 Adapter
>= IWineD3DImpl_GetAdapterCount(iface
) ||
980 Mode
>= IWineD3DImpl_GetAdapterModeCount(iface
, Adapter
, Format
)) {
981 return WINED3DERR_INVALIDCALL
;
984 if (Adapter
== 0) { /* Display */
985 #if !defined( DEBUG_SINGLE_MODE )
989 /* Work out the current screen bpp */
990 HDC hdc
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
991 int bpp
= GetDeviceCaps(hdc
, BITSPIXEL
);
994 /* If we are filtering to a specific format, then need to skip all unrelated
995 modes, but if mode is irrelevant, then we can use the index directly */
996 if (Format
== D3DFMT_UNKNOWN
)
1002 DEVMODEW DevModeWtmp
;
1005 while (i
<(Mode
) && EnumDisplaySettingsExW(NULL
, j
, &DevModeWtmp
, 0)) {
1009 case D3DFMT_UNKNOWN
:
1012 case D3DFMT_X8R8G8B8
:
1013 case D3DFMT_A8R8G8B8
:
1014 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 32) i
++;
1015 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 24) i
++;
1017 case D3DFMT_X1R5G5B5
:
1018 case D3DFMT_A1R5G5B5
:
1020 if (min(DevModeWtmp
.dmBitsPerPel
, bpp
) == 16) i
++;
1023 /* Skip other modes as they do not match requested format */
1030 /* Now get the display mode via the calculated index */
1031 if (EnumDisplaySettingsExW(NULL
, ModeIdx
, &DevModeW
, 0))
1033 pMode
->Width
= DevModeW
.dmPelsWidth
;
1034 pMode
->Height
= DevModeW
.dmPelsHeight
;
1035 bpp
= min(DevModeW
.dmBitsPerPel
, bpp
);
1036 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
1037 if (DevModeW
.dmFields
& DM_DISPLAYFREQUENCY
)
1039 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1042 if (Format
== D3DFMT_UNKNOWN
)
1045 case 8: pMode
->Format
= D3DFMT_R3G3B2
; break;
1046 case 16: pMode
->Format
= D3DFMT_R5G6B5
; break;
1047 case 24: /* Robots and EVE Online need 24 and 32 bit as A8R8G8B8 to start */
1048 case 32: pMode
->Format
= D3DFMT_A8R8G8B8
; break;
1049 default: pMode
->Format
= D3DFMT_UNKNOWN
;
1052 pMode
->Format
= Format
;
1057 TRACE_(d3d_caps
)("Requested mode out of range %d\n", Mode
);
1058 return WINED3DERR_INVALIDCALL
;
1062 /* Return one setting of the format requested */
1063 if (Mode
> 0) return WINED3DERR_INVALIDCALL
;
1065 pMode
->Height
= 600;
1066 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
1067 pMode
->Format
= (Format
== D3DFMT_UNKNOWN
) ? D3DFMT_A8R8G8B8
: Format
;
1070 TRACE_(d3d_caps
)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode
->Width
, pMode
->Height
,
1071 pMode
->RefreshRate
, pMode
->Format
, debug_d3dformat(pMode
->Format
), bpp
);
1074 FIXME_(d3d_caps
)("Adapter not primary display\n");
1080 static HRESULT WINAPI
IWineD3DImpl_GetAdapterDisplayMode(IWineD3D
*iface
, UINT Adapter
, WINED3DDISPLAYMODE
* pMode
) {
1081 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1082 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, pMode: %p)\n", This
, Adapter
, pMode
);
1084 if (NULL
== pMode
||
1085 Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1086 return WINED3DERR_INVALIDCALL
;
1089 if (Adapter
== 0) { /* Display */
1093 EnumDisplaySettingsExW(NULL
, (DWORD
)-1, &DevModeW
, 0);
1094 pMode
->Width
= DevModeW
.dmPelsWidth
;
1095 pMode
->Height
= DevModeW
.dmPelsHeight
;
1096 bpp
= DevModeW
.dmBitsPerPel
;
1097 pMode
->RefreshRate
= D3DADAPTER_DEFAULT
;
1098 if (DevModeW
.dmFields
&DM_DISPLAYFREQUENCY
)
1100 pMode
->RefreshRate
= DevModeW
.dmDisplayFrequency
;
1104 case 8: pMode
->Format
= D3DFMT_R3G3B2
; break;
1105 case 16: pMode
->Format
= D3DFMT_R5G6B5
; break;
1106 case 24: pMode
->Format
= D3DFMT_X8R8G8B8
; break; /* Robots needs 24bit to be X8R8G8B8 */
1107 case 32: pMode
->Format
= D3DFMT_X8R8G8B8
; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
1108 default: pMode
->Format
= D3DFMT_UNKNOWN
;
1112 FIXME_(d3d_caps
)("Adapter not primary display\n");
1115 TRACE_(d3d_caps
)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode
->Width
,
1116 pMode
->Height
, pMode
->RefreshRate
, debug_d3dformat(pMode
->Format
));
1120 static Display
* WINAPI
IWineD3DImpl_GetAdapterDisplay(IWineD3D
*iface
, UINT Adapter
) {
1123 /* only works with one adapter at the moment... */
1125 /* Get the display */
1126 device_context
= GetDC(0);
1127 display
= get_display(device_context
);
1128 ReleaseDC(0, device_context
);
1132 /* NOTE: due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
1133 and fields being inserted in the middle, a new structure is used in place */
1134 static HRESULT WINAPI
IWineD3DImpl_GetAdapterIdentifier(IWineD3D
*iface
, UINT Adapter
, DWORD Flags
,
1135 WINED3DADAPTER_IDENTIFIER
* pIdentifier
) {
1136 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1138 TRACE_(d3d_caps
)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This
, Adapter
, Flags
, pIdentifier
);
1140 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1141 return WINED3DERR_INVALIDCALL
;
1144 if (Adapter
== 0) { /* Display - only device supported for now */
1146 BOOL isGLInfoValid
= This
->isGLInfoValid
;
1148 /* FillGLCaps updates gl_info, but we only want to store and
1149 reuse the values once we have a context which is valid. Values from
1150 a temporary context may differ from the final ones */
1151 if (isGLInfoValid
== FALSE
) {
1152 WineD3D_Context
*fake_ctx
= NULL
;
1153 if (glXGetCurrentContext() == NULL
) fake_ctx
= WineD3D_CreateFakeGLContext();
1154 /* If we don't know the device settings, go query them now */
1155 isGLInfoValid
= IWineD3DImpl_FillGLCaps(iface
, IWineD3DImpl_GetAdapterDisplay(iface
, Adapter
));
1156 if (fake_ctx
!= NULL
) WineD3D_ReleaseFakeGLContext(fake_ctx
);
1159 /* If it worked, return the information requested */
1160 if (isGLInfoValid
) {
1161 TRACE_(d3d_caps
)("device/Vendor Name and Version detection using FillGLCaps\n");
1162 strcpy(pIdentifier
->Driver
, "Display");
1163 strcpy(pIdentifier
->Description
, "Direct3D HAL");
1165 /* Note dx8 doesn't supply a DeviceName */
1166 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1167 /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
1168 pIdentifier
->DriverVersion
->u
.HighPart
= MAKEDWORD_VERSION(6, 14);
1169 pIdentifier
->DriverVersion
->u
.LowPart
= This
->gl_info
.gl_driver_version
;
1170 *(pIdentifier
->VendorId
) = This
->gl_info
.gl_vendor
;
1171 *(pIdentifier
->DeviceId
) = This
->gl_info
.gl_card
;
1172 *(pIdentifier
->SubSysId
) = 0;
1173 *(pIdentifier
->Revision
) = 0;
1177 /* If it failed, return dummy values from an NVidia driver */
1178 WARN_(d3d_caps
)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
1179 strcpy(pIdentifier
->Driver
, "Display");
1180 strcpy(pIdentifier
->Description
, "Direct3D HAL");
1181 if (NULL
!= pIdentifier
->DeviceName
) strcpy(pIdentifier
->DeviceName
, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
1182 /* Current Windows Nvidia drivers have versions like e.g. 6.14.10.5672 */
1183 pIdentifier
->DriverVersion
->u
.HighPart
= MAKEDWORD_VERSION(6, 14);
1184 /* 71.74 is a current Linux Nvidia driver version */
1185 pIdentifier
->DriverVersion
->u
.LowPart
= MAKEDWORD_VERSION(10, (71*100+74));
1186 *(pIdentifier
->VendorId
) = VENDOR_NVIDIA
;
1187 *(pIdentifier
->DeviceId
) = CARD_NVIDIA_GEFORCE4_TI4600
;
1188 *(pIdentifier
->SubSysId
) = 0;
1189 *(pIdentifier
->Revision
) = 0;
1192 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
1193 if (Flags
& D3DENUM_NO_WHQL_LEVEL
) {
1194 *(pIdentifier
->WHQLLevel
) = 0;
1196 *(pIdentifier
->WHQLLevel
) = 1;
1200 FIXME_(d3d_caps
)("Adapter not primary display\n");
1206 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context
* ctx
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
1207 #if 0 /* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1209 int rb
, gb
, bb
, ab
, type
, buf_sz
;
1211 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_RED_SIZE
, &rb
);
1212 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_GREEN_SIZE
, &gb
);
1213 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_BLUE_SIZE
, &bb
);
1214 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_ALPHA_SIZE
, &ab
);
1215 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_RENDER_TYPE
, &type
);
1216 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_BUFFER_SIZE
, &buf_sz
);
1219 case WINED3DFMT_X8R8G8B8
:
1220 case WINED3DFMT_R8G8B8
:
1221 if (8 == rb
&& 8 == gb
&& 8 == bb
) return TRUE
;
1223 case WINED3DFMT_A8R8G8B8
:
1224 if (8 == rb
&& 8 == gb
&& 8 == bb
&& 8 == ab
) return TRUE
;
1226 case WINED3DFMT_A2R10G10B10
:
1227 if (10 == rb
&& 10 == gb
&& 10 == bb
&& 2 == ab
) return TRUE
;
1229 case WINED3DFMT_X1R5G5B5
:
1230 if (5 == rb
&& 5 == gb
&& 5 == bb
) return TRUE
;
1232 case WINED3DFMT_A1R5G5B5
:
1233 if (5 == rb
&& 5 == gb
&& 5 == bb
&& 1 == ab
) return TRUE
;
1235 case WINED3DFMT_X4R4G4B4
:
1236 if (16 == buf_sz
&& 4 == rb
&& 4 == gb
&& 4 == bb
) return TRUE
;
1238 case WINED3DFMT_R5G6B5
:
1239 if (5 == rb
&& 6 == gb
&& 5 == bb
) return TRUE
;
1241 case WINED3DFMT_R3G3B2
:
1242 if (3 == rb
&& 3 == gb
&& 2 == bb
) return TRUE
;
1244 case WINED3DFMT_A8P8
:
1245 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
&& 8 == ab
) return TRUE
;
1248 if (type
& GLX_COLOR_INDEX_BIT
&& 8 == buf_sz
) return TRUE
;
1251 ERR("unsupported format %s\n", debug_d3dformat(Format
));
1255 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1257 case WINED3DFMT_X8R8G8B8
:
1258 case WINED3DFMT_R8G8B8
:
1259 case WINED3DFMT_A8R8G8B8
:
1260 case WINED3DFMT_A2R10G10B10
:
1261 case WINED3DFMT_X1R5G5B5
:
1262 case WINED3DFMT_A1R5G5B5
:
1263 case WINED3DFMT_R5G6B5
:
1264 case WINED3DFMT_R3G3B2
:
1265 case WINED3DFMT_A8P8
:
1269 ERR("unsupported format %s\n", debug_d3dformat(Format
));
1276 static BOOL
IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context
* ctx
, GLXFBConfig cfgs
, WINED3DFORMAT Format
) {
1277 #if 0/* This code performs a strict test between the format and the current X11 buffer depth, which may give the best performance */
1281 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_DEPTH_SIZE
, &db
);
1282 gl_test
= glXGetFBConfigAttrib(ctx
->display
, cfgs
, GLX_STENCIL_SIZE
, &sb
);
1285 case WINED3DFMT_D16
:
1286 case WINED3DFMT_D16_LOCKABLE
:
1287 if (16 == db
) return TRUE
;
1289 case WINED3DFMT_D32
:
1290 if (32 == db
) return TRUE
;
1292 case WINED3DFMT_D15S1
:
1293 if (15 == db
) return TRUE
;
1295 case WINED3DFMT_D24S8
:
1296 if (24 == db
&& 8 == sb
) return TRUE
;
1298 case WINED3DFMT_D24FS8
:
1299 if (24 == db
&& 8 == sb
) return TRUE
;
1301 case WINED3DFMT_D24X8
:
1302 if (24 == db
) return TRUE
;
1304 case WINED3DFMT_D24X4S4
:
1305 if (24 == db
&& 4 == sb
) return TRUE
;
1307 case WINED3DFMT_D32F_LOCKABLE
:
1308 if (32 == db
) return TRUE
;
1311 ERR("unsupported format %s\n", debug_d3dformat(Format
));
1315 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1317 case WINED3DFMT_D16
:
1318 case WINED3DFMT_D16_LOCKABLE
:
1319 case WINED3DFMT_D32
:
1320 case WINED3DFMT_D15S1
:
1321 case WINED3DFMT_D24S8
:
1322 case WINED3DFMT_D24FS8
:
1323 case WINED3DFMT_D24X8
:
1324 case WINED3DFMT_D24X4S4
:
1325 case WINED3DFMT_D32F_LOCKABLE
:
1328 ERR("unsupported format %s\n", debug_d3dformat(Format
));
1335 static HRESULT WINAPI
IWineD3DImpl_CheckDepthStencilMatch(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1336 WINED3DFORMAT AdapterFormat
,
1337 WINED3DFORMAT RenderTargetFormat
,
1338 WINED3DFORMAT DepthStencilFormat
) {
1339 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1340 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1341 WineD3D_Context
* ctx
= NULL
;
1342 GLXFBConfig
* cfgs
= NULL
;
1346 WARN_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1348 DeviceType
, debug_d3ddevicetype(DeviceType
),
1349 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1350 RenderTargetFormat
, debug_d3dformat(RenderTargetFormat
),
1351 DepthStencilFormat
, debug_d3dformat(DepthStencilFormat
));
1353 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1354 TRACE("(%p) Failed: Atapter (%u) higher than supported adapters (%u) returning WINED3DERR_INVALIDCALL\n", This
, Adapter
, IWineD3D_GetAdapterCount(iface
));
1355 return WINED3DERR_INVALIDCALL
;
1357 /* TODO: use the real context if it's available */
1358 ctx
= WineD3D_CreateFakeGLContext();
1360 cfgs
= glXGetFBConfigs(ctx
->display
, DefaultScreen(ctx
->display
), &nCfgs
);
1362 TRACE_(d3d_caps
)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This
);
1366 for (it
= 0; it
< nCfgs
; ++it
) {
1367 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx
, cfgs
[it
], RenderTargetFormat
)) {
1368 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx
, cfgs
[it
], DepthStencilFormat
)) {
1377 /* If there's a corrent context then we cannot create a fake one so pass everything */
1382 WineD3D_ReleaseFakeGLContext(ctx
);
1384 if (hr
!= WINED3D_OK
)
1385 TRACE_(d3d_caps
)("Failed to match stencil format to device\b");
1387 TRACE_(d3d_caps
)("(%p) : Returning %lx\n", This
, hr
);
1391 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1392 WINED3DFORMAT SurfaceFormat
,
1393 BOOL Windowed
, WINED3DMULTISAMPLE_TYPE MultiSampleType
, DWORD
* pQualityLevels
) {
1395 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1396 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
1399 DeviceType
, debug_d3ddevicetype(DeviceType
),
1400 SurfaceFormat
, debug_d3dformat(SurfaceFormat
),
1405 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1406 return WINED3DERR_INVALIDCALL
;
1409 if (pQualityLevels
!= NULL
) {
1410 static int s_single_shot
= 0;
1411 if (!s_single_shot
) {
1412 FIXME("Quality levels unsupported at present\n");
1415 *pQualityLevels
= 1; /* Guess at a value! */
1418 if (WINED3DMULTISAMPLE_NONE
== MultiSampleType
) return WINED3D_OK
;
1419 return WINED3DERR_NOTAVAILABLE
;
1422 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceType(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE CheckType
,
1423 WINED3DFORMAT DisplayFormat
, WINED3DFORMAT BackBufferFormat
, BOOL Windowed
) {
1425 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1426 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1429 CheckType
, debug_d3ddevicetype(CheckType
),
1430 DisplayFormat
, debug_d3dformat(DisplayFormat
),
1431 BackBufferFormat
, debug_d3dformat(BackBufferFormat
),
1434 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1435 return WINED3DERR_INVALIDCALL
;
1439 GLXFBConfig
* cfgs
= NULL
;
1442 HRESULT hr
= WINED3DERR_NOTAVAILABLE
;
1444 WineD3D_Context
* ctx
= WineD3D_CreateFakeGLContext();
1446 cfgs
= glXGetFBConfigs(ctx
->display
, DefaultScreen(ctx
->display
), &nCfgs
);
1447 for (it
= 0; it
< nCfgs
; ++it
) {
1448 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx
, cfgs
[it
], DisplayFormat
)) {
1455 WineD3D_ReleaseFakeGLContext(ctx
);
1460 return WINED3DERR_NOTAVAILABLE
;
1463 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormat(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1464 WINED3DFORMAT AdapterFormat
, DWORD Usage
, WINED3DRESOURCETYPE RType
, WINED3DFORMAT CheckFormat
) {
1465 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1466 TRACE_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1469 DeviceType
, debug_d3ddevicetype(DeviceType
),
1470 AdapterFormat
, debug_d3dformat(AdapterFormat
),
1471 Usage
, debug_d3dusage(Usage
), debug_d3dusagequery(Usage
),
1472 RType
, debug_d3dresourcetype(RType
),
1473 CheckFormat
, debug_d3dformat(CheckFormat
));
1475 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1476 return WINED3DERR_INVALIDCALL
;
1479 /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
1480 * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
1481 * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
1482 if (Usage
& WINED3DUSAGE_QUERY_VERTEXTEXTURE
) {
1483 TRACE_(d3d_caps
)("[FAILED]\n");
1484 return WINED3DERR_NOTAVAILABLE
; /* Enable when fully supported */
1487 if(Usage
& WINED3DUSAGE_DEPTHSTENCIL
) {
1488 switch (CheckFormat
) {
1489 case WINED3DFMT_D16_LOCKABLE
:
1490 case WINED3DFMT_D32
:
1491 case WINED3DFMT_D15S1
:
1492 case WINED3DFMT_D24S8
:
1493 case WINED3DFMT_D24X8
:
1494 case WINED3DFMT_D24X4S4
:
1495 case WINED3DFMT_D16
:
1496 case WINED3DFMT_L16
:
1497 case WINED3DFMT_D32F_LOCKABLE
:
1498 case WINED3DFMT_D24FS8
:
1499 TRACE_(d3d_caps
)("[OK]\n");
1502 TRACE_(d3d_caps
)("[FAILED]\n");
1503 return WINED3DERR_NOTAVAILABLE
;
1505 } else if(Usage
& WINED3DUSAGE_RENDERTARGET
) {
1506 switch (CheckFormat
) {
1507 case WINED3DFMT_R8G8B8
:
1508 case WINED3DFMT_A8R8G8B8
:
1509 case WINED3DFMT_X8R8G8B8
:
1510 case WINED3DFMT_R5G6B5
:
1511 case WINED3DFMT_X1R5G5B5
:
1512 case WINED3DFMT_A1R5G5B5
:
1513 case WINED3DFMT_A4R4G4B4
:
1514 case WINED3DFMT_R3G3B2
:
1515 case WINED3DFMT_X4R4G4B4
:
1516 case WINED3DFMT_A8B8G8R8
:
1517 case WINED3DFMT_X8B8G8R8
:
1519 TRACE_(d3d_caps
)("[OK]\n");
1522 TRACE_(d3d_caps
)("[FAILED]\n");
1523 return WINED3DERR_NOTAVAILABLE
;
1527 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC
)) {
1528 switch (CheckFormat
) {
1534 TRACE_(d3d_caps
)("[OK]\n");
1537 break; /* Avoid compiler warnings */
1541 /* This format is nothing special and it is supported perfectly.
1542 * However, ati and nvidia driver on windows do not mark this format
1543 * supported(tested with the dxCapsViewer) and pretending to
1544 * support this format uncovers a bug in Battlefield 1942(fonts are missing)
1545 * So do the same as Windows drivers and pretend not to support it on dx8 and 9
1546 * Enable it on dx7. It will need additional checking on dx10 when we support it.
1548 if(This
->dxVersion
> 7 && CheckFormat
== WINED3DFMT_R8G8B8
) {
1549 TRACE_(d3d_caps
)("[FAILED]\n");
1550 return WINED3DERR_NOTAVAILABLE
;
1553 switch (CheckFormat
) {
1556 * supported: RGB(A) formats
1558 case WINED3DFMT_R8G8B8
: /* Enable for dx7, blacklisted for 8 and 9 above */
1559 case WINED3DFMT_A8R8G8B8
:
1560 case WINED3DFMT_X8R8G8B8
:
1561 case WINED3DFMT_R5G6B5
:
1562 case WINED3DFMT_X1R5G5B5
:
1563 case WINED3DFMT_A1R5G5B5
:
1564 case WINED3DFMT_A4R4G4B4
:
1565 case WINED3DFMT_R3G3B2
:
1567 case WINED3DFMT_A8R3G3B2
:
1568 case WINED3DFMT_X4R4G4B4
:
1569 case WINED3DFMT_A8B8G8R8
:
1570 case WINED3DFMT_X8B8G8R8
:
1571 case WINED3DFMT_A2R10G10B10
:
1572 case WINED3DFMT_A2B10G10R10
:
1573 TRACE_(d3d_caps
)("[OK]\n");
1577 * supported: Palettized
1580 TRACE_(d3d_caps
)("[OK]\n");
1584 * Supported: (Alpha)-Luminance
1587 case WINED3DFMT_A8L8
:
1588 case WINED3DFMT_A4L4
:
1589 TRACE_(d3d_caps
)("[OK]\n");
1593 * Not supported for now: Bump mapping formats
1594 * Enable some because games often fail when they are not available
1595 * and are still playable even without bump mapping
1597 case WINED3DFMT_V8U8
:
1598 case WINED3DFMT_V16U16
:
1599 case WINED3DFMT_L6V5U5
:
1600 case WINED3DFMT_X8L8V8U8
:
1601 case WINED3DFMT_Q8W8V8U8
:
1602 case WINED3DFMT_W11V11U10
:
1603 case WINED3DFMT_A2W10V10U10
:
1604 WARN_(d3d_caps
)("[Not supported, but pretended to do]\n");
1608 * DXTN Formats: Handled above
1617 * Odd formats - not supported
1619 case WINED3DFMT_VERTEXDATA
:
1620 case WINED3DFMT_INDEX16
:
1621 case WINED3DFMT_INDEX32
:
1622 case WINED3DFMT_Q16W16V16U16
:
1623 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1624 return WINED3DERR_NOTAVAILABLE
;
1627 * Float formats: Not supported right now
1629 case WINED3DFMT_R16F
:
1630 case WINED3DFMT_G16R16F
:
1631 case WINED3DFMT_A16B16G16R16F
:
1632 case WINED3DFMT_R32F
:
1633 case WINED3DFMT_G32R32F
:
1634 case WINED3DFMT_A32B32G32R32F
:
1635 case WINED3DFMT_CxV8U8
:
1636 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1637 return WINED3DERR_NOTAVAILABLE
;
1640 case WINED3DFMT_G16R16
:
1641 case WINED3DFMT_A16B16G16R16
:
1642 TRACE_(d3d_caps
)("[FAILED]\n"); /* Enable when implemented */
1643 return WINED3DERR_NOTAVAILABLE
;
1649 TRACE_(d3d_caps
)("[FAILED]\n");
1650 return WINED3DERR_NOTAVAILABLE
;
1653 static HRESULT WINAPI
IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
,
1654 WINED3DFORMAT SourceFormat
, WINED3DFORMAT TargetFormat
) {
1655 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1657 FIXME_(d3d_caps
)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
1660 DeviceType
, debug_d3ddevicetype(DeviceType
),
1661 SourceFormat
, debug_d3dformat(SourceFormat
),
1662 TargetFormat
, debug_d3dformat(TargetFormat
));
1666 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1667 subset of a D3DCAPS9 structure. However, it has to come via a void *
1668 as the d3d8 interface cannot import the d3d9 header */
1669 static HRESULT WINAPI
IWineD3DImpl_GetDeviceCaps(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, WINED3DCAPS
* pCaps
) {
1671 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
1673 TRACE_(d3d_caps
)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This
, Adapter
, DeviceType
, pCaps
);
1675 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
1676 return WINED3DERR_INVALIDCALL
;
1679 /* FIXME: both the gl_info and the shader_mode should be made per adapter */
1681 /* If we don't know the device settings, go query them now */
1682 if (This
->isGLInfoValid
== FALSE
) {
1683 /* use the desktop window to fill gl caps */
1684 BOOL rc
= IWineD3DImpl_FillGLCaps(iface
, IWineD3DImpl_GetAdapterDisplay(iface
, Adapter
));
1686 /* We are running off a real context, save the values */
1687 if (rc
) This
->isGLInfoValid
= TRUE
;
1689 select_shader_mode(&This
->gl_info
, DeviceType
,
1690 &wined3d_settings
.ps_selected_mode
, &wined3d_settings
.vs_selected_mode
);
1691 select_shader_max_constants(&This
->gl_info
);
1693 /* ------------------------------------------------
1694 The following fields apply to both d3d8 and d3d9
1695 ------------------------------------------------ */
1696 *pCaps
->DeviceType
= (DeviceType
== WINED3DDEVTYPE_HAL
) ? WINED3DDEVTYPE_HAL
: WINED3DDEVTYPE_REF
; /* Not quite true, but use h/w supported by opengl I suppose */
1697 *pCaps
->AdapterOrdinal
= Adapter
;
1700 *pCaps
->Caps2
= D3DCAPS2_CANRENDERWINDOWED
;
1701 *pCaps
->Caps3
= WINED3DDEVCAPS_HWTRANSFORMANDLIGHT
;
1702 *pCaps
->PresentationIntervals
= D3DPRESENT_INTERVAL_IMMEDIATE
;
1704 *pCaps
->CursorCaps
= 0;
1707 *pCaps
->DevCaps
= WINED3DDEVCAPS_FLOATTLVERTEX
|
1708 WINED3DDEVCAPS_EXECUTESYSTEMMEMORY
|
1709 WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY
|
1710 WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
1711 WINED3DDEVCAPS_DRAWPRIMTLVERTEX
|
1712 WINED3DDEVCAPS_HWTRANSFORMANDLIGHT
|
1713 WINED3DDEVCAPS_EXECUTEVIDEOMEMORY
|
1714 WINED3DDEVCAPS_PUREDEVICE
|
1715 WINED3DDEVCAPS_HWRASTERIZATION
|
1716 WINED3DDEVCAPS_TEXTUREVIDEOMEMORY
|
1717 WINED3DDEVCAPS_TEXTURESYSTEMMEMORY
|
1718 WINED3DDEVCAPS_CANRENDERAFTERFLIP
|
1719 WINED3DDEVCAPS_DRAWPRIMITIVES2
|
1720 WINED3DDEVCAPS_DRAWPRIMITIVES2EX
;
1722 *pCaps
->PrimitiveMiscCaps
= D3DPMISCCAPS_CULLNONE
|
1723 D3DPMISCCAPS_CULLCCW
|
1724 D3DPMISCCAPS_CULLCW
|
1725 D3DPMISCCAPS_COLORWRITEENABLE
|
1726 D3DPMISCCAPS_CLIPTLVERTS
|
1727 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
1728 D3DPMISCCAPS_MASKZ
|
1729 D3DPMISCCAPS_BLENDOP
;
1731 D3DPMISCCAPS_NULLREFERENCE
1732 D3DPMISCCAPS_INDEPENDENTWRITEMASKS
1733 D3DPMISCCAPS_FOGANDSPECULARALPHA
1734 D3DPMISCCAPS_SEPARATEALPHABLEND
1735 D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
1736 D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
1737 D3DPMISCCAPS_FOGVERTEXCLAMPED */
1739 /* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
1741 if (GL_SUPPORT(NV_REGISTER_COMBINERS
))
1742 *pCaps
->PrimitiveMiscCaps
|= D3DPMISCCAPS_TSSARGTEMP
;
1743 if (GL_SUPPORT(NV_REGISTER_COMBINERS2
))
1744 *pCaps
->PrimitiveMiscCaps
|= D3DPMISCCAPS_PERSTAGECONSTANT
;
1747 *pCaps
->RasterCaps
= WINED3DPRASTERCAPS_DITHER
|
1748 WINED3DPRASTERCAPS_PAT
|
1749 WINED3DPRASTERCAPS_WFOG
|
1750 WINED3DPRASTERCAPS_ZFOG
|
1751 WINED3DPRASTERCAPS_FOGVERTEX
|
1752 WINED3DPRASTERCAPS_FOGTABLE
|
1753 WINED3DPRASTERCAPS_FOGRANGE
|
1754 WINED3DPRASTERCAPS_STIPPLE
|
1755 WINED3DPRASTERCAPS_SUBPIXEL
|
1756 WINED3DPRASTERCAPS_ZTEST
|
1757 WINED3DPRASTERCAPS_SCISSORTEST
|
1758 WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
|
1759 WINED3DPRASTERCAPS_DEPTHBIAS
;
1761 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1762 *pCaps
->RasterCaps
|= WINED3DPRASTERCAPS_ANISOTROPY
|
1763 WINED3DPRASTERCAPS_ZBIAS
|
1764 WINED3DPRASTERCAPS_MIPMAPLODBIAS
;
1767 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1768 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1769 WINED3DPRASTERCAPS_ANTIALIASEDGES
1770 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1771 WINED3DPRASTERCAPS_WBUFFER */
1773 *pCaps
->ZCmpCaps
= D3DPCMPCAPS_ALWAYS
|
1775 D3DPCMPCAPS_GREATER
|
1776 D3DPCMPCAPS_GREATEREQUAL
|
1778 D3DPCMPCAPS_LESSEQUAL
|
1780 D3DPCMPCAPS_NOTEQUAL
;
1782 *pCaps
->SrcBlendCaps
= D3DPBLENDCAPS_BLENDFACTOR
|
1783 D3DPBLENDCAPS_BOTHINVSRCALPHA
|
1784 D3DPBLENDCAPS_BOTHSRCALPHA
|
1785 D3DPBLENDCAPS_DESTALPHA
|
1786 D3DPBLENDCAPS_DESTCOLOR
|
1787 D3DPBLENDCAPS_INVDESTALPHA
|
1788 D3DPBLENDCAPS_INVDESTCOLOR
|
1789 D3DPBLENDCAPS_INVSRCALPHA
|
1790 D3DPBLENDCAPS_INVSRCCOLOR
|
1792 D3DPBLENDCAPS_SRCALPHA
|
1793 D3DPBLENDCAPS_SRCALPHASAT
|
1794 D3DPBLENDCAPS_SRCCOLOR
|
1797 *pCaps
->DestBlendCaps
= D3DPBLENDCAPS_BLENDFACTOR
|
1798 D3DPBLENDCAPS_BOTHINVSRCALPHA
|
1799 D3DPBLENDCAPS_BOTHSRCALPHA
|
1800 D3DPBLENDCAPS_DESTALPHA
|
1801 D3DPBLENDCAPS_DESTCOLOR
|
1802 D3DPBLENDCAPS_INVDESTALPHA
|
1803 D3DPBLENDCAPS_INVDESTCOLOR
|
1804 D3DPBLENDCAPS_INVSRCALPHA
|
1805 D3DPBLENDCAPS_INVSRCCOLOR
|
1807 D3DPBLENDCAPS_SRCALPHA
|
1808 D3DPBLENDCAPS_SRCALPHASAT
|
1809 D3DPBLENDCAPS_SRCCOLOR
|
1812 *pCaps
->AlphaCmpCaps
= D3DPCMPCAPS_ALWAYS
|
1814 D3DPCMPCAPS_GREATER
|
1815 D3DPCMPCAPS_GREATEREQUAL
|
1817 D3DPCMPCAPS_LESSEQUAL
|
1819 D3DPCMPCAPS_NOTEQUAL
;
1821 *pCaps
->ShadeCaps
= WINED3DPSHADECAPS_SPECULARGOURAUDRGB
|
1822 WINED3DPSHADECAPS_COLORGOURAUDRGB
|
1823 WINED3DPSHADECAPS_ALPHAFLATBLEND
|
1824 WINED3DPSHADECAPS_ALPHAGOURAUDBLEND
|
1825 WINED3DPSHADECAPS_COLORFLATRGB
|
1826 WINED3DPSHADECAPS_FOGFLAT
|
1827 WINED3DPSHADECAPS_FOGGOURAUD
|
1828 WINED3DPSHADECAPS_SPECULARFLATRGB
;
1830 *pCaps
->TextureCaps
= WINED3DPTEXTURECAPS_ALPHA
|
1831 WINED3DPTEXTURECAPS_ALPHAPALETTE
|
1832 WINED3DPTEXTURECAPS_BORDER
|
1833 WINED3DPTEXTURECAPS_MIPMAP
|
1834 WINED3DPTEXTURECAPS_PROJECTED
|
1835 WINED3DPTEXTURECAPS_PERSPECTIVE
|
1836 WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL
;
1838 if( GL_SUPPORT(EXT_TEXTURE3D
)) {
1839 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_VOLUMEMAP
|
1840 WINED3DPTEXTURECAPS_MIPVOLUMEMAP
|
1841 WINED3DPTEXTURECAPS_VOLUMEMAP_POW2
;
1844 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
1845 *pCaps
->TextureCaps
|= WINED3DPTEXTURECAPS_CUBEMAP
|
1846 WINED3DPTEXTURECAPS_MIPCUBEMAP
|
1847 WINED3DPTEXTURECAPS_CUBEMAP_POW2
;
1851 *pCaps
->TextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
1852 WINED3DPTFILTERCAPS_MAGFPOINT
|
1853 WINED3DPTFILTERCAPS_MINFLINEAR
|
1854 WINED3DPTFILTERCAPS_MINFPOINT
|
1855 WINED3DPTFILTERCAPS_MIPFLINEAR
|
1856 WINED3DPTFILTERCAPS_MIPFPOINT
|
1857 WINED3DPTFILTERCAPS_LINEAR
|
1858 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
1859 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
1860 WINED3DPTFILTERCAPS_MIPLINEAR
|
1861 WINED3DPTFILTERCAPS_MIPNEAREST
|
1862 WINED3DPTFILTERCAPS_NEAREST
;
1864 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1865 *pCaps
->TextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
1866 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
1869 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP
)) {
1870 *pCaps
->CubeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
1871 WINED3DPTFILTERCAPS_MAGFPOINT
|
1872 WINED3DPTFILTERCAPS_MINFLINEAR
|
1873 WINED3DPTFILTERCAPS_MINFPOINT
|
1874 WINED3DPTFILTERCAPS_MIPFLINEAR
|
1875 WINED3DPTFILTERCAPS_MIPFPOINT
|
1876 WINED3DPTFILTERCAPS_LINEAR
|
1877 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
1878 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
1879 WINED3DPTFILTERCAPS_MIPLINEAR
|
1880 WINED3DPTFILTERCAPS_MIPNEAREST
|
1881 WINED3DPTFILTERCAPS_NEAREST
;
1883 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC
)) {
1884 *pCaps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
|
1885 WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
1888 *pCaps
->CubeTextureFilterCaps
= 0;
1890 if (GL_SUPPORT(EXT_TEXTURE3D
)) {
1891 *pCaps
->VolumeTextureFilterCaps
= WINED3DPTFILTERCAPS_MAGFLINEAR
|
1892 WINED3DPTFILTERCAPS_MAGFPOINT
|
1893 WINED3DPTFILTERCAPS_MINFLINEAR
|
1894 WINED3DPTFILTERCAPS_MINFPOINT
|
1895 WINED3DPTFILTERCAPS_MIPFLINEAR
|
1896 WINED3DPTFILTERCAPS_MIPFPOINT
|
1897 WINED3DPTFILTERCAPS_LINEAR
|
1898 WINED3DPTFILTERCAPS_LINEARMIPLINEAR
|
1899 WINED3DPTFILTERCAPS_LINEARMIPNEAREST
|
1900 WINED3DPTFILTERCAPS_MIPLINEAR
|
1901 WINED3DPTFILTERCAPS_MIPNEAREST
|
1902 WINED3DPTFILTERCAPS_NEAREST
;
1904 *pCaps
->VolumeTextureFilterCaps
= 0;
1906 *pCaps
->TextureAddressCaps
= D3DPTADDRESSCAPS_INDEPENDENTUV
|
1907 D3DPTADDRESSCAPS_CLAMP
|
1908 D3DPTADDRESSCAPS_WRAP
;
1910 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP
)) {
1911 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_BORDER
;
1913 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT
)) {
1914 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_MIRROR
;
1916 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE
)) {
1917 *pCaps
->TextureAddressCaps
|= D3DPTADDRESSCAPS_MIRRORONCE
;
1920 *pCaps
->VolumeTextureAddressCaps
= 0;
1922 *pCaps
->LineCaps
= D3DLINECAPS_TEXTURE
|
1926 D3DLINECAPS_ALPHACMP
1929 *pCaps
->MaxTextureWidth
= GL_LIMITS(texture_size
);
1930 *pCaps
->MaxTextureHeight
= GL_LIMITS(texture_size
);
1932 if(GL_SUPPORT(EXT_TEXTURE3D
))
1933 *pCaps
->MaxVolumeExtent
= GL_LIMITS(texture3d_size
);
1935 *pCaps
->MaxVolumeExtent
= 0;
1937 *pCaps
->MaxTextureRepeat
= 32768;
1938 *pCaps
->MaxTextureAspectRatio
= GL_LIMITS(texture_size
);
1939 *pCaps
->MaxVertexW
= 1.0;
1941 *pCaps
->GuardBandLeft
= 0;
1942 *pCaps
->GuardBandTop
= 0;
1943 *pCaps
->GuardBandRight
= 0;
1944 *pCaps
->GuardBandBottom
= 0;
1946 *pCaps
->ExtentsAdjust
= 0;
1948 *pCaps
->StencilCaps
= D3DSTENCILCAPS_DECRSAT
|
1949 D3DSTENCILCAPS_INCRSAT
|
1950 D3DSTENCILCAPS_INVERT
|
1951 D3DSTENCILCAPS_KEEP
|
1952 D3DSTENCILCAPS_REPLACE
|
1953 D3DSTENCILCAPS_ZERO
;
1954 if (GL_SUPPORT(EXT_STENCIL_WRAP
)) {
1955 *pCaps
->StencilCaps
|= D3DSTENCILCAPS_DECR
|
1956 D3DSTENCILCAPS_INCR
;
1958 if ( This
->dxVersion
> 8 &&
1959 ( GL_SUPPORT(EXT_STENCIL_TWO_SIDE
) ||
1960 GL_SUPPORT(ATI_SEPARATE_STENCIL
) ) ) {
1961 *pCaps
->StencilCaps
|= D3DSTENCILCAPS_TWOSIDED
;
1964 *pCaps
->FVFCaps
= D3DFVFCAPS_PSIZE
| 0x0008; /* 8 texture coords */
1966 *pCaps
->TextureOpCaps
= D3DTEXOPCAPS_ADD
|
1967 D3DTEXOPCAPS_ADDSIGNED
|
1968 D3DTEXOPCAPS_ADDSIGNED2X
|
1969 D3DTEXOPCAPS_MODULATE
|
1970 D3DTEXOPCAPS_MODULATE2X
|
1971 D3DTEXOPCAPS_MODULATE4X
|
1972 D3DTEXOPCAPS_SELECTARG1
|
1973 D3DTEXOPCAPS_SELECTARG2
|
1974 D3DTEXOPCAPS_DISABLE
;
1976 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE
) ||
1977 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE
) ||
1978 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
1979 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
1980 D3DTEXOPCAPS_BLENDTEXTUREALPHA
|
1981 D3DTEXOPCAPS_BLENDFACTORALPHA
|
1982 D3DTEXOPCAPS_BLENDCURRENTALPHA
|
1984 D3DTEXOPCAPS_SUBTRACT
;
1986 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4
)) {
1987 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_ADDSMOOTH
|
1988 D3DTEXOPCAPS_MULTIPLYADD
|
1989 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
1990 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
1991 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM
;
1993 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3
))
1994 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_DOTPRODUCT3
;
1996 if (GL_SUPPORT(NV_REGISTER_COMBINERS
)) {
1997 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
|
1998 D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
;
2003 *pCaps
->TextureOpCaps
|= D3DTEXOPCAPS_BUMPENVMAP
;
2005 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2006 D3DTEXOPCAPS_PREMODULATE */
2009 *pCaps
->MaxTextureBlendStages
= GL_LIMITS(texture_stages
);
2010 *pCaps
->MaxSimultaneousTextures
= GL_LIMITS(textures
);
2011 *pCaps
->MaxUserClipPlanes
= GL_LIMITS(clipplanes
);
2012 *pCaps
->MaxActiveLights
= GL_LIMITS(lights
);
2016 #if 0 /* TODO: Blends support in drawprim */
2017 *pCaps
->MaxVertexBlendMatrices
= GL_LIMITS(blends
);
2019 *pCaps
->MaxVertexBlendMatrices
= 0;
2021 *pCaps
->MaxVertexBlendMatrixIndex
= 1;
2023 *pCaps
->MaxAnisotropy
= GL_LIMITS(anisotropy
);
2024 *pCaps
->MaxPointSize
= GL_LIMITS(pointsize
);
2027 *pCaps
->VertexProcessingCaps
= WINED3DVTXPCAPS_DIRECTIONALLIGHTS
|
2028 WINED3DVTXPCAPS_MATERIALSOURCE7
|
2029 WINED3DVTXPCAPS_POSITIONALLIGHTS
|
2030 WINED3DVTXPCAPS_LOCALVIEWER
|
2031 WINED3DVTXPCAPS_VERTEXFOG
|
2032 WINED3DVTXPCAPS_TEXGEN
;
2034 D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
2036 *pCaps
->MaxPrimitiveCount
= 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
2037 *pCaps
->MaxVertexIndex
= 0xFFFFF;
2038 *pCaps
->MaxStreams
= MAX_STREAMS
;
2039 *pCaps
->MaxStreamStride
= 1024;
2041 /* FIXME: the shader mode should be per adapter */
2042 if (wined3d_settings
.vs_selected_mode
== SHADER_GLSL
) {
2043 /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
2044 models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
2045 vs_nv_version which is based on NV_vertex_program. For Ati cards there's no easy way, so for
2046 now only support 2.0/3.0 detection on Nvidia GeforceFX cards and default to 3.0 for everything else */
2047 if(This
->gl_info
.vs_nv_version
== VS_VERSION_20
)
2048 *pCaps
->VertexShaderVersion
= D3DVS_VERSION(2,0);
2050 *pCaps
->VertexShaderVersion
= D3DVS_VERSION(3,0);
2051 TRACE_(d3d_caps
)("Hardware vertex shader version 3.0 enabled (GLSL)\n");
2052 } else if (wined3d_settings
.vs_selected_mode
== SHADER_ARB
) {
2053 *pCaps
->VertexShaderVersion
= D3DVS_VERSION(1,1);
2054 TRACE_(d3d_caps
)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
2055 } else if (wined3d_settings
.vs_selected_mode
== SHADER_SW
) {
2056 *pCaps
->VertexShaderVersion
= D3DVS_VERSION(3,0);
2057 TRACE_(d3d_caps
)("Software vertex shader version 3.0 enabled\n");
2059 *pCaps
->VertexShaderVersion
= 0;
2060 TRACE_(d3d_caps
)("Vertex shader functionality not available\n");
2063 *pCaps
->MaxVertexShaderConst
= GL_LIMITS(vshader_constantsF
);
2065 /* FIXME: the shader mode should be per adapter */
2066 if (wined3d_settings
.ps_selected_mode
== SHADER_GLSL
) {
2067 /* See the comment about VS2.0/VS3.0 detection as we do the same here but then based on NV_fragment_program
2068 in case of GeforceFX cards. */
2069 if(This
->gl_info
.ps_nv_version
== PS_VERSION_20
)
2070 *pCaps
->PixelShaderVersion
= D3DPS_VERSION(2,0);
2072 *pCaps
->PixelShaderVersion
= D3DPS_VERSION(3,0);
2073 /* FIXME: The following line is card dependent. -1.0 to 1.0 is a safe default clamp range for now */
2074 *pCaps
->PixelShader1xMaxValue
= 1.0;
2075 TRACE_(d3d_caps
)("Hardware pixel shader version 3.0 enabled (GLSL)\n");
2076 } else if (wined3d_settings
.ps_selected_mode
== SHADER_ARB
) {
2077 *pCaps
->PixelShaderVersion
= D3DPS_VERSION(1,4);
2078 *pCaps
->PixelShader1xMaxValue
= 1.0;
2079 TRACE_(d3d_caps
)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
2080 /* FIXME: Uncomment this when there is support for software Pixel Shader 3.0 and PS_SW is defined
2081 } else if (wined3d_settings.ps_selected_mode = SHADER_SW) {
2082 *pCaps->PixelShaderVersion = D3DPS_VERSION(3,0);
2083 *pCaps->PixelShader1xMaxValue = 1.0;
2084 TRACE_(d3d_caps)("Software pixel shader version 3.0 enabled\n"); */
2086 *pCaps
->PixelShaderVersion
= 0;
2087 *pCaps
->PixelShader1xMaxValue
= 0.0;
2088 TRACE_(d3d_caps
)("Pixel shader functionality not available\n");
2091 /* ------------------------------------------------
2092 The following fields apply to d3d9 only
2093 ------------------------------------------------ */
2094 if (This
->dxVersion
> 8) {
2095 GLint max_buffers
= 1;
2096 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
2097 *pCaps
->DevCaps2
= 0;
2098 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES and VS3.0 needs atleast D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
2099 *pCaps
->MaxNpatchTessellationLevel
= 0;
2100 *pCaps
->MasterAdapterOrdinal
= 0;
2101 *pCaps
->AdapterOrdinalInGroup
= 0;
2102 *pCaps
->NumberOfAdaptersInGroup
= 1;
2104 if(*pCaps
->VertexShaderVersion
>= D3DVS_VERSION(2,0)) {
2105 /* OpenGL supports all formats below perhaps not allways without conversion but it supports them.
2106 Further GLSL doesn't seem to have an official unsigned type as I'm not sure how we handle it
2107 don't advertise iet yet. We might need to add some clamping in the shader engine to support it.
2108 TODO: D3DDTCAPS_USHORT2N, D3DDTCAPS_USHORT4N, D3DDTCAPS_UDEC3, D3DDTCAPS_DEC3N */
2109 *pCaps
->DeclTypes
= D3DDTCAPS_UBYTE4
|
2113 D3DDTCAPS_FLOAT16_2
|
2114 D3DDTCAPS_FLOAT16_4
;
2117 *pCaps
->DeclTypes
= 0;
2119 #if 0 /*FIXME: Simultaneous render targets*/
2120 GL_MAX_DRAW_BUFFERS_ATI
0x00008824
2121 if (GL_SUPPORT(GL_MAX_DRAW_BUFFERS_ATI
)) {
2123 glEnable(GL_MAX_DRAW_BUFFERS_ATI
);
2124 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI
, &max_buffers
);
2125 glDisable(GL_MAX_DRAW_BUFFERS_ATI
);
2129 *pCaps
->NumSimultaneousRTs
= max_buffers
;
2130 *pCaps
->StretchRectFilterCaps
= 0;
2131 *pCaps
->VertexTextureFilterCaps
= 0;
2133 if(*pCaps
->VertexShaderVersion
== D3DVS_VERSION(3,0)) {
2134 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2135 use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
2136 *pCaps
->VS20Caps
.Caps
= D3DVS20CAPS_PREDICATION
;
2137 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= D3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2138 *pCaps
->VS20Caps
.NumTemps
= max(32, This
->gl_info
.vs_arb_max_temps
);
2139 *pCaps
->VS20Caps
.StaticFlowControlDepth
= D3DVS20_MAX_STATICFLOWCONTROLDEPTH
; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
2141 *pCaps
->MaxVShaderInstructionsExecuted
= 65535; /* VS 3.0 needs atleast 65535, some cards even use 2^32-1 */
2142 *pCaps
->MaxVertexShader30InstructionSlots
= max(512, This
->gl_info
.vs_arb_max_instructions
);
2143 } else if(*pCaps
->VertexShaderVersion
== D3DVS_VERSION(2,0)) {
2144 *pCaps
->VS20Caps
.Caps
= 0;
2145 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH
;
2146 *pCaps
->VS20Caps
.NumTemps
= max(12, This
->gl_info
.vs_arb_max_temps
);
2147 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 1;
2149 *pCaps
->MaxVShaderInstructionsExecuted
= 65535;
2150 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2151 } else { /* VS 1.x */
2152 *pCaps
->VS20Caps
.Caps
= 0;
2153 *pCaps
->VS20Caps
.DynamicFlowControlDepth
= 0;
2154 *pCaps
->VS20Caps
.NumTemps
= 0;
2155 *pCaps
->VS20Caps
.StaticFlowControlDepth
= 0;
2157 *pCaps
->MaxVShaderInstructionsExecuted
= 0;
2158 *pCaps
->MaxVertexShader30InstructionSlots
= 0;
2161 if(*pCaps
->PixelShaderVersion
== D3DPS_VERSION(3,0)) {
2162 /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
2163 use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
2165 /* 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 */
2166 *pCaps
->PS20Caps
.Caps
= D3DPS20CAPS_ARBITRARYSWIZZLE
|
2167 D3DPS20CAPS_GRADIENTINSTRUCTIONS
|
2168 D3DPS20CAPS_PREDICATION
|
2169 D3DPS20CAPS_NODEPENDENTREADLIMIT
|
2170 D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT
;
2171 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= D3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
2172 *pCaps
->PS20Caps
.NumTemps
= max(32, This
->gl_info
.ps_arb_max_temps
);
2173 *pCaps
->PS20Caps
.StaticFlowControlDepth
= D3DPS20_MAX_STATICFLOWCONTROLDEPTH
; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
2174 *pCaps
->PS20Caps
.NumInstructionSlots
= D3DPS20_MAX_NUMINSTRUCTIONSLOTS
; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
2176 *pCaps
->MaxPShaderInstructionsExecuted
= 65535;
2177 *pCaps
->MaxPixelShader30InstructionSlots
= max(D3DMIN30SHADERINSTRUCTIONS
, This
->gl_info
.ps_arb_max_instructions
);
2178 } else if(*pCaps
->PixelShaderVersion
== D3DPS_VERSION(2,0)) {
2179 /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
2180 *pCaps
->PS20Caps
.Caps
= 0;
2181 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0; /* D3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
2182 *pCaps
->PS20Caps
.NumTemps
= max(12, This
->gl_info
.ps_arb_max_temps
);
2183 *pCaps
->PS20Caps
.StaticFlowControlDepth
= D3DPS20_MIN_STATICFLOWCONTROLDEPTH
; /* Minumum: 1 */
2184 *pCaps
->PS20Caps
.NumInstructionSlots
= D3DPS20_MIN_NUMINSTRUCTIONSLOTS
; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
2186 *pCaps
->MaxPShaderInstructionsExecuted
= 512; /* Minimum value, a GeforceFX uses 1024 */
2187 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2188 } else { /* PS 1.x */
2189 *pCaps
->PS20Caps
.Caps
= 0;
2190 *pCaps
->PS20Caps
.DynamicFlowControlDepth
= 0;
2191 *pCaps
->PS20Caps
.NumTemps
= 0;
2192 *pCaps
->PS20Caps
.StaticFlowControlDepth
= 0;
2193 *pCaps
->PS20Caps
.NumInstructionSlots
= 0;
2195 *pCaps
->MaxPShaderInstructionsExecuted
= 0;
2196 *pCaps
->MaxPixelShader30InstructionSlots
= 0;
2204 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
2205 and fields being inserted in the middle, a new structure is used in place */
2206 static HRESULT WINAPI
IWineD3DImpl_CreateDevice(IWineD3D
*iface
, UINT Adapter
, WINED3DDEVTYPE DeviceType
, HWND hFocusWindow
,
2207 DWORD BehaviourFlags
, IWineD3DDevice
** ppReturnedDeviceInterface
,
2210 IWineD3DDeviceImpl
*object
= NULL
;
2211 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2213 HRESULT temp_result
;
2215 /* Validate the adapter number */
2216 if (Adapter
>= IWineD3D_GetAdapterCount(iface
)) {
2217 return WINED3DERR_INVALIDCALL
;
2220 /* Create a WineD3DDevice object */
2221 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IWineD3DDeviceImpl
));
2222 *ppReturnedDeviceInterface
= (IWineD3DDevice
*)object
;
2223 TRACE("Created WineD3DDevice object @ %p\n", object
);
2224 if (NULL
== object
) {
2225 return WINED3DERR_OUTOFVIDEOMEMORY
;
2228 /* Set up initial COM information */
2229 object
->lpVtbl
= &IWineD3DDevice_Vtbl
;
2231 object
->wineD3D
= iface
;
2232 IWineD3D_AddRef(object
->wineD3D
);
2233 object
->parent
= parent
;
2235 /* Set the state up as invalid until the device is fully created */
2236 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2238 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, RetDevInt: %p)\n", This
, Adapter
, DeviceType
,
2239 hFocusWindow
, BehaviourFlags
, ppReturnedDeviceInterface
);
2241 /* Save the creation parameters */
2242 object
->createParms
.AdapterOrdinal
= Adapter
;
2243 object
->createParms
.DeviceType
= DeviceType
;
2244 object
->createParms
.hFocusWindow
= hFocusWindow
;
2245 object
->createParms
.BehaviorFlags
= BehaviourFlags
;
2247 /* Initialize other useful values */
2248 object
->adapterNo
= Adapter
;
2249 object
->devType
= DeviceType
;
2251 TRACE("(%p) : Creating stateblock\n", This
);
2252 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
2253 if (WINED3D_OK
!= IWineD3DDevice_CreateStateBlock((IWineD3DDevice
*)object
,
2255 (IWineD3DStateBlock
**)&object
->stateBlock
,
2256 NULL
) || NULL
== object
->stateBlock
) { /* Note: No parent needed for initial internal stateblock */
2257 WARN("Failed to create stateblock\n");
2258 goto create_device_error
;
2260 TRACE("(%p) : Created stateblock (%p)\n", This
, object
->stateBlock
);
2261 object
->updateStateBlock
= object
->stateBlock
;
2262 IWineD3DStateBlock_AddRef((IWineD3DStateBlock
*)object
->updateStateBlock
);
2263 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
2265 /* Setup some defaults for creating the implicit swapchain */
2267 /* FIXME: both of those should be made per adapter */
2268 IWineD3DImpl_FillGLCaps(iface
, IWineD3DImpl_GetAdapterDisplay(iface
, Adapter
));
2270 select_shader_mode(&This
->gl_info
, DeviceType
,
2271 &wined3d_settings
.ps_selected_mode
, &wined3d_settings
.vs_selected_mode
);
2272 select_shader_max_constants(&This
->gl_info
);
2274 temp_result
= allocate_shader_constants(object
->updateStateBlock
);
2275 if (WINED3D_OK
!= temp_result
)
2278 /* set the state of the device to valid */
2279 object
->state
= WINED3D_OK
;
2281 /* Get the initial screen setup for ddraw */
2282 object
->ddraw_width
= GetSystemMetrics(SM_CXSCREEN
);
2283 object
->ddraw_height
= GetSystemMetrics(SM_CYSCREEN
);
2284 hDC
= CreateDCA("DISPLAY", NULL
, NULL
, NULL
);
2285 object
->ddraw_format
= pixelformat_for_depth(GetDeviceCaps(hDC
, BITSPIXEL
) * GetDeviceCaps(hDC
, PLANES
));
2289 create_device_error
:
2291 /* Set the device state to error */
2292 object
->state
= WINED3DERR_DRIVERINTERNALERROR
;
2294 if (object
->updateStateBlock
!= NULL
) {
2295 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)object
->updateStateBlock
);
2296 object
->updateStateBlock
= NULL
;
2298 if (object
->stateBlock
!= NULL
) {
2299 IWineD3DStateBlock_Release((IWineD3DStateBlock
*)object
->stateBlock
);
2300 object
->stateBlock
= NULL
;
2302 if (object
->renderTarget
!= NULL
) {
2303 IWineD3DSurface_Release(object
->renderTarget
);
2304 object
->renderTarget
= NULL
;
2306 if (object
->stencilBufferTarget
!= NULL
) {
2307 IWineD3DSurface_Release(object
->stencilBufferTarget
);
2308 object
->stencilBufferTarget
= NULL
;
2310 if (object
->stencilBufferTarget
!= NULL
) {
2311 IWineD3DSurface_Release(object
->stencilBufferTarget
);
2312 object
->stencilBufferTarget
= NULL
;
2314 HeapFree(GetProcessHeap(), 0, object
);
2315 *ppReturnedDeviceInterface
= NULL
;
2316 return WINED3DERR_INVALIDCALL
;
2320 static HRESULT WINAPI
IWineD3DImpl_GetParent(IWineD3D
*iface
, IUnknown
**pParent
) {
2321 IWineD3DImpl
*This
= (IWineD3DImpl
*)iface
;
2322 IUnknown_AddRef(This
->parent
);
2323 *pParent
= This
->parent
;
2327 /**********************************************************
2328 * IWineD3D VTbl follows
2329 **********************************************************/
2331 const IWineD3DVtbl IWineD3D_Vtbl
=
2334 IWineD3DImpl_QueryInterface
,
2335 IWineD3DImpl_AddRef
,
2336 IWineD3DImpl_Release
,
2338 IWineD3DImpl_GetParent
,
2339 IWineD3DImpl_GetAdapterCount
,
2340 IWineD3DImpl_RegisterSoftwareDevice
,
2341 IWineD3DImpl_GetAdapterMonitor
,
2342 IWineD3DImpl_GetAdapterModeCount
,
2343 IWineD3DImpl_EnumAdapterModes
,
2344 IWineD3DImpl_GetAdapterDisplayMode
,
2345 IWineD3DImpl_GetAdapterIdentifier
,
2346 IWineD3DImpl_CheckDeviceMultiSampleType
,
2347 IWineD3DImpl_CheckDepthStencilMatch
,
2348 IWineD3DImpl_CheckDeviceType
,
2349 IWineD3DImpl_CheckDeviceFormat
,
2350 IWineD3DImpl_CheckDeviceFormatConversion
,
2351 IWineD3DImpl_GetDeviceCaps
,
2352 IWineD3DImpl_CreateDevice