mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-30 04:48:36 +00:00
d3dx9: Add support for specifying a starting mip level when initializing a d3dx_image structure.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
8d4024ca7e
commit
86a87b0403
|
@ -120,7 +120,8 @@ struct d3dx_image
|
|||
D3DXIMAGE_FILEFORMAT image_file_format;
|
||||
};
|
||||
|
||||
HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags);
|
||||
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);
|
||||
void d3dximage_info_from_d3dx_image(D3DXIMAGE_INFO *info, struct d3dx_image *image);
|
||||
|
@ -171,9 +172,8 @@ 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 void *src_data, const PALETTEENTRY *palette,
|
||||
DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels,
|
||||
unsigned int *loaded_miplevels);
|
||||
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,
|
||||
|
|
|
@ -437,6 +437,20 @@ static HRESULT d3dformat_to_dds_pixel_format(struct dds_pixel_format *pixel_form
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static void d3dx_get_next_mip_level_size(struct volume *size)
|
||||
{
|
||||
size->width = max(size->width / 2, 1);
|
||||
size->height = max(size->height / 2, 1);
|
||||
size->depth = max(size->depth / 2, 1);
|
||||
}
|
||||
|
||||
static const char *debug_volume(const struct volume *volume)
|
||||
{
|
||||
if (!volume)
|
||||
return "(null)";
|
||||
return wine_dbg_sprintf("(%ux%ux%u)", volume->width, volume->height, volume->depth);
|
||||
}
|
||||
|
||||
static HRESULT d3dx_calculate_pixels_size(D3DFORMAT format, uint32_t width, uint32_t height,
|
||||
uint32_t *pitch, uint32_t *size)
|
||||
{
|
||||
|
@ -570,9 +584,8 @@ 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 void *src_data, const PALETTEENTRY *palette,
|
||||
DWORD filter, D3DCOLOR color_key, const D3DXIMAGE_INFO *src_info, unsigned int skip_levels,
|
||||
unsigned int *loaded_miplevels)
|
||||
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;
|
||||
|
@ -580,49 +593,29 @@ HRESULT load_texture_from_dds(IDirect3DTexture9 *texture, const void *src_data,
|
|||
UINT mip_level;
|
||||
UINT mip_levels;
|
||||
UINT mip_level_size;
|
||||
UINT width, height;
|
||||
IDirect3DSurface9 *surface;
|
||||
const struct dds_header *header = src_data;
|
||||
const BYTE *pixels = (BYTE *)(header + 1);
|
||||
const BYTE *pixels = image->pixels;
|
||||
struct volume mip_size = image->size;
|
||||
|
||||
/* Loading a cube texture as a simple texture is also supported
|
||||
* (only first face texture is taken). Same with volume textures. */
|
||||
if ((src_info->ResourceType != D3DRTYPE_TEXTURE)
|
||||
&& (src_info->ResourceType != D3DRTYPE_CUBETEXTURE)
|
||||
&& (src_info->ResourceType != D3DRTYPE_VOLUMETEXTURE))
|
||||
mip_levels = min(image->mip_levels, IDirect3DTexture9_GetLevelCount(texture));
|
||||
for (mip_level = 0; mip_level < mip_levels; ++mip_level)
|
||||
{
|
||||
WARN("Trying to load a %u resource as a 2D texture, returning failure.\n", src_info->ResourceType);
|
||||
return D3DXERR_INVALIDDATA;
|
||||
}
|
||||
|
||||
width = src_info->Width;
|
||||
height = src_info->Height;
|
||||
mip_levels = min(src_info->MipLevels, IDirect3DTexture9_GetLevelCount(texture));
|
||||
if (src_info->ResourceType == D3DRTYPE_VOLUMETEXTURE)
|
||||
mip_levels = 1;
|
||||
for (mip_level = 0; mip_level < mip_levels + skip_levels; ++mip_level)
|
||||
{
|
||||
hr = d3dx_calculate_pixels_size(src_info->Format, width, height, &src_pitch, &mip_level_size);
|
||||
hr = d3dx_calculate_pixels_size(image->format, mip_size.width, mip_size.height, &src_pitch, &mip_level_size);
|
||||
if (FAILED(hr)) return hr;
|
||||
|
||||
if (mip_level >= skip_levels)
|
||||
{
|
||||
SetRect(&src_rect, 0, 0, width, height);
|
||||
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;
|
||||
|
||||
IDirect3DTexture9_GetSurfaceLevel(texture, mip_level - skip_levels, &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;
|
||||
width = max(1, width / 2);
|
||||
height = max(1, height / 2);
|
||||
pixels += mip_level_size * mip_size.depth;
|
||||
d3dx_get_next_mip_level_size(&mip_size);
|
||||
}
|
||||
|
||||
*loaded_miplevels = mip_levels - skip_levels;
|
||||
*loaded_miplevels = mip_levels;
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
@ -733,7 +726,7 @@ HRESULT load_volume_texture_from_dds(IDirect3DVolumeTexture9 *volume_texture, co
|
|||
}
|
||||
|
||||
static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src_data_size,
|
||||
struct d3dx_image *image)
|
||||
struct d3dx_image *image, uint32_t starting_mip_level)
|
||||
{
|
||||
const struct dds_header *header = src_data;
|
||||
uint32_t expected_src_data_size;
|
||||
|
@ -781,6 +774,27 @@ static HRESULT d3dx_initialize_image_from_dds(const void *src_data, uint32_t src
|
|||
|
||||
image->pixels = ((BYTE *)src_data) + sizeof(*header);
|
||||
image->image_file_format = D3DXIFF_DDS;
|
||||
if (starting_mip_level && (image->mip_levels > 1))
|
||||
{
|
||||
uint32_t i, row_pitch, slice_pitch, initial_mip_levels;
|
||||
const struct volume initial_size = image->size;
|
||||
|
||||
initial_mip_levels = image->mip_levels;
|
||||
for (i = 0; i < starting_mip_level; i++)
|
||||
{
|
||||
d3dx_calculate_pixels_size(image->format, image->size.width, image->size.height, &row_pitch, &slice_pitch);
|
||||
|
||||
image->pixels += slice_pitch * image->size.depth;
|
||||
d3dx_get_next_mip_level_size(&image->size);
|
||||
if (--image->mip_levels == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE("Requested starting mip level %u, actual starting mip level is %u (of %u total in image).\n",
|
||||
starting_mip_level, (initial_mip_levels - image->mip_levels), initial_mip_levels);
|
||||
TRACE("Original dimensions %s, new dimensions %s.\n", debug_volume(&initial_size), debug_volume(&image->size));
|
||||
}
|
||||
|
||||
return D3D_OK;
|
||||
}
|
||||
|
||||
|
@ -1130,14 +1144,15 @@ exit:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT d3dx_image_init(const void *src_data, uint32_t src_data_size, struct d3dx_image *image, uint32_t flags)
|
||||
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)
|
||||
{
|
||||
if (!src_data || !src_data_size || !image)
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
memset(image, 0, sizeof(*image));
|
||||
if ((src_data_size >= 4) && !memcmp(src_data, "DDS ", 4))
|
||||
return d3dx_initialize_image_from_dds(src_data, src_data_size, image);
|
||||
return d3dx_initialize_image_from_dds(src_data, src_data_size, image, starting_mip_level);
|
||||
|
||||
return d3dx_initialize_image_from_wic(src_data, src_data_size, image, flags);
|
||||
}
|
||||
|
@ -1210,7 +1225,7 @@ HRESULT WINAPI D3DXGetImageInfoFromFileInMemory(const void *data, UINT datasize,
|
|||
if (!info)
|
||||
return D3D_OK;
|
||||
|
||||
hr = d3dx_image_init(data, datasize, &image, D3DX_IMAGE_INFO_ONLY);
|
||||
hr = d3dx_image_init(data, datasize, &image, 0, D3DX_IMAGE_INFO_ONLY);
|
||||
if (FAILED(hr)) {
|
||||
TRACE("Invalid or unsupported image file\n");
|
||||
return D3DXERR_INVALIDDATA;
|
||||
|
@ -1359,7 +1374,7 @@ HRESULT WINAPI D3DXLoadSurfaceFromFileInMemory(IDirect3DSurface9 *pDestSurface,
|
|||
if (!pDestSurface || !pSrcData || !SrcDataSize)
|
||||
return D3DERR_INVALIDCALL;
|
||||
|
||||
hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0);
|
||||
hr = d3dx_image_init(pSrcData, SrcDataSize, &image, 0, 0);
|
||||
if (FAILED(hr))
|
||||
return D3DXERR_INVALIDDATA;
|
||||
|
||||
|
|
|
@ -2393,7 +2393,7 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
|
|||
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
check_texture_mip_levels(texture, 1, FALSE);
|
||||
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE);
|
||||
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
|
||||
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
|
||||
|
||||
IDirect3DTexture9_Release(texture);
|
||||
|
@ -2407,9 +2407,9 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
|
|||
D3DX_DEFAULT, D3DX_SKIP_DDS_MIP_LEVELS(3, D3DX_FILTER_POINT), 0, &img_info, NULL, &texture);
|
||||
ok(hr == D3D_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
check_texture_mip_levels(texture, 1, TRUE);
|
||||
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, TRUE);
|
||||
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, TRUE);
|
||||
check_texture_mip_levels(texture, 1, FALSE);
|
||||
check_image_info(&img_info, 1, 1, 1, 1, D3DFMT_R8G8B8, D3DRTYPE_TEXTURE, D3DXIFF_DDS, FALSE);
|
||||
check_texture_level_desc(texture, 0, D3DFMT_X8R8G8B8, D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT, 0, 0, 1, 1, FALSE);
|
||||
|
||||
IDirect3DTexture9_Release(texture);
|
||||
|
||||
|
@ -2463,7 +2463,6 @@ static void test_D3DXCreateTextureFromFileInMemoryEx(IDirect3DDevice9 *device)
|
|||
for (mip_level = 0; mip_level < ARRAY_SIZE(dds_volume_24bit_4_4_4_expected); ++mip_level)
|
||||
{
|
||||
const uint32_t expected_color = dds_volume_24bit_4_4_4_expected[mip_level];
|
||||
BOOL todo = !!mip_level;
|
||||
uint32_t x, y;
|
||||
|
||||
IDirect3DTexture9_GetLevelDesc(texture, mip_level, &desc);
|
||||
|
@ -2472,7 +2471,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);
|
||||
|
|
|
@ -587,7 +587,8 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
|
|||
return D3DERR_INVALIDCALL;
|
||||
|
||||
staging_tex = tex = *texture = NULL;
|
||||
hr = d3dx_image_init(srcdata, srcdatasize, &image, 0);
|
||||
skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0;
|
||||
hr = d3dx_image_init(srcdata, srcdatasize, &image, skip_levels, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
FIXME("Unrecognized file format, returning failure.\n");
|
||||
|
@ -634,20 +635,6 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
|
|||
miplevels = imginfo.MipLevels;
|
||||
}
|
||||
|
||||
skip_levels = mipfilter != D3DX_DEFAULT ? mipfilter >> D3DX_SKIP_DDS_MIP_LEVELS_SHIFT : 0;
|
||||
if (skip_levels && imginfo.MipLevels > skip_levels)
|
||||
{
|
||||
TRACE("Skipping the first %u (of %u) levels of a DDS mipmapped texture.\n",
|
||||
skip_levels, imginfo.MipLevels);
|
||||
TRACE("Texture level 0 dimensions are %ux%u.\n", imginfo.Width, imginfo.Height);
|
||||
width >>= skip_levels;
|
||||
height >>= skip_levels;
|
||||
miplevels -= skip_levels;
|
||||
}
|
||||
else
|
||||
{
|
||||
skip_levels = 0;
|
||||
}
|
||||
|
||||
/* Fix up texture creation parameters. */
|
||||
hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
|
||||
|
@ -710,8 +697,7 @@ HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *devi
|
|||
}
|
||||
else
|
||||
{
|
||||
hr = load_texture_from_dds(tex, srcdata, palette, filter, colorkey, &imginfo, skip_levels,
|
||||
&loaded_miplevels);
|
||||
hr = load_texture_from_dds(tex, palette, filter, colorkey, &image, &loaded_miplevels);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
|
|
Loading…
Reference in a new issue