user32: Rearrange ComboBox repositioning code.
[wine.git] / dlls / d3dx9_36 / texture.c
blob2d94f7215bbb61d3df81c992bb0359882e5e9d3a
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(IDirect3DBaseTexture9 *texture,
65 const PALETTEENTRY *palette,
66 UINT srclevel,
67 DWORD filter)
69 UINT level;
70 HRESULT hr;
71 D3DRESOURCETYPE type;
73 TRACE("(%p, %p, %u, %#x)\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 == D3DX_DEFAULT)
82 srclevel = 0;
83 else if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
84 return D3DERR_INVALIDCALL;
86 switch (type = IDirect3DBaseTexture9_GetType(texture))
88 case D3DRTYPE_TEXTURE:
89 case D3DRTYPE_CUBETEXTURE:
91 IDirect3DSurface9 *topsurf, *mipsurf;
92 D3DSURFACE_DESC desc;
93 int i, numfaces;
95 if (type == D3DRTYPE_TEXTURE)
97 numfaces = 1;
98 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
100 else
102 numfaces = 6;
103 IDirect3DCubeTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
106 if (filter == D3DX_DEFAULT)
108 if (is_pow2(desc.Width) && is_pow2(desc.Height))
109 filter = D3DX_FILTER_BOX;
110 else
111 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
114 for (i = 0; i < numfaces; i++)
116 level = srclevel + 1;
117 hr = get_surface(type, texture, i, srclevel, &topsurf);
119 if (FAILED(hr))
120 return D3DERR_INVALIDCALL;
122 while (get_surface(type, texture, i, level, &mipsurf) == D3D_OK)
124 hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
125 IDirect3DSurface9_Release(topsurf);
126 topsurf = mipsurf;
128 if (FAILED(hr))
129 break;
131 level++;
134 IDirect3DSurface9_Release(topsurf);
135 if (FAILED(hr))
136 return hr;
139 return D3D_OK;
142 case D3DRTYPE_VOLUMETEXTURE:
144 D3DVOLUME_DESC desc;
145 int level, level_count;
146 IDirect3DVolume9 *top_volume, *mip_volume;
147 IDirect3DVolumeTexture9 *volume_texture = (IDirect3DVolumeTexture9*) texture;
149 IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, srclevel, &desc);
151 if (filter == D3DX_DEFAULT)
153 if (is_pow2(desc.Width) && is_pow2(desc.Height) && is_pow2(desc.Depth))
154 filter = D3DX_FILTER_BOX;
155 else
156 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
159 hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, srclevel, &top_volume);
160 if (FAILED(hr))
161 return hr;
163 level_count = IDirect3DVolumeTexture9_GetLevelCount(volume_texture);
164 for (level = srclevel + 1; level < level_count; level++)
166 IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, level, &mip_volume);
167 hr = D3DXLoadVolumeFromVolume(mip_volume, palette, NULL, top_volume, palette, NULL, filter, 0);
168 IDirect3DVolume9_Release(top_volume);
169 top_volume = mip_volume;
171 if (FAILED(hr))
172 break;
175 IDirect3DVolume9_Release(top_volume);
176 if (FAILED(hr))
177 return hr;
179 return D3D_OK;
182 default:
183 return D3DERR_INVALIDCALL;
187 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
188 UINT* width,
189 UINT* height,
190 UINT* miplevels,
191 DWORD usage,
192 D3DFORMAT* format,
193 D3DPOOL pool)
195 UINT w = (width && *width) ? *width : 1;
196 UINT h = (height && *height) ? *height : 1;
197 D3DCAPS9 caps;
198 D3DDEVICE_CREATION_PARAMETERS params;
199 IDirect3D9 *d3d = NULL;
200 D3DDISPLAYMODE mode;
201 HRESULT hr;
202 D3DFORMAT usedformat = D3DFMT_UNKNOWN;
204 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
206 if (!device)
207 return D3DERR_INVALIDCALL;
209 /* usage */
210 if (usage == D3DX_DEFAULT)
211 usage = 0;
212 if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
213 return D3DERR_INVALIDCALL;
215 /* pool */
216 if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
217 return D3DERR_INVALIDCALL;
219 /* width and height */
220 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
221 return D3DERR_INVALIDCALL;
223 /* 256 x 256 default width/height */
224 if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
225 w = h = 256;
226 else if (w == D3DX_DEFAULT)
227 w = (height ? h : 256);
228 else if (h == D3DX_DEFAULT)
229 h = (width ? w : 256);
231 /* ensure width/height is power of 2 */
232 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
233 w = make_pow2(w);
235 if (w > caps.MaxTextureWidth)
236 w = caps.MaxTextureWidth;
238 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
239 h = make_pow2(h);
241 if (h > caps.MaxTextureHeight)
242 h = caps.MaxTextureHeight;
244 /* texture must be square? */
245 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
247 if (w > h)
248 h = w;
249 else
250 w = h;
253 if (width)
254 *width = w;
256 if (height)
257 *height = h;
259 /* miplevels */
260 if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
262 if (*miplevels > 1)
263 *miplevels = 0;
265 else if (miplevels)
267 UINT max_mipmaps = 1;
269 if (!width && !height)
270 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
271 else
273 UINT max_dimen = max(w, h);
275 while (max_dimen > 1)
277 max_dimen >>= 1;
278 max_mipmaps++;
282 if (*miplevels == 0 || *miplevels > max_mipmaps)
283 *miplevels = max_mipmaps;
286 /* format */
287 if (format)
289 TRACE("Requested format %x\n", *format);
290 usedformat = *format;
293 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
295 if (FAILED(hr))
296 goto cleanup;
298 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
300 if (FAILED(hr))
301 goto cleanup;
303 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
305 if (FAILED(hr))
306 goto cleanup;
308 if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
309 usedformat = D3DFMT_A8R8G8B8;
311 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
312 usage, D3DRTYPE_TEXTURE, usedformat);
314 if (FAILED(hr))
316 /* Heuristic to choose the fallback format */
317 const PixelFormatDesc *fmt = get_format_info(usedformat);
318 BOOL allow_24bits;
319 int bestscore = INT_MIN, i = 0, j;
320 unsigned int channels;
321 const PixelFormatDesc *curfmt;
323 if (!fmt)
325 FIXME("Pixel format %x not handled\n", usedformat);
326 goto cleanup;
329 allow_24bits = fmt->bytes_per_pixel == 3;
330 channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
331 + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
332 usedformat = D3DFMT_UNKNOWN;
334 while ((curfmt = get_format_info_idx(i)))
336 unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
337 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
338 int score;
340 i++;
342 if (curchannels < channels)
343 continue;
344 if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
345 continue;
347 hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
348 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
349 if (FAILED(hr))
350 continue;
352 /* This format can be used, let's evaluate it.
353 Weights chosen quite arbitrarily... */
354 score = 16 - 4 * (curchannels - channels);
356 for (j = 0; j < 4; j++)
358 int diff = curfmt->bits[j] - fmt->bits[j];
359 score += 16 - (diff < 0 ? -diff * 4 : diff);
362 if (score > bestscore)
364 bestscore = score;
365 usedformat = curfmt->format;
368 hr = D3D_OK;
371 cleanup:
373 if (d3d)
374 IDirect3D9_Release(d3d);
376 if (FAILED(hr))
377 return hr;
379 if (usedformat == D3DFMT_UNKNOWN)
381 WARN("Couldn't find a suitable pixel format\n");
382 return D3DERR_NOTAVAILABLE;
385 TRACE("Format chosen: %x\n", usedformat);
386 if (format)
387 *format = usedformat;
389 return D3D_OK;
392 HRESULT WINAPI D3DXCheckCubeTextureRequirements(LPDIRECT3DDEVICE9 device,
393 UINT *size,
394 UINT *miplevels,
395 DWORD usage,
396 D3DFORMAT *format,
397 D3DPOOL pool)
399 D3DCAPS9 caps;
400 UINT s = (size && *size) ? *size : 256;
401 HRESULT hr;
403 TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
405 if (s == D3DX_DEFAULT)
406 s = 256;
408 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
409 return D3DERR_INVALIDCALL;
411 if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
412 return D3DERR_NOTAVAILABLE;
414 /* ensure width/height is power of 2 */
415 if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
416 s = make_pow2(s);
418 hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
420 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
422 if(miplevels)
423 *miplevels = 1;
426 if (size)
427 *size = s;
429 return hr;
432 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(LPDIRECT3DDEVICE9 device,
433 UINT *width,
434 UINT *height,
435 UINT *depth,
436 UINT *miplevels,
437 DWORD usage,
438 D3DFORMAT *format,
439 D3DPOOL pool)
441 D3DCAPS9 caps;
442 UINT w = width ? *width : D3DX_DEFAULT;
443 UINT h = height ? *height : D3DX_DEFAULT;
444 UINT d = (depth && *depth) ? *depth : 1;
445 HRESULT hr;
447 TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
448 usage, format, pool);
450 if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
451 return D3DERR_INVALIDCALL;
453 if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
454 return D3DERR_NOTAVAILABLE;
456 hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
457 if (d == D3DX_DEFAULT)
458 d = 1;
460 /* ensure width/height is power of 2 */
461 if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
462 (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
464 w = make_pow2(w);
465 h = make_pow2(h);
466 d = make_pow2(d);
469 if (w > caps.MaxVolumeExtent)
470 w = caps.MaxVolumeExtent;
471 if (h > caps.MaxVolumeExtent)
472 h = caps.MaxVolumeExtent;
473 if (d > caps.MaxVolumeExtent)
474 d = caps.MaxVolumeExtent;
476 if (miplevels)
478 if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
479 *miplevels = 1;
480 else if ((usage & D3DUSAGE_AUTOGENMIPMAP))
482 if (*miplevels > 1)
483 *miplevels = 0;
485 else
487 UINT max_mipmaps = 1;
488 UINT max_dimen = max(max(w, h), d);
490 while (max_dimen > 1)
492 max_dimen >>= 1;
493 max_mipmaps++;
496 if (*miplevels == 0 || *miplevels > max_mipmaps)
497 *miplevels = max_mipmaps;
501 if (width)
502 *width = w;
503 if (height)
504 *height = h;
505 if (depth)
506 *depth = d;
508 return hr;
511 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
512 UINT width,
513 UINT height,
514 UINT miplevels,
515 DWORD usage,
516 D3DFORMAT format,
517 D3DPOOL pool,
518 LPDIRECT3DTEXTURE9 *ppTexture)
520 HRESULT hr;
522 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
523 pool, ppTexture);
525 if (!pDevice || !ppTexture)
526 return D3DERR_INVALIDCALL;
528 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
530 if (FAILED(hr))
531 return hr;
533 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
536 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
537 LPCVOID srcdata,
538 UINT srcdatasize,
539 UINT width,
540 UINT height,
541 UINT miplevels,
542 DWORD usage,
543 D3DFORMAT format,
544 D3DPOOL pool,
545 DWORD filter,
546 DWORD mipfilter,
547 D3DCOLOR colorkey,
548 D3DXIMAGE_INFO* srcinfo,
549 PALETTEENTRY* palette,
550 LPDIRECT3DTEXTURE9* texture)
552 IDirect3DTexture9 **texptr;
553 IDirect3DTexture9 *buftex;
554 IDirect3DSurface9 *surface;
555 BOOL file_width = FALSE, file_height = FALSE;
556 BOOL file_format = FALSE, file_miplevels = FALSE;
557 BOOL dynamic_texture;
558 D3DXIMAGE_INFO imginfo;
559 UINT loaded_miplevels;
560 D3DCAPS9 caps;
561 HRESULT hr;
563 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
564 height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
566 /* check for invalid parameters */
567 if (!device || !texture || !srcdata || !srcdatasize)
568 return D3DERR_INVALIDCALL;
570 hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
572 if (FAILED(hr))
574 *texture = NULL;
575 return hr;
578 /* handle default values */
579 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
580 width = imginfo.Width;
582 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
583 height = imginfo.Height;
585 if (width == D3DX_DEFAULT)
586 width = make_pow2(imginfo.Width);
588 if (height == D3DX_DEFAULT)
589 height = make_pow2(imginfo.Height);
591 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
592 format = imginfo.Format;
594 if (width == D3DX_FROM_FILE)
596 file_width = TRUE;
597 width = imginfo.Width;
600 if (height == D3DX_FROM_FILE)
602 file_height = TRUE;
603 height = imginfo.Height;
606 if (format == D3DFMT_FROM_FILE)
608 file_format = TRUE;
609 format = imginfo.Format;
612 if (miplevels == D3DX_FROM_FILE)
614 file_miplevels = TRUE;
615 miplevels = imginfo.MipLevels;
618 /* fix texture creation parameters */
619 hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
621 if (FAILED(hr))
623 *texture = NULL;
624 return hr;
627 if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
629 FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
630 miplevels = imginfo.MipLevels;
633 if (((file_width) && (width != imginfo.Width)) ||
634 ((file_height) && (height != imginfo.Height)) ||
635 ((file_format) && (format != imginfo.Format)) ||
636 ((file_miplevels) && (miplevels != imginfo.MipLevels)))
638 return D3DERR_NOTAVAILABLE;
641 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
642 return D3DERR_INVALIDCALL;
644 /* Create the to-be-filled texture */
645 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
646 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
648 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
649 texptr = &buftex;
651 else
653 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
654 texptr = texture;
657 if (FAILED(hr))
659 *texture = NULL;
660 return hr;
663 /* Load the file */
664 if (imginfo.ImageFileFormat != D3DXIFF_DDS)
666 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
667 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
668 IDirect3DSurface9_Release(surface);
670 else
672 hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
675 if (FAILED(hr))
677 IDirect3DTexture9_Release(*texptr);
678 *texture = NULL;
679 return hr;
682 loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
683 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
685 if (FAILED(hr))
687 IDirect3DTexture9_Release(*texptr);
688 *texture = NULL;
689 return hr;
692 /* Move the data to the actual texture if necessary */
693 if (texptr == &buftex)
695 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
697 if (FAILED(hr))
699 IDirect3DTexture9_Release(buftex);
700 *texture = NULL;
701 return hr;
704 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
705 IDirect3DTexture9_Release(buftex);
708 if (srcinfo)
709 *srcinfo = imginfo;
711 return D3D_OK;
714 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
715 LPCVOID srcdata,
716 UINT srcdatasize,
717 LPDIRECT3DTEXTURE9 *texture)
719 TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
721 return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
722 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
725 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
726 LPCWSTR srcfile,
727 UINT width,
728 UINT height,
729 UINT miplevels,
730 DWORD usage,
731 D3DFORMAT format,
732 D3DPOOL pool,
733 DWORD filter,
734 DWORD mipfilter,
735 D3DCOLOR colorkey,
736 D3DXIMAGE_INFO *srcinfo,
737 PALETTEENTRY *palette,
738 LPDIRECT3DTEXTURE9 *texture)
740 HRESULT hr;
741 DWORD size;
742 LPVOID buffer;
744 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
745 device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
746 mipfilter, colorkey, srcinfo, palette, texture);
748 if (!srcfile)
749 return D3DERR_INVALIDCALL;
751 hr = map_view_of_file(srcfile, &buffer, &size);
752 if (FAILED(hr))
753 return D3DXERR_INVALIDDATA;
755 hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
756 filter, mipfilter, colorkey, srcinfo, palette, texture);
758 UnmapViewOfFile(buffer);
760 return hr;
763 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
764 LPCSTR srcfile,
765 UINT width,
766 UINT height,
767 UINT miplevels,
768 DWORD usage,
769 D3DFORMAT format,
770 D3DPOOL pool,
771 DWORD filter,
772 DWORD mipfilter,
773 D3DCOLOR colorkey,
774 D3DXIMAGE_INFO *srcinfo,
775 PALETTEENTRY *palette,
776 LPDIRECT3DTEXTURE9 *texture)
778 LPWSTR widename;
779 HRESULT hr;
780 DWORD len;
782 TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
783 device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
784 mipfilter, colorkey, srcinfo, palette, texture);
786 if (!device || !srcfile || !texture)
787 return D3DERR_INVALIDCALL;
789 len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
790 widename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*widename));
791 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
793 hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
794 usage, format, pool, filter, mipfilter,
795 colorkey, srcinfo, palette, texture);
797 HeapFree(GetProcessHeap(), 0, widename);
798 return hr;
801 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
802 LPCSTR srcfile,
803 LPDIRECT3DTEXTURE9 *texture)
805 TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
807 return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
808 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
811 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
812 LPCWSTR srcfile,
813 LPDIRECT3DTEXTURE9 *texture)
815 TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
817 return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
818 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
822 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
823 HMODULE srcmodule,
824 LPCSTR resource,
825 LPDIRECT3DTEXTURE9 *texture)
827 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
829 return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
830 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
833 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
834 HMODULE srcmodule,
835 LPCWSTR resource,
836 LPDIRECT3DTEXTURE9 *texture)
838 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
840 return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
841 D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
844 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
845 HMODULE srcmodule,
846 LPCSTR resource,
847 UINT width,
848 UINT height,
849 UINT miplevels,
850 DWORD usage,
851 D3DFORMAT format,
852 D3DPOOL pool,
853 DWORD filter,
854 DWORD mipfilter,
855 D3DCOLOR colorkey,
856 D3DXIMAGE_INFO *srcinfo,
857 PALETTEENTRY *palette,
858 LPDIRECT3DTEXTURE9 *texture)
860 HRSRC resinfo;
862 TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
864 if (!device || !texture)
865 return D3DERR_INVALIDCALL;
867 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
869 if (resinfo)
871 LPVOID buffer;
872 HRESULT hr;
873 DWORD size;
875 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
877 if (FAILED(hr))
878 return D3DXERR_INVALIDDATA;
880 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
881 height, miplevels, usage, format,
882 pool, filter, mipfilter, colorkey,
883 srcinfo, palette, texture);
886 /* Try loading the resource as bitmap data */
887 resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
889 if (resinfo)
891 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
892 return E_NOTIMPL;
895 return D3DXERR_INVALIDDATA;
898 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
899 HMODULE srcmodule,
900 LPCWSTR resource,
901 UINT width,
902 UINT height,
903 UINT miplevels,
904 DWORD usage,
905 D3DFORMAT format,
906 D3DPOOL pool,
907 DWORD filter,
908 DWORD mipfilter,
909 D3DCOLOR colorkey,
910 D3DXIMAGE_INFO *srcinfo,
911 PALETTEENTRY *palette,
912 LPDIRECT3DTEXTURE9 *texture)
914 HRSRC resinfo;
916 TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
918 if (!device || !texture)
919 return D3DERR_INVALIDCALL;
921 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
923 if (resinfo)
925 LPVOID buffer;
926 HRESULT hr;
927 DWORD size;
929 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
931 if (FAILED(hr))
932 return D3DXERR_INVALIDDATA;
934 return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
935 height, miplevels, usage, format,
936 pool, filter, mipfilter, colorkey,
937 srcinfo, palette, texture);
940 /* Try loading the resource as bitmap data */
941 resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
943 if (resinfo)
945 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
946 return E_NOTIMPL;
949 return D3DXERR_INVALIDDATA;
952 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
953 UINT size,
954 UINT miplevels,
955 DWORD usage,
956 D3DFORMAT format,
957 D3DPOOL pool,
958 LPDIRECT3DCUBETEXTURE9 *texture)
960 HRESULT hr;
962 TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
963 pool, texture);
965 if (!device || !texture)
966 return D3DERR_INVALIDCALL;
968 hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
970 if (FAILED(hr))
972 TRACE("D3DXCheckCubeTextureRequirements failed\n");
973 return hr;
976 return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
979 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
980 LPCVOID data,
981 UINT datasize,
982 LPDIRECT3DCUBETEXTURE9 *texture)
984 TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
986 return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
987 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
990 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
991 UINT width,
992 UINT height,
993 UINT depth,
994 UINT miplevels,
995 DWORD usage,
996 D3DFORMAT format,
997 D3DPOOL pool,
998 LPDIRECT3DVOLUMETEXTURE9 *texture)
1000 HRESULT hr;
1002 TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
1003 miplevels, usage, format, pool, texture);
1005 if (!device || !texture)
1006 return D3DERR_INVALIDCALL;
1008 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
1009 &miplevels, usage, &format, pool);
1011 if (FAILED(hr))
1013 TRACE("D3DXCheckVolumeTextureRequirements failed\n");
1014 return hr;
1017 return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
1018 usage, format, pool, texture, NULL);
1021 HRESULT WINAPI D3DXCreateVolumeTextureFromFileA(IDirect3DDevice9 *device,
1022 const char *filename,
1023 IDirect3DVolumeTexture9 **volume_texture)
1025 int len;
1026 HRESULT hr;
1027 void *data;
1028 DWORD data_size;
1029 WCHAR *filenameW;
1031 TRACE("(%p, %s, %p): relay\n",
1032 device, debugstr_a(filename), volume_texture);
1034 if (!filename) return D3DERR_INVALIDCALL;
1036 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1037 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1038 if (!filenameW) return E_OUTOFMEMORY;
1039 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1041 hr = map_view_of_file(filenameW, &data, &data_size);
1042 HeapFree(GetProcessHeap(), 0, filenameW);
1043 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1045 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1046 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1048 UnmapViewOfFile(data);
1049 return hr;
1052 HRESULT WINAPI D3DXCreateVolumeTextureFromFileW(IDirect3DDevice9 *device,
1053 const WCHAR *filename,
1054 IDirect3DVolumeTexture9 **volume_texture)
1056 HRESULT hr;
1057 void *data;
1058 DWORD data_size;
1060 TRACE("(%p, %s, %p): relay\n",
1061 device, debugstr_w(filename), volume_texture);
1063 if (!filename) return D3DERR_INVALIDCALL;
1065 hr = map_view_of_file(filename, &data, &data_size);
1066 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1068 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
1069 D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
1071 UnmapViewOfFile(data);
1072 return hr;
1075 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExA(IDirect3DDevice9 *device,
1076 const char *filename,
1077 UINT width,
1078 UINT height,
1079 UINT depth,
1080 UINT mip_levels,
1081 DWORD usage,
1082 D3DFORMAT format,
1083 D3DPOOL pool,
1084 DWORD filter,
1085 DWORD mip_filter,
1086 D3DCOLOR color_key,
1087 D3DXIMAGE_INFO *src_info,
1088 PALETTEENTRY *palette,
1089 IDirect3DVolumeTexture9 **volume_texture)
1091 int len;
1092 HRESULT hr;
1093 WCHAR *filenameW;
1094 void *data;
1095 DWORD data_size;
1097 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1098 device, debugstr_a(filename), width, height, depth, mip_levels,
1099 usage, format, pool, filter, mip_filter, color_key, src_info,
1100 palette, volume_texture);
1102 if (!filename) return D3DERR_INVALIDCALL;
1104 len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1105 filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1106 if (!filenameW) return E_OUTOFMEMORY;
1107 MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1109 hr = map_view_of_file(filenameW, &data, &data_size);
1110 HeapFree(GetProcessHeap(), 0, filenameW);
1111 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1113 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1114 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1115 volume_texture);
1117 UnmapViewOfFile(data);
1118 return hr;
1121 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExW(IDirect3DDevice9 *device,
1122 const WCHAR *filename,
1123 UINT width,
1124 UINT height,
1125 UINT depth,
1126 UINT mip_levels,
1127 DWORD usage,
1128 D3DFORMAT format,
1129 D3DPOOL pool,
1130 DWORD filter,
1131 DWORD mip_filter,
1132 D3DCOLOR color_key,
1133 D3DXIMAGE_INFO *src_info,
1134 PALETTEENTRY *palette,
1135 IDirect3DVolumeTexture9 **volume_texture)
1137 HRESULT hr;
1138 void *data;
1139 DWORD data_size;
1141 TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1142 device, debugstr_w(filename), width, height, depth, mip_levels,
1143 usage, format, pool, filter, mip_filter, color_key, src_info,
1144 palette, volume_texture);
1146 if (!filename) return D3DERR_INVALIDCALL;
1148 hr = map_view_of_file(filename, &data, &data_size);
1149 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1151 hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1152 mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1153 volume_texture);
1155 UnmapViewOfFile(data);
1156 return hr;
1159 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device,
1160 const void *data,
1161 UINT data_size,
1162 IDirect3DVolumeTexture9 **volume_texture)
1164 TRACE("(%p, %p, %u, %p): relay\n", device, data, data_size, volume_texture);
1166 return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1167 D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
1168 0, NULL, NULL, volume_texture);
1171 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1172 const void *data,
1173 UINT data_size,
1174 UINT width,
1175 UINT height,
1176 UINT depth,
1177 UINT mip_levels,
1178 DWORD usage,
1179 D3DFORMAT format,
1180 D3DPOOL pool,
1181 DWORD filter,
1182 DWORD mip_filter,
1183 D3DCOLOR color_key,
1184 D3DXIMAGE_INFO *info,
1185 PALETTEENTRY *palette,
1186 IDirect3DVolumeTexture9 **volume_texture)
1188 HRESULT hr;
1189 D3DCAPS9 caps;
1190 D3DXIMAGE_INFO image_info;
1191 BOOL dynamic_texture;
1192 BOOL file_width = FALSE;
1193 BOOL file_height = FALSE;
1194 BOOL file_depth = FALSE;
1195 BOOL file_format = FALSE;
1196 BOOL file_mip_levels = FALSE;
1197 IDirect3DVolumeTexture9 *tex, *buftex;
1199 TRACE("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n",
1200 device, data, data_size, width, height, depth, mip_levels, usage, format, pool,
1201 filter, mip_filter, color_key, info, palette, volume_texture);
1203 if (!device || !data || !data_size || !volume_texture)
1204 return D3DERR_INVALIDCALL;
1206 hr = D3DXGetImageInfoFromFileInMemory(data, data_size, &image_info);
1207 if (FAILED(hr)) return hr;
1209 if (image_info.ImageFileFormat != D3DXIFF_DDS)
1210 return D3DXERR_INVALIDDATA;
1212 if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
1213 width = image_info.Width;
1214 if (width == D3DX_DEFAULT)
1215 width = make_pow2(image_info.Width);
1217 if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
1218 height = image_info.Height;
1219 if (height == D3DX_DEFAULT)
1220 height = make_pow2(image_info.Height);
1222 if (depth == 0 || depth == D3DX_DEFAULT_NONPOW2)
1223 depth = image_info.Depth;
1224 if (depth == D3DX_DEFAULT)
1225 depth = make_pow2(image_info.Depth);
1227 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1228 format = image_info.Format;
1230 if (width == D3DX_FROM_FILE)
1232 file_width = TRUE;
1233 width = image_info.Width;
1236 if (height == D3DX_FROM_FILE)
1238 file_height = TRUE;
1239 height = image_info.Height;
1242 if (depth == D3DX_FROM_FILE)
1244 file_depth = TRUE;
1245 depth = image_info.Depth;
1248 if (format == D3DFMT_FROM_FILE)
1250 file_format = TRUE;
1251 format = image_info.Format;
1254 if (mip_levels == D3DX_FROM_FILE)
1256 file_mip_levels = TRUE;
1257 mip_levels = image_info.MipLevels;
1260 hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mip_levels, usage, &format, pool);
1261 if (FAILED(hr)) return hr;
1263 if ((file_width && width != image_info.Width)
1264 || (file_height && height != image_info.Height)
1265 || (file_depth && depth != image_info.Depth)
1266 || (file_format && format != image_info.Format)
1267 || (file_mip_levels && mip_levels != image_info.MipLevels))
1268 return D3DERR_NOTAVAILABLE;
1270 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1271 if (FAILED(hr))
1272 return D3DERR_INVALIDCALL;
1274 if (mip_levels > image_info.MipLevels)
1276 FIXME("Generation of mipmaps for volume textures is not implemented yet\n");
1277 mip_levels = image_info.MipLevels;
1280 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1281 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1283 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1284 tex = buftex;
1286 else
1288 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1289 buftex = NULL;
1292 if (FAILED(hr)) return hr;
1294 hr = load_volume_texture_from_dds(tex, data, palette, filter, color_key, &image_info);
1295 if (FAILED(hr))
1297 IDirect3DVolumeTexture9_Release(tex);
1298 return hr;
1301 if (buftex)
1303 hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1304 if (FAILED(hr))
1306 IDirect3DVolumeTexture9_Release(buftex);
1307 return hr;
1310 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1311 IDirect3DVolumeTexture9_Release(buftex);
1314 if (info)
1315 *info = image_info;
1317 *volume_texture = tex;
1318 return D3D_OK;
1321 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
1322 LPD3DXFILL2D function,
1323 LPVOID funcdata)
1325 DWORD miplevels;
1326 DWORD m, i, x, y, c, v;
1327 D3DSURFACE_DESC desc;
1328 D3DLOCKED_RECT lock_rect;
1329 D3DXVECTOR4 value;
1330 D3DXVECTOR2 coord, size;
1331 const PixelFormatDesc *format;
1332 BYTE *data, *pos;
1333 BYTE byte, mask;
1334 float comp_value;
1336 if (texture == NULL || function == NULL)
1337 return D3DERR_INVALIDCALL;
1339 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1341 for (m = 0; m < miplevels; m++)
1343 if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1344 return D3DERR_INVALIDCALL;
1346 format = get_format_info(desc.Format);
1347 if (format->format == D3DFMT_UNKNOWN)
1349 FIXME("Unsupported texture format %#x\n", desc.Format);
1350 return D3DERR_INVALIDCALL;
1353 if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1354 return D3DERR_INVALIDCALL;
1356 size.x = 1.0f / desc.Width;
1357 size.y = 1.0f / desc.Height;
1359 data = lock_rect.pBits;
1361 for (y = 0; y < desc.Height; y++)
1363 /* The callback function expects the coordinates of the center
1364 of the texel */
1365 coord.y = (y + 0.5f) / desc.Height;
1367 for (x = 0; x < desc.Width; x++)
1369 coord.x = (x + 0.5f) / desc.Width;
1371 function(&value, &coord, &size, funcdata);
1373 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1375 for (i = 0; i < format->bytes_per_pixel; i++)
1376 pos[i] = 0;
1378 for (c = 0; c < 4; c++)
1380 switch (c)
1382 case 0: /* Alpha */
1383 comp_value = value.w;
1384 break;
1385 case 1: /* Red */
1386 comp_value = value.x;
1387 break;
1388 case 2: /* Green */
1389 comp_value = value.y;
1390 break;
1391 case 3: /* Blue */
1392 comp_value = value.z;
1393 break;
1396 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1398 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1400 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1401 byte = (v << format->shift[c] >> i) & mask;
1402 pos[i / 8] |= byte;
1407 IDirect3DTexture9_UnlockRect(texture, m);
1410 return D3D_OK;
1413 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1414 const void *src_data,
1415 UINT src_data_size,
1416 UINT size,
1417 UINT mip_levels,
1418 DWORD usage,
1419 D3DFORMAT format,
1420 D3DPOOL pool,
1421 DWORD filter,
1422 DWORD mip_filter,
1423 D3DCOLOR color_key,
1424 D3DXIMAGE_INFO *src_info,
1425 PALETTEENTRY *palette,
1426 IDirect3DCubeTexture9 **cube_texture)
1428 HRESULT hr;
1429 D3DCAPS9 caps;
1430 UINT loaded_miplevels;
1431 D3DXIMAGE_INFO img_info;
1432 BOOL dynamic_texture;
1433 BOOL file_size = FALSE;
1434 BOOL file_format = FALSE;
1435 BOOL file_mip_levels = FALSE;
1436 IDirect3DCubeTexture9 *tex, *buftex;
1438 TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
1439 src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
1440 color_key, src_info, palette, cube_texture);
1442 if (!device || !cube_texture || !src_data || !src_data_size)
1443 return D3DERR_INVALIDCALL;
1445 hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
1446 if (FAILED(hr))
1447 return hr;
1449 if (img_info.ImageFileFormat != D3DXIFF_DDS)
1450 return D3DXERR_INVALIDDATA;
1452 if (img_info.Width != img_info.Height)
1453 return D3DXERR_INVALIDDATA;
1455 if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
1456 size = img_info.Width;
1457 if (size == D3DX_DEFAULT)
1458 size = make_pow2(img_info.Width);
1460 if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1461 format = img_info.Format;
1463 if (size == D3DX_FROM_FILE)
1465 file_size = TRUE;
1466 size = img_info.Width;
1469 if (format == D3DFMT_FROM_FILE)
1471 file_format = TRUE;
1472 format = img_info.Format;
1475 if (mip_levels == D3DX_FROM_FILE)
1477 file_mip_levels = TRUE;
1478 mip_levels = img_info.MipLevels;
1481 hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
1482 if (FAILED(hr))
1483 return hr;
1485 if ((file_size && size != img_info.Width)
1486 || (file_format && format != img_info.Format)
1487 || (file_mip_levels && mip_levels != img_info.MipLevels))
1488 return D3DERR_NOTAVAILABLE;
1490 hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1491 if (FAILED(hr))
1492 return D3DERR_INVALIDCALL;
1494 if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
1496 FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
1497 mip_levels = img_info.MipLevels;
1500 dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1501 if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1503 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1504 tex = buftex;
1506 else
1508 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1509 buftex = NULL;
1511 if (FAILED(hr))
1512 return hr;
1514 hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info);
1515 if (FAILED(hr))
1517 IDirect3DCubeTexture9_Release(tex);
1518 return hr;
1521 loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels);
1522 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
1523 if (FAILED(hr))
1525 IDirect3DCubeTexture9_Release(tex);
1526 return hr;
1529 if (buftex)
1531 hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1532 if (FAILED(hr))
1534 IDirect3DCubeTexture9_Release(buftex);
1535 return hr;
1538 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1539 IDirect3DCubeTexture9_Release(buftex);
1542 if (src_info)
1543 *src_info = img_info;
1545 *cube_texture = tex;
1546 return D3D_OK;
1550 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1551 const char *src_filename,
1552 IDirect3DCubeTexture9 **cube_texture)
1554 int len;
1555 HRESULT hr;
1556 WCHAR *filename;
1557 void *data;
1558 DWORD data_size;
1560 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1562 if (!src_filename) return D3DERR_INVALIDCALL;
1564 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1565 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1566 if (!filename) return E_OUTOFMEMORY;
1567 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1569 hr = map_view_of_file(filename, &data, &data_size);
1570 if (FAILED(hr))
1572 HeapFree(GetProcessHeap(), 0, filename);
1573 return D3DXERR_INVALIDDATA;
1576 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1577 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1579 UnmapViewOfFile(data);
1580 HeapFree(GetProcessHeap(), 0, filename);
1581 return hr;
1584 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1585 const WCHAR *src_filename,
1586 IDirect3DCubeTexture9 **cube_texture)
1588 HRESULT hr;
1589 void *data;
1590 DWORD data_size;
1592 TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1594 hr = map_view_of_file(src_filename, &data, &data_size);
1595 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1597 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1598 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1600 UnmapViewOfFile(data);
1601 return hr;
1604 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1605 const char *src_filename,
1606 UINT size,
1607 UINT mip_levels,
1608 DWORD usage,
1609 D3DFORMAT format,
1610 D3DPOOL pool,
1611 DWORD filter,
1612 DWORD mip_filter,
1613 D3DCOLOR color_key,
1614 D3DXIMAGE_INFO *image_info,
1615 PALETTEENTRY *palette,
1616 IDirect3DCubeTexture9 **cube_texture)
1618 int len;
1619 HRESULT hr;
1620 WCHAR *filename;
1621 void *data;
1622 DWORD data_size;
1624 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1625 device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1626 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1628 if (!src_filename) return D3DERR_INVALIDCALL;
1630 len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1631 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1632 if (!filename) return E_OUTOFMEMORY;
1633 MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1635 hr = map_view_of_file(filename, &data, &data_size);
1636 if (FAILED(hr))
1638 HeapFree(GetProcessHeap(), 0, filename);
1639 return D3DXERR_INVALIDDATA;
1642 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1643 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1645 UnmapViewOfFile(data);
1646 HeapFree(GetProcessHeap(), 0, filename);
1647 return hr;
1650 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1651 const WCHAR *src_filename,
1652 UINT size,
1653 UINT mip_levels,
1654 DWORD usage,
1655 D3DFORMAT format,
1656 D3DPOOL pool,
1657 DWORD filter,
1658 DWORD mip_filter,
1659 D3DCOLOR color_key,
1660 D3DXIMAGE_INFO *image_info,
1661 PALETTEENTRY *palette,
1662 IDirect3DCubeTexture9 **cube_texture)
1664 HRESULT hr;
1665 void *data;
1666 DWORD data_size;
1668 TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1669 device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1670 pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1672 hr = map_view_of_file(src_filename, &data, &data_size);
1673 if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1675 hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1676 usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1678 UnmapViewOfFile(data);
1679 return hr;
1682 enum cube_coord
1684 XCOORD = 0,
1685 XCOORDINV = 1,
1686 YCOORD = 2,
1687 YCOORDINV = 3,
1688 ZERO = 4,
1689 ONE = 5
1692 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1694 switch (coord)
1696 case XCOORD:
1697 return x + 0.5f;
1698 case XCOORDINV:
1699 return size - x - 0.5f;
1700 case YCOORD:
1701 return y + 0.5f;
1702 case YCOORDINV:
1703 return size - y - 0.5f;
1704 case ZERO:
1705 return 0.0f;
1706 case ONE:
1707 return size;
1708 default:
1709 ERR("Unexpected coordinate value\n");
1710 return 0.0f;
1714 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1715 LPD3DXFILL3D function,
1716 LPVOID funcdata)
1718 DWORD miplevels;
1719 DWORD m, i, x, y, c, f, v;
1720 D3DSURFACE_DESC desc;
1721 D3DLOCKED_RECT lock_rect;
1722 D3DXVECTOR4 value;
1723 D3DXVECTOR3 coord, size;
1724 const PixelFormatDesc *format;
1725 BYTE *data, *pos;
1726 BYTE byte, mask;
1727 float comp_value;
1728 static const enum cube_coord coordmap[6][3] =
1730 {ONE, YCOORDINV, XCOORDINV},
1731 {ZERO, YCOORDINV, XCOORD},
1732 {XCOORD, ONE, YCOORD},
1733 {XCOORD, ZERO, YCOORDINV},
1734 {XCOORD, YCOORDINV, ONE},
1735 {XCOORDINV, YCOORDINV, ZERO}
1738 if (texture == NULL || function == NULL)
1739 return D3DERR_INVALIDCALL;
1741 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1743 for (m = 0; m < miplevels; m++)
1745 if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1746 return D3DERR_INVALIDCALL;
1748 format = get_format_info(desc.Format);
1749 if (format->format == D3DFMT_UNKNOWN)
1751 FIXME("Unsupported texture format %#x\n", desc.Format);
1752 return D3DERR_INVALIDCALL;
1755 for (f = 0; f < 6; f++)
1757 if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1758 return D3DERR_INVALIDCALL;
1760 size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1761 size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1762 size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1764 data = lock_rect.pBits;
1766 for (y = 0; y < desc.Height; y++)
1768 for (x = 0; x < desc.Width; x++)
1770 coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1771 coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1772 coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1774 function(&value, &coord, &size, funcdata);
1776 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1778 for (i = 0; i < format->bytes_per_pixel; i++)
1779 pos[i] = 0;
1781 for (c = 0; c < 4; c++)
1783 switch (c)
1785 case 0: /* Alpha */
1786 comp_value = value.w;
1787 break;
1788 case 1: /* Red */
1789 comp_value = value.x;
1790 break;
1791 case 2: /* Green */
1792 comp_value = value.y;
1793 break;
1794 case 3: /* Blue */
1795 comp_value = value.z;
1796 break;
1799 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1801 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1803 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1804 byte = (v << format->shift[c] >> i) & mask;
1805 pos[i / 8] |= byte;
1810 IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1814 return D3D_OK;
1817 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1818 LPD3DXFILL3D function,
1819 LPVOID funcdata)
1821 DWORD miplevels;
1822 DWORD m, i, x, y, z, c, v;
1823 D3DVOLUME_DESC desc;
1824 D3DLOCKED_BOX lock_box;
1825 D3DXVECTOR4 value;
1826 D3DXVECTOR3 coord, size;
1827 const PixelFormatDesc *format;
1828 BYTE *data, *pos;
1829 BYTE byte, mask;
1830 float comp_value;
1832 if (texture == NULL || function == NULL)
1833 return D3DERR_INVALIDCALL;
1835 miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1837 for (m = 0; m < miplevels; m++)
1839 if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1840 return D3DERR_INVALIDCALL;
1842 format = get_format_info(desc.Format);
1843 if (format->format == D3DFMT_UNKNOWN)
1845 FIXME("Unsupported texture format %#x\n", desc.Format);
1846 return D3DERR_INVALIDCALL;
1849 if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1850 return D3DERR_INVALIDCALL;
1852 size.x = 1.0f / desc.Width;
1853 size.y = 1.0f / desc.Height;
1854 size.z = 1.0f / desc.Depth;
1856 data = lock_box.pBits;
1858 for (z = 0; z < desc.Depth; z++)
1860 /* The callback function expects the coordinates of the center
1861 of the texel */
1862 coord.z = (z + 0.5f) / desc.Depth;
1864 for (y = 0; y < desc.Height; y++)
1866 coord.y = (y + 0.5f) / desc.Height;
1868 for (x = 0; x < desc.Width; x++)
1870 coord.x = (x + 0.5f) / desc.Width;
1872 function(&value, &coord, &size, funcdata);
1874 pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1876 for (i = 0; i < format->bytes_per_pixel; i++)
1877 pos[i] = 0;
1879 for (c = 0; c < 4; c++)
1881 switch (c)
1883 case 0: /* Alpha */
1884 comp_value = value.w;
1885 break;
1886 case 1: /* Red */
1887 comp_value = value.x;
1888 break;
1889 case 2: /* Green */
1890 comp_value = value.y;
1891 break;
1892 case 3: /* Blue */
1893 comp_value = value.z;
1894 break;
1897 v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1899 for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1901 mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1902 byte = (v << format->shift[c] >> i) & mask;
1903 pos[i / 8] |= byte;
1909 IDirect3DVolumeTexture9_UnlockBox(texture, m);
1912 return D3D_OK;
1915 HRESULT WINAPI D3DXSaveTextureToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1916 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1918 int len;
1919 WCHAR *filename;
1920 HRESULT hr;
1921 ID3DXBuffer *buffer;
1923 TRACE("(%s, %#x, %p, %p): relay\n",
1924 wine_dbgstr_a(dst_filename), file_format, src_texture, src_palette);
1926 if (!dst_filename) return D3DERR_INVALIDCALL;
1928 len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
1929 filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1930 if (!filename) return E_OUTOFMEMORY;
1931 MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
1933 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1934 if (SUCCEEDED(hr))
1936 hr = write_buffer_to_file(filename, buffer);
1937 ID3DXBuffer_Release(buffer);
1940 HeapFree(GetProcessHeap(), 0, filename);
1941 return hr;
1944 HRESULT WINAPI D3DXSaveTextureToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1945 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1947 HRESULT hr;
1948 ID3DXBuffer *buffer;
1950 TRACE("(%s, %#x, %p, %p): relay\n",
1951 wine_dbgstr_w(dst_filename), file_format, src_texture, src_palette);
1953 if (!dst_filename) return D3DERR_INVALIDCALL;
1955 hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1956 if (SUCCEEDED(hr))
1958 hr = write_buffer_to_file(dst_filename, buffer);
1959 ID3DXBuffer_Release(buffer);
1962 return hr;
1965 HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format,
1966 IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1968 HRESULT hr;
1969 D3DRESOURCETYPE type;
1970 IDirect3DSurface9 *surface;
1972 TRACE("(%p, %#x, %p, %p)\n",
1973 dst_buffer, file_format, src_texture, src_palette);
1975 if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
1977 if (file_format == D3DXIFF_DDS)
1979 FIXME("DDS file format isn't supported yet\n");
1980 return E_NOTIMPL;
1983 type = IDirect3DBaseTexture9_GetType(src_texture);
1984 switch (type)
1986 case D3DRTYPE_TEXTURE:
1987 case D3DRTYPE_CUBETEXTURE:
1988 hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
1989 break;
1990 case D3DRTYPE_VOLUMETEXTURE:
1991 FIXME("Volume textures aren't supported yet\n");
1992 return E_NOTIMPL;
1993 default:
1994 return D3DERR_INVALIDCALL;
1997 if (SUCCEEDED(hr))
1999 hr = D3DXSaveSurfaceToFileInMemory(dst_buffer, file_format, surface, src_palette, NULL);
2000 IDirect3DSurface9_Release(surface);
2003 return hr;