* Copyright 2003-2004 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
+ * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#define DEBUG_SINGLE_MODE 0
#endif
-
#include "config.h"
#include <assert.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
+#define GLINFO_LOCATION (*gl_info)
+
+/* The d3d device ID */
+static const GUID IID_D3DDEVICE_D3DUID = { 0xaeb2cdd4, 0x6e41, 0x43ea, { 0x94,0x1c,0x83,0x61,0xcc,0x76,0x07,0x81 } };
+
/* Extension detection */
static const struct {
const char *extension_string;
{"GL_APPLE_fence", APPLE_FENCE, 0 },
{"GL_APPLE_flush_render", APPLE_FLUSH_RENDER, 0 },
{"GL_APPLE_ycbcr_422", APPLE_YCBCR_422, 0 },
+ {"GL_APPLE_float_pixels", APPLE_FLOAT_PIXELS, 0 },
/* ATI */
{"GL_ATI_separate_stencil", ATI_SEPARATE_STENCIL, 0 },
{"GL_ATI_texture_env_combine3", ATI_TEXTURE_ENV_COMBINE3, 0 },
{"GL_ATI_texture_mirror_once", ATI_TEXTURE_MIRROR_ONCE, 0 },
- {"GL_ATI_envmap_bumpmap", ATI_ENVMAP_BUMPMAP, 0 },
+ {"GL_ATI_fragment_shader", ATI_FRAGMENT_SHADER, 0 },
+ {"GL_ATI_texture_compression_3dc", ATI_TEXTURE_COMPRESSION_3DC, 0 },
/* ARB */
+ {"GL_ARB_color_buffer_float", ARB_COLOR_BUFFER_FLOAT, 0 },
{"GL_ARB_draw_buffers", ARB_DRAW_BUFFERS, 0 },
{"GL_ARB_fragment_program", ARB_FRAGMENT_PROGRAM, 0 },
{"GL_ARB_fragment_shader", ARB_FRAGMENT_SHADER, 0 },
+ {"GL_ARB_geometry_shader4", ARB_GEOMETRY_SHADER4, 0 },
{"GL_ARB_half_float_pixel", ARB_HALF_FLOAT_PIXEL, 0 },
{"GL_ARB_imaging", ARB_IMAGING, 0 },
{"GL_ARB_multisample", ARB_MULTISAMPLE, 0 }, /* needs GLX_ARB_MULTISAMPLE as well */
{"GL_ARB_texture_env_dot3", ARB_TEXTURE_ENV_DOT3, 0 },
{"GL_ARB_texture_float", ARB_TEXTURE_FLOAT, 0 },
{"GL_ARB_texture_mirrored_repeat", ARB_TEXTURE_MIRRORED_REPEAT, 0 },
- {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, 0 },
+ {"GL_ARB_texture_non_power_of_two", ARB_TEXTURE_NON_POWER_OF_TWO, MAKEDWORD_VERSION(2, 0) },
+ {"GL_ARB_texture_rectangle", ARB_TEXTURE_RECTANGLE, 0 },
+ {"GL_ARB_texture_rg", ARB_TEXTURE_RG, 0 },
{"GL_ARB_vertex_blend", ARB_VERTEX_BLEND, 0 },
{"GL_ARB_vertex_buffer_object", ARB_VERTEX_BUFFER_OBJECT, 0 },
{"GL_ARB_vertex_program", ARB_VERTEX_PROGRAM, 0 },
{"GL_ARB_vertex_shader", ARB_VERTEX_SHADER, 0 },
{"GL_ARB_shader_objects", ARB_SHADER_OBJECTS, 0 },
+ {"GL_ARB_shader_texture_lod", ARB_SHADER_TEXTURE_LOD, 0 },
+ {"GL_ARB_half_float_vertex", ARB_HALF_FLOAT_VERTEX, 0 },
/* EXT */
+ {"GL_EXT_blend_color", EXT_BLEND_COLOR, 0 },
{"GL_EXT_blend_minmax", EXT_BLEND_MINMAX, 0 },
+ {"GL_EXT_blend_equation_separate", EXT_BLEND_EQUATION_SEPARATE, 0 },
+ {"GL_EXT_blend_func_separate", EXT_BLEND_FUNC_SEPARATE, 0 },
{"GL_EXT_fog_coord", EXT_FOG_COORD, 0 },
{"GL_EXT_framebuffer_blit", EXT_FRAMEBUFFER_BLIT, 0 },
+ {"GL_EXT_framebuffer_multisample", EXT_FRAMEBUFFER_MULTISAMPLE, 0 },
{"GL_EXT_framebuffer_object", EXT_FRAMEBUFFER_OBJECT, 0 },
{"GL_EXT_paletted_texture", EXT_PALETTED_TEXTURE, 0 },
{"GL_EXT_point_parameters", EXT_POINT_PARAMETERS, 0 },
{"GL_EXT_stencil_wrap", EXT_STENCIL_WRAP, 0 },
{"GL_EXT_texture3D", EXT_TEXTURE3D, MAKEDWORD_VERSION(1, 2) },
{"GL_EXT_texture_compression_s3tc", EXT_TEXTURE_COMPRESSION_S3TC, 0 },
+ {"GL_EXT_texture_compression_rgtc", EXT_TEXTURE_COMPRESSION_RGTC, 0 },
{"GL_EXT_texture_env_add", EXT_TEXTURE_ENV_ADD, 0 },
{"GL_EXT_texture_env_combine", EXT_TEXTURE_ENV_COMBINE, 0 },
{"GL_EXT_texture_env_dot3", EXT_TEXTURE_ENV_DOT3, 0 },
{"GL_EXT_texture_sRGB", EXT_TEXTURE_SRGB, 0 },
+ {"GL_EXT_texture_swizzle", EXT_TEXTURE_SWIZZLE, 0 },
{"GL_EXT_texture_filter_anisotropic", EXT_TEXTURE_FILTER_ANISOTROPIC, 0 },
{"GL_EXT_texture_lod", EXT_TEXTURE_LOD, 0 },
{"GL_EXT_texture_lod_bias", EXT_TEXTURE_LOD_BIAS, 0 },
+ {"GL_EXT_vertex_array_bgra", EXT_VERTEX_ARRAY_BGRA, 0 },
{"GL_EXT_vertex_shader", EXT_VERTEX_SHADER, 0 },
- {"GL_EXT_vertex_weighting", EXT_VERTEX_WEIGHTING, 0 },
+ {"GL_EXT_gpu_program_parameters", EXT_GPU_PROGRAM_PARAMETERS, 0 },
/* NV */
{"GL_NV_half_float", NV_HALF_FLOAT, 0 },
{"GL_NV_vertex_program2", NV_VERTEX_PROGRAM2, 0 },
{"GL_NV_vertex_program3", NV_VERTEX_PROGRAM3, 0 },
{"GL_NV_depth_clamp", NV_DEPTH_CLAMP, 0 },
+ {"GL_NV_light_max_exponent", NV_LIGHT_MAX_EXPONENT, 0 },
/* SGI */
{"GL_SGIS_generate_mipmap", SGIS_GENERATE_MIPMAP, 0 },
* Utility functions follow
**********************************************************/
-/* Adapters */
-static int numAdapters = 0;
-static struct WineD3DAdapter Adapters[1];
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat, WINED3DSURFTYPE SurfaceType);
+static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
+ WINED3DDEVTYPE DeviceType);
+static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
+static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType);
/* lookup tables */
-int minLookup[MAX_LOOKUPS];
-int maxLookup[MAX_LOOKUPS];
+const int minLookup[MAX_LOOKUPS] =
+{
+ WINED3DTADDRESS_WRAP, /* WINELOOKUP_WARPPARAM */
+};
+
+const int maxLookup[MAX_LOOKUPS] =
+{
+ WINED3DTADDRESS_MIRRORONCE, /* WINELOOKUP_WARPPARAM */
+};
+
DWORD *stateLookup[MAX_LOOKUPS];
-DWORD minMipLookup[WINED3DTEXF_ANISOTROPIC + 1][WINED3DTEXF_LINEAR + 1];
+struct min_lookup minMipLookup[WINED3DTEXF_ANISOTROPIC + 1];
+const struct min_lookup minMipLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
+{
+ {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
+ {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
+ {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
+ {{GL_NEAREST, GL_NEAREST, GL_NEAREST}},
+};
+
+GLenum magLookup[WINED3DTEXF_ANISOTROPIC + 1];
+const GLenum magLookup_noFilter[WINED3DTEXF_ANISOTROPIC + 1] =
+{
+ GL_NEAREST, GL_NEAREST, GL_NEAREST, GL_NEAREST
+};
+/* drawStridedSlow attributes */
+glAttribFunc position_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc diffuse_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc specular_func_3ubv;
+glAttribFunc specular_funcs[WINED3D_FFP_EMIT_COUNT];
+glAttribFunc normal_funcs[WINED3D_FFP_EMIT_COUNT];
+glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT];
/**
- * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
- * ie there is no GL Context - Get a default rendering context to enable the
- * function query some info from GL
+ * Note: GL seems to trap if GetDeviceCaps is called before any HWND's created,
+ * i.e., there is no GL Context - Get a default rendering context to enable the
+ * function query some info from GL.
*/
static int wined3d_fake_gl_context_ref = 0;
if(!wined3d_fake_gl_context_foreign && glCtx) {
TRACE_(d3d_caps)("destroying fake GL context\n");
pwglMakeCurrent(NULL, NULL);
- //ros hack, this line does destire the real icd interface in windows and reactos
- // pwglDeleteContext(glCtx);
+ //pwglDeleteContext(glCtx);
}
if(wined3d_fake_gl_context_hdc)
ReleaseDC(wined3d_fake_gl_context_hwnd, wined3d_fake_gl_context_hdc);
/* Adjust the amount of used texture memory */
long WineD3DAdapterChangeGLRam(IWineD3DDeviceImpl *D3DDevice, long glram){
- UINT Adapter = D3DDevice->adapterNo;
+ struct WineD3DAdapter *adapter = D3DDevice->adapter;
- Adapters[Adapter].UsedTextureRam += glram;
- TRACE("Adjusted gl ram by %ld to %d\n", glram, Adapters[Adapter].UsedTextureRam);
- return Adapters[Adapter].UsedTextureRam;
+ adapter->UsedTextureRam += glram;
+ TRACE("Adjusted gl ram by %ld to %d\n", glram, adapter->UsedTextureRam);
+ return adapter->UsedTextureRam;
}
/**********************************************************
TRACE("(%p) : Releasing from %d\n", This, This->ref);
ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
+ unsigned int i;
+
+ for (i = 0; i < This->adapter_count; ++i)
+ {
+ HeapFree(GetProcessHeap(), 0, This->adapters[i].cfgs);
+ }
HeapFree(GetProcessHeap(), 0, This);
}
/* Set the shader type for this device, depending on the given capabilities,
* the device type, and the user preferences in wined3d_settings */
-static void select_shader_mode(
- WineD3D_GL_Info *gl_info,
- WINED3DDEVTYPE DeviceType,
- int* ps_selected,
- int* vs_selected) {
-
+static void select_shader_mode(const WineD3D_GL_Info *gl_info, WINED3DDEVTYPE DeviceType, int *ps_selected, int *vs_selected)
+{
if (wined3d_settings.vs_mode == VS_NONE) {
*vs_selected = SHADER_NONE;
} else if (gl_info->supported[ARB_VERTEX_SHADER] && wined3d_settings.glslRequested) {
*ps_selected = SHADER_GLSL;
} else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) {
*ps_selected = SHADER_ARB;
+ } else if (gl_info->supported[ATI_FRAGMENT_SHADER]) {
+ *ps_selected = SHADER_ATI;
} else {
*ps_selected = SHADER_NONE;
}
switch (vs_selected_mode) {
case SHADER_GLSL:
- /* Subtract the other potential uniforms from the max available (bools, ints, and 1 row of projection matrix) */
- gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 1;
+ gl_info->max_vshader_constantsF = gl_info->vs_glsl_constantsF;
break;
case SHADER_ARB:
- /* We have to subtract any other PARAMs that we might use in our shader programs.
- * ATI seems to count 2 implicit PARAMs when we use fog and NVIDIA counts 1,
- * and we reference one row of the PROJECTION matrix which counts as 1 PARAM. */
- gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF - 3;
+ gl_info->max_vshader_constantsF = gl_info->vs_arb_constantsF;
break;
default:
gl_info->max_vshader_constantsF = 0;
switch (ps_selected_mode) {
case SHADER_GLSL:
- /* Subtract the other potential uniforms from the max available (bools & ints), and 2 states for fog.
- * In theory the texbem instruction may need one more shader constant too. But lets assume
- * that a sm <= 1.3 shader does not need all the uniforms provided by a glsl-capable card,
- * and lets not take away a uniform needlessly from all other shaders.
- */
- gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF - (MAX_CONST_B / 4) - MAX_CONST_I - 2;
+ gl_info->max_pshader_constantsF = gl_info->ps_glsl_constantsF;
break;
case SHADER_ARB:
- /* The arb shader only loads the bump mapping environment matrix into the shader if it finds
- * a free constant to do that, so only reduce the number of available constants by 2 for the fog states.
- */
- gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF - 2;
+ gl_info->max_pshader_constantsF = gl_info->ps_arb_constantsF;
break;
default:
gl_info->max_pshader_constantsF = 0;
* IWineD3D parts follows
**********************************************************/
-#define GLINFO_LOCATION (*gl_info)
-static inline BOOL test_arb_vs_offset_limit(WineD3D_GL_Info *gl_info) {
+static inline BOOL test_arb_vs_offset_limit(const WineD3D_GL_Info *gl_info)
+{
GLuint prog;
BOOL ret = FALSE;
const char *testcode =
"!!ARBvp1.0\n"
"PARAM C[66] = { program.env[0..65] };\n"
"ADDRESS A0;"
- "ARL A0.x, 0.0;\n"
+ "PARAM zero = {0.0, 0.0, 0.0, 0.0};\n"
+ "ARL A0.x, zero.x;\n"
"MOV result.position, C[A0.x + 65];\n"
"END\n";
return 0;
}
-BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
+static BOOL IWineD3DImpl_FillGLCaps(WineD3D_GL_Info *gl_info) {
const char *GL_Extensions = NULL;
const char *WGL_Extensions = NULL;
const char *gl_string = NULL;
GLfloat gl_floatv[2];
int major = 1, minor = 0;
BOOL return_value = TRUE;
- int i;
+ unsigned i;
HDC hdc;
unsigned int vidmem=0;
ENTER_GL();
gl_string = (const char *) glGetString(GL_RENDERER);
- if (NULL == gl_string)
- gl_string = "None";
+ if (!gl_string) gl_string = "None";
strcpy(gl_info->gl_renderer, gl_string);
gl_string = (const char *) glGetString(GL_VENDOR);
gl_info->gl_vendor = VENDOR_NVIDIA;
} else if (strstr(gl_string, "ATI")) {
gl_info->gl_vendor = VENDOR_ATI;
- } else if (strstr(gl_string, "Intel(R)") ||
- strstr(gl_info->gl_renderer, "Intel(R)")) {
+ } else if (strstr(gl_string, "Intel(R)") ||
+ strstr(gl_info->gl_renderer, "Intel(R)") ||
+ strstr(gl_string, "Intel Inc.")) {
gl_info->gl_vendor = VENDOR_INTEL;
} else if (strstr(gl_string, "Mesa")) {
gl_info->gl_vendor = VENDOR_MESA;
gl_string = (const char *) glGetString(GL_VERSION);
if (gl_string != NULL) {
+ /* First, parse the generic opengl version. This is supposed not to be convoluted with
+ * driver specific information
+ */
+ gl_string_cursor = gl_string;
+ major = atoi(gl_string_cursor);
+ if(major <= 0) {
+ ERR("Invalid opengl major version: %d\n", major);
+ }
+ while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
+ ++gl_string_cursor;
+ }
+ if (*gl_string_cursor++ != '.') {
+ ERR_(d3d_caps)("Invalid opengl version string: %s\n", debugstr_a(gl_string));
+ }
+ minor = atoi(gl_string_cursor);
+ TRACE_(d3d_caps)("Found OpenGL version: %d.%d\n", major, minor);
+ gl_info->gl_version = MAKEDWORD_VERSION(major, minor);
+
+ /* Now parse the driver specific string which we'll report to the app */
switch (gl_info->gl_vendor) {
case VENDOR_NVIDIA:
gl_string_cursor = strstr(gl_string, "NVIDIA");
}
break;
- case VENDOR_INTEL:
+ case VENDOR_INTEL:
+ /* Apple and Mesa version strings look differently, but both provide intel drivers */
+ if(strstr(gl_string, "APPLE")) {
+ /* [0-9]+.[0-9]+ APPLE-[0-9]+.[0.9]+.[0.9]+
+ * We only need the first part, and use the APPLE as identification
+ * "1.2 APPLE-1.4.56"
+ */
+ gl_string_cursor = gl_string;
+ major = atoi(gl_string_cursor);
+ while (*gl_string_cursor <= '9' && *gl_string_cursor >= '0') {
+ ++gl_string_cursor;
+ }
+
+ if (*gl_string_cursor++ != '.') {
+ ERR_(d3d_caps)("Invalid MacOS-Intel version string: %s\n", debugstr_a(gl_string));
+ break;
+ }
+
+ minor = atoi(gl_string_cursor);
+ break;
+ }
+
case VENDOR_MESA:
gl_string_cursor = strstr(gl_string, "Mesa");
gl_string_cursor = strstr(gl_string_cursor, " ");
major = 0;
minor = 9;
}
- gl_info->gl_driver_version = MAKEDWORD_VERSION(major, minor);
- TRACE_(d3d_caps)("found GL_VERSION (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->gl_driver_version);
+ gl_info->driver_version = MAKEDWORD_VERSION(major, minor);
+ TRACE_(d3d_caps)("found driver version (%s)->%i.%i->(0x%08x)\n", debugstr_a(gl_string), major, minor, gl_info->driver_version);
+ /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
+ gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
+ } else {
+ FIXME("OpenGL driver did not return version information\n");
+ gl_info->driver_version = MAKEDWORD_VERSION(0, 0);
+ gl_info->driver_version_hipart = MAKEDWORD_VERSION(6, 14);
}
TRACE_(d3d_caps)("found GL_RENDERER (%s)->(0x%04x)\n", debugstr_a(gl_info->gl_renderer), gl_info->gl_card);
* Initialize openGL extension related variables
* with Default values
*/
- memset(&gl_info->supported, 0, sizeof(gl_info->supported));
+ memset(gl_info->supported, 0, sizeof(gl_info->supported));
gl_info->max_buffers = 1;
gl_info->max_textures = 1;
gl_info->max_texture_stages = 1;
gl_info->max_fragment_samplers = 1;
gl_info->max_vertex_samplers = 0;
- gl_info->max_combined_samplers = 0;
+ gl_info->max_combined_samplers = gl_info->max_fragment_samplers + gl_info->max_vertex_samplers;
gl_info->max_sampler_stages = 1;
gl_info->ps_arb_version = PS_VERSION_NOT_SUPPORTED;
gl_info->ps_arb_max_temps = 0;
gl_info->max_texture_size = gl_max;
TRACE_(d3d_caps)("Maximum texture size support - max texture size=%d\n", gl_max);
- glGetFloatv(GL_POINT_SIZE_RANGE, gl_floatv);
+ glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, gl_floatv);
gl_info->max_pointsizemin = gl_floatv[0];
gl_info->max_pointsize = gl_floatv[1];
TRACE_(d3d_caps)("Maximum point size support - max point size=%f\n", gl_floatv[1]);
- glGetIntegerv(GL_AUX_BUFFERS, &gl_max);
- gl_info->max_aux_buffers = gl_max;
- TRACE_(d3d_caps)("Offscreen rendering support - number of aux buffers=%d\n", gl_max);
-
/* Parse the gl supported features, in theory enabling parts of our code appropriately */
GL_Extensions = (const char *) glGetString(GL_EXTENSIONS);
TRACE_(d3d_caps)("GL_Extensions reported:\n");
}
}
}
+
+ LEAVE_GL();
+
/* Now work out what GL support this card really has */
#define USE_GL_FUNC(type, pfn, ext, replace) { \
DWORD ver = ver_for_ext(ext); \
if(gl_info->supported[ext]) gl_info->pfn = (type) pwglGetProcAddress(#pfn); \
- else if(ver && ver <= gl_info->gl_driver_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
+ else if(ver && ver <= gl_info->gl_version) gl_info->pfn = (type) pwglGetProcAddress(#replace); \
else gl_info->pfn = NULL; \
}
GL_EXT_FUNCS_GEN;
WGL_EXT_FUNCS_GEN;
#undef USE_GL_FUNC
+ ENTER_GL();
/* Now mark all the extensions supported which are included in the opengl core version. Do this *after*
* loading the functions, otherwise the code above will load the extension entry points instead of the
* core functions, which may not work
*/
for (i = 0; i < (sizeof(EXTENSION_MAP) / sizeof(*EXTENSION_MAP)); ++i) {
if (gl_info->supported[EXTENSION_MAP[i].extension] == FALSE &&
- EXTENSION_MAP[i].version <= gl_info->gl_driver_version && EXTENSION_MAP[i].version) {
+ EXTENSION_MAP[i].version <= gl_info->gl_version && EXTENSION_MAP[i].version) {
TRACE_(d3d_caps)(" GL CORE: %s support\n", EXTENSION_MAP[i].extension_string);
gl_info->supported[EXTENSION_MAP[i].extension] = TRUE;
}
*/
gl_info->supported[NV_FENCE] = FALSE;
}
+ if (gl_info->supported[APPLE_FLOAT_PIXELS]) {
+ /* GL_APPLE_float_pixels == GL_ARB_texture_float + GL_ARB_half_float_pixel
+ *
+ * The enums are the same:
+ * GL_RGBA16F_ARB = GL_RGBA_FLOAT16_APPLE = 0x881A
+ * GL_RGB16F_ARB = GL_RGB_FLOAT16_APPLE = 0x881B
+ * GL_RGBA32F_ARB = GL_RGBA_FLOAT32_APPLE = 0x8814
+ * GL_RGB32F_ARB = GL_RGB_FLOAT32_APPLE = 0x8815
+ * GL_HALF_FLOAT_ARB = GL_HALF_APPLE = 0x140B
+ */
+ if(!gl_info->supported[ARB_TEXTURE_FLOAT]) {
+ TRACE_(d3d_caps)(" IMPLIED: GL_ARB_texture_float support(from GL_APPLE_float_pixels\n");
+ gl_info->supported[ARB_TEXTURE_FLOAT] = TRUE;
+ }
+ if(!gl_info->supported[ARB_HALF_FLOAT_PIXEL]) {
+ TRACE_(d3d_caps)(" IMPLIED: GL_ARB_half_float_pixel support(from GL_APPLE_float_pixels\n");
+ gl_info->supported[ARB_HALF_FLOAT_PIXEL] = TRUE;
+ }
+ }
if (gl_info->supported[ARB_TEXTURE_CUBE_MAP]) {
TRACE_(d3d_caps)(" IMPLIED: NVIDIA (NV) Texture Gen Reflection support\n");
gl_info->supported[NV_TEXGEN_REFLECTION] = TRUE;
}
if (gl_info->supported[NV_TEXTURE_SHADER2]) {
- /* GL_ATI_envmap_bumpmap won't play nice with texture shaders, so disable it
- * Won't occur in any real world situation though
- */
- gl_info->supported[ATI_ENVMAP_BUMPMAP] = FALSE;
+ if(gl_info->supported[NV_REGISTER_COMBINERS]) {
+ /* Also disable ATI_FRAGMENT_SHADER if register combiners and texture_shader2
+ * are supported. The nv extensions provide the same functionality as the
+ * ATI one, and a bit more(signed pixelformats)
+ */
+ gl_info->supported[ATI_FRAGMENT_SHADER] = FALSE;
+ }
}
if (gl_info->supported[ARB_DRAW_BUFFERS]) {
glGetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, &gl_max);
* a fixed function pipeline anymore.
*
* So this is just a check to check that our assumption holds true. If not, write a warning
- * and reduce the number of vertex samplers or propably disable vertex texture fetch.
+ * and reduce the number of vertex samplers or probably disable vertex texture fetch.
*/
if(gl_info->max_vertex_samplers &&
MAX_TEXTURES + gl_info->max_vertex_samplers > gl_info->max_combined_samplers) {
FIXME("OpenGL implementation supports %u vertex samplers and %u total samplers\n",
gl_info->max_vertex_samplers, gl_info->max_combined_samplers);
FIXME("Expected vertex samplers + MAX_TEXTURES(=8) > combined_samplers\n");
- gl_info->max_vertex_samplers = max(0, gl_info->max_combined_samplers - MAX_TEXTURES);
+ if( gl_info->max_combined_samplers > MAX_TEXTURES )
+ gl_info->max_vertex_samplers =
+ gl_info->max_combined_samplers - MAX_TEXTURES;
+ else
+ gl_info->max_vertex_samplers = 0;
}
} else {
gl_info->max_combined_samplers = gl_info->max_fragment_samplers;
} else if (gl_info->supported[NV_FRAGMENT_PROGRAM]) {
gl_info->ps_nv_version = PS_VERSION_20;
}
-
+ if (gl_info->supported[NV_LIGHT_MAX_EXPONENT]) {
+ glGetFloatv(GL_MAX_SHININESS_NV, &gl_info->max_shininess);
+ } else {
+ gl_info->max_shininess = 128.0;
+ }
+ if (gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO]) {
+ /* If we have full NP2 texture support, disable GL_ARB_texture_rectangle because we will never use it.
+ * This saves a few redundant glDisable calls
+ */
+ gl_info->supported[ARB_TEXTURE_RECTANGLE] = FALSE;
+ }
+ if(gl_info->supported[ATI_FRAGMENT_SHADER]) {
+ /* Disable NV_register_combiners and fragment shader if this is supported.
+ * generally the NV extensions are preferred over the ATI ones, and this
+ * extension is disabled if register_combiners and texture_shader2 are both
+ * supported. So we reach this place only if we have incomplete NV dxlevel 8
+ * fragment processing support
+ */
+ gl_info->supported[NV_REGISTER_COMBINERS] = FALSE;
+ gl_info->supported[NV_REGISTER_COMBINERS2] = FALSE;
+ gl_info->supported[NV_TEXTURE_SHADER] = FALSE;
+ gl_info->supported[NV_TEXTURE_SHADER2] = FALSE;
+ gl_info->supported[NV_TEXTURE_SHADER3] = FALSE;
+ }
+ if(gl_info->supported[NV_HALF_FLOAT]) {
+ /* GL_ARB_half_float_vertex is a subset of GL_NV_half_float */
+ gl_info->supported[ARB_HALF_FLOAT_VERTEX] = TRUE;
+ }
+ if(gl_info->supported[ARB_POINT_SPRITE]) {
+ gl_info->max_point_sprite_units = gl_info->max_textures;
+ } else {
+ gl_info->max_point_sprite_units = 0;
+ }
}
checkGLcall("extension detection\n");
* video memory. If the value is slightly wrong it doesn't matter as we didn't include AGP-like memory which
* makes the amount of addressable memory higher and second OpenGL isn't that critical it moves to system
* memory behind our backs if really needed.
- * Note that the amout of video memory can be overruled using a registry setting.
+ * Note that the amount of video memory can be overruled using a registry setting.
*/
switch (gl_info->gl_vendor) {
case VENDOR_NVIDIA:
* shader capabilities, so we use the shader capabilities to distinguish between FX and 6xxx/7xxx.
*/
if(WINE_D3D9_CAPABLE(gl_info) && (gl_info->vs_nv_version == VS_VERSION_30)) {
+ /* Geforce 200 - highend */
+ if(strstr(gl_info->gl_renderer, "GTX 280") ||
+ strstr(gl_info->gl_renderer, "GTX 285") ||
+ strstr(gl_info->gl_renderer, "GTX 295"))
+ {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX280;
+ vidmem = 1024;
+ }
+ /* Geforce 200 - midend high */
+ if(strstr(gl_info->gl_renderer, "GTX 275")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX275;
+ vidmem = 896;
+ }
+ /* Geforce 200 - midend */
+ if(strstr(gl_info->gl_renderer, "GTX 260")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_GTX260;
+ vidmem = 1024;
+ }
+ /* Geforce9 - highend / Geforce 200 - midend (GTS 150/250 are based on the same core) */
+ else if(strstr(gl_info->gl_renderer, "9800") ||
+ strstr(gl_info->gl_renderer, "GTS 150") ||
+ strstr(gl_info->gl_renderer, "GTS 250"))
+ {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_9800GT;
+ vidmem = 512;
+ }
+ /* Geforce9 - midend */
+ else if(strstr(gl_info->gl_renderer, "9600")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_9600GT;
+ vidmem = 384; /* The 9600GSO has 384MB, the 9600GT has 512-1024MB */
+ }
+ /* Geforce9 - midend low / Geforce 200 - low*/
+ else if(strstr(gl_info->gl_renderer, "9500") ||
+ strstr(gl_info->gl_renderer, "GT 120") ||
+ strstr(gl_info->gl_renderer, "GT 130"))
+ {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_9500GT;
+ vidmem = 256; /* The 9500GT has 256-1024MB */
+ }
+ /* Geforce9 - lowend */
+ else if(strstr(gl_info->gl_renderer, "9400")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_9400GT;
+ vidmem = 256; /* The 9400GT has 256-1024MB */
+ }
+ /* Geforce9 - lowend low */
+ else if(strstr(gl_info->gl_renderer, "9100") ||
+ strstr(gl_info->gl_renderer, "9200") ||
+ strstr(gl_info->gl_renderer, "9300") ||
+ strstr(gl_info->gl_renderer, "G 100"))
+ {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_9200;
+ vidmem = 256; /* The 9100-9300 cards have 256MB */
+ }
/* Geforce8 - highend */
- if (strstr(gl_info->gl_renderer, "8800")) {
+ else if (strstr(gl_info->gl_renderer, "8800")) {
gl_info->gl_card = CARD_NVIDIA_GEFORCE_8800GTS;
vidmem = 320; /* The 8800GTS uses 320MB, a 8800GTX can have 768MB */
}
+ /* Geforce8 - midend mobile */
+ else if(strstr(gl_info->gl_renderer, "8600 M")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_8600MGT;
+ vidmem = 512;
+ }
/* Geforce8 - midend */
else if(strstr(gl_info->gl_renderer, "8600") ||
strstr(gl_info->gl_renderer, "8700"))
gl_info->gl_card = CARD_NVIDIA_GEFORCE_7800GT;
vidmem = 256; /* A 7800GT uses 256MB while highend 7900 cards can use 512MB */
}
- /* Geforce7 midend / Geforce6 highend */
- else if(strstr(gl_info->gl_renderer, "6800") ||
- strstr(gl_info->gl_renderer, "7600") ||
- strstr(gl_info->gl_renderer, "7700"))
+ /* Geforce7 midend */
+ else if(strstr(gl_info->gl_renderer, "7600") ||
+ strstr(gl_info->gl_renderer, "7700")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_7600;
+ vidmem = 256; /* The 7600 uses 256-512MB */
+ /* Geforce7 lower medium */
+ } else if(strstr(gl_info->gl_renderer, "7400")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_7400;
+ vidmem = 256; /* The 7400 uses 256-512MB */
+ }
+ /* Geforce7 lowend */
+ else if(strstr(gl_info->gl_renderer, "7300")) {
+ gl_info->gl_card = CARD_NVIDIA_GEFORCE_7300;
+ vidmem = 256; /* Mac Pros with this card have 256 MB */
+ }
+ /* Geforce6 highend */
+ else if(strstr(gl_info->gl_renderer, "6800"))
{
gl_info->gl_card = CARD_NVIDIA_GEFORCE_6800;
vidmem = 128; /* The 6800 uses 128-256MB, the 7600 uses 256-512MB */
break;
case VENDOR_ATI:
if(WINE_D3D9_CAPABLE(gl_info)) {
- /* Radeon R6xx HD2900 - highend */
- if (strstr(gl_info->gl_renderer, "HD 2900")) {
+ /* Radeon R6xx HD2900/HD3800 - highend */
+ if (strstr(gl_info->gl_renderer, "HD 2900") ||
+ strstr(gl_info->gl_renderer, "HD 3870") ||
+ strstr(gl_info->gl_renderer, "HD 3850"))
+ {
gl_info->gl_card = CARD_ATI_RADEON_HD2900;
- vidmem = 512; /* HD2900 uses 512-1024MB */
+ vidmem = 512; /* HD2900/HD3800 uses 256-1024MB */
}
- /* Radeon R6xx HD2600- midend */
- else if (strstr(gl_info->gl_renderer, "HD 2600")) {
+ /* Radeon R6xx HD2600/HD3600 - midend; HD3830 is China-only midend */
+ else if (strstr(gl_info->gl_renderer, "HD 2600") ||
+ strstr(gl_info->gl_renderer, "HD 3830") ||
+ strstr(gl_info->gl_renderer, "HD 3690") ||
+ strstr(gl_info->gl_renderer, "HD 3650"))
+ {
gl_info->gl_card = CARD_ATI_RADEON_HD2600;
- vidmem = 256; /* HD2600 uses 256-512MB */
+ vidmem = 256; /* HD2600/HD3600 uses 256-512MB */
}
- /* Radeon R6xx HD2300/HD2400 - lowend */
+ /* Radeon R6xx HD2300/HD2400/HD3400 - lowend */
else if (strstr(gl_info->gl_renderer, "HD 2300") ||
- strstr(gl_info->gl_renderer, "HD 2400"))
+ strstr(gl_info->gl_renderer, "HD 2400") ||
+ strstr(gl_info->gl_renderer, "HD 3470") ||
+ strstr(gl_info->gl_renderer, "HD 3450") ||
+ strstr(gl_info->gl_renderer, "HD 3430"))
{
gl_info->gl_card = CARD_ATI_RADEON_HD2300;
vidmem = 128; /* HD2300 uses at least 128MB, HD2400 uses 256MB */
}
+ /* Radeon R6xx/R7xx integrated */
+ else if (strstr(gl_info->gl_renderer, "HD 3100") ||
+ strstr(gl_info->gl_renderer, "HD 3200") ||
+ strstr(gl_info->gl_renderer, "HD 3300"))
+ {
+ gl_info->gl_card = CARD_ATI_RADEON_HD3200;
+ vidmem = 128; /* 128MB */
+ }
/* Radeon R5xx */
else if (strstr(gl_info->gl_renderer, "X1600") ||
strstr(gl_info->gl_renderer, "X1650") ||
gl_info->gl_card = CARD_ATI_RADEON_X700;
vidmem = 128; /* x700/x8*0 use 128-256MB, >=x1300 128-512MB */
}
+ /* Radeon Xpress Series - onboard, DX9b, Shader 2.0, 300-400MHz */
+ else if(strstr(gl_info->gl_renderer, "Radeon Xpress"))
+ {
+ gl_info->gl_card = CARD_ATI_RADEON_XPRESS_200M;
+ vidmem = 64; /* Shared RAM, BIOS configurable, 64-256M */
+ }
/* Radeon R3xx */
else {
gl_info->gl_card = CARD_ATI_RADEON_9500; /* Radeon 9500/9550/9600/9700/9800/X300/X550/X600 */
}
break;
case VENDOR_INTEL:
- if (strstr(gl_info->gl_renderer, "915GM")) {
+ if (strstr(gl_info->gl_renderer, "GMA 950") ||
+ strstr(gl_info->gl_renderer, "945GM")) {
+ /* MacOS calls the card GMA 950, but everywhere else the PCI ID is named 945GM */
+ gl_info->gl_card = CARD_INTEL_I945GM;
+ vidmem = 64;
+ } else if (strstr(gl_info->gl_renderer, "915GM")) {
gl_info->gl_card = CARD_INTEL_I915GM;
} else if (strstr(gl_info->gl_renderer, "915G")) {
gl_info->gl_card = CARD_INTEL_I915G;
else
gl_info->gl_card = CARD_NVIDIA_RIVA_128;
}
- TRACE("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
+ TRACE_(d3d_caps)("FOUND (fake) card: 0x%x (vendor id), 0x%x (device id)\n", gl_info->gl_vendor, gl_info->gl_card);
/* If we have an estimate use it, else default to 64MB; */
if(vidmem)
else
gl_info->vidmem = WINE_DEFAULT_VIDMEM;
- /* Load all the lookup tables
- TODO: It may be a good idea to make minLookup and maxLookup const and populate them in wined3d_private.h where they are declared */
- minLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_WRAP;
- maxLookup[WINELOOKUP_WARPPARAM] = WINED3DTADDRESS_MIRRORONCE;
-
- minLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_NONE;
- maxLookup[WINELOOKUP_MAGFILTER] = WINED3DTEXF_ANISOTROPIC;
-
-
+ /* Load all the lookup tables */
for (i = 0; i < MAX_LOOKUPS; i++) {
stateLookup[i] = HeapAlloc(GetProcessHeap(), 0, sizeof(*stateLookup[i]) * (1 + maxLookup[i] - minLookup[i]) );
}
stateLookup[WINELOOKUP_WARPPARAM][WINED3DTADDRESS_MIRRORONCE - minLookup[WINELOOKUP_WARPPARAM]] =
gl_info->supported[ATI_TEXTURE_MIRROR_ONCE] ? GL_MIRROR_CLAMP_TO_EDGE_ATI : GL_REPEAT;
- stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_NONE - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
- stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_POINT - minLookup[WINELOOKUP_MAGFILTER]] = GL_NEAREST;
- stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_LINEAR - minLookup[WINELOOKUP_MAGFILTER]] = GL_LINEAR;
- stateLookup[WINELOOKUP_MAGFILTER][WINED3DTEXF_ANISOTROPIC - minLookup[WINELOOKUP_MAGFILTER]] =
+ magLookup[WINED3DTEXF_NONE - WINED3DTEXF_NONE] = GL_NEAREST;
+ magLookup[WINED3DTEXF_POINT - WINED3DTEXF_NONE] = GL_NEAREST;
+ magLookup[WINED3DTEXF_LINEAR - WINED3DTEXF_NONE] = GL_LINEAR;
+ magLookup[WINED3DTEXF_ANISOTROPIC - WINED3DTEXF_NONE] =
gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR : GL_NEAREST;
- minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_NONE] = GL_LINEAR;
- minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_POINT] = GL_LINEAR;
- minMipLookup[WINED3DTEXF_NONE][WINED3DTEXF_LINEAR] = GL_LINEAR;
- minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_NONE] = GL_NEAREST;
- minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
- minMipLookup[WINED3DTEXF_POINT][WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
- minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_NONE] = GL_LINEAR;
- minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
- minMipLookup[WINED3DTEXF_LINEAR][WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
- minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_NONE] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ?
- GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
- minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_POINT] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
- minMipLookup[WINED3DTEXF_ANISOTROPIC][WINED3DTEXF_LINEAR] = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
+ minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_NONE] = GL_LINEAR;
+ minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_POINT] = GL_LINEAR;
+ minMipLookup[WINED3DTEXF_NONE].mip[WINED3DTEXF_LINEAR] = GL_LINEAR;
+ minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_NONE] = GL_NEAREST;
+ minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_POINT] = GL_NEAREST_MIPMAP_NEAREST;
+ minMipLookup[WINED3DTEXF_POINT].mip[WINED3DTEXF_LINEAR] = GL_NEAREST_MIPMAP_LINEAR;
+ minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_NONE] = GL_LINEAR;
+ minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_POINT] = GL_LINEAR_MIPMAP_NEAREST;
+ minMipLookup[WINED3DTEXF_LINEAR].mip[WINED3DTEXF_LINEAR] = GL_LINEAR_MIPMAP_LINEAR;
+ minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_NONE]
+ = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
+ minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_POINT]
+ = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR;
+ minMipLookup[WINED3DTEXF_ANISOTROPIC].mip[WINED3DTEXF_LINEAR]
+ = gl_info->supported[EXT_TEXTURE_FILTER_ANISOTROPIC] ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
/* TODO: config lookups */
/* Make sure there's an active HDC else the WGL extensions will fail */
hdc = pwglGetCurrentDC();
if (hdc) {
- WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
- TRACE_(d3d_caps)("WGL_Extensions reported:\n");
+ /* Not all GL drivers might offer WGL extensions e.g. VirtualBox */
+ if(GL_EXTCALL(wglGetExtensionsStringARB))
+ WGL_Extensions = GL_EXTCALL(wglGetExtensionsStringARB(hdc));
if (NULL == WGL_Extensions) {
ERR(" WGL_Extensions returns NULL\n");
} else {
+ TRACE_(d3d_caps)("WGL_Extensions reported:\n");
while (*WGL_Extensions != 0x00) {
const char *Start;
char ThisExtn[256];
gl_info->supported[WGL_ARB_PBUFFER] = TRUE;
TRACE_(d3d_caps)("FOUND: WGL_ARB_pbuffer support\n");
}
+ if (!strcmp(ThisExtn, "WGL_ARB_pixel_format")) {
+ gl_info->supported[WGL_ARB_PIXEL_FORMAT] = TRUE;
+ TRACE_(d3d_caps)("FOUND: WGL_ARB_pixel_format support\n");
+ }
+ if (!strcmp(ThisExtn, "WGL_WINE_pixel_format_passthrough")) {
+ gl_info->supported[WGL_WINE_PIXEL_FORMAT_PASSTHROUGH] = TRUE;
+ TRACE_(d3d_caps)("FOUND: WGL_WINE_pixel_format_passthrough support\n");
+ }
}
}
}
return return_value;
}
-#undef GLINFO_LOCATION
/**********************************************************
* IWineD3D implementation follows
static UINT WINAPI IWineD3DImpl_GetAdapterCount (IWineD3D *iface) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- TRACE_(d3d_caps)("(%p): Reporting %d adapters\n", This, numAdapters);
- return numAdapters;
+ TRACE_(d3d_caps)("(%p): Reporting %u adapters\n", This, This->adapter_count);
+
+ return This->adapter_count;
}
static HRESULT WINAPI IWineD3DImpl_RegisterSoftwareDevice(IWineD3D *iface, void* pInitializeFunction) {
static HMONITOR WINAPI IWineD3DImpl_GetAdapterMonitor(IWineD3D *iface, UINT Adapter) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
+ TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
+
if (Adapter >= IWineD3DImpl_GetAdapterCount(iface)) {
return NULL;
}
- TRACE_(d3d_caps)("(%p)->(%d)\n", This, Adapter);
- return MonitorFromPoint(Adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
+ return MonitorFromPoint(This->adapters[Adapter].monitorPoint, MONITOR_DEFAULTTOPRIMARY);
}
/* FIXME: GetAdapterModeCount and EnumAdapterModes currently only returns modes
if (Adapter == 0 && !DEBUG_SINGLE_MODE) { /* Display */
DEVMODEW DevModeW;
int ModeIdx = 0;
- int i = 0;
+ UINT i = 0;
int j = 0;
ZeroMemory(&DevModeW, sizeof(DevModeW));
if (DevModeW.dmFields & DM_DISPLAYFREQUENCY)
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
- if (Format == WINED3DFMT_UNKNOWN)
- {
- switch (DevModeW.dmBitsPerPel)
- {
- case 8:
- pMode->Format = WINED3DFMT_P8;
- break;
- case 16:
- pMode->Format = WINED3DFMT_R5G6B5;
- break;
- case 32:
- pMode->Format = WINED3DFMT_X8R8G8B8;
- break;
- default:
- pMode->Format = WINED3DFMT_UNKNOWN;
- ERR("Unhandled bit depth (%u) in mode list!\n", DevModeW.dmBitsPerPel);
- }
+ if (Format == WINED3DFMT_UNKNOWN) {
+ pMode->Format = pixelformat_for_depth(DevModeW.dmBitsPerPel);
} else {
pMode->Format = Format;
}
pMode->RefreshRate = DevModeW.dmDisplayFrequency;
}
- switch (bpp) {
- case 8: pMode->Format = WINED3DFMT_R3G3B2; break;
- case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
- case 24: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* Robots needs 24bit to be X8R8G8B8 */
- case 32: pMode->Format = WINED3DFMT_X8R8G8B8; break; /* EVE online and the Fur demo need 32bit AdapterDisplatMode to return X8R8G8B8 */
- default: pMode->Format = WINED3DFMT_UNKNOWN;
- }
-
+ pMode->Format = pixelformat_for_depth(bpp);
} else {
FIXME_(d3d_caps)("Adapter not primary display\n");
}
/* Return the information requested */
TRACE_(d3d_caps)("device/Vendor Name and Version detection using FillGLCaps\n");
- strcpy(pIdentifier->Driver, Adapters[Adapter].driver);
- strcpy(pIdentifier->Description, Adapters[Adapter].description);
+ strcpy(pIdentifier->Driver, This->adapters[Adapter].driver);
+ if(This->adapters[Adapter].gl_info.driver_description)
+ strcpy(pIdentifier->Description, This->adapters[Adapter].gl_info.driver_description);
+ else /* Copy default description "Direct3D HAL" */
+ strcpy(pIdentifier->Description, This->adapters[Adapter].description);
/* Note dx8 doesn't supply a DeviceName */
if (NULL != pIdentifier->DeviceName) strcpy(pIdentifier->DeviceName, "\\\\.\\DISPLAY"); /* FIXME: May depend on desktop? */
- /* Current Windows drivers have versions like 6.14.... (some older have an earlier version) */
- pIdentifier->DriverVersion->u.HighPart = MAKEDWORD_VERSION(6, 14);
- pIdentifier->DriverVersion->u.LowPart = Adapters[Adapter].gl_info.gl_driver_version;
- *(pIdentifier->VendorId) = Adapters[Adapter].gl_info.gl_vendor;
- *(pIdentifier->DeviceId) = Adapters[Adapter].gl_info.gl_card;
+ pIdentifier->DriverVersion->u.HighPart = This->adapters[Adapter].gl_info.driver_version_hipart;
+ pIdentifier->DriverVersion->u.LowPart = This->adapters[Adapter].gl_info.driver_version;
+ *(pIdentifier->VendorId) = This->adapters[Adapter].gl_info.gl_vendor;
+ *(pIdentifier->DeviceId) = This->adapters[Adapter].gl_info.gl_card;
*(pIdentifier->SubSysId) = 0;
*(pIdentifier->Revision) = 0;
+ *pIdentifier->DeviceIdentifier = IID_D3DDEVICE_D3DUID;
+
+ if(wined3d_settings.pci_device_id != PCI_DEVICE_NONE)
+ {
+ TRACE_(d3d_caps)("Overriding pci device id with: %x\n", wined3d_settings.pci_device_id);
+ *(pIdentifier->DeviceId) = wined3d_settings.pci_device_id;
+ }
+
+ if(wined3d_settings.pci_vendor_id != PCI_VENDOR_NONE)
+ {
+ TRACE_(d3d_caps)("Overriding pci vendor id with: %x\n", wined3d_settings.pci_vendor_id);
+ *(pIdentifier->VendorId) = wined3d_settings.pci_vendor_id;
+ }
- /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
if (Flags & WINED3DENUM_NO_WHQL_LEVEL) {
*(pIdentifier->WHQLLevel) = 0;
} else {
return WINED3D_OK;
}
-static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
+static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(const WineD3D_GL_Info *gl_info,
+ const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
+{
short redSize, greenSize, blueSize, alphaSize, colorBits;
if(!cfg)
return FALSE;
- if(!getColorBits(Format, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits)) {
- ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
- return FALSE;
- }
+ if(cfg->iPixelType == WGL_TYPE_RGBA_ARB) { /* Integer RGBA formats */
+ if (!getColorBits(format_desc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
+ {
+ ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
+ return FALSE;
+ }
- if(cfg->redSize < redSize)
- return FALSE;
+ if(cfg->redSize < redSize)
+ return FALSE;
- if(cfg->greenSize < greenSize)
- return FALSE;
+ if(cfg->greenSize < greenSize)
+ return FALSE;
- if(cfg->blueSize < blueSize)
- return FALSE;
+ if(cfg->blueSize < blueSize)
+ return FALSE;
- if(cfg->alphaSize < alphaSize)
+ if(cfg->alphaSize < alphaSize)
+ return FALSE;
+
+ return TRUE;
+ } else if(cfg->iPixelType == WGL_TYPE_RGBA_FLOAT_ARB) { /* Float RGBA formats; TODO: WGL_NV_float_buffer */
+ if (format_desc->format == WINED3DFMT_R16_FLOAT)
+ return (cfg->redSize == 16 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
+ if (format_desc->format == WINED3DFMT_R16G16_FLOAT)
+ return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 0 && cfg->alphaSize == 0);
+ if (format_desc->format == WINED3DFMT_R16G16B16A16_FLOAT)
+ return (cfg->redSize == 16 && cfg->greenSize == 16 && cfg->blueSize == 16 && cfg->alphaSize == 16);
+ if (format_desc->format == WINED3DFMT_R32_FLOAT)
+ return (cfg->redSize == 32 && cfg->greenSize == 0 && cfg->blueSize == 0 && cfg->alphaSize == 0);
+ if (format_desc->format == WINED3DFMT_R32G32_FLOAT)
+ return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 0 && cfg->alphaSize == 0);
+ if (format_desc->format == WINED3DFMT_R32G32B32A32_FLOAT)
+ return (cfg->redSize == 32 && cfg->greenSize == 32 && cfg->blueSize == 32 && cfg->alphaSize == 32);
+ } else {
+ /* Probably a color index mode */
return FALSE;
+ }
- return TRUE;
+ return FALSE;
}
-static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_PixelFormat *cfg, WINED3DFORMAT Format) {
+static BOOL IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(const WineD3D_GL_Info *gl_info,
+ const WineD3D_PixelFormat *cfg, const struct GlPixelFormatDesc *format_desc)
+{
short depthSize, stencilSize;
+ BOOL lockable = FALSE;
if(!cfg)
return FALSE;
- if(!getDepthStencilBits(Format, &depthSize, &stencilSize)) {
- ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(Format));
+ if (!getDepthStencilBits(format_desc, &depthSize, &stencilSize))
+ {
+ ERR("Unable to check compatibility for Format=%s\n", debug_d3dformat(format_desc->format));
return FALSE;
}
- if(cfg->depthSize < depthSize)
+ if ((format_desc->format == WINED3DFMT_D16_LOCKABLE) || (format_desc->format == WINED3DFMT_D32F_LOCKABLE))
+ lockable = TRUE;
+
+ /* On some modern cards like the Geforce8/9 GLX doesn't offer some dephthstencil formats which D3D9 reports.
+ * We can safely report 'compatible' formats (e.g. D24 can be used for D16) as long as we aren't dealing with
+ * a lockable format. This also helps D3D <= 7 as they expect D16 which isn't offered without this on Geforce8 cards. */
+ if(!(cfg->depthSize == depthSize || (!lockable && cfg->depthSize > depthSize)))
return FALSE;
+ /* Some cards like Intel i915 ones only offer D24S8 but lots of games also need a format without stencil, so
+ * allow more stencil bits than requested. */
if(cfg->stencilSize < stencilSize)
return FALSE;
WINED3DFORMAT DepthStencilFormat) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
int nCfgs;
- WineD3D_PixelFormat *cfgs;
+ const WineD3D_PixelFormat *cfgs;
+ const struct WineD3DAdapter *adapter;
+ const struct GlPixelFormatDesc *rt_format_desc;
+ const struct GlPixelFormatDesc *ds_format_desc;
int it;
WARN_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n",
return WINED3DERR_INVALIDCALL;
}
- cfgs = Adapters[Adapter].cfgs;
- nCfgs = Adapters[Adapter].nCfgs;
+ adapter = &This->adapters[Adapter];
+ rt_format_desc = getFormatDescEntry(RenderTargetFormat, &adapter->gl_info);
+ ds_format_desc = getFormatDescEntry(DepthStencilFormat, &adapter->gl_info);
+ cfgs = adapter->cfgs;
+ nCfgs = adapter->nCfgs;
for (it = 0; it < nCfgs; ++it) {
- if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], RenderTargetFormat)) {
- if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&cfgs[it], DepthStencilFormat)) {
+ if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, &cfgs[it], rt_format_desc))
+ {
+ if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[it], ds_format_desc))
+ {
TRACE_(d3d_caps)("(%p) : Formats matched\n", This);
return WINED3D_OK;
}
BOOL Windowed, WINED3DMULTISAMPLE_TYPE MultiSampleType, DWORD* pQualityLevels) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
+ const struct GlPixelFormatDesc *glDesc;
+ const struct WineD3DAdapter *adapter;
+
+ TRACE_(d3d_caps)("(%p)-> (Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x, pQual:%p)\n",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
return WINED3DERR_INVALIDCALL;
}
- /* TODO: Store in Adapter structure */
- if (pQualityLevels != NULL) {
- static int s_single_shot = 0;
- if (!s_single_shot) {
- FIXME("Quality levels unsupported at present\n");
- s_single_shot = 1;
+ /* TODO: handle Windowed, add more quality levels */
+
+ if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
+
+ /* By default multisampling is disabled right now as it causes issues
+ * on some Nvidia driver versions and it doesn't work well in combination
+ * with FBOs yet. */
+ if(!wined3d_settings.allow_multisampling)
+ return WINED3DERR_NOTAVAILABLE;
+
+ adapter = &This->adapters[Adapter];
+ glDesc = getFormatDescEntry(SurfaceFormat, &adapter->gl_info);
+ if (!glDesc) return WINED3DERR_INVALIDCALL;
+
+ if(glDesc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)) {
+ int i, nCfgs;
+ const WineD3D_PixelFormat *cfgs;
+
+ cfgs = adapter->cfgs;
+ nCfgs = adapter->nCfgs;
+ for(i=0; i<nCfgs; i++) {
+ if(cfgs[i].numSamples != MultiSampleType)
+ continue;
+
+ if (!IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, &cfgs[i], glDesc))
+ continue;
+
+ TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
+
+ if(pQualityLevels)
+ *pQualityLevels = 1; /* Guess at a value! */
+ return WINED3D_OK;
}
- *pQualityLevels = 1; /* Guess at a value! */
}
+ else if(glDesc->Flags & WINED3DFMT_FLAG_RENDERTARGET) {
+ short redSize, greenSize, blueSize, alphaSize, colorBits;
+ int i, nCfgs;
+ const WineD3D_PixelFormat *cfgs;
- if (WINED3DMULTISAMPLE_NONE == MultiSampleType) return WINED3D_OK;
+ if (!getColorBits(glDesc, &redSize, &greenSize, &blueSize, &alphaSize, &colorBits))
+ {
+ ERR("Unable to color bits for format %#x, can't check multisampling capability!\n", SurfaceFormat);
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ cfgs = adapter->cfgs;
+ nCfgs = adapter->nCfgs;
+ for(i=0; i<nCfgs; i++) {
+ if(cfgs[i].numSamples != MultiSampleType)
+ continue;
+ if(cfgs[i].redSize != redSize)
+ continue;
+ if(cfgs[i].greenSize != greenSize)
+ continue;
+ if(cfgs[i].blueSize != blueSize)
+ continue;
+ if(cfgs[i].alphaSize != alphaSize)
+ continue;
+
+ TRACE("Found iPixelFormat=%d to support MultiSampleType=%d for format %s\n", cfgs[i].iPixelFormat, MultiSampleType, debug_d3dformat(SurfaceFormat));
+
+ if(pQualityLevels)
+ *pQualityLevels = 1; /* Guess at a value! */
+ return WINED3D_OK;
+ }
+ }
return WINED3DERR_NOTAVAILABLE;
}
-static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE CheckType,
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
WINED3DFORMAT DisplayFormat, WINED3DFORMAT BackBufferFormat, BOOL Windowed) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- int nCfgs = 0;
- WineD3D_PixelFormat *cfgs;
- int it;
HRESULT hr = WINED3DERR_NOTAVAILABLE;
+ UINT nmodes;
TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n",
This,
Adapter,
- CheckType, debug_d3ddevicetype(CheckType),
+ DeviceType, debug_d3ddevicetype(DeviceType),
DisplayFormat, debug_d3dformat(DisplayFormat),
BackBufferFormat, debug_d3dformat(BackBufferFormat),
Windowed);
return WINED3DERR_INVALIDCALL;
}
- cfgs = Adapters[Adapter].cfgs;
- nCfgs = Adapters[Adapter].nCfgs;
- for (it = 0; it < nCfgs; ++it) {
- if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&cfgs[it], DisplayFormat)) {
- hr = WINED3D_OK;
- TRACE_(d3d_caps)("OK\n");
- break ;
- }
+ /* The task of this function is to check whether a certain display / backbuffer format
+ * combination is available on the given adapter. In fullscreen mode microsoft specified
+ * that the display format shouldn't provide alpha and that ignoring alpha the backbuffer
+ * and display format should match exactly.
+ * In windowed mode format conversion can occur and this depends on the driver. When format
+ * conversion is done, this function should nevertheless fail and applications need to use
+ * CheckDeviceFormatConversion.
+ * At the moment we assume that fullscreen and windowed have the same capabilities */
+
+ /* There are only 4 display formats */
+ if(!((DisplayFormat == WINED3DFMT_R5G6B5) ||
+ (DisplayFormat == WINED3DFMT_X1R5G5B5) ||
+ (DisplayFormat == WINED3DFMT_X8R8G8B8) ||
+ (DisplayFormat == WINED3DFMT_A2R10G10B10)))
+ {
+ TRACE_(d3d_caps)("Format %s unsupported as display format\n", debug_d3dformat(DisplayFormat));
+ return WINED3DERR_NOTAVAILABLE;
}
- if(hr != WINED3D_OK)
- ERR("unsupported format %s\n", debug_d3dformat(DisplayFormat));
-
- if(hr != WINED3D_OK)
- TRACE_(d3d_caps)("returning something different from WINED3D_OK\n");
+ /* If the requested DisplayFormat is not available, don't continue */
+ nmodes = IWineD3DImpl_GetAdapterModeCount(iface, Adapter, DisplayFormat);
+ if(!nmodes) {
+ TRACE_(d3d_caps)("No available modes for display format %s\n", debug_d3dformat(DisplayFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
- return hr;
-}
+ /* Windowed mode allows you to specify WINED3DFMT_UNKNOWN for the backbufferformat, it means 'reuse' the display format for the backbuffer */
+ if(!Windowed && BackBufferFormat == WINED3DFMT_UNKNOWN) {
+ TRACE_(d3d_caps)("BackBufferFormat WINED3FMT_UNKNOWN not available in Windowed mode\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
-#define GLINFO_LOCATION Adapters[Adapter].gl_info
-static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
- WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
- IWineD3DImpl *This = (IWineD3DImpl *)iface;
- TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
- This,
- Adapter,
- DeviceType, debug_d3ddevicetype(DeviceType),
- AdapterFormat, debug_d3dformat(AdapterFormat),
- Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
- RType, debug_d3dresourcetype(RType),
- CheckFormat, debug_d3dformat(CheckFormat));
+ /* In FULLSCREEN mode R5G6B5 can only be mixed with backbuffer format R5G6B5 */
+ if( (DisplayFormat == WINED3DFMT_R5G6B5) && (BackBufferFormat != WINED3DFMT_R5G6B5) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
+ }
- if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
- return WINED3DERR_INVALIDCALL;
+ /* In FULLSCREEN mode X1R5G5B5 can only be mixed with backbuffer format *1R5G5B5 */
+ if( (DisplayFormat == WINED3DFMT_X1R5G5B5) && !((BackBufferFormat == WINED3DFMT_X1R5G5B5) || (BackBufferFormat == WINED3DFMT_A1R5G5B5)) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
}
- if (Usage & WINED3DUSAGE_QUERY_FILTER) {
- switch (CheckFormat) {
- /* Filtering not supported */
- case WINED3DFMT_R32F:
- case WINED3DFMT_A32B32G32R32F:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- default:
- break;
- }
+ /* In FULLSCREEN mode X8R8G8B8 can only be mixed with backbuffer format *8R8G8B8 */
+ if( (DisplayFormat == WINED3DFMT_X8R8G8B8) && !((BackBufferFormat == WINED3DFMT_X8R8G8B8) || (BackBufferFormat == WINED3DFMT_A8R8G8B8)) ) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
}
- if (Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
- if(!GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
- TRACE_(d3d_caps)("[FAILED] - No mipmap generation support\n");
- return WINED3DERR_NOTAVAILABLE;
- }
+ /* A2R10G10B10 is only allowed in fullscreen mode and it can only be mixed with backbuffer format A2R10G10B10 */
+ if( (DisplayFormat == WINED3DFMT_A2R10G10B10) && ((BackBufferFormat != WINED3DFMT_A2R10G10B10) || Windowed)) {
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
+ return WINED3DERR_NOTAVAILABLE;
}
- if(RType == WINED3DRTYPE_VOLUMETEXTURE) {
- if(!GL_SUPPORT(EXT_TEXTURE3D)) {
- TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- /* Filter formats that need conversion; For one part, this conversion is unimplemented,
- * and volume textures are huge, so it would be a big performance hit. Unless we hit an
- * app needing one of those formats, don't advertize them to avoid leading apps into
- * temptation. The windows drivers don't support most of those formats on volumes anyway,
- * except of R32F.
- */
- switch(CheckFormat) {
- case WINED3DFMT_P8:
- case WINED3DFMT_A4L4:
- case WINED3DFMT_R32F:
- case WINED3DFMT_R16F:
- case WINED3DFMT_X8L8V8U8:
- case WINED3DFMT_L6V5U5:
- TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
- return WINED3DERR_NOTAVAILABLE;
+ /* Use CheckDeviceFormat to see if the BackBufferFormat is usable with the given DisplayFormat */
+ hr = IWineD3DImpl_CheckDeviceFormat(iface, Adapter, DeviceType, DisplayFormat, WINED3DUSAGE_RENDERTARGET, WINED3DRTYPE_SURFACE, BackBufferFormat, SURFACE_OPENGL);
+ if(FAILED(hr))
+ TRACE_(d3d_caps)("Unsupported display/backbuffer format combination %s/%s\n", debug_d3dformat(DisplayFormat), debug_d3dformat(BackBufferFormat));
- case WINED3DFMT_Q8W8V8U8:
- case WINED3DFMT_V16U16:
- if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
- TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- break;
+ return hr;
+}
- case WINED3DFMT_V8U8:
- if(!GL_SUPPORT(NV_TEXTURE_SHADER) || !GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
- TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- break;
- case WINED3DFMT_DXT1:
- case WINED3DFMT_DXT2:
- case WINED3DFMT_DXT3:
- case WINED3DFMT_DXT4:
- case WINED3DFMT_DXT5:
- /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
- * compressed texture results in an error. While the D3D refrast does
- * support s3tc volumes, at least the nvidia windows driver does not, so
- * we're free not to support this format.
- */
- TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
- return WINED3DERR_NOTAVAILABLE;
+/* Check if we support bumpmapping for a format */
+static BOOL CheckBumpMapCapability(struct WineD3DAdapter *adapter,
+ WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
+{
+ const struct fragment_pipeline *fp;
- default:
- /* Do nothing, continue with checking the format below */
- break;
- }
- }
- /* TODO: Check support against more of the WINED3DUSAGE_QUERY_* constants
- * See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/IDirect3D9__CheckDeviceFormat.asp
- * and http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/D3DUSAGE_QUERY.asp */
- if (Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
- if (!GL_LIMITS(vertex_samplers)) {
+ switch(format_desc->format)
+ {
+ case WINED3DFMT_R8G8_SNORM:
+ case WINED3DFMT_R16G16_SNORM:
+ case WINED3DFMT_L6V5U5:
+ case WINED3DFMT_X8L8V8U8:
+ case WINED3DFMT_R8G8B8A8_SNORM:
+ /* Ask the fixed function pipeline implementation if it can deal
+ * with the conversion. If we've got a GL extension giving native
+ * support this will be an identity conversion. */
+ fp = select_fragment_implementation(adapter, DeviceType);
+ if (fp->color_fixup_supported(format_desc->color_fixup))
+ {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
+ return FALSE;
- switch (CheckFormat) {
- case WINED3DFMT_A32B32G32R32F:
- if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+ default:
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+ }
+}
- default:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
+static BOOL CheckDepthStencilCapability(struct WineD3DAdapter *adapter,
+ const struct GlPixelFormatDesc *display_format_desc, const struct GlPixelFormatDesc *ds_format_desc)
+{
+ int it=0;
+
+ /* Only allow depth/stencil formats */
+ if (!(ds_format_desc->Flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))) return FALSE;
+
+ /* Walk through all WGL pixel formats to find a match */
+ for (it = 0; it < adapter->nCfgs; ++it)
+ {
+ WineD3D_PixelFormat *cfg = &adapter->cfgs[it];
+ if (IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info, cfg, display_format_desc))
+ {
+ if (IWineD3DImpl_IsPixelFormatCompatibleWithDepthFmt(&adapter->gl_info, cfg, ds_format_desc))
+ {
+ return TRUE;
+ }
}
}
- if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
- switch (CheckFormat) {
- /* In theory we could do all formats, just fetch them accordingly should the buffer be locked.
- * Windows supports only those 3, and enumerating the other formats confuses applications
- */
- case WINED3DFMT_D24S8:
- case WINED3DFMT_D24X8:
- case WINED3DFMT_D16:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- case WINED3DFMT_D16_LOCKABLE:
- case WINED3DFMT_D24FS8:
- case WINED3DFMT_D32F_LOCKABLE:
- case WINED3DFMT_D24X4S4:
- case WINED3DFMT_D15S1:
- case WINED3DFMT_D32:
- TRACE_(d3d_caps)("[FAILED]. Disabled because not enumerated on windows\n");
- return WINED3DERR_NOTAVAILABLE;
- default:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- } else if(Usage & WINED3DUSAGE_RENDERTARGET) {
- switch (CheckFormat) {
- case WINED3DFMT_R8G8B8:
- case WINED3DFMT_A8R8G8B8:
- case WINED3DFMT_X8R8G8B8:
- case WINED3DFMT_R5G6B5:
- case WINED3DFMT_X1R5G5B5:
- case WINED3DFMT_A1R5G5B5:
- case WINED3DFMT_A4R4G4B4:
- case WINED3DFMT_R3G3B2:
- case WINED3DFMT_X4R4G4B4:
- case WINED3DFMT_A8B8G8R8:
- case WINED3DFMT_X8B8G8R8:
- case WINED3DFMT_P8:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- case WINED3DFMT_R16F:
- case WINED3DFMT_A16B16G16R16F:
- if (!GL_SUPPORT(ARB_HALF_FLOAT_PIXEL) || !GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- case WINED3DFMT_A32B32G32R32F:
- if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- default:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+ return FALSE;
+}
+
+static BOOL CheckFilterCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
+{
+ /* The flags entry of a format contains the filtering capability */
+ if (format_desc->Flags & WINED3DFMT_FLAG_FILTERING) return TRUE;
+
+ return FALSE;
+}
+
+/* Check the render target capabilities of a format */
+static BOOL CheckRenderTargetCapability(struct WineD3DAdapter *adapter,
+ const struct GlPixelFormatDesc *adapter_format_desc, const struct GlPixelFormatDesc *check_format_desc)
+{
+ /* Filter out non-RT formats */
+ if (!(check_format_desc->Flags & WINED3DFMT_FLAG_RENDERTARGET)) return FALSE;
+
+ if(wined3d_settings.offscreen_rendering_mode == ORM_BACKBUFFER) {
+ WineD3D_PixelFormat *cfgs = adapter->cfgs;
+ int it;
+ short AdapterRed, AdapterGreen, AdapterBlue, AdapterAlpha, AdapterTotalSize;
+ short CheckRed, CheckGreen, CheckBlue, CheckAlpha, CheckTotalSize;
+
+ getColorBits(adapter_format_desc, &AdapterRed, &AdapterGreen, &AdapterBlue, &AdapterAlpha, &AdapterTotalSize);
+ getColorBits(check_format_desc, &CheckRed, &CheckGreen, &CheckBlue, &CheckAlpha, &CheckTotalSize);
+
+ /* In backbuffer mode the front and backbuffer share the same WGL pixelformat.
+ * The format must match in RGB, alpha is allowed to be different. (Only the backbuffer can have alpha) */
+ if(!((AdapterRed == CheckRed) && (AdapterGreen == CheckGreen) && (AdapterBlue == CheckBlue))) {
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
}
- } else if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
- if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
- switch (CheckFormat) {
- case WINED3DFMT_V8U8:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- /* TODO: Other bump map formats */
- default:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+
+ /* Check if there is a WGL pixel format matching the requirements, the format should also be window
+ * drawable (not offscreen; e.g. Nvidia offers R5G6B5 for pbuffers even when X is running at 24bit) */
+ for (it = 0; it < adapter->nCfgs; ++it)
+ {
+ if (cfgs[it].windowDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
+ &cfgs[it], check_format_desc))
+ {
+ TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
+ cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
+ return TRUE;
}
}
- if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
- switch (CheckFormat) {
- case WINED3DFMT_V8U8:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- default:
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+ } else if(wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER) {
+ /* We can probably use this function in FBO mode too on some drivers to get some basic indication of the capabilities. */
+ WineD3D_PixelFormat *cfgs = adapter->cfgs;
+ int it;
+
+ /* Check if there is a WGL pixel format matching the requirements, the pixel format should also be usable with pbuffers */
+ for (it = 0; it < adapter->nCfgs; ++it)
+ {
+ if (cfgs[it].pbufferDrawable && IWineD3DImpl_IsPixelFormatCompatibleWithRenderFmt(&adapter->gl_info,
+ &cfgs[it], check_format_desc))
+ {
+ TRACE_(d3d_caps)("iPixelFormat=%d is compatible with CheckFormat=%s\n",
+ cfgs[it].iPixelFormat, debug_d3dformat(check_format_desc->format));
+ return TRUE;
}
}
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+ } else if(wined3d_settings.offscreen_rendering_mode == ORM_FBO){
+ /* For now return TRUE for FBOs until we have some proper checks.
+ * Note that this function will only be called when the format is around for texturing. */
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL CheckSrgbReadCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
+{
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+
+ /* Check for supported sRGB formats (Texture loading and framebuffer) */
+ if(!GL_SUPPORT(EXT_TEXTURE_SRGB)) {
+ TRACE_(d3d_caps)("[FAILED] GL_EXT_texture_sRGB not supported\n");
+ return FALSE;
}
- if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
- switch (CheckFormat) {
+ switch (format_desc->format)
+ {
+ case WINED3DFMT_A8R8G8B8:
+ case WINED3DFMT_X8R8G8B8:
+ case WINED3DFMT_A4R4G4B4:
+ case WINED3DFMT_L8:
+ case WINED3DFMT_A8L8:
case WINED3DFMT_DXT1:
case WINED3DFMT_DXT2:
case WINED3DFMT_DXT3:
case WINED3DFMT_DXT4:
case WINED3DFMT_DXT5:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+
default:
- break; /* Avoid compiler warnings */
- }
+ TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(format_desc->format));
+ return FALSE;
}
+ return FALSE;
+}
- /* Check for supported sRGB formats (Texture loading and framebuffer) */
- if (GL_SUPPORT(EXT_TEXTURE_SRGB) && (Usage & WINED3DUSAGE_QUERY_SRGBREAD)) {
- switch (CheckFormat) {
- case WINED3DFMT_A8R8G8B8:
- case WINED3DFMT_X8R8G8B8:
- case WINED3DFMT_A4R4G4B4:
- case WINED3DFMT_L8:
- case WINED3DFMT_A8L8:
- case WINED3DFMT_DXT1:
- case WINED3DFMT_DXT2:
- case WINED3DFMT_DXT3:
- case WINED3DFMT_DXT4:
- case WINED3DFMT_DXT5:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+static BOOL CheckSrgbWriteCapability(struct WineD3DAdapter *adapter,
+ WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
+{
+ /* Only offer SRGB writing on X8R8G8B8/A8R8G8B8 when we use ARB or GLSL shaders as we are
+ * doing the color fixup in shaders.
+ * Note Windows drivers (at least on the Geforce 8800) also offer this on R5G6B5. */
+ if ((format_desc->format == WINED3DFMT_X8R8G8B8) || (format_desc->format == WINED3DFMT_A8R8G8B8))
+ {
+ int vs_selected_mode;
+ int ps_selected_mode;
+ select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
- default:
- TRACE_(d3d_caps)("[FAILED] Gamma texture format %s not supported.\n", debug_d3dformat(CheckFormat));
- return WINED3DERR_NOTAVAILABLE;
+ if((ps_selected_mode == SHADER_ARB) || (ps_selected_mode == SHADER_GLSL)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
}
}
- if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
+ TRACE_(d3d_caps)("[FAILED] - no SRGB writing support on format=%s\n", debug_d3dformat(format_desc->format));
+ return FALSE;
+}
- BOOL half_pixel_support = GL_SUPPORT(ARB_HALF_FLOAT_PIXEL);
+/* Check if a format support blending in combination with pixel shaders */
+static BOOL CheckPostPixelShaderBlendingCapability(struct WineD3DAdapter *adapter,
+ const struct GlPixelFormatDesc *format_desc)
+{
+ /* The flags entry of a format contains the post pixel shader blending capability */
+ if (format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING) return TRUE;
- switch (CheckFormat) {
- case WINED3DFMT_R16F:
- case WINED3DFMT_A16B16G16R16F:
- if (!half_pixel_support) break;
- case WINED3DFMT_R32F:
- case WINED3DFMT_A32B32G32R32F:
- TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- default:
- break; /* Avoid compiler warnings */
- }
- }
+ return FALSE;
+}
- /* This format is nothing special and it is supported perfectly.
- * However, ati and nvidia driver on windows do not mark this format as
- * supported (tested with the dxCapsViewer) and pretending to
- * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
- * So do the same as Windows drivers and pretend not to support it on dx8 and 9
- * Enable it on dx7. It will need additional checking on dx10 when we support it.
+static BOOL CheckWrapAndMipCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
+{
+ /* OpenGL supports mipmapping on all formats basically. Wrapping is unsupported,
+ * but we have to report mipmapping so we cannot reject this flag. Tests show that
+ * windows reports WRAPANDMIP on unfilterable surfaces as well, apparently to show
+ * that wrapping is supported. The lack of filtering will sort out the mipmapping
+ * capability anyway.
+ *
+ * For now lets report this on all formats, but in the future we may want to
+ * restrict it to some should games need that
*/
- if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
- }
+ return TRUE;
+}
- switch (CheckFormat) {
+/* Check if a texture format is supported on the given adapter */
+static BOOL CheckTextureCapability(struct WineD3DAdapter *adapter,
+ WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *format_desc)
+{
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+ const shader_backend_t *shader_backend;
+ const struct fragment_pipeline *fp;
+ switch (format_desc->format)
+ {
/*****
* supported: RGB(A) formats
*/
case WINED3DFMT_X1R5G5B5:
case WINED3DFMT_A1R5G5B5:
case WINED3DFMT_A4R4G4B4:
- case WINED3DFMT_R3G3B2:
- case WINED3DFMT_A8:
+ case WINED3DFMT_A8_UNORM:
case WINED3DFMT_X4R4G4B4:
- case WINED3DFMT_A8B8G8R8:
+ case WINED3DFMT_R8G8B8A8_UNORM:
case WINED3DFMT_X8B8G8R8:
case WINED3DFMT_A2R10G10B10:
- case WINED3DFMT_A2B10G10R10:
+ case WINED3DFMT_R10G10B10A2_UNORM:
+ case WINED3DFMT_R16G16_UNORM:
TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+ return TRUE;
+
+ case WINED3DFMT_R3G3B2:
+ TRACE_(d3d_caps)("[FAILED] - Not supported on Windows\n");
+ return FALSE;
/*****
* supported: Palettized
*/
case WINED3DFMT_P8:
TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+ return TRUE;
+ /* No Windows driver offers A8P8, so don't offer it either */
+ case WINED3DFMT_A8P8:
+ return FALSE;
/*****
* Supported: (Alpha)-Luminance
*/
case WINED3DFMT_L8:
case WINED3DFMT_A8L8:
- case WINED3DFMT_A4L4:
+ case WINED3DFMT_L16:
TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
+ return TRUE;
+
+ /* Not supported on Windows, thus disabled */
+ case WINED3DFMT_A4L4:
+ TRACE_(d3d_caps)("[FAILED] - not supported on windows\n");
+ return FALSE;
+
+ /*****
+ * Supported: Depth/Stencil formats
+ */
+ case WINED3DFMT_D16_LOCKABLE:
+ case WINED3DFMT_D16_UNORM:
+ case WINED3DFMT_D15S1:
+ case WINED3DFMT_D24X8:
+ case WINED3DFMT_D24X4S4:
+ case WINED3DFMT_D24S8:
+ case WINED3DFMT_D24FS8:
+ case WINED3DFMT_D32:
+ case WINED3DFMT_D32F_LOCKABLE:
+ return TRUE;
/*****
* Not supported everywhere(depends on GL_ATI_envmap_bumpmap or
- * GL_NV_texture_shader), but advertized to make apps happy.
- * Enable some because games often fail when they are not available
- * and are still playable even without bump mapping
+ * GL_NV_texture_shader). Emulated by shaders
*/
- case WINED3DFMT_V8U8:
- case WINED3DFMT_V16U16:
- case WINED3DFMT_L6V5U5:
+ case WINED3DFMT_R8G8_SNORM:
case WINED3DFMT_X8L8V8U8:
- case WINED3DFMT_Q8W8V8U8:
- WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
- return WINED3D_OK;
+ case WINED3DFMT_L6V5U5:
+ case WINED3DFMT_R8G8B8A8_SNORM:
+ case WINED3DFMT_R16G16_SNORM:
+ /* Ask the shader backend if it can deal with the conversion. If
+ * we've got a GL extension giving native support this will be an
+ * identity conversion. */
+ shader_backend = select_shader_backend(adapter, DeviceType);
+ if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup))
+ {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
- /* Those are not advertized by the nvidia windows driver, and not
- * supported natively by GL_NV_texture_shader or GL_ATI_envmap_bumpmap.
- * WINED3DFMT_A2W10V10U10 could be loaded into shaders using the unsigned
- * ARGB format if needed
- */
- case WINED3DFMT_W11V11U10:
- case WINED3DFMT_A2W10V10U10:
- WARN_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+ case WINED3DFMT_DXT1:
+ case WINED3DFMT_DXT2:
+ case WINED3DFMT_DXT3:
+ case WINED3DFMT_DXT4:
+ case WINED3DFMT_DXT5:
+ if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
- /*****
- * DXTN Formats: Handled above
- * WINED3DFMT_DXT1
- * WINED3DFMT_DXT2
- * WINED3DFMT_DXT3
- * WINED3DFMT_DXT4
- * WINED3DFMT_DXT5
- */
/*****
* Odd formats - not supported
*/
case WINED3DFMT_VERTEXDATA:
- case WINED3DFMT_INDEX16:
- case WINED3DFMT_INDEX32:
- case WINED3DFMT_Q16W16V16U16:
+ case WINED3DFMT_R16_UINT:
+ case WINED3DFMT_R32_UINT:
+ case WINED3DFMT_R16G16B16A16_SNORM:
+ case WINED3DFMT_A2W10V10U10:
+ case WINED3DFMT_W11V11U10:
TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
- return WINED3DERR_NOTAVAILABLE;
+ return FALSE;
/*****
- * Float formats: Not supported right now
+ * WINED3DFMT_CxV8U8: Not supported right now
*/
- case WINED3DFMT_G16R16F:
- case WINED3DFMT_G32R32F:
case WINED3DFMT_CxV8U8:
TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
- return WINED3DERR_NOTAVAILABLE;
+ return FALSE;
+
+ /* YUV formats */
+ case WINED3DFMT_UYVY:
+ case WINED3DFMT_YUY2:
+ if(GL_SUPPORT(APPLE_YCBCR_422)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+ case WINED3DFMT_YV12:
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
/* Not supported */
- case WINED3DFMT_G16R16:
- case WINED3DFMT_A16B16G16R16:
+ case WINED3DFMT_R16G16B16A16_UNORM:
case WINED3DFMT_A8R3G3B2:
TRACE_(d3d_caps)("[FAILED]\n"); /* Enable when implemented */
- return WINED3DERR_NOTAVAILABLE;
+ return FALSE;
+
+ /* Floating point formats */
+ case WINED3DFMT_R16_FLOAT:
+ case WINED3DFMT_R16G16_FLOAT:
+ case WINED3DFMT_R16G16B16A16_FLOAT:
+ if(GL_SUPPORT(ARB_TEXTURE_FLOAT) && GL_SUPPORT(ARB_HALF_FLOAT_PIXEL)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+
+ case WINED3DFMT_R32_FLOAT:
+ case WINED3DFMT_R32G32_FLOAT:
+ case WINED3DFMT_R32G32B32A32_FLOAT:
+ if (GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
/* ATI instancing hack: Although ATI cards do not support Shader Model 3.0, they support
* instancing. To query if the card supports instancing CheckDeviceFormat with the special format
TRACE("ATI Instancing check hack\n");
if(GL_SUPPORT(ARB_VERTEX_PROGRAM) || GL_SUPPORT(ARB_VERTEX_SHADER)) {
TRACE_(d3d_caps)("[OK]\n");
- return WINED3D_OK;
- } else {
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
+ return TRUE;
+ }
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+
+ /* Some weird FOURCC formats */
+ case WINED3DFMT_R8G8_B8G8:
+ case WINED3DFMT_G8R8_G8B8:
+ case WINED3DFMT_MULTI2_ARGB8:
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+
+ /* Vendor specific formats */
+ case WINED3DFMT_ATI2N:
+ if(GL_SUPPORT(ATI_TEXTURE_COMPRESSION_3DC) || GL_SUPPORT(EXT_TEXTURE_COMPRESSION_RGTC)) {
+ shader_backend = select_shader_backend(adapter, DeviceType);
+ fp = select_fragment_implementation(adapter, DeviceType);
+ if (shader_backend->shader_color_fixup_supported(format_desc->color_fixup)
+ && fp->color_fixup_supported(format_desc->color_fixup))
+ {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
}
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+
+ case WINED3DFMT_NVHU:
+ case WINED3DFMT_NVHS:
+ /* These formats seem to be similar to the HILO formats in GL_NV_texture_shader. NVHU
+ * is said to be GL_UNSIGNED_HILO16, NVHS GL_SIGNED_HILO16. Rumours say that d3d computes
+ * a 3rd channel similarly to D3DFMT_CxV8U8(So NVHS could be called D3DFMT_CxV16U16).
+ * ATI refused to support formats which can easilly be emulated with pixel shaders, so
+ * Applications have to deal with not having NVHS and NVHU.
+ */
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+
+ case WINED3DFMT_UNKNOWN:
+ return FALSE;
+
+ default:
+ ERR("Unhandled format=%s\n", debug_d3dformat(format_desc->format));
+ break;
+ }
+ return FALSE;
+}
+
+static BOOL CheckSurfaceCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *adapter_format_desc,
+ WINED3DDEVTYPE DeviceType, const struct GlPixelFormatDesc *check_format_desc, WINED3DSURFTYPE SurfaceType)
+{
+ const struct blit_shader *blitter;
+
+ if(SurfaceType == SURFACE_GDI) {
+ switch(check_format_desc->format)
+ {
+ case WINED3DFMT_R8G8B8:
+ case WINED3DFMT_A8R8G8B8:
+ case WINED3DFMT_X8R8G8B8:
+ case WINED3DFMT_R5G6B5:
+ case WINED3DFMT_X1R5G5B5:
+ case WINED3DFMT_A1R5G5B5:
+ case WINED3DFMT_A4R4G4B4:
+ case WINED3DFMT_R3G3B2:
+ case WINED3DFMT_A8_UNORM:
+ case WINED3DFMT_A8R3G3B2:
+ case WINED3DFMT_X4R4G4B4:
+ case WINED3DFMT_R10G10B10A2_UNORM:
+ case WINED3DFMT_R8G8B8A8_UNORM:
+ case WINED3DFMT_X8B8G8R8:
+ case WINED3DFMT_R16G16_UNORM:
+ case WINED3DFMT_A2R10G10B10:
+ case WINED3DFMT_R16G16B16A16_UNORM:
+ case WINED3DFMT_P8:
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ default:
+ TRACE_(d3d_caps)("[FAILED] - not available on GDI surfaces\n");
+ return FALSE;
+ }
+ }
+
+ /* All format that are supported for textures are supported for surfaces as well */
+ if (CheckTextureCapability(adapter, DeviceType, check_format_desc)) return TRUE;
+ /* All depth stencil formats are supported on surfaces */
+ if (CheckDepthStencilCapability(adapter, adapter_format_desc, check_format_desc)) return TRUE;
+
+ /* If opengl can't process the format natively, the blitter may be able to convert it */
+ blitter = select_blit_implementation(adapter, DeviceType);
+ if (blitter->color_fixup_supported(check_format_desc->color_fixup))
+ {
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+ }
+
+ /* Reject other formats */
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+}
+
+static BOOL CheckVertexTextureCapability(struct WineD3DAdapter *adapter, const struct GlPixelFormatDesc *format_desc)
+{
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+
+ if (!GL_LIMITS(vertex_samplers)) {
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+ }
+
+ switch (format_desc->format)
+ {
+ case WINED3DFMT_R32G32B32A32_FLOAT:
+ if (!GL_SUPPORT(ARB_TEXTURE_FLOAT)) {
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+ }
+ TRACE_(d3d_caps)("[OK]\n");
+ return TRUE;
+
+ default:
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return FALSE;
+ }
+ return FALSE;
+}
+
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
+ WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat,
+ WINED3DSURFTYPE SurfaceType) {
+ IWineD3DImpl *This = (IWineD3DImpl *)iface;
+ struct WineD3DAdapter *adapter = &This->adapters[Adapter];
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+ const struct GlPixelFormatDesc *format_desc = getFormatDescEntry(CheckFormat, gl_info);
+ const struct GlPixelFormatDesc *adapter_format_desc = getFormatDescEntry(AdapterFormat, gl_info);
+ DWORD UsageCaps = 0;
+
+ TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
+ This,
+ Adapter,
+ DeviceType, debug_d3ddevicetype(DeviceType),
+ AdapterFormat, debug_d3dformat(AdapterFormat),
+ Usage, debug_d3dusage(Usage), debug_d3dusagequery(Usage),
+ RType, debug_d3dresourcetype(RType),
+ CheckFormat, debug_d3dformat(CheckFormat));
+
+ if (Adapter >= IWineD3D_GetAdapterCount(iface)) {
+ return WINED3DERR_INVALIDCALL;
+ }
+
+ if(RType == WINED3DRTYPE_CUBETEXTURE) {
+
+ if(SurfaceType != SURFACE_OPENGL) {
+ TRACE("[FAILED]\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Cubetexture allows:
+ * - D3DUSAGE_AUTOGENMIPMAP
+ * - D3DUSAGE_DEPTHSTENCIL
+ * - D3DUSAGE_DYNAMIC
+ * - D3DUSAGE_NONSECURE (d3d9ex)
+ * - D3DUSAGE_RENDERTARGET
+ * - D3DUSAGE_SOFTWAREPROCESSING
+ * - D3DUSAGE_QUERY_WRAPANDMIP
+ */
+ if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
+ /* Check if the texture format is around */
+ if (CheckTextureCapability(adapter, DeviceType, format_desc))
+ {
+ if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
+ /* Check for automatic mipmap generation support */
+ if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
+ UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
+ } else {
+ /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
+ TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
+ }
+ }
+
+ /* Always report dynamic locking */
+ if(Usage & WINED3DUSAGE_DYNAMIC)
+ UsageCaps |= WINED3DUSAGE_DYNAMIC;
+
+ if(Usage & WINED3DUSAGE_RENDERTARGET) {
+ if(CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_RENDERTARGET;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Always report software processing */
+ if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
+ UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
+
+ /* Check QUERY_FILTER support */
+ if(Usage & WINED3DUSAGE_QUERY_FILTER) {
+ if (CheckFilterCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_POSTPIXELSHADER_BLENDING support */
+ if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
+ if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBREAD support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
+ if (CheckSrgbReadCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBWRITE support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
+ if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_VERTEXTEXTURE support */
+ if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
+ if (CheckVertexTextureCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_WRAPANDMIP support */
+ if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
+ if (CheckWrapAndMipCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - Cube texture format not supported\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No cube texture support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ } else if(RType == WINED3DRTYPE_SURFACE) {
+ /* Surface allows:
+ * - D3DUSAGE_DEPTHSTENCIL
+ * - D3DUSAGE_NONSECURE (d3d9ex)
+ * - D3DUSAGE_RENDERTARGET
+ */
+
+ if (CheckSurfaceCapability(adapter, adapter_format_desc, DeviceType, format_desc, SurfaceType))
+ {
+ if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
+ if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No depthstencil support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ if(Usage & WINED3DUSAGE_RENDERTARGET) {
+ if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_RENDERTARGET;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_POSTPIXELSHADER_BLENDING support */
+ if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
+ if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - Not supported for plain surfaces\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ } else if(RType == WINED3DRTYPE_TEXTURE) {
+ /* Texture allows:
+ * - D3DUSAGE_AUTOGENMIPMAP
+ * - D3DUSAGE_DEPTHSTENCIL
+ * - D3DUSAGE_DMAP
+ * - D3DUSAGE_DYNAMIC
+ * - D3DUSAGE_NONSECURE (d3d9ex)
+ * - D3DUSAGE_RENDERTARGET
+ * - D3DUSAGE_SOFTWAREPROCESSING
+ * - D3DUSAGE_TEXTAPI (d3d9ex)
+ * - D3DUSAGE_QUERY_WRAPANDMIP
+ */
+
+ if(SurfaceType != SURFACE_OPENGL) {
+ TRACE("[FAILED]\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Check if the texture format is around */
+ if (CheckTextureCapability(adapter, DeviceType, format_desc))
+ {
+ if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
+ /* Check for automatic mipmap generation support */
+ if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
+ UsageCaps |= WINED3DUSAGE_AUTOGENMIPMAP;
+ } else {
+ /* When autogenmipmap isn't around continue and return WINED3DOK_NOAUTOGEN instead of D3D_OK */
+ TRACE_(d3d_caps)("[FAILED] - No autogenmipmap support, but continuing\n");
+ }
+ }
+
+ /* Always report dynamic locking */
+ if(Usage & WINED3DUSAGE_DYNAMIC)
+ UsageCaps |= WINED3DUSAGE_DYNAMIC;
+
+ if(Usage & WINED3DUSAGE_RENDERTARGET) {
+ if (CheckRenderTargetCapability(adapter, adapter_format_desc, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_RENDERTARGET;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No rendertarget support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Always report software processing */
+ if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
+ UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
+
+ /* Check QUERY_FILTER support */
+ if(Usage & WINED3DUSAGE_QUERY_FILTER) {
+ if (CheckFilterCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_LEGACYBUMPMAP support */
+ if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
+ if (CheckBumpMapCapability(adapter, DeviceType, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_POSTPIXELSHADER_BLENDING support */
+ if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
+ if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBREAD support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
+ if (CheckSrgbReadCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBWRITE support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
+ if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_VERTEXTEXTURE support */
+ if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
+ if (CheckVertexTextureCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_WRAPANDMIP support */
+ if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
+ if (CheckWrapAndMipCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
+ if (CheckDepthStencilCapability(adapter, adapter_format_desc, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No depth stencil support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - Texture format not supported\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ } else if((RType == WINED3DRTYPE_VOLUME) || (RType == WINED3DRTYPE_VOLUMETEXTURE)) {
+ /* Volume is to VolumeTexture what Surface is to Texture but its usage caps are not documented.
+ * Most driver seem to offer (nearly) the same on Volume and VolumeTexture, so do that too.
+ *
+ * Volumetexture allows:
+ * - D3DUSAGE_DYNAMIC
+ * - D3DUSAGE_NONSECURE (d3d9ex)
+ * - D3DUSAGE_SOFTWAREPROCESSING
+ * - D3DUSAGE_QUERY_WRAPANDMIP
+ */
+
+ if(SurfaceType != SURFACE_OPENGL) {
+ TRACE("[FAILED]\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Check volume texture and volume usage caps */
+ if(GL_SUPPORT(EXT_TEXTURE3D)) {
+ if (!CheckTextureCapability(adapter, DeviceType, format_desc))
+ {
+ TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Always report dynamic locking */
+ if(Usage & WINED3DUSAGE_DYNAMIC)
+ UsageCaps |= WINED3DUSAGE_DYNAMIC;
+
+ /* Always report software processing */
+ if(Usage & WINED3DUSAGE_SOFTWAREPROCESSING)
+ UsageCaps |= WINED3DUSAGE_SOFTWAREPROCESSING;
+
+ /* Check QUERY_FILTER support */
+ if(Usage & WINED3DUSAGE_QUERY_FILTER) {
+ if (CheckFilterCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_FILTER;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query filter support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_POSTPIXELSHADER_BLENDING support */
+ if(Usage & WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) {
+ if (CheckPostPixelShaderBlendingCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query post pixelshader blending support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBREAD support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBREAD) {
+ if (CheckSrgbReadCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBREAD;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbread support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_SRGBWRITE support */
+ if(Usage & WINED3DUSAGE_QUERY_SRGBWRITE) {
+ if (CheckSrgbWriteCapability(adapter, DeviceType, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_SRGBWRITE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query srgbwrite support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_VERTEXTEXTURE support */
+ if(Usage & WINED3DUSAGE_QUERY_VERTEXTEXTURE) {
+ if (CheckVertexTextureCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_VERTEXTEXTURE;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No query vertextexture support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+
+ /* Check QUERY_WRAPANDMIP support */
+ if(Usage & WINED3DUSAGE_QUERY_WRAPANDMIP) {
+ if (CheckWrapAndMipCapability(adapter, format_desc))
+ {
+ UsageCaps |= WINED3DUSAGE_QUERY_WRAPANDMIP;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No wrapping and mipmapping support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ }
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - No volume texture support\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* Filter formats that need conversion; For one part, this conversion is unimplemented,
+ * and volume textures are huge, so it would be a big performance hit. Unless we hit an
+ * app needing one of those formats, don't advertize them to avoid leading apps into
+ * temptation. The windows drivers don't support most of those formats on volumes anyway,
+ * except of R32F.
+ */
+ switch(CheckFormat) {
+ case WINED3DFMT_P8:
+ case WINED3DFMT_A4L4:
+ case WINED3DFMT_R32_FLOAT:
+ case WINED3DFMT_R16_FLOAT:
+ case WINED3DFMT_X8L8V8U8:
+ case WINED3DFMT_L6V5U5:
+ case WINED3DFMT_R16G16_UNORM:
+ TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
+ return WINED3DERR_NOTAVAILABLE;
+
+ case WINED3DFMT_R8G8B8A8_SNORM:
+ case WINED3DFMT_R16G16_SNORM:
+ if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
+ TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ break;
+
+ case WINED3DFMT_R8G8_SNORM:
+ if(!GL_SUPPORT(NV_TEXTURE_SHADER)) {
+ TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+ break;
+
+ case WINED3DFMT_DXT1:
+ case WINED3DFMT_DXT2:
+ case WINED3DFMT_DXT3:
+ case WINED3DFMT_DXT4:
+ case WINED3DFMT_DXT5:
+ /* The GL_EXT_texture_compression_s3tc spec requires that loading an s3tc
+ * compressed texture results in an error. While the D3D refrast does
+ * support s3tc volumes, at least the nvidia windows driver does not, so
+ * we're free not to support this format.
+ */
+ TRACE_(d3d_caps)("[FAILED] - DXTn does not support 3D textures\n");
+ return WINED3DERR_NOTAVAILABLE;
+
+ default:
+ /* Do nothing, continue with checking the format below */
+ break;
+ }
+ } else if(RType == WINED3DRTYPE_BUFFER){
+ /* For instance vertexbuffer/indexbuffer aren't supported yet because no Windows drivers seem to offer it */
+ TRACE_(d3d_caps)("Unhandled resource type D3DRTYPE_INDEXBUFFER / D3DRTYPE_VERTEXBUFFER\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* This format is nothing special and it is supported perfectly.
+ * However, ati and nvidia driver on windows do not mark this format as
+ * supported (tested with the dxCapsViewer) and pretending to
+ * support this format uncovers a bug in Battlefield 1942 (fonts are missing)
+ * So do the same as Windows drivers and pretend not to support it on dx8 and 9
+ * Enable it on dx7. It will need additional checking on dx10 when we support it.
+ */
+ if(This->dxVersion > 7 && CheckFormat == WINED3DFMT_R8G8B8) {
+ TRACE_(d3d_caps)("[FAILED]\n");
+ return WINED3DERR_NOTAVAILABLE;
+ }
+
+ /* When the UsageCaps exactly matches Usage return WINED3D_OK except for the situation in which
+ * WINED3DUSAGE_AUTOGENMIPMAP isn't around, then WINED3DOK_NOAUTOGEN is returned if all the other
+ * usage flags match. */
+ if(UsageCaps == Usage) {
+ return WINED3D_OK;
+ } else if((UsageCaps == (Usage & ~WINED3DUSAGE_AUTOGENMIPMAP)) && (Usage & WINED3DUSAGE_AUTOGENMIPMAP)){
+ return WINED3DOK_NOAUTOGEN;
+ } else {
+ TRACE_(d3d_caps)("[FAILED] - Usage=%#08x requested for CheckFormat=%s and RType=%d but only %#08x is available\n", Usage, debug_d3dformat(CheckFormat), RType, UsageCaps);
+ return WINED3DERR_NOTAVAILABLE;
+ }
+}
+
+static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
+ WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
+ IWineD3DImpl *This = (IWineD3DImpl *)iface;
+
+ FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
+ This,
+ Adapter,
+ DeviceType, debug_d3ddevicetype(DeviceType),
+ SourceFormat, debug_d3dformat(SourceFormat),
+ TargetFormat, debug_d3dformat(TargetFormat));
+ return WINED3D_OK;
+}
+
+static const shader_backend_t *select_shader_backend(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
+{
+ const shader_backend_t *ret;
+ int vs_selected_mode;
+ int ps_selected_mode;
+
+ select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
+ if (vs_selected_mode == SHADER_GLSL || ps_selected_mode == SHADER_GLSL) {
+ ret = &glsl_shader_backend;
+ } else if (vs_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_ARB) {
+ ret = &arb_program_shader_backend;
+ } else {
+ ret = &none_shader_backend;
+ }
+ return ret;
+}
+
+static const struct fragment_pipeline *select_fragment_implementation(struct WineD3DAdapter *adapter,
+ WINED3DDEVTYPE DeviceType)
+{
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+ int vs_selected_mode;
+ int ps_selected_mode;
- default:
- break;
+ select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
+ if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
+ return &arbfp_fragment_pipeline;
+ } else if(ps_selected_mode == SHADER_ATI) {
+ return &atifs_fragment_pipeline;
+ } else if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
+ return &nvts_fragment_pipeline;
+ } else if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
+ return &nvrc_fragment_pipeline;
+ } else {
+ return &ffp_fragment_pipeline;
}
-
- TRACE_(d3d_caps)("[FAILED]\n");
- return WINED3DERR_NOTAVAILABLE;
}
-static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormatConversion(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
- WINED3DFORMAT SourceFormat, WINED3DFORMAT TargetFormat) {
- IWineD3DImpl *This = (IWineD3DImpl *)iface;
+static const struct blit_shader *select_blit_implementation(struct WineD3DAdapter *adapter, WINED3DDEVTYPE DeviceType)
+{
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
+ int vs_selected_mode;
+ int ps_selected_mode;
- FIXME_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), SrcFmt:(%u,%s), TgtFmt:(%u,%s))\n",
- This,
- Adapter,
- DeviceType, debug_d3ddevicetype(DeviceType),
- SourceFormat, debug_d3dformat(SourceFormat),
- TargetFormat, debug_d3dformat(TargetFormat));
- return WINED3D_OK;
+ select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
+ if((ps_selected_mode == SHADER_ARB || ps_selected_mode == SHADER_GLSL) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
+ return &arbfp_blit;
+ } else {
+ return &ffp_blit;
+ }
}
/* Note: d3d8 passes in a pointer to a D3DCAPS8 structure, which is a true
static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DCAPS* pCaps) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
+ struct WineD3DAdapter *adapter = &This->adapters[Adapter];
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
int vs_selected_mode;
int ps_selected_mode;
+ struct shader_caps shader_caps;
+ struct fragment_caps fragment_caps;
+ const shader_backend_t *shader_backend;
+ const struct fragment_pipeline *frag_pipeline = NULL;
+ DWORD ckey_caps, blit_caps, fx_caps;
TRACE_(d3d_caps)("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);
return WINED3DERR_INVALIDCALL;
}
- select_shader_mode(&Adapters[Adapter].gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
+ select_shader_mode(&adapter->gl_info, DeviceType, &ps_selected_mode, &vs_selected_mode);
/* This function should *not* be modifying GL caps
* TODO: move the functionality where it belongs */
- select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[Adapter].gl_info);
+ select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
/* ------------------------------------------------
The following fields apply to both d3d8 and d3d9
------------------------------------------------ */
- *pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
- *pCaps->AdapterOrdinal = Adapter;
+ pCaps->DeviceType = (DeviceType == WINED3DDEVTYPE_HAL) ? WINED3DDEVTYPE_HAL : WINED3DDEVTYPE_REF; /* Not quite true, but use h/w supported by opengl I suppose */
+ pCaps->AdapterOrdinal = Adapter;
- *pCaps->Caps = 0;
- *pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
- WINED3DCAPS2_FULLSCREENGAMMA |
- WINED3DCAPS2_DYNAMICTEXTURES;
+ pCaps->Caps = 0;
+ pCaps->Caps2 = WINED3DCAPS2_CANRENDERWINDOWED |
+ WINED3DCAPS2_FULLSCREENGAMMA |
+ WINED3DCAPS2_DYNAMICTEXTURES;
if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
- *pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
- }
- *pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD;
- *pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
- WINED3DPRESENT_INTERVAL_ONE;
-
- *pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
- WINED3DCURSORCAPS_LOWRES;
-
- *pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
- WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
- WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
- WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
- WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
- WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
- WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
- WINED3DDEVCAPS_PUREDEVICE |
- WINED3DDEVCAPS_HWRASTERIZATION |
- WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
- WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
- WINED3DDEVCAPS_CANRENDERAFTERFLIP |
- WINED3DDEVCAPS_DRAWPRIMITIVES2 |
- WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
- WINED3DDEVCAPS_RTPATCHES;
-
- *pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
- WINED3DPMISCCAPS_CULLCCW |
- WINED3DPMISCCAPS_CULLCW |
- WINED3DPMISCCAPS_COLORWRITEENABLE |
- WINED3DPMISCCAPS_CLIPTLVERTS |
- WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
- WINED3DPMISCCAPS_MASKZ |
- WINED3DPMISCCAPS_BLENDOP;
+ pCaps->Caps2 |= WINED3DCAPS2_CANAUTOGENMIPMAP;
+ }
+
+ pCaps->Caps3 = WINED3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD |
+ WINED3DCAPS3_COPY_TO_VIDMEM |
+ WINED3DCAPS3_COPY_TO_SYSTEMMEM;
+
+ pCaps->PresentationIntervals = WINED3DPRESENT_INTERVAL_IMMEDIATE |
+ WINED3DPRESENT_INTERVAL_ONE;
+
+ pCaps->CursorCaps = WINED3DCURSORCAPS_COLOR |
+ WINED3DCURSORCAPS_LOWRES;
+
+ pCaps->DevCaps = WINED3DDEVCAPS_FLOATTLVERTEX |
+ WINED3DDEVCAPS_EXECUTESYSTEMMEMORY |
+ WINED3DDEVCAPS_TLVERTEXSYSTEMMEMORY|
+ WINED3DDEVCAPS_TLVERTEXVIDEOMEMORY |
+ WINED3DDEVCAPS_DRAWPRIMTLVERTEX |
+ WINED3DDEVCAPS_HWTRANSFORMANDLIGHT |
+ WINED3DDEVCAPS_EXECUTEVIDEOMEMORY |
+ WINED3DDEVCAPS_PUREDEVICE |
+ WINED3DDEVCAPS_HWRASTERIZATION |
+ WINED3DDEVCAPS_TEXTUREVIDEOMEMORY |
+ WINED3DDEVCAPS_TEXTURESYSTEMMEMORY |
+ WINED3DDEVCAPS_CANRENDERAFTERFLIP |
+ WINED3DDEVCAPS_DRAWPRIMITIVES2 |
+ WINED3DDEVCAPS_DRAWPRIMITIVES2EX |
+ WINED3DDEVCAPS_RTPATCHES;
+
+ pCaps->PrimitiveMiscCaps = WINED3DPMISCCAPS_CULLNONE |
+ WINED3DPMISCCAPS_CULLCCW |
+ WINED3DPMISCCAPS_CULLCW |
+ WINED3DPMISCCAPS_COLORWRITEENABLE |
+ WINED3DPMISCCAPS_CLIPTLVERTS |
+ WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
+ WINED3DPMISCCAPS_MASKZ |
+ WINED3DPMISCCAPS_BLENDOP |
+ WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING;
/* TODO:
WINED3DPMISCCAPS_NULLREFERENCE
WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
WINED3DPMISCCAPS_FOGANDSPECULARALPHA
- WINED3DPMISCCAPS_SEPARATEALPHABLEND
WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
- WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
-/* The caps below can be supported but aren't handled yet in utils.c 'd3dta_to_combiner_input', disable them until support is fixed */
-#if 0
- if (GL_SUPPORT(NV_REGISTER_COMBINERS))
- *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_TSSARGTEMP;
- if (GL_SUPPORT(NV_REGISTER_COMBINERS2))
- *pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_PERSTAGECONSTANT;
-#endif
-
- *pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
- WINED3DPRASTERCAPS_PAT |
- WINED3DPRASTERCAPS_WFOG |
- WINED3DPRASTERCAPS_ZFOG |
- WINED3DPRASTERCAPS_FOGVERTEX |
- WINED3DPRASTERCAPS_FOGTABLE |
- WINED3DPRASTERCAPS_STIPPLE |
- WINED3DPRASTERCAPS_SUBPIXEL |
- WINED3DPRASTERCAPS_ZTEST |
- WINED3DPRASTERCAPS_SCISSORTEST |
- WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
- WINED3DPRASTERCAPS_DEPTHBIAS;
+ if(GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE) && GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE))
+ pCaps->PrimitiveMiscCaps |= WINED3DPMISCCAPS_SEPARATEALPHABLEND;
+
+ pCaps->RasterCaps = WINED3DPRASTERCAPS_DITHER |
+ WINED3DPRASTERCAPS_PAT |
+ WINED3DPRASTERCAPS_WFOG |
+ WINED3DPRASTERCAPS_ZFOG |
+ WINED3DPRASTERCAPS_FOGVERTEX |
+ WINED3DPRASTERCAPS_FOGTABLE |
+ WINED3DPRASTERCAPS_STIPPLE |
+ WINED3DPRASTERCAPS_SUBPIXEL |
+ WINED3DPRASTERCAPS_ZTEST |
+ WINED3DPRASTERCAPS_SCISSORTEST |
+ WINED3DPRASTERCAPS_SLOPESCALEDEPTHBIAS |
+ WINED3DPRASTERCAPS_DEPTHBIAS;
if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
- *pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
- WINED3DPRASTERCAPS_ZBIAS |
- WINED3DPRASTERCAPS_MIPMAPLODBIAS;
+ pCaps->RasterCaps |= WINED3DPRASTERCAPS_ANISOTROPY |
+ WINED3DPRASTERCAPS_ZBIAS |
+ WINED3DPRASTERCAPS_MIPMAPLODBIAS;
}
if(GL_SUPPORT(NV_FOG_DISTANCE)) {
- *pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
+ pCaps->RasterCaps |= WINED3DPRASTERCAPS_FOGRANGE;
}
/* FIXME Add:
- WINED3DPRASTERCAPS_COLORPERSPECTIVE
- WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
- WINED3DPRASTERCAPS_ANTIALIASEDGES
- WINED3DPRASTERCAPS_ZBUFFERLESSHSR
- WINED3DPRASTERCAPS_WBUFFER */
-
- *pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
- WINED3DPCMPCAPS_EQUAL |
- WINED3DPCMPCAPS_GREATER |
- WINED3DPCMPCAPS_GREATEREQUAL |
- WINED3DPCMPCAPS_LESS |
- WINED3DPCMPCAPS_LESSEQUAL |
- WINED3DPCMPCAPS_NEVER |
- WINED3DPCMPCAPS_NOTEQUAL;
-
- *pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
- WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
- WINED3DPBLENDCAPS_BOTHSRCALPHA |
- WINED3DPBLENDCAPS_DESTALPHA |
- WINED3DPBLENDCAPS_DESTCOLOR |
- WINED3DPBLENDCAPS_INVDESTALPHA |
- WINED3DPBLENDCAPS_INVDESTCOLOR |
- WINED3DPBLENDCAPS_INVSRCALPHA |
- WINED3DPBLENDCAPS_INVSRCCOLOR |
- WINED3DPBLENDCAPS_ONE |
- WINED3DPBLENDCAPS_SRCALPHA |
- WINED3DPBLENDCAPS_SRCALPHASAT |
- WINED3DPBLENDCAPS_SRCCOLOR |
- WINED3DPBLENDCAPS_ZERO;
-
- *pCaps->DestBlendCaps = WINED3DPBLENDCAPS_BLENDFACTOR |
- WINED3DPBLENDCAPS_DESTALPHA |
- WINED3DPBLENDCAPS_DESTCOLOR |
- WINED3DPBLENDCAPS_INVDESTALPHA |
- WINED3DPBLENDCAPS_INVDESTCOLOR |
- WINED3DPBLENDCAPS_INVSRCALPHA |
- WINED3DPBLENDCAPS_INVSRCCOLOR |
- WINED3DPBLENDCAPS_ONE |
- WINED3DPBLENDCAPS_SRCALPHA |
- WINED3DPBLENDCAPS_SRCCOLOR |
- WINED3DPBLENDCAPS_ZERO;
+ WINED3DPRASTERCAPS_COLORPERSPECTIVE
+ WINED3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
+ WINED3DPRASTERCAPS_ANTIALIASEDGES
+ WINED3DPRASTERCAPS_ZBUFFERLESSHSR
+ WINED3DPRASTERCAPS_WBUFFER */
+
+ pCaps->ZCmpCaps = WINED3DPCMPCAPS_ALWAYS |
+ WINED3DPCMPCAPS_EQUAL |
+ WINED3DPCMPCAPS_GREATER |
+ WINED3DPCMPCAPS_GREATEREQUAL |
+ WINED3DPCMPCAPS_LESS |
+ WINED3DPCMPCAPS_LESSEQUAL |
+ WINED3DPCMPCAPS_NEVER |
+ WINED3DPCMPCAPS_NOTEQUAL;
+
+ pCaps->SrcBlendCaps = WINED3DPBLENDCAPS_BOTHINVSRCALPHA |
+ WINED3DPBLENDCAPS_BOTHSRCALPHA |
+ WINED3DPBLENDCAPS_DESTALPHA |
+ WINED3DPBLENDCAPS_DESTCOLOR |
+ WINED3DPBLENDCAPS_INVDESTALPHA |
+ WINED3DPBLENDCAPS_INVDESTCOLOR |
+ WINED3DPBLENDCAPS_INVSRCALPHA |
+ WINED3DPBLENDCAPS_INVSRCCOLOR |
+ WINED3DPBLENDCAPS_ONE |
+ WINED3DPBLENDCAPS_SRCALPHA |
+ WINED3DPBLENDCAPS_SRCALPHASAT |
+ WINED3DPBLENDCAPS_SRCCOLOR |
+ WINED3DPBLENDCAPS_ZERO;
+
+ pCaps->DestBlendCaps = WINED3DPBLENDCAPS_DESTALPHA |
+ WINED3DPBLENDCAPS_DESTCOLOR |
+ WINED3DPBLENDCAPS_INVDESTALPHA |
+ WINED3DPBLENDCAPS_INVDESTCOLOR |
+ WINED3DPBLENDCAPS_INVSRCALPHA |
+ WINED3DPBLENDCAPS_INVSRCCOLOR |
+ WINED3DPBLENDCAPS_ONE |
+ WINED3DPBLENDCAPS_SRCALPHA |
+ WINED3DPBLENDCAPS_SRCCOLOR |
+ WINED3DPBLENDCAPS_ZERO;
/* NOTE: WINED3DPBLENDCAPS_SRCALPHASAT is not supported as dest blend factor,
* according to the glBlendFunc manpage
*
* legacy settings for srcblend only
*/
- *pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
- WINED3DPCMPCAPS_EQUAL |
- WINED3DPCMPCAPS_GREATER |
- WINED3DPCMPCAPS_GREATEREQUAL |
- WINED3DPCMPCAPS_LESS |
- WINED3DPCMPCAPS_LESSEQUAL |
- WINED3DPCMPCAPS_NEVER |
- WINED3DPCMPCAPS_NOTEQUAL;
-
- *pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
- WINED3DPSHADECAPS_COLORGOURAUDRGB |
- WINED3DPSHADECAPS_ALPHAFLATBLEND |
- WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
- WINED3DPSHADECAPS_COLORFLATRGB |
- WINED3DPSHADECAPS_FOGFLAT |
- WINED3DPSHADECAPS_FOGGOURAUD |
- WINED3DPSHADECAPS_SPECULARFLATRGB;
-
- *pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
- WINED3DPTEXTURECAPS_ALPHAPALETTE |
- WINED3DPTEXTURECAPS_BORDER |
- WINED3DPTEXTURECAPS_MIPMAP |
- WINED3DPTEXTURECAPS_PROJECTED |
- WINED3DPTEXTURECAPS_PERSPECTIVE;
+ if( GL_SUPPORT(EXT_BLEND_COLOR)) {
+ pCaps->SrcBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
+ pCaps->DestBlendCaps |= WINED3DPBLENDCAPS_BLENDFACTOR;
+ }
+
+
+ pCaps->AlphaCmpCaps = WINED3DPCMPCAPS_ALWAYS |
+ WINED3DPCMPCAPS_EQUAL |
+ WINED3DPCMPCAPS_GREATER |
+ WINED3DPCMPCAPS_GREATEREQUAL |
+ WINED3DPCMPCAPS_LESS |
+ WINED3DPCMPCAPS_LESSEQUAL |
+ WINED3DPCMPCAPS_NEVER |
+ WINED3DPCMPCAPS_NOTEQUAL;
+
+ pCaps->ShadeCaps = WINED3DPSHADECAPS_SPECULARGOURAUDRGB |
+ WINED3DPSHADECAPS_COLORGOURAUDRGB |
+ WINED3DPSHADECAPS_ALPHAFLATBLEND |
+ WINED3DPSHADECAPS_ALPHAGOURAUDBLEND |
+ WINED3DPSHADECAPS_COLORFLATRGB |
+ WINED3DPSHADECAPS_FOGFLAT |
+ WINED3DPSHADECAPS_FOGGOURAUD |
+ WINED3DPSHADECAPS_SPECULARFLATRGB;
+
+ pCaps->TextureCaps = WINED3DPTEXTURECAPS_ALPHA |
+ WINED3DPTEXTURECAPS_ALPHAPALETTE |
+ WINED3DPTEXTURECAPS_TRANSPARENCY |
+ WINED3DPTEXTURECAPS_BORDER |
+ WINED3DPTEXTURECAPS_MIPMAP |
+ WINED3DPTEXTURECAPS_PROJECTED |
+ WINED3DPTEXTURECAPS_PERSPECTIVE;
if( !GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
- *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
- WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
+ pCaps->TextureCaps |= WINED3DPTEXTURECAPS_POW2 |
+ WINED3DPTEXTURECAPS_NONPOW2CONDITIONAL;
}
if( GL_SUPPORT(EXT_TEXTURE3D)) {
- *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
- WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
- WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
+ pCaps->TextureCaps |= WINED3DPTEXTURECAPS_VOLUMEMAP |
+ WINED3DPTEXTURECAPS_MIPVOLUMEMAP |
+ WINED3DPTEXTURECAPS_VOLUMEMAP_POW2;
}
if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
- *pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
- WINED3DPTEXTURECAPS_MIPCUBEMAP |
- WINED3DPTEXTURECAPS_CUBEMAP_POW2;
+ pCaps->TextureCaps |= WINED3DPTEXTURECAPS_CUBEMAP |
+ WINED3DPTEXTURECAPS_MIPCUBEMAP |
+ WINED3DPTEXTURECAPS_CUBEMAP_POW2;
}
- *pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
- WINED3DPTFILTERCAPS_MAGFPOINT |
- WINED3DPTFILTERCAPS_MINFLINEAR |
- WINED3DPTFILTERCAPS_MINFPOINT |
- WINED3DPTFILTERCAPS_MIPFLINEAR |
- WINED3DPTFILTERCAPS_MIPFPOINT |
- WINED3DPTFILTERCAPS_LINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
- WINED3DPTFILTERCAPS_MIPLINEAR |
- WINED3DPTFILTERCAPS_MIPNEAREST |
- WINED3DPTFILTERCAPS_NEAREST;
+ pCaps->TextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
+ WINED3DPTFILTERCAPS_MAGFPOINT |
+ WINED3DPTFILTERCAPS_MINFLINEAR |
+ WINED3DPTFILTERCAPS_MINFPOINT |
+ WINED3DPTFILTERCAPS_MIPFLINEAR |
+ WINED3DPTFILTERCAPS_MIPFPOINT |
+ WINED3DPTFILTERCAPS_LINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+ WINED3DPTFILTERCAPS_MIPLINEAR |
+ WINED3DPTFILTERCAPS_MIPNEAREST |
+ WINED3DPTFILTERCAPS_NEAREST;
if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
- *pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
- WINED3DPTFILTERCAPS_MINFANISOTROPIC;
+ pCaps->TextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
+ WINED3DPTFILTERCAPS_MINFANISOTROPIC;
}
if (GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
- *pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
- WINED3DPTFILTERCAPS_MAGFPOINT |
- WINED3DPTFILTERCAPS_MINFLINEAR |
- WINED3DPTFILTERCAPS_MINFPOINT |
- WINED3DPTFILTERCAPS_MIPFLINEAR |
- WINED3DPTFILTERCAPS_MIPFPOINT |
- WINED3DPTFILTERCAPS_LINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
- WINED3DPTFILTERCAPS_MIPLINEAR |
- WINED3DPTFILTERCAPS_MIPNEAREST |
- WINED3DPTFILTERCAPS_NEAREST;
+ pCaps->CubeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
+ WINED3DPTFILTERCAPS_MAGFPOINT |
+ WINED3DPTFILTERCAPS_MINFLINEAR |
+ WINED3DPTFILTERCAPS_MINFPOINT |
+ WINED3DPTFILTERCAPS_MIPFLINEAR |
+ WINED3DPTFILTERCAPS_MIPFPOINT |
+ WINED3DPTFILTERCAPS_LINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+ WINED3DPTFILTERCAPS_MIPLINEAR |
+ WINED3DPTFILTERCAPS_MIPNEAREST |
+ WINED3DPTFILTERCAPS_NEAREST;
if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
- *pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
+ pCaps->CubeTextureFilterCaps |= WINED3DPTFILTERCAPS_MAGFANISOTROPIC |
WINED3DPTFILTERCAPS_MINFANISOTROPIC;
}
} else
- *pCaps->CubeTextureFilterCaps = 0;
+ pCaps->CubeTextureFilterCaps = 0;
if (GL_SUPPORT(EXT_TEXTURE3D)) {
- *pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
- WINED3DPTFILTERCAPS_MAGFPOINT |
- WINED3DPTFILTERCAPS_MINFLINEAR |
- WINED3DPTFILTERCAPS_MINFPOINT |
- WINED3DPTFILTERCAPS_MIPFLINEAR |
- WINED3DPTFILTERCAPS_MIPFPOINT |
- WINED3DPTFILTERCAPS_LINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
- WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
- WINED3DPTFILTERCAPS_MIPLINEAR |
- WINED3DPTFILTERCAPS_MIPNEAREST |
- WINED3DPTFILTERCAPS_NEAREST;
+ pCaps->VolumeTextureFilterCaps = WINED3DPTFILTERCAPS_MAGFLINEAR |
+ WINED3DPTFILTERCAPS_MAGFPOINT |
+ WINED3DPTFILTERCAPS_MINFLINEAR |
+ WINED3DPTFILTERCAPS_MINFPOINT |
+ WINED3DPTFILTERCAPS_MIPFLINEAR |
+ WINED3DPTFILTERCAPS_MIPFPOINT |
+ WINED3DPTFILTERCAPS_LINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPLINEAR |
+ WINED3DPTFILTERCAPS_LINEARMIPNEAREST |
+ WINED3DPTFILTERCAPS_MIPLINEAR |
+ WINED3DPTFILTERCAPS_MIPNEAREST |
+ WINED3DPTFILTERCAPS_NEAREST;
} else
- *pCaps->VolumeTextureFilterCaps = 0;
+ pCaps->VolumeTextureFilterCaps = 0;
- *pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
- WINED3DPTADDRESSCAPS_CLAMP |
- WINED3DPTADDRESSCAPS_WRAP;
+ pCaps->TextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
+ WINED3DPTADDRESSCAPS_CLAMP |
+ WINED3DPTADDRESSCAPS_WRAP;
if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
- *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
+ pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
}
if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
- *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
+ pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
}
if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
- *pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
+ pCaps->TextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
}
if (GL_SUPPORT(EXT_TEXTURE3D)) {
- *pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
- WINED3DPTADDRESSCAPS_CLAMP |
- WINED3DPTADDRESSCAPS_WRAP;
+ pCaps->VolumeTextureAddressCaps = WINED3DPTADDRESSCAPS_INDEPENDENTUV |
+ WINED3DPTADDRESSCAPS_CLAMP |
+ WINED3DPTADDRESSCAPS_WRAP;
if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
- *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
+ pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_BORDER;
}
if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
- *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
+ pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRROR;
}
if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
- *pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
+ pCaps->VolumeTextureAddressCaps |= WINED3DPTADDRESSCAPS_MIRRORONCE;
}
} else
- *pCaps->VolumeTextureAddressCaps = 0;
-
- *pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
- WINED3DLINECAPS_ZTEST;
- /* FIXME: Add
- WINED3DLINECAPS_BLEND
- WINED3DLINECAPS_ALPHACMP
- WINED3DLINECAPS_FOG */
+ pCaps->VolumeTextureAddressCaps = 0;
+
+ pCaps->LineCaps = WINED3DLINECAPS_TEXTURE |
+ WINED3DLINECAPS_ZTEST |
+ WINED3DLINECAPS_BLEND |
+ WINED3DLINECAPS_ALPHACMP |
+ WINED3DLINECAPS_FOG;
+ /* WINED3DLINECAPS_ANTIALIAS is not supported on Windows, and dx and gl seem to have a different
+ * idea how generating the smoothing alpha values works; the result is different
+ */
- *pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
- *pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
+ pCaps->MaxTextureWidth = GL_LIMITS(texture_size);
+ pCaps->MaxTextureHeight = GL_LIMITS(texture_size);
if(GL_SUPPORT(EXT_TEXTURE3D))
- *pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
+ pCaps->MaxVolumeExtent = GL_LIMITS(texture3d_size);
else
- *pCaps->MaxVolumeExtent = 0;
+ pCaps->MaxVolumeExtent = 0;
- *pCaps->MaxTextureRepeat = 32768;
- *pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
- *pCaps->MaxVertexW = 1.0;
+ pCaps->MaxTextureRepeat = 32768;
+ pCaps->MaxTextureAspectRatio = GL_LIMITS(texture_size);
+ pCaps->MaxVertexW = 1.0;
- *pCaps->GuardBandLeft = 0;
- *pCaps->GuardBandTop = 0;
- *pCaps->GuardBandRight = 0;
- *pCaps->GuardBandBottom = 0;
+ pCaps->GuardBandLeft = 0;
+ pCaps->GuardBandTop = 0;
+ pCaps->GuardBandRight = 0;
+ pCaps->GuardBandBottom = 0;
- *pCaps->ExtentsAdjust = 0;
+ pCaps->ExtentsAdjust = 0;
- *pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
- WINED3DSTENCILCAPS_INCRSAT |
- WINED3DSTENCILCAPS_INVERT |
- WINED3DSTENCILCAPS_KEEP |
- WINED3DSTENCILCAPS_REPLACE |
- WINED3DSTENCILCAPS_ZERO;
+ pCaps->StencilCaps = WINED3DSTENCILCAPS_DECRSAT |
+ WINED3DSTENCILCAPS_INCRSAT |
+ WINED3DSTENCILCAPS_INVERT |
+ WINED3DSTENCILCAPS_KEEP |
+ WINED3DSTENCILCAPS_REPLACE |
+ WINED3DSTENCILCAPS_ZERO;
if (GL_SUPPORT(EXT_STENCIL_WRAP)) {
- *pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
- WINED3DSTENCILCAPS_INCR;
+ pCaps->StencilCaps |= WINED3DSTENCILCAPS_DECR |
+ WINED3DSTENCILCAPS_INCR;
}
if ( This->dxVersion > 8 &&
( GL_SUPPORT(EXT_STENCIL_TWO_SIDE) ||
GL_SUPPORT(ATI_SEPARATE_STENCIL) ) ) {
- *pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
- }
-
- *pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
-
- *pCaps->TextureOpCaps = WINED3DTEXOPCAPS_ADD |
- WINED3DTEXOPCAPS_ADDSIGNED |
- WINED3DTEXOPCAPS_ADDSIGNED2X |
- WINED3DTEXOPCAPS_MODULATE |
- WINED3DTEXOPCAPS_MODULATE2X |
- WINED3DTEXOPCAPS_MODULATE4X |
- WINED3DTEXOPCAPS_SELECTARG1 |
- WINED3DTEXOPCAPS_SELECTARG2 |
- WINED3DTEXOPCAPS_DISABLE;
-
- if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
- GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
- GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA |
- WINED3DTEXOPCAPS_BLENDTEXTUREALPHA |
- WINED3DTEXOPCAPS_BLENDFACTORALPHA |
- WINED3DTEXOPCAPS_BLENDCURRENTALPHA |
- WINED3DTEXOPCAPS_LERP |
- WINED3DTEXOPCAPS_SUBTRACT;
- }
- if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
- GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH |
- WINED3DTEXOPCAPS_MULTIPLYADD |
- WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
- WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
- WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
- }
- if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
-
- if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR |
- WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
- }
-
- if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
- } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
- /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
- * not support 3D textures. This asks for trouble if an app uses both bump mapping
- * and 3D textures. It also allows us to keep the code simpler by having texture
- * shaders constantly enabled.
- */
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
- /* TODO: Luminance bump map? */
+ pCaps->StencilCaps |= WINED3DSTENCILCAPS_TWOSIDED;
}
-#if 0
- /* FIXME: Add
- *pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
- WINED3DTEXOPCAPS_PREMODULATE */
-#endif
- *pCaps->MaxTextureBlendStages = GL_LIMITS(texture_stages);
- *pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
- *pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
- *pCaps->MaxActiveLights = GL_LIMITS(lights);
+ pCaps->FVFCaps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
- *pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
- *pCaps->MaxVertexBlendMatrixIndex = 0;
+ pCaps->MaxUserClipPlanes = GL_LIMITS(clipplanes);
+ pCaps->MaxActiveLights = GL_LIMITS(lights);
- *pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
- *pCaps->MaxPointSize = GL_LIMITS(pointsize);
+ pCaps->MaxVertexBlendMatrices = GL_LIMITS(blends);
+ pCaps->MaxVertexBlendMatrixIndex = 0;
+ pCaps->MaxAnisotropy = GL_LIMITS(anisotropy);
+ pCaps->MaxPointSize = GL_LIMITS(pointsize);
- *pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
- WINED3DVTXPCAPS_MATERIALSOURCE7 |
- WINED3DVTXPCAPS_POSITIONALLIGHTS |
- WINED3DVTXPCAPS_LOCALVIEWER |
- WINED3DVTXPCAPS_VERTEXFOG |
- WINED3DVTXPCAPS_TEXGEN;
+
+ pCaps->VertexProcessingCaps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS |
+ WINED3DVTXPCAPS_MATERIALSOURCE7 |
+ WINED3DVTXPCAPS_POSITIONALLIGHTS |
+ WINED3DVTXPCAPS_LOCALVIEWER |
+ WINED3DVTXPCAPS_VERTEXFOG |
+ WINED3DVTXPCAPS_TEXGEN;
/* FIXME: Add
D3DVTXPCAPS_TWEENING, D3DVTXPCAPS_TEXGEN_SPHEREMAP */
- *pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
- *pCaps->MaxVertexIndex = 0xFFFFF;
- *pCaps->MaxStreams = MAX_STREAMS;
- *pCaps->MaxStreamStride = 1024;
-
- if (vs_selected_mode == SHADER_GLSL) {
- /* Nvidia Geforce6/7 or Ati R4xx/R5xx cards with GLSL support, support VS 3.0 but older Nvidia/Ati
- * models with GLSL support only support 2.0. In case of nvidia we can detect VS 2.0 support using
- * vs_nv_version which is based on NV_vertex_program.
- * For Ati cards there's no way using glsl (it abstracts the lowlevel info away) and also not
- * using ARB_vertex_program. It is safe to assume that when a card supports pixel shader 2.0 it
- * supports vertex shader 2.0 too and the way around. We can detect ps2.0 using the maximum number
- * of native instructions, so use that here. For more info see the pixel shader versioning code below. */
- if((GLINFO_LOCATION.vs_nv_version == VS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
- *pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
- else
- *pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
- TRACE_(d3d_caps)("Hardware vertex shader version %d.%d enabled (GLSL)\n", (*pCaps->VertexShaderVersion >> 8) & 0xff, *pCaps->VertexShaderVersion & 0xff);
- } else if (vs_selected_mode == SHADER_ARB) {
- *pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
- TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
- } else {
- *pCaps->VertexShaderVersion = 0;
- TRACE_(d3d_caps)("Vertex shader functionality not available\n");
- }
+ pCaps->MaxPrimitiveCount = 0xFFFFF; /* For now set 2^20-1 which is used by most >=Geforce3/Radeon8500 cards */
+ pCaps->MaxVertexIndex = 0xFFFFF;
+ pCaps->MaxStreams = MAX_STREAMS;
+ pCaps->MaxStreamStride = 1024;
- *pCaps->MaxVertexShaderConst = GL_LIMITS(vshader_constantsF);
+ /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
+ pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET |
+ WINED3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
+ pCaps->MaxNpatchTessellationLevel = 0;
+ pCaps->MasterAdapterOrdinal = 0;
+ pCaps->AdapterOrdinalInGroup = 0;
+ pCaps->NumberOfAdaptersInGroup = 1;
- if (ps_selected_mode == SHADER_GLSL) {
- /* Older DX9-class videocards (GeforceFX / Radeon >9500/X*00) only support pixel shader 2.0/2.0a/2.0b.
- * In OpenGL the extensions related to GLSL abstract lowlevel GL info away which is needed
- * to distinguish between 2.0 and 3.0 (and 2.0a/2.0b). In case of Nvidia we use their fragment
- * program extensions. On other hardware including ATI GL_ARB_fragment_program offers the info
- * in max native instructions. Intel and others also offer the info in this extension but they
- * don't support GLSL (at least on Windows).
- *
- * PS2.0 requires at least 96 instructions, 2.0a/2.0b go upto 512. Assume that if the number
- * of instructions is 512 or less we have to do with ps2.0 hardware.
- * NOTE: ps3.0 hardware requires 512 or more instructions but ati and nvidia offer 'enough' (1024 vs 4096) on their most basic ps3.0 hardware.
- */
- if((GLINFO_LOCATION.ps_nv_version == PS_VERSION_20) || (GLINFO_LOCATION.ps_arb_max_instructions <= 512))
- *pCaps->PixelShaderVersion = WINED3DPS_VERSION(2,0);
- else
- *pCaps->PixelShaderVersion = WINED3DPS_VERSION(3,0);
- /* FIXME: The following line is card dependent. -8.0 to 8.0 is the
- * Direct3D minimum requirement.
- *
- * Both GL_ARB_fragment_program and GLSL require a "maximum representable magnitude"
- * of colors to be 2^10, and 2^32 for other floats. Should we use 1024 here?
- *
- * The problem is that the refrast clamps temporary results in the shader to
- * [-MaxValue;+MaxValue]. If the card's max value is bigger than the one we advertize here,
- * then applications may miss the clamping behavior. On the other hand, if it is smaller,
- * the shader will generate incorrect results too. Unfortunately, GL deliberately doesn't
- * offer a way to query this.
- */
- *pCaps->PixelShader1xMaxValue = 8.0;
- TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (*pCaps->PixelShaderVersion >> 8) & 0xff, *pCaps->PixelShaderVersion & 0xff);
- } else if (ps_selected_mode == SHADER_ARB) {
- *pCaps->PixelShaderVersion = WINED3DPS_VERSION(1,4);
- *pCaps->PixelShader1xMaxValue = 8.0;
- TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
+ pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
+
+ pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
+ WINED3DPTFILTERCAPS_MAGFPOINT |
+ WINED3DPTFILTERCAPS_MINFLINEAR |
+ WINED3DPTFILTERCAPS_MAGFLINEAR;
+ pCaps->VertexTextureFilterCaps = 0;
+
+ memset(&shader_caps, 0, sizeof(shader_caps));
+ shader_backend = select_shader_backend(adapter, DeviceType);
+ shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
+
+ memset(&fragment_caps, 0, sizeof(fragment_caps));
+ frag_pipeline = select_fragment_implementation(adapter, DeviceType);
+ frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &fragment_caps);
+
+ /* Add shader misc caps. Only some of them belong to the shader parts of the pipeline */
+ pCaps->PrimitiveMiscCaps |= fragment_caps.PrimitiveMiscCaps;
+
+ /* This takes care for disabling vertex shader or pixel shader caps while leaving the other one enabled.
+ * Ignore shader model capabilities if disabled in config
+ */
+ if(vs_selected_mode == SHADER_NONE) {
+ TRACE_(d3d_caps)("Vertex shader disabled in config, reporting version 0.0\n");
+ pCaps->VertexShaderVersion = WINED3DVS_VERSION(0,0);
+ pCaps->MaxVertexShaderConst = 0;
} else {
- *pCaps->PixelShaderVersion = 0;
- *pCaps->PixelShader1xMaxValue = 0.0;
- TRACE_(d3d_caps)("Pixel shader functionality not available\n");
+ pCaps->VertexShaderVersion = shader_caps.VertexShaderVersion;
+ pCaps->MaxVertexShaderConst = shader_caps.MaxVertexShaderConst;
}
- /* ------------------------------------------------
- The following fields apply to d3d9 only
- ------------------------------------------------ */
- if (This->dxVersion > 8) {
- /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
- *pCaps->DevCaps2 = WINED3DDEVCAPS2_STREAMOFFSET;
- /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
- *pCaps->MaxNpatchTessellationLevel = 0;
- *pCaps->MasterAdapterOrdinal = 0;
- *pCaps->AdapterOrdinalInGroup = 0;
- *pCaps->NumberOfAdaptersInGroup = 1;
-
- if(*pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
- /* OpenGL supports all the formats below, perhaps not always
- * without conversion, but it supports them.
- * Further GLSL doesn't seem to have an official unsigned type so
- * don't advertise it yet as I'm not sure how we handle it.
- * We might need to add some clamping in the shader engine to
- * support it.
- * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
- *pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
- WINED3DDTCAPS_UBYTE4N |
- WINED3DDTCAPS_SHORT2N |
- WINED3DDTCAPS_SHORT4N;
- if (GL_SUPPORT(NV_HALF_FLOAT)) {
- *pCaps->DeclTypes |=
- WINED3DDTCAPS_FLOAT16_2 |
- WINED3DDTCAPS_FLOAT16_4;
- }
- } else
- *pCaps->DeclTypes = 0;
-
- *pCaps->NumSimultaneousRTs = GL_LIMITS(buffers);
-
-
- *pCaps->StretchRectFilterCaps = WINED3DPTFILTERCAPS_MINFPOINT |
- WINED3DPTFILTERCAPS_MAGFPOINT |
- WINED3DPTFILTERCAPS_MINFLINEAR |
- WINED3DPTFILTERCAPS_MAGFLINEAR;
- *pCaps->VertexTextureFilterCaps = 0;
-
- if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
- /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
- use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
- *pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
- *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
- *pCaps->VS20Caps.NumTemps = max(32, GLINFO_LOCATION.vs_arb_max_temps);
- *pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
-
- *pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
- *pCaps->MaxVertexShader30InstructionSlots = max(512, GLINFO_LOCATION.vs_arb_max_instructions);
- } else if(*pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
- *pCaps->VS20Caps.Caps = 0;
- *pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
- *pCaps->VS20Caps.NumTemps = max(12, GLINFO_LOCATION.vs_arb_max_temps);
- *pCaps->VS20Caps.StaticFlowControlDepth = 1;
-
- *pCaps->MaxVShaderInstructionsExecuted = 65535;
- *pCaps->MaxVertexShader30InstructionSlots = 0;
- } else { /* VS 1.x */
- *pCaps->VS20Caps.Caps = 0;
- *pCaps->VS20Caps.DynamicFlowControlDepth = 0;
- *pCaps->VS20Caps.NumTemps = 0;
- *pCaps->VS20Caps.StaticFlowControlDepth = 0;
-
- *pCaps->MaxVShaderInstructionsExecuted = 0;
- *pCaps->MaxVertexShader30InstructionSlots = 0;
- }
-
- if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
- /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
- use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
-
- /* 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 */
- *pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
- WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
- WINED3DPS20CAPS_PREDICATION |
- WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
- WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
- *pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
- *pCaps->PS20Caps.NumTemps = max(32, GLINFO_LOCATION.ps_arb_max_temps);
- *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
- *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
-
- *pCaps->MaxPShaderInstructionsExecuted = 65535;
- *pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, GLINFO_LOCATION.ps_arb_max_instructions);
- } else if(*pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
- /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
- *pCaps->PS20Caps.Caps = 0;
- *pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
- *pCaps->PS20Caps.NumTemps = max(12, GLINFO_LOCATION.ps_arb_max_temps);
- *pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minumum: 1 */
- *pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
-
- *pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
- *pCaps->MaxPixelShader30InstructionSlots = 0;
- } else { /* PS 1.x */
- *pCaps->PS20Caps.Caps = 0;
- *pCaps->PS20Caps.DynamicFlowControlDepth = 0;
- *pCaps->PS20Caps.NumTemps = 0;
- *pCaps->PS20Caps.StaticFlowControlDepth = 0;
- *pCaps->PS20Caps.NumInstructionSlots = 0;
-
- *pCaps->MaxPShaderInstructionsExecuted = 0;
- *pCaps->MaxPixelShader30InstructionSlots = 0;
- }
+ if(ps_selected_mode == SHADER_NONE) {
+ TRACE_(d3d_caps)("Pixel shader disabled in config, reporting version 0.0\n");
+ pCaps->PixelShaderVersion = WINED3DPS_VERSION(0,0);
+ pCaps->PixelShader1xMaxValue = 0.0;
+ } else {
+ pCaps->PixelShaderVersion = shader_caps.PixelShaderVersion;
+ pCaps->PixelShader1xMaxValue = shader_caps.PixelShader1xMaxValue;
}
- return WINED3D_OK;
-}
+ pCaps->TextureOpCaps = fragment_caps.TextureOpCaps;
+ pCaps->MaxTextureBlendStages = fragment_caps.MaxTextureBlendStages;
+ pCaps->MaxSimultaneousTextures = fragment_caps.MaxSimultaneousTextures;
-static unsigned int glsl_program_key_hash(void *key) {
- glsl_program_key_t *k = (glsl_program_key_t *)key;
+ pCaps->VS20Caps = shader_caps.VS20Caps;
+ pCaps->MaxVShaderInstructionsExecuted = shader_caps.MaxVShaderInstructionsExecuted;
+ pCaps->MaxVertexShader30InstructionSlots= shader_caps.MaxVertexShader30InstructionSlots;
+ pCaps->PS20Caps = shader_caps.PS20Caps;
+ pCaps->MaxPShaderInstructionsExecuted = shader_caps.MaxPShaderInstructionsExecuted;
+ pCaps->MaxPixelShader30InstructionSlots = shader_caps.MaxPixelShader30InstructionSlots;
- unsigned int hash = k->vshader | k->pshader << 16;
- hash += ~(hash << 15);
- hash ^= (hash >> 10);
- hash += (hash << 3);
- hash ^= (hash >> 6);
- hash += ~(hash << 11);
- hash ^= (hash >> 16);
+ /* The following caps are shader specific, but they are things we cannot detect, or which
+ * are the same among all shader models. So to avoid code duplication set the shader version
+ * specific, but otherwise constant caps here
+ */
+ if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(3,0)) {
+ /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
+ use the VS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum VS3.0 value. */
+ pCaps->VS20Caps.Caps = WINED3DVS20CAPS_PREDICATION;
+ pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* VS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
+ pCaps->VS20Caps.NumTemps = max(32, adapter->gl_info.vs_arb_max_temps);
+ pCaps->VS20Caps.StaticFlowControlDepth = WINED3DVS20_MAX_STATICFLOWCONTROLDEPTH ; /* level of nesting in loops / if-statements; VS 3.0 requires MAX (4) */
+
+ pCaps->MaxVShaderInstructionsExecuted = 65535; /* VS 3.0 needs at least 65535, some cards even use 2^32-1 */
+ pCaps->MaxVertexShader30InstructionSlots = max(512, adapter->gl_info.vs_arb_max_instructions);
+ } else if(pCaps->VertexShaderVersion == WINED3DVS_VERSION(2,0)) {
+ pCaps->VS20Caps.Caps = 0;
+ pCaps->VS20Caps.DynamicFlowControlDepth = WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH;
+ pCaps->VS20Caps.NumTemps = max(12, adapter->gl_info.vs_arb_max_temps);
+ pCaps->VS20Caps.StaticFlowControlDepth = 1;
+
+ pCaps->MaxVShaderInstructionsExecuted = 65535;
+ pCaps->MaxVertexShader30InstructionSlots = 0;
+ } else { /* VS 1.x */
+ pCaps->VS20Caps.Caps = 0;
+ pCaps->VS20Caps.DynamicFlowControlDepth = 0;
+ pCaps->VS20Caps.NumTemps = 0;
+ pCaps->VS20Caps.StaticFlowControlDepth = 0;
+
+ pCaps->MaxVShaderInstructionsExecuted = 0;
+ pCaps->MaxVertexShader30InstructionSlots = 0;
+ }
- return hash;
-}
+ if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(3,0)) {
+ /* Where possible set the caps based on OpenGL extensions and if they aren't set (in case of software rendering)
+ use the PS 3.0 from MSDN or else if there's OpenGL spec use a hardcoded value minimum PS 3.0 value. */
+
+ /* 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 */
+ pCaps->PS20Caps.Caps = WINED3DPS20CAPS_ARBITRARYSWIZZLE |
+ WINED3DPS20CAPS_GRADIENTINSTRUCTIONS |
+ WINED3DPS20CAPS_PREDICATION |
+ WINED3DPS20CAPS_NODEPENDENTREADLIMIT |
+ WINED3DPS20CAPS_NOTEXINSTRUCTIONLIMIT;
+ pCaps->PS20Caps.DynamicFlowControlDepth = WINED3DPS20_MAX_DYNAMICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_DYNAMICFLOWCONTROLDEPTH (24) */
+ pCaps->PS20Caps.NumTemps = max(32, adapter->gl_info.ps_arb_max_temps);
+ pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MAX_STATICFLOWCONTROLDEPTH; /* PS 3.0 requires MAX_STATICFLOWCONTROLDEPTH (4) */
+ pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MAX_NUMINSTRUCTIONSLOTS; /* PS 3.0 requires MAX_NUMINSTRUCTIONSLOTS (512) */
+
+ pCaps->MaxPShaderInstructionsExecuted = 65535;
+ pCaps->MaxPixelShader30InstructionSlots = max(WINED3DMIN30SHADERINSTRUCTIONS, adapter->gl_info.ps_arb_max_instructions);
+ } else if(pCaps->PixelShaderVersion == WINED3DPS_VERSION(2,0)) {
+ /* Below we assume PS2.0 specs, not extended 2.0a(GeforceFX)/2.0b(Radeon R3xx) ones */
+ pCaps->PS20Caps.Caps = 0;
+ pCaps->PS20Caps.DynamicFlowControlDepth = 0; /* WINED3DVS20_MIN_DYNAMICFLOWCONTROLDEPTH = 0 */
+ pCaps->PS20Caps.NumTemps = max(12, adapter->gl_info.ps_arb_max_temps);
+ pCaps->PS20Caps.StaticFlowControlDepth = WINED3DPS20_MIN_STATICFLOWCONTROLDEPTH; /* Minimum: 1 */
+ pCaps->PS20Caps.NumInstructionSlots = WINED3DPS20_MIN_NUMINSTRUCTIONSLOTS; /* Minimum number (64 ALU + 32 Texture), a GeforceFX uses 512 */
+
+ pCaps->MaxPShaderInstructionsExecuted = 512; /* Minimum value, a GeforceFX uses 1024 */
+ pCaps->MaxPixelShader30InstructionSlots = 0;
+ } else { /* PS 1.x */
+ pCaps->PS20Caps.Caps = 0;
+ pCaps->PS20Caps.DynamicFlowControlDepth = 0;
+ pCaps->PS20Caps.NumTemps = 0;
+ pCaps->PS20Caps.StaticFlowControlDepth = 0;
+ pCaps->PS20Caps.NumInstructionSlots = 0;
+
+ pCaps->MaxPShaderInstructionsExecuted = 0;
+ pCaps->MaxPixelShader30InstructionSlots = 0;
+ }
-static BOOL glsl_program_key_compare(void *keya, void *keyb) {
- glsl_program_key_t *ka = (glsl_program_key_t *)keya;
- glsl_program_key_t *kb = (glsl_program_key_t *)keyb;
+ if(pCaps->VertexShaderVersion >= WINED3DVS_VERSION(2,0)) {
+ /* OpenGL supports all the formats below, perhaps not always
+ * without conversion, but it supports them.
+ * Further GLSL doesn't seem to have an official unsigned type so
+ * don't advertise it yet as I'm not sure how we handle it.
+ * We might need to add some clamping in the shader engine to
+ * support it.
+ * TODO: WINED3DDTCAPS_USHORT2N, WINED3DDTCAPS_USHORT4N, WINED3DDTCAPS_UDEC3, WINED3DDTCAPS_DEC3N */
+ pCaps->DeclTypes = WINED3DDTCAPS_UBYTE4 |
+ WINED3DDTCAPS_UBYTE4N |
+ WINED3DDTCAPS_SHORT2N |
+ WINED3DDTCAPS_SHORT4N;
+ if (GL_SUPPORT(ARB_HALF_FLOAT_VERTEX)) {
+ pCaps->DeclTypes |= WINED3DDTCAPS_FLOAT16_2 |
+ WINED3DDTCAPS_FLOAT16_4;
+ }
+ } else
+ pCaps->DeclTypes = 0;
+
+ /* Set DirectDraw helper Caps */
+ ckey_caps = WINEDDCKEYCAPS_DESTBLT |
+ WINEDDCKEYCAPS_SRCBLT;
+ fx_caps = WINEDDFXCAPS_BLTALPHA |
+ WINEDDFXCAPS_BLTMIRRORLEFTRIGHT |
+ WINEDDFXCAPS_BLTMIRRORUPDOWN |
+ WINEDDFXCAPS_BLTROTATION90 |
+ WINEDDFXCAPS_BLTSHRINKX |
+ WINEDDFXCAPS_BLTSHRINKXN |
+ WINEDDFXCAPS_BLTSHRINKY |
+ WINEDDFXCAPS_BLTSHRINKXN |
+ WINEDDFXCAPS_BLTSTRETCHX |
+ WINEDDFXCAPS_BLTSTRETCHXN |
+ WINEDDFXCAPS_BLTSTRETCHY |
+ WINEDDFXCAPS_BLTSTRETCHYN;
+ blit_caps = WINEDDCAPS_BLT |
+ WINEDDCAPS_BLTCOLORFILL |
+ WINEDDCAPS_BLTDEPTHFILL |
+ WINEDDCAPS_BLTSTRETCH |
+ WINEDDCAPS_CANBLTSYSMEM |
+ WINEDDCAPS_CANCLIP |
+ WINEDDCAPS_CANCLIPSTRETCHED |
+ WINEDDCAPS_COLORKEY |
+ WINEDDCAPS_COLORKEYHWASSIST |
+ WINEDDCAPS_ALIGNBOUNDARYSRC;
+
+ /* Fill the ddraw caps structure */
+ pCaps->DirectDrawCaps.Caps = WINEDDCAPS_GDI |
+ WINEDDCAPS_PALETTE |
+ blit_caps;
+ pCaps->DirectDrawCaps.Caps2 = WINEDDCAPS2_CERTIFIED |
+ WINEDDCAPS2_NOPAGELOCKREQUIRED |
+ WINEDDCAPS2_PRIMARYGAMMA |
+ WINEDDCAPS2_WIDESURFACES |
+ WINEDDCAPS2_CANRENDERWINDOWED;
+ pCaps->DirectDrawCaps.SVBCaps = blit_caps;
+ pCaps->DirectDrawCaps.SVBCKeyCaps = ckey_caps;
+ pCaps->DirectDrawCaps.SVBFXCaps = fx_caps;
+ pCaps->DirectDrawCaps.VSBCaps = blit_caps;
+ pCaps->DirectDrawCaps.VSBCKeyCaps = ckey_caps;
+ pCaps->DirectDrawCaps.VSBFXCaps = fx_caps;
+ pCaps->DirectDrawCaps.SSBCaps = blit_caps;
+ pCaps->DirectDrawCaps.SSBCKeyCaps = ckey_caps;
+ pCaps->DirectDrawCaps.SSBFXCaps = fx_caps;
+
+ pCaps->DirectDrawCaps.ddsCaps = WINEDDSCAPS_ALPHA |
+ WINEDDSCAPS_BACKBUFFER |
+ WINEDDSCAPS_FLIP |
+ WINEDDSCAPS_FRONTBUFFER |
+ WINEDDSCAPS_OFFSCREENPLAIN |
+ WINEDDSCAPS_PALETTE |
+ WINEDDSCAPS_PRIMARYSURFACE |
+ WINEDDSCAPS_SYSTEMMEMORY |
+ WINEDDSCAPS_VIDEOMEMORY |
+ WINEDDSCAPS_VISIBLE;
+ pCaps->DirectDrawCaps.StrideAlign = DDRAW_PITCH_ALIGNMENT;
+
+ /* Set D3D caps if OpenGL is available. */
+ if (adapter->opengl)
+ {
+ pCaps->DirectDrawCaps.ddsCaps |=WINEDDSCAPS_3DDEVICE |
+ WINEDDSCAPS_MIPMAP |
+ WINEDDSCAPS_TEXTURE |
+ WINEDDSCAPS_ZBUFFER;
+ pCaps->DirectDrawCaps.Caps |= WINEDDCAPS_3D;
+ }
- return ka->vshader == kb->vshader && ka->pshader == kb->pshader;
+ return WINED3D_OK;
}
/* Note due to structure differences between dx8 and dx9 D3DPRESENT_PARAMETERS,
and fields being inserted in the middle, a new structure is used in place */
-static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType, HWND hFocusWindow,
- DWORD BehaviourFlags, IWineD3DDevice** ppReturnedDeviceInterface,
- IUnknown *parent) {
-
+static HRESULT WINAPI IWineD3DImpl_CreateDevice(IWineD3D *iface, UINT Adapter,
+ WINED3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviourFlags, IUnknown *parent,
+ IWineD3DDeviceParent *device_parent, IWineD3DDevice **ppReturnedDeviceInterface)
+{
IWineD3DDeviceImpl *object = NULL;
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- HDC hDC;
+ struct WineD3DAdapter *adapter = &This->adapters[Adapter];
+ WINED3DDISPLAYMODE mode;
+ const struct fragment_pipeline *frag_pipeline = NULL;
int i;
+ struct fragment_caps ffp_caps;
+ struct shader_caps shader_caps;
+ HRESULT hr;
/* Validate the adapter number. If no adapters are available(no GL), ignore the adapter
* number and create a device without a 3D adapter for 2D only operation.
object->lpVtbl = &IWineD3DDevice_Vtbl;
object->ref = 1;
object->wineD3D = iface;
- object->adapter = numAdapters ? &Adapters[Adapter] : NULL;
+ object->adapter = This->adapter_count ? adapter : NULL;
IWineD3D_AddRef(object->wineD3D);
object->parent = parent;
+ object->device_parent = device_parent;
list_init(&object->resources);
+ list_init(&object->shaders);
if(This->dxVersion == 7) {
- object->surface_alignment = 8;
+ object->surface_alignment = DDRAW_PITCH_ALIGNMENT;
} else {
- object->surface_alignment = 4;
+ object->surface_alignment = D3D8_PITCH_ALIGNMENT;
}
object->posFixup[0] = 1.0; /* This is needed to get the x coord unmodified through a MAD */
object->adapterNo = Adapter;
object->devType = DeviceType;
- select_shader_mode(&GLINFO_LOCATION, DeviceType, &object->ps_selected_mode, &object->vs_selected_mode);
- if (object->ps_selected_mode == SHADER_GLSL || object->vs_selected_mode == SHADER_GLSL) {
- object->shader_backend = &glsl_shader_backend;
- object->glsl_program_lookup = hash_table_create(&glsl_program_key_hash, &glsl_program_key_compare);
- } else if (object->ps_selected_mode == SHADER_ARB || object->vs_selected_mode == SHADER_ARB) {
- object->shader_backend = &arb_program_shader_backend;
- } else {
- object->shader_backend = &none_shader_backend;
+ select_shader_mode(&adapter->gl_info, DeviceType,
+ &object->ps_selected_mode, &object->vs_selected_mode);
+ object->shader_backend = select_shader_backend(adapter, DeviceType);
+
+ memset(&shader_caps, 0, sizeof(shader_caps));
+ object->shader_backend->shader_get_caps(DeviceType, &adapter->gl_info, &shader_caps);
+ object->d3d_vshader_constantF = shader_caps.MaxVertexShaderConst;
+ object->d3d_pshader_constantF = shader_caps.MaxPixelShaderConst;
+
+ memset(&ffp_caps, 0, sizeof(ffp_caps));
+ frag_pipeline = select_fragment_implementation(adapter, DeviceType);
+ object->frag_pipe = frag_pipeline;
+ frag_pipeline->get_caps(DeviceType, &adapter->gl_info, &ffp_caps);
+ object->max_ffp_textures = ffp_caps.MaxSimultaneousTextures;
+ object->max_ffp_texture_stages = ffp_caps.MaxTextureBlendStages;
+ hr = compile_state_table(object->StateTable, object->multistate_funcs, &adapter->gl_info,
+ ffp_vertexstate_template, frag_pipeline, misc_state_template);
+
+ if (FAILED(hr)) {
+ IWineD3D_Release(object->wineD3D);
+ HeapFree(GetProcessHeap(), 0, object);
+
+ return hr;
}
+ object->blitter = select_blit_implementation(adapter, DeviceType);
+
/* set the state of the device to valid */
object->state = WINED3D_OK;
/* Get the initial screen setup for ddraw */
- object->ddraw_width = GetSystemMetrics(SM_CXSCREEN);
- object->ddraw_height = GetSystemMetrics(SM_CYSCREEN);
- hDC = GetDC(0);
- object->ddraw_format = pixelformat_for_depth(GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES));
- ReleaseDC(0, hDC);
+ IWineD3DImpl_GetAdapterDisplayMode(iface, Adapter, &mode);
+
+ object->ddraw_width = mode.Width;
+ object->ddraw_height = mode.Height;
+ object->ddraw_format = mode.Format;
for(i = 0; i < PATCHMAP_SIZE; i++) {
list_init(&object->patches[i]);
}
+
+ IWineD3DDeviceParent_WineD3DDeviceCreated(device_parent, *ppReturnedDeviceInterface);
+
return WINED3D_OK;
}
-#undef GLINFO_LOCATION
static HRESULT WINAPI IWineD3DImpl_GetParent(IWineD3D *iface, IUnknown **pParent) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
return IUnknown_Release(volumeParent);
}
-static BOOL implementation_is_apple(WineD3D_GL_Info *gl_info) {
+static BOOL match_apple(const WineD3D_GL_Info *gl_info)
+{
/* MacOS has various specialities in the extensions it advertises. Some have to be loaded from
* the opengl 1.2+ core, while other extensions are advertised, but software emulated. So try to
* detect the Apple OpenGL implementation to apply some extension fixups afterwards.
* aren't sufficient either because a Linux binary may display on a macos X server via remote X11.
* So try to detect the GL implementation by looking at certain Apple extensions. Some extensions
* like client storage might be supported on other implementations too, but GL_APPLE_flush_render
- * is specific to the MacOS window management, and GL_APPLE_ycbcr_422 is a Quicktime specific, so
- * it the chance that other implementations support it is rather rare since Win32 Quicktime uses
+ * is specific to the Mac OS X window management, and GL_APPLE_ycbcr_422 is QuickTime specific. So
+ * the chance that other implementations support them is rather small since Win32 QuickTime uses
* DirectDraw, not OpenGL.
*/
if(gl_info->supported[APPLE_FENCE] &&
}
}
-static void fixup_extensions(WineD3D_GL_Info *gl_info) {
- if(implementation_is_apple(gl_info)) {
- /* MacOS advertises more GLSL vertex shader uniforms than support on hardware, and if more are
- * used it falls back to software. While the compiler can detect if the shader uses all declared
- * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
- * using relative addressing falls back to software.
- *
- * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
- */
- if(gl_info->vs_glsl_constantsF <= gl_info->vs_arb_constantsF) {
- FIXME("GLSL doesn't advertise more vertex shader uniforms than ARB. Driver fixup outdated?\n");
- } else {
- TRACE("Driver claims %u GLSL vs uniforms, replacing with %u ARB vp uniforms\n",
- gl_info->vs_glsl_constantsF, gl_info->vs_arb_constantsF);
- gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
+static void test_pbo_functionality(WineD3D_GL_Info *gl_info) {
+ /* Some OpenGL implementations, namely Apple's Geforce 8 driver, advertises PBOs,
+ * but glTexSubImage from a PBO fails miserably, with the first line repeated over
+ * all the texture. This function detects this bug by its symptom and disables PBOs
+ * if the test fails.
+ *
+ * The test uploads a 4x4 texture via the PBO in the "native" format GL_BGRA,
+ * GL_UNSIGNED_INT_8_8_8_8_REV. This format triggers the bug, and it is what we use
+ * for D3DFMT_A8R8G8B8. Then the texture is read back without any PBO and the data
+ * read back is compared to the original. If they are equal PBOs are assumed to work,
+ * otherwise the PBO extension is disabled.
+ */
+ GLuint texture, pbo;
+ static const unsigned int pattern[] = {
+ 0x00000000, 0x000000ff, 0x0000ff00, 0x40ff0000,
+ 0x80ffffff, 0x40ffff00, 0x00ff00ff, 0x0000ffff,
+ 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x000000ff,
+ 0x80ff00ff, 0x0000ffff, 0x00ff00ff, 0x40ff00ff
+ };
+ unsigned int check[sizeof(pattern) / sizeof(pattern[0])];
+
+ if(!gl_info->supported[ARB_PIXEL_BUFFER_OBJECT]) {
+ /* No PBO -> No point in testing them */
+ return;
+ }
+
+ while(glGetError());
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 4, 4, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
+ checkGLcall("Specifying the PBO test texture\n");
+
+ GL_EXTCALL(glGenBuffersARB(1, &pbo));
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo));
+ GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, sizeof(pattern), pattern, GL_STREAM_DRAW_ARB));
+ checkGLcall("Specifying the PBO test pbo\n");
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+ checkGLcall("Loading the PBO test texture\n");
+
+ GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
+ glFinish(); /* just to be sure */
+
+ memset(check, 0, sizeof(check));
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, check);
+ checkGLcall("Reading back the PBO test texture\n");
+
+ glDeleteTextures(1, &texture);
+ GL_EXTCALL(glDeleteBuffersARB(1, &pbo));
+ checkGLcall("PBO test cleanup\n");
+
+ if(memcmp(check, pattern, sizeof(check)) != 0) {
+ WARN_(d3d_caps)("PBO test failed, read back data doesn't match original\n");
+ WARN_(d3d_caps)("Disabling PBOs. This may result in slower performance\n");
+ gl_info->supported[ARB_PIXEL_BUFFER_OBJECT] = FALSE;
+ } else {
+ TRACE_(d3d_caps)("PBO test successful\n");
+ }
+}
+
+/* Certain applications(Steam) complain if we report an outdated driver version. In general,
+ * reporting a driver version is moot because we are not the Windows driver, and we have different
+ * bugs, features, etc.
+ *
+ * If a card is not found in this table, the gl driver version is reported
+ */
+struct driver_version_information {
+ WORD vendor; /* reported PCI card vendor ID */
+ WORD card; /* reported PCI card device ID */
+ const char *description; /* Description of the card e.g. NVIDIA RIVA TNT */
+ WORD hipart_hi, hipart_lo; /* driver hiword to report */
+ WORD lopart_hi, lopart_lo; /* driver loword to report */
+};
+
+static const struct driver_version_information driver_version_table[] = {
+ /* Nvidia drivers. Geforce6 and newer cards are supported by the current driver (180.x)
+ * GeforceFX support is up to 173.x, - driver uses numbering x.y.11.7341 for 173.41 where x is the windows revision (6=2000/xp, 7=vista), y is unknown
+ * Geforce2MX/3/4 up to 96.x - driver uses numbering 9.6.8.9 for 96.89
+ * TNT/Geforce1/2 up to 71.x - driver uses numbering 7.1.8.6 for 71.86
+ *
+ * All version numbers used below are from the Linux nvidia drivers.
+ */
+ {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT, "NVIDIA RIVA TNT", 7, 1, 8, 6 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_RIVA_TNT2, "NVIDIA RIVA TNT2/TNT2 Pro", 7, 1, 8, 6 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE, "NVIDIA GeForce 256", 7, 1, 8, 6 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2_MX, "NVIDIA GeForce2 MX/MX 400", 9, 6, 4, 3 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE2, "NVIDIA GeForce2 GTS/GeForce2 Pro", 7, 1, 8, 6 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE3, "NVIDIA GeForce3", 9, 6, 4, 3 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_MX, "NVIDIA GeForce4 MX 460", 9, 6, 4, 3 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE4_TI4200, "NVIDIA GeForce4 Ti 4200", 9, 6, 4, 3 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5200, "NVIDIA GeForce FX 5200", 7, 15, 11, 7341 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5600, "NVIDIA GeForce FX 5600", 7, 15, 11, 7341 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCEFX_5800, "NVIDIA GeForce FX 5800", 7, 15, 11, 7341 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6200, "NVIDIA GeForce 6200", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6600GT, "NVIDIA GeForce 6600 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_6800, "NVIDIA GeForce 6800", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7300, "NVIDIA GeForce Go 7300", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7400, "NVIDIA GeForce Go 7400", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7600, "NVIDIA GeForce 7600 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_7800GT, "NVIDIA GeForce 7800 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8300GS, "NVIDIA GeForce 8300 GS", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600GT, "NVIDIA GeForce 8600 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8600MGT, "NVIDIA GeForce 8600M GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_8800GTS, "NVIDIA GeForce 8800 GTS", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9200, "NVIDIA GeForce 9200", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9400GT, "NVIDIA GeForce 9400 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9500GT, "NVIDIA GeForce 9500 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9600GT, "NVIDIA GeForce 9600 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_9800GT, "NVIDIA GeForce 9800 GT", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX260, "NVIDIA GeForce GTX 260", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX275, "NVIDIA GeForce GTX 275", 7, 15, 11, 8044 },
+ {VENDOR_NVIDIA, CARD_NVIDIA_GEFORCE_GTX280, "NVIDIA GeForce GTX 280", 7, 15, 11, 8044 },
+
+ /* ATI cards. The driver versions are somewhat similar, but not quite the same. Let's hardcode */
+ {VENDOR_ATI, CARD_ATI_RADEON_9500, "ATI Radeon 9500", 6, 14, 10, 6764 },
+ {VENDOR_ATI, CARD_ATI_RADEON_X700, "ATI Radeon X700 SE", 6, 14, 10, 6764 },
+ {VENDOR_ATI, CARD_ATI_RADEON_X1600, "ATI Radeon X1600 Series", 6, 14, 10, 6764 },
+ {VENDOR_ATI, CARD_ATI_RADEON_HD2300, "ATI Mobility Radeon HD 2300", 6, 14, 10, 6764 },
+ {VENDOR_ATI, CARD_ATI_RADEON_HD2600, "ATI Mobility Radeon HD 2600", 6, 14, 10, 6764 },
+ {VENDOR_ATI, CARD_ATI_RADEON_HD2900, "ATI Radeon HD 2900 XT", 6, 14, 10, 6764 },
+
+ /* TODO: Add information about legacy ATI hardware, Intel and other cards */
+};
+
+static BOOL match_ati_r300_to_500(const WineD3D_GL_Info *gl_info) {
+ if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+ if(gl_info->gl_card == CARD_ATI_RADEON_9500) return TRUE;
+ if(gl_info->gl_card == CARD_ATI_RADEON_X700) return TRUE;
+ if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return TRUE;
+ return FALSE;
+}
+
+static BOOL match_geforce5(const WineD3D_GL_Info *gl_info) {
+ if(gl_info->gl_vendor == VENDOR_NVIDIA) {
+ if(gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5800 || gl_info->gl_card == CARD_NVIDIA_GEFORCEFX_5600) {
+ return TRUE;
}
+ }
+ return FALSE;
+}
- /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
- * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
- * If real NP2 textures are used, the driver falls back to software. So remove the supported
- * flag for this extension
- */
- if(gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] && gl_info->gl_vendor == VENDOR_ATI) {
- if(gl_info->gl_card == CARD_ATI_RADEON_X700 || gl_info->gl_card == CARD_ATI_RADEON_X1600 ||
- gl_info->gl_card == CARD_ATI_RADEON_9500 || gl_info->gl_card == CARD_ATI_RADEON_8500 ||
- gl_info->gl_card == CARD_ATI_RADEON_7200 || gl_info->gl_card == CARD_ATI_RAGE_128PRO) {
- TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
- gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
- }
+static BOOL match_apple_intel(const WineD3D_GL_Info *gl_info) {
+ return gl_info->gl_vendor == VENDOR_INTEL && match_apple(gl_info);
+}
+
+static BOOL match_apple_nonr500ati(const WineD3D_GL_Info *gl_info) {
+ if(!match_apple(gl_info)) return FALSE;
+ if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+ if(gl_info->gl_card == CARD_ATI_RADEON_X1600) return FALSE;
+ return TRUE;
+}
+
+static BOOL match_fglrx(const WineD3D_GL_Info *gl_info) {
+ if(gl_info->gl_vendor != VENDOR_ATI) return FALSE;
+ if(match_apple(gl_info)) return FALSE;
+ if(strstr(gl_info->gl_renderer, "DRI")) return FALSE; /* Filter out Mesa DRI drivers */
+ return TRUE;
+}
+
+static void quirk_arb_constants(WineD3D_GL_Info *gl_info) {
+ TRACE_(d3d_caps)("Using ARB vs constant limit(=%u) for GLSL\n", gl_info->vs_arb_constantsF);
+ gl_info->vs_glsl_constantsF = gl_info->vs_arb_constantsF;
+ TRACE_(d3d_caps)("Using ARB ps constant limit(=%u) for GLSL\n", gl_info->ps_arb_constantsF);
+ gl_info->ps_glsl_constantsF = gl_info->ps_arb_constantsF;
+}
+
+static void quirk_apple_glsl_constants(WineD3D_GL_Info *gl_info) {
+ quirk_arb_constants(gl_info);
+ /* MacOS needs uniforms for relative addressing offsets. This can accumulate to quite a few uniforms.
+ * Beyond that the general uniform isn't optimal, so reserve a number of uniforms. 12 vec4's should
+ * allow 48 different offsets or other helper immediate values
+ */
+ TRACE_(d3d_caps)("Reserving 12 GLSL constants for compiler private use\n");
+ gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 12);
+}
+
+/* fglrx crashes with a very bad kernel panic if GL_POINT_SPRITE_ARB is set to GL_COORD_REPLACE_ARB
+ * on more than one texture unit. This means that the d3d9 visual point size test will cause a
+ * kernel panic on any machine running fglrx 9.3(latest that supports r300 to r500 cards). This
+ * quirk only enables point sprites on the first texture unit. This keeps point sprites working in
+ * most games, but avoids the crash
+ *
+ * A more sophisticated way would be to find all units that need texture coordinates and enable
+ * point sprites for one if only one is found, and software emulate point sprites in drawStridedSlow
+ * if more than one unit needs texture coordinates(This requires software ffp and vertex shaders though)
+ *
+ * Note that disabling the extension entirely does not gain predictability because there is no point
+ * sprite capability flag in d3d, so the potential rendering bugs are the same if we disable the extension.
+ */
+static void quirk_one_point_sprite(WineD3D_GL_Info *gl_info) {
+ if(gl_info->supported[ARB_POINT_SPRITE]) {
+ TRACE("Limiting point sprites to one texture unit\n");
+ gl_info->max_point_sprite_units = 1;
+ }
+}
+
+static void quirk_ati_dx9(WineD3D_GL_Info *gl_info) {
+ quirk_arb_constants(gl_info);
+
+ /* MacOS advertises GL_ARB_texture_non_power_of_two on ATI r500 and earlier cards, although
+ * these cards only support GL_ARB_texture_rectangle(D3DPTEXTURECAPS_NONPOW2CONDITIONAL).
+ * If real NP2 textures are used, the driver falls back to software. We could just remove the
+ * extension and use GL_ARB_texture_rectangle instead, but texture_rectangle is inconventient
+ * due to the non-normalized texture coordinates. Thus set an internal extension flag,
+ * GL_WINE_normalized_texrect, which signals the code that it can use non power of two textures
+ * as per GL_ARB_texture_non_power_of_two, but has to stick to the texture_rectangle limits.
+ *
+ * fglrx doesn't advertise GL_ARB_texture_non_power_of_two, but it advertises opengl 2.0 which
+ * has this extension promoted to core. The extension loading code sets this extension supported
+ * due to that, so this code works on fglrx as well.
+ */
+ TRACE("GL_ARB_texture_non_power_of_two advertised on R500 or earlier card, removing\n");
+ gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+ gl_info->supported[WINE_NORMALIZED_TEXRECT] = TRUE;
+
+ /* fglrx has the same structural issues as the one described in quirk_apple_glsl_constants, although
+ * it is generally more efficient. Reserve just 8 constants
+ */
+ TRACE_(d3d_caps)("Reserving 8 GLSL constants for compiler private use\n");
+ gl_info->reserved_glsl_constants = max(gl_info->reserved_glsl_constants, 8);
+}
+
+static void quirk_no_np2(WineD3D_GL_Info *gl_info) {
+ /* The nVidia GeForceFX series reports OpenGL 2.0 capabilities with the latest drivers versions, but
+ * doesn't explicitly advertise the ARB_tex_npot extension in the GL extension string.
+ * This usually means that ARB_tex_npot is supported in hardware as long as the application is staying
+ * within the limits enforced by the ARB_texture_rectangle extension. This however is not true for the
+ * FX series, which instantly falls back to a slower software path as soon as ARB_tex_npot is used.
+ * We therefore completely remove ARB_tex_npot from the list of supported extensions.
+ *
+ * Note that wine_normalized_texrect can't be used in this case because internally it uses ARB_tex_npot,
+ * triggering the software fallback. There is not much we can do here apart from disabling the
+ * software-emulated extension and reenable ARB_tex_rect (which was previously disabled
+ * in IWineD3DImpl_FillGLCaps).
+ * This fixup removes performance problems on both the FX 5900 and FX 5700 (e.g. for framebuffer
+ * post-processing effects in the game "Max Payne 2").
+ * The behaviour can be verified through a simple test app attached in bugreport #14724.
+ */
+ TRACE("GL_ARB_texture_non_power_of_two advertised through OpenGL 2.0 on NV FX card, removing\n");
+ gl_info->supported[ARB_TEXTURE_NON_POWER_OF_TWO] = FALSE;
+ gl_info->supported[ARB_TEXTURE_RECTANGLE] = TRUE;
+}
+
+static void quirk_texcoord_w(WineD3D_GL_Info *gl_info) {
+ /* The Intel GPUs on MacOS set the .w register of texcoords to 0.0 by default, which causes problems
+ * with fixed function fragment processing. Ideally this flag should be detected with a test shader
+ * and OpenGL feedback mode, but some GL implementations (MacOS ATI at least, probably all MacOS ones)
+ * do not like vertex shaders in feedback mode and return an error, even though it should be valid
+ * according to the spec.
+ *
+ * We don't want to enable this on all cards, as it adds an extra instruction per texcoord used. This
+ * makes the shader slower and eats instruction slots which should be available to the d3d app.
+ *
+ * ATI Radeon HD 2xxx cards on MacOS have the issue. Instead of checking for the buggy cards, blacklist
+ * all radeon cards on Macs and whitelist the good ones. That way we're prepared for the future. If
+ * this workaround is activated on cards that do not need it, it won't break things, just affect
+ * performance negatively.
+ */
+ TRACE("Enabling vertex texture coord fixes in vertex shaders\n");
+ gl_info->set_texcoord_w = TRUE;
+}
+
+struct driver_quirk quirk_table[] = {
+ {
+ match_ati_r300_to_500,
+ quirk_ati_dx9,
+ "ATI GLSL constant and normalized texrect quirk"
+ },
+ /* MacOS advertises more GLSL vertex shader uniforms than supported by the hardware, and if more are
+ * used it falls back to software. While the compiler can detect if the shader uses all declared
+ * uniforms, the optimization fails if the shader uses relative addressing. So any GLSL shader
+ * using relative addressing falls back to software.
+ *
+ * ARB vp gives the correct amount of uniforms, so use it instead of GLSL
+ */
+ {
+ match_apple,
+ quirk_apple_glsl_constants,
+ "Apple GLSL uniform override"
+ },
+ {
+ match_geforce5,
+ quirk_no_np2,
+ "Geforce 5 NP2 disable"
+ },
+ {
+ match_apple_intel,
+ quirk_texcoord_w,
+ "Init texcoord .w for Apple Intel GPU driver"
+ },
+ {
+ match_apple_nonr500ati,
+ quirk_texcoord_w,
+ "Init texcoord .w for Apple ATI >= r600 GPU driver"
+ },
+ {
+ match_fglrx,
+ quirk_one_point_sprite,
+ "Fglrx point sprite crash workaround"
+ }
+};
+
+static void fixup_extensions(WineD3D_GL_Info *gl_info) {
+ unsigned int i;
+
+ for(i = 0; i < (sizeof(quirk_table) / sizeof(*quirk_table)); i++) {
+ if(!quirk_table[i].match(gl_info)) continue;
+ TRACE_(d3d_caps)("Applying driver quirk \"%s\"\n", quirk_table[i].description);
+ quirk_table[i].apply(gl_info);
+ }
+
+ /* Find out if PBOs work as they are supposed to */
+ test_pbo_functionality(gl_info);
+
+ /* Fixup the driver version */
+ for(i = 0; i < (sizeof(driver_version_table) / sizeof(driver_version_table[0])); i++) {
+ if(gl_info->gl_vendor == driver_version_table[i].vendor &&
+ gl_info->gl_card == driver_version_table[i].card) {
+ TRACE_(d3d_caps)("Found card 0x%04x, 0x%04x in driver version DB\n", gl_info->gl_vendor, gl_info->gl_card);
+
+ gl_info->driver_version = MAKEDWORD_VERSION(driver_version_table[i].lopart_hi,
+ driver_version_table[i].lopart_lo);
+ gl_info->driver_version_hipart = MAKEDWORD_VERSION(driver_version_table[i].hipart_hi,
+ driver_version_table[i].hipart_lo);
+ strcpy(gl_info->driver_description, driver_version_table[i].description);
+ break;
}
}
}
-#define PUSH1(att) attribs[nAttribs++] = (att);
-#define GLINFO_LOCATION (Adapters[0].gl_info)
-BOOL InitAdapters(void) {
+static void WINE_GLAPI invalid_func(const void *data)
+{
+ ERR("Invalid vertex attribute function called\n");
+ DebugBreak();
+}
+
+static void WINE_GLAPI invalid_texcoord_func(GLenum unit, const void *data)
+{
+ ERR("Invalid texcoord function called\n");
+ DebugBreak();
+}
+
+/* Helper functions for providing vertex data to opengl. The arrays are initialized based on
+ * the extension detection and are used in drawStridedSlow
+ */
+static void WINE_GLAPI position_d3dcolor(const void *data)
+{
+ DWORD pos = *((const DWORD *)data);
+
+ FIXME("Add a test for fixed function position from d3dcolor type\n");
+ glVertex4s(D3DCOLOR_B_R(pos),
+ D3DCOLOR_B_G(pos),
+ D3DCOLOR_B_B(pos),
+ D3DCOLOR_B_A(pos));
+}
+
+static void WINE_GLAPI position_float4(const void *data)
+{
+ const GLfloat *pos = data;
+
+ if (pos[3] < eps && pos[3] > -eps)
+ glVertex3fv(pos);
+ else {
+ float w = 1.0 / pos[3];
+
+ glVertex4f(pos[0] * w, pos[1] * w, pos[2] * w, w);
+ }
+}
+
+static void WINE_GLAPI diffuse_d3dcolor(const void *data)
+{
+ DWORD diffuseColor = *((const DWORD *)data);
+
+ glColor4ub(D3DCOLOR_B_R(diffuseColor),
+ D3DCOLOR_B_G(diffuseColor),
+ D3DCOLOR_B_B(diffuseColor),
+ D3DCOLOR_B_A(diffuseColor));
+}
+
+static void WINE_GLAPI specular_d3dcolor(const void *data)
+{
+ DWORD specularColor = *((const DWORD *)data);
+ GLbyte d[] = {D3DCOLOR_B_R(specularColor),
+ D3DCOLOR_B_G(specularColor),
+ D3DCOLOR_B_B(specularColor)};
+
+ specular_func_3ubv(d);
+}
+
+static void WINE_GLAPI warn_no_specular_func(const void *data)
+{
+ WARN("GL_EXT_secondary_color not supported\n");
+}
+
+static void fillGLAttribFuncs(const WineD3D_GL_Info *gl_info)
+{
+ position_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glVertex3fv;
+ position_funcs[WINED3D_FFP_EMIT_FLOAT4] = position_float4;
+ position_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = position_d3dcolor;
+ position_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_SHORT4] = (glAttribFunc)glVertex2sv;
+ position_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+ position_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glColor3fv;
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glColor4fv;
+ diffuse_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = diffuse_d3dcolor;
+ diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_UBYTE4N] = (glAttribFunc)glColor4ubv;
+ diffuse_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_SHORT4N] = (glAttribFunc)glColor4sv;
+ diffuse_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_USHORT4N] = (glAttribFunc)glColor4usv;
+ diffuse_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+ diffuse_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+
+ /* No 4 component entry points here */
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
+ if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)GL_EXTCALL(glSecondaryColor3fvEXT);
+ } else {
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT3] = warn_no_specular_func;
+ }
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT4] = invalid_func;
+ if(GL_SUPPORT(EXT_SECONDARY_COLOR)) {
+ specular_func_3ubv = (glAttribFunc)GL_EXTCALL(glSecondaryColor3ubvEXT);
+ specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = specular_d3dcolor;
+ } else {
+ specular_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = warn_no_specular_func;
+ }
+ specular_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+ specular_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+
+ /* Only 3 component entry points here. Test how others behave. Float4 normals are used
+ * by one of our tests, trying to pass it to the pixel shader, which fails on Windows.
+ */
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT1] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT2] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glAttribFunc)glNormal3fv;
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glAttribFunc)glNormal3fv; /* Just ignore the 4th value */
+ normal_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_SHORT2] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_SHORT4] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_func;
+ normal_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_func;
+
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT1] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord1fvARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2fvARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT3] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord3fvARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4fvARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_D3DCOLOR] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2svARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4svARB);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_UBYTE4N] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT2N] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_SHORT4N] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT2N] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_USHORT4N] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_UDEC3] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_DEC3N] = invalid_texcoord_func;
+ if (GL_SUPPORT(NV_HALF_FLOAT))
+ {
+ /* Not supported by ARB_HALF_FLOAT_VERTEX, so check for NV_HALF_FLOAT */
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord2hvNV);
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = (glMultiTexCoordFunc)GL_EXTCALL(glMultiTexCoord4hvNV);
+ } else {
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_2] = invalid_texcoord_func;
+ multi_texcoord_funcs[WINED3D_FFP_EMIT_FLOAT16_4] = invalid_texcoord_func;
+ }
+}
+
+BOOL InitAdapters(IWineD3DImpl *This)
+{
static HMODULE mod_gl;
BOOL ret;
int ps_selected_mode, vs_selected_mode;
/* No need to hold any lock. The calling library makes sure only one thread calls
* wined3d simultaneously
*/
- if(numAdapters > 0) return TRUE;
TRACE("Initializing adapters\n");
mod_gl = LoadLibraryA("opengl32.dll");
if(!mod_gl) {
ERR("Can't load opengl32.dll!\n");
- return FALSE;
+ goto nogl_adapter;
}
#else
#define USE_GL_FUNC(pfn) pfn = (void*)pwglGetProcAddress(#pfn);
/* To bypass the opengl32 thunks load wglGetProcAddress from gdi32 (glXGetProcAddress wrapper) instead of opengl32's */
- mod_gl = GetModuleHandleA("opengl32.dll");
+ mod_gl = GetModuleHandleA("gdi32.dll");
#endif
}
if(!pwglGetProcAddress) {
ERR("Unable to load wglGetProcAddress!\n");
- return FALSE;
+ goto nogl_adapter;
}
/* Dynamically load all GL core functions */
GL_FUNCS_GEN;
#undef USE_GL_FUNC
+ /* Load glFinish and glFlush from opengl32.dll even if we're not using WIN32 opengl
+ * otherwise because we have to use winex11.drv's override
+ */
+#ifdef USE_WIN32_OPENGL
+ glFinish = (void*)GetProcAddress(mod_gl, "glFinish");
+ glFlush = (void*)GetProcAddress(mod_gl, "glFlush");
+#else
+ glFinish = (void*)pwglGetProcAddress("wglFinish");
+ glFlush = (void*)pwglGetProcAddress("wglFlush");
+#endif
+
+ glEnableWINE = glEnable;
+ glDisableWINE = glDisable;
+
/* For now only one default adapter */
{
+ struct WineD3DAdapter *adapter = &This->adapters[0];
+ const WineD3D_GL_Info *gl_info = &adapter->gl_info;
int iPixelFormat;
- int attribs[8];
- int values[8];
- int nAttribs = 0;
int res;
+ int i;
WineD3D_PixelFormat *cfgs;
- int attribute;
DISPLAY_DEVICEW DisplayDevice;
HDC hdc;
TRACE("Initializing default adapter\n");
- Adapters[0].monitorPoint.x = -1;
- Adapters[0].monitorPoint.y = -1;
+ adapter->num = 0;
+ adapter->monitorPoint.x = -1;
+ adapter->monitorPoint.y = -1;
if (!WineD3D_CreateFakeGLContext()) {
ERR("Failed to get a gl context for default adapter\n");
- HeapFree(GetProcessHeap(), 0, Adapters);
WineD3D_ReleaseFakeGLContext();
- return FALSE;
+ goto nogl_adapter;
}
- ret = IWineD3DImpl_FillGLCaps(&Adapters[0].gl_info);
+ ret = IWineD3DImpl_FillGLCaps(&adapter->gl_info);
if(!ret) {
ERR("Failed to initialize gl caps for default adapter\n");
- HeapFree(GetProcessHeap(), 0, Adapters);
WineD3D_ReleaseFakeGLContext();
- return FALSE;
+ goto nogl_adapter;
}
- ret = initPixelFormats(&Adapters[0].gl_info);
+ ret = initPixelFormats(&adapter->gl_info);
if(!ret) {
ERR("Failed to init gl formats\n");
- HeapFree(GetProcessHeap(), 0, Adapters);
WineD3D_ReleaseFakeGLContext();
- return FALSE;
+ goto nogl_adapter;
}
hdc = pwglGetCurrentDC();
if(!hdc) {
ERR("Failed to get gl HDC\n");
- HeapFree(GetProcessHeap(), 0, Adapters);
WineD3D_ReleaseFakeGLContext();
- return FALSE;
+ goto nogl_adapter;
}
- Adapters[0].driver = "Display";
- Adapters[0].description = "Direct3D HAL";
+ adapter->driver = "Display";
+ adapter->description = "Direct3D HAL";
/* Use the VideoRamSize registry setting when set */
if(wined3d_settings.emulated_textureram)
- Adapters[0].TextureRam = wined3d_settings.emulated_textureram;
+ adapter->TextureRam = wined3d_settings.emulated_textureram;
else
- Adapters[0].TextureRam = Adapters[0].gl_info.vidmem;
- Adapters[0].UsedTextureRam = 0;
- TRACE("Emulating %dMB of texture ram\n", Adapters[0].TextureRam/(1024*1024));
+ adapter->TextureRam = adapter->gl_info.vidmem;
+ adapter->UsedTextureRam = 0;
+ TRACE("Emulating %dMB of texture ram\n", adapter->TextureRam/(1024*1024));
/* Initialize the Adapter's DeviceName which is required for ChangeDisplaySettings and friends */
DisplayDevice.cb = sizeof(DisplayDevice);
EnumDisplayDevicesW(NULL, 0 /* Adapter 0 = iDevNum 0 */, &DisplayDevice, 0);
TRACE("DeviceName: %s\n", debugstr_w(DisplayDevice.DeviceName));
- strcpyW(Adapters[0].DeviceName, DisplayDevice.DeviceName);
+ strcpyW(adapter->DeviceName, DisplayDevice.DeviceName);
+
+ if(GL_SUPPORT(WGL_ARB_PIXEL_FORMAT))
+ {
+ int attribute;
+ int attribs[10];
+ int values[10];
+ int nAttribs = 0;
+
+ attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
+ GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &adapter->nCfgs));
+
+ adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, adapter->nCfgs *sizeof(WineD3D_PixelFormat));
+ cfgs = adapter->cfgs;
+ attribs[nAttribs++] = WGL_RED_BITS_ARB;
+ attribs[nAttribs++] = WGL_GREEN_BITS_ARB;
+ attribs[nAttribs++] = WGL_BLUE_BITS_ARB;
+ attribs[nAttribs++] = WGL_ALPHA_BITS_ARB;
+ attribs[nAttribs++] = WGL_DEPTH_BITS_ARB;
+ attribs[nAttribs++] = WGL_STENCIL_BITS_ARB;
+ attribs[nAttribs++] = WGL_DRAW_TO_WINDOW_ARB;
+ attribs[nAttribs++] = WGL_PIXEL_TYPE_ARB;
+ attribs[nAttribs++] = WGL_DOUBLE_BUFFER_ARB;
+ attribs[nAttribs++] = WGL_AUX_BUFFERS_ARB;
+
+ for (iPixelFormat=1; iPixelFormat <= adapter->nCfgs; ++iPixelFormat)
+ {
+ res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
- attribute = WGL_NUMBER_PIXEL_FORMATS_ARB;
- GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, 0, 0, 1, &attribute, &Adapters[0].nCfgs));
+ if(!res)
+ continue;
- Adapters[0].cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Adapters[0].nCfgs *sizeof(WineD3D_PixelFormat));
- cfgs = Adapters[0].cfgs;
- PUSH1(WGL_RED_BITS_ARB)
- PUSH1(WGL_GREEN_BITS_ARB)
- PUSH1(WGL_BLUE_BITS_ARB)
- PUSH1(WGL_ALPHA_BITS_ARB)
- PUSH1(WGL_DEPTH_BITS_ARB)
- PUSH1(WGL_STENCIL_BITS_ARB)
+ /* Cache the pixel format */
+ cfgs->iPixelFormat = iPixelFormat;
+ cfgs->redSize = values[0];
+ cfgs->greenSize = values[1];
+ cfgs->blueSize = values[2];
+ cfgs->alphaSize = values[3];
+ cfgs->depthSize = values[4];
+ cfgs->stencilSize = values[5];
+ cfgs->windowDrawable = values[6];
+ cfgs->iPixelType = values[7];
+ cfgs->doubleBuffer = values[8];
+ cfgs->auxBuffers = values[9];
+
+ cfgs->pbufferDrawable = FALSE;
+ /* Check for pbuffer support when it is around as wglGetPixelFormatAttribiv fails for unknown attributes. */
+ if(GL_SUPPORT(WGL_ARB_PBUFFER)) {
+ int attrib = WGL_DRAW_TO_PBUFFER_ARB;
+ int value;
+ if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 1, &attrib, &value)))
+ cfgs->pbufferDrawable = value;
+ }
- for(iPixelFormat=1; iPixelFormat<=Adapters[0].nCfgs; iPixelFormat++) {
- res = GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, nAttribs, attribs, values));
+ cfgs->numSamples = 0;
+ /* Check multisample support */
+ if(GL_SUPPORT(ARB_MULTISAMPLE)) {
+ int attrib[2] = {WGL_SAMPLE_BUFFERS_ARB, WGL_SAMPLES_ARB};
+ int value[2];
+ if(GL_EXTCALL(wglGetPixelFormatAttribivARB(hdc, iPixelFormat, 0, 2, attrib, value))) {
+ /* value[0] = WGL_SAMPLE_BUFFERS_ARB which tells whether multisampling is supported.
+ * value[1] = number of multi sample buffers*/
+ if(value[0])
+ cfgs->numSamples = value[1];
+ }
+ }
- if(!res)
- continue;
+ TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
+ cfgs++;
+ }
+ }
+ else
+ {
+ int nCfgs = DescribePixelFormat(hdc, 0, 0, 0);
+ adapter->cfgs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nCfgs*sizeof(WineD3D_PixelFormat));
+ adapter->nCfgs = 0; /* We won't accept all formats e.g. software accelerated ones will be skipped */
+
+ cfgs = adapter->cfgs;
+ for(iPixelFormat=1; iPixelFormat<=nCfgs; iPixelFormat++)
+ {
+ PIXELFORMATDESCRIPTOR ppfd;
+
+ res = DescribePixelFormat(hdc, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &ppfd);
+ if(!res)
+ continue;
+
+ /* We only want HW acceleration using an OpenGL ICD driver.
+ * PFD_GENERIC_FORMAT = slow opengl 1.1 gdi software rendering
+ * PFD_GENERIC_ACCELERATED = partial hw acceleration using a MCD driver (e.g. 3dfx minigl)
+ */
+ if(ppfd.dwFlags & (PFD_GENERIC_FORMAT | PFD_GENERIC_ACCELERATED))
+ {
+ TRACE("Skipping iPixelFormat=%d because it isn't ICD accelerated\n", iPixelFormat);
+ continue;
+ }
+
+ cfgs->iPixelFormat = iPixelFormat;
+ cfgs->redSize = ppfd.cRedBits;
+ cfgs->greenSize = ppfd.cGreenBits;
+ cfgs->blueSize = ppfd.cBlueBits;
+ cfgs->alphaSize = ppfd.cAlphaBits;
+ cfgs->depthSize = ppfd.cDepthBits;
+ cfgs->stencilSize = ppfd.cStencilBits;
+ cfgs->pbufferDrawable = 0;
+ cfgs->windowDrawable = (ppfd.dwFlags & PFD_DRAW_TO_WINDOW) ? 1 : 0;
+ cfgs->iPixelType = (ppfd.iPixelType == PFD_TYPE_RGBA) ? WGL_TYPE_RGBA_ARB : WGL_TYPE_COLORINDEX_ARB;
+ cfgs->doubleBuffer = (ppfd.dwFlags & PFD_DOUBLEBUFFER) ? 1 : 0;
+ cfgs->auxBuffers = ppfd.cAuxBuffers;
+ cfgs->numSamples = 0;
+
+ TRACE("iPixelFormat=%d, iPixelType=%#x, doubleBuffer=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d, windowDrawable=%d, pbufferDrawable=%d\n", cfgs->iPixelFormat, cfgs->iPixelType, cfgs->doubleBuffer, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize, cfgs->windowDrawable, cfgs->pbufferDrawable);
+ cfgs++;
+ adapter->nCfgs++;
+ }
+
+ /* Yikes we haven't found any suitable formats. This should only happen in case of GDI software rendering which we can't use anyway as its 3D functionality is very, very limited */
+ if(!adapter->nCfgs)
+ {
+ ERR("Disabling Direct3D because no hardware accelerated pixel formats have been found!\n");
- /* Cache the pixel format */
- cfgs->iPixelFormat = iPixelFormat;
- cfgs->redSize = values[0];
- cfgs->greenSize = values[1];
- cfgs->blueSize = values[2];
- cfgs->alphaSize = values[3];
- cfgs->depthSize = values[4];
- cfgs->stencilSize = values[5];
+ WineD3D_ReleaseFakeGLContext();
+ HeapFree(GetProcessHeap(), 0, adapter->cfgs);
+ goto nogl_adapter;
+ }
+ }
- TRACE("iPixelFormat=%d, RGBA=%d/%d/%d/%d, depth=%d, stencil=%d\n", cfgs->iPixelFormat, cfgs->redSize, cfgs->greenSize, cfgs->blueSize, cfgs->alphaSize, cfgs->depthSize, cfgs->stencilSize);
- cfgs++;
+ /* D16, D24X8 and D24S8 are common depth / depth+stencil formats. All drivers support them though this doesn't
+ * mean that the format is offered in hardware. For instance Geforce8 cards don't have offer D16 in hardware
+ * but just fake it using D24(X8?) which is fine. D3D also allows that.
+ * Some display drivers (i915 on Linux) only report mixed depth+stencil formats like D24S8. MSDN clearly mentions
+ * that only on lockable formats (e.g. D16_locked) the bit order is guaranteed and that on other formats the
+ * driver is allowed to consume more bits EXCEPT for stencil bits.
+ *
+ * Mark an adapter with this broken stencil behavior.
+ */
+ adapter->brokenStencil = TRUE;
+ for (i = 0, cfgs = adapter->cfgs; i < adapter->nCfgs; ++i)
+ {
+ /* Nearly all drivers offer depth formats without stencil, only on i915 this if-statement won't be entered. */
+ if(cfgs[i].depthSize && !cfgs[i].stencilSize) {
+ adapter->brokenStencil = FALSE;
+ break;
+ }
}
- WineD3D_ReleaseFakeGLContext();
- fixup_extensions(&Adapters[0].gl_info);
+ fixup_extensions(&adapter->gl_info);
+ add_gl_compat_wrappers(&adapter->gl_info);
- select_shader_mode(&Adapters[0].gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
- select_shader_max_constants(ps_selected_mode, vs_selected_mode, &Adapters[0].gl_info);
+ WineD3D_ReleaseFakeGLContext();
+ select_shader_mode(&adapter->gl_info, WINED3DDEVTYPE_HAL, &ps_selected_mode, &vs_selected_mode);
+ select_shader_max_constants(ps_selected_mode, vs_selected_mode, &adapter->gl_info);
+ fillGLAttribFuncs(&adapter->gl_info);
+ adapter->opengl = TRUE;
}
- numAdapters = 1;
- TRACE("%d adapters successfully initialized\n", numAdapters);
+ This->adapter_count = 1;
+ TRACE("%u adapters successfully initialized\n", This->adapter_count);
return TRUE;
+
+nogl_adapter:
+ /* Initialize an adapter for ddraw-only memory counting */
+ memset(This->adapters, 0, sizeof(This->adapters));
+ This->adapters[0].num = 0;
+ This->adapters[0].opengl = FALSE;
+ This->adapters[0].monitorPoint.x = -1;
+ This->adapters[0].monitorPoint.y = -1;
+
+ This->adapters[0].driver = "Display";
+ This->adapters[0].description = "WineD3D DirectDraw Emulation";
+ if(wined3d_settings.emulated_textureram) {
+ This->adapters[0].TextureRam = wined3d_settings.emulated_textureram;
+ } else {
+ This->adapters[0].TextureRam = 8 * 1024 * 1024; /* This is plenty for a DDraw-only card */
+ }
+
+ initPixelFormatsNoGL(&This->adapters[0].gl_info);
+
+ This->adapter_count = 1;
+ return FALSE;
}
-#undef PUSH1
-#undef GLINFO_LOCATION
/**********************************************************
* IWineD3D VTbl follows