From 1215ee024148952525317cc104ce91e650f21ca3 Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Wed, 5 Jun 2024 11:11:59 -0400 Subject: [PATCH] d3dx9: Add support for specifying which mip level to get pixel data from to d3dx_image_get_pixels(). Signed-off-by: Connor McAdams --- dlls/d3dx9_36/d3dx9_private.h | 4 +- dlls/d3dx9_36/surface.c | 72 +++++++++++++---------------------- dlls/d3dx9_36/tests/texture.c | 20 +++++----- dlls/d3dx9_36/texture.c | 48 ++++++++++++----------- 4 files changed, 62 insertions(+), 82 deletions(-) diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 07b4aff5137..701afffd046 100644 --- a/dlls/d3dx9_36/d3dx9_private.h +++ b/dlls/d3dx9_36/d3dx9_private.h @@ -123,7 +123,7 @@ struct d3dx_image HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t starting_mip_level, uint32_t flags); void d3dx_image_cleanup(struct d3dx_image *image); -HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels); +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels); void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image); struct d3dx_include_from_file @@ -172,8 +172,6 @@ void point_filter_argb_pixels(const BYTE *src, UINT src_row_pitch, UINT src_slic BYTE *dst, UINT dst_row_pitch, UINT dst_slice_pitch, const struct volume *dst_size, const struct pixel_format_desc *dst_format, D3DCOLOR color_key, const PALETTEENTRY *palette); -HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, - const struct d3dx_image *image, unsigned int *loaded_miplevels); HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info); HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *dst_palette, diff --git a/dlls/d3dx9_36/surface.c b/dlls/d3dx9_36/surface.c index 45277e28109..3e0b880eec4 100644 --- a/dlls/d3dx9_36/surface.c +++ b/dlls/d3dx9_36/surface.c @@ -584,42 +584,6 @@ HRESULT load_volume_from_dds(IDirect3DVolume9 *dst_volume, const PALETTEENTRY *d row_pitch, slice_pitch, NULL, src_box, filter, color_key); } -HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const PALETTEENTRY *palette, DWORD filter, D3DCOLOR color_key, - const struct d3dx_image *image, unsigned int *loaded_miplevels) -{ - HRESULT hr; - RECT src_rect; - UINT src_pitch; - UINT mip_level; - UINT mip_levels; - UINT mip_level_size; - IDirect3DSurface9 *surface; - const BYTE *pixels = image->pixels; - struct volume mip_size = image->size; - - mip_levels = min(image->mip_levels, IDirect3DTexture9_GetLevelCount(texture)); - for (mip_level = 0; mip_level < mip_levels; ++mip_level) - { - hr = d3dx_calculate_pixels_size(image->format, mip_size.width, mip_size.height, &src_pitch, &mip_level_size); - if (FAILED(hr)) return hr; - - SetRect(&src_rect, 0, 0, mip_size.width, mip_size.height); - IDirect3DTexture9_GetSurfaceLevel(texture, mip_level, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels, image->format, src_pitch, - NULL, &src_rect, filter, color_key); - IDirect3DSurface9_Release(surface); - if (FAILED(hr)) - return hr; - - pixels += mip_level_size * mip_size.depth; - d3dx_get_next_mip_level_size(&mip_size); - } - - *loaded_miplevels = mip_levels; - - return D3D_OK; -} - HRESULT load_cube_texture_from_dds(IDirect3DCubeTexture9 *cube_texture, const void *src_data, const PALETTEENTRY *palette, DWORD filter, DWORD color_key, const D3DXIMAGE_INFO *src_info) { @@ -1163,19 +1127,37 @@ void d3dx_image_cleanup(struct d3dx_image *image) free(image->palette); } -HRESULT d3dx_image_get_pixels(struct d3dx_image *image, struct d3dx_pixels *pixels) +HRESULT d3dx_image_get_pixels(struct d3dx_image *image, uint32_t mip_level, struct d3dx_pixels *pixels) { - uint32_t row_pitch, slice_pitch; + struct volume mip_level_size = image->size; + const BYTE *pixels_ptr = image->pixels; + uint32_t row_pitch, slice_pitch, i; RECT unaligned_rect; HRESULT hr = S_OK; - hr = d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch); - if (FAILED(hr)) - return hr; + if (mip_level >= image->mip_levels) + { + ERR("Tried to retrieve mip level %u, but image only has %u mip levels.\n", mip_level, image->mip_levels); + return E_FAIL; + } - SetRect(&unaligned_rect, 0, 0, image->size.width, image->size.height); - set_d3dx_pixels(pixels, image->pixels, row_pitch, slice_pitch, image->palette, image->size.width, image->size.height, - image->size.depth, &unaligned_rect); + slice_pitch = row_pitch = 0; + for (i = 0; i < image->mip_levels; i++) + { + hr = d3dx_calculate_pixels_size(image->format, mip_level_size.width, mip_level_size.height, &row_pitch, &slice_pitch); + if (FAILED(hr)) + return hr; + + if (i == mip_level) + break; + + pixels_ptr += slice_pitch * mip_level_size.depth; + d3dx_get_next_mip_level_size(&mip_level_size); + } + + SetRect(&unaligned_rect, 0, 0, mip_level_size.width, mip_level_size.height); + set_d3dx_pixels(pixels, pixels_ptr, row_pitch, slice_pitch, image->palette, mip_level_size.width, + mip_level_size.height, mip_level_size.depth, &unaligned_rect); return D3D_OK; } @@ -1384,7 +1366,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface, else SetRect(&src_rect, 0, 0, img_info.Width, img_info.Height); - hr = d3dx_image_get_pixels(&image, &pixels); + hr = d3dx_image_get_pixels(&image, 0, &pixels); if (FAILED(hr)) goto exit; diff --git a/dlls/d3dx9_36/tests/texture.c b/dlls/d3dx9_36/tests/texture.c index 04dab09c33c..4da8f56f834 100644 --- a/dlls/d3dx9_36/tests/texture.c +++ b/dlls/d3dx9_36/tests/texture.c @@ -2158,7 +2158,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) type = IDirect3DTexture9_GetType(texture); ok(type == D3DRTYPE_TEXTURE, "IDirect3DTexture9_GetType returned %u, expected %u.\n", type, D3DRTYPE_TEXTURE); level_count = IDirect3DBaseTexture9_GetLevelCount((IDirect3DBaseTexture9 *)texture); - todo_wine ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count); + ok(level_count == 3, "Texture has %lu mip levels, 3 expected.\n", level_count); hr = IDirect3DTexture9_GetLevelDesc(texture, 0, &desc); ok(hr == D3D_OK, "IDirect3DTexture9_GetLevelDesc returned %#lx, expected %#lx.\n", hr, D3D_OK); ok(desc.Width == 4, "Width is %u, expected 4.\n", desc.Width); @@ -2192,19 +2192,18 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) */ hr = D3DXCreateTextureFromFileInMemory(device, dds_volume_dxt3_4_4_4, sizeof(dds_volume_dxt3_4_4_4), &texture); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - check_texture_mip_levels(texture, 3, TRUE); + check_texture_mip_levels(texture, 3, FALSE); if (has_2d_dxt3) { struct surface_readback surface_rb; uint32_t mip_level; check_texture_level_desc(texture, 0, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 4, 4, FALSE); - check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, TRUE); - check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, TRUE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, 0, D3DPOOL_MANAGED, 0, 0, 1, 1, FALSE); for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) { const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; - BOOL todo = !!mip_level; uint32_t x, y; IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2213,7 +2212,7 @@ static void test_D3DXCreateTextureFromFileInMemory(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); @@ -2487,16 +2486,15 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) D3DX_DEFAULT, D3DX_DEFAULT, 0, &img_info, NULL, &texture); ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr); - check_texture_mip_levels(texture, 3, TRUE); + check_texture_mip_levels(texture, 3, FALSE); check_image_info(&img_info, 4, 4, 4, 3, D3DFMT_DXT3, D3DRTYPE_VOLUMETEXTURE, D3DXIFF_DDS, FALSE); check_texture_level_desc(texture, 0, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 4, 4, FALSE); - check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, TRUE); - check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE); + check_texture_level_desc(texture, 1, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 2, 2, FALSE); + check_texture_level_desc(texture, 2, D3DFMT_DXT3, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE); for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_dxt3_4_4_4_expected_uncompressed); ++mip_level) { const uint32_t expected_color = dds_volume_dxt3_4_4_4_expected_uncompressed[mip_level]; - BOOL todo = !!mip_level; uint32_t x, y; IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc); @@ -2505,7 +2503,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device) { for (x = 0; x < desc.Width; ++x) { - check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, todo); + check_readback_pixel_4bpp(&surface_rb, x, y, expected_color, FALSE); } } release_surface_readback(&surface_rb); diff --git a/dlls/d3dx9_36/texture.c b/dlls/d3dx9_36/texture.c index f8b4a7795f7..5a68b2dd1c4 100644 --- a/dlls/d3dx9_36/texture.c +++ b/dlls/d3dx9_36/texture.c @@ -567,10 +567,10 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo, PALETTEENTRY *palette, struct IDirect3DTexture9 **texture) { + const struct pixel_format_desc *src_fmt_desc, *dst_fmt_desc; BOOL dynamic_texture, format_specified = FALSE; - unsigned int loaded_miplevels, skip_levels; + uint32_t loaded_miplevels, skip_levels, i; IDirect3DTexture9 *staging_tex, *tex; - IDirect3DSurface9 *surface; struct d3dx_image image; D3DXIMAGE_INFO imginfo; D3DCAPS9 caps; @@ -619,13 +619,6 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi if (colorkey && !format_specified) format = get_alpha_replacement_format(format); - if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE - && D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1) - { - FIXME("Generation of mipmaps for compressed volume textures is not implemented yet.\n"); - miplevels = 1; - } - if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps))) { hr = D3DERR_INVALIDCALL; @@ -652,24 +645,33 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi } TRACE("Texture created correctly. Now loading the texture data into it.\n"); - if (imginfo.ImageFileFormat != D3DXIFF_DDS) + dst_fmt_desc = get_format_info(format); + src_fmt_desc = get_format_info(imginfo.Format); + loaded_miplevels = min(imginfo.MipLevels, IDirect3DTexture9_GetLevelCount(tex)); + for (i = 0; i < loaded_miplevels; i++) { - const RECT src_rect = { 0, 0, imginfo.Width, imginfo.Height }; - struct d3dx_pixels pixels; + struct d3dx_pixels src_pixels, dst_pixels; + D3DSURFACE_DESC dst_surface_desc; + D3DLOCKED_RECT dst_locked_rect; + RECT dst_rect; - hr = d3dx_image_get_pixels(&image, &pixels); + hr = d3dx_image_get_pixels(&image, i, &src_pixels); if (FAILED(hr)) - goto err; + break; - IDirect3DTexture9_GetSurfaceLevel(tex, 0, &surface); - hr = D3DXLoadSurfaceFromMemory(surface, palette, NULL, pixels.data, imginfo.Format, - pixels.row_pitch, pixels.palette, &src_rect, filter, colorkey); - IDirect3DSurface9_Release(surface); - loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(tex), imginfo.MipLevels); - } - else - { - hr = load_texture_from_dds(tex, palette, filter, colorkey, &image, &loaded_miplevels); + hr = IDirect3DTexture9_LockRect(tex, i, &dst_locked_rect, NULL, 0); + if (FAILED(hr)) + break; + + IDirect3DTexture9_GetLevelDesc(tex, i, &dst_surface_desc); + SetRect(&dst_rect, 0, 0, dst_surface_desc.Width, dst_surface_desc.Height); + set_d3dx_pixels(&dst_pixels, dst_locked_rect.pBits, dst_locked_rect.Pitch, 0, palette, + dst_surface_desc.Width, dst_surface_desc.Height, 1, &dst_rect); + + hr = d3dx_load_pixels_from_pixels(&dst_pixels, dst_fmt_desc, &src_pixels, src_fmt_desc, filter, colorkey); + IDirect3DTexture9_UnlockRect(tex, i); + if (FAILED(hr)) + break; } if (FAILED(hr))