vbscript: Use 0 as an invalid label value.
[wine/multimedia.git] / dlls / d3dx9_36 / texture.c
blob20d8880d9403432b987d1ed6637fac5228943ed7
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, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_w(srcfile), width,
677 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
679 if (!srcfile)
680 return D3DERR_INVALIDCALL;
682 hr = map_view_of_file(srcfile, &buffer, &size);
683 if (FAILED(hr))
684 return D3DXERR_INVALIDDATA;
686 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
687 filter, mipfilter, colorkey, srcinfo, palette, texture);
689 UnmapViewOfFile(buffer);
691 return hr;
694 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
695 LPCSTR srcfile,
696 UINT width,
697 UINT height,
698 UINT miplevels,
699 DWORD usage,
700 D3DFORMAT format,
701 D3DPOOL pool,
702 DWORD filter,
703 DWORD mipfilter,
704 D3DCOLOR colorkey,
705 D3DXIMAGE_INFO *srcinfo,
706 PALETTEENTRY *palette,
707 LPDIRECT3DTEXTURE9 *texture)
709 LPWSTR widename;
710 HRESULT hr;
711 DWORD len;
713 TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_a(srcfile), width,
714 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
716 if (!device || !srcfile || !texture)
717 return D3DERR_INVALIDCALL;
719 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
720 widename = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
721 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
723 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
724 usage, format, pool, filter, mipfilter,
725 colorkey, srcinfo, palette, texture);
727 HeapFree(GetProcessHeap(), 0, widename);
728 return hr;
731 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
732 LPCSTR srcfile,
733 LPDIRECT3DTEXTURE9 *texture)
735 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
737 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
738 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
741 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
742 LPCWSTR srcfile,
743 LPDIRECT3DTEXTURE9 *texture)
745 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
747 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
748 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
752 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
753 HMODULE srcmodule,
754 LPCSTR resource,
755 LPDIRECT3DTEXTURE9 *texture)
757 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
759 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
760 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
763 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
764 HMODULE srcmodule,
765 LPCWSTR resource,
766 LPDIRECT3DTEXTURE9 *texture)
768 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
770 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
771 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
774 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
775 HMODULE srcmodule,
776 LPCSTR resource,
777 UINT width,
778 UINT height,
779 UINT miplevels,
780 DWORD usage,
781 D3DFORMAT format,
782 D3DPOOL pool,
783 DWORD filter,
784 DWORD mipfilter,
785 D3DCOLOR colorkey,
786 D3DXIMAGE_INFO *srcinfo,
787 PALETTEENTRY *palette,
788 LPDIRECT3DTEXTURE9 *texture)
790 HRSRC resinfo;
792 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
794 if (!device || !texture)
795 return D3DERR_INVALIDCALL;
797 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
799 if (resinfo)
801 LPVOID buffer;
802 HRESULT hr;
803 DWORD size;
805 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
807 if (FAILED(hr))
808 return D3DXERR_INVALIDDATA;
810 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
811 height, miplevels, usage, format,
812 pool, filter, mipfilter, colorkey,
813 srcinfo, palette, texture);
816 /* Try loading the resource as bitmap data */
817 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
819 if (resinfo)
821 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
822 return E_NOTIMPL;
825 return D3DXERR_INVALIDDATA;
828 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
829 HMODULE srcmodule,
830 LPCWSTR resource,
831 UINT width,
832 UINT height,
833 UINT miplevels,
834 DWORD usage,
835 D3DFORMAT format,
836 D3DPOOL pool,
837 DWORD filter,
838 DWORD mipfilter,
839 D3DCOLOR colorkey,
840 D3DXIMAGE_INFO *srcinfo,
841 PALETTEENTRY *palette,
842 LPDIRECT3DTEXTURE9 *texture)
844 HRSRC resinfo;
846 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
848 if (!device || !texture)
849 return D3DERR_INVALIDCALL;
851 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
853 if (resinfo)
855 LPVOID buffer;
856 HRESULT hr;
857 DWORD size;
859 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
861 if (FAILED(hr))
862 return D3DXERR_INVALIDDATA;
864 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
865 height, miplevels, usage, format,
866 pool, filter, mipfilter, colorkey,
867 srcinfo, palette, texture);
870 /* Try loading the resource as bitmap data */
871 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
873 if (resinfo)
875 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
876 return E_NOTIMPL;
879 return D3DXERR_INVALIDDATA;
882 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
883 UINT size,
884 UINT miplevels,
885 DWORD usage,
886 D3DFORMAT format,
887 D3DPOOL pool,
888 LPDIRECT3DCUBETEXTURE9 *texture)
890 HRESULT hr;
892 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
893 pool, texture);
895 if (!device || !texture)
896 return D3DERR_INVALIDCALL;
898 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
900 if (FAILED(hr))
902 TRACE("D3DXCheckCubeTextureRequirements failed\n");
903 return hr;
906 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
909 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
910 UINT width,
911 UINT height,
912 UINT depth,
913 UINT miplevels,
914 DWORD usage,
915 D3DFORMAT format,
916 D3DPOOL pool,
917 LPDIRECT3DVOLUMETEXTURE9 *texture)
919 HRESULT hr;
921 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
922 miplevels, usage, format, pool, texture);
924 if (!device || !texture)
925 return D3DERR_INVALIDCALL;
927 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
928 &miplevels, usage, &format, pool);
930 if (FAILED(hr))
932 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
933 return hr;
936 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
937 usage, format, pool, texture, NULL);
940 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
941 LPD3DXFILL2D function,
942 LPVOID funcdata)
944 DWORD miplevels;
945 DWORD m, i, x, y, c, v;
946 D3DSURFACE_DESC desc;
947 D3DLOCKED_RECT lock_rect;
948 D3DXVECTOR4 value;
949 D3DXVECTOR2 coord, size;
950 const PixelFormatDesc *format;
951 BYTE *data, *pos;
952 BYTE byte, mask;
953 float comp_value;
955 if (texture == NULL || function == NULL)
956 return D3DERR_INVALIDCALL;
958 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
960 for (m = 0; m < miplevels; m++)
962 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
963 return D3DERR_INVALIDCALL;
965 format = get_format_info(desc.Format);
966 if (format->format == D3DFMT_UNKNOWN)
968 FIXME("Unsupported texture format %#x\n", desc.Format);
969 return D3DERR_INVALIDCALL;
972 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
973 return D3DERR_INVALIDCALL;
975 size.x = 1.0f / desc.Width;
976 size.y = 1.0f / desc.Height;
978 data = lock_rect.pBits;
980 for (y = 0; y < desc.Height; y++)
982 /* The callback function expects the coordinates of the center
983 of the texel */
984 coord.y = (y + 0.5f) / desc.Height;
986 for (x = 0; x < desc.Width; x++)
988 coord.x = (x + 0.5f) / desc.Width;
990 function(&value, &coord, &size, funcdata);
992 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
994 for (i = 0; i < format->bytes_per_pixel; i++)
995 pos[i] = 0;
997 for (c = 0; c < 4; c++)
999 switch (c)
1001 case 0: /* Alpha */
1002 comp_value = value.w;
1003 break;
1004 case 1: /* Red */
1005 comp_value = value.x;
1006 break;
1007 case 2: /* Green */
1008 comp_value = value.y;
1009 break;
1010 case 3: /* Blue */
1011 comp_value = value.z;
1012 break;
1015 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1017 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1019 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1020 byte = (v << format->shift[c] >> i) & mask;
1021 pos[i / 8] |= byte;
1026 IDirect3DTexture9_UnlockRect(texture, m);
1029 return D3D_OK;
1032 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 pDevice, LPCVOID pSrcData, UINT SrcDataSize,
1033 UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey,
1034 D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture)
1036 FIXME("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): stub\n", pDevice, pSrcData, SrcDataSize, Size, MipLevels,
1037 Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture);
1039 return E_NOTIMPL;
1042 enum cube_coord
1044 XCOORD = 0,
1045 XCOORDINV = 1,
1046 YCOORD = 2,
1047 YCOORDINV = 3,
1048 ZERO = 4,
1049 ONE = 5
1052 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1054 switch (coord)
1056 case XCOORD:
1057 return x + 0.5f;
1058 case XCOORDINV:
1059 return size - x - 0.5f;
1060 case YCOORD:
1061 return y + 0.5f;
1062 case YCOORDINV:
1063 return size - y - 0.5f;
1064 case ZERO:
1065 return 0.0f;
1066 case ONE:
1067 return size;
1068 default:
1069 ERR("Unexpected coordinate value\n");
1070 return 0.0f;
1074 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1075 LPD3DXFILL3D function,
1076 LPVOID funcdata)
1078 DWORD miplevels;
1079 DWORD m, i, x, y, c, f, v;
1080 D3DSURFACE_DESC desc;
1081 D3DLOCKED_RECT lock_rect;
1082 D3DXVECTOR4 value;
1083 D3DXVECTOR3 coord, size;
1084 const PixelFormatDesc *format;
1085 BYTE *data, *pos;
1086 BYTE byte, mask;
1087 float comp_value;
1088 static const enum cube_coord coordmap[6][3] =
1090 {ONE, YCOORDINV, XCOORDINV},
1091 {ZERO, YCOORDINV, XCOORD},
1092 {XCOORD, ONE, YCOORD},
1093 {XCOORD, ZERO, YCOORDINV},
1094 {XCOORD, YCOORDINV, ONE},
1095 {XCOORDINV, YCOORDINV, ZERO}
1098 if (texture == NULL || function == NULL)
1099 return D3DERR_INVALIDCALL;
1101 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1103 for (m = 0; m < miplevels; m++)
1105 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1106 return D3DERR_INVALIDCALL;
1108 format = get_format_info(desc.Format);
1109 if (format->format == D3DFMT_UNKNOWN)
1111 FIXME("Unsupported texture format %#x\n", desc.Format);
1112 return D3DERR_INVALIDCALL;
1115 for (f = 0; f < 6; f++)
1117 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1118 return D3DERR_INVALIDCALL;
1120 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1121 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1122 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1124 data = lock_rect.pBits;
1126 for (y = 0; y < desc.Height; y++)
1128 for (x = 0; x < desc.Width; x++)
1130 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1131 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1132 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1134 function(&value, &coord, &size, funcdata);
1136 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1138 for (i = 0; i < format->bytes_per_pixel; i++)
1139 pos[i] = 0;
1141 for (c = 0; c < 4; c++)
1143 switch (c)
1145 case 0: /* Alpha */
1146 comp_value = value.w;
1147 break;
1148 case 1: /* Red */
1149 comp_value = value.x;
1150 break;
1151 case 2: /* Green */
1152 comp_value = value.y;
1153 break;
1154 case 3: /* Blue */
1155 comp_value = value.z;
1156 break;
1159 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1161 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1163 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1164 byte = (v << format->shift[c] >> i) & mask;
1165 pos[i / 8] |= byte;
1170 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1174 return D3D_OK;
1177 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1178 LPD3DXFILL3D function,
1179 LPVOID funcdata)
1181 DWORD miplevels;
1182 DWORD m, i, x, y, z, c, v;
1183 D3DVOLUME_DESC desc;
1184 D3DLOCKED_BOX lock_box;
1185 D3DXVECTOR4 value;
1186 D3DXVECTOR3 coord, size;
1187 const PixelFormatDesc *format;
1188 BYTE *data, *pos;
1189 BYTE byte, mask;
1190 float comp_value;
1192 if (texture == NULL || function == NULL)
1193 return D3DERR_INVALIDCALL;
1195 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1197 for (m = 0; m < miplevels; m++)
1199 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1200 return D3DERR_INVALIDCALL;
1202 format = get_format_info(desc.Format);
1203 if (format->format == D3DFMT_UNKNOWN)
1205 FIXME("Unsupported texture format %#x\n", desc.Format);
1206 return D3DERR_INVALIDCALL;
1209 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1210 return D3DERR_INVALIDCALL;
1212 size.x = 1.0f / desc.Width;
1213 size.y = 1.0f / desc.Height;
1214 size.z = 1.0f / desc.Depth;
1216 data = lock_box.pBits;
1218 for (z = 0; z < desc.Depth; z++)
1220 /* The callback function expects the coordinates of the center
1221 of the texel */
1222 coord.z = (z + 0.5f) / desc.Depth;
1224 for (y = 0; y < desc.Height; y++)
1226 coord.y = (y + 0.5f) / desc.Height;
1228 for (x = 0; x < desc.Width; x++)
1230 coord.x = (x + 0.5f) / desc.Width;
1232 function(&value, &coord, &size, funcdata);
1234 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1236 for (i = 0; i < format->bytes_per_pixel; i++)
1237 pos[i] = 0;
1239 for (c = 0; c < 4; c++)
1241 switch (c)
1243 case 0: /* Alpha */
1244 comp_value = value.w;
1245 break;
1246 case 1: /* Red */
1247 comp_value = value.x;
1248 break;
1249 case 2: /* Green */
1250 comp_value = value.y;
1251 break;
1252 case 3: /* Blue */
1253 comp_value = value.z;
1254 break;
1257 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1259 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1261 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1262 byte = (v << format->shift[c] >> i) & mask;
1263 pos[i / 8] |= byte;
1269 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1272 return D3D_OK;