windowsccodecs: Implement DdsDecoder_Dds_GetParameters().

Signed-off-by: Ziqing Hui <zhui@codeweavers.com>
Signed-off-by: Vincent Povirk <vincent@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Ziqing Hui 2020-05-12 10:25:22 +08:00 committed by Alexandre Julliard
parent a9c70877f3
commit d622b134dd
2 changed files with 108 additions and 7 deletions

View File

@ -48,6 +48,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
#define DDPF_LUMINANCE 0x00020000
#define DDPF_BUMPDUDV 0x00080000
#define DDSCAPS2_CUBEMAP 0x00000200
#define DDSCAPS2_VOLUME 0x00200000
#define DDS_DIMENSION_TEXTURE1D 2
#define DDS_DIMENSION_TEXTURE2D 3
#define DDS_DIMENSION_TEXTURE3D 4
#define DDS_RESOURCE_MISC_TEXTURECUBE 0x00000004
typedef struct {
DWORD size;
DWORD flags;
@ -107,6 +116,65 @@ static inline BOOL has_extended_header(DDS_HEADER *header)
(header->ddspf.fourCC == MAKEFOURCC('D', 'X', '1', '0'));
}
static WICDdsDimension get_dimension(DDS_HEADER *header, DDS_HEADER_DXT10 *header_dxt10)
{
if (header_dxt10) {
if (header_dxt10->miscFlag & DDS_RESOURCE_MISC_TEXTURECUBE) return WICDdsTextureCube;
switch (header_dxt10->resourceDimension)
{
case DDS_DIMENSION_TEXTURE1D: return WICDdsTexture1D;
case DDS_DIMENSION_TEXTURE2D: return WICDdsTexture2D;
case DDS_DIMENSION_TEXTURE3D: return WICDdsTexture3D;
default: return WICDdsTexture2D;
}
} else {
if (header->caps2 & DDSCAPS2_CUBEMAP) {
return WICDdsTextureCube;
} else if (header->caps2 & DDSCAPS2_VOLUME) {
return WICDdsTexture3D;
} else {
return WICDdsTexture2D;
}
}
}
static DXGI_FORMAT get_format_from_fourcc(DWORD fourcc)
{
switch (fourcc)
{
case MAKEFOURCC('D', 'X', 'T', '1'):
return DXGI_FORMAT_BC1_UNORM;
case MAKEFOURCC('D', 'X', 'T', '2'):
case MAKEFOURCC('D', 'X', 'T', '3'):
return DXGI_FORMAT_BC2_UNORM;
case MAKEFOURCC('D', 'X', 'T', '4'):
case MAKEFOURCC('D', 'X', 'T', '5'):
return DXGI_FORMAT_BC3_UNORM;
case MAKEFOURCC('D', 'X', '1', '0'):
/* format is indicated in extended header */
return DXGI_FORMAT_UNKNOWN;
default:
/* there are DDS files where fourCC is set directly to DXGI_FORMAT enumeration value */
return fourcc;
}
}
static WICDdsAlphaMode get_alpha_mode_from_fourcc(DWORD fourcc)
{
switch (fourcc)
{
case MAKEFOURCC('D', 'X', 'T', '1'):
case MAKEFOURCC('D', 'X', 'T', '2'):
case MAKEFOURCC('D', 'X', 'T', '4'):
return WICDdsAlphaModePremultiplied;
case MAKEFOURCC('D', 'X', 'T', '3'):
case MAKEFOURCC('D', 'X', 'T', '5'):
return WICDdsAlphaModeStraight;
default:
return WICDdsAlphaModeUnknown;
}
}
static inline DdsDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
{
return CONTAINING_RECORD(iface, DdsDecoder, IWICBitmapDecoder_iface);
@ -587,9 +655,47 @@ static ULONG WINAPI DdsDecoder_Dds_Release(IWICDdsDecoder *iface)
static HRESULT WINAPI DdsDecoder_Dds_GetParameters(IWICDdsDecoder *iface,
WICDdsParameters *parameters)
{
TRACE("(%p,%p): Stub.\n", iface, parameters);
DdsDecoder *This = impl_from_IWICDdsDecoder(iface);
HRESULT hr;
return E_NOTIMPL;
if (!parameters) return E_INVALIDARG;
EnterCriticalSection(&This->lock);
if (!This->initialized) {
hr = WINCODEC_ERR_WRONGSTATE;
goto end;
}
parameters->Width = This->header.width;
parameters->Height = This->header.height;
parameters->Depth = 1;
parameters->MipLevels = 1;
parameters->ArraySize = 1;
if (This->header.depth) parameters->Depth = This->header.depth;
if (This->header.mipMapCount) parameters->MipLevels = This->header.mipMapCount;
if (has_extended_header(&This->header)) {
if (This->header_dxt10.arraySize) parameters->ArraySize = This->header_dxt10.arraySize;
parameters->DxgiFormat = This->header_dxt10.dxgiFormat;
parameters->Dimension = get_dimension(NULL, &This->header_dxt10);
parameters->AlphaMode = This->header_dxt10.miscFlags2 & 0x00000008;
} else {
parameters->DxgiFormat = get_format_from_fourcc(This->header.ddspf.fourCC);
parameters->Dimension = get_dimension(&This->header, NULL);
parameters->AlphaMode = get_alpha_mode_from_fourcc(This->header.ddspf.fourCC);
}
TRACE("(%p) -> (%dx%d depth=%d mipLevels=%d arraySize=%d dxgiFormat=0x%x dimension=0x%x alphaMode=0x%x)\n",
iface, parameters->Width, parameters->Height, parameters->Depth, parameters->MipLevels,
parameters->ArraySize, parameters->DxgiFormat, parameters->Dimension, parameters->AlphaMode);
hr = S_OK;
end:
LeaveCriticalSection(&This->lock);
return hr;
}
static HRESULT WINAPI DdsDecoder_Dds_GetFrame(IWICDdsDecoder *iface,

View File

@ -320,12 +320,10 @@ static void test_dds_decoder_image_parameters(void)
hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL);
ok (hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr);
todo_wine {
hr = IWICDdsDecoder_GetParameters(dds_decoder, &parameters);
ok(hr == WINCODEC_ERR_WRONGSTATE, "%d: Expected hr=WINCODEC_ERR_WRONGSTATE, got %x\n", i, hr);
hr = IWICDdsDecoder_GetParameters(dds_decoder, NULL);
ok(hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr);
};
hr = init_decoder(decoder, stream, S_OK, -1);
if (hr != S_OK) goto next;
@ -339,8 +337,6 @@ static void test_dds_decoder_image_parameters(void)
hr = IWICBitmapDecoder_GetFrameCount(decoder, NULL);
ok (hr == E_INVALIDARG, "%d: Expected hr=S_OK, got %x\n", i, hr);
todo_wine {
hr = IWICDdsDecoder_GetParameters(dds_decoder, &parameters);
ok (hr == S_OK, "%d: GetParameters failed, hr=%x\n", i, hr);
if (hr == S_OK) {
@ -363,7 +359,6 @@ static void test_dds_decoder_image_parameters(void)
}
hr = IWICDdsDecoder_GetParameters(dds_decoder, NULL);
ok (hr == E_INVALIDARG, "%d: Expected hr=E_INVALIDARG, got %x\n", i, hr);
};
next:
if (decoder) IWICBitmapDecoder_Release(decoder);