wined3d: Ask the ffp/shader/blit implementation about format support.

If a format is not supported natively by opengl, a shader may be able
to convert it. Up to now, CheckDeviceFormat had magic knowldge which
GL extensions lead to which supported format. This patch adds
functions that allow CheckDeviceFormat to ask the actual
implementation for its capabilities.
This commit is contained in:
Stefan Dösinger 2008-08-07 14:51:35 -05:00 committed by Alexandre Julliard
parent 438b6bd4c3
commit bfe7067973
10 changed files with 182 additions and 81 deletions

View File

@ -2180,6 +2180,23 @@ static void shader_arb_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info
}
}
static BOOL shader_arb_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt));
switch(fmt) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_Q8W8V8U8:
case WINED3DFMT_ATI2N:
TRACE("[OK]\n");
return TRUE;
default:
TRACE("[FAILED\n");
return FALSE;
}
}
const shader_backend_t arb_program_shader_backend = {
shader_arb_select,
shader_arb_select_depth_blt,
@ -2194,6 +2211,7 @@ const shader_backend_t arb_program_shader_backend = {
shader_arb_generate_pshader,
shader_arb_generate_vshader,
shader_arb_get_caps,
shader_arb_conv_supported,
};
/* ARB_fragment_program fixed function pipeline replacement definitions */
@ -2961,5 +2979,6 @@ const struct fragment_pipeline arbfp_fragment_pipeline = {
arbfp_get_caps,
arbfp_alloc,
arbfp_free,
shader_arb_conv_supported,
arbfp_fragmentstate_template
};

View File

@ -1063,10 +1063,24 @@ static void atifs_free(IWineD3DDevice *iface) {
}
#undef GLINFO_LOCATION
static BOOL atifs_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt));
switch(fmt) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
TRACE("[OK]\n");
return TRUE;
default:
TRACE("[FAILED\n");
return FALSE;
}
}
const struct fragment_pipeline atifs_fragment_pipeline = {
atifs_enable,
atifs_get_caps,
atifs_alloc,
atifs_free,
atifs_conv_supported,
atifs_fragmentstate_template
};

View File

