}
}
+static D3DFORMAT get_luminance_replacement_format(D3DFORMAT format)
+{
+ static const struct
+ {
+ D3DFORMAT luminance_format;
+ D3DFORMAT replacement_format;
+ } luminance_replacements[] =
+ {
+ {D3DFMT_L8, D3DFMT_X8R8G8B8},
+ {D3DFMT_A8L8, D3DFMT_A8R8G8B8},
+ {D3DFMT_A4L4, D3DFMT_A4R4G4B4},
+ {D3DFMT_L16, D3DFMT_A16B16G16R16}
+ };
+ unsigned int i;
+
+ for (i = 0; i < sizeof(luminance_replacements) / sizeof(luminance_replacements[0]); ++i)
+ if (format == luminance_replacements[i].luminance_format)
+ return luminance_replacements[i].replacement_format;
+ return format;
+}
+
HRESULT WINAPI D3DXCheckTextureRequirements(struct IDirect3DDevice9 *device, UINT *width, UINT *height,
UINT *miplevels, DWORD usage, D3DFORMAT *format, D3DPOOL pool)
{
D3DDISPLAYMODE mode;
HRESULT hr;
D3DFORMAT usedformat = D3DFMT_UNKNOWN;
+ const struct pixel_format_desc *fmt;
TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
return D3DERR_INVALIDCALL;
- /* width and height */
- if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
- return D3DERR_INVALIDCALL;
-
- /* 256 x 256 default width/height */
- if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
- w = h = 256;
- else if (w == D3DX_DEFAULT)
- w = (height ? h : 256);
- else if (h == D3DX_DEFAULT)
- h = (width ? w : 256);
-
- /* ensure width/height is power of 2 */
- if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
- w = make_pow2(w);
-
- if (w > caps.MaxTextureWidth)
- w = caps.MaxTextureWidth;
-
- if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
- h = make_pow2(h);
-
- if (h > caps.MaxTextureHeight)
- h = caps.MaxTextureHeight;
-
- /* texture must be square? */
- if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
- {
- if (w > h)
- h = w;
- else
- w = h;
- }
-
- if (width)
- *width = w;
-
- if (height)
- *height = h;
-
- /* miplevels */
- if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
- {
- if (*miplevels > 1)
- *miplevels = 0;
- }
- else if (miplevels)
- {
- UINT max_mipmaps = 1;
-
- if (!width && !height)
- max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
- else
- {
- UINT max_dimen = max(w, h);
-
- while (max_dimen > 1)
- {
- max_dimen >>= 1;
- max_mipmaps++;
- }
- }
-
- if (*miplevels == 0 || *miplevels > max_mipmaps)
- *miplevels = max_mipmaps;
- }
-
/* format */
if (format)
{
if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
usedformat = D3DFMT_A8R8G8B8;
+ fmt = get_format_info(usedformat);
+
hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
usage, D3DRTYPE_TEXTURE, usedformat);
-
if (FAILED(hr))
{
- /* Heuristic to choose the fallback format */
- const struct pixel_format_desc *fmt = get_format_info(usedformat);
BOOL allow_24bits;
int bestscore = INT_MIN, i = 0, j;
unsigned int channels;
- const struct pixel_format_desc *curfmt;
+ const struct pixel_format_desc *curfmt, *bestfmt = NULL;
+
+ TRACE("Requested format is not supported, looking for a fallback.\n");
if (!fmt)
{
FIXME("Pixel format %x not handled\n", usedformat);
goto cleanup;
}
+ fmt = get_format_info(get_luminance_replacement_format(usedformat));
allow_24bits = fmt->bytes_per_pixel == 3;
- channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
- + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
+ channels = !!fmt->bits[0] + !!fmt->bits[1] + !!fmt->bits[2] + !!fmt->bits[3];
usedformat = D3DFMT_UNKNOWN;
while ((curfmt = get_format_info_idx(i)))
{
- unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
- + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
+ unsigned int curchannels = !!curfmt->bits[0] + !!curfmt->bits[1]
+ + !!curfmt->bits[2] + !!curfmt->bits[3];
int score;
i++;
/* This format can be used, let's evaluate it.
Weights chosen quite arbitrarily... */
- score = 16 - 4 * (curchannels - channels);
+ score = 512 * (curfmt->type == fmt->type);
+ score -= 32 * (curchannels - channels);
for (j = 0; j < 4; j++)
{
int diff = curfmt->bits[j] - fmt->bits[j];
- score += 16 - (diff < 0 ? -diff * 4 : diff);
+ score -= (diff < 0 ? -diff * 8 : diff) * (j == 0 ? 1 : 2);
}
if (score > bestscore)
{
bestscore = score;
usedformat = curfmt->format;
+ bestfmt = curfmt;
}
}
+ fmt = bestfmt;
hr = D3D_OK;
}
+ if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
+ return D3DERR_INVALIDCALL;
+
+ if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
+ w = h = 256;
+ else if (w == D3DX_DEFAULT)
+ w = (height ? h : 256);
+ else if (h == D3DX_DEFAULT)
+ h = (width ? w : 256);
+
+ if (fmt->block_width != 1 || fmt->block_height != 1)
+ {
+ if (w % fmt->block_width)
+ w += fmt->block_width - w % fmt->block_width;
+ if (h % fmt->block_height)
+ h += fmt->block_height - h % fmt->block_height;
+ }
+
+ if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
+ w = make_pow2(w);
+
+ if (w > caps.MaxTextureWidth)
+ w = caps.MaxTextureWidth;
+
+ if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
+ h = make_pow2(h);
+
+ if (h > caps.MaxTextureHeight)
+ h = caps.MaxTextureHeight;
+
+ if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
+ {
+ if (w > h)
+ h = w;
+ else
+ w = h;
+ }
+
+ if (width)
+ *width = w;
+
+ if (height)
+ *height = h;
+
+ if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
+ {
+ if (*miplevels > 1)
+ *miplevels = 0;
+ }
+ else if (miplevels)
+ {
+ UINT max_mipmaps = 1;
+
+ if (!width && !height)
+ max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
+ else
+ {
+ UINT max_dimen = max(w, h);
+
+ while (max_dimen > 1)
+ {
+ max_dimen >>= 1;
+ max_mipmaps++;
+ }
+ }
+
+ if (*miplevels == 0 || *miplevels > max_mipmaps)
+ *miplevels = max_mipmaps;
+ }
+
cleanup:
if (d3d)
return IDirect3DDevice9_CreateTexture(device, width, height, miplevels, usage, format, pool, texture, NULL);
}
+static D3DFORMAT get_alpha_replacement_format(D3DFORMAT format)
+{
+ static const struct
+ {
+ D3DFORMAT orig_format;
+ D3DFORMAT replacement_format;
+ }
+ replacement_formats[] =
+ {
+ {D3DFMT_X8R8G8B8, D3DFMT_A8R8G8B8},
+ {D3DFMT_X1R5G5B5, D3DFMT_A1R5G5B5},
+ {D3DFMT_X4R4G4B4, D3DFMT_A4R4G4B4},
+ {D3DFMT_X8B8G8R8, D3DFMT_A8B8G8R8},
+ {D3DFMT_L8, D3DFMT_A8L8},
+ };
+ unsigned int i;
+
+ for (i = 0; i < sizeof(replacement_formats) / sizeof(replacement_formats[0]); ++i)
+ if (replacement_formats[i].orig_format == format)
+ return replacement_formats[i].replacement_format;
+ return format;
+}
+
HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *device, const void *srcdata,
UINT srcdatasize, UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
IDirect3DTexture9 **texptr;
IDirect3DTexture9 *buftex;
IDirect3DSurface9 *surface;
- BOOL file_width = FALSE, file_height = FALSE;
- BOOL file_format = FALSE, file_miplevels = FALSE;
- BOOL dynamic_texture;
+ BOOL dynamic_texture, format_specified = FALSE;
D3DXIMAGE_INFO imginfo;
- UINT loaded_miplevels;
+ UINT loaded_miplevels, skip_levels;
D3DCAPS9 caps;
HRESULT hr;
- TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
- height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
+ TRACE("device %p, srcdata %p, srcdatasize %u, width %u, height %u, miplevels %u,"
+ " usage %#x, format %#x, pool %#x, filter %#x, mipfilter %#x, colorkey %#x,"
+ " srcinfo %p, palette %p, texture %p.\n",
+ device, srcdata, srcdatasize, width, height, miplevels, usage, format, pool,
+ filter, mipfilter, colorkey, srcinfo, palette, texture);
/* check for invalid parameters */
if (!device || !texture || !srcdata || !srcdatasize)
return D3DERR_INVALIDCALL;
hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
-
if (FAILED(hr))
{
+ FIXME("Unrecognized file format, returning failure.\n");
*texture = NULL;
return hr;
}
if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
format = imginfo.Format;
+ else
+ format_specified = TRUE;
if (width == D3DX_FROM_FILE)
{
- file_width = TRUE;
width = imginfo.Width;
}
if (height == D3DX_FROM_FILE)
{
- file_height = TRUE;
height = imginfo.Height;
}
if (format == D3DFMT_FROM_FILE)
{
- file_format = TRUE;
format = imginfo.Format;
}
if (miplevels == D3DX_FROM_FILE)
{
- file_miplevels = TRUE;
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 texture creation parameters */
hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
-
if (FAILED(hr))
{
+ FIXME("Couldn't find suitable texture parameters.\n");
*texture = NULL;
return hr;
}
+ if (colorkey && !format_specified)
+ format = get_alpha_replacement_format(format);
+
if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
{
- FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
+ FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet.\n");
miplevels = imginfo.MipLevels;
}
-
- if (((file_width) && (width != imginfo.Width)) ||
- ((file_height) && (height != imginfo.Height)) ||
- ((file_format) && (format != imginfo.Format)) ||
- ((file_miplevels) && (miplevels != imginfo.MipLevels)))
+ if (imginfo.ResourceType == D3DRTYPE_VOLUMETEXTURE
+ && D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5 && miplevels > 1)
{
- return D3DERR_NOTAVAILABLE;
+ FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet.\n");
+ miplevels = 1;
}
if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
{
- hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
+ hr = D3DXCreateTexture(device, width, height, miplevels, 0, format, D3DPOOL_SYSTEMMEM, &buftex);
texptr = &buftex;
}
else
if (FAILED(hr))
{
+ FIXME("Texture creation failed.\n");
*texture = NULL;
return hr;
}
- /* Load the file */
+ TRACE("Texture created correctly. Now loading the texture data into it.\n");
if (imginfo.ImageFileFormat != D3DXIFF_DDS)
{
IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
IDirect3DSurface9_Release(surface);
+ loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
}
else
{
- hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
+ hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo, skip_levels,
+ &loaded_miplevels);
}
if (FAILED(hr))
{
+ FIXME("Texture loading failed.\n");
IDirect3DTexture9_Release(*texptr);
*texture = NULL;
return hr;
}
- loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
-
if (FAILED(hr))
{
+ FIXME("Texture filtering failed.\n");
IDirect3DTexture9_Release(*texptr);
*texture = NULL;
return hr;
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
{
+ void *buffer;
HRESULT hr;
DWORD size;
- LPVOID buffer;
- TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
- device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
- mipfilter, colorkey, srcinfo, palette, texture);
+ TRACE("device %p, srcfile %s, width %u, height %u, miplevels %u, usage %#x, format %#x, "
+ "pool %#x, filter %#x, mipfilter %#x, colorkey 0x%08x, srcinfo %p, palette %p, texture %p.\n",
+ device, debugstr_w(srcfile), width, height, miplevels, usage, format,
+ pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
if (!srcfile)
return D3DERR_INVALIDCALL;
D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
{
- LPWSTR widename;
+ WCHAR *widename;
HRESULT hr;
DWORD len;
- TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
- device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
- mipfilter, colorkey, srcinfo, palette, texture);
+ TRACE("device %p, srcfile %s, width %u, height %u, miplevels %u, usage %#x, format %#x, "
+ "pool %#x, filter %#x, mipfilter %#x, colorkey 0x%08x, srcinfo %p, palette %p, texture %p.\n",
+ device, debugstr_a(srcfile), width, height, miplevels, usage, format,
+ pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
if (!device || !srcfile || !texture)
return D3DERR_INVALIDCALL;
if (mip_levels > image_info.MipLevels)
{
- FIXME("Generation of mipmaps for volume textures is not implemented yet\n");
+ FIXME("Generation of mipmaps for volume textures is not implemented yet.\n");
mip_levels = image_info.MipLevels;
}
return D3D_OK;
}
+HRESULT WINAPI D3DXFillTextureTX(struct IDirect3DTexture9 *texture, ID3DXTextureShader *texture_shader)
+{
+ FIXME("texture %p, texture_shader %p stub.\n", texture, texture_shader);
+ return E_NOTIMPL;
+}
+
HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
const void *src_data,
UINT src_data_size,
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");
+ FIXME("Generation of mipmaps for compressed pixel formats is not supported yet.\n");
mip_levels = img_info.MipLevels;
}
return D3D_OK;
}
+HRESULT WINAPI D3DXFillCubeTextureTX(struct IDirect3DCubeTexture9 *texture, ID3DXTextureShader *texture_shader)
+{
+ FIXME("texture %p, texture_shader %p stub.\n", texture, texture_shader);
+ return E_NOTIMPL;
+}
+
HRESULT WINAPI D3DXFillVolumeTexture(struct IDirect3DVolumeTexture9 *texture, LPD3DXFILL3D function, void *funcdata)
{
DWORD miplevels;
return D3D_OK;
}
+HRESULT WINAPI D3DXFillVolumeTextureTX(struct IDirect3DVolumeTexture9 *texture, ID3DXTextureShader *texture_shader)
+{
+ FIXME("texture %p, texture_shader %p stub.\n", texture, texture_shader);
+ return E_NOTIMPL;
+}
+
HRESULT WINAPI D3DXSaveTextureToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
{
if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
if (file_format == D3DXIFF_DDS)
- {
- FIXME("DDS file format isn't supported yet\n");
- return E_NOTIMPL;
- }
+ return save_dds_texture_to_memory(dst_buffer, src_texture, src_palette);
type = IDirect3DBaseTexture9_GetType(src_texture);
switch (type)