Ziqing Hui : windowsccodecs: Implement DdsDecoder_Dds_GetParameters().

Alexandre Julliard julliard at winehq.org
Wed May 13 16:29:53 CDT 2020


Module: wine
Branch: master
Commit: d622b134dd69f685caf06fcbe28c9f7d5dbde626
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=d622b134dd69f685caf06fcbe28c9f7d5dbde626

Author: Ziqing Hui <zhui at codeweavers.com>
Date:   Tue May 12 10:25:22 2020 +0800

windowsccodecs: Implement DdsDecoder_Dds_GetParameters().

Signed-off-by: Ziqing Hui <zhui at codeweavers.com>
Signed-off-by: Vincent Povirk <vincent at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/windowscodecs/ddsformat.c       | 110 ++++++++++++++++++++++++++++++++++-
 dlls/windowscodecs/tests/ddsformat.c |   5 --
 2 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/dlls/windowscodecs/ddsformat.c b/dlls/windowscodecs/ddsformat.c
index f096f94b6a..de4cd1ea01 100644
--- a/dlls/windowscodecs/ddsformat.c
+++ b/dlls/windowscodecs/ddsformat.c
@@ -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,
diff --git a/dlls/windowscodecs/tests/ddsformat.c b/dlls/windowscodecs/tests/ddsformat.c
index f0814b46ef..209d39f11f 100644
--- a/dlls/windowscodecs/tests/ddsformat.c
+++ b/dlls/windowscodecs/tests/ddsformat.c
@@ -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);




More information about the wine-cvs mailing list