@ -1113,8 +1113,23 @@ static void shader_none_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_inf
pCaps->PixelShaderVersion = 0;
pCaps->PixelShader1xMaxValue = 0.0;
}
#undef GLINFO_LOCATION
static BOOL shader_none_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s", debug_d3dformat(fmt));
switch(fmt) {
/* Faked to make some apps happy. */
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_Q8W8V8U8:
TRACE("[OK]\n");
return TRUE;
default:
TRACE("[FAILED]\n");
return FALSE;
}
}
const shader_backend_t none_shader_backend = {
shader_none_select,
@ -1130,6 +1145,7 @@ const shader_backend_t none_shader_backend = {
shader_none_generate_pshader,
shader_none_generate_vshader,
shader_none_get_caps,
shader_none_conv_supported
};
/* *******************************************

View File

@ -149,6 +149,9 @@ 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);
static const struct fragment_pipeline *select_fragment_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
static const shader_backend_t *select_shader_backend(UINT Adapter, WINED3DDEVTYPE DeviceType);
static const struct blit_shader *select_blit_implementation(UINT Adapter, WINED3DDEVTYPE DeviceType);
/* lookup tables */
int minLookup[MAX_LOOKUPS];
@ -1960,46 +1963,40 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceType(IWineD3D *iface, UINT Adapter
#define GLINFO_LOCATION Adapters[Adapter].gl_info
/* Check if we support bumpmapping for a format */
static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
static BOOL CheckBumpMapCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
{
/* TODO: Check this in the fixed function pipeline backend */
if(GL_SUPPORT(NV_REGISTER_COMBINERS) && GL_SUPPORT(NV_TEXTURE_SHADER2)) {
switch (CheckFormat) {
case WINED3DFMT_V8U8:
const struct fragment_pipeline *fp;
const GlPixelFormatDesc *glDesc;
switch(CheckFormat) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_Q8W8V8U8:
getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
/* We have a GL extension giving native support */
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
/* TODO: Other bump map formats */
default:
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
}
if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP) || GL_SUPPORT(ATI_FRAGMENT_SHADER)) {
switch (CheckFormat) {
case WINED3DFMT_V8U8:
}
/* No native support: Ask the fixed function pipeline implementation if it
* can deal with the conversion
*/
fp = select_fragment_implementation(Adapter, DeviceType);
if(fp->conv_supported(CheckFormat)) {
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
default:
} else {
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
}
default:
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
if(GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
switch (CheckFormat) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_Q8W8V8U8:
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
default:
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
}
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
/* Check if the given DisplayFormat + DepthStencilFormat combination is valid for the Adapter */
@ -2186,8 +2183,12 @@ static BOOL CheckWrapAndMipCapability(UINT Adapter, WINED3DFORMAT CheckFormat) {
}
/* Check if a texture format is supported on the given adapter */
static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
static BOOL CheckTextureCapability(UINT Adapter, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat)
{
const shader_backend_t *shader_backend;
const struct fragment_pipeline *fp;
const GlPixelFormatDesc *glDesc;
switch (CheckFormat) {
/*****
@ -2247,53 +2248,33 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
/*****
* 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:
if(GL_SUPPORT(NV_TEXTURE_SHADER) || GL_SUPPORT(ATI_ENVMAP_BUMPMAP) ||
GL_SUPPORT(ATI_FRAGMENT_SHADER)) {
return TRUE;
}
if(GL_SUPPORT(ARB_FRAGMENT_SHADER) || GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
/* Shader emulated */
return TRUE;
}
TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\n");
return FALSE;
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_L6V5U5:
if(GL_SUPPORT(ARB_FRAGMENT_SHADER) || GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
/* Shader emulated */
return TRUE;
}
WARN_(d3d_caps)("[FAILED]\n");
return FALSE;
case WINED3DFMT_Q8W8V8U8:
case WINED3DFMT_V16U16:
if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
WARN_(d3d_caps)("[Not supported, but pretended to do]\n");
return TRUE;
}
if(GL_SUPPORT(ARB_FRAGMENT_SHADER) || GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
/* Shader emulated */
return TRUE;
}
TRACE_(d3d_caps)("[FAILED] - No converted formats on volumes\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 FALSE;
getFormatDescEntry(CheckFormat, &GLINFO_LOCATION, &glDesc);
if(glDesc->conversion_group == WINED3DFMT_UNKNOWN) {
/* We have a GL extension giving native support */
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
}
/* No native support: Ask the fixed function pipeline implementation if it
* can deal with the conversion
*/
shader_backend = select_shader_backend(Adapter, DeviceType);
if(shader_backend->shader_conv_supported(CheckFormat)) {
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
} else {
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
}
case WINED3DFMT_DXT1:
case WINED3DFMT_DXT2:
@ -2394,6 +2375,14 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
/* 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_conv_supported(CheckFormat) &&
fp->conv_supported(CheckFormat)) {
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
}
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
}
@ -2410,12 +2399,21 @@ static BOOL CheckTextureCapability(UINT Adapter, WINED3DFORMAT CheckFormat)
return FALSE;
}
static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DFORMAT CheckFormat) {
static BOOL CheckSurfaceCapability(UINT Adapter, WINED3DFORMAT AdapterFormat, WINED3DDEVTYPE DeviceType, WINED3DFORMAT CheckFormat) {
const struct blit_shader *blitter;
/* All format that are supported for textures are supported for surfaces as well */
if(CheckTextureCapability(Adapter, CheckFormat)) return TRUE;
if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) return TRUE;
/* All depth stencil formats are supported on surfaces */
if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) 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->conv_supported(CheckFormat)) {
TRACE_(d3d_caps)("[OK]\n");
return TRUE;
}
/* Reject other formats */
TRACE_(d3d_caps)("[FAILED]\n");
return FALSE;
@ -2474,7 +2472,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
*/
if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
/* Check if the texture format is around */
if(CheckTextureCapability(Adapter, CheckFormat)) {
if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
/* Check for automatic mipmap generation support */
if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
@ -2576,7 +2574,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
* - D3DUSAGE_RENDERTARGET
*/
if(CheckSurfaceCapability(Adapter, AdapterFormat, CheckFormat)) {
if(CheckSurfaceCapability(Adapter, AdapterFormat, DeviceType, CheckFormat)) {
if(Usage & WINED3DUSAGE_DEPTHSTENCIL) {
if(CheckDepthStencilCapability(Adapter, AdapterFormat, CheckFormat)) {
UsageCaps |= WINED3DUSAGE_DEPTHSTENCIL;
@ -2623,7 +2621,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
*/
/* Check if the texture format is around */
if(CheckTextureCapability(Adapter, CheckFormat)) {
if(CheckTextureCapability(Adapter, DeviceType, CheckFormat)) {
if(Usage & WINED3DUSAGE_AUTOGENMIPMAP) {
/* Check for automatic mipmap generation support */
if(GL_SUPPORT(SGIS_GENERATE_MIPMAP)) {
@ -2663,7 +2661,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
/* Check QUERY_LEGACYBUMPMAP support */
if(Usage & WINED3DUSAGE_QUERY_LEGACYBUMPMAP) {
if(CheckBumpMapCapability(Adapter, CheckFormat)) {
if(CheckBumpMapCapability(Adapter, DeviceType, CheckFormat)) {
UsageCaps |= WINED3DUSAGE_QUERY_LEGACYBUMPMAP;
} else {
TRACE_(d3d_caps)("[FAILED] - No legacy bumpmap support\n");
@ -2746,7 +2744,7 @@ static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapt
/* Check volume texture and volume usage caps */
if(GL_SUPPORT(EXT_TEXTURE3D)) {
if(CheckTextureCapability(Adapter, CheckFormat) == FALSE) {
if(CheckTextureCapability(Adapter, DeviceType, CheckFormat) == FALSE) {
TRACE_(d3d_caps)("[FAILED] - Format not supported\n");
return WINED3DERR_NOTAVAILABLE;
}

View File

@ -3731,6 +3731,23 @@ static void shader_glsl_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_inf
TRACE_(d3d_caps)("Hardware pixel shader version %d.%d enabled (GLSL)\n", (pCaps->PixelShaderVersion >> 8) & 0xff, pCaps->PixelShaderVersion & 0xff);
}
static BOOL shader_glsl_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s:", debug_d3dformat(fmt));
switch(fmt) {
case WINED3DFMT_V8U8:
case WINED3DFMT_V16U16:
case WINED3DFMT_X8L8V8U8:
case WINED3DFMT_L6V5U5:
case WINED3DFMT_Q8W8V8U8:
case WINED3DFMT_ATI2N:
TRACE("[OK]\n");
return TRUE;
default:
TRACE("[FAILED\n");
return FALSE;
}
}
const shader_backend_t glsl_shader_backend = {
shader_glsl_select,
shader_glsl_select_depth_blt,
@ -3745,4 +3762,5 @@ const shader_backend_t glsl_shader_backend = {
shader_glsl_generate_pshader,
shader_glsl_generate_vshader,
shader_glsl_get_caps,
shader_glsl_conv_supported,
};

View File

@ -673,6 +673,11 @@ static void nvrc_fragment_free(IWineD3DDevice *iface) {}
* register combiners extension(Pre-GF3).
*/
static BOOL nvts_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s: [FAILED]", debug_d3dformat(fmt));
return FALSE;
}
const struct StateEntryTemplate nvrc_fragmentstate_template[] = {
{ STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 },
{ STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1), { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP), nvrc_colorop }, 0 },
@ -805,6 +810,7 @@ const struct fragment_pipeline nvts_fragment_pipeline = {
nvrc_fragment_get_caps,
nvrc_fragment_alloc,
nvrc_fragment_free,
nvts_conv_supported,
nvrc_fragmentstate_template
};
@ -813,5 +819,6 @@ const struct fragment_pipeline nvrc_fragment_pipeline = {
nvrc_fragment_get_caps,
nvrc_fragment_alloc,
nvrc_fragment_free,
nvts_conv_supported,
nvrc_fragmentstate_template
};

View File

@ -5620,12 +5620,17 @@ static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_in
static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
static void ffp_fragment_free(IWineD3DDevice *iface) {}
static BOOL ffp_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking shader format support for format %s: [FAILED]", debug_d3dformat(fmt));
return FALSE;
}
const struct fragment_pipeline ffp_fragment_pipeline = {
ffp_enable,
ffp_fragment_get_caps,
ffp_fragment_alloc,
ffp_fragment_free,
ffp_conv_supported,
ffp_fragmentstate_template
};

View File

@ -4648,9 +4648,15 @@ static void ffp_blit_unset(IWineD3DDevice *iface) {
}
}
static BOOL ffp_blit_conv_supported(WINED3DFORMAT fmt) {
TRACE("Checking blit format support for format %s: [FAILED]\n", debug_d3dformat(fmt));
return FALSE;
}
const struct blit_shader ffp_blit = {
ffp_blit_alloc,
ffp_blit_free,
ffp_blit_set,
ffp_blit_unset
ffp_blit_unset,
ffp_blit_conv_supported
};

View File

@ -413,6 +413,21 @@ BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
gl_info->gl_formats[dst].conversion_group= WINED3DFMT_ATI2N;
}
if(!GL_SUPPORT(APPLE_YCBCR_422)) {
dst = getFmtIdx(WINED3DFMT_YUY2);
gl_info->gl_formats[dst].glInternal = GL_LUMINANCE_ALPHA;
gl_info->gl_formats[dst].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */
gl_info->gl_formats[dst].glFormat = GL_LUMINANCE_ALPHA;
gl_info->gl_formats[dst].glType = GL_UNSIGNED_BYTE;
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_YUY2;
dst = getFmtIdx(WINED3DFMT_UYVY);
gl_info->gl_formats[dst].glInternal = GL_LUMINANCE_ALPHA;
gl_info->gl_formats[dst].glGammaInternal = GL_LUMINANCE_ALPHA; /* not srgb */
gl_info->gl_formats[dst].glFormat = GL_LUMINANCE_ALPHA;
gl_info->gl_formats[dst].glType = GL_UNSIGNED_BYTE;
gl_info->gl_formats[dst].conversion_group = WINED3DFMT_UYVY;
}
return TRUE;
}

View File

@ -247,6 +247,7 @@ typedef struct {
void (*shader_generate_pshader)(IWineD3DPixelShader *iface, SHADER_BUFFER *buffer);
void (*shader_generate_vshader)(IWineD3DVertexShader *iface, SHADER_BUFFER *buffer);
void (*shader_get_caps)(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct shader_caps *caps);
BOOL (*shader_conv_supported)(WINED3DFORMAT conv);
} shader_backend_t;
extern const shader_backend_t atifs_shader_backend;
@ -556,6 +557,7 @@ struct fragment_pipeline {
void (*get_caps)(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *caps);
HRESULT (*alloc_private)(IWineD3DDevice *iface);
void (*free_private)(IWineD3DDevice *iface);
BOOL (*conv_supported)(WINED3DFORMAT conv);
const struct StateEntryTemplate *states;
};
@ -581,6 +583,7 @@ struct blit_shader {
void (*free_private)(IWineD3DDevice *iface);
HRESULT (*set_shader)(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height);
void (*unset_shader)(IWineD3DDevice *iface);
BOOL (*conv_supported)(WINED3DFORMAT conv);
};
extern const struct blit_shader ffp_blit;