[4/8] d3dx9: Implement D3DXCreateCubeTextureFromFileInMemoryEx.

Józef Kucia joseph.kucia at gmail.com
Wed May 9 16:32:07 CDT 2012


---
 dlls/d3dx9_36/d3dx9_36_private.h |    4 +
 dlls/d3dx9_36/surface.c          |   61 +++++++++++++++++
 dlls/d3dx9_36/tests/surface.c    |   44 ++++++------
 dlls/d3dx9_36/texture.c          |  137 ++++++++++++++++++++++++++++++++++++--
 4 files changed, 217 insertions(+), 29 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h
index a6c4fcd..d258de5 100644
--- a/dlls/d3dx9_36/d3dx9_36_private.h
+++ b/dlls/d3dx9_36/d3dx9_36_private.h
@@ -62,6 +62,10 @@ HRESULT load_resource_into_memory(HMODULE module, HRSRC resinfo, LPVOID *buffer,
 const PixelFormatDesc *get_format_info(D3DFORMAT format) DECLSPEC_HIDDEN;
 const PixelFormatDesc *get_format_info_idx(int idx) DECLSPEC_HIDDEN;
 
+HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data,
+    UINT src_data_size, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key,
+    const D3DXIMAGE_INFO *src_info) DECLSPEC_HIDDEN;
+
 /* debug helpers */
 const char *debug_d3dxparameter_class(D3DXPARAMETER_CLASS c) DECLSPEC_HIDDEN;
 const char *debug_d3dxparameter_type(D3DXPARAMETER_TYPE t) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c
index c842f6c..8a6dc0e 100644
--- a/dlls/d3dx9_36/surface.c
+++ b/dlls/d3dx9_36/surface.c
@@ -95,6 +95,9 @@ static const GUID *d3dformat_to_wic_guid(D3DFORMAT format)
 #define DDS_CAPS2_CUBEMAP_NEGATIVEY 0x2000
 #define DDS_CAPS2_CUBEMAP_POSITIVEZ 0x4000
 #define DDS_CAPS2_CUBEMAP_NEGATIVEZ 0x8000
+#define DDS_CAPS2_CUBEMAP_ALL_FACES ( DDS_CAPS2_CUBEMAP_POSITIVEX | DDS_CAPS2_CUBEMAP_NEGATIVEX \
+                                    | DDS_CAPS2_CUBEMAP_POSITIVEY | DDS_CAPS2_CUBEMAP_NEGATIVEY \
+                                    | DDS_CAPS2_CUBEMAP_POSITIVEZ | DDS_CAPS2_CUBEMAP_NEGATIVEZ )
 #define DDS_CAPS2_VOLUME 0x200000
 
 /* dds_pixel_format.flags */
@@ -372,6 +375,64 @@ static HRESULT get_image_info_from_dds(const void *buffer, UINT length, D3DXIMAG
    return D3D_OK;
 }
 
+HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, UINT src_data_size,
+    const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info)
+{
+    HRESULT hr;
+    int face;
+    int mip_level;
+    UINT size;
+    RECT src_rect;
+    UINT src_pitch;
+    UINT mip_levels;
+    UINT mip_level_size;
+    IDirect3DSurface9 *surface;
+    const struct dds_header *header = src_data;
+    const BYTE *pixels = (BYTE *)(header + 1);
+
+    if (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)
+        return D3DXERR_INVALIDDATA;
+
+    if ((header->caps2 & DDS_CAPS2_CUBEMAP_ALL_FACES) != DDS_CAPS2_CUBEMAP_ALL_FACES)
+    {
+        WARN("Only full cubemaps are supported\n");
+        return D3DXERR_INVALIDDATA;
+    }
+
+    mip_levels = min(src_info->MipLevels, IDirect3DCubeTexture9_GetLevelCount(cube_texture));
+    for (face = D3DCUBEMAP_FACE_POSITIVE_X; face <= D3DCUBEMAP_FACE_NEGATIVE_Z; face++)
+    {
+        size = src_info->Width;
+        for (mip_level = 0; mip_level < mip_levels; mip_level++)
+        {
+            hr = calculate_dds_surface_size(src_info, size, size, &src_pitch, &mip_level_size);
+            if (FAILED(hr)) return hr;
+
+            SetRect(&src_rect, 0, 0, size, size);
+
+            IDirect3DCubeTexture9_GetCubeMapSurface(cube_texture, face, mip_level, &surface);
+            hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, src_info->Format, src_pitch,
+                NULL, &src_rect, filter, color_key);
+            IDirect3DSurface9_Release(surface);
+            if (FAILED(hr)) return hr;
+
+            pixels += mip_level_size;
+            size = max(1, size / 2);
+        }
+
+        /* if texture has fewer mip levels than DDS file, skip excessive mip levels */
+        while (mip_level < src_info->MipLevels)
+        {
+            calculate_dds_surface_size(src_info, size, size, &src_pitch, &mip_level_size);
+            pixels += mip_level_size;
+            size = max(1, size / 2);
+            mip_level++;
+        }
+    }
+
+    return D3D_OK;
+}
+
 /************************************************************
  * D3DXGetImageInfoFromFileInMemory
  *
diff --git a/dlls/d3dx9_36/tests/surface.c b/dlls/d3dx9_36/tests/surface.c
index 32b00bb..ab56593 100644
--- a/dlls/d3dx9_36/tests/surface.c
+++ b/dlls/d3dx9_36/tests/surface.c
@@ -843,36 +843,34 @@ static void test_D3DXCreateCubeTexture(IDirect3DDevice9 *device)
     IDirect3DCubeTexture9 *cube_texture;
     D3DSURFACE_DESC surface_desc;
 
-    todo_wine {
-        hr = D3DXCreateCubeTextureFromFileInMemory(NULL, dds_cube_map, sizeof(dds_cube_map), &cube_texture);
-        ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+    hr = D3DXCreateCubeTextureFromFileInMemory(NULL, dds_cube_map, sizeof(dds_cube_map), &cube_texture);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
 
-        hr = D3DXCreateCubeTextureFromFileInMemory(device, NULL, sizeof(dds_cube_map), &cube_texture);
-        ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+    hr = D3DXCreateCubeTextureFromFileInMemory(device, NULL, sizeof(dds_cube_map), &cube_texture);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
 
-        hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, 0, &cube_texture);
-        ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+    hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, 0, &cube_texture);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
 
-        hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), NULL);
-        ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+    hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), NULL);
+    ok(hr == D3DERR_INVALIDCALL, "D3DXCreateCubeTextureFromFileInMemory returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
 
-        hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), &cube_texture);
-        if(SUCCEEDED(hr)) {
-            levelcount = IDirect3DCubeTexture9_GetLevelCount(cube_texture);
-            ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount);
+    hr = D3DXCreateCubeTextureFromFileInMemory(device, dds_cube_map, sizeof(dds_cube_map), &cube_texture);
+    if(SUCCEEDED(hr)) {
+        levelcount = IDirect3DCubeTexture9_GetLevelCount(cube_texture);
+        todo_wine ok(levelcount == 3, "GetLevelCount returned %u, expected 3\n", levelcount);
 
-            hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
-            ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK);
-            ok(surface_desc.Width == 4, "Got width %u, expected 4\n", surface_desc.Width);
-            ok(surface_desc.Height == 4, "Got height %u, expected 4\n", surface_desc.Height);
+        hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 0, &surface_desc);
+        ok(hr == D3D_OK, "GetLevelDesc returned %#x, expected %#x\n", hr, D3D_OK);
+        ok(surface_desc.Width == 4, "Got width %u, expected 4\n", surface_desc.Width);
+        ok(surface_desc.Height == 4, "Got height %u, expected 4\n", surface_desc.Height);
 
-            hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 3, &surface_desc);
-            ok(hr == D3DERR_INVALIDCALL, "GetLevelDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
+        hr = IDirect3DCubeTexture9_GetLevelDesc(cube_texture, 3, &surface_desc);
+        todo_wine ok(hr == D3DERR_INVALIDCALL, "GetLevelDesc returned %#x, expected %#x\n", hr, D3DERR_INVALIDCALL);
 
-            ref = IDirect3DCubeTexture9_Release(cube_texture);
-            ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref);
-        } else skip("Couldn't create cube texture\n");
-    }
+        ref = IDirect3DCubeTexture9_Release(cube_texture);
+        ok(ref == 0, "Invalid reference count. Got %u, expected 0\n", ref);
+    } else skip("Couldn't create cube texture\n");
 }
 
 static void test_D3DXCreateVolumeTexture(IDirect3DDevice9 *device)
diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c
index 93ac533..a75cc28 100644
--- a/dlls/d3dx9_36/texture.c
+++ b/dlls/d3dx9_36/texture.c
@@ -1078,16 +1078,141 @@ HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
     return D3D_OK;
 }
 
-HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 pDevice, LPCVOID pSrcData, UINT SrcDataSize,
-        UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey,
-        D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture)
+HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
+                                                       const void *src_data,
+                                                       UINT src_data_size,
+                                                       UINT size,
+                                                       UINT mip_levels,
+                                                       DWORD usage,
+                                                       D3DFORMAT format,
+                                                       D3DPOOL pool,
+                                                       DWORD filter,
+                                                       DWORD mip_filter,
+                                                       D3DCOLOR color_key,
+                                                       D3DXIMAGE_INFO *src_info,
+                                                       PALETTEENTRY *palette,
+                                                       IDirect3DCubeTexture9 **cube_texture)
 {
-    FIXME("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): stub\n", pDevice, pSrcData, SrcDataSize, Size, MipLevels,
-            Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture);
+    HRESULT hr;
+    D3DCAPS9 caps;
+    UINT loaded_miplevels;
+    D3DXIMAGE_INFO img_info;
+    BOOL file_size = FALSE;
+    BOOL file_format = FALSE;
+    BOOL file_mip_levels = FALSE;
+    IDirect3DCubeTexture9 *tex, *buftex;
+
+    TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
+        src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
+        color_key, src_info, palette, cube_texture);
+
+    if (!device || !cube_texture || !src_data || !src_data_size)
+        return D3DERR_INVALIDCALL;
 
-    return E_NOTIMPL;
+    hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
+    if (FAILED(hr))
+        return hr;
+
+    if (img_info.ImageFileFormat != D3DXIFF_DDS)
+        return D3DXERR_INVALIDDATA;
+
+    if (img_info.Width != img_info.Height)
+        return D3DXERR_INVALIDDATA;
+
+    if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
+        size = img_info.Width;
+    if (size == D3DX_DEFAULT)
+        size = make_pow2(img_info.Width);
+
+    if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
+        format = img_info.Format;
+
+    if (size == D3DX_FROM_FILE)
+    {
+        file_size = TRUE;
+        size = img_info.Width;
+    }
+
+    if (format == D3DFMT_FROM_FILE)
+    {
+        file_format = TRUE;
+        format = img_info.Format;
+    }
+
+    if (mip_levels == D3DX_FROM_FILE)
+    {
+        file_mip_levels = TRUE;
+        mip_levels = img_info.MipLevels;
+    }
+
+    hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
+    if (FAILED(hr))
+        return hr;
+
+    if ((file_size && size != img_info.Width)
+            || (file_format && format != img_info.Format)
+            || (file_mip_levels && mip_levels != img_info.MipLevels))
+        return D3DERR_NOTAVAILABLE;
+
+    hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
+    if (FAILED(hr))
+        return D3DERR_INVALIDCALL;
+
+    if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
+    {
+        FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
+        mip_levels = img_info.MipLevels;
+    }
+
+    if ((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (pool != D3DPOOL_DEFAULT) && (usage != D3DUSAGE_DYNAMIC))
+    {
+        hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
+        buftex = NULL;
+    }
+    else
+    {
+        hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
+        tex = buftex;
+    }
+    if (FAILED(hr))
+        return hr;
+
+    hr = load_cube_texture_from_dds(tex, src_data, src_data_size, palette, filter, color_key, &img_info);
+    if (FAILED(hr))
+    {
+        IDirect3DCubeTexture9_Release(tex);
+        return hr;
+    }
+
+    loaded_miplevels = min(mip_levels, img_info.MipLevels);
+    hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
+    if (FAILED(hr))
+    {
+        IDirect3DCubeTexture9_Release(tex);
+        return hr;
+    }
+
+    if (buftex)
+    {
+        hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
+        if (FAILED(hr))
+        {
+            IDirect3DCubeTexture9_Release(buftex);
+            return hr;
+        }
+
+        IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
+        IDirect3DCubeTexture9_Release(buftex);
+    }
+
+    if (src_info)
+        *src_info = img_info;
+
+    *cube_texture = tex;
+    return D3D_OK;
 }
 
+
 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
                                               const char *src_filename,
                                               IDirect3DCubeTexture9 **cube_texture)
-- 
1.7.8.6




More information about the wine-patches mailing list