1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

d3dx9: Add support for specifying which mip level to get pixel data from to d3dx_image_get_pixels().

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2024-06-05 11:11:59 -04:00 committed by Alexandre Julliard
parent be746bee64
commit 1215ee0241
4 changed files with 62 additions and 82 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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))