wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / d3dx9_36 / texture.c
blob1c40d961c05c6946ed95cee2b60c738328aa8bf7
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 enum cube_coord
1034 XCOORD = 0,
1035 XCOORDINV = 1,
1036 YCOORD = 2,
1037 YCOORDINV = 3,
1038 ZERO = 4,
1039 ONE = 5
1042 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1044 switch (coord)
1046 case XCOORD:
1047 return x + 0.5f;
1048 case XCOORDINV:
1049 return size - x - 0.5f;
1050 case YCOORD:
1051 return y + 0.5f;
1052 case YCOORDINV:
1053 return size - y - 0.5f;
1054 case ZERO:
1055 return 0.0f;
1056 case ONE:
1057 return size;
1058 default:
1059 ERR("Unexpected coordinate value\n");
1060 return 0.0f;
1064 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1065 LPD3DXFILL3D function,
1066 LPVOID funcdata)
1068 DWORD miplevels;
1069 DWORD m, i, x, y, c, f, v;
1070 D3DSURFACE_DESC desc;
1071 D3DLOCKED_RECT lock_rect;
1072 D3DXVECTOR4 value;
1073 D3DXVECTOR3 coord, size;
1074 const PixelFormatDesc *format;
1075 BYTE *data, *pos;
1076 BYTE byte, mask;
1077 float comp_value;
1078 static const enum cube_coord coordmap[6][3] =
1080 {ONE, YCOORDINV, XCOORDINV},
1081 {ZERO, YCOORDINV, XCOORD},
1082 {XCOORD, ONE, YCOORD},
1083 {XCOORD, ZERO, YCOORDINV},
1084 {XCOORD, YCOORDINV, ONE},
1085 {XCOORDINV, YCOORDINV, ZERO}
1088 if (texture == NULL || function == NULL)
1089 return D3DERR_INVALIDCALL;
1091 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1093 for (m = 0; m < miplevels; m++)
1095 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1096 return D3DERR_INVALIDCALL;
1098 format = get_format_info(desc.Format);
1099 if (format->format == D3DFMT_UNKNOWN)
1101 FIXME("Unsupported texture format %#x\n", desc.Format);
1102 return D3DERR_INVALIDCALL;
1105 for (f = 0; f < 6; f++)
1107 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1108 return D3DERR_INVALIDCALL;
1110 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1111 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1112 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1114 data = lock_rect.pBits;
1116 for (y = 0; y < desc.Height; y++)
1118 for (x = 0; x < desc.Width; x++)
1120 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1121 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1122 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1124 function(&value, &coord, &size, funcdata);
1126 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1128 for (i = 0; i < format->bytes_per_pixel; i++)
1129 pos[i] = 0;
1131 for (c = 0; c < 4; c++)
1133 switch (c)
1135 case 0: /* Alpha */
1136 comp_value = value.w;
1137 break;
1138 case 1: /* Red */
1139 comp_value = value.x;
1140 break;
1141 case 2: /* Green */
1142 comp_value = value.y;
1143 break;
1144 case 3: /* Blue */
1145 comp_value = value.z;
1146 break;
1149 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1151 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1153 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1154 byte = (v << format->shift[c] >> i) & mask;
1155 pos[i / 8] |= byte;
1160 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1164 return D3D_OK;
1167 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1168 LPD3DXFILL3D function,
1169 LPVOID funcdata)
1171 DWORD miplevels;
1172 DWORD m, i, x, y, z, c, v;
1173 D3DVOLUME_DESC desc;
1174 D3DLOCKED_BOX lock_box;
1175 D3DXVECTOR4 value;
1176 D3DXVECTOR3 coord, size;
1177 const PixelFormatDesc *format;
1178 BYTE *data, *pos;
1179 BYTE byte, mask;
1180 float comp_value;
1182 if (texture == NULL || function == NULL)
1183 return D3DERR_INVALIDCALL;
1185 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1187 for (m = 0; m < miplevels; m++)
1189 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1190 return D3DERR_INVALIDCALL;
1192 format = get_format_info(desc.Format);
1193 if (format->format == D3DFMT_UNKNOWN)
1195 FIXME("Unsupported texture format %#x\n", desc.Format);
1196 return D3DERR_INVALIDCALL;
1199 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1200 return D3DERR_INVALIDCALL;
1202 size.x = 1.0f / desc.Width;
1203 size.y = 1.0f / desc.Height;
1204 size.z = 1.0f / desc.Depth;
1206 data = lock_box.pBits;
1208 for (z = 0; z < desc.Depth; z++)
1210 /* The callback function expects the coordinates of the center
1211 of the texel */
1212 coord.z = (z + 0.5f) / desc.Depth;
1214 for (y = 0; y < desc.Height; y++)
1216 coord.y = (y + 0.5f) / desc.Height;
1218 for (x = 0; x < desc.Width; x++)
1220 coord.x = (x + 0.5f) / desc.Width;
1222 function(&value, &coord, &size, funcdata);
1224 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1226 for (i = 0; i < format->bytes_per_pixel; i++)
1227 pos[i] = 0;
1229 for (c = 0; c < 4; c++)
1231 switch (c)
1233 case 0: /* Alpha */
1234 comp_value = value.w;
1235 break;
1236 case 1: /* Red */
1237 comp_value = value.x;
1238 break;
1239 case 2: /* Green */
1240 comp_value = value.y;
1241 break;
1242 case 3: /* Blue */
1243 comp_value = value.z;
1244 break;
1247 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1249 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1251 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1252 byte = (v << format->shift[c] >> i) & mask;
1253 pos[i / 8] |= byte;
1259 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1262 return D3D_OK;