msxml3: Protect content callbacks from being called on reset content handler pointer.
[wine/wine-gecko.git] / dlls / d3dx9_36 / texture.c
blob1606c9a00f9ad1b855e2f7fda58ba07454247b9e
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 D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
912 LPCVOID data,
913 UINT datasize,
914 LPDIRECT3DCUBETEXTURE9 *texture)
916 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
918 return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
919 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
922 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
923 UINT width,
924 UINT height,
925 UINT depth,
926 UINT miplevels,
927 DWORD usage,
928 D3DFORMAT format,
929 D3DPOOL pool,
930 LPDIRECT3DVOLUMETEXTURE9 *texture)
932 HRESULT hr;
934 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
935 miplevels, usage, format, pool, texture);
937 if (!device || !texture)
938 return D3DERR_INVALIDCALL;
940 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
941 &miplevels, usage, &format, pool);
943 if (FAILED(hr))
945 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
946 return hr;
949 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
950 usage, format, pool, texture, NULL);
953 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
954 LPCVOID data,
955 UINT datasize,
956 LPDIRECT3DVOLUMETEXTURE9 *texture)
958 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
960 return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
961 D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
962 0, NULL, NULL, texture);
965 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
966 LPCVOID data,
967 UINT datasize,
968 UINT width,
969 UINT height,
970 UINT depth,
971 UINT miplevels,
972 DWORD usage,
973 D3DFORMAT format,
974 D3DPOOL pool,
975 DWORD filter,
976 DWORD mipfilter,
977 D3DCOLOR colorkey,
978 D3DXIMAGE_INFO *imageinfo,
979 PALETTEENTRY *palette,
980 LPDIRECT3DVOLUMETEXTURE9 *texture)
982 FIXME("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p) : stub\n",
983 device, data, datasize, width, height, depth, miplevels, usage, format, pool,
984 filter, mipfilter, colorkey, imageinfo, palette, texture);
986 return E_NOTIMPL;
989 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
990 LPD3DXFILL2D function,
991 LPVOID funcdata)
993 DWORD miplevels;
994 DWORD m, i, x, y, c, v;
995 D3DSURFACE_DESC desc;
996 D3DLOCKED_RECT lock_rect;
997 D3DXVECTOR4 value;
998 D3DXVECTOR2 coord, size;
999 const PixelFormatDesc *format;
1000 BYTE *data, *pos;
1001 BYTE byte, mask;
1002 float comp_value;
1004 if (texture == NULL || function == NULL)
1005 return D3DERR_INVALIDCALL;
1007 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1009 for (m = 0; m < miplevels; m++)
1011 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1012 return D3DERR_INVALIDCALL;
1014 format = get_format_info(desc.Format);
1015 if (format->format == D3DFMT_UNKNOWN)
1017 FIXME("Unsupported texture format %#x\n", desc.Format);
1018 return D3DERR_INVALIDCALL;
1021 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1022 return D3DERR_INVALIDCALL;
1024 size.x = 1.0f / desc.Width;
1025 size.y = 1.0f / desc.Height;
1027 data = lock_rect.pBits;
1029 for (y = 0; y < desc.Height; y++)
1031 /* The callback function expects the coordinates of the center
1032 of the texel */
1033 coord.y = (y + 0.5f) / desc.Height;
1035 for (x = 0; x < desc.Width; x++)
1037 coord.x = (x + 0.5f) / desc.Width;
1039 function(&value, &coord, &size, funcdata);
1041 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1043 for (i = 0; i < format->bytes_per_pixel; i++)
1044 pos[i] = 0;
1046 for (c = 0; c < 4; c++)
1048 switch (c)
1050 case 0: /* Alpha */
1051 comp_value = value.w;
1052 break;
1053 case 1: /* Red */
1054 comp_value = value.x;
1055 break;
1056 case 2: /* Green */
1057 comp_value = value.y;
1058 break;
1059 case 3: /* Blue */
1060 comp_value = value.z;
1061 break;
1064 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1066 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1068 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1069 byte = (v << format->shift[c] >> i) & mask;
1070 pos[i / 8] |= byte;
1075 IDirect3DTexture9_UnlockRect(texture, m);
1078 return D3D_OK;
1081 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 pDevice, LPCVOID pSrcData, UINT SrcDataSize,
1082 UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey,
1083 D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture)
1085 FIXME("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): stub\n", pDevice, pSrcData, SrcDataSize, Size, MipLevels,
1086 Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture);
1088 return E_NOTIMPL;
1091 enum cube_coord
1093 XCOORD = 0,
1094 XCOORDINV = 1,
1095 YCOORD = 2,
1096 YCOORDINV = 3,
1097 ZERO = 4,
1098 ONE = 5
1101 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1103 switch (coord)
1105 case XCOORD:
1106 return x + 0.5f;
1107 case XCOORDINV:
1108 return size - x - 0.5f;
1109 case YCOORD:
1110 return y + 0.5f;
1111 case YCOORDINV:
1112 return size - y - 0.5f;
1113 case ZERO:
1114 return 0.0f;
1115 case ONE:
1116 return size;
1117 default:
1118 ERR("Unexpected coordinate value\n");
1119 return 0.0f;
1123 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1124 LPD3DXFILL3D function,
1125 LPVOID funcdata)
1127 DWORD miplevels;
1128 DWORD m, i, x, y, c, f, v;
1129 D3DSURFACE_DESC desc;
1130 D3DLOCKED_RECT lock_rect;
1131 D3DXVECTOR4 value;
1132 D3DXVECTOR3 coord, size;
1133 const PixelFormatDesc *format;
1134 BYTE *data, *pos;
1135 BYTE byte, mask;
1136 float comp_value;
1137 static const enum cube_coord coordmap[6][3] =
1139 {ONE, YCOORDINV, XCOORDINV},
1140 {ZERO, YCOORDINV, XCOORD},
1141 {XCOORD, ONE, YCOORD},
1142 {XCOORD, ZERO, YCOORDINV},
1143 {XCOORD, YCOORDINV, ONE},
1144 {XCOORDINV, YCOORDINV, ZERO}
1147 if (texture == NULL || function == NULL)
1148 return D3DERR_INVALIDCALL;
1150 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1152 for (m = 0; m < miplevels; m++)
1154 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1155 return D3DERR_INVALIDCALL;
1157 format = get_format_info(desc.Format);
1158 if (format->format == D3DFMT_UNKNOWN)
1160 FIXME("Unsupported texture format %#x\n", desc.Format);
1161 return D3DERR_INVALIDCALL;
1164 for (f = 0; f < 6; f++)
1166 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1167 return D3DERR_INVALIDCALL;
1169 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1170 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1171 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1173 data = lock_rect.pBits;
1175 for (y = 0; y < desc.Height; y++)
1177 for (x = 0; x < desc.Width; x++)
1179 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1180 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1181 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1183 function(&value, &coord, &size, funcdata);
1185 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1187 for (i = 0; i < format->bytes_per_pixel; i++)
1188 pos[i] = 0;
1190 for (c = 0; c < 4; c++)
1192 switch (c)
1194 case 0: /* Alpha */
1195 comp_value = value.w;
1196 break;
1197 case 1: /* Red */
1198 comp_value = value.x;
1199 break;
1200 case 2: /* Green */
1201 comp_value = value.y;
1202 break;
1203 case 3: /* Blue */
1204 comp_value = value.z;
1205 break;
1208 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1210 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1212 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1213 byte = (v << format->shift[c] >> i) & mask;
1214 pos[i / 8] |= byte;
1219 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1223 return D3D_OK;
1226 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1227 LPD3DXFILL3D function,
1228 LPVOID funcdata)
1230 DWORD miplevels;
1231 DWORD m, i, x, y, z, c, v;
1232 D3DVOLUME_DESC desc;
1233 D3DLOCKED_BOX lock_box;
1234 D3DXVECTOR4 value;
1235 D3DXVECTOR3 coord, size;
1236 const PixelFormatDesc *format;
1237 BYTE *data, *pos;
1238 BYTE byte, mask;
1239 float comp_value;
1241 if (texture == NULL || function == NULL)
1242 return D3DERR_INVALIDCALL;
1244 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1246 for (m = 0; m < miplevels; m++)
1248 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1249 return D3DERR_INVALIDCALL;
1251 format = get_format_info(desc.Format);
1252 if (format->format == D3DFMT_UNKNOWN)
1254 FIXME("Unsupported texture format %#x\n", desc.Format);
1255 return D3DERR_INVALIDCALL;
1258 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1259 return D3DERR_INVALIDCALL;
1261 size.x = 1.0f / desc.Width;
1262 size.y = 1.0f / desc.Height;
1263 size.z = 1.0f / desc.Depth;
1265 data = lock_box.pBits;
1267 for (z = 0; z < desc.Depth; z++)
1269 /* The callback function expects the coordinates of the center
1270 of the texel */
1271 coord.z = (z + 0.5f) / desc.Depth;
1273 for (y = 0; y < desc.Height; y++)
1275 coord.y = (y + 0.5f) / desc.Height;
1277 for (x = 0; x < desc.Width; x++)
1279 coord.x = (x + 0.5f) / desc.Width;
1281 function(&value, &coord, &size, funcdata);
1283 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1285 for (i = 0; i < format->bytes_per_pixel; i++)
1286 pos[i] = 0;
1288 for (c = 0; c < 4; c++)
1290 switch (c)
1292 case 0: /* Alpha */
1293 comp_value = value.w;
1294 break;
1295 case 1: /* Red */
1296 comp_value = value.x;
1297 break;
1298 case 2: /* Green */
1299 comp_value = value.y;
1300 break;
1301 case 3: /* Blue */
1302 comp_value = value.z;
1303 break;
1306 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1308 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1310 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1311 byte = (v << format->shift[c] >> i) & mask;
1312 pos[i / 8] |= byte;
1318 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1321 return D3D_OK;