d3dx9_36: Print the debug string and not the pointer to it.
[wine/multimedia.git] / dlls / d3dx9_36 / texture.c
blob4fc6effc02d008faebb9a255befd0d2d1775e24a
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)
221 UINT max_mipmaps = 1;
223 if (!width && !height)
224 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
225 else
227 UINT max_dimen = max(w, h);
229 while (max_dimen > 1)
231 max_dimen >>= 1;
232 max_mipmaps++;
236 if (*miplevels == 0 || *miplevels > max_mipmaps)
237 *miplevels = max_mipmaps;
240 /* format */
241 if (format)
243 TRACE("Requested format %x\n", *format);
244 usedformat = *format;
247 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
249 if (FAILED(hr))
250 goto cleanup;
252 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
254 if (FAILED(hr))
255 goto cleanup;
257 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
259 if (FAILED(hr))
260 goto cleanup;
262 if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
263 usedformat = D3DFMT_A8R8G8B8;
265 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
266 usage, D3DRTYPE_TEXTURE, usedformat);
268 if (FAILED(hr))
270 /* Heuristic to choose the fallback format */
271 const PixelFormatDesc *fmt = get_format_info(usedformat);
272 BOOL allow_24bits;
273 int bestscore = INT_MIN, i = 0, j;
274 unsigned int channels;
275 const PixelFormatDesc *curfmt;
277 if (!fmt)
279 FIXME("Pixel format %x not handled\n", usedformat);
280 goto cleanup;
283 allow_24bits = fmt->bytes_per_pixel == 3;
284 channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
285 + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
286 usedformat = D3DFMT_UNKNOWN;
288 while ((curfmt = get_format_info_idx(i)))
290 unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
291 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
292 int score;
294 i++;
296 if (curchannels < channels)
297 continue;
298 if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
299 continue;
301 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
302 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
303 if (FAILED(hr))
304 continue;
306 /* This format can be used, let's evaluate it.
307 Weights chosen quite arbitrarily... */
308 score = 16 - 4 * (curchannels - channels);
310 for (j = 0; j < 4; j++)
312 int diff = curfmt->bits[j] - fmt->bits[j];
313 score += 16 - (diff < 0 ? -diff * 4 : diff);
316 if (score > bestscore)
318 bestscore = score;
319 usedformat = curfmt->format;
322 hr = D3D_OK;
325 cleanup:
327 if (d3d)
328 IDirect3D9_Release(d3d);
330 if (FAILED(hr))
331 return hr;
333 if (usedformat == D3DFMT_UNKNOWN)
335 WARN("Couldn't find a suitable pixel format\n");
336 return D3DERR_NOTAVAILABLE;
339 TRACE("Format chosen: %x\n", usedformat);
340 if (format)
341 *format = usedformat;
343 return D3D_OK;
346 HRESULT WINAPI D3DXCheckCubeTextureRequirements(LPDIRECT3DDEVICE9 device,
347 UINT *size,
348 UINT *miplevels,
349 DWORD usage,
350 D3DFORMAT *format,
351 D3DPOOL pool)
353 D3DCAPS9 caps;
354 UINT s = (size && *size) ? *size : 256;
355 HRESULT hr;
357 TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
359 if (s == D3DX_DEFAULT)
360 s = 256;
362 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
363 return D3DERR_INVALIDCALL;
365 if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
366 return D3DERR_NOTAVAILABLE;
368 /* ensure width/height is power of 2 */
369 if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
370 s = make_pow2(s);
372 hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
374 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
376 if(miplevels)
377 *miplevels = 1;
380 if (size)
381 *size = s;
383 return hr;
386 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(LPDIRECT3DDEVICE9 device,
387 UINT *width,
388 UINT *height,
389 UINT *depth,
390 UINT *miplevels,
391 DWORD usage,
392 D3DFORMAT *format,
393 D3DPOOL pool)
395 D3DCAPS9 caps;
396 UINT w = width ? *width : D3DX_DEFAULT;
397 UINT h = height ? *height : D3DX_DEFAULT;
398 UINT d = (depth && *depth) ? *depth : 1;
399 HRESULT hr;
401 TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
402 usage, format, pool);
404 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
405 return D3DERR_INVALIDCALL;
407 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
408 return D3DERR_NOTAVAILABLE;
410 hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
411 if (d == D3DX_DEFAULT)
412 d = 1;
414 /* ensure width/height is power of 2 */
415 if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
416 (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
418 w = make_pow2(w);
419 h = make_pow2(h);
420 d = make_pow2(d);
423 if (w > caps.MaxVolumeExtent)
424 w = caps.MaxVolumeExtent;
425 if (h > caps.MaxVolumeExtent)
426 h = caps.MaxVolumeExtent;
427 if (d > caps.MaxVolumeExtent)
428 d = caps.MaxVolumeExtent;
430 if (miplevels)
432 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
433 *miplevels = 1;
434 else
436 UINT max_mipmaps = 1;
437 UINT max_dimen = max(max(w, h), d);
439 while (max_dimen > 1)
441 max_dimen >>= 1;
442 max_mipmaps++;
445 if (*miplevels == 0 || *miplevels > max_mipmaps)
446 *miplevels = max_mipmaps;
450 if (width)
451 *width = w;
452 if (height)
453 *height = h;
454 if (depth)
455 *depth = d;
457 return hr;
460 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
461 UINT width,
462 UINT height,
463 UINT miplevels,
464 DWORD usage,
465 D3DFORMAT format,
466 D3DPOOL pool,
467 LPDIRECT3DTEXTURE9 *ppTexture)
469 HRESULT hr;
471 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
472 pool, ppTexture);
474 if (!pDevice || !ppTexture)
475 return D3DERR_INVALIDCALL;
477 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
479 if (FAILED(hr))
480 return hr;
482 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
485 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
486 LPCVOID srcdata,
487 UINT srcdatasize,
488 UINT width,
489 UINT height,
490 UINT miplevels,
491 DWORD usage,
492 D3DFORMAT format,
493 D3DPOOL pool,
494 DWORD filter,
495 DWORD mipfilter,
496 D3DCOLOR colorkey,
497 D3DXIMAGE_INFO* srcinfo,
498 PALETTEENTRY* palette,
499 LPDIRECT3DTEXTURE9* texture)
501 IDirect3DTexture9 **texptr;
502 IDirect3DTexture9 *buftex;
503 IDirect3DSurface9 *surface;
504 BOOL file_width = FALSE, file_height = FALSE;
505 BOOL file_format = FALSE, file_miplevels = FALSE;
506 D3DXIMAGE_INFO imginfo;
507 D3DCAPS9 caps;
508 HRESULT hr;
510 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
511 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
513 /* check for invalid parameters */
514 if (!device || !texture || !srcdata || !srcdatasize)
515 return D3DERR_INVALIDCALL;
517 hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
519 if (FAILED(hr))
521 *texture = NULL;
522 return hr;
525 /* handle default values */
526 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
527 width = imginfo.Width;
529 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
530 height = imginfo.Height;
532 if (width == D3DX_DEFAULT)
533 width = make_pow2(imginfo.Width);
535 if (height == D3DX_DEFAULT)
536 height = make_pow2(imginfo.Height);
538 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
539 format = imginfo.Format;
541 if (width == D3DX_FROM_FILE)
543 file_width = TRUE;
544 width = imginfo.Width;
547 if (height == D3DX_FROM_FILE)
549 file_height = TRUE;
550 height = imginfo.Height;
553 if (format == D3DFMT_FROM_FILE)
555 file_format = TRUE;
556 format = imginfo.Format;
559 if (miplevels == D3DX_FROM_FILE)
561 file_miplevels = TRUE;
562 miplevels = imginfo.MipLevels;
565 /* fix texture creation parameters */
566 hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
568 if (FAILED(hr))
570 *texture = NULL;
571 return hr;
574 if (((file_width) && (width != imginfo.Width)) ||
575 ((file_height) && (height != imginfo.Height)) ||
576 ((file_format) && (format != imginfo.Format)) ||
577 ((file_miplevels) && (miplevels != imginfo.MipLevels)))
579 return D3DERR_NOTAVAILABLE;
582 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
583 return D3DERR_INVALIDCALL;
585 /* Create the to-be-filled texture */
586 if ((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (pool != D3DPOOL_DEFAULT) && (usage != D3DUSAGE_DYNAMIC))
588 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
589 texptr = texture;
591 else
593 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
594 texptr = &buftex;
597 if (FAILED(hr))
599 *texture = NULL;
600 return hr;
603 /* Load the file */
604 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
605 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
606 IDirect3DSurface9_Release(surface);
608 if (FAILED(hr))
610 IDirect3DTexture9_Release(*texptr);
611 *texture = NULL;
612 return hr;
615 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, 0, mipfilter);
617 if (FAILED(hr))
619 IDirect3DTexture9_Release(*texptr);
620 *texture = NULL;
621 return hr;
624 /* Move the data to the actual texture if necessary */
625 if (texptr == &buftex)
627 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
629 if (FAILED(hr))
631 IDirect3DTexture9_Release(buftex);
632 *texture = NULL;
633 return hr;
636 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
637 IDirect3DTexture9_Release(buftex);
640 if (srcinfo)
641 *srcinfo = imginfo;
643 return D3D_OK;
646 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
647 LPCVOID srcdata,
648 UINT srcdatasize,
649 LPDIRECT3DTEXTURE9 *texture)
651 TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
653 return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
654 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
657 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
658 LPCWSTR srcfile,
659 UINT width,
660 UINT height,
661 UINT miplevels,
662 DWORD usage,
663 D3DFORMAT format,
664 D3DPOOL pool,
665 DWORD filter,
666 DWORD mipfilter,
667 D3DCOLOR colorkey,
668 D3DXIMAGE_INFO *srcinfo,
669 PALETTEENTRY *palette,
670 LPDIRECT3DTEXTURE9 *texture)
672 HRESULT hr;
673 DWORD size;
674 LPVOID buffer;
676 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
677 device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
678 mipfilter, colorkey, srcinfo, palette, texture);
680 if (!srcfile)
681 return D3DERR_INVALIDCALL;
683 hr = map_view_of_file(srcfile, &buffer, &size);
684 if (FAILED(hr))
685 return D3DXERR_INVALIDDATA;
687 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
688 filter, mipfilter, colorkey, srcinfo, palette, texture);
690 UnmapViewOfFile(buffer);
692 return hr;
695 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
696 LPCSTR srcfile,
697 UINT width,
698 UINT height,
699 UINT miplevels,
700 DWORD usage,
701 D3DFORMAT format,
702 D3DPOOL pool,
703 DWORD filter,
704 DWORD mipfilter,
705 D3DCOLOR colorkey,
706 D3DXIMAGE_INFO *srcinfo,
707 PALETTEENTRY *palette,
708 LPDIRECT3DTEXTURE9 *texture)
710 LPWSTR widename;
711 HRESULT hr;
712 DWORD len;
714 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
715 device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
716 mipfilter, colorkey, srcinfo, palette, texture);
718 if (!device || !srcfile || !texture)
719 return D3DERR_INVALIDCALL;
721 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
722 widename = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
723 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
725 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
726 usage, format, pool, filter, mipfilter,
727 colorkey, srcinfo, palette, texture);
729 HeapFree(GetProcessHeap(), 0, widename);
730 return hr;
733 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
734 LPCSTR srcfile,
735 LPDIRECT3DTEXTURE9 *texture)
737 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
739 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
740 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
743 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
744 LPCWSTR srcfile,
745 LPDIRECT3DTEXTURE9 *texture)
747 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
749 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
750 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
754 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
755 HMODULE srcmodule,
756 LPCSTR resource,
757 LPDIRECT3DTEXTURE9 *texture)
759 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
761 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
762 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
765 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
766 HMODULE srcmodule,
767 LPCWSTR resource,
768 LPDIRECT3DTEXTURE9 *texture)
770 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
772 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
773 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
776 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
777 HMODULE srcmodule,
778 LPCSTR resource,
779 UINT width,
780 UINT height,
781 UINT miplevels,
782 DWORD usage,
783 D3DFORMAT format,
784 D3DPOOL pool,
785 DWORD filter,
786 DWORD mipfilter,
787 D3DCOLOR colorkey,
788 D3DXIMAGE_INFO *srcinfo,
789 PALETTEENTRY *palette,
790 LPDIRECT3DTEXTURE9 *texture)
792 HRSRC resinfo;
794 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
796 if (!device || !texture)
797 return D3DERR_INVALIDCALL;
799 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
801 if (resinfo)
803 LPVOID buffer;
804 HRESULT hr;
805 DWORD size;
807 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
809 if (FAILED(hr))
810 return D3DXERR_INVALIDDATA;
812 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
813 height, miplevels, usage, format,
814 pool, filter, mipfilter, colorkey,
815 srcinfo, palette, texture);
818 /* Try loading the resource as bitmap data */
819 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
821 if (resinfo)
823 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
824 return E_NOTIMPL;
827 return D3DXERR_INVALIDDATA;
830 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
831 HMODULE srcmodule,
832 LPCWSTR resource,
833 UINT width,
834 UINT height,
835 UINT miplevels,
836 DWORD usage,
837 D3DFORMAT format,
838 D3DPOOL pool,
839 DWORD filter,
840 DWORD mipfilter,
841 D3DCOLOR colorkey,
842 D3DXIMAGE_INFO *srcinfo,
843 PALETTEENTRY *palette,
844 LPDIRECT3DTEXTURE9 *texture)
846 HRSRC resinfo;
848 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
850 if (!device || !texture)
851 return D3DERR_INVALIDCALL;
853 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
855 if (resinfo)
857 LPVOID buffer;
858 HRESULT hr;
859 DWORD size;
861 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
863 if (FAILED(hr))
864 return D3DXERR_INVALIDDATA;
866 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
867 height, miplevels, usage, format,
868 pool, filter, mipfilter, colorkey,
869 srcinfo, palette, texture);
872 /* Try loading the resource as bitmap data */
873 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
875 if (resinfo)
877 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
878 return E_NOTIMPL;
881 return D3DXERR_INVALIDDATA;
884 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
885 UINT size,
886 UINT miplevels,
887 DWORD usage,
888 D3DFORMAT format,
889 D3DPOOL pool,
890 LPDIRECT3DCUBETEXTURE9 *texture)
892 HRESULT hr;
894 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
895 pool, texture);
897 if (!device || !texture)
898 return D3DERR_INVALIDCALL;
900 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
902 if (FAILED(hr))
904 TRACE("D3DXCheckCubeTextureRequirements failed\n");
905 return hr;
908 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
911 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
912 UINT width,
913 UINT height,
914 UINT depth,
915 UINT miplevels,
916 DWORD usage,
917 D3DFORMAT format,
918 D3DPOOL pool,
919 LPDIRECT3DVOLUMETEXTURE9 *texture)
921 HRESULT hr;
923 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
924 miplevels, usage, format, pool, texture);
926 if (!device || !texture)
927 return D3DERR_INVALIDCALL;
929 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
930 &miplevels, usage, &format, pool);
932 if (FAILED(hr))
934 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
935 return hr;
938 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
939 usage, format, pool, texture, NULL);
942 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
943 LPD3DXFILL2D function,
944 LPVOID funcdata)
946 DWORD miplevels;
947 DWORD m, i, x, y, c, v;
948 D3DSURFACE_DESC desc;
949 D3DLOCKED_RECT lock_rect;
950 D3DXVECTOR4 value;
951 D3DXVECTOR2 coord, size;
952 const PixelFormatDesc *format;
953 BYTE *data, *pos;
954 BYTE byte, mask;
955 float comp_value;
957 if (texture == NULL || function == NULL)
958 return D3DERR_INVALIDCALL;
960 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
962 for (m = 0; m < miplevels; m++)
964 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
965 return D3DERR_INVALIDCALL;
967 format = get_format_info(desc.Format);
968 if (format->format == D3DFMT_UNKNOWN)
970 FIXME("Unsupported texture format %#x\n", desc.Format);
971 return D3DERR_INVALIDCALL;
974 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
975 return D3DERR_INVALIDCALL;
977 size.x = 1.0f / desc.Width;
978 size.y = 1.0f / desc.Height;
980 data = lock_rect.pBits;
982 for (y = 0; y < desc.Height; y++)
984 /* The callback function expects the coordinates of the center
985 of the texel */
986 coord.y = (y + 0.5f) / desc.Height;
988 for (x = 0; x < desc.Width; x++)
990 coord.x = (x + 0.5f) / desc.Width;
992 function(&value, &coord, &size, funcdata);
994 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
996 for (i = 0; i < format->bytes_per_pixel; i++)
997 pos[i] = 0;
999 for (c = 0; c < 4; c++)
1001 switch (c)
1003 case 0: /* Alpha */
1004 comp_value = value.w;
1005 break;
1006 case 1: /* Red */
1007 comp_value = value.x;
1008 break;
1009 case 2: /* Green */
1010 comp_value = value.y;
1011 break;
1012 case 3: /* Blue */
1013 comp_value = value.z;
1014 break;
1017 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1019 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1021 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1022 byte = (v << format->shift[c] >> i) & mask;
1023 pos[i / 8] |= byte;
1028 IDirect3DTexture9_UnlockRect(texture, m);
1031 return D3D_OK;
1034 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 pDevice, LPCVOID pSrcData, UINT SrcDataSize,
1035 UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey,
1036 D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture)
1038 FIXME("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): stub\n", pDevice, pSrcData, SrcDataSize, Size, MipLevels,
1039 Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture);
1041 return E_NOTIMPL;
1044 enum cube_coord
1046 XCOORD = 0,
1047 XCOORDINV = 1,
1048 YCOORD = 2,
1049 YCOORDINV = 3,
1050 ZERO = 4,
1051 ONE = 5
1054 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1056 switch (coord)
1058 case XCOORD:
1059 return x + 0.5f;
1060 case XCOORDINV:
1061 return size - x - 0.5f;
1062 case YCOORD:
1063 return y + 0.5f;
1064 case YCOORDINV:
1065 return size - y - 0.5f;
1066 case ZERO:
1067 return 0.0f;
1068 case ONE:
1069 return size;
1070 default:
1071 ERR("Unexpected coordinate value\n");
1072 return 0.0f;
1076 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1077 LPD3DXFILL3D function,
1078 LPVOID funcdata)
1080 DWORD miplevels;
1081 DWORD m, i, x, y, c, f, v;
1082 D3DSURFACE_DESC desc;
1083 D3DLOCKED_RECT lock_rect;
1084 D3DXVECTOR4 value;
1085 D3DXVECTOR3 coord, size;
1086 const PixelFormatDesc *format;
1087 BYTE *data, *pos;
1088 BYTE byte, mask;
1089 float comp_value;
1090 static const enum cube_coord coordmap[6][3] =
1092 {ONE, YCOORDINV, XCOORDINV},
1093 {ZERO, YCOORDINV, XCOORD},
1094 {XCOORD, ONE, YCOORD},
1095 {XCOORD, ZERO, YCOORDINV},
1096 {XCOORD, YCOORDINV, ONE},
1097 {XCOORDINV, YCOORDINV, ZERO}
1100 if (texture == NULL || function == NULL)
1101 return D3DERR_INVALIDCALL;
1103 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1105 for (m = 0; m < miplevels; m++)
1107 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1108 return D3DERR_INVALIDCALL;
1110 format = get_format_info(desc.Format);
1111 if (format->format == D3DFMT_UNKNOWN)
1113 FIXME("Unsupported texture format %#x\n", desc.Format);
1114 return D3DERR_INVALIDCALL;
1117 for (f = 0; f < 6; f++)
1119 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1120 return D3DERR_INVALIDCALL;
1122 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1123 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1124 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1126 data = lock_rect.pBits;
1128 for (y = 0; y < desc.Height; y++)
1130 for (x = 0; x < desc.Width; x++)
1132 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1133 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1134 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1136 function(&value, &coord, &size, funcdata);
1138 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1140 for (i = 0; i < format->bytes_per_pixel; i++)
1141 pos[i] = 0;
1143 for (c = 0; c < 4; c++)
1145 switch (c)
1147 case 0: /* Alpha */
1148 comp_value = value.w;
1149 break;
1150 case 1: /* Red */
1151 comp_value = value.x;
1152 break;
1153 case 2: /* Green */
1154 comp_value = value.y;
1155 break;
1156 case 3: /* Blue */
1157 comp_value = value.z;
1158 break;
1161 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1163 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1165 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1166 byte = (v << format->shift[c] >> i) & mask;
1167 pos[i / 8] |= byte;
1172 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1176 return D3D_OK;
1179 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1180 LPD3DXFILL3D function,
1181 LPVOID funcdata)
1183 DWORD miplevels;
1184 DWORD m, i, x, y, z, c, v;
1185 D3DVOLUME_DESC desc;
1186 D3DLOCKED_BOX lock_box;
1187 D3DXVECTOR4 value;
1188 D3DXVECTOR3 coord, size;
1189 const PixelFormatDesc *format;
1190 BYTE *data, *pos;
1191 BYTE byte, mask;
1192 float comp_value;
1194 if (texture == NULL || function == NULL)
1195 return D3DERR_INVALIDCALL;
1197 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1199 for (m = 0; m < miplevels; m++)
1201 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1202 return D3DERR_INVALIDCALL;
1204 format = get_format_info(desc.Format);
1205 if (format->format == D3DFMT_UNKNOWN)
1207 FIXME("Unsupported texture format %#x\n", desc.Format);
1208 return D3DERR_INVALIDCALL;
1211 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1212 return D3DERR_INVALIDCALL;
1214 size.x = 1.0f / desc.Width;
1215 size.y = 1.0f / desc.Height;
1216 size.z = 1.0f / desc.Depth;
1218 data = lock_box.pBits;
1220 for (z = 0; z < desc.Depth; z++)
1222 /* The callback function expects the coordinates of the center
1223 of the texel */
1224 coord.z = (z + 0.5f) / desc.Depth;
1226 for (y = 0; y < desc.Height; y++)
1228 coord.y = (y + 0.5f) / desc.Height;
1230 for (x = 0; x < desc.Width; x++)
1232 coord.x = (x + 0.5f) / desc.Width;
1234 function(&value, &coord, &size, funcdata);
1236 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1238 for (i = 0; i < format->bytes_per_pixel; i++)
1239 pos[i] = 0;
1241 for (c = 0; c < 4; c++)
1243 switch (c)
1245 case 0: /* Alpha */
1246 comp_value = value.w;
1247 break;
1248 case 1: /* Red */
1249 comp_value = value.x;
1250 break;
1251 case 2: /* Green */
1252 comp_value = value.y;
1253 break;
1254 case 3: /* Blue */
1255 comp_value = value.z;
1256 break;
1259 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1261 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1263 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1264 byte = (v << format->shift[c] >> i) & mask;
1265 pos[i / 8] |= byte;
1271 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1274 return D3D_OK;