wined3d: Shader declaration cap fixes.
[wine/wine-gecko.git] / dlls / wined3d / directx.c
blob9bc7e7103547d16e56861bcd27f8a54fd37a7a80
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., 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*/
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 /* lookup tables */
62 int minLookup[MAX_LOOKUPS];
63 int maxLookup[MAX_LOOKUPS];
64 DWORD *stateLookup[MAX_LOOKUPS];
66 DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
70 /**
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;
81 BOOL created = FALSE;
82 XVisualInfo template;
83 HDC device_context;
84 Visual* visual;
85 BOOL failed = FALSE;
86 int num;
87 XWindowAttributes win_attr;
88 TRACE_(d3d_caps)("Creating Fake GL Context\n");
90 ctx.drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
92 /* Get the display */
93 device_context = GetDC(0);
94 ctx.display = get_display(device_context);
95 ReleaseDC(0, device_context);
97 /* Get the X visual */
98 ENTER_GL();
99 if (XGetWindowAttributes(ctx.display, ctx.drawable, &win_attr)) {
100 visual = win_attr.visual;
101 } else {
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) {
107 LEAVE_GL();
108 WARN_(d3d_caps)("Error creating visual info for capabilities initialization\n");
109 failed = TRUE;
112 /* Create a GL context */
113 if (!failed) {
114 ctx.glCtx = glXCreateContext(ctx.display, ctx.visInfo, NULL, GL_TRUE);
116 if (ctx.glCtx == NULL) {
117 LEAVE_GL();
118 WARN_(d3d_caps)("Error creating default context for capabilities initialization\n");
119 failed = TRUE;
123 /* Make it the current GL context */
124 if (!failed && glXMakeCurrent(ctx.display, ctx.drawable, ctx.glCtx) == False) {
125 glXDestroyContext(ctx.display, ctx.glCtx);
126 LEAVE_GL();
127 WARN_(d3d_caps)("Error setting default context as current for capabilities initialization\n");
128 failed = TRUE;
131 /* It worked! Wow... */
132 if (!failed) {
133 gotContext = TRUE;
134 created = TRUE;
135 ret = &ctx;
136 } else {
137 ret = NULL;
140 } else {
141 if (ctx.ref > 0) ret = &ctx;
144 if (NULL != ret) InterlockedIncrement(&ret->ref);
145 return ret;
148 static void WineD3D_ReleaseFakeGLContext(WineD3D_Context* ctx) {
149 /* If we created a dummy context, throw it away */
150 if (NULL != ctx) {
151 if (0 == InterlockedDecrement(&ctx->ref)) {
152 glXMakeCurrent(ctx->display, None, NULL);
153 glXDestroyContext(ctx->display, ctx->glCtx);
154 ctx->display = NULL;
155 ctx->glCtx = NULL;
156 LEAVE_GL();
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);
174 *ppobj = This;
175 return S_OK;
177 *ppobj = NULL;
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);
186 return refCount;
189 static ULONG WINAPI IWineD3DImpl_Release(IWineD3D *iface) {
190 IWineD3DImpl *This = (IWineD3DImpl *)iface;
191 ULONG ref;
192 TRACE("(%p) : Releasing from %ld\n", This, This->ref);
193 ref = InterlockedDecrement(&This->ref);
194 if (ref == 0) {
195 HeapFree(GetProcessHeap(), 0, This);
198 return ref;
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,
207 int* ps_selected,
208 int* vs_selected) {
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;
222 } else {
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;
235 } else {
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) {
244 case SHADER_GLSL:
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;
247 break;
248 case SHADER_ARB:
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;
253 break;
254 case SHADER_SW:
255 gl_info->max_vshader_constantsF = 96; /* TODO: Fixup software shaders */
256 break;
257 default:
258 gl_info->max_vshader_constantsF = 0;
259 break;
262 switch (wined3d_settings.ps_selected_mode) {
263 case SHADER_GLSL:
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;
266 break;
267 case SHADER_ARB:
268 gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
269 break;
270 case SHADER_SW:
271 gl_info->max_pshader_constantsF = 96; /* TODO: Fixup software shaders */
272 break;
273 default:
274 gl_info->max_pshader_constantsF = 0;
275 break;
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;
291 GLint gl_max;
292 GLfloat gl_floatv[2];
293 Bool test = 0;
294 int major, minor;
295 WineD3D_Context *fake_ctx = NULL;
296 BOOL gotContext = FALSE;
297 int i;
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;
304 } else {
305 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);
317 } else {
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;
334 } else {
335 gl_info->gl_vendor = VENDOR_WINE;
337 } else {
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) {
349 case VENDOR_NVIDIA:
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));
353 break;
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));
359 break;
362 while (*gl_string_cursor == ' ') {
363 ++gl_string_cursor;
366 if (!*gl_string_cursor) {
367 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
368 break;
371 major = atoi(gl_string_cursor);
372 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
373 ++gl_string_cursor;
376 if (*gl_string_cursor++ != '.') {
377 ERR_(d3d_caps)("Invalid nVidia version string: %s\n", debugstr_a(gl_string));
378 break;
381 minor = atoi(gl_string_cursor);
382 minor = major*100+minor;
383 major = 10;
385 break;
387 case VENDOR_ATI:
388 major = minor = 0;
389 gl_string_cursor = strchr(gl_string, '-');
390 if (gl_string_cursor) {
391 int error = 0;
392 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')
396 error = 1;
397 if (!error && *(gl_string_cursor+2) > '9' && *(gl_string_cursor+2) < '0')
398 error = 1;
399 if (!error && *(gl_string_cursor+4) > '9' && *(gl_string_cursor+4) < '0')
400 error = 1;
401 if (!error && *(gl_string_cursor+1) != '.' && *(gl_string_cursor+3) != '.')
402 error = 1;
404 /* Mark version number as malformed */
405 if (error)
406 gl_string_cursor = 0;
409 if (!gl_string_cursor)
410 WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
411 else {
412 major = *gl_string_cursor - '0';
413 minor = (*(gl_string_cursor+2) - '0') * 256 + (*(gl_string_cursor+4) - '0');
415 break;
417 case VENDOR_INTEL:
418 case VENDOR_MESA:
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) {
423 char tmp[16];
424 int cursor = 0;
426 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
427 tmp[cursor++] = *gl_string_cursor;
428 ++gl_string_cursor;
430 tmp[cursor] = 0;
431 major = atoi(tmp);
433 if (*gl_string_cursor != '.') WARN_(d3d_caps)("malformed GL_VERSION (%s)\n", debugstr_a(gl_string));
434 ++gl_string_cursor;
436 cursor = 0;
437 while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
438 tmp[cursor++] = *gl_string_cursor;
439 ++gl_string_cursor;
441 tmp[cursor] = 0;
442 minor = atoi(tmp);
444 break;
446 default:
447 major = 0;
448 minor = 9;
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) {
456 case VENDOR_NVIDIA:
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;
469 } else {
470 gl_info->gl_card = CARD_NVIDIA_GEFORCE4_TI4600;
472 break;
474 case VENDOR_ATI:
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;
479 } else {
480 gl_info->gl_card = CARD_ATI_RADEON_8500;
482 break;
484 case VENDOR_INTEL:
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;
495 } else {
496 gl_info->gl_card = CARD_INTEL_I915G;
498 break;
500 default:
501 gl_info->gl_card = CARD_WINE;
502 break;
504 } else {
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);
534 GL_EXT_FUNCS_GEN;
535 GLX_EXT_FUNCS_GEN;
536 #undef USE_GL_FUNC
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");
561 } else {
562 while (*GL_Extensions != 0x00) {
563 const char *Start = GL_Extensions;
564 char ThisExtn[256];
566 memset(ThisExtn, 0x00, sizeof(ThisExtn));
567 while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
568 GL_Extensions++;
570 memcpy(ThisExtn, Start, (GL_Extensions - Start));
571 TRACE_(d3d_caps)("- %s\n", ThisExtn);
574 * ARB
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;
675 * EXT
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;
732 * NVIDIA
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;
773 else
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;
779 * ATI
781 /** TODO */
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");
858 } else {
859 while (*GLX_Extensions != 0x00) {
860 const char *Start = GLX_Extensions;
861 char ThisExtn[256];
863 memset(ThisExtn, 0x00, sizeof(ThisExtn));
864 while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
865 GLX_Extensions++;
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) {
879 return TRUE;
880 } else {
881 return FALSE;
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);
894 return 1;
897 static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
898 IWineD3DImpl *This = (IWineD3DImpl *)iface;
899 FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
900 return WINED3D_OK;
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)) {
908 return NULL;
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)) {
924 return 0;
927 if (Adapter == 0) { /* Display */
928 int i = 0;
929 int j = 0;
930 #if !defined( DEBUG_SINGLE_MODE )
931 DEVMODEW DevModeW;
933 /* Work out the current screen bpp */
934 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
935 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
936 DeleteDC(hdc);
938 while (EnumDisplaySettingsExW(NULL, j, &DevModeW, 0)) {
939 j++;
940 switch (Format)
942 case D3DFMT_UNKNOWN:
943 i++;
944 break;
945 case D3DFMT_X8R8G8B8:
946 case D3DFMT_A8R8G8B8:
947 if (min(DevModeW.dmBitsPerPel, bpp) == 32) i++;
948 if (min(DevModeW.dmBitsPerPel, bpp) == 24) i++;
949 break;
950 case D3DFMT_X1R5G5B5:
951 case D3DFMT_A1R5G5B5:
952 case D3DFMT_R5G6B5:
953 if (min(DevModeW.dmBitsPerPel, bpp) == 16) i++;
954 break;
955 default:
956 /* Skip other modes as they do not match requested format */
957 break;
960 #else
961 i = 1;
962 j = 1;
963 #endif
964 TRACE_(d3d_caps)("(%p}->(Adapter: %d) => %d (out of %d)\n", This, Adapter, i, j);
965 return i;
966 } else {
967 FIXME_(d3d_caps)("Adapter not primary display\n");
969 return 0;
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 */
978 if (NULL == pMode ||
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 )
986 DEVMODEW DevModeW;
987 int ModeIdx = 0;
989 /* Work out the current screen bpp */
990 HDC hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
991 int bpp = GetDeviceCaps(hdc, BITSPIXEL);
992 DeleteDC(hdc);
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)
998 ModeIdx = Mode;
999 } else {
1000 int i = 0;
1001 int j = 0;
1002 DEVMODEW DevModeWtmp;
1005 while (i<(Mode) && EnumDisplaySettingsExW(NULL, j, &DevModeWtmp, 0)) {
1006 j++;
1007 switch (Format)
1009 case D3DFMT_UNKNOWN:
1010 i++;
1011 break;
1012 case D3DFMT_X8R8G8B8:
1013 case D3DFMT_A8R8G8B8:
1014 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 32) i++;
1015 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 24) i++;
1016 break;
1017 case D3DFMT_X1R5G5B5:
1018 case D3DFMT_A1R5G5B5:
1019 case D3DFMT_R5G6B5:
1020 if (min(DevModeWtmp.dmBitsPerPel, bpp) == 16) i++;
1021 break;
1022 default:
1023 /* Skip other modes as they do not match requested format */
1024 break;
1027 ModeIdx = j;
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)
1044 switch (bpp) {
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;
1051 } else {
1052 pMode->Format = Format;
1055 else
1057 TRACE_(d3d_caps)("Requested mode out of range %d\n", Mode);
1058 return WINED3DERR_INVALIDCALL;
1061 #else
1062 /* Return one setting of the format requested */
1063 if (Mode > 0) return WINED3DERR_INVALIDCALL;
1064 pMode->Width = 800;
1065 pMode->Height = 600;
1066 pMode->RefreshRate = D3DADAPTER_DEFAULT;
1067 pMode->Format = (Format == D3DFMT_UNKNOWN) ? D3DFMT_A8R8G8B8 : Format;
1068 bpp = 32;
1069 #endif
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);
1073 } else {
1074 FIXME_(d3d_caps)("Adapter not primary display\n");
1077 return WINED3D_OK;
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 */
1090 int bpp = 0;
1091 DEVMODEW DevModeW;
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;
1103 switch (bpp) {
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;
1111 } else {
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));
1117 return WINED3D_OK;
1120 static Display * WINAPI IWineD3DImpl_GetAdapterDisplay(IWineD3D *iface, UINT Adapter) {
1121 Display *display;
1122 HDC device_context;
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);
1129 return display;
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;
1175 } else {
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;
1195 } else {
1196 *(pIdentifier->WHQLLevel) = 1;
1199 } else {
1200 FIXME_(d3d_caps)("Adapter not primary display\n");
1203 return WINED3D_OK;
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 */
1208 int gl_test;
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);
1218 switch (Format) {
1219 case WINED3DFMT_X8R8G8B8:
1220 case WINED3DFMT_R8G8B8:
1221 if (8 == rb && 8 == gb && 8 == bb) return TRUE;
1222 break;
1223 case WINED3DFMT_A8R8G8B8:
1224 if (8 == rb && 8 == gb && 8 == bb && 8 == ab) return TRUE;
1225 break;
1226 case WINED3DFMT_A2R10G10B10:
1227 if (10 == rb && 10 == gb && 10 == bb && 2 == ab) return TRUE;
1228 break;
1229 case WINED3DFMT_X1R5G5B5:
1230 if (5 == rb && 5 == gb && 5 == bb) return TRUE;
1231 break;
1232 case WINED3DFMT_A1R5G5B5:
1233 if (5 == rb && 5 == gb && 5 == bb && 1 == ab) return TRUE;
1234 break;
1235 case WINED3DFMT_X4R4G4B4:
1236 if (16 == buf_sz && 4 == rb && 4 == gb && 4 == bb) return TRUE;
1237 break;
1238 case WINED3DFMT_R5G6B5:
1239 if (5 == rb && 6 == gb && 5 == bb) return TRUE;
1240 break;
1241 case WINED3DFMT_R3G3B2:
1242 if (3 == rb && 3 == gb && 2 == bb) return TRUE;
1243 break;
1244 case WINED3DFMT_A8P8:
1245 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz && 8 == ab) return TRUE;
1246 break;
1247 case WINED3DFMT_P8:
1248 if (type & GLX_COLOR_INDEX_BIT && 8 == buf_sz) return TRUE;
1249 break;
1250 default:
1251 ERR("unsupported format %s\n", debug_d3dformat(Format));
1252 break;
1254 return FALSE;
1255 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1256 switch (Format) {
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:
1266 case WINED3DFMT_P8:
1267 return TRUE;
1268 default:
1269 ERR("unsupported format %s\n", debug_d3dformat(Format));
1270 break;
1272 return FALSE;
1273 #endif
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 */
1278 int gl_test;
1279 int db, sb;
1281 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_DEPTH_SIZE, &db);
1282 gl_test = glXGetFBConfigAttrib(ctx->display, cfgs, GLX_STENCIL_SIZE, &sb);
1284 switch (Format) {
1285 case WINED3DFMT_D16:
1286 case WINED3DFMT_D16_LOCKABLE:
1287 if (16 == db) return TRUE;
1288 break;
1289 case WINED3DFMT_D32:
1290 if (32 == db) return TRUE;
1291 break;
1292 case WINED3DFMT_D15S1:
1293 if (15 == db) return TRUE;
1294 break;
1295 case WINED3DFMT_D24S8:
1296 if (24 == db && 8 == sb) return TRUE;
1297 break;
1298 case WINED3DFMT_D24FS8:
1299 if (24 == db && 8 == sb) return TRUE;
1300 break;
1301 case WINED3DFMT_D24X8:
1302 if (24 == db) return TRUE;
1303 break;
1304 case WINED3DFMT_D24X4S4:
1305 if (24 == db && 4 == sb) return TRUE;
1306 break;
1307 case WINED3DFMT_D32F_LOCKABLE:
1308 if (32 == db) return TRUE;
1309 break;
1310 default:
1311 ERR("unsupported format %s\n", debug_d3dformat(Format));
1312 break;
1314 return FALSE;
1315 #else /* Most of the time performance is less of an issue than compatibility, this code allows for most common opengl/d3d formats */
1316 switch (Format) {
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:
1326 return TRUE;
1327 default:
1328 ERR("unsupported format %s\n", debug_d3dformat(Format));
1329 break;
1331 return FALSE;
1332 #endif
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;
1343 int nCfgs = 0;
1344 int it;
1346 WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
1347 This, Adapter,
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();
1359 if(NULL != ctx) {
1360 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1361 } else {
1362 TRACE_(d3d_caps)("(%p) : Unable to create a fake context at this time (there may already be an active context)\n", This);
1365 if (NULL != cfgs) {
1366 for (it = 0; it < nCfgs; ++it) {
1367 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], RenderTargetFormat)) {
1368 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithDepthFmt(ctx, cfgs[it], DepthStencilFormat)) {
1369 hr = WINED3D_OK;
1370 break ;
1374 XFree(cfgs);
1375 cfgs = NULL;
1376 } else {
1377 /* If there's a corrent context then we cannot create a fake one so pass everything */
1378 hr = WINED3D_OK;
1381 if (ctx != NULL)
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);
1388 return 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",
1397 This,
1398 Adapter,
1399 DeviceType, debug_d3ddevicetype(DeviceType),
1400 SurfaceFormat, debug_d3dformat(SurfaceFormat),
1401 Windowed,
1402 MultiSampleType,
1403 pQualityLevels);
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");
1413 s_single_shot = 1;
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",
1427 This,
1428 Adapter,
1429 CheckType, debug_d3ddevicetype(CheckType),
1430 DisplayFormat, debug_d3dformat(DisplayFormat),
1431 BackBufferFormat, debug_d3dformat(BackBufferFormat),
1432 Windowed);
1434 if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
1435 return WINED3DERR_INVALIDCALL;
1439 GLXFBConfig* cfgs = NULL;
1440 int nCfgs = 0;
1441 int it;
1442 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1444 WineD3D_Context* ctx = WineD3D_CreateFakeGLContext();
1445 if (NULL != ctx) {
1446 cfgs = glXGetFBConfigs(ctx->display, DefaultScreen(ctx->display), &nCfgs);
1447 for (it = 0; it < nCfgs; ++it) {
1448 if (IWineD3DImpl_IsGLXFBConfigCompatibleWithRenderFmt(ctx, cfgs[it], DisplayFormat)) {
1449 hr = WINED3D_OK;
1450 break ;
1453 XFree(cfgs);
1455 WineD3D_ReleaseFakeGLContext(ctx);
1456 return hr;
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)) ",
1467 This,
1468 Adapter,
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");
1500 return WINED3D_OK;
1501 default:
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:
1518 case WINED3DFMT_P8:
1519 TRACE_(d3d_caps)("[OK]\n");
1520 return WINED3D_OK;
1521 default:
1522 TRACE_(d3d_caps)("[FAILED]\n");
1523 return WINED3DERR_NOTAVAILABLE;
1527 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
1528 switch (CheckFormat) {
1529 case D3DFMT_DXT1:
1530 case D3DFMT_DXT2:
1531 case D3DFMT_DXT3:
1532 case D3DFMT_DXT4:
1533 case D3DFMT_DXT5:
1534 TRACE_(d3d_caps)("[OK]\n");
1535 return WINED3D_OK;
1536 default:
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) {
1555 /*****
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:
1566 case WINED3DFMT_A8:
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");
1574 return WINED3D_OK;
1576 /*****
1577 * supported: Palettized
1579 case WINED3DFMT_P8:
1580 TRACE_(d3d_caps)("[OK]\n");
1581 return WINED3D_OK;
1583 /*****
1584 * Supported: (Alpha)-Luminance
1586 case WINED3DFMT_L8:
1587 case WINED3DFMT_A8L8:
1588 case WINED3DFMT_A4L4:
1589 TRACE_(d3d_caps)("[OK]\n");
1590 return WINED3D_OK;
1592 /*****
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");
1605 return WINED3D_OK;
1607 /*****
1608 * DXTN Formats: Handled above
1609 * WINED3DFMT_DXT1
1610 * WINED3DFMT_DXT2
1611 * WINED3DFMT_DXT3
1612 * WINED3DFMT_DXT4
1613 * WINED3DFMT_DXT5
1616 /*****
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;
1626 /*****
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;
1639 /* Not supported */
1640 case WINED3DFMT_G16R16:
1641 case WINED3DFMT_A16B16G16R16:
1642 TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
1643 return WINED3DERR_NOTAVAILABLE;
1645 default:
1646 break;
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",
1658 This,
1659 Adapter,
1660 DeviceType, debug_d3ddevicetype(DeviceType),
1661 SourceFormat, debug_d3dformat(SourceFormat),
1662 TargetFormat, debug_d3dformat(TargetFormat));
1663 return WINED3D_OK;
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;
1699 *pCaps->Caps = 0;
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;
1730 /* TODO:
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 */
1740 #if 0
1741 if (GL_SUPPORT(NV_REGISTER_COMBINERS))
1742 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_TSSARGTEMP;
1743 if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
1744 *pCaps->PrimitiveMiscCaps |= D3DPMISCCAPS_PERSTAGECONSTANT;
1745 #endif
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;
1766 /* FIXME Add:
1767 WINED3DPRASTERCAPS_COLORPERSPECTIVE
1768 WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
1769 WINED3DPRASTERCAPS_ANTIALIASEDGES
1770 WINED3DPRASTERCAPS_ZBUFFERLESSHSR
1771 WINED3DPRASTERCAPS_WBUFFER */
1773 *pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS |
1774 D3DPCMPCAPS_EQUAL |
1775 D3DPCMPCAPS_GREATER |
1776 D3DPCMPCAPS_GREATEREQUAL |
1777 D3DPCMPCAPS_LESS |
1778 D3DPCMPCAPS_LESSEQUAL |
1779 D3DPCMPCAPS_NEVER |
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 |
1791 D3DPBLENDCAPS_ONE |
1792 D3DPBLENDCAPS_SRCALPHA |
1793 D3DPBLENDCAPS_SRCALPHASAT |
1794 D3DPBLENDCAPS_SRCCOLOR |
1795 D3DPBLENDCAPS_ZERO;
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 |
1806 D3DPBLENDCAPS_ONE |
1807 D3DPBLENDCAPS_SRCALPHA |
1808 D3DPBLENDCAPS_SRCALPHASAT |
1809 D3DPBLENDCAPS_SRCCOLOR |
1810 D3DPBLENDCAPS_ZERO;
1812 *pCaps->AlphaCmpCaps = D3DPCMPCAPS_ALWAYS |
1813 D3DPCMPCAPS_EQUAL |
1814 D3DPCMPCAPS_GREATER |
1815 D3DPCMPCAPS_GREATEREQUAL |
1816 D3DPCMPCAPS_LESS |
1817 D3DPCMPCAPS_LESSEQUAL |
1818 D3DPCMPCAPS_NEVER |
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;
1887 } else
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;
1903 } else
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 |
1923 D3DLINECAPS_ZTEST;
1924 /* FIXME: Add
1925 D3DLINECAPS_BLEND
1926 D3DLINECAPS_ALPHACMP
1927 D3DLINECAPS_FOG */
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);
1934 else
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 |
1983 D3DTEXOPCAPS_LERP |
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;
2002 #if 0
2003 *pCaps->TextureOpCaps |= D3DTEXOPCAPS_BUMPENVMAP;
2004 /* FIXME: Add
2005 D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
2006 D3DTEXOPCAPS_PREMODULATE */
2007 #endif
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);
2018 #else
2019 *pCaps->MaxVertexBlendMatrices = 0;
2020 #endif
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;
2033 /* FIXME: Add
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);
2049 else
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");
2058 } else {
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);
2071 else
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"); */
2085 } else {
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 |
2110 D3DDTCAPS_UBYTE4N |
2111 D3DDTCAPS_SHORT2N |
2112 D3DDTCAPS_SHORT4N |
2113 D3DDTCAPS_FLOAT16_2 |
2114 D3DDTCAPS_FLOAT16_4;
2116 } else
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)) {
2122 ENTER_GL();
2123 glEnable(GL_MAX_DRAW_BUFFERS_ATI);
2124 glGetIntegerv(GL_MAX_DRAW_BUFFERS_ATI, &max_buffers);
2125 glDisable(GL_MAX_DRAW_BUFFERS_ATI);
2126 LEAVE_GL();
2128 #endif
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;
2200 return WINED3D_OK;
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,
2208 IUnknown *parent) {
2210 IWineD3DDeviceImpl *object = NULL;
2211 IWineD3DImpl *This = (IWineD3DImpl *)iface;
2212 HDC hDC;
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;
2230 object->ref = 1;
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,
2254 WINED3DSBT_INIT,
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 */
2266 ENTER_GL();
2267 /* FIXME: both of those should be made per adapter */
2268 IWineD3DImpl_FillGLCaps(iface, IWineD3DImpl_GetAdapterDisplay(iface, Adapter));
2269 LEAVE_GL();
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)
2276 return 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));
2286 DeleteDC(hDC);
2288 return WINED3D_OK;
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;
2324 return WINED3D_OK;
2327 /**********************************************************
2328 * IWineD3D VTbl follows
2329 **********************************************************/
2331 const IWineD3DVtbl IWineD3D_Vtbl =
2333 /* IUnknown */
2334 IWineD3DImpl_QueryInterface,
2335 IWineD3DImpl_AddRef,
2336 IWineD3DImpl_Release,
2337 /* IWineD3D */
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