d3dx9: Correctly check if a texture is dynamic in D3DXCreateTextureFromFileInMemoryEx.
[wine/multimedia.git] / dlls / d3dx9_36 / texture.c
blob2a4a3008a367ddc9ef0bec31a810bd39a422f351
1 /*
2 * Copyright 2009 Tony Wasserka
3 * Copyright 2010 Christian Costa
4 * Copyright 2010 Owen Rudge for CodeWeavers
5 * Copyright 2010 Matteo Bruni for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/unicode.h"
23 #include "wine/debug.h"
24 #include "d3dx9_36_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
28 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
29 static BOOL is_pow2(UINT num)
31 return !(num & (num - 1));
34 /* Returns the smallest power of 2 which is greater than or equal to num */
35 static UINT make_pow2(UINT num)
37 UINT result = 1;
39 /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */
40 if (num >= 0x80000000)
41 return 0x80000000;
43 while (result < num)
44 result <<= 1;
46 return result;
49 static HRESULT get_surface(D3DRESOURCETYPE type, LPDIRECT3DBASETEXTURE9 tex,
50 int face, UINT level, LPDIRECT3DSURFACE9 *surf)
52 switch (type)
54 case D3DRTYPE_TEXTURE:
55 return IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) tex, level, surf);
56 case D3DRTYPE_CUBETEXTURE:
57 return IDirect3DCubeTexture9_GetCubeMapSurface((IDirect3DCubeTexture9*) tex, face, level, surf);
58 default:
59 ERR("Unexpected texture type\n");
60 return E_NOTIMPL;
64 HRESULT WINAPI D3DXFilterTexture(LPDIRECT3DBASETEXTURE9 texture,
65 CONST PALETTEENTRY *palette,
66 UINT srclevel,
67 DWORD filter)
69 UINT level;
70 HRESULT hr;
71 D3DRESOURCETYPE type;
73 TRACE("(%p, %p, %d, %d)\n", texture, palette, srclevel, filter);
75 if (!texture)
76 return D3DERR_INVALIDCALL;
78 if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT)
79 return D3DERR_INVALIDCALL;
81 if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
82 return D3DERR_INVALIDCALL;
84 switch (type = IDirect3DBaseTexture9_GetType(texture))
86 case D3DRTYPE_TEXTURE:
87 case D3DRTYPE_CUBETEXTURE:
89 IDirect3DSurface9 *topsurf, *mipsurf;
90 D3DSURFACE_DESC desc;
91 int i, numfaces;
93 if (type == D3DRTYPE_TEXTURE)
95 numfaces = 1;
96 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
98 else
100 numfaces = 6;
101 IDirect3DCubeTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
104 if (filter == D3DX_DEFAULT)
106 if (is_pow2(desc.Width) && is_pow2(desc.Height))
107 filter = D3DX_FILTER_BOX;
108 else
109 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
112 for (i = 0; i < numfaces; i++)
114 level = srclevel + 1;
115 hr = get_surface(type, texture, i, srclevel, &topsurf);
117 if (FAILED(hr))
118 return D3DERR_INVALIDCALL;
120 while (get_surface(type, texture, i, level, &mipsurf) == D3D_OK)
122 hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
123 IDirect3DSurface9_Release(topsurf);
124 topsurf = mipsurf;
126 if (FAILED(hr))
127 break;
129 level++;
132 IDirect3DSurface9_Release(topsurf);
133 if (FAILED(hr))
134 return hr;
137 return D3D_OK;
140 default:
141 FIXME("Implement volume texture filtering\n");
142 return E_NOTIMPL;
146 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
147 UINT* width,
148 UINT* height,
149 UINT* miplevels,
150 DWORD usage,
151 D3DFORMAT* format,
152 D3DPOOL pool)
154 UINT w = (width && *width) ? *width : 1;
155 UINT h = (height && *height) ? *height : 1;
156 D3DCAPS9 caps;
157 D3DDEVICE_CREATION_PARAMETERS params;
158 IDirect3D9 *d3d = NULL;
159 D3DDISPLAYMODE mode;
160 HRESULT hr;
161 D3DFORMAT usedformat = D3DFMT_UNKNOWN;
163 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
165 if (!device)
166 return D3DERR_INVALIDCALL;
168 /* usage */
169 if (usage == D3DX_DEFAULT)
170 usage = 0;
171 if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
172 return D3DERR_INVALIDCALL;
174 /* pool */
175 if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
176 return D3DERR_INVALIDCALL;
178 /* width and height */
179 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
180 return D3DERR_INVALIDCALL;
182 /* 256 x 256 default width/height */
183 if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
184 w = h = 256;
185 else if (w == D3DX_DEFAULT)
186 w = (height ? h : 256);
187 else if (h == D3DX_DEFAULT)
188 h = (width ? w : 256);
190 /* ensure width/height is power of 2 */
191 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
192 w = make_pow2(w);
194 if (w > caps.MaxTextureWidth)
195 w = caps.MaxTextureWidth;
197 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
198 h = make_pow2(h);
200 if (h > caps.MaxTextureHeight)
201 h = caps.MaxTextureHeight;
203 /* texture must be square? */
204 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
206 if (w > h)
207 h = w;
208 else
209 w = h;
212 if (width)
213 *width = w;
215 if (height)
216 *height = h;
218 /* miplevels */
219 if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
221 if (*miplevels > 1)
222 *miplevels = 0;
224 else if (miplevels)
226 UINT max_mipmaps = 1;
228 if (!width && !height)
229 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
230 else
232 UINT max_dimen = max(w, h);
234 while (max_dimen > 1)
236 max_dimen >>= 1;
237 max_mipmaps++;
241 if (*miplevels == 0 || *miplevels > max_mipmaps)
242 *miplevels = max_mipmaps;
245 /* format */
246 if (format)
248 TRACE("Requested format %x\n", *format);
249 usedformat = *format;
252 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
254 if (FAILED(hr))
255 goto cleanup;
257 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
259 if (FAILED(hr))
260 goto cleanup;
262 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
264 if (FAILED(hr))
265 goto cleanup;
267 if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
268 usedformat = D3DFMT_A8R8G8B8;
270 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
271 usage, D3DRTYPE_TEXTURE, usedformat);
273 if (FAILED(hr))
275 /* Heuristic to choose the fallback format */
276 const PixelFormatDesc *fmt = get_format_info(usedformat);
277 BOOL allow_24bits;
278 int bestscore = INT_MIN, i = 0, j;
279 unsigned int channels;
280 const PixelFormatDesc *curfmt;
282 if (!fmt)
284 FIXME("Pixel format %x not handled\n", usedformat);
285 goto cleanup;
288 allow_24bits = fmt->bytes_per_pixel == 3;
289 channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
290 + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
291 usedformat = D3DFMT_UNKNOWN;
293 while ((curfmt = get_format_info_idx(i)))
295 unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
296 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
297 int score;
299 i++;
301 if (curchannels < channels)
302 continue;
303 if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
304 continue;
306 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
307 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
308 if (FAILED(hr))
309 continue;
311 /* This format can be used, let's evaluate it.
312 Weights chosen quite arbitrarily... */
313 score = 16 - 4 * (curchannels - channels);
315 for (j = 0; j < 4; j++)
317 int diff = curfmt->bits[j] - fmt->bits[j];
318 score += 16 - (diff < 0 ? -diff * 4 : diff);
321 if (score > bestscore)
323 bestscore = score;
324 usedformat = curfmt->format;
327 hr = D3D_OK;
330 cleanup:
332 if (d3d)
333 IDirect3D9_Release(d3d);
335 if (FAILED(hr))
336 return hr;
338 if (usedformat == D3DFMT_UNKNOWN)
340 WARN("Couldn't find a suitable pixel format\n");
341 return D3DERR_NOTAVAILABLE;
344 TRACE("Format chosen: %x\n", usedformat);
345 if (format)
346 *format = usedformat;
348 return D3D_OK;
351 HRESULT WINAPI D3DXCheckCubeTextureRequirements(LPDIRECT3DDEVICE9 device,
352 UINT *size,
353 UINT *miplevels,
354 DWORD usage,
355 D3DFORMAT *format,
356 D3DPOOL pool)
358 D3DCAPS9 caps;
359 UINT s = (size && *size) ? *size : 256;
360 HRESULT hr;
362 TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
364 if (s == D3DX_DEFAULT)
365 s = 256;
367 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
368 return D3DERR_INVALIDCALL;
370 if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
371 return D3DERR_NOTAVAILABLE;
373 /* ensure width/height is power of 2 */
374 if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
375 s = make_pow2(s);
377 hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
379 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
381 if(miplevels)
382 *miplevels = 1;
385 if (size)
386 *size = s;
388 return hr;
391 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(LPDIRECT3DDEVICE9 device,
392 UINT *width,
393 UINT *height,
394 UINT *depth,
395 UINT *miplevels,
396 DWORD usage,
397 D3DFORMAT *format,
398 D3DPOOL pool)
400 D3DCAPS9 caps;
401 UINT w = width ? *width : D3DX_DEFAULT;
402 UINT h = height ? *height : D3DX_DEFAULT;
403 UINT d = (depth && *depth) ? *depth : 1;
404 HRESULT hr;
406 TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
407 usage, format, pool);
409 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
410 return D3DERR_INVALIDCALL;
412 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
413 return D3DERR_NOTAVAILABLE;
415 hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
416 if (d == D3DX_DEFAULT)
417 d = 1;
419 /* ensure width/height is power of 2 */
420 if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
421 (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
423 w = make_pow2(w);
424 h = make_pow2(h);
425 d = make_pow2(d);
428 if (w > caps.MaxVolumeExtent)
429 w = caps.MaxVolumeExtent;
430 if (h > caps.MaxVolumeExtent)
431 h = caps.MaxVolumeExtent;
432 if (d > caps.MaxVolumeExtent)
433 d = caps.MaxVolumeExtent;
435 if (miplevels)
437 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
438 *miplevels = 1;
439 else if ((usage & D3DUSAGE_AUTOGENMIPMAP))
441 if (*miplevels > 1)
442 *miplevels = 0;
444 else
446 UINT max_mipmaps = 1;
447 UINT max_dimen = max(max(w, h), d);
449 while (max_dimen > 1)
451 max_dimen >>= 1;
452 max_mipmaps++;
455 if (*miplevels == 0 || *miplevels > max_mipmaps)
456 *miplevels = max_mipmaps;
460 if (width)
461 *width = w;
462 if (height)
463 *height = h;
464 if (depth)
465 *depth = d;
467 return hr;
470 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
471 UINT width,
472 UINT height,
473 UINT miplevels,
474 DWORD usage,
475 D3DFORMAT format,
476 D3DPOOL pool,
477 LPDIRECT3DTEXTURE9 *ppTexture)
479 HRESULT hr;
481 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
482 pool, ppTexture);
484 if (!pDevice || !ppTexture)
485 return D3DERR_INVALIDCALL;
487 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
489 if (FAILED(hr))
490 return hr;
492 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
495 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
496 LPCVOID srcdata,
497 UINT srcdatasize,
498 UINT width,
499 UINT height,
500 UINT miplevels,
501 DWORD usage,
502 D3DFORMAT format,
503 D3DPOOL pool,
504 DWORD filter,
505 DWORD mipfilter,
506 D3DCOLOR colorkey,
507 D3DXIMAGE_INFO* srcinfo,
508 PALETTEENTRY* palette,
509 LPDIRECT3DTEXTURE9* texture)
511 IDirect3DTexture9 **texptr;
512 IDirect3DTexture9 *buftex;
513 IDirect3DSurface9 *surface;
514 BOOL file_width = FALSE, file_height = FALSE;
515 BOOL file_format = FALSE, file_miplevels = FALSE;
516 BOOL dynamic_texture;
517 D3DXIMAGE_INFO imginfo;
518 UINT loaded_miplevels;
519 D3DCAPS9 caps;
520 HRESULT hr;
522 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
523 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
525 /* check for invalid parameters */
526 if (!device || !texture || !srcdata || !srcdatasize)
527 return D3DERR_INVALIDCALL;
529 hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
531 if (FAILED(hr))
533 *texture = NULL;
534 return hr;
537 /* handle default values */
538 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
539 width = imginfo.Width;
541 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
542 height = imginfo.Height;
544 if (width == D3DX_DEFAULT)
545 width = make_pow2(imginfo.Width);
547 if (height == D3DX_DEFAULT)
548 height = make_pow2(imginfo.Height);
550 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
551 format = imginfo.Format;
553 if (width == D3DX_FROM_FILE)
555 file_width = TRUE;
556 width = imginfo.Width;
559 if (height == D3DX_FROM_FILE)
561 file_height = TRUE;
562 height = imginfo.Height;
565 if (format == D3DFMT_FROM_FILE)
567 file_format = TRUE;
568 format = imginfo.Format;
571 if (miplevels == D3DX_FROM_FILE)
573 file_miplevels = TRUE;
574 miplevels = imginfo.MipLevels;
577 /* fix texture creation parameters */
578 hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
580 if (FAILED(hr))
582 *texture = NULL;
583 return hr;
586 if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
588 FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
589 miplevels = imginfo.MipLevels;
592 if (((file_width) && (width != imginfo.Width)) ||
593 ((file_height) && (height != imginfo.Height)) ||
594 ((file_format) && (format != imginfo.Format)) ||
595 ((file_miplevels) && (miplevels != imginfo.MipLevels)))
597 return D3DERR_NOTAVAILABLE;
600 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
601 return D3DERR_INVALIDCALL;
603 /* Create the to-be-filled texture */
604 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
605 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
607 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
608 texptr = &buftex;
610 else
612 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
613 texptr = texture;
616 if (FAILED(hr))
618 *texture = NULL;
619 return hr;
622 /* Load the file */
623 if (imginfo.ImageFileFormat != D3DXIFF_DDS)
625 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
626 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
627 IDirect3DSurface9_Release(surface);
629 else
631 hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
634 if (FAILED(hr))
636 IDirect3DTexture9_Release(*texptr);
637 *texture = NULL;
638 return hr;
641 loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
642 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
644 if (FAILED(hr))
646 IDirect3DTexture9_Release(*texptr);
647 *texture = NULL;
648 return hr;
651 /* Move the data to the actual texture if necessary */
652 if (texptr == &buftex)
654 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
656 if (FAILED(hr))
658 IDirect3DTexture9_Release(buftex);
659 *texture = NULL;
660 return hr;
663 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
664 IDirect3DTexture9_Release(buftex);
667 if (srcinfo)
668 *srcinfo = imginfo;
670 return D3D_OK;
673 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
674 LPCVOID srcdata,
675 UINT srcdatasize,
676 LPDIRECT3DTEXTURE9 *texture)
678 TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
680 return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
681 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
684 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
685 LPCWSTR srcfile,
686 UINT width,
687 UINT height,
688 UINT miplevels,
689 DWORD usage,
690 D3DFORMAT format,
691 D3DPOOL pool,
692 DWORD filter,
693 DWORD mipfilter,
694 D3DCOLOR colorkey,
695 D3DXIMAGE_INFO *srcinfo,
696 PALETTEENTRY *palette,
697 LPDIRECT3DTEXTURE9 *texture)
699 HRESULT hr;
700 DWORD size;
701 LPVOID buffer;
703 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
704 device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
705 mipfilter, colorkey, srcinfo, palette, texture);
707 if (!srcfile)
708 return D3DERR_INVALIDCALL;
710 hr = map_view_of_file(srcfile, &buffer, &size);
711 if (FAILED(hr))
712 return D3DXERR_INVALIDDATA;
714 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
715 filter, mipfilter, colorkey, srcinfo, palette, texture);
717 UnmapViewOfFile(buffer);
719 return hr;
722 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
723 LPCSTR srcfile,
724 UINT width,
725 UINT height,
726 UINT miplevels,
727 DWORD usage,
728 D3DFORMAT format,
729 D3DPOOL pool,
730 DWORD filter,
731 DWORD mipfilter,
732 D3DCOLOR colorkey,
733 D3DXIMAGE_INFO *srcinfo,
734 PALETTEENTRY *palette,
735 LPDIRECT3DTEXTURE9 *texture)
737 LPWSTR widename;
738 HRESULT hr;
739 DWORD len;
741 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
742 device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
743 mipfilter, colorkey, srcinfo, palette, texture);
745 if (!device || !srcfile || !texture)
746 return D3DERR_INVALIDCALL;
748 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
749 widename = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
750 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
752 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
753 usage, format, pool, filter, mipfilter,
754 colorkey, srcinfo, palette, texture);
756 HeapFree(GetProcessHeap(), 0, widename);
757 return hr;
760 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
761 LPCSTR srcfile,
762 LPDIRECT3DTEXTURE9 *texture)
764 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
766 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
767 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
770 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
771 LPCWSTR srcfile,
772 LPDIRECT3DTEXTURE9 *texture)
774 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
776 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
777 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
781 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
782 HMODULE srcmodule,
783 LPCSTR resource,
784 LPDIRECT3DTEXTURE9 *texture)
786 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
788 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
789 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
792 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
793 HMODULE srcmodule,
794 LPCWSTR resource,
795 LPDIRECT3DTEXTURE9 *texture)
797 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
799 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
800 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
803 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
804 HMODULE srcmodule,
805 LPCSTR resource,
806 UINT width,
807 UINT height,
808 UINT miplevels,
809 DWORD usage,
810 D3DFORMAT format,
811 D3DPOOL pool,
812 DWORD filter,
813 DWORD mipfilter,
814 D3DCOLOR colorkey,
815 D3DXIMAGE_INFO *srcinfo,
816 PALETTEENTRY *palette,
817 LPDIRECT3DTEXTURE9 *texture)
819 HRSRC resinfo;
821 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
823 if (!device || !texture)
824 return D3DERR_INVALIDCALL;
826 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
828 if (resinfo)
830 LPVOID buffer;
831 HRESULT hr;
832 DWORD size;
834 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
836 if (FAILED(hr))
837 return D3DXERR_INVALIDDATA;
839 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
840 height, miplevels, usage, format,
841 pool, filter, mipfilter, colorkey,
842 srcinfo, palette, texture);
845 /* Try loading the resource as bitmap data */
846 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
848 if (resinfo)
850 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
851 return E_NOTIMPL;
854 return D3DXERR_INVALIDDATA;
857 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
858 HMODULE srcmodule,
859 LPCWSTR resource,
860 UINT width,
861 UINT height,
862 UINT miplevels,
863 DWORD usage,
864 D3DFORMAT format,
865 D3DPOOL pool,
866 DWORD filter,
867 DWORD mipfilter,
868 D3DCOLOR colorkey,
869 D3DXIMAGE_INFO *srcinfo,
870 PALETTEENTRY *palette,
871 LPDIRECT3DTEXTURE9 *texture)
873 HRSRC resinfo;
875 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
877 if (!device || !texture)
878 return D3DERR_INVALIDCALL;
880 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
882 if (resinfo)
884 LPVOID buffer;
885 HRESULT hr;
886 DWORD size;
888 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
890 if (FAILED(hr))
891 return D3DXERR_INVALIDDATA;
893 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
894 height, miplevels, usage, format,
895 pool, filter, mipfilter, colorkey,
896 srcinfo, palette, texture);
899 /* Try loading the resource as bitmap data */
900 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
902 if (resinfo)
904 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
905 return E_NOTIMPL;
908 return D3DXERR_INVALIDDATA;
911 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
912 UINT size,
913 UINT miplevels,
914 DWORD usage,
915 D3DFORMAT format,
916 D3DPOOL pool,
917 LPDIRECT3DCUBETEXTURE9 *texture)
919 HRESULT hr;
921 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
922 pool, texture);
924 if (!device || !texture)
925 return D3DERR_INVALIDCALL;
927 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
929 if (FAILED(hr))
931 TRACE("D3DXCheckCubeTextureRequirements failed\n");
932 return hr;
935 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
938 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
939 LPCVOID data,
940 UINT datasize,
941 LPDIRECT3DCUBETEXTURE9 *texture)
943 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
945 return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
946 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
949 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
950 UINT width,
951 UINT height,
952 UINT depth,
953 UINT miplevels,
954 DWORD usage,
955 D3DFORMAT format,
956 D3DPOOL pool,
957 LPDIRECT3DVOLUMETEXTURE9 *texture)
959 HRESULT hr;
961 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
962 miplevels, usage, format, pool, texture);
964 if (!device || !texture)
965 return D3DERR_INVALIDCALL;
967 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
968 &miplevels, usage, &format, pool);
970 if (FAILED(hr))
972 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
973 return hr;
976 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
977 usage, format, pool, texture, NULL);
980 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
981 LPCVOID data,
982 UINT datasize,
983 LPDIRECT3DVOLUMETEXTURE9 *texture)
985 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
987 return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
988 D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
989 0, NULL, NULL, texture);
992 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
993 LPCVOID data,
994 UINT datasize,
995 UINT width,
996 UINT height,
997 UINT depth,
998 UINT miplevels,
999 DWORD usage,
1000 D3DFORMAT format,
1001 D3DPOOL pool,
1002 DWORD filter,
1003 DWORD mipfilter,
1004 D3DCOLOR colorkey,
1005 D3DXIMAGE_INFO *imageinfo,
1006 PALETTEENTRY *palette,
1007 LPDIRECT3DVOLUMETEXTURE9 *texture)
1009 FIXME("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p) : stub\n",
1010 device, data, datasize, width, height, depth, miplevels, usage, format, pool,
1011 filter, mipfilter, colorkey, imageinfo, palette, texture);
1013 return E_NOTIMPL;
1016 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
1017 LPD3DXFILL2D function,
1018 LPVOID funcdata)
1020 DWORD miplevels;
1021 DWORD m, i, x, y, c, v;
1022 D3DSURFACE_DESC desc;
1023 D3DLOCKED_RECT lock_rect;
1024 D3DXVECTOR4 value;
1025 D3DXVECTOR2 coord, size;
1026 const PixelFormatDesc *format;
1027 BYTE *data, *pos;
1028 BYTE byte, mask;
1029 float comp_value;
1031 if (texture == NULL || function == NULL)
1032 return D3DERR_INVALIDCALL;
1034 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1036 for (m = 0; m < miplevels; m++)
1038 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1039 return D3DERR_INVALIDCALL;
1041 format = get_format_info(desc.Format);
1042 if (format->format == D3DFMT_UNKNOWN)
1044 FIXME("Unsupported texture format %#x\n", desc.Format);
1045 return D3DERR_INVALIDCALL;
1048 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1049 return D3DERR_INVALIDCALL;
1051 size.x = 1.0f / desc.Width;
1052 size.y = 1.0f / desc.Height;
1054 data = lock_rect.pBits;
1056 for (y = 0; y < desc.Height; y++)
1058 /* The callback function expects the coordinates of the center
1059 of the texel */
1060 coord.y = (y + 0.5f) / desc.Height;
1062 for (x = 0; x < desc.Width; x++)
1064 coord.x = (x + 0.5f) / desc.Width;
1066 function(&value, &coord, &size, funcdata);
1068 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1070 for (i = 0; i < format->bytes_per_pixel; i++)
1071 pos[i] = 0;
1073 for (c = 0; c < 4; c++)
1075 switch (c)
1077 case 0: /* Alpha */
1078 comp_value = value.w;
1079 break;
1080 case 1: /* Red */
1081 comp_value = value.x;
1082 break;
1083 case 2: /* Green */
1084 comp_value = value.y;
1085 break;
1086 case 3: /* Blue */
1087 comp_value = value.z;
1088 break;
1091 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1093 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1095 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1096 byte = (v << format->shift[c] >> i) & mask;
1097 pos[i / 8] |= byte;
1102 IDirect3DTexture9_UnlockRect(texture, m);
1105 return D3D_OK;
1108 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1109 const void *src_data,
1110 UINT src_data_size,
1111 UINT size,
1112 UINT mip_levels,
1113 DWORD usage,
1114 D3DFORMAT format,
1115 D3DPOOL pool,
1116 DWORD filter,
1117 DWORD mip_filter,
1118 D3DCOLOR color_key,
1119 D3DXIMAGE_INFO *src_info,
1120 PALETTEENTRY *palette,
1121 IDirect3DCubeTexture9 **cube_texture)
1123 HRESULT hr;
1124 D3DCAPS9 caps;
1125 UINT loaded_miplevels;
1126 D3DXIMAGE_INFO img_info;
1127 BOOL file_size = FALSE;
1128 BOOL file_format = FALSE;
1129 BOOL file_mip_levels = FALSE;
1130 IDirect3DCubeTexture9 *tex, *buftex;
1132 TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
1133 src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
1134 color_key, src_info, palette, cube_texture);
1136 if (!device || !cube_texture || !src_data || !src_data_size)
1137 return D3DERR_INVALIDCALL;
1139 hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
1140 if (FAILED(hr))
1141 return hr;
1143 if (img_info.ImageFileFormat != D3DXIFF_DDS)
1144 return D3DXERR_INVALIDDATA;
1146 if (img_info.Width != img_info.Height)
1147 return D3DXERR_INVALIDDATA;
1149 if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
1150 size = img_info.Width;
1151 if (size == D3DX_DEFAULT)
1152 size = make_pow2(img_info.Width);
1154 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1155 format = img_info.Format;
1157 if (size == D3DX_FROM_FILE)
1159 file_size = TRUE;
1160 size = img_info.Width;
1163 if (format == D3DFMT_FROM_FILE)
1165 file_format = TRUE;
1166 format = img_info.Format;
1169 if (mip_levels == D3DX_FROM_FILE)
1171 file_mip_levels = TRUE;
1172 mip_levels = img_info.MipLevels;
1175 hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
1176 if (FAILED(hr))
1177 return hr;
1179 if ((file_size && size != img_info.Width)
1180 || (file_format && format != img_info.Format)
1181 || (file_mip_levels && mip_levels != img_info.MipLevels))
1182 return D3DERR_NOTAVAILABLE;
1184 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1185 if (FAILED(hr))
1186 return D3DERR_INVALIDCALL;
1188 if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
1190 FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
1191 mip_levels = img_info.MipLevels;
1194 if (pool == D3DPOOL_DEFAULT && !((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && usage == D3DUSAGE_DYNAMIC))
1196 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1197 tex = buftex;
1199 else
1201 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1202 buftex = NULL;
1204 if (FAILED(hr))
1205 return hr;
1207 hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info);
1208 if (FAILED(hr))
1210 IDirect3DCubeTexture9_Release(tex);
1211 return hr;
1214 loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels);
1215 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
1216 if (FAILED(hr))
1218 IDirect3DCubeTexture9_Release(tex);
1219 return hr;
1222 if (buftex)
1224 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1225 if (FAILED(hr))
1227 IDirect3DCubeTexture9_Release(buftex);
1228 return hr;
1231 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1232 IDirect3DCubeTexture9_Release(buftex);
1235 if (src_info)
1236 *src_info = img_info;
1238 *cube_texture = tex;
1239 return D3D_OK;
1243 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1244 const char *src_filename,
1245 IDirect3DCubeTexture9 **cube_texture)
1247 int len;
1248 HRESULT hr;
1249 WCHAR *filename;
1250 void *data;
1251 DWORD data_size;
1253 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1255 if (!src_filename) return D3DERR_INVALIDCALL;
1257 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1258 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1259 if (!filename) return E_OUTOFMEMORY;
1260 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1262 hr = map_view_of_file(filename, &data, &data_size);
1263 if (FAILED(hr))
1265 HeapFree(GetProcessHeap(), 0, filename);
1266 return D3DXERR_INVALIDDATA;
1269 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1270 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1272 UnmapViewOfFile(data);
1273 HeapFree(GetProcessHeap(), 0, filename);
1274 return hr;
1277 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1278 const WCHAR *src_filename,
1279 IDirect3DCubeTexture9 **cube_texture)
1281 HRESULT hr;
1282 void *data;
1283 DWORD data_size;
1285 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1287 hr = map_view_of_file(src_filename, &data, &data_size);
1288 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1290 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1291 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1293 UnmapViewOfFile(data);
1294 return hr;
1297 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1298 const char *src_filename,
1299 UINT size,
1300 UINT mip_levels,
1301 DWORD usage,
1302 D3DFORMAT format,
1303 D3DPOOL pool,
1304 DWORD filter,
1305 DWORD mip_filter,
1306 D3DCOLOR color_key,
1307 D3DXIMAGE_INFO *image_info,
1308 PALETTEENTRY *palette,
1309 IDirect3DCubeTexture9 **cube_texture)
1311 int len;
1312 HRESULT hr;
1313 WCHAR *filename;
1314 void *data;
1315 DWORD data_size;
1317 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1318 device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1319 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1321 if (!src_filename) return D3DERR_INVALIDCALL;
1323 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1324 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1325 if (!filename) return E_OUTOFMEMORY;
1326 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1328 hr = map_view_of_file(filename, &data, &data_size);
1329 if (FAILED(hr))
1331 HeapFree(GetProcessHeap(), 0, filename);
1332 return D3DXERR_INVALIDDATA;
1335 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1336 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1338 UnmapViewOfFile(data);
1339 HeapFree(GetProcessHeap(), 0, filename);
1340 return hr;
1343 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1344 const WCHAR *src_filename,
1345 UINT size,
1346 UINT mip_levels,
1347 DWORD usage,
1348 D3DFORMAT format,
1349 D3DPOOL pool,
1350 DWORD filter,
1351 DWORD mip_filter,
1352 D3DCOLOR color_key,
1353 D3DXIMAGE_INFO *image_info,
1354 PALETTEENTRY *palette,
1355 IDirect3DCubeTexture9 **cube_texture)
1357 HRESULT hr;
1358 void *data;
1359 DWORD data_size;
1361 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1362 device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1363 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1365 hr = map_view_of_file(src_filename, &data, &data_size);
1366 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1368 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1369 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1371 UnmapViewOfFile(data);
1372 return hr;
1375 enum cube_coord
1377 XCOORD = 0,
1378 XCOORDINV = 1,
1379 YCOORD = 2,
1380 YCOORDINV = 3,
1381 ZERO = 4,
1382 ONE = 5
1385 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1387 switch (coord)
1389 case XCOORD:
1390 return x + 0.5f;
1391 case XCOORDINV:
1392 return size - x - 0.5f;
1393 case YCOORD:
1394 return y + 0.5f;
1395 case YCOORDINV:
1396 return size - y - 0.5f;
1397 case ZERO:
1398 return 0.0f;
1399 case ONE:
1400 return size;
1401 default:
1402 ERR("Unexpected coordinate value\n");
1403 return 0.0f;
1407 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1408 LPD3DXFILL3D function,
1409 LPVOID funcdata)
1411 DWORD miplevels;
1412 DWORD m, i, x, y, c, f, v;
1413 D3DSURFACE_DESC desc;
1414 D3DLOCKED_RECT lock_rect;
1415 D3DXVECTOR4 value;
1416 D3DXVECTOR3 coord, size;
1417 const PixelFormatDesc *format;
1418 BYTE *data, *pos;
1419 BYTE byte, mask;
1420 float comp_value;
1421 static const enum cube_coord coordmap[6][3] =
1423 {ONE, YCOORDINV, XCOORDINV},
1424 {ZERO, YCOORDINV, XCOORD},
1425 {XCOORD, ONE, YCOORD},
1426 {XCOORD, ZERO, YCOORDINV},
1427 {XCOORD, YCOORDINV, ONE},
1428 {XCOORDINV, YCOORDINV, ZERO}
1431 if (texture == NULL || function == NULL)
1432 return D3DERR_INVALIDCALL;
1434 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1436 for (m = 0; m < miplevels; m++)
1438 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1439 return D3DERR_INVALIDCALL;
1441 format = get_format_info(desc.Format);
1442 if (format->format == D3DFMT_UNKNOWN)
1444 FIXME("Unsupported texture format %#x\n", desc.Format);
1445 return D3DERR_INVALIDCALL;
1448 for (f = 0; f < 6; f++)
1450 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1451 return D3DERR_INVALIDCALL;
1453 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1454 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1455 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1457 data = lock_rect.pBits;
1459 for (y = 0; y < desc.Height; y++)
1461 for (x = 0; x < desc.Width; x++)
1463 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1464 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1465 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1467 function(&value, &coord, &size, funcdata);
1469 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1471 for (i = 0; i < format->bytes_per_pixel; i++)
1472 pos[i] = 0;
1474 for (c = 0; c < 4; c++)
1476 switch (c)
1478 case 0: /* Alpha */
1479 comp_value = value.w;
1480 break;
1481 case 1: /* Red */
1482 comp_value = value.x;
1483 break;
1484 case 2: /* Green */
1485 comp_value = value.y;
1486 break;
1487 case 3: /* Blue */
1488 comp_value = value.z;
1489 break;
1492 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1494 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1496 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1497 byte = (v << format->shift[c] >> i) & mask;
1498 pos[i / 8] |= byte;
1503 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1507 return D3D_OK;
1510 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1511 LPD3DXFILL3D function,
1512 LPVOID funcdata)
1514 DWORD miplevels;
1515 DWORD m, i, x, y, z, c, v;
1516 D3DVOLUME_DESC desc;
1517 D3DLOCKED_BOX lock_box;
1518 D3DXVECTOR4 value;
1519 D3DXVECTOR3 coord, size;
1520 const PixelFormatDesc *format;
1521 BYTE *data, *pos;
1522 BYTE byte, mask;
1523 float comp_value;
1525 if (texture == NULL || function == NULL)
1526 return D3DERR_INVALIDCALL;
1528 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1530 for (m = 0; m < miplevels; m++)
1532 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1533 return D3DERR_INVALIDCALL;
1535 format = get_format_info(desc.Format);
1536 if (format->format == D3DFMT_UNKNOWN)
1538 FIXME("Unsupported texture format %#x\n", desc.Format);
1539 return D3DERR_INVALIDCALL;
1542 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1543 return D3DERR_INVALIDCALL;
1545 size.x = 1.0f / desc.Width;
1546 size.y = 1.0f / desc.Height;
1547 size.z = 1.0f / desc.Depth;
1549 data = lock_box.pBits;
1551 for (z = 0; z < desc.Depth; z++)
1553 /* The callback function expects the coordinates of the center
1554 of the texel */
1555 coord.z = (z + 0.5f) / desc.Depth;
1557 for (y = 0; y < desc.Height; y++)
1559 coord.y = (y + 0.5f) / desc.Height;
1561 for (x = 0; x < desc.Width; x++)
1563 coord.x = (x + 0.5f) / desc.Width;
1565 function(&value, &coord, &size, funcdata);
1567 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1569 for (i = 0; i < format->bytes_per_pixel; i++)
1570 pos[i] = 0;
1572 for (c = 0; c < 4; c++)
1574 switch (c)
1576 case 0: /* Alpha */
1577 comp_value = value.w;
1578 break;
1579 case 1: /* Red */
1580 comp_value = value.x;
1581 break;
1582 case 2: /* Green */
1583 comp_value = value.y;
1584 break;
1585 case 3: /* Blue */
1586 comp_value = value.z;
1587 break;
1590 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1592 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1594 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1595 byte = (v << format->shift[c] >> i) & mask;
1596 pos[i / 8] |= byte;
1602 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1605 return D3D_OK;