mshtml: Moved creating nsIFile to separated function.
[wine/multimedia.git] / dlls / d3dx9_36 / texture.c
blobec9bad99f8d1f94a09cc8e08063050592d43a0bd
1 /*
2 * Copyright 2009 Tony Wasserka
3 * Copyright 2010 Christian Costa
4 * Copyright 2010 Owen Rudge for CodeWeavers
5 * Copyright 2010 Matteo Bruni for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/unicode.h"
23 #include "wine/debug.h"
24 #include "d3dx9_36_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
29 static BOOL is_pow2(UINT num)
31 return !(num & (num - 1));
34 /* Returns the smallest power of 2 which is greater than or equal to num */
35 static UINT make_pow2(UINT num)
37 UINT result = 1;
39 /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */
40 if (num >= 0x80000000)
41 return 0x80000000;
43 while (result < num)
44 result <<= 1;
46 return result;
49 static HRESULT get_surface(D3DRESOURCETYPE type, LPDIRECT3DBASETEXTURE9 tex,
50 int face, UINT level, LPDIRECT3DSURFACE9 *surf)
52 switch (type)
54 case D3DRTYPE_TEXTURE:
55 return IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) tex, level, surf);
56 case D3DRTYPE_CUBETEXTURE:
57 return IDirect3DCubeTexture9_GetCubeMapSurface((IDirect3DCubeTexture9*) tex, face, level, surf);
58 default:
59 ERR("Unexpected texture type\n");
60 return E_NOTIMPL;
64 HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture,
65 const PALETTEENTRY *palette,
66 UINT srclevel,
67 DWORD filter)
69 UINT level;
70 HRESULT hr;
71 D3DRESOURCETYPE type;
73 TRACE("(%p, %p, %u, %#x)\n", texture, palette, srclevel, filter);
75 if (!texture)
76 return D3DERR_INVALIDCALL;
78 if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT)
79 return D3DERR_INVALIDCALL;
81 if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
82 return D3DERR_INVALIDCALL;
84 switch (type = IDirect3DBaseTexture9_GetType(texture))
86 case D3DRTYPE_TEXTURE:
87 case D3DRTYPE_CUBETEXTURE:
89 IDirect3DSurface9 *topsurf, *mipsurf;
90 D3DSURFACE_DESC desc;
91 int i, numfaces;
93 if (type == D3DRTYPE_TEXTURE)
95 numfaces = 1;
96 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
98 else
100 numfaces = 6;
101 IDirect3DCubeTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
104 if (filter == D3DX_DEFAULT)
106 if (is_pow2(desc.Width) && is_pow2(desc.Height))
107 filter = D3DX_FILTER_BOX;
108 else
109 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
112 for (i = 0; i < numfaces; i++)
114 level = srclevel + 1;
115 hr = get_surface(type, texture, i, srclevel, &topsurf);
117 if (FAILED(hr))
118 return D3DERR_INVALIDCALL;
120 while (get_surface(type, texture, i, level, &mipsurf) == D3D_OK)
122 hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
123 IDirect3DSurface9_Release(topsurf);
124 topsurf = mipsurf;
126 if (FAILED(hr))
127 break;
129 level++;
132 IDirect3DSurface9_Release(topsurf);
133 if (FAILED(hr))
134 return hr;
137 return D3D_OK;
140 case D3DRTYPE_VOLUMETEXTURE:
142 D3DVOLUME_DESC desc;
143 int level, level_count;
144 IDirect3DVolume9 *top_volume, *mip_volume;
145 IDirect3DVolumeTexture9 *volume_texture = (IDirect3DVolumeTexture9*) texture;
147 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, srclevel, &desc);
149 if (filter == D3DX_DEFAULT)
151 if (is_pow2(desc.Width) && is_pow2(desc.Height) && is_pow2(desc.Depth))
152 filter = D3DX_FILTER_BOX;
153 else
154 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
157 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, srclevel, &top_volume);
158 if (FAILED(hr))
159 return hr;
161 level_count = IDirect3DVolumeTexture9_GetLevelCount(volume_texture);
162 for (level = srclevel + 1; level < level_count; level++)
164 IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, level, &mip_volume);
165 hr = D3DXLoadVolumeFromVolume(mip_volume, palette, NULL, top_volume, palette, NULL, filter, 0);
166 IDirect3DVolume9_Release(top_volume);
167 top_volume = mip_volume;
169 if (FAILED(hr))
170 break;
173 IDirect3DVolume9_Release(top_volume);
174 if (FAILED(hr))
175 return hr;
177 return D3D_OK;
180 default:
181 return D3DERR_INVALIDCALL;
185 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
186 UINT* width,
187 UINT* height,
188 UINT* miplevels,
189 DWORD usage,
190 D3DFORMAT* format,
191 D3DPOOL pool)
193 UINT w = (width && *width) ? *width : 1;
194 UINT h = (height && *height) ? *height : 1;
195 D3DCAPS9 caps;
196 D3DDEVICE_CREATION_PARAMETERS params;
197 IDirect3D9 *d3d = NULL;
198 D3DDISPLAYMODE mode;
199 HRESULT hr;
200 D3DFORMAT usedformat = D3DFMT_UNKNOWN;
202 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
204 if (!device)
205 return D3DERR_INVALIDCALL;
207 /* usage */
208 if (usage == D3DX_DEFAULT)
209 usage = 0;
210 if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
211 return D3DERR_INVALIDCALL;
213 /* pool */
214 if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
215 return D3DERR_INVALIDCALL;
217 /* width and height */
218 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
219 return D3DERR_INVALIDCALL;
221 /* 256 x 256 default width/height */
222 if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
223 w = h = 256;
224 else if (w == D3DX_DEFAULT)
225 w = (height ? h : 256);
226 else if (h == D3DX_DEFAULT)
227 h = (width ? w : 256);
229 /* ensure width/height is power of 2 */
230 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
231 w = make_pow2(w);
233 if (w > caps.MaxTextureWidth)
234 w = caps.MaxTextureWidth;
236 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
237 h = make_pow2(h);
239 if (h > caps.MaxTextureHeight)
240 h = caps.MaxTextureHeight;
242 /* texture must be square? */
243 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
245 if (w > h)
246 h = w;
247 else
248 w = h;
251 if (width)
252 *width = w;
254 if (height)
255 *height = h;
257 /* miplevels */
258 if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
260 if (*miplevels > 1)
261 *miplevels = 0;
263 else if (miplevels)
265 UINT max_mipmaps = 1;
267 if (!width && !height)
268 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
269 else
271 UINT max_dimen = max(w, h);
273 while (max_dimen > 1)
275 max_dimen >>= 1;
276 max_mipmaps++;
280 if (*miplevels == 0 || *miplevels > max_mipmaps)
281 *miplevels = max_mipmaps;
284 /* format */
285 if (format)
287 TRACE("Requested format %x\n", *format);
288 usedformat = *format;
291 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
293 if (FAILED(hr))
294 goto cleanup;
296 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
298 if (FAILED(hr))
299 goto cleanup;
301 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
303 if (FAILED(hr))
304 goto cleanup;
306 if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
307 usedformat = D3DFMT_A8R8G8B8;
309 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
310 usage, D3DRTYPE_TEXTURE, usedformat);
312 if (FAILED(hr))
314 /* Heuristic to choose the fallback format */
315 const PixelFormatDesc *fmt = get_format_info(usedformat);
316 BOOL allow_24bits;
317 int bestscore = INT_MIN, i = 0, j;
318 unsigned int channels;
319 const PixelFormatDesc *curfmt;
321 if (!fmt)
323 FIXME("Pixel format %x not handled\n", usedformat);
324 goto cleanup;
327 allow_24bits = fmt->bytes_per_pixel == 3;
328 channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
329 + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
330 usedformat = D3DFMT_UNKNOWN;
332 while ((curfmt = get_format_info_idx(i)))
334 unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
335 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
336 int score;
338 i++;
340 if (curchannels < channels)
341 continue;
342 if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
343 continue;
345 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
346 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
347 if (FAILED(hr))
348 continue;
350 /* This format can be used, let's evaluate it.
351 Weights chosen quite arbitrarily... */
352 score = 16 - 4 * (curchannels - channels);
354 for (j = 0; j < 4; j++)
356 int diff = curfmt->bits[j] - fmt->bits[j];
357 score += 16 - (diff < 0 ? -diff * 4 : diff);
360 if (score > bestscore)
362 bestscore = score;
363 usedformat = curfmt->format;
366 hr = D3D_OK;
369 cleanup:
371 if (d3d)
372 IDirect3D9_Release(d3d);
374 if (FAILED(hr))
375 return hr;
377 if (usedformat == D3DFMT_UNKNOWN)
379 WARN("Couldn't find a suitable pixel format\n");
380 return D3DERR_NOTAVAILABLE;
383 TRACE("Format chosen: %x\n", usedformat);
384 if (format)
385 *format = usedformat;
387 return D3D_OK;
390 HRESULT WINAPI D3DXCheckCubeTextureRequirements(LPDIRECT3DDEVICE9 device,
391 UINT *size,
392 UINT *miplevels,
393 DWORD usage,
394 D3DFORMAT *format,
395 D3DPOOL pool)
397 D3DCAPS9 caps;
398 UINT s = (size && *size) ? *size : 256;
399 HRESULT hr;
401 TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
403 if (s == D3DX_DEFAULT)
404 s = 256;
406 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
407 return D3DERR_INVALIDCALL;
409 if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
410 return D3DERR_NOTAVAILABLE;
412 /* ensure width/height is power of 2 */
413 if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
414 s = make_pow2(s);
416 hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
418 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
420 if(miplevels)
421 *miplevels = 1;
424 if (size)
425 *size = s;
427 return hr;
430 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(LPDIRECT3DDEVICE9 device,
431 UINT *width,
432 UINT *height,
433 UINT *depth,
434 UINT *miplevels,
435 DWORD usage,
436 D3DFORMAT *format,
437 D3DPOOL pool)
439 D3DCAPS9 caps;
440 UINT w = width ? *width : D3DX_DEFAULT;
441 UINT h = height ? *height : D3DX_DEFAULT;
442 UINT d = (depth && *depth) ? *depth : 1;
443 HRESULT hr;
445 TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
446 usage, format, pool);
448 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
449 return D3DERR_INVALIDCALL;
451 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
452 return D3DERR_NOTAVAILABLE;
454 hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
455 if (d == D3DX_DEFAULT)
456 d = 1;
458 /* ensure width/height is power of 2 */
459 if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
460 (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
462 w = make_pow2(w);
463 h = make_pow2(h);
464 d = make_pow2(d);
467 if (w > caps.MaxVolumeExtent)
468 w = caps.MaxVolumeExtent;
469 if (h > caps.MaxVolumeExtent)
470 h = caps.MaxVolumeExtent;
471 if (d > caps.MaxVolumeExtent)
472 d = caps.MaxVolumeExtent;
474 if (miplevels)
476 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
477 *miplevels = 1;
478 else if ((usage & D3DUSAGE_AUTOGENMIPMAP))
480 if (*miplevels > 1)
481 *miplevels = 0;
483 else
485 UINT max_mipmaps = 1;
486 UINT max_dimen = max(max(w, h), d);
488 while (max_dimen > 1)
490 max_dimen >>= 1;
491 max_mipmaps++;
494 if (*miplevels == 0 || *miplevels > max_mipmaps)
495 *miplevels = max_mipmaps;
499 if (width)
500 *width = w;
501 if (height)
502 *height = h;
503 if (depth)
504 *depth = d;
506 return hr;
509 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
510 UINT width,
511 UINT height,
512 UINT miplevels,
513 DWORD usage,
514 D3DFORMAT format,
515 D3DPOOL pool,
516 LPDIRECT3DTEXTURE9 *ppTexture)
518 HRESULT hr;
520 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
521 pool, ppTexture);
523 if (!pDevice || !ppTexture)
524 return D3DERR_INVALIDCALL;
526 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
528 if (FAILED(hr))
529 return hr;
531 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
534 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
535 LPCVOID srcdata,
536 UINT srcdatasize,
537 UINT width,
538 UINT height,
539 UINT miplevels,
540 DWORD usage,
541 D3DFORMAT format,
542 D3DPOOL pool,
543 DWORD filter,
544 DWORD mipfilter,
545 D3DCOLOR colorkey,
546 D3DXIMAGE_INFO* srcinfo,
547 PALETTEENTRY* palette,
548 LPDIRECT3DTEXTURE9* texture)
550 IDirect3DTexture9 **texptr;
551 IDirect3DTexture9 *buftex;
552 IDirect3DSurface9 *surface;
553 BOOL file_width = FALSE, file_height = FALSE;
554 BOOL file_format = FALSE, file_miplevels = FALSE;
555 BOOL dynamic_texture;
556 D3DXIMAGE_INFO imginfo;
557 UINT loaded_miplevels;
558 D3DCAPS9 caps;
559 HRESULT hr;
561 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
562 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
564 /* check for invalid parameters */
565 if (!device || !texture || !srcdata || !srcdatasize)
566 return D3DERR_INVALIDCALL;
568 hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
570 if (FAILED(hr))
572 *texture = NULL;
573 return hr;
576 /* handle default values */
577 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
578 width = imginfo.Width;
580 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
581 height = imginfo.Height;
583 if (width == D3DX_DEFAULT)
584 width = make_pow2(imginfo.Width);
586 if (height == D3DX_DEFAULT)
587 height = make_pow2(imginfo.Height);
589 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
590 format = imginfo.Format;
592 if (width == D3DX_FROM_FILE)
594 file_width = TRUE;
595 width = imginfo.Width;
598 if (height == D3DX_FROM_FILE)
600 file_height = TRUE;
601 height = imginfo.Height;
604 if (format == D3DFMT_FROM_FILE)
606 file_format = TRUE;
607 format = imginfo.Format;
610 if (miplevels == D3DX_FROM_FILE)
612 file_miplevels = TRUE;
613 miplevels = imginfo.MipLevels;
616 /* fix texture creation parameters */
617 hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
619 if (FAILED(hr))
621 *texture = NULL;
622 return hr;
625 if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
627 FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
628 miplevels = imginfo.MipLevels;
631 if (((file_width) && (width != imginfo.Width)) ||
632 ((file_height) && (height != imginfo.Height)) ||
633 ((file_format) && (format != imginfo.Format)) ||
634 ((file_miplevels) && (miplevels != imginfo.MipLevels)))
636 return D3DERR_NOTAVAILABLE;
639 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
640 return D3DERR_INVALIDCALL;
642 /* Create the to-be-filled texture */
643 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
644 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
646 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
647 texptr = &buftex;
649 else
651 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
652 texptr = texture;
655 if (FAILED(hr))
657 *texture = NULL;
658 return hr;
661 /* Load the file */
662 if (imginfo.ImageFileFormat != D3DXIFF_DDS)
664 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
665 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
666 IDirect3DSurface9_Release(surface);
668 else
670 hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
673 if (FAILED(hr))
675 IDirect3DTexture9_Release(*texptr);
676 *texture = NULL;
677 return hr;
680 loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
681 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
683 if (FAILED(hr))
685 IDirect3DTexture9_Release(*texptr);
686 *texture = NULL;
687 return hr;
690 /* Move the data to the actual texture if necessary */
691 if (texptr == &buftex)
693 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
695 if (FAILED(hr))
697 IDirect3DTexture9_Release(buftex);
698 *texture = NULL;
699 return hr;
702 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
703 IDirect3DTexture9_Release(buftex);
706 if (srcinfo)
707 *srcinfo = imginfo;
709 return D3D_OK;
712 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
713 LPCVOID srcdata,
714 UINT srcdatasize,
715 LPDIRECT3DTEXTURE9 *texture)
717 TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
719 return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
720 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
723 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
724 LPCWSTR srcfile,
725 UINT width,
726 UINT height,
727 UINT miplevels,
728 DWORD usage,
729 D3DFORMAT format,
730 D3DPOOL pool,
731 DWORD filter,
732 DWORD mipfilter,
733 D3DCOLOR colorkey,
734 D3DXIMAGE_INFO *srcinfo,
735 PALETTEENTRY *palette,
736 LPDIRECT3DTEXTURE9 *texture)
738 HRESULT hr;
739 DWORD size;
740 LPVOID buffer;
742 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
743 device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
744 mipfilter, colorkey, srcinfo, palette, texture);
746 if (!srcfile)
747 return D3DERR_INVALIDCALL;
749 hr = map_view_of_file(srcfile, &buffer, &size);
750 if (FAILED(hr))
751 return D3DXERR_INVALIDDATA;
753 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
754 filter, mipfilter, colorkey, srcinfo, palette, texture);
756 UnmapViewOfFile(buffer);
758 return hr;
761 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
762 LPCSTR srcfile,
763 UINT width,
764 UINT height,
765 UINT miplevels,
766 DWORD usage,
767 D3DFORMAT format,
768 D3DPOOL pool,
769 DWORD filter,
770 DWORD mipfilter,
771 D3DCOLOR colorkey,
772 D3DXIMAGE_INFO *srcinfo,
773 PALETTEENTRY *palette,
774 LPDIRECT3DTEXTURE9 *texture)
776 LPWSTR widename;
777 HRESULT hr;
778 DWORD len;
780 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
781 device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
782 mipfilter, colorkey, srcinfo, palette, texture);
784 if (!device || !srcfile || !texture)
785 return D3DERR_INVALIDCALL;
787 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
788 widename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*widename));
789 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
791 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
792 usage, format, pool, filter, mipfilter,
793 colorkey, srcinfo, palette, texture);
795 HeapFree(GetProcessHeap(), 0, widename);
796 return hr;
799 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
800 LPCSTR srcfile,
801 LPDIRECT3DTEXTURE9 *texture)
803 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
805 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
806 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
809 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
810 LPCWSTR srcfile,
811 LPDIRECT3DTEXTURE9 *texture)
813 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
815 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
816 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
820 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
821 HMODULE srcmodule,
822 LPCSTR resource,
823 LPDIRECT3DTEXTURE9 *texture)
825 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
827 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
828 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
831 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
832 HMODULE srcmodule,
833 LPCWSTR resource,
834 LPDIRECT3DTEXTURE9 *texture)
836 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
838 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
839 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
842 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
843 HMODULE srcmodule,
844 LPCSTR resource,
845 UINT width,
846 UINT height,
847 UINT miplevels,
848 DWORD usage,
849 D3DFORMAT format,
850 D3DPOOL pool,
851 DWORD filter,
852 DWORD mipfilter,
853 D3DCOLOR colorkey,
854 D3DXIMAGE_INFO *srcinfo,
855 PALETTEENTRY *palette,
856 LPDIRECT3DTEXTURE9 *texture)
858 HRSRC resinfo;
860 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
862 if (!device || !texture)
863 return D3DERR_INVALIDCALL;
865 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
867 if (resinfo)
869 LPVOID buffer;
870 HRESULT hr;
871 DWORD size;
873 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
875 if (FAILED(hr))
876 return D3DXERR_INVALIDDATA;
878 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
879 height, miplevels, usage, format,
880 pool, filter, mipfilter, colorkey,
881 srcinfo, palette, texture);
884 /* Try loading the resource as bitmap data */
885 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
887 if (resinfo)
889 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
890 return E_NOTIMPL;
893 return D3DXERR_INVALIDDATA;
896 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
897 HMODULE srcmodule,
898 LPCWSTR resource,
899 UINT width,
900 UINT height,
901 UINT miplevels,
902 DWORD usage,
903 D3DFORMAT format,
904 D3DPOOL pool,
905 DWORD filter,
906 DWORD mipfilter,
907 D3DCOLOR colorkey,
908 D3DXIMAGE_INFO *srcinfo,
909 PALETTEENTRY *palette,
910 LPDIRECT3DTEXTURE9 *texture)
912 HRSRC resinfo;
914 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
916 if (!device || !texture)
917 return D3DERR_INVALIDCALL;
919 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
921 if (resinfo)
923 LPVOID buffer;
924 HRESULT hr;
925 DWORD size;
927 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
929 if (FAILED(hr))
930 return D3DXERR_INVALIDDATA;
932 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
933 height, miplevels, usage, format,
934 pool, filter, mipfilter, colorkey,
935 srcinfo, palette, texture);
938 /* Try loading the resource as bitmap data */
939 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
941 if (resinfo)
943 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
944 return E_NOTIMPL;
947 return D3DXERR_INVALIDDATA;
950 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
951 UINT size,
952 UINT miplevels,
953 DWORD usage,
954 D3DFORMAT format,
955 D3DPOOL pool,
956 LPDIRECT3DCUBETEXTURE9 *texture)
958 HRESULT hr;
960 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
961 pool, texture);
963 if (!device || !texture)
964 return D3DERR_INVALIDCALL;
966 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
968 if (FAILED(hr))
970 TRACE("D3DXCheckCubeTextureRequirements failed\n");
971 return hr;
974 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
977 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
978 LPCVOID data,
979 UINT datasize,
980 LPDIRECT3DCUBETEXTURE9 *texture)
982 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
984 return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
985 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
988 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
989 UINT width,
990 UINT height,
991 UINT depth,
992 UINT miplevels,
993 DWORD usage,
994 D3DFORMAT format,
995 D3DPOOL pool,
996 LPDIRECT3DVOLUMETEXTURE9 *texture)
998 HRESULT hr;
1000 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
1001 miplevels, usage, format, pool, texture);
1003 if (!device || !texture)
1004 return D3DERR_INVALIDCALL;
1006 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
1007 &miplevels, usage, &format, pool);
1009 if (FAILED(hr))
1011 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
1012 return hr;
1015 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
1016 usage, format, pool, texture, NULL);
1019 HRESULT WINAPI D3DXCreateVolumeTextureFromFileA(IDirect3DDevice9 *device,
1020 const char *filename,
1021 IDirect3DVolumeTexture9 **volume_texture)
1023 int len;
1024 HRESULT hr;
1025 void *data;
1026 DWORD data_size;
1027 WCHAR *filenameW;
1029 TRACE("(%p, %s, %p): relay\n",
1030 device, debugstr_a(filename), volume_texture);
1032 if (!filename) return D3DERR_INVALIDCALL;
1034 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1035 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1036 if (!filenameW) return E_OUTOFMEMORY;
1037 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1039 hr = map_view_of_file(filenameW, &data, &data_size);
1040 HeapFree(GetProcessHeap(), 0, filenameW);
1041 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1043 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1044 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1046 UnmapViewOfFile(data);
1047 return hr;
1050 HRESULT WINAPI D3DXCreateVolumeTextureFromFileW(IDirect3DDevice9 *device,
1051 const WCHAR *filename,
1052 IDirect3DVolumeTexture9 **volume_texture)
1054 HRESULT hr;
1055 void *data;
1056 DWORD data_size;
1058 TRACE("(%p, %s, %p): relay\n",
1059 device, debugstr_w(filename), volume_texture);
1061 if (!filename) return D3DERR_INVALIDCALL;
1063 hr = map_view_of_file(filename, &data, &data_size);
1064 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1066 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1067 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1069 UnmapViewOfFile(data);
1070 return hr;
1073 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExA(IDirect3DDevice9 *device,
1074 const char *filename,
1075 UINT width,
1076 UINT height,
1077 UINT depth,
1078 UINT mip_levels,
1079 DWORD usage,
1080 D3DFORMAT format,
1081 D3DPOOL pool,
1082 DWORD filter,
1083 DWORD mip_filter,
1084 D3DCOLOR color_key,
1085 D3DXIMAGE_INFO *src_info,
1086 PALETTEENTRY *palette,
1087 IDirect3DVolumeTexture9 **volume_texture)
1089 int len;
1090 HRESULT hr;
1091 WCHAR *filenameW;
1092 void *data;
1093 DWORD data_size;
1095 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1096 device, debugstr_a(filename), width, height, depth, mip_levels,
1097 usage, format, pool, filter, mip_filter, color_key, src_info,
1098 palette, volume_texture);
1100 if (!filename) return D3DERR_INVALIDCALL;
1102 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1103 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1104 if (!filenameW) return E_OUTOFMEMORY;
1105 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1107 hr = map_view_of_file(filenameW, &data, &data_size);
1108 HeapFree(GetProcessHeap(), 0, filenameW);
1109 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1111 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1112 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1113 volume_texture);
1115 UnmapViewOfFile(data);
1116 return hr;
1119 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExW(IDirect3DDevice9 *device,
1120 const WCHAR *filename,
1121 UINT width,
1122 UINT height,
1123 UINT depth,
1124 UINT mip_levels,
1125 DWORD usage,
1126 D3DFORMAT format,
1127 D3DPOOL pool,
1128 DWORD filter,
1129 DWORD mip_filter,
1130 D3DCOLOR color_key,
1131 D3DXIMAGE_INFO *src_info,
1132 PALETTEENTRY *palette,
1133 IDirect3DVolumeTexture9 **volume_texture)
1135 HRESULT hr;
1136 void *data;
1137 DWORD data_size;
1139 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1140 device, debugstr_w(filename), width, height, depth, mip_levels,
1141 usage, format, pool, filter, mip_filter, color_key, src_info,
1142 palette, volume_texture);
1144 if (!filename) return D3DERR_INVALIDCALL;
1146 hr = map_view_of_file(filename, &data, &data_size);
1147 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1149 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1150 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1151 volume_texture);
1153 UnmapViewOfFile(data);
1154 return hr;
1157 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device,
1158 const void *data,
1159 UINT data_size,
1160 IDirect3DVolumeTexture9 **volume_texture)
1162 TRACE("(%p, %p, %u, %p): relay\n", device, data, data_size, volume_texture);
1164 return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1165 D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
1166 0, NULL, NULL, volume_texture);
1169 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1170 const void *data,
1171 UINT data_size,
1172 UINT width,
1173 UINT height,
1174 UINT depth,
1175 UINT mip_levels,
1176 DWORD usage,
1177 D3DFORMAT format,
1178 D3DPOOL pool,
1179 DWORD filter,
1180 DWORD mip_filter,
1181 D3DCOLOR color_key,
1182 D3DXIMAGE_INFO *info,
1183 PALETTEENTRY *palette,
1184 IDirect3DVolumeTexture9 **volume_texture)
1186 HRESULT hr;
1187 D3DCAPS9 caps;
1188 D3DXIMAGE_INFO image_info;
1189 BOOL dynamic_texture;
1190 BOOL file_width = FALSE;
1191 BOOL file_height = FALSE;
1192 BOOL file_depth = FALSE;
1193 BOOL file_format = FALSE;
1194 BOOL file_mip_levels = FALSE;
1195 IDirect3DVolumeTexture9 *tex, *buftex;
1197 TRACE("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n",
1198 device, data, data_size, width, height, depth, mip_levels, usage, format, pool,
1199 filter, mip_filter, color_key, info, palette, volume_texture);
1201 if (!device || !data || !data_size || !volume_texture)
1202 return D3DERR_INVALIDCALL;
1204 hr = D3DXGetImageInfoFromFileInMemory(data, data_size, &image_info);
1205 if (FAILED(hr)) return hr;
1207 if (image_info.ImageFileFormat != D3DXIFF_DDS)
1208 return D3DXERR_INVALIDDATA;
1210 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
1211 width = image_info.Width;
1212 if (width == D3DX_DEFAULT)
1213 width = make_pow2(image_info.Width);
1215 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
1216 height = image_info.Height;
1217 if (height == D3DX_DEFAULT)
1218 height = make_pow2(image_info.Height);
1220 if (depth == 0 || depth == D3DX_DEFAULT_NONPOW2)
1221 depth = image_info.Depth;
1222 if (depth == D3DX_DEFAULT)
1223 depth = make_pow2(image_info.Depth);
1225 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1226 format = image_info.Format;
1228 if (width == D3DX_FROM_FILE)
1230 file_width = TRUE;
1231 width = image_info.Width;
1234 if (height == D3DX_FROM_FILE)
1236 file_height = TRUE;
1237 height = image_info.Height;
1240 if (depth == D3DX_FROM_FILE)
1242 file_depth = TRUE;
1243 depth = image_info.Depth;
1246 if (format == D3DFMT_FROM_FILE)
1248 file_format = TRUE;
1249 format = image_info.Format;
1252 if (mip_levels == D3DX_FROM_FILE)
1254 file_mip_levels = TRUE;
1255 mip_levels = image_info.MipLevels;
1258 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mip_levels, usage, &format, pool);
1259 if (FAILED(hr)) return hr;
1261 if ((file_width && width != image_info.Width)
1262 || (file_height && height != image_info.Height)
1263 || (file_depth && depth != image_info.Depth)
1264 || (file_format && format != image_info.Format)
1265 || (file_mip_levels && mip_levels != image_info.MipLevels))
1266 return D3DERR_NOTAVAILABLE;
1268 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1269 if (FAILED(hr))
1270 return D3DERR_INVALIDCALL;
1272 if (mip_levels > image_info.MipLevels)
1274 FIXME("Generation of mipmaps for volume textures is not implemented yet\n");
1275 mip_levels = image_info.MipLevels;
1278 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1279 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1281 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1282 tex = buftex;
1284 else
1286 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1287 buftex = NULL;
1290 if (FAILED(hr)) return hr;
1292 hr = load_volume_texture_from_dds(tex, data, palette, filter, color_key, &image_info);
1293 if (FAILED(hr))
1295 IDirect3DVolumeTexture9_Release(tex);
1296 return hr;
1299 if (buftex)
1301 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1302 if (FAILED(hr))
1304 IDirect3DVolumeTexture9_Release(buftex);
1305 return hr;
1308 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1309 IDirect3DVolumeTexture9_Release(buftex);
1312 if (info)
1313 *info = image_info;
1315 *volume_texture = tex;
1316 return D3D_OK;
1319 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
1320 LPD3DXFILL2D function,
1321 LPVOID funcdata)
1323 DWORD miplevels;
1324 DWORD m, i, x, y, c, v;
1325 D3DSURFACE_DESC desc;
1326 D3DLOCKED_RECT lock_rect;
1327 D3DXVECTOR4 value;
1328 D3DXVECTOR2 coord, size;
1329 const PixelFormatDesc *format;
1330 BYTE *data, *pos;
1331 BYTE byte, mask;
1332 float comp_value;
1334 if (texture == NULL || function == NULL)
1335 return D3DERR_INVALIDCALL;
1337 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1339 for (m = 0; m < miplevels; m++)
1341 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1342 return D3DERR_INVALIDCALL;
1344 format = get_format_info(desc.Format);
1345 if (format->format == D3DFMT_UNKNOWN)
1347 FIXME("Unsupported texture format %#x\n", desc.Format);
1348 return D3DERR_INVALIDCALL;
1351 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1352 return D3DERR_INVALIDCALL;
1354 size.x = 1.0f / desc.Width;
1355 size.y = 1.0f / desc.Height;
1357 data = lock_rect.pBits;
1359 for (y = 0; y < desc.Height; y++)
1361 /* The callback function expects the coordinates of the center
1362 of the texel */
1363 coord.y = (y + 0.5f) / desc.Height;
1365 for (x = 0; x < desc.Width; x++)
1367 coord.x = (x + 0.5f) / desc.Width;
1369 function(&value, &coord, &size, funcdata);
1371 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1373 for (i = 0; i < format->bytes_per_pixel; i++)
1374 pos[i] = 0;
1376 for (c = 0; c < 4; c++)
1378 switch (c)
1380 case 0: /* Alpha */
1381 comp_value = value.w;
1382 break;
1383 case 1: /* Red */
1384 comp_value = value.x;
1385 break;
1386 case 2: /* Green */
1387 comp_value = value.y;
1388 break;
1389 case 3: /* Blue */
1390 comp_value = value.z;
1391 break;
1394 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1396 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1398 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1399 byte = (v << format->shift[c] >> i) & mask;
1400 pos[i / 8] |= byte;
1405 IDirect3DTexture9_UnlockRect(texture, m);
1408 return D3D_OK;
1411 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1412 const void *src_data,
1413 UINT src_data_size,
1414 UINT size,
1415 UINT mip_levels,
1416 DWORD usage,
1417 D3DFORMAT format,
1418 D3DPOOL pool,
1419 DWORD filter,
1420 DWORD mip_filter,
1421 D3DCOLOR color_key,
1422 D3DXIMAGE_INFO *src_info,
1423 PALETTEENTRY *palette,
1424 IDirect3DCubeTexture9 **cube_texture)
1426 HRESULT hr;
1427 D3DCAPS9 caps;
1428 UINT loaded_miplevels;
1429 D3DXIMAGE_INFO img_info;
1430 BOOL dynamic_texture;
1431 BOOL file_size = FALSE;
1432 BOOL file_format = FALSE;
1433 BOOL file_mip_levels = FALSE;
1434 IDirect3DCubeTexture9 *tex, *buftex;
1436 TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
1437 src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
1438 color_key, src_info, palette, cube_texture);
1440 if (!device || !cube_texture || !src_data || !src_data_size)
1441 return D3DERR_INVALIDCALL;
1443 hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
1444 if (FAILED(hr))
1445 return hr;
1447 if (img_info.ImageFileFormat != D3DXIFF_DDS)
1448 return D3DXERR_INVALIDDATA;
1450 if (img_info.Width != img_info.Height)
1451 return D3DXERR_INVALIDDATA;
1453 if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
1454 size = img_info.Width;
1455 if (size == D3DX_DEFAULT)
1456 size = make_pow2(img_info.Width);
1458 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1459 format = img_info.Format;
1461 if (size == D3DX_FROM_FILE)
1463 file_size = TRUE;
1464 size = img_info.Width;
1467 if (format == D3DFMT_FROM_FILE)
1469 file_format = TRUE;
1470 format = img_info.Format;
1473 if (mip_levels == D3DX_FROM_FILE)
1475 file_mip_levels = TRUE;
1476 mip_levels = img_info.MipLevels;
1479 hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
1480 if (FAILED(hr))
1481 return hr;
1483 if ((file_size && size != img_info.Width)
1484 || (file_format && format != img_info.Format)
1485 || (file_mip_levels && mip_levels != img_info.MipLevels))
1486 return D3DERR_NOTAVAILABLE;
1488 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1489 if (FAILED(hr))
1490 return D3DERR_INVALIDCALL;
1492 if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
1494 FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
1495 mip_levels = img_info.MipLevels;
1498 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1499 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1501 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1502 tex = buftex;
1504 else
1506 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1507 buftex = NULL;
1509 if (FAILED(hr))
1510 return hr;
1512 hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info);
1513 if (FAILED(hr))
1515 IDirect3DCubeTexture9_Release(tex);
1516 return hr;
1519 loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels);
1520 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
1521 if (FAILED(hr))
1523 IDirect3DCubeTexture9_Release(tex);
1524 return hr;
1527 if (buftex)
1529 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1530 if (FAILED(hr))
1532 IDirect3DCubeTexture9_Release(buftex);
1533 return hr;
1536 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1537 IDirect3DCubeTexture9_Release(buftex);
1540 if (src_info)
1541 *src_info = img_info;
1543 *cube_texture = tex;
1544 return D3D_OK;
1548 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1549 const char *src_filename,
1550 IDirect3DCubeTexture9 **cube_texture)
1552 int len;
1553 HRESULT hr;
1554 WCHAR *filename;
1555 void *data;
1556 DWORD data_size;
1558 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1560 if (!src_filename) return D3DERR_INVALIDCALL;
1562 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1563 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1564 if (!filename) return E_OUTOFMEMORY;
1565 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1567 hr = map_view_of_file(filename, &data, &data_size);
1568 if (FAILED(hr))
1570 HeapFree(GetProcessHeap(), 0, filename);
1571 return D3DXERR_INVALIDDATA;
1574 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1575 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1577 UnmapViewOfFile(data);
1578 HeapFree(GetProcessHeap(), 0, filename);
1579 return hr;
1582 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1583 const WCHAR *src_filename,
1584 IDirect3DCubeTexture9 **cube_texture)
1586 HRESULT hr;
1587 void *data;
1588 DWORD data_size;
1590 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1592 hr = map_view_of_file(src_filename, &data, &data_size);
1593 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1595 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1596 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1598 UnmapViewOfFile(data);
1599 return hr;
1602 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1603 const char *src_filename,
1604 UINT size,
1605 UINT mip_levels,
1606 DWORD usage,
1607 D3DFORMAT format,
1608 D3DPOOL pool,
1609 DWORD filter,
1610 DWORD mip_filter,
1611 D3DCOLOR color_key,
1612 D3DXIMAGE_INFO *image_info,
1613 PALETTEENTRY *palette,
1614 IDirect3DCubeTexture9 **cube_texture)
1616 int len;
1617 HRESULT hr;
1618 WCHAR *filename;
1619 void *data;
1620 DWORD data_size;
1622 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1623 device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1624 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1626 if (!src_filename) return D3DERR_INVALIDCALL;
1628 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1629 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1630 if (!filename) return E_OUTOFMEMORY;
1631 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1633 hr = map_view_of_file(filename, &data, &data_size);
1634 if (FAILED(hr))
1636 HeapFree(GetProcessHeap(), 0, filename);
1637 return D3DXERR_INVALIDDATA;
1640 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1641 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1643 UnmapViewOfFile(data);
1644 HeapFree(GetProcessHeap(), 0, filename);
1645 return hr;
1648 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1649 const WCHAR *src_filename,
1650 UINT size,
1651 UINT mip_levels,
1652 DWORD usage,
1653 D3DFORMAT format,
1654 D3DPOOL pool,
1655 DWORD filter,
1656 DWORD mip_filter,
1657 D3DCOLOR color_key,
1658 D3DXIMAGE_INFO *image_info,
1659 PALETTEENTRY *palette,
1660 IDirect3DCubeTexture9 **cube_texture)
1662 HRESULT hr;
1663 void *data;
1664 DWORD data_size;
1666 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1667 device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1668 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1670 hr = map_view_of_file(src_filename, &data, &data_size);
1671 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1673 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1674 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1676 UnmapViewOfFile(data);
1677 return hr;
1680 enum cube_coord
1682 XCOORD = 0,
1683 XCOORDINV = 1,
1684 YCOORD = 2,
1685 YCOORDINV = 3,
1686 ZERO = 4,
1687 ONE = 5
1690 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1692 switch (coord)
1694 case XCOORD:
1695 return x + 0.5f;
1696 case XCOORDINV:
1697 return size - x - 0.5f;
1698 case YCOORD:
1699 return y + 0.5f;
1700 case YCOORDINV:
1701 return size - y - 0.5f;
1702 case ZERO:
1703 return 0.0f;
1704 case ONE:
1705 return size;
1706 default:
1707 ERR("Unexpected coordinate value\n");
1708 return 0.0f;
1712 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1713 LPD3DXFILL3D function,
1714 LPVOID funcdata)
1716 DWORD miplevels;
1717 DWORD m, i, x, y, c, f, v;
1718 D3DSURFACE_DESC desc;
1719 D3DLOCKED_RECT lock_rect;
1720 D3DXVECTOR4 value;
1721 D3DXVECTOR3 coord, size;
1722 const PixelFormatDesc *format;
1723 BYTE *data, *pos;
1724 BYTE byte, mask;
1725 float comp_value;
1726 static const enum cube_coord coordmap[6][3] =
1728 {ONE, YCOORDINV, XCOORDINV},
1729 {ZERO, YCOORDINV, XCOORD},
1730 {XCOORD, ONE, YCOORD},
1731 {XCOORD, ZERO, YCOORDINV},
1732 {XCOORD, YCOORDINV, ONE},
1733 {XCOORDINV, YCOORDINV, ZERO}
1736 if (texture == NULL || function == NULL)
1737 return D3DERR_INVALIDCALL;
1739 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1741 for (m = 0; m < miplevels; m++)
1743 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1744 return D3DERR_INVALIDCALL;
1746 format = get_format_info(desc.Format);
1747 if (format->format == D3DFMT_UNKNOWN)
1749 FIXME("Unsupported texture format %#x\n", desc.Format);
1750 return D3DERR_INVALIDCALL;
1753 for (f = 0; f < 6; f++)
1755 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1756 return D3DERR_INVALIDCALL;
1758 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1759 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1760 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1762 data = lock_rect.pBits;
1764 for (y = 0; y < desc.Height; y++)
1766 for (x = 0; x < desc.Width; x++)
1768 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1769 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1770 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1772 function(&value, &coord, &size, funcdata);
1774 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1776 for (i = 0; i < format->bytes_per_pixel; i++)
1777 pos[i] = 0;
1779 for (c = 0; c < 4; c++)
1781 switch (c)
1783 case 0: /* Alpha */
1784 comp_value = value.w;
1785 break;
1786 case 1: /* Red */
1787 comp_value = value.x;
1788 break;
1789 case 2: /* Green */
1790 comp_value = value.y;
1791 break;
1792 case 3: /* Blue */
1793 comp_value = value.z;
1794 break;
1797 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1799 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1801 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1802 byte = (v << format->shift[c] >> i) & mask;
1803 pos[i / 8] |= byte;
1808 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1812 return D3D_OK;
1815 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1816 LPD3DXFILL3D function,
1817 LPVOID funcdata)
1819 DWORD miplevels;
1820 DWORD m, i, x, y, z, c, v;
1821 D3DVOLUME_DESC desc;
1822 D3DLOCKED_BOX lock_box;
1823 D3DXVECTOR4 value;
1824 D3DXVECTOR3 coord, size;
1825 const PixelFormatDesc *format;
1826 BYTE *data, *pos;
1827 BYTE byte, mask;
1828 float comp_value;
1830 if (texture == NULL || function == NULL)
1831 return D3DERR_INVALIDCALL;
1833 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1835 for (m = 0; m < miplevels; m++)
1837 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1838 return D3DERR_INVALIDCALL;
1840 format = get_format_info(desc.Format);
1841 if (format->format == D3DFMT_UNKNOWN)
1843 FIXME("Unsupported texture format %#x\n", desc.Format);
1844 return D3DERR_INVALIDCALL;
1847 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1848 return D3DERR_INVALIDCALL;
1850 size.x = 1.0f / desc.Width;
1851 size.y = 1.0f / desc.Height;
1852 size.z = 1.0f / desc.Depth;
1854 data = lock_box.pBits;
1856 for (z = 0; z < desc.Depth; z++)
1858 /* The callback function expects the coordinates of the center
1859 of the texel */
1860 coord.z = (z + 0.5f) / desc.Depth;
1862 for (y = 0; y < desc.Height; y++)
1864 coord.y = (y + 0.5f) / desc.Height;
1866 for (x = 0; x < desc.Width; x++)
1868 coord.x = (x + 0.5f) / desc.Width;
1870 function(&value, &coord, &size, funcdata);
1872 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1874 for (i = 0; i < format->bytes_per_pixel; i++)
1875 pos[i] = 0;
1877 for (c = 0; c < 4; c++)
1879 switch (c)
1881 case 0: /* Alpha */
1882 comp_value = value.w;
1883 break;
1884 case 1: /* Red */
1885 comp_value = value.x;
1886 break;
1887 case 2: /* Green */
1888 comp_value = value.y;
1889 break;
1890 case 3: /* Blue */
1891 comp_value = value.z;
1892 break;
1895 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1897 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1899 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1900 byte = (v << format->shift[c] >> i) & mask;
1901 pos[i / 8] |= byte;
1907 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1910 return D3D_OK;
1913 HRESULT WINAPI D3DXSaveTextureToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1914 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1916 int len;
1917 WCHAR *filename;
1918 HRESULT hr;
1919 ID3DXBuffer *buffer;
1921 TRACE("(%s, %#x, %p, %p): relay\n",
1922 wine_dbgstr_a(dst_filename), file_format, src_texture, src_palette);
1924 if (!dst_filename) return D3DERR_INVALIDCALL;
1926 len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
1927 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1928 if (!filename) return E_OUTOFMEMORY;
1929 MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
1931 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1932 if (SUCCEEDED(hr))
1934 hr = write_buffer_to_file(filename, buffer);
1935 ID3DXBuffer_Release(buffer);
1938 HeapFree(GetProcessHeap(), 0, filename);
1939 return hr;
1942 HRESULT WINAPI D3DXSaveTextureToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1943 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1945 HRESULT hr;
1946 ID3DXBuffer *buffer;
1948 TRACE("(%s, %#x, %p, %p): relay\n",
1949 wine_dbgstr_w(dst_filename), file_format, src_texture, src_palette);
1951 if (!dst_filename) return D3DERR_INVALIDCALL;
1953 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1954 if (SUCCEEDED(hr))
1956 hr = write_buffer_to_file(dst_filename, buffer);
1957 ID3DXBuffer_Release(buffer);
1960 return hr;
1963 HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format,
1964 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1966 HRESULT hr;
1967 D3DRESOURCETYPE type;
1968 IDirect3DSurface9 *surface;
1970 TRACE("(%p, %#x, %p, %p)\n",
1971 dst_buffer, file_format, src_texture, src_palette);
1973 if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
1975 if (file_format == D3DXIFF_DDS)
1977 FIXME("DDS file format isn't supported yet\n");
1978 return E_NOTIMPL;
1981 type = IDirect3DBaseTexture9_GetType(src_texture);
1982 switch (type)
1984 case D3DRTYPE_TEXTURE:
1985 case D3DRTYPE_CUBETEXTURE:
1986 hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
1987 break;
1988 case D3DRTYPE_VOLUMETEXTURE:
1989 FIXME("Volume textures aren't supported yet\n");
1990 return E_NOTIMPL;
1991 default:
1992 return D3DERR_INVALIDCALL;
1995 if (SUCCEEDED(hr))
1997 hr = D3DXSaveSurfaceToFileInMemory(dst_buffer, file_format, surface, src_palette, NULL);
1998 IDirect3DSurface9_Release(surface);
2001 return hr;