Add support for proper saving of the "FLATMENU" and "GRADIENTCAPION"
[wine/dcerpc.git] / dlls / wined3d / directx.c
blob4938c88b650b3d0f2518f092e50d93fab595d8b0
1 /*
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 /* Compile time diagnostics: */
26 /* Uncomment this to force only a single display mode to be exposed: */
27 /*#define DEBUG_SINGLE_MODE*/
30 #include "config.h"
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 )
53 Display *display;
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;
58 return display;
61 /**
62 * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
63 * ie there is no GL Context - Get a default rendering context to enable the
64 * function query some info from GL
65 */
66 static WineD3D_Context* WineD3D_CreateFakeGLContext(void) {
67 static WineD3D_Context ctx = { NULL, NULL, NULL, 0, 0 };
68 WineD3D_Context* ret = NULL;
70 if (glXGetCurrentContext() == NULL) {
71 BOOL gotContext = FALSE;
72 BOOL created = FALSE;
73 XVisualInfo template;
74 HDC device_context;
75 Visual* visual;
76 BOOL failed = FALSE;
77 int num;
78 XWindowAttributes win_attr;
80 TRACE_(d3d_caps)("Creating Fake GL Context\n");
82 ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
84 /* Get the display */
85 device_context = GetDC(0);
86 ctx.display = get_display(device_context);
87 ReleaseDC(0, device_context);
89 /* Get the X visual */
90 ENTER_GL();
91 if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
92 visual = win_attr.visual;
93 } else {
94 visual = DefaultVisual(ctx.display, DefaultScreen(ctx.display));
96 template.visualid = XVisualIDFromVisual(visual);
97 ctx.visInfo = XGetVisualInfo(ctx.display, VisualIDMask, &template, &num);
98 if (ctx.visInfo == NULL) {
99 LEAVE_GL();
100 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
101 failed = TRUE;
104 /* Create a GL context */
105 if (!failed) {
106 ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
108 if (ctx.glCtx == NULL) {
109 LEAVE_GL();
110 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
111 failed = TRUE;
115 /* Make it the current GL context */
116 if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
117 glXDestroyContext(ctx.display, ctx.glCtx);
118 LEAVE_GL();
119 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
120 failed = TRUE;
123 /* It worked! Wow... */
124 if (!failed) {
125 gotContext = TRUE;
126 created = TRUE;
127 ret = &ctx;
128 } else {
129 ret = NULL;
132 } else {
133 if (ctx.ref > 0) ret = &ctx;
136 if (NULL != ret) InterlockedIncrement(&ret->ref);
137 return ret;
140 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
141 /* If we created a dummy context, throw it away */
142 if (NULL != ctx) {
143 if (0 == InterlockedDecrement(&ctx->ref)) {
144 glXMakeCurrent(ctx->display, None, NULL);
145 glXDestroyContext(ctx->display, ctx->glCtx);
146 ctx->display = NULL;
147 ctx->glCtx = NULL;
148 LEAVE_GL();
153 /**********************************************************
154 * IUnknown parts follows
155 **********************************************************/
157 HRESULT WINAPI IWineD3DImpl_QueryInterface(IWineD3D *iface,REFIID riid,LPVOID *ppobj)
159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
160 /* FIXME: This needs to extend an IWineD3DBaseObject */
162 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
163 if (IsEqualGUID(riid, &IID_IUnknown)
164 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
165 IUnknown_AddRef(iface);
166 *ppobj = This;
167 return D3D_OK;
170 return E_NOINTERFACE;
173 ULONG WINAPI IWineD3DImpl_AddRef(IWineD3D *iface) {
174 IWineD3DImpl *This = (IWineD3DImpl *)iface;
175 ULONG refCount = InterlockedIncrement(&This->ref);
177 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
178 return refCount;
181 ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
182 IWineD3DImpl *This = (IWineD3DImpl *)iface;
183 ULONG ref;
184 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
185 ref = InterlockedDecrement(&This->ref);
186 if (ref == 0) {
187 HeapFree(GetProcessHeap(), 0, This);
190 return ref;
193 /**********************************************************
194 * IWineD3D parts follows
195 **********************************************************/
197 static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info, Display* display) {
198 const char *GL_Extensions = NULL;
199 const char *GLX_Extensions = NULL;
200 const char *gl_string = NULL;
201 const char *gl_string_cursor = NULL;
202 GLint gl_max;
203 Bool test = 0;
204 int major, minor;
206 TRACE_(d3d_caps)("(%p, %p)\n", gl_info, display);
208 /* Fill in the GL info retrievable depending on the display */
209 if (NULL != display) {
210 test = glXQueryVersion(display, &major, &minor);
211 gl_info->glx_version = ((major & 0x0000FFFF) << 16) | (minor & 0x0000FFFF);
212 gl_string = glXGetClientString(display, GLX_VENDOR);
213 } else {
214 gl_string = glGetString(GL_VENDOR);
217 /* Fill in the GL vendor */
218 if (strstr(gl_string, "NVIDIA")) {
219 gl_info->gl_vendor = VENDOR_NVIDIA;
220 } else if (strstr(gl_string, "ATI")) {
221 gl_info->gl_vendor = VENDOR_ATI;
222 } else {
223 gl_info->gl_vendor = VENDOR_WINE;
226 TRACE_(d3d_caps)("found GL_VENDOR (%s)->(0x%04x)\n", debugstr_a(gl_string), gl_info->gl_vendor);
228 /* Parse the GL_VERSION field into major and minor information */
229 gl_string = glGetString(GL_VERSION);
230 switch (gl_info->gl_vendor) {
231 case VENDOR_NVIDIA:
232 gl_string_cursor = strstr(gl_string, "NVIDIA");
233 gl_string_cursor = strstr(gl_string_cursor, " ");
234 while (*gl_string_cursor && ' ' == *gl_string_cursor) ++gl_string_cursor;
235 if (*gl_string_cursor) {
236 char tmp[16];
237 int cursor = 0;
239 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
240 tmp[cursor++] = *gl_string_cursor;
241 ++gl_string_cursor;
243 tmp[cursor] = 0;
244 major = atoi(tmp);
246 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
247 ++gl_string_cursor;
249 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
250 tmp[cursor++] = *gl_string_cursor;
251 ++gl_string_cursor;
253 tmp[cursor] = 0;
254 minor = atoi(tmp);
256 break;
258 case VENDOR_ATI:
259 major = minor = 0;
260 gl_string_cursor = strchr(gl_string, '-');
261 if (gl_string_cursor) {
262 int error = 0;
263 gl_string_cursor++;
265 /* Check if version number is of the form x.y.z */
266 if (*gl_string_cursor > '9' && *gl_string_cursor < '0')
267 error = 1;
268 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
269 error = 1;
270 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
271 error = 1;
272 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
273 error = 1;
275 /* Mark version number as malformed */
276 if (error)
277 gl_string_cursor = 0;
280 if (!gl_string_cursor)
281 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
282 else {
283 major = *gl_string_cursor - '0';
284 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
286 break;
288 default:
289 major = 0;
290 minor = 9;
292 gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
293 TRACE_(d3d_caps)("found GL_VERSION (%s)->(0x%08lx)\n", debugstr_a(gl_string), gl_info->gl_driver_version);
295 /* Fill in the renderer information */
296 gl_string = glGetString(GL_RENDERER);
297 strcpy(gl_info->gl_renderer, gl_string);
299 switch (gl_info->gl_vendor) {
300 case VENDOR_NVIDIA:
301 if (strstr(gl_info->gl_renderer, "GeForce4 Ti")) {
302 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
303 } else if (strstr(gl_info->gl_renderer, "GeForceFX")) {
304 gl_info->gl_card = CARD_NVIDIA_GEFORCEFX_5900ULTRA;
305 } else {
306 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
308 break;
310 case VENDOR_ATI:
311 if (strstr(gl_info->gl_renderer, "RADEON 9800 PRO")) {
312 gl_info->gl_card = CARD_ATI_RADEON_9800PRO;
313 } else if (strstr(gl_info->gl_renderer, "RADEON 9700 PRO")) {
314 gl_info->gl_card = CARD_ATI_RADEON_9700PRO;
315 } else {
316 gl_info->gl_card = CARD_ATI_RADEON_8500;
318 break;
320 default:
321 gl_info->gl_card = CARD_WINE;
322 break;
325 TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
328 * Initialize openGL extension related variables
329 * with Default values
331 memset(&gl_info->supported, 0, sizeof(gl_info->supported));
332 gl_info->max_textures = 1;
333 gl_info->max_samplers = 1;
334 gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
335 gl_info->vs_arb_version = VS_VERSION_NOT_SUPPORTED;
336 gl_info->vs_nv_version = VS_VERSION_NOT_SUPPORTED;
337 gl_info->vs_ati_version = VS_VERSION_NOT_SUPPORTED;
339 /* Now work out what GL support this card really has */
340 #define USE_GL_FUNC(type, pfn) gl_info->pfn = NULL;
341 GL_EXT_FUNCS_GEN;
342 #undef USE_GL_FUNC
344 /* Retrieve opengl defaults */
345 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
346 gl_info->max_clipplanes = min(D3DMAXUSERCLIPPLANES, gl_max);
347 TRACE_(d3d_caps)("ClipPlanes support - num Planes=%d\n", gl_max);
349 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
350 gl_info->max_lights = gl_max;
351 TRACE_(d3d_caps)("Lights support - max lights=%d\n", gl_max);
353 /* Parse the gl supported features, in theory enabling parts of our code appropriately */
354 GL_Extensions = glGetString(GL_EXTENSIONS);
355 TRACE_(d3d_caps)("GL_Extensions reported:\n");
357 if (NULL == GL_Extensions) {
358 ERR(" GL_Extensions returns NULL\n");
359 } else {
360 while (*GL_Extensions != 0x00) {
361 const char *Start = GL_Extensions;
362 char ThisExtn[256];
364 memset(ThisExtn, 0x00, sizeof(ThisExtn));
365 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
366 GL_Extensions++;
368 memcpy(ThisExtn, Start, (GL_Extensions - Start));
369 TRACE_(d3d_caps)("- %s\n", ThisExtn);
372 * ARB
374 if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
375 gl_info->ps_arb_version = PS_VERSION_11;
376 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - version=%02x\n", gl_info->ps_arb_version);
377 gl_info->supported[ARB_FRAGMENT_PROGRAM] = TRUE;
378 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &gl_max);
379 TRACE_(d3d_caps)(" FOUND: ARB Pixel Shader support - GL_MAX_TEXTURE_IMAGE_UNITS_ARB=%u\n", gl_max);
380 gl_info->max_samplers = min(16, gl_max);
381 } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
382 TRACE_(d3d_caps)(" FOUND: ARB Multisample support\n");
383 gl_info->supported[ARB_MULTISAMPLE] = TRUE;
384 } else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
385 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
386 TRACE_(d3d_caps)(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
387 gl_info->supported[ARB_MULTITEXTURE] = TRUE;
388 gl_info->max_textures = min(8, gl_max);
389 gl_info->max_samplers = max(gl_info->max_samplers, gl_max);
390 } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
391 TRACE_(d3d_caps)(" FOUND: ARB Texture Cube Map support\n");
392 gl_info->supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
393 TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
394 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
395 } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
396 TRACE_(d3d_caps)(" FOUND: ARB Texture Compression support\n");
397 gl_info->supported[ARB_TEXTURE_COMPRESSION] = TRUE;
398 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_add") == 0) {
399 TRACE_(d3d_caps)(" FOUND: ARB Texture Env Add support\n");
400 gl_info->supported[ARB_TEXTURE_ENV_ADD] = TRUE;
401 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
402 TRACE_(d3d_caps)(" FOUND: ARB Texture Env combine support\n");
403 gl_info->supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
404 } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
405 TRACE_(d3d_caps)(" FOUND: ARB Dot3 support\n");
406 gl_info->supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
407 } else if (strcmp(ThisExtn, "GL_ARB_texture_border_clamp") == 0) {
408 TRACE_(d3d_caps)(" FOUND: ARB Texture border clamp support\n");
409 gl_info->supported[ARB_TEXTURE_BORDER_CLAMP] = TRUE;
410 } else if (strcmp(ThisExtn, "GL_ARB_texture_mirrored_repeat") == 0) {
411 TRACE_(d3d_caps)(" FOUND: ARB Texture mirrored repeat support\n");
412 gl_info->supported[ARB_TEXTURE_MIRRORED_REPEAT] = TRUE;
413 } else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
414 gl_info->vs_arb_version = VS_VERSION_11;
415 TRACE_(d3d_caps)(" FOUND: ARB Vertex Shader support - version=%02x\n", gl_info->vs_arb_version);
416 gl_info->supported[ARB_VERTEX_PROGRAM] = TRUE;
417 } else if (strcmp(ThisExtn, "GL_ARB_vertex_blend") == 0) {
418 TRACE_(d3d_caps)(" FOUND: ARB Vertex Blend support\n");
419 gl_info->supported[ARB_VERTEX_BLEND] = TRUE;
420 } else if (strcmp(ThisExtn, "GL_ARB_vertex_buffer_object") == 0) {
421 TRACE_(d3d_caps)(" FOUND: ARB Vertex Buffer support\n");
422 gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] = TRUE;
425 * EXT
427 } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
428 TRACE_(d3d_caps)(" FOUND: EXT Fog coord support\n");
429 gl_info->supported[EXT_FOG_COORD] = TRUE;
430 } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
431 TRACE_(d3d_caps)(" FOUND: EXT Paletted texture support\n");
432 gl_info->supported[EXT_PALETTED_TEXTURE] = TRUE;
433 } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
434 TRACE_(d3d_caps)(" FOUND: EXT Point parameters support\n");
435 gl_info->supported[EXT_POINT_PARAMETERS] = TRUE;
436 } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
437 TRACE_(d3d_caps)(" FOUND: EXT Secondary coord support\n");
438 gl_info->supported[EXT_SECONDARY_COLOR] = TRUE;
439 } else if (strcmp(ThisExtn, "GL_EXT_stencil_wrap") == 0) {
440 TRACE_(d3d_caps)(" FOUND: EXT Stencil wrap support\n");
441 gl_info->supported[EXT_STENCIL_WRAP] = TRUE;
442 } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) {
443 TRACE_(d3d_caps)(" FOUND: EXT Texture S3TC compression support\n");
444 gl_info->supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE;
445 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_add") == 0) {
446 TRACE_(d3d_caps)(" FOUND: EXT Texture Env Add support\n");
447 gl_info->supported[EXT_TEXTURE_ENV_ADD] = TRUE;
448 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_combine") == 0) {
449 TRACE_(d3d_caps)(" FOUND: EXT Texture Env combine support\n");
450 gl_info->supported[EXT_TEXTURE_ENV_COMBINE] = TRUE;
451 } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) {
452 TRACE_(d3d_caps)(" FOUND: EXT Dot3 support\n");
453 gl_info->supported[EXT_TEXTURE_ENV_DOT3] = TRUE;
454 } else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
455 TRACE_(d3d_caps)(" FOUND: EXT Texture Anisotropic filter support\n");
456 gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
457 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
458 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD support\n");
459 gl_info->supported[EXT_TEXTURE_LOD] = TRUE;
460 } else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
461 TRACE_(d3d_caps)(" FOUND: EXT Texture LOD bias support\n");
462 gl_info->supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
463 } else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
464 TRACE_(d3d_caps)(" FOUND: EXT Vertex weighting support\n");
465 gl_info->supported[EXT_VERTEX_WEIGHTING] = TRUE;
468 * NVIDIA
470 } else if (strstr(ThisExtn, "GL_NV_fog_distance")) {
471 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Fog Distance support\n");
472 gl_info->supported[NV_FOG_DISTANCE] = TRUE;
473 } else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
474 gl_info->ps_nv_version = PS_VERSION_11;
475 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", gl_info->ps_nv_version);
476 } else if (strcmp(ThisExtn, "GL_NV_register_combiners") == 0) {
477 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (1) support\n");
478 gl_info->supported[NV_REGISTER_COMBINERS] = TRUE;
479 } else if (strcmp(ThisExtn, "GL_NV_register_combiners2") == 0) {
480 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Register combiners (2) support\n");
481 gl_info->supported[NV_REGISTER_COMBINERS2] = TRUE;
482 } else if (strcmp(ThisExtn, "GL_NV_texgen_reflection") == 0) {
483 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Gen Reflection support\n");
484 gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
485 } else if (strcmp(ThisExtn, "GL_NV_texture_env_combine4") == 0) {
486 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Env combine (4) support\n");
487 gl_info->supported[NV_TEXTURE_ENV_COMBINE4] = TRUE;
488 } else if (strcmp(ThisExtn, "GL_NV_texture_shader") == 0) {
489 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (1) support\n");
490 gl_info->supported[NV_TEXTURE_SHADER] = TRUE;
491 } else if (strcmp(ThisExtn, "GL_NV_texture_shader2") == 0) {
492 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (2) support\n");
493 gl_info->supported[NV_TEXTURE_SHADER2] = TRUE;
494 } else if (strcmp(ThisExtn, "GL_NV_texture_shader3") == 0) {
495 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Texture Shader (3) support\n");
496 gl_info->supported[NV_TEXTURE_SHADER3] = TRUE;
497 } else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
498 gl_info->vs_nv_version = max(gl_info->vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program1_1")) ? VS_VERSION_11 : VS_VERSION_10);
499 gl_info->vs_nv_version = max(gl_info->vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program2")) ? VS_VERSION_20 : VS_VERSION_10);
500 TRACE_(d3d_caps)(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", gl_info->vs_nv_version);
501 gl_info->supported[NV_VERTEX_PROGRAM] = TRUE;
504 * ATI
506 /** TODO */
507 } else if (strcmp(ThisExtn, "GL_ATI_texture_env_combine3") == 0) {
508 TRACE_(d3d_caps)(" FOUND: ATI Texture Env combine (3) support\n");
509 gl_info->supported[ATI_TEXTURE_ENV_COMBINE3] = TRUE;
510 } else if (strcmp(ThisExtn, "GL_ATI_texture_mirror_once") == 0) {
511 TRACE_(d3d_caps)(" FOUND: ATI Texture Mirror Once support\n");
512 gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] = TRUE;
513 } else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
514 gl_info->vs_ati_version = VS_VERSION_11;
515 TRACE_(d3d_caps)(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", gl_info->vs_ati_version);
516 gl_info->supported[EXT_VERTEX_SHADER] = TRUE;
520 if (*GL_Extensions == ' ') GL_Extensions++;
524 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB(#pfn);
525 GL_EXT_FUNCS_GEN;
526 #undef USE_GL_FUNC
528 if (display != NULL) {
529 GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
530 TRACE_(d3d_caps)("GLX_Extensions reported:\n");
532 if (NULL == GLX_Extensions) {
533 ERR(" GLX_Extensions returns NULL\n");
534 } else {
535 while (*GLX_Extensions != 0x00) {
536 const char *Start = GLX_Extensions;
537 char ThisExtn[256];
539 memset(ThisExtn, 0x00, sizeof(ThisExtn));
540 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
541 GLX_Extensions++;
543 memcpy(ThisExtn, Start, (GLX_Extensions - Start));
544 TRACE_(d3d_caps)("- %s\n", ThisExtn);
545 if (*GLX_Extensions == ' ') GLX_Extensions++;
550 #define USE_GL_FUNC(type, pfn) gl_info->pfn = (type) glXGetProcAddressARB(#pfn);
551 GLX_EXT_FUNCS_GEN;
552 #undef USE_GL_FUNC
554 /* Only save the values obtained when a display is provided */
555 if (display != NULL) {
556 return TRUE;
557 } else {
558 return FALSE;
562 /**********************************************************
563 * IWineD3D implementation follows
564 **********************************************************/
566 UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
567 IWineD3DImpl *This = (IWineD3DImpl *)iface;
569 /* FIXME: Set to one for now to imply the display */
570 TRACE_(d3d_caps)("(%p): Mostly stub, only returns primary display\n", This);
571 return 1;
574 HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
575 IWineD3DImpl *This = (IWineD3DImpl *)iface;
576 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
577 return D3D_OK;
580 HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
581 IWineD3DImpl *This = (IWineD3DImpl *)iface;
582 FIXME_(d3d_caps)("(%p)->(Adptr:%d)\n", This, Adapter);
583 if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
584 return NULL;
586 return D3D_OK;
589 /* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
590 of the same bpp but different resolutions */
592 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
593 UINT WINAPI IWineD3DImpl_GetAdapterModeCount(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format) {
594 IWineD3DImpl *This = (IWineD3DImpl *)iface;
595 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Format: %s)\n", This, Adapter, debug_d3dformat(Format));
597 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
598 return 0;
601 if (Adapter == 0) { /* Display */
602 int i = 0;
603 int j = 0;
604 #if !defined( DEBUG_SINGLE_MODE )
605 DEVMODEW DevModeW;
607 /* Work out the current screen bpp */
608 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
609 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
610 DeleteDC(hdc);
612 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
613 j++;
614 switch (Format)
616 case D3DFMT_UNKNOWN:
617 i++;
618 break;
619 case D3DFMT_X8R8G8B8:
620 case D3DFMT_A8R8G8B8:
621 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
622 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
623 break;
624 case D3DFMT_X1R5G5B5:
625 case D3DFMT_A1R5G5B5:
626 case D3DFMT_R5G6B5:
627 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
628 break;
629 default:
630 /* Skip other modes as they do not match requested format */
631 break;
634 #else
635 i = 1;
636 j = 1;
637 #endif
638 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
639 return i;
640 } else {
641 FIXME_(d3d_caps)("Adapter not primary display\n");
643 return 0;
646 /* Note: dx9 supplies a format. Calls from d3d8 supply D3DFMT_UNKNOWN */
647 HRESULT WINAPI IWineD3DImpl_EnumAdapterModes(IWineD3D *iface, UINT Adapter, WINED3DFORMAT Format, UINT Mode, D3DDISPLAYMODE* pMode) {
648 IWineD3DImpl *This = (IWineD3DImpl *)iface;
649 TRACE_(d3d_caps)("(%p}->(Adapter:%d, mode:%d, pMode:%p, format:%s)\n", This, Adapter, Mode, pMode, debug_d3dformat(Format));
651 /* Validate the parameters as much as possible */
652 if (NULL == pMode ||
653 Adapter >= IWineD3DImpl_GetAdapterCount(iface) ||
654 Mode >= IWineD3DImpl_GetAdapterModeCount(iface, Adapter, Format)) {
655 return D3DERR_INVALIDCALL;
658 if (Adapter == 0) { /* Display */
659 #if !defined( DEBUG_SINGLE_MODE )
660 DEVMODEW DevModeW;
661 int ModeIdx = 0;
663 /* Work out the current screen bpp */
664 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
665 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
666 DeleteDC(hdc);
668 /* If we are filtering to a specific format, then need to skip all unrelated
669 modes, but if mode is irrelevant, then we can use the index directly */
670 if (Format == D3DFMT_UNKNOWN)
672 ModeIdx = Mode;
673 } else {
674 int i = 0;
675 int j = 0;
676 DEVMODEW DevModeWtmp;
679 while (i<(Mode+1) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
680 j++;
681 switch (Format)
683 case D3DFMT_UNKNOWN:
684 i++;
685 break;
686 case D3DFMT_X8R8G8B8:
687 case D3DFMT_A8R8G8B8:
688 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
689 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
690 break;
691 case D3DFMT_X1R5G5B5:
692 case D3DFMT_A1R5G5B5:
693 case D3DFMT_R5G6B5:
694 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
695 break;
696 default:
697 /* Skip other modes as they do not match requested format */
698 break;
701 ModeIdx = j;
704 /* Now get the display mode via the calculated index */
705 if (EnumDisplaySettingsExW(NULL, ModeIdx, &DevModeW, 0))
707 pMode->Width = DevModeW.dmPelsWidth;
708 pMode->Height = DevModeW.dmPelsHeight;
709 bpp = min(DevModeW.dmBitsPerPel, bpp);
710 pMode->RefreshRate = D3DADAPTER_DEFAULT;
711 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
713 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
716 if (Format == D3DFMT_UNKNOWN)
718 switch (bpp) {
719 case 8: pMode->Format = D3DFMT_R3G3B2; break;
720 case 16: pMode->Format = D3DFMT_R5G6B5; break;
721 case 24: /* pMode->Format = D3DFMT_R5G6B5; break;*/ /* Make 24bit appear as 32 bit */
722 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
723 default: pMode->Format = D3DFMT_UNKNOWN;
725 } else {
726 pMode->Format = Format;
729 else
731 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
732 return D3DERR_INVALIDCALL;
735 #else
736 /* Return one setting of the format requested */
737 if (Mode > 0) return D3DERR_INVALIDCALL;
738 pMode->Width = 800;
739 pMode->Height = 600;
740 pMode->RefreshRate = D3DADAPTER_DEFAULT;
741 pMode->Format = (Format==D3DFMT_UNKNOWN)?D3DFMT_A8R8G8B8:Format;
742 bpp = 32;
743 #endif
744 TRACE_(d3d_caps)("W %d H %d rr %d fmt (%x - %s) bpp %u\n", pMode->Width, pMode->Height,
745 pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
747 } else {
748 FIXME_(d3d_caps)("Adapter not primary display\n");
751 return D3D_OK;
754 HRESULT WINAPI IWineD3DImpl_GetAdapterDisplayMode(IWineD3D *iface, UINT Adapter, D3DDISPLAYMODE* pMode) {
755 IWineD3DImpl *This = (IWineD3DImpl *)iface;
756 TRACE_(d3d_caps)("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);
758 if (NULL == pMode ||
759 Adapter >= IWineD3D_GetAdapterCount(iface)) {
760 return D3DERR_INVALIDCALL;
763 if (Adapter == 0) { /* Display */
764 int bpp = 0;
765 DEVMODEW DevModeW;
767 EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
768 pMode->Width = DevModeW.dmPelsWidth;
769 pMode->Height = DevModeW.dmPelsHeight;
770 bpp = DevModeW.dmBitsPerPel;
771 pMode->RefreshRate = D3DADAPTER_DEFAULT;
772 if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
774 pMode->RefreshRate = DevModeW.dmDisplayFrequency;
777 switch (bpp) {
778 case 8: pMode->Format = D3DFMT_R3G3B2; break;
779 case 16: pMode->Format = D3DFMT_R5G6B5; break;
780 case 24: /*pMode->Format = D3DFMT_R5G6B5; break;*/ /* Make 24bit appear as 32 bit */
781 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
782 default: pMode->Format = D3DFMT_UNKNOWN;
785 } else {
786 FIXME_(d3d_caps)("Adapter not primary display\n");
789 TRACE_(d3d_caps)("returning w:%d, h:%d, ref:%d, fmt:%s\n", pMode->Width,
790 pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
791 return D3D_OK;
794 /* Note due to structure differences between dx8 and dx9 D3DADAPTER_IDENTIFIER,
795 and fields being inserted in the middle, a new structure is used in place */
796 HRESULT WINAPI IWineD3DImpl_GetAdapterIdentifier(IWineD3D *iface, UINT Adapter, DWORD Flags,
797 WINED3DADAPTER_IDENTIFIER* pIdentifier) {
798 IWineD3DImpl *This = (IWineD3DImpl *)iface;
800 TRACE_(d3d_caps)("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);
802 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
803 return D3DERR_INVALIDCALL;
806 if (Adapter == 0) { /* Display - only device supported for now */
808 BOOL isGLInfoValid = This->isGLInfoValid;
810 /* FillGLCaps updates gl_info, but we only want to store and
811 reuse the values once we have a context which is valid. Values from
812 a temporary context may differ from the final ones */
813 if (isGLInfoValid == FALSE) {
815 /* If we don't know the device settings, go query them now via a
816 fake context */
817 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
818 if (NULL != ctx) {
819 isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, ctx->display);
820 WineD3D_ReleaseFakeGLContext(ctx);
824 /* If it worked, return the information requested */
825 if (isGLInfoValid) {
826 TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
827 strcpy(pIdentifier->Driver, "Display");
828 strcpy(pIdentifier->Description, "Direct3D HAL");
830 /* Note dx8 doesn't supply a DeviceName */
831 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
832 pIdentifier->DriverVersion->u.HighPart = 0xa;
833 pIdentifier->DriverVersion->u.LowPart = This->gl_info.gl_driver_version;
834 *(pIdentifier->VendorId) = This->gl_info.gl_vendor;
835 *(pIdentifier->DeviceId) = This->gl_info.gl_card;
836 *(pIdentifier->SubSysId) = 0;
837 *(pIdentifier->Revision) = 0;
839 } else {
841 /* If it failed, return dummy values from an NVidia driver */
842 WARN_(d3d_caps)("Cannot get GLCaps for device/Vendor Name and Version detection using FillGLCaps, currently using NVIDIA identifiers\n");
843 strcpy(pIdentifier->Driver, "Display");
844 strcpy(pIdentifier->Description, "Direct3D HAL");
845 if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
846 pIdentifier->DriverVersion->u.HighPart = 0xa;
847 pIdentifier->DriverVersion->u.LowPart = MAKEDWORD_VERSION(53, 96); /* last Linux Nvidia drivers */
848 *(pIdentifier->VendorId) = VENDOR_NVIDIA;
849 *(pIdentifier->DeviceId) = CARD_NVIDIA_GEFORCE4_TI4600;
850 *(pIdentifier->SubSysId) = 0;
851 *(pIdentifier->Revision) = 0;
854 /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
855 if (Flags & D3DENUM_NO_WHQL_LEVEL) {
856 *(pIdentifier->WHQLLevel) = 0;
857 } else {
858 *(pIdentifier->WHQLLevel) = 1;
861 } else {
862 FIXME_(d3d_caps)("Adapter not primary display\n");
865 return D3D_OK;
868 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
869 int gl_test;
870 int rb, gb, bb, ab, type, buf_sz;
872 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RED_SIZE, &rb);
873 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_GREEN_SIZE, &gb);
874 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BLUE_SIZE, &bb);
875 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_ALPHA_SIZE, &ab);
876 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_RENDER_TYPE, &type);
877 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_BUFFER_SIZE, &buf_sz);
879 switch (Format) {
880 case WINED3DFMT_X8R8G8B8:
881 case WINED3DFMT_R8G8B8:
882 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
883 break;
884 case WINED3DFMT_A8R8G8B8:
885 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
886 break;
887 case WINED3DFMT_X1R5G5B5:
888 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
889 break;
890 case WINED3DFMT_A1R5G5B5:
891 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
892 break;
893 case WINED3DFMT_R5G6B5:
894 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
895 break;
896 case WINED3DFMT_R3G3B2:
897 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
898 break;
899 case WINED3DFMT_A8P8:
900 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
901 break;
902 case WINED3DFMT_P8:
903 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
904 break;
905 default:
906 ERR("unsupported format %s\n", debug_d3dformat(Format));
907 break;
909 return FALSE;
912 static BOOL IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(WineD3D_Context* ctx, GLXFBConfig cfgs, WINED3DFORMAT Format) {
913 int gl_test;
914 int db, sb;
916 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
917 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
919 switch (Format) {
920 case WINED3DFMT_D16:
921 case WINED3DFMT_D16_LOCKABLE:
922 if (16 == db) return TRUE;
923 break;
924 case WINED3DFMT_D32:
925 if (32 == db) return TRUE;
926 break;
927 case WINED3DFMT_D15S1:
928 if (15 == db) return TRUE;
929 break;
930 case WINED3DFMT_D24S8:
931 if (24 == db && 8 == sb) return TRUE;
932 break;
933 case WINED3DFMT_D24X8:
934 if (24 == db) return TRUE;
935 break;
936 case WINED3DFMT_D24X4S4:
937 if (24 == db && 4 == sb) return TRUE;
938 break;
939 case WINED3DFMT_D32F_LOCKABLE:
940 if (32 == db) return TRUE;
941 break;
942 default:
943 ERR("unsupported format %s\n", debug_d3dformat(Format));
944 break;
946 return FALSE;
949 HRESULT WINAPI IWineD3DImpl_CheckDepthStencilMatch(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType,
950 WINED3DFORMAT AdapterFormat,
951 WINED3DFORMAT RenderTargetFormat,
952 WINED3DFORMAT DepthStencilFormat) {
953 IWineD3DImpl *This = (IWineD3DImpl *)iface;
954 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
955 This, Adapter,
956 DeviceType, debug_d3ddevicetype(DeviceType),
957 AdapterFormat, debug_d3dformat(AdapterFormat),
958 RenderTargetFormat, debug_d3dformat(RenderTargetFormat),
959 DepthStencilFormat, debug_d3dformat(DepthStencilFormat));
961 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
962 return D3DERR_INVALIDCALL;
966 GLXFBConfig* cfgs = NULL;
967 int nCfgs = 0;
968 int it;
969 HRESULT hr = D3DERR_NOTAVAILABLE;
971 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
972 if (NULL != ctx) {
973 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
974 for (it = 0; it < nCfgs; ++it) {
975 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
976 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
977 hr = D3D_OK;
978 break ;
982 XFree(cfgs);
984 WineD3D_ReleaseFakeGLContext(ctx);
985 return hr;
989 return D3DERR_NOTAVAILABLE;
992 HRESULT WINAPI IWineD3DImpl_CheckDeviceMultiSampleType(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType,
993 WINED3DFORMAT SurfaceFormat,
994 BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
996 IWineD3DImpl *This = (IWineD3DImpl *)iface;
997 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
998 This,
999 Adapter,
1000 DeviceType, debug_d3ddevicetype(DeviceType),
1001 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1002 Windowed,
1003 MultiSampleType,
1004 pQualityLevels);
1006 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1007 return D3DERR_INVALIDCALL;
1010 if (pQualityLevels != NULL) {
1011 static int s_single_shot = 0;
1012 if (!s_single_shot) {
1013 FIXME("Quality levels unsupported at present\n");
1014 s_single_shot = 1;
1016 *pQualityLevels = 1; /* Guess at a value! */
1019 if (D3DMULTISAMPLE_NONE == MultiSampleType) return D3D_OK;
1020 return D3DERR_NOTAVAILABLE;
1023 HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, D3DDEVTYPE CheckType,
1024 WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
1026 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1027 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
1028 This,
1029 Adapter,
1030 CheckType, debug_d3ddevicetype(CheckType),
1031 DisplayFormat, debug_d3dformat(DisplayFormat),
1032 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1033 Windowed);
1035 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1036 return D3DERR_INVALIDCALL;
1040 GLXFBConfig* cfgs = NULL;
1041 int nCfgs = 0;
1042 int it;
1043 HRESULT hr = D3DERR_NOTAVAILABLE;
1045 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1046 if (NULL != ctx) {
1047 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1048 for (it = 0; it < nCfgs; ++it) {
1049 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1050 hr = D3D_OK;
1051 break ;
1054 XFree(cfgs);
1056 WineD3D_ReleaseFakeGLContext(ctx);
1057 return hr;
1061 return D3DERR_NOTAVAILABLE;
1064 HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType,
1065 WINED3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
1066 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1067 TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
1068 This,
1069 Adapter,
1070 DeviceType, debug_d3ddevicetype(DeviceType),
1071 AdapterFormat, debug_d3dformat(AdapterFormat),
1072 Usage, debug_d3dusage(Usage),
1073 RType, debug_d3dresourcetype(RType),
1074 CheckFormat, debug_d3dformat(CheckFormat));
1076 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1077 return D3DERR_INVALIDCALL;
1080 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1081 switch (CheckFormat) {
1082 case D3DFMT_DXT1:
1083 case D3DFMT_DXT3:
1084 case D3DFMT_DXT5:
1085 TRACE_(d3d_caps)("[OK]\n");
1086 return D3D_OK;
1087 default:
1088 break; /* Avoid compiler warnings */
1092 switch (CheckFormat) {
1093 /*****
1094 * check supported using GL_SUPPORT
1096 case D3DFMT_DXT1:
1097 case D3DFMT_DXT2:
1098 case D3DFMT_DXT3:
1099 case D3DFMT_DXT4:
1100 case D3DFMT_DXT5:
1102 /*****
1103 * supported
1105 /*case D3DFMT_R5G6B5: */
1106 /*case D3DFMT_X1R5G5B5:*/
1107 /*case D3DFMT_A1R5G5B5: */
1108 /*case D3DFMT_A4R4G4B4:*/
1110 /*****
1111 * unsupported
1114 /* color buffer */
1115 /*case D3DFMT_X8R8G8B8:*/
1116 case D3DFMT_A8R3G3B2:
1118 /* Paletted */
1119 case D3DFMT_P8:
1120 case D3DFMT_A8P8:
1122 /* Luminance */
1123 case D3DFMT_L8:
1124 case D3DFMT_A8L8:
1125 case D3DFMT_A4L4:
1127 /* Bump */
1128 #if 0
1129 case D3DFMT_V8U8:
1130 case D3DFMT_V16U16:
1131 #endif
1132 case D3DFMT_L6V5U5:
1133 case D3DFMT_X8L8V8U8:
1134 case D3DFMT_Q8W8V8U8:
1135 case D3DFMT_W11V11U10:
1137 /****
1138 * currently hard to support
1140 case D3DFMT_UYVY:
1141 case D3DFMT_YUY2:
1143 /* Since we do not support these formats right now, don't pretend to. */
1144 TRACE_(d3d_caps)("[FAILED]\n");
1145 return D3DERR_NOTAVAILABLE;
1146 default:
1147 break;
1150 TRACE_(d3d_caps)("[OK]\n");
1151 return D3D_OK;
1154 HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType,
1155 WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
1156 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1158 FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))",
1159 This,
1160 Adapter,
1161 DeviceType, debug_d3ddevicetype(DeviceType),
1162 SourceFormat, debug_d3dformat(SourceFormat),
1163 TargetFormat, debug_d3dformat(TargetFormat));
1164 return D3D_OK;
1167 /* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
1168 subset of a D3DCAPS9 structure. However, it has to come via a void *
1169 as the d3d8 interface cannot import the d3d9 header */
1170 HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
1172 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1173 BOOL gotContext = FALSE;
1174 GLint gl_tex_size = 0;
1175 WineD3D_Context *fake_ctx = NULL;
1177 TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
1179 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1180 return D3DERR_INVALIDCALL;
1183 /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
1184 ie there is no GL Context - Get a default rendering context to enable the
1185 function query some info from GL */
1186 if (glXGetCurrentContext() == NULL) {
1187 fake_ctx = WineD3D_CreateFakeGLContext();
1188 if (NULL != fake_ctx) gotContext = TRUE;
1189 } else {
1190 gotContext = TRUE;
1193 if (gotContext == FALSE) {
1195 FIXME_(d3d_caps)("GetDeviceCaps called but no GL Context - Returning dummy values\n");
1196 gl_tex_size=65535;
1197 *(pCaps->MaxTextureBlendStages) = 2;
1198 *pCaps->MaxSimultaneousTextures = 2;
1199 *pCaps->MaxUserClipPlanes = 8;
1200 *pCaps->MaxActiveLights = 8;
1201 *pCaps->MaxVertexBlendMatrices = 0;
1202 *pCaps->MaxVertexBlendMatrixIndex = 1;
1203 *pCaps->MaxAnisotropy = 0;
1204 *pCaps->MaxPointSize = 255.0;
1206 } else {
1207 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
1210 /* If we don't know the device settings, go query them now */
1211 if (This->isGLInfoValid == FALSE) {
1212 BOOL rc = IWineD3DImpl_FillGLCaps(&This->gl_info, NULL);
1214 /* If we are running off a real context, save the values */
1215 if (rc && ((NULL != fake_ctx))) This->isGLInfoValid = TRUE;
1218 /* ------------------------------------------------
1219 The following fields apply to both d3d8 and d3d9
1220 ------------------------------------------------ */
1221 *pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
1222 *pCaps->AdapterOrdinal = Adapter;
1224 *pCaps->Caps = 0;
1225 *pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
1226 *pCaps->Caps3 = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
1227 *pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;
1229 *pCaps->CursorCaps = 0;
1232 *pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX |
1233 D3DDEVCAPS_HWTRANSFORMANDLIGHT |
1234 D3DDEVCAPS_PUREDEVICE |
1235 D3DDEVCAPS_HWRASTERIZATION;
1238 *pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW |
1239 D3DPMISCCAPS_CULLCW |
1240 D3DPMISCCAPS_COLORWRITEENABLE |
1241 D3DPMISCCAPS_CLIPTLVERTS |
1242 D3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
1243 D3DPMISCCAPS_MASKZ;
1244 /*NOT: D3DPMISCCAPS_TSSARGTEMP*/
1246 *pCaps->RasterCaps = D3DPRASTERCAPS_DITHER |
1247 D3DPRASTERCAPS_PAT |
1248 D3DPRASTERCAPS_WFOG |
1249 D3DPRASTERCAPS_ZFOG |
1250 D3DPRASTERCAPS_FOGVERTEX |
1251 D3DPRASTERCAPS_FOGTABLE |
1252 D3DPRASTERCAPS_FOGRANGE;
1254 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1255 *pCaps->RasterCaps |= D3DPRASTERCAPS_ANISOTROPY |
1256 D3DPRASTERCAPS_ZBIAS |
1257 D3DPRASTERCAPS_MIPMAPLODBIAS;
1259 /* FIXME Add:
1260 D3DPRASTERCAPS_COLORPERSPECTIVE
1261 D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1262 D3DPRASTERCAPS_ANTIALIASEDGES
1263 D3DPRASTERCAPS_ZBUFFERLESSHSR
1264 D3DPRASTERCAPS_WBUFFER */
1266 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1267 D3DPCMPCAPS_EQUAL |
1268 D3DPCMPCAPS_GREATER |
1269 D3DPCMPCAPS_GREATEREQUAL |
1270 D3DPCMPCAPS_LESS |
1271 D3DPCMPCAPS_LESSEQUAL |
1272 D3DPCMPCAPS_NEVER |
1273 D3DPCMPCAPS_NOTEQUAL;
1275 *pCaps->SrcBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
1276 *pCaps->DestBlendCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
1277 *pCaps->AlphaCmpCaps = 0xFFFFFFFF; /*FIXME: Tidy up later */
1279 *pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB |
1280 D3DPSHADECAPS_COLORGOURAUDRGB;
1282 *pCaps->TextureCaps = D3DPTEXTURECAPS_ALPHA |
1283 D3DPTEXTURECAPS_ALPHAPALETTE |
1284 D3DPTEXTURECAPS_VOLUMEMAP |
1285 D3DPTEXTURECAPS_MIPMAP |
1286 D3DPTEXTURECAPS_PROJECTED |
1287 D3DPTEXTURECAPS_PERSPECTIVE |
1288 D3DPTEXTURECAPS_VOLUMEMAP_POW2 ;
1289 /* TODO: add support for NON-POW2 if avaialble
1292 if (This->dxVersion > 8) {
1293 *pCaps->TextureCaps |= D3DPTEXTURECAPS_NONPOW2CONDITIONAL;
1295 } else { /* NONPOW2 isn't accessible by d3d8 yet */
1296 *pCaps->TextureCaps |= D3DPTEXTURECAPS_POW2;
1299 if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
1300 *pCaps->TextureCaps |= D3DPTEXTURECAPS_CUBEMAP |
1301 D3DPTEXTURECAPS_MIPCUBEMAP |
1302 D3DPTEXTURECAPS_CUBEMAP_POW2;
1306 *pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR |
1307 D3DPTFILTERCAPS_MAGFPOINT |
1308 D3DPTFILTERCAPS_MINFLINEAR |
1309 D3DPTFILTERCAPS_MINFPOINT |
1310 D3DPTFILTERCAPS_MIPFLINEAR |
1311 D3DPTFILTERCAPS_MIPFPOINT;
1313 *pCaps->CubeTextureFilterCaps = 0;
1314 *pCaps->VolumeTextureFilterCaps = 0;
1316 *pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_BORDER |
1317 D3DPTADDRESSCAPS_CLAMP |
1318 D3DPTADDRESSCAPS_WRAP;
1320 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
1321 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_BORDER;
1323 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
1324 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
1326 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
1327 *pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRRORONCE;
1330 *pCaps->VolumeTextureAddressCaps = 0;
1332 *pCaps->LineCaps = D3DLINECAPS_TEXTURE |
1333 D3DLINECAPS_ZTEST;
1334 /* FIXME: Add
1335 D3DLINECAPS_BLEND
1336 D3DLINECAPS_ALPHACMP
1337 D3DLINECAPS_FOG */
1339 *pCaps->MaxTextureWidth = gl_tex_size;
1340 *pCaps->MaxTextureHeight = gl_tex_size;
1342 *pCaps->MaxVolumeExtent = 0;
1344 *pCaps->MaxTextureRepeat = 32768;
1345 *pCaps->MaxTextureAspectRatio = 32768;
1346 *pCaps->MaxVertexW = 1.0;
1348 *pCaps->GuardBandLeft = 0;
1349 *pCaps->GuardBandTop = 0;
1350 *pCaps->GuardBandRight = 0;
1351 *pCaps->GuardBandBottom = 0;
1353 *pCaps->ExtentsAdjust = 0;
1355 *pCaps->StencilCaps = D3DSTENCILCAPS_DECRSAT |
1356 D3DSTENCILCAPS_INCRSAT |
1357 D3DSTENCILCAPS_INVERT |
1358 D3DSTENCILCAPS_KEEP |
1359 D3DSTENCILCAPS_REPLACE |
1360 D3DSTENCILCAPS_ZERO;
1361 if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
1362 *pCaps->StencilCaps |= D3DSTENCILCAPS_DECR |
1363 D3DSTENCILCAPS_INCR;
1366 *pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
1368 *pCaps->TextureOpCaps = D3DTEXOPCAPS_ADD |
1369 D3DTEXOPCAPS_ADDSIGNED |
1370 D3DTEXOPCAPS_ADDSIGNED2X |
1371 D3DTEXOPCAPS_MODULATE |
1372 D3DTEXOPCAPS_MODULATE2X |
1373 D3DTEXOPCAPS_MODULATE4X |
1374 D3DTEXOPCAPS_SELECTARG1 |
1375 D3DTEXOPCAPS_SELECTARG2 |
1376 D3DTEXOPCAPS_DISABLE;
1377 #if defined(GL_VERSION_1_3)
1378 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 |
1379 D3DTEXOPCAPS_SUBTRACT;
1380 #endif
1381 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
1382 GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
1383 GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1384 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BLENDDIFFUSEALPHA |
1385 D3DTEXOPCAPS_BLENDTEXTUREALPHA |
1386 D3DTEXOPCAPS_BLENDFACTORALPHA |
1387 D3DTEXOPCAPS_BLENDCURRENTALPHA |
1388 D3DTEXOPCAPS_LERP;
1390 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1391 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_ADDSMOOTH |
1392 D3DTEXOPCAPS_MULTIPLYADD |
1393 D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
1394 D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
1395 D3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
1398 #if 0
1399 pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
1400 /* FIXME: Add
1401 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
1402 D3DTEXOPCAPS_PREMODULATE */
1403 #endif
1405 if (gotContext) {
1406 GLint gl_max;
1407 GLfloat gl_float;
1408 #if defined(GL_VERSION_1_3)
1409 glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
1410 #else
1411 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
1412 #endif
1413 TRACE_(d3d_caps)("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
1414 *pCaps->MaxTextureBlendStages = min(8, gl_max);
1415 *pCaps->MaxSimultaneousTextures = min(8, gl_max);
1417 glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
1418 *pCaps->MaxUserClipPlanes = min(D3DMAXUSERCLIPPLANES, gl_max);
1419 TRACE_(d3d_caps)("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", *pCaps->MaxUserClipPlanes);
1421 glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
1422 *pCaps->MaxActiveLights = gl_max;
1423 TRACE_(d3d_caps)("GLCaps: GL_MAX_LIGHTS=%ld\n", *pCaps->MaxActiveLights);
1425 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
1426 glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
1427 #if 0 /* TODO : add support for blends to drawprim */
1428 *pCaps->MaxVertexBlendMatrices = gl_max;
1429 #else
1430 *pCaps->MaxVertexBlendMatrices = 0;
1431 #endif
1432 *pCaps->MaxVertexBlendMatrixIndex = 1;
1433 } else {
1434 *pCaps->MaxVertexBlendMatrices = 0;
1435 *pCaps->MaxVertexBlendMatrixIndex = 1;
1438 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
1439 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
1440 *pCaps->MaxAnisotropy = gl_max;
1441 } else {
1442 *pCaps->MaxAnisotropy = 0;
1445 glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
1446 *pCaps->MaxPointSize = gl_float;
1449 *pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS |
1450 D3DVTXPCAPS_MATERIALSOURCE7 |
1451 D3DVTXPCAPS_POSITIONALLIGHTS |
1452 D3DVTXPCAPS_LOCALVIEWER |
1453 D3DVTXPCAPS_TEXGEN;
1454 /* FIXME: Add
1455 D3DVTXPCAPS_TWEENING */
1457 *pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
1458 *pCaps->MaxVertexIndex = 0xFFFFFFFF;
1459 *pCaps->MaxStreams = MAX_STREAMS;
1460 *pCaps->MaxStreamStride = 1024;
1462 if (((vs_mode == VS_HW) && GL_SUPPORT(ARB_VERTEX_PROGRAM)) || (vs_mode == VS_SW) || (DeviceType == D3DDEVTYPE_REF)) {
1463 *pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
1465 if (This->gl_info.gl_vendor == VENDOR_MESA ||
1466 This->gl_info.gl_vendor == VENDOR_WINE) {
1467 *pCaps->MaxVertexShaderConst = 95;
1468 } else {
1469 *pCaps->MaxVertexShaderConst = WINED3D_VSHADER_MAX_CONSTANTS;
1471 } else {
1472 *pCaps->VertexShaderVersion = 0;
1473 *pCaps->MaxVertexShaderConst = 0;
1476 if ((ps_mode == PS_HW) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && (DeviceType != D3DDEVTYPE_REF)) {
1477 *pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
1478 *pCaps->PixelShader1xMaxValue = 1.0;
1479 } else {
1480 *pCaps->PixelShaderVersion = 0;
1481 *pCaps->PixelShader1xMaxValue = 0.0;
1483 /* TODO: ARB_FRAGMENT_PROGRAM_100 */
1485 /* ------------------------------------------------
1486 The following fields apply to d3d9 only
1487 ------------------------------------------------ */
1488 if (This->dxVersion > 8) {
1489 GLint max_buffers=1;
1490 FIXME("Caps support for directx9 is nonexistent at the moment!\n");
1491 *pCaps->DevCaps2 = 0;
1492 /* TODO: D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES */
1493 *pCaps->MaxNpatchTessellationLevel = 0;
1494 *pCaps->MasterAdapterOrdinal = 0;
1495 *pCaps->AdapterOrdinalInGroup = 0;
1496 *pCaps->NumberOfAdaptersInGroup = 1;
1497 *pCaps->DeclTypes = 0;
1498 #if 0 /*FIXME: Simultaneous render targets*/
1499 GL_MAX_DRAW_BUFFERS_ATI 0x00008824
1500 if (GL_SUPPORT(GL_MAX_DRAW_BUFFERS_ATI)) {
1501 ENTER_GL();
1502 glEnable(GL_MAX_DRAW_BUFFERS_ATI);
1503 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &max_buffers);
1504 glDisable(GL_MAX_DRAW_BUFFERS_ATI);
1505 LEAVE_GL();
1507 #endif
1508 *pCaps->NumSimultaneousRTs = max_buffers;
1509 *pCaps->StretchRectFilterCaps = 0;
1510 /* TODO: add
1511 D3DPTFILTERCAPS_MINFPOINT
1512 D3DPTFILTERCAPS_MAGFPOINT
1513 D3DPTFILTERCAPS_MINFLINEAR
1514 D3DPTFILTERCAPS_MAGFLINEAR
1516 *pCaps->VS20Caps.Caps = 0;
1517 *pCaps->PS20Caps.Caps = 0;
1518 *pCaps->VertexTextureFilterCaps = 0;
1519 *pCaps->MaxVShaderInstructionsExecuted = 0;
1520 *pCaps->MaxPShaderInstructionsExecuted = 0;
1521 *pCaps->MaxVertexShader30InstructionSlots = 0;
1522 *pCaps->MaxPixelShader30InstructionSlots = 0;
1525 /* If we created a dummy context, throw it away */
1526 if (NULL != fake_ctx) WineD3D_ReleaseFakeGLContext(fake_ctx);
1527 return D3D_OK;
1531 /* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
1532 and fields being inserted in the middle, a new structure is used in place */
1533 HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
1534 DWORD BehaviourFlags, WINED3DPRESENT_PARAMETERS* pPresentationParameters,
1535 IWineD3DDevice** ppReturnedDeviceInterface, IUnknown *parent,
1536 D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1538 IWineD3DDeviceImpl *object = NULL;
1539 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1540 IWineD3DSwapChainImpl *swapchain;
1542 /* Validate the adapter number */
1543 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1544 return D3DERR_INVALIDCALL;
1547 /* Create a WineD3DDevice object */
1548 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DDeviceImpl));
1549 *ppReturnedDeviceInterface = (IWineD3DDevice *)object;
1550 TRACE("Created WineD3DDevice object @ %p \n", object);
1551 if (NULL == object) {
1552 return D3DERR_OUTOFVIDEOMEMORY;
1555 /* Set up initial COM information */
1556 object->lpVtbl = &IWineD3DDevice_Vtbl;
1557 object->ref = 1;
1558 object->wineD3D = iface;
1559 IWineD3D_AddRef(object->wineD3D);
1560 object->parent = parent;
1562 TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
1563 hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);
1564 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
1565 *(pPresentationParameters->AutoDepthStencilFormat), debug_d3dformat(*(pPresentationParameters->AutoDepthStencilFormat)),
1566 *(pPresentationParameters->BackBufferFormat), debug_d3dformat(*(pPresentationParameters->BackBufferFormat)));
1568 /* Save the creation parameters */
1569 object->createParms.AdapterOrdinal = Adapter;
1570 object->createParms.DeviceType = DeviceType;
1571 object->createParms.hFocusWindow = hFocusWindow;
1572 object->createParms.BehaviorFlags = BehaviourFlags;
1574 /* Initialize other useful values */
1575 object->presentParms.BackBufferCount = 1; /* Opengl only supports one? */
1576 object->adapterNo = Adapter;
1577 object->devType = DeviceType;
1579 /* FIXME: Use for dx8 code eventually too! */
1580 /* Deliberately no indentation here, as this if will be removed when dx8 support merged in */
1581 if (This->dxVersion > 8) {
1583 /* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
1584 IWineD3DDevice_CreateStateBlock((IWineD3DDevice *)object,
1585 (D3DSTATEBLOCKTYPE) 0,
1586 (IWineD3DStateBlock **)&object->stateBlock,
1587 NULL); /* Note: No parent needed for initial internal stateblock */
1588 object->updateStateBlock = object->stateBlock;
1589 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)object->updateStateBlock);
1590 /* Setup surfaces for the backbuffer, frontbuffer and depthstencil buffer */
1592 /* Setup the implicite swapchain */
1593 TRACE("Creating implicite swapchain\n");
1595 if (D3D_OK == D3DCB_CreateAdditionalSwapChain((IUnknown *) object->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain) && swapchain != NULL) {
1597 object->renderTarget = swapchain->backBuffer;
1598 IWineD3DSurface_AddRef(object->renderTarget);
1599 /* Depth Stencil support */
1600 object->stencilBufferTarget = object->depthStencilBuffer;
1601 if (NULL != object->stencilBufferTarget) {
1602 IWineD3DSurface_AddRef(object->stencilBufferTarget);
1605 /* Set up some starting GL setup */
1607 ENTER_GL();
1609 * Initialize openGL extension related variables
1610 * with Default values
1613 This->isGLInfoValid = IWineD3DImpl_FillGLCaps(&This->gl_info, swapchain->display);
1614 /* Setup all the devices defaults */
1615 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)object->stateBlock);
1616 #if 0
1617 IWineD3DImpl_CheckGraphicsMemory();
1618 #endif
1619 LEAVE_GL();
1621 { /* Set a default viewport */
1622 D3DVIEWPORT9 vp;
1623 vp.X = 0;
1624 vp.Y = 0;
1625 vp.Width = *(pPresentationParameters->BackBufferWidth);
1626 vp.Height = *(pPresentationParameters->BackBufferHeight);
1627 vp.MinZ = 0.0f;
1628 vp.MaxZ = 1.0f;
1629 IWineD3DDevice_SetViewport((IWineD3DDevice *)object, &vp);
1633 /* Initialize the current view state */
1634 object->modelview_valid = 1;
1635 object->proj_valid = 0;
1636 object->view_ident = 1;
1637 object->last_was_rhw = 0;
1638 glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
1639 TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
1641 /* Clear the screen */
1642 IWineD3DDevice_Clear((IWineD3DDevice *) object, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
1643 } else { /* couldn't create swapchain */
1644 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->updateStateBlock);
1645 object->updateStateBlock = NULL;
1646 IWineD3DStateBlock_Release((IWineD3DStateBlock *)object->stateBlock);
1647 object->stateBlock = NULL;
1648 HeapFree(GetProcessHeap(), 0, object);
1649 *ppReturnedDeviceInterface = NULL;
1650 return D3DERR_INVALIDCALL;
1653 } else { /* End of FIXME: remove when dx8 merged in */
1655 FIXME("(%p) Incomplete stub for d3d8\n", This);
1659 return D3D_OK;
1662 HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
1663 IWineD3DImpl *This = (IWineD3DImpl *)iface;
1664 IUnknown_AddRef(This->parent);
1665 *pParent = This->parent;
1666 return D3D_OK;
1669 /**********************************************************
1670 * IWineD3D VTbl follows
1671 **********************************************************/
1673 const IWineD3DVtbl IWineD3D_Vtbl =
1675 IWineD3DImpl_QueryInterface,
1676 IWineD3DImpl_AddRef,
1677 IWineD3DImpl_Release,
1678 IWineD3DImpl_GetParent,
1679 IWineD3DImpl_GetAdapterCount,
1680 IWineD3DImpl_RegisterSoftwareDevice,
1681 IWineD3DImpl_GetAdapterMonitor,
1682 IWineD3DImpl_GetAdapterModeCount,
1683 IWineD3DImpl_EnumAdapterModes,
1684 IWineD3DImpl_GetAdapterDisplayMode,
1685 IWineD3DImpl_GetAdapterIdentifier,
1686 IWineD3DImpl_CheckDeviceMultiSampleType,
1687 IWineD3DImpl_CheckDepthStencilMatch,
1688 IWineD3DImpl_CheckDeviceType,
1689 IWineD3DImpl_CheckDeviceFormat,
1690 IWineD3DImpl_CheckDeviceFormatConversion,
1691 IWineD3DImpl_GetDeviceCaps,
1692 IWineD3DImpl_CreateDevice