d3dx9: Use structure to pass volume size to pixel format conversion functions.
[wine/multimedia.git] / dlls / d3dx9_36 / texture.c
blob91f97c28efc81948d2a78da1ac4f7bbcce846ec7
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(LPDIRECT3DBASETEXTURE9 texture,
65 CONST PALETTEENTRY *palette,
66 UINT srclevel,
67 DWORD filter)
69 UINT level;
70 HRESULT hr;
71 D3DRESOURCETYPE type;
73 TRACE("(%p, %p, %d, %d)\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 default:
141 FIXME("Implement volume texture filtering\n");
142 return E_NOTIMPL;
146 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
147 UINT* width,
148 UINT* height,
149 UINT* miplevels,
150 DWORD usage,
151 D3DFORMAT* format,
152 D3DPOOL pool)
154 UINT w = (width && *width) ? *width : 1;
155 UINT h = (height && *height) ? *height : 1;
156 D3DCAPS9 caps;
157 D3DDEVICE_CREATION_PARAMETERS params;
158 IDirect3D9 *d3d = NULL;
159 D3DDISPLAYMODE mode;
160 HRESULT hr;
161 D3DFORMAT usedformat = D3DFMT_UNKNOWN;
163 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
165 if (!device)
166 return D3DERR_INVALIDCALL;
168 /* usage */
169 if (usage == D3DX_DEFAULT)
170 usage = 0;
171 if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
172 return D3DERR_INVALIDCALL;
174 /* pool */
175 if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
176 return D3DERR_INVALIDCALL;
178 /* width and height */
179 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
180 return D3DERR_INVALIDCALL;
182 /* 256 x 256 default width/height */
183 if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
184 w = h = 256;
185 else if (w == D3DX_DEFAULT)
186 w = (height ? h : 256);
187 else if (h == D3DX_DEFAULT)
188 h = (width ? w : 256);
190 /* ensure width/height is power of 2 */
191 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
192 w = make_pow2(w);
194 if (w > caps.MaxTextureWidth)
195 w = caps.MaxTextureWidth;
197 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
198 h = make_pow2(h);
200 if (h > caps.MaxTextureHeight)
201 h = caps.MaxTextureHeight;
203 /* texture must be square? */
204 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
206 if (w > h)
207 h = w;
208 else
209 w = h;
212 if (width)
213 *width = w;
215 if (height)
216 *height = h;
218 /* miplevels */
219 if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
221 if (*miplevels > 1)
222 *miplevels = 0;
224 else if (miplevels)
226 UINT max_mipmaps = 1;
228 if (!width && !height)
229 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
230 else
232 UINT max_dimen = max(w, h);
234 while (max_dimen > 1)
236 max_dimen >>= 1;
237 max_mipmaps++;
241 if (*miplevels == 0 || *miplevels > max_mipmaps)
242 *miplevels = max_mipmaps;
245 /* format */
246 if (format)
248 TRACE("Requested format %x\n", *format);
249 usedformat = *format;
252 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
254 if (FAILED(hr))
255 goto cleanup;
257 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
259 if (FAILED(hr))
260 goto cleanup;
262 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
264 if (FAILED(hr))
265 goto cleanup;
267 if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
268 usedformat = D3DFMT_A8R8G8B8;
270 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
271 usage, D3DRTYPE_TEXTURE, usedformat);
273 if (FAILED(hr))
275 /* Heuristic to choose the fallback format */
276 const PixelFormatDesc *fmt = get_format_info(usedformat);
277 BOOL allow_24bits;
278 int bestscore = INT_MIN, i = 0, j;
279 unsigned int channels;
280 const PixelFormatDesc *curfmt;
282 if (!fmt)
284 FIXME("Pixel format %x not handled\n", usedformat);
285 goto cleanup;
288 allow_24bits = fmt->bytes_per_pixel == 3;
289 channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
290 + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
291 usedformat = D3DFMT_UNKNOWN;
293 while ((curfmt = get_format_info_idx(i)))
295 unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
296 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
297 int score;
299 i++;
301 if (curchannels < channels)
302 continue;
303 if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
304 continue;
306 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
307 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
308 if (FAILED(hr))
309 continue;
311 /* This format can be used, let's evaluate it.
312 Weights chosen quite arbitrarily... */
313 score = 16 - 4 * (curchannels - channels);
315 for (j = 0; j < 4; j++)
317 int diff = curfmt->bits[j] - fmt->bits[j];
318 score += 16 - (diff < 0 ? -diff * 4 : diff);
321 if (score > bestscore)
323 bestscore = score;
324 usedformat = curfmt->format;
327 hr = D3D_OK;
330 cleanup:
332 if (d3d)
333 IDirect3D9_Release(d3d);
335 if (FAILED(hr))
336 return hr;
338 if (usedformat == D3DFMT_UNKNOWN)
340 WARN("Couldn't find a suitable pixel format\n");
341 return D3DERR_NOTAVAILABLE;
344 TRACE("Format chosen: %x\n", usedformat);
345 if (format)
346 *format = usedformat;
348 return D3D_OK;
351 HRESULT WINAPI D3DXCheckCubeTextureRequirements(LPDIRECT3DDEVICE9 device,
352 UINT *size,
353 UINT *miplevels,
354 DWORD usage,
355 D3DFORMAT *format,
356 D3DPOOL pool)
358 D3DCAPS9 caps;
359 UINT s = (size && *size) ? *size : 256;
360 HRESULT hr;
362 TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
364 if (s == D3DX_DEFAULT)
365 s = 256;
367 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
368 return D3DERR_INVALIDCALL;
370 if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
371 return D3DERR_NOTAVAILABLE;
373 /* ensure width/height is power of 2 */
374 if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
375 s = make_pow2(s);
377 hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
379 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
381 if(miplevels)
382 *miplevels = 1;
385 if (size)
386 *size = s;
388 return hr;
391 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(LPDIRECT3DDEVICE9 device,
392 UINT *width,
393 UINT *height,
394 UINT *depth,
395 UINT *miplevels,
396 DWORD usage,
397 D3DFORMAT *format,
398 D3DPOOL pool)
400 D3DCAPS9 caps;
401 UINT w = width ? *width : D3DX_DEFAULT;
402 UINT h = height ? *height : D3DX_DEFAULT;
403 UINT d = (depth && *depth) ? *depth : 1;
404 HRESULT hr;
406 TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
407 usage, format, pool);
409 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
410 return D3DERR_INVALIDCALL;
412 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
413 return D3DERR_NOTAVAILABLE;
415 hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
416 if (d == D3DX_DEFAULT)
417 d = 1;
419 /* ensure width/height is power of 2 */
420 if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
421 (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
423 w = make_pow2(w);
424 h = make_pow2(h);
425 d = make_pow2(d);
428 if (w > caps.MaxVolumeExtent)
429 w = caps.MaxVolumeExtent;
430 if (h > caps.MaxVolumeExtent)
431 h = caps.MaxVolumeExtent;
432 if (d > caps.MaxVolumeExtent)
433 d = caps.MaxVolumeExtent;
435 if (miplevels)
437 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
438 *miplevels = 1;
439 else if ((usage & D3DUSAGE_AUTOGENMIPMAP))
441 if (*miplevels > 1)
442 *miplevels = 0;
444 else
446 UINT max_mipmaps = 1;
447 UINT max_dimen = max(max(w, h), d);
449 while (max_dimen > 1)
451 max_dimen >>= 1;
452 max_mipmaps++;
455 if (*miplevels == 0 || *miplevels > max_mipmaps)
456 *miplevels = max_mipmaps;
460 if (width)
461 *width = w;
462 if (height)
463 *height = h;
464 if (depth)
465 *depth = d;
467 return hr;
470 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
471 UINT width,
472 UINT height,
473 UINT miplevels,
474 DWORD usage,
475 D3DFORMAT format,
476 D3DPOOL pool,
477 LPDIRECT3DTEXTURE9 *ppTexture)
479 HRESULT hr;
481 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
482 pool, ppTexture);
484 if (!pDevice || !ppTexture)
485 return D3DERR_INVALIDCALL;
487 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
489 if (FAILED(hr))
490 return hr;
492 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
495 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
496 LPCVOID srcdata,
497 UINT srcdatasize,
498 UINT width,
499 UINT height,
500 UINT miplevels,
501 DWORD usage,
502 D3DFORMAT format,
503 D3DPOOL pool,
504 DWORD filter,
505 DWORD mipfilter,
506 D3DCOLOR colorkey,
507 D3DXIMAGE_INFO* srcinfo,
508 PALETTEENTRY* palette,
509 LPDIRECT3DTEXTURE9* texture)
511 IDirect3DTexture9 **texptr;
512 IDirect3DTexture9 *buftex;
513 IDirect3DSurface9 *surface;
514 BOOL file_width = FALSE, file_height = FALSE;
515 BOOL file_format = FALSE, file_miplevels = FALSE;
516 BOOL dynamic_texture;
517 D3DXIMAGE_INFO imginfo;
518 UINT loaded_miplevels;
519 D3DCAPS9 caps;
520 HRESULT hr;
522 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
523 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
525 /* check for invalid parameters */
526 if (!device || !texture || !srcdata || !srcdatasize)
527 return D3DERR_INVALIDCALL;
529 hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
531 if (FAILED(hr))
533 *texture = NULL;
534 return hr;
537 /* handle default values */
538 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
539 width = imginfo.Width;
541 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
542 height = imginfo.Height;
544 if (width == D3DX_DEFAULT)
545 width = make_pow2(imginfo.Width);
547 if (height == D3DX_DEFAULT)
548 height = make_pow2(imginfo.Height);
550 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
551 format = imginfo.Format;
553 if (width == D3DX_FROM_FILE)
555 file_width = TRUE;
556 width = imginfo.Width;
559 if (height == D3DX_FROM_FILE)
561 file_height = TRUE;
562 height = imginfo.Height;
565 if (format == D3DFMT_FROM_FILE)
567 file_format = TRUE;
568 format = imginfo.Format;
571 if (miplevels == D3DX_FROM_FILE)
573 file_miplevels = TRUE;
574 miplevels = imginfo.MipLevels;
577 /* fix texture creation parameters */
578 hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
580 if (FAILED(hr))
582 *texture = NULL;
583 return hr;
586 if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
588 FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
589 miplevels = imginfo.MipLevels;
592 if (((file_width) && (width != imginfo.Width)) ||
593 ((file_height) && (height != imginfo.Height)) ||
594 ((file_format) && (format != imginfo.Format)) ||
595 ((file_miplevels) && (miplevels != imginfo.MipLevels)))
597 return D3DERR_NOTAVAILABLE;
600 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
601 return D3DERR_INVALIDCALL;
603 /* Create the to-be-filled texture */
604 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
605 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
607 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
608 texptr = &buftex;
610 else
612 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
613 texptr = texture;
616 if (FAILED(hr))
618 *texture = NULL;
619 return hr;
622 /* Load the file */
623 if (imginfo.ImageFileFormat != D3DXIFF_DDS)
625 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
626 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
627 IDirect3DSurface9_Release(surface);
629 else
631 hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
634 if (FAILED(hr))
636 IDirect3DTexture9_Release(*texptr);
637 *texture = NULL;
638 return hr;
641 loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
642 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
644 if (FAILED(hr))
646 IDirect3DTexture9_Release(*texptr);
647 *texture = NULL;
648 return hr;
651 /* Move the data to the actual texture if necessary */
652 if (texptr == &buftex)
654 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
656 if (FAILED(hr))
658 IDirect3DTexture9_Release(buftex);
659 *texture = NULL;
660 return hr;
663 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
664 IDirect3DTexture9_Release(buftex);
667 if (srcinfo)
668 *srcinfo = imginfo;
670 return D3D_OK;
673 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
674 LPCVOID srcdata,
675 UINT srcdatasize,
676 LPDIRECT3DTEXTURE9 *texture)
678 TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
680 return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
681 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
684 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
685 LPCWSTR srcfile,
686 UINT width,
687 UINT height,
688 UINT miplevels,
689 DWORD usage,
690 D3DFORMAT format,
691 D3DPOOL pool,
692 DWORD filter,
693 DWORD mipfilter,
694 D3DCOLOR colorkey,
695 D3DXIMAGE_INFO *srcinfo,
696 PALETTEENTRY *palette,
697 LPDIRECT3DTEXTURE9 *texture)
699 HRESULT hr;
700 DWORD size;
701 LPVOID buffer;
703 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
704 device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
705 mipfilter, colorkey, srcinfo, palette, texture);
707 if (!srcfile)
708 return D3DERR_INVALIDCALL;
710 hr = map_view_of_file(srcfile, &buffer, &size);
711 if (FAILED(hr))
712 return D3DXERR_INVALIDDATA;
714 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
715 filter, mipfilter, colorkey, srcinfo, palette, texture);
717 UnmapViewOfFile(buffer);
719 return hr;
722 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
723 LPCSTR srcfile,
724 UINT width,
725 UINT height,
726 UINT miplevels,
727 DWORD usage,
728 D3DFORMAT format,
729 D3DPOOL pool,
730 DWORD filter,
731 DWORD mipfilter,
732 D3DCOLOR colorkey,
733 D3DXIMAGE_INFO *srcinfo,
734 PALETTEENTRY *palette,
735 LPDIRECT3DTEXTURE9 *texture)
737 LPWSTR widename;
738 HRESULT hr;
739 DWORD len;
741 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
742 device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
743 mipfilter, colorkey, srcinfo, palette, texture);
745 if (!device || !srcfile || !texture)
746 return D3DERR_INVALIDCALL;
748 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
749 widename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*widename));
750 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
752 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
753 usage, format, pool, filter, mipfilter,
754 colorkey, srcinfo, palette, texture);
756 HeapFree(GetProcessHeap(), 0, widename);
757 return hr;
760 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
761 LPCSTR srcfile,
762 LPDIRECT3DTEXTURE9 *texture)
764 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
766 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
767 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
770 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
771 LPCWSTR srcfile,
772 LPDIRECT3DTEXTURE9 *texture)
774 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
776 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
777 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
781 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
782 HMODULE srcmodule,
783 LPCSTR resource,
784 LPDIRECT3DTEXTURE9 *texture)
786 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
788 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
789 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
792 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
793 HMODULE srcmodule,
794 LPCWSTR resource,
795 LPDIRECT3DTEXTURE9 *texture)
797 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
799 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
800 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
803 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
804 HMODULE srcmodule,
805 LPCSTR resource,
806 UINT width,
807 UINT height,
808 UINT miplevels,
809 DWORD usage,
810 D3DFORMAT format,
811 D3DPOOL pool,
812 DWORD filter,
813 DWORD mipfilter,
814 D3DCOLOR colorkey,
815 D3DXIMAGE_INFO *srcinfo,
816 PALETTEENTRY *palette,
817 LPDIRECT3DTEXTURE9 *texture)
819 HRSRC resinfo;
821 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
823 if (!device || !texture)
824 return D3DERR_INVALIDCALL;
826 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
828 if (resinfo)
830 LPVOID buffer;
831 HRESULT hr;
832 DWORD size;
834 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
836 if (FAILED(hr))
837 return D3DXERR_INVALIDDATA;
839 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
840 height, miplevels, usage, format,
841 pool, filter, mipfilter, colorkey,
842 srcinfo, palette, texture);
845 /* Try loading the resource as bitmap data */
846 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
848 if (resinfo)
850 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
851 return E_NOTIMPL;
854 return D3DXERR_INVALIDDATA;
857 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
858 HMODULE srcmodule,
859 LPCWSTR resource,
860 UINT width,
861 UINT height,
862 UINT miplevels,
863 DWORD usage,
864 D3DFORMAT format,
865 D3DPOOL pool,
866 DWORD filter,
867 DWORD mipfilter,
868 D3DCOLOR colorkey,
869 D3DXIMAGE_INFO *srcinfo,
870 PALETTEENTRY *palette,
871 LPDIRECT3DTEXTURE9 *texture)
873 HRSRC resinfo;
875 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
877 if (!device || !texture)
878 return D3DERR_INVALIDCALL;
880 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
882 if (resinfo)
884 LPVOID buffer;
885 HRESULT hr;
886 DWORD size;
888 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
890 if (FAILED(hr))
891 return D3DXERR_INVALIDDATA;
893 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
894 height, miplevels, usage, format,
895 pool, filter, mipfilter, colorkey,
896 srcinfo, palette, texture);
899 /* Try loading the resource as bitmap data */
900 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
902 if (resinfo)
904 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
905 return E_NOTIMPL;
908 return D3DXERR_INVALIDDATA;
911 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
912 UINT size,
913 UINT miplevels,
914 DWORD usage,
915 D3DFORMAT format,
916 D3DPOOL pool,
917 LPDIRECT3DCUBETEXTURE9 *texture)
919 HRESULT hr;
921 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
922 pool, texture);
924 if (!device || !texture)
925 return D3DERR_INVALIDCALL;
927 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
929 if (FAILED(hr))
931 TRACE("D3DXCheckCubeTextureRequirements failed\n");
932 return hr;
935 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
938 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
939 LPCVOID data,
940 UINT datasize,
941 LPDIRECT3DCUBETEXTURE9 *texture)
943 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
945 return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
946 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
949 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
950 UINT width,
951 UINT height,
952 UINT depth,
953 UINT miplevels,
954 DWORD usage,
955 D3DFORMAT format,
956 D3DPOOL pool,
957 LPDIRECT3DVOLUMETEXTURE9 *texture)
959 HRESULT hr;
961 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
962 miplevels, usage, format, pool, texture);
964 if (!device || !texture)
965 return D3DERR_INVALIDCALL;
967 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
968 &miplevels, usage, &format, pool);
970 if (FAILED(hr))
972 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
973 return hr;
976 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
977 usage, format, pool, texture, NULL);
980 HRESULT WINAPI D3DXCreateVolumeTextureFromFileA(IDirect3DDevice9 *device,
981 const char *filename,
982 IDirect3DVolumeTexture9 **volume_texture)
984 int len;
985 HRESULT hr;
986 void *data;
987 DWORD data_size;
988 WCHAR *filenameW;
990 TRACE("(%p, %s, %p): relay\n",
991 device, debugstr_a(filename), volume_texture);
993 if (!filename) return D3DERR_INVALIDCALL;
995 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
996 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
997 if (!filenameW) return E_OUTOFMEMORY;
998 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1000 hr = map_view_of_file(filenameW, &data, &data_size);
1001 HeapFree(GetProcessHeap(), 0, filenameW);
1002 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1004 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1005 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1007 UnmapViewOfFile(data);
1008 return hr;
1011 HRESULT WINAPI D3DXCreateVolumeTextureFromFileW(IDirect3DDevice9 *device,
1012 const WCHAR *filename,
1013 IDirect3DVolumeTexture9 **volume_texture)
1015 HRESULT hr;
1016 void *data;
1017 DWORD data_size;
1019 TRACE("(%p, %s, %p): relay\n",
1020 device, debugstr_w(filename), volume_texture);
1022 if (!filename) return D3DERR_INVALIDCALL;
1024 hr = map_view_of_file(filename, &data, &data_size);
1025 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1027 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1028 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1030 UnmapViewOfFile(data);
1031 return hr;
1034 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExA(IDirect3DDevice9 *device,
1035 const char *filename,
1036 UINT width,
1037 UINT height,
1038 UINT depth,
1039 UINT mip_levels,
1040 DWORD usage,
1041 D3DFORMAT format,
1042 D3DPOOL pool,
1043 DWORD filter,
1044 DWORD mip_filter,
1045 D3DCOLOR color_key,
1046 D3DXIMAGE_INFO *src_info,
1047 PALETTEENTRY *palette,
1048 IDirect3DVolumeTexture9 **volume_texture)
1050 int len;
1051 HRESULT hr;
1052 WCHAR *filenameW;
1053 void *data;
1054 DWORD data_size;
1056 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1057 device, debugstr_a(filename), width, height, depth, mip_levels,
1058 usage, format, pool, filter, mip_filter, color_key, src_info,
1059 palette, volume_texture);
1061 if (!filename) return D3DERR_INVALIDCALL;
1063 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1064 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1065 if (!filenameW) return E_OUTOFMEMORY;
1066 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1068 hr = map_view_of_file(filenameW, &data, &data_size);
1069 HeapFree(GetProcessHeap(), 0, filenameW);
1070 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1072 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1073 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1074 volume_texture);
1076 UnmapViewOfFile(data);
1077 return hr;
1080 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExW(IDirect3DDevice9 *device,
1081 const WCHAR *filename,
1082 UINT width,
1083 UINT height,
1084 UINT depth,
1085 UINT mip_levels,
1086 DWORD usage,
1087 D3DFORMAT format,
1088 D3DPOOL pool,
1089 DWORD filter,
1090 DWORD mip_filter,
1091 D3DCOLOR color_key,
1092 D3DXIMAGE_INFO *src_info,
1093 PALETTEENTRY *palette,
1094 IDirect3DVolumeTexture9 **volume_texture)
1096 HRESULT hr;
1097 void *data;
1098 DWORD data_size;
1100 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1101 device, debugstr_w(filename), width, height, depth, mip_levels,
1102 usage, format, pool, filter, mip_filter, color_key, src_info,
1103 palette, volume_texture);
1105 if (!filename) return D3DERR_INVALIDCALL;
1107 hr = map_view_of_file(filename, &data, &data_size);
1108 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1110 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1111 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1112 volume_texture);
1114 UnmapViewOfFile(data);
1115 return hr;
1118 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device,
1119 const void *data,
1120 UINT data_size,
1121 IDirect3DVolumeTexture9 **volume_texture)
1123 TRACE("(%p, %p, %u, %p): relay\n", device, data, data_size, volume_texture);
1125 return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1126 D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
1127 0, NULL, NULL, volume_texture);
1130 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1131 const void *data,
1132 UINT data_size,
1133 UINT width,
1134 UINT height,
1135 UINT depth,
1136 UINT mip_levels,
1137 DWORD usage,
1138 D3DFORMAT format,
1139 D3DPOOL pool,
1140 DWORD filter,
1141 DWORD mip_filter,
1142 D3DCOLOR color_key,
1143 D3DXIMAGE_INFO *info,
1144 PALETTEENTRY *palette,
1145 IDirect3DVolumeTexture9 **volume_texture)
1147 HRESULT hr;
1148 D3DCAPS9 caps;
1149 D3DXIMAGE_INFO image_info;
1150 BOOL dynamic_texture;
1151 BOOL file_width = FALSE;
1152 BOOL file_height = FALSE;
1153 BOOL file_depth = FALSE;
1154 BOOL file_format = FALSE;
1155 BOOL file_mip_levels = FALSE;
1156 IDirect3DVolumeTexture9 *tex, *buftex;
1158 TRACE("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n",
1159 device, data, data_size, width, height, depth, mip_levels, usage, format, pool,
1160 filter, mip_filter, color_key, info, palette, volume_texture);
1162 if (!device || !data || !data_size || !volume_texture)
1163 return D3DERR_INVALIDCALL;
1165 hr = D3DXGetImageInfoFromFileInMemory(data, data_size, &image_info);
1166 if (FAILED(hr)) return hr;
1168 if (image_info.ImageFileFormat != D3DXIFF_DDS)
1169 return D3DXERR_INVALIDDATA;
1171 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
1172 width = image_info.Width;
1173 if (width == D3DX_DEFAULT)
1174 width = make_pow2(image_info.Width);
1176 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
1177 height = image_info.Height;
1178 if (height == D3DX_DEFAULT)
1179 height = make_pow2(image_info.Height);
1181 if (depth == 0 || depth == D3DX_DEFAULT_NONPOW2)
1182 depth = image_info.Depth;
1183 if (depth == D3DX_DEFAULT)
1184 depth = make_pow2(image_info.Depth);
1186 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1187 format = image_info.Format;
1189 if (width == D3DX_FROM_FILE)
1191 file_width = TRUE;
1192 width = image_info.Width;
1195 if (height == D3DX_FROM_FILE)
1197 file_height = TRUE;
1198 height = image_info.Height;
1201 if (depth == D3DX_FROM_FILE)
1203 file_depth = TRUE;
1204 depth = image_info.Depth;
1207 if (format == D3DFMT_FROM_FILE)
1209 file_format = TRUE;
1210 format = image_info.Format;
1213 if (mip_levels == D3DX_FROM_FILE)
1215 file_mip_levels = TRUE;
1216 mip_levels = image_info.MipLevels;
1219 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mip_levels, usage, &format, pool);
1220 if (FAILED(hr)) return hr;
1222 if ((file_width && width != image_info.Width)
1223 || (file_height && height != image_info.Height)
1224 || (file_depth && depth != image_info.Depth)
1225 || (file_format && format != image_info.Format)
1226 || (file_mip_levels && mip_levels != image_info.MipLevels))
1227 return D3DERR_NOTAVAILABLE;
1229 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1230 if (FAILED(hr))
1231 return D3DERR_INVALIDCALL;
1233 if (mip_levels > image_info.MipLevels)
1235 FIXME("Generation of mipmaps for volume textures is not implemented yet\n");
1236 mip_levels = image_info.MipLevels;
1239 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1240 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1242 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1243 tex = buftex;
1245 else
1247 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1248 buftex = NULL;
1251 if (FAILED(hr)) return hr;
1253 hr = load_volume_texture_from_dds(tex, data, palette, filter, color_key, &image_info);
1254 if (FAILED(hr))
1256 IDirect3DVolumeTexture9_Release(tex);
1257 return hr;
1260 if (buftex)
1262 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1263 if (FAILED(hr))
1265 IDirect3DVolumeTexture9_Release(buftex);
1266 return hr;
1269 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1270 IDirect3DVolumeTexture9_Release(buftex);
1273 if (info)
1274 *info = image_info;
1276 *volume_texture = tex;
1277 return D3D_OK;
1280 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
1281 LPD3DXFILL2D function,
1282 LPVOID funcdata)
1284 DWORD miplevels;
1285 DWORD m, i, x, y, c, v;
1286 D3DSURFACE_DESC desc;
1287 D3DLOCKED_RECT lock_rect;
1288 D3DXVECTOR4 value;
1289 D3DXVECTOR2 coord, size;
1290 const PixelFormatDesc *format;
1291 BYTE *data, *pos;
1292 BYTE byte, mask;
1293 float comp_value;
1295 if (texture == NULL || function == NULL)
1296 return D3DERR_INVALIDCALL;
1298 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1300 for (m = 0; m < miplevels; m++)
1302 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1303 return D3DERR_INVALIDCALL;
1305 format = get_format_info(desc.Format);
1306 if (format->format == D3DFMT_UNKNOWN)
1308 FIXME("Unsupported texture format %#x\n", desc.Format);
1309 return D3DERR_INVALIDCALL;
1312 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1313 return D3DERR_INVALIDCALL;
1315 size.x = 1.0f / desc.Width;
1316 size.y = 1.0f / desc.Height;
1318 data = lock_rect.pBits;
1320 for (y = 0; y < desc.Height; y++)
1322 /* The callback function expects the coordinates of the center
1323 of the texel */
1324 coord.y = (y + 0.5f) / desc.Height;
1326 for (x = 0; x < desc.Width; x++)
1328 coord.x = (x + 0.5f) / desc.Width;
1330 function(&value, &coord, &size, funcdata);
1332 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1334 for (i = 0; i < format->bytes_per_pixel; i++)
1335 pos[i] = 0;
1337 for (c = 0; c < 4; c++)
1339 switch (c)
1341 case 0: /* Alpha */
1342 comp_value = value.w;
1343 break;
1344 case 1: /* Red */
1345 comp_value = value.x;
1346 break;
1347 case 2: /* Green */
1348 comp_value = value.y;
1349 break;
1350 case 3: /* Blue */
1351 comp_value = value.z;
1352 break;
1355 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1357 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1359 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1360 byte = (v << format->shift[c] >> i) & mask;
1361 pos[i / 8] |= byte;
1366 IDirect3DTexture9_UnlockRect(texture, m);
1369 return D3D_OK;
1372 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1373 const void *src_data,
1374 UINT src_data_size,
1375 UINT size,
1376 UINT mip_levels,
1377 DWORD usage,
1378 D3DFORMAT format,
1379 D3DPOOL pool,
1380 DWORD filter,
1381 DWORD mip_filter,
1382 D3DCOLOR color_key,
1383 D3DXIMAGE_INFO *src_info,
1384 PALETTEENTRY *palette,
1385 IDirect3DCubeTexture9 **cube_texture)
1387 HRESULT hr;
1388 D3DCAPS9 caps;
1389 UINT loaded_miplevels;
1390 D3DXIMAGE_INFO img_info;
1391 BOOL dynamic_texture;
1392 BOOL file_size = FALSE;
1393 BOOL file_format = FALSE;
1394 BOOL file_mip_levels = FALSE;
1395 IDirect3DCubeTexture9 *tex, *buftex;
1397 TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
1398 src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
1399 color_key, src_info, palette, cube_texture);
1401 if (!device || !cube_texture || !src_data || !src_data_size)
1402 return D3DERR_INVALIDCALL;
1404 hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
1405 if (FAILED(hr))
1406 return hr;
1408 if (img_info.ImageFileFormat != D3DXIFF_DDS)
1409 return D3DXERR_INVALIDDATA;
1411 if (img_info.Width != img_info.Height)
1412 return D3DXERR_INVALIDDATA;
1414 if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
1415 size = img_info.Width;
1416 if (size == D3DX_DEFAULT)
1417 size = make_pow2(img_info.Width);
1419 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1420 format = img_info.Format;
1422 if (size == D3DX_FROM_FILE)
1424 file_size = TRUE;
1425 size = img_info.Width;
1428 if (format == D3DFMT_FROM_FILE)
1430 file_format = TRUE;
1431 format = img_info.Format;
1434 if (mip_levels == D3DX_FROM_FILE)
1436 file_mip_levels = TRUE;
1437 mip_levels = img_info.MipLevels;
1440 hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
1441 if (FAILED(hr))
1442 return hr;
1444 if ((file_size && size != img_info.Width)
1445 || (file_format && format != img_info.Format)
1446 || (file_mip_levels && mip_levels != img_info.MipLevels))
1447 return D3DERR_NOTAVAILABLE;
1449 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1450 if (FAILED(hr))
1451 return D3DERR_INVALIDCALL;
1453 if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
1455 FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
1456 mip_levels = img_info.MipLevels;
1459 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1460 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1462 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1463 tex = buftex;
1465 else
1467 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1468 buftex = NULL;
1470 if (FAILED(hr))
1471 return hr;
1473 hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info);
1474 if (FAILED(hr))
1476 IDirect3DCubeTexture9_Release(tex);
1477 return hr;
1480 loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels);
1481 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
1482 if (FAILED(hr))
1484 IDirect3DCubeTexture9_Release(tex);
1485 return hr;
1488 if (buftex)
1490 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1491 if (FAILED(hr))
1493 IDirect3DCubeTexture9_Release(buftex);
1494 return hr;
1497 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1498 IDirect3DCubeTexture9_Release(buftex);
1501 if (src_info)
1502 *src_info = img_info;
1504 *cube_texture = tex;
1505 return D3D_OK;
1509 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1510 const char *src_filename,
1511 IDirect3DCubeTexture9 **cube_texture)
1513 int len;
1514 HRESULT hr;
1515 WCHAR *filename;
1516 void *data;
1517 DWORD data_size;
1519 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1521 if (!src_filename) return D3DERR_INVALIDCALL;
1523 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1524 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1525 if (!filename) return E_OUTOFMEMORY;
1526 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1528 hr = map_view_of_file(filename, &data, &data_size);
1529 if (FAILED(hr))
1531 HeapFree(GetProcessHeap(), 0, filename);
1532 return D3DXERR_INVALIDDATA;
1535 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1536 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1538 UnmapViewOfFile(data);
1539 HeapFree(GetProcessHeap(), 0, filename);
1540 return hr;
1543 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1544 const WCHAR *src_filename,
1545 IDirect3DCubeTexture9 **cube_texture)
1547 HRESULT hr;
1548 void *data;
1549 DWORD data_size;
1551 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1553 hr = map_view_of_file(src_filename, &data, &data_size);
1554 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1556 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1557 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1559 UnmapViewOfFile(data);
1560 return hr;
1563 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1564 const char *src_filename,
1565 UINT size,
1566 UINT mip_levels,
1567 DWORD usage,
1568 D3DFORMAT format,
1569 D3DPOOL pool,
1570 DWORD filter,
1571 DWORD mip_filter,
1572 D3DCOLOR color_key,
1573 D3DXIMAGE_INFO *image_info,
1574 PALETTEENTRY *palette,
1575 IDirect3DCubeTexture9 **cube_texture)
1577 int len;
1578 HRESULT hr;
1579 WCHAR *filename;
1580 void *data;
1581 DWORD data_size;
1583 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1584 device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1585 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1587 if (!src_filename) return D3DERR_INVALIDCALL;
1589 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1590 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1591 if (!filename) return E_OUTOFMEMORY;
1592 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1594 hr = map_view_of_file(filename, &data, &data_size);
1595 if (FAILED(hr))
1597 HeapFree(GetProcessHeap(), 0, filename);
1598 return D3DXERR_INVALIDDATA;
1601 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1602 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1604 UnmapViewOfFile(data);
1605 HeapFree(GetProcessHeap(), 0, filename);
1606 return hr;
1609 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1610 const WCHAR *src_filename,
1611 UINT size,
1612 UINT mip_levels,
1613 DWORD usage,
1614 D3DFORMAT format,
1615 D3DPOOL pool,
1616 DWORD filter,
1617 DWORD mip_filter,
1618 D3DCOLOR color_key,
1619 D3DXIMAGE_INFO *image_info,
1620 PALETTEENTRY *palette,
1621 IDirect3DCubeTexture9 **cube_texture)
1623 HRESULT hr;
1624 void *data;
1625 DWORD data_size;
1627 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1628 device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1629 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1631 hr = map_view_of_file(src_filename, &data, &data_size);
1632 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1634 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1635 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1637 UnmapViewOfFile(data);
1638 return hr;
1641 enum cube_coord
1643 XCOORD = 0,
1644 XCOORDINV = 1,
1645 YCOORD = 2,
1646 YCOORDINV = 3,
1647 ZERO = 4,
1648 ONE = 5
1651 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1653 switch (coord)
1655 case XCOORD:
1656 return x + 0.5f;
1657 case XCOORDINV:
1658 return size - x - 0.5f;
1659 case YCOORD:
1660 return y + 0.5f;
1661 case YCOORDINV:
1662 return size - y - 0.5f;
1663 case ZERO:
1664 return 0.0f;
1665 case ONE:
1666 return size;
1667 default:
1668 ERR("Unexpected coordinate value\n");
1669 return 0.0f;
1673 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1674 LPD3DXFILL3D function,
1675 LPVOID funcdata)
1677 DWORD miplevels;
1678 DWORD m, i, x, y, c, f, v;
1679 D3DSURFACE_DESC desc;
1680 D3DLOCKED_RECT lock_rect;
1681 D3DXVECTOR4 value;
1682 D3DXVECTOR3 coord, size;
1683 const PixelFormatDesc *format;
1684 BYTE *data, *pos;
1685 BYTE byte, mask;
1686 float comp_value;
1687 static const enum cube_coord coordmap[6][3] =
1689 {ONE, YCOORDINV, XCOORDINV},
1690 {ZERO, YCOORDINV, XCOORD},
1691 {XCOORD, ONE, YCOORD},
1692 {XCOORD, ZERO, YCOORDINV},
1693 {XCOORD, YCOORDINV, ONE},
1694 {XCOORDINV, YCOORDINV, ZERO}
1697 if (texture == NULL || function == NULL)
1698 return D3DERR_INVALIDCALL;
1700 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1702 for (m = 0; m < miplevels; m++)
1704 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1705 return D3DERR_INVALIDCALL;
1707 format = get_format_info(desc.Format);
1708 if (format->format == D3DFMT_UNKNOWN)
1710 FIXME("Unsupported texture format %#x\n", desc.Format);
1711 return D3DERR_INVALIDCALL;
1714 for (f = 0; f < 6; f++)
1716 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1717 return D3DERR_INVALIDCALL;
1719 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1720 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1721 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1723 data = lock_rect.pBits;
1725 for (y = 0; y < desc.Height; y++)
1727 for (x = 0; x < desc.Width; x++)
1729 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1730 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1731 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1733 function(&value, &coord, &size, funcdata);
1735 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1737 for (i = 0; i < format->bytes_per_pixel; i++)
1738 pos[i] = 0;
1740 for (c = 0; c < 4; c++)
1742 switch (c)
1744 case 0: /* Alpha */
1745 comp_value = value.w;
1746 break;
1747 case 1: /* Red */
1748 comp_value = value.x;
1749 break;
1750 case 2: /* Green */
1751 comp_value = value.y;
1752 break;
1753 case 3: /* Blue */
1754 comp_value = value.z;
1755 break;
1758 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1760 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1762 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1763 byte = (v << format->shift[c] >> i) & mask;
1764 pos[i / 8] |= byte;
1769 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1773 return D3D_OK;
1776 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1777 LPD3DXFILL3D function,
1778 LPVOID funcdata)
1780 DWORD miplevels;
1781 DWORD m, i, x, y, z, c, v;
1782 D3DVOLUME_DESC desc;
1783 D3DLOCKED_BOX lock_box;
1784 D3DXVECTOR4 value;
1785 D3DXVECTOR3 coord, size;
1786 const PixelFormatDesc *format;
1787 BYTE *data, *pos;
1788 BYTE byte, mask;
1789 float comp_value;
1791 if (texture == NULL || function == NULL)
1792 return D3DERR_INVALIDCALL;
1794 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1796 for (m = 0; m < miplevels; m++)
1798 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1799 return D3DERR_INVALIDCALL;
1801 format = get_format_info(desc.Format);
1802 if (format->format == D3DFMT_UNKNOWN)
1804 FIXME("Unsupported texture format %#x\n", desc.Format);
1805 return D3DERR_INVALIDCALL;
1808 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1809 return D3DERR_INVALIDCALL;
1811 size.x = 1.0f / desc.Width;
1812 size.y = 1.0f / desc.Height;
1813 size.z = 1.0f / desc.Depth;
1815 data = lock_box.pBits;
1817 for (z = 0; z < desc.Depth; z++)
1819 /* The callback function expects the coordinates of the center
1820 of the texel */
1821 coord.z = (z + 0.5f) / desc.Depth;
1823 for (y = 0; y < desc.Height; y++)
1825 coord.y = (y + 0.5f) / desc.Height;
1827 for (x = 0; x < desc.Width; x++)
1829 coord.x = (x + 0.5f) / desc.Width;
1831 function(&value, &coord, &size, funcdata);
1833 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1835 for (i = 0; i < format->bytes_per_pixel; i++)
1836 pos[i] = 0;
1838 for (c = 0; c < 4; c++)
1840 switch (c)
1842 case 0: /* Alpha */
1843 comp_value = value.w;
1844 break;
1845 case 1: /* Red */
1846 comp_value = value.x;
1847 break;
1848 case 2: /* Green */
1849 comp_value = value.y;
1850 break;
1851 case 3: /* Blue */
1852 comp_value = value.z;
1853 break;
1856 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1858 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1860 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1861 byte = (v << format->shift[c] >> i) & mask;
1862 pos[i / 8] |= byte;
1868 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1871 return D3D_OK;
1874 HRESULT WINAPI D3DXSaveTextureToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1875 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1877 int len;
1878 WCHAR *filename;
1879 HRESULT hr;
1880 ID3DXBuffer *buffer;
1882 TRACE("(%s, %#x, %p, %p): relay\n",
1883 wine_dbgstr_a(dst_filename), file_format, src_texture, src_palette);
1885 if (!dst_filename) return D3DERR_INVALIDCALL;
1887 len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
1888 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1889 if (!filename) return E_OUTOFMEMORY;
1890 MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
1892 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1893 if (SUCCEEDED(hr))
1895 hr = write_buffer_to_file(filename, buffer);
1896 ID3DXBuffer_Release(buffer);
1899 HeapFree(GetProcessHeap(), 0, filename);
1900 return hr;
1903 HRESULT WINAPI D3DXSaveTextureToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1904 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1906 HRESULT hr;
1907 ID3DXBuffer *buffer;
1909 TRACE("(%s, %#x, %p, %p): relay\n",
1910 wine_dbgstr_w(dst_filename), file_format, src_texture, src_palette);
1912 if (!dst_filename) return D3DERR_INVALIDCALL;
1914 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1915 if (SUCCEEDED(hr))
1917 hr = write_buffer_to_file(dst_filename, buffer);
1918 ID3DXBuffer_Release(buffer);
1921 return hr;
1924 HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format,
1925 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1927 HRESULT hr;
1928 D3DRESOURCETYPE type;
1929 IDirect3DSurface9 *surface;
1931 TRACE("(%p, %#x, %p, %p)\n",
1932 dst_buffer, file_format, src_texture, src_palette);
1934 if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
1936 if (file_format == D3DXIFF_DDS)
1938 FIXME("DDS file format isn't supported yet\n");
1939 return E_NOTIMPL;
1942 type = IDirect3DBaseTexture9_GetType(src_texture);
1943 switch (type)
1945 case D3DRTYPE_TEXTURE:
1946 case D3DRTYPE_CUBETEXTURE:
1947 hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
1948 break;
1949 case D3DRTYPE_VOLUMETEXTURE:
1950 FIXME("Volume textures aren't supported yet\n");
1951 return E_NOTIMPL;
1952 default:
1953 return D3DERR_INVALIDCALL;
1956 if (SUCCEEDED(hr))
1958 hr = D3DXSaveSurfaceToFileInMemory(dst_buffer, file_format, surface, src_palette, NULL);
1959 IDirect3DSurface9_Release(surface);
1962 return hr;