d3dx9: Avoid LPD3DXEFFECTSTATEMANAGER.
[wine] / dlls / d3dx9_36 / texture.c
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
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "wine/unicode.h"
23 #include "wine/debug.h"
24 #include "d3dx9_36_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
27
28 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
29 static BOOL is_pow2(UINT num)
30 {
31     return !(num & (num - 1));
32 }
33
34 /* Returns the smallest power of 2 which is greater than or equal to num */
35 static UINT make_pow2(UINT num)
36 {
37     UINT result = 1;
38
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;
42
43     while (result < num)
44         result <<= 1;
45
46     return result;
47 }
48
49 static HRESULT get_surface(D3DRESOURCETYPE type, struct IDirect3DBaseTexture9 *tex,
50         int face, UINT level, struct IDirect3DSurface9 **surf)
51 {
52     switch (type)
53     {
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;
61     }
62 }
63
64 HRESULT WINAPI D3DXFilterTexture(IDirect3DBaseTexture9 *texture,
65                                  const PALETTEENTRY *palette,
66                                  UINT srclevel,
67                                  DWORD filter)
68 {
69     UINT level;
70     HRESULT hr;
71     D3DRESOURCETYPE type;
72
73     TRACE("(%p, %p, %u, %#x)\n", texture, palette, srclevel, filter);
74
75     if (!texture)
76         return D3DERR_INVALIDCALL;
77
78     if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT)
79         return D3DERR_INVALIDCALL;
80
81     if (srclevel == D3DX_DEFAULT)
82         srclevel = 0;
83     else if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
84         return D3DERR_INVALIDCALL;
85
86     switch (type = IDirect3DBaseTexture9_GetType(texture))
87     {
88         case D3DRTYPE_TEXTURE:
89         case D3DRTYPE_CUBETEXTURE:
90         {
91             IDirect3DSurface9 *topsurf, *mipsurf;
92             D3DSURFACE_DESC desc;
93             int i, numfaces;
94
95             if (type == D3DRTYPE_TEXTURE)
96             {
97                 numfaces = 1;
98                 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
99             }
100             else
101             {
102                 numfaces = 6;
103                 IDirect3DCubeTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
104             }
105
106             if (filter == D3DX_DEFAULT)
107             {
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;
112             }
113
114             for (i = 0; i < numfaces; i++)
115             {
116                 level = srclevel + 1;
117                 hr = get_surface(type, texture, i, srclevel, &topsurf);
118
119                 if (FAILED(hr))
120                     return D3DERR_INVALIDCALL;
121
122                 while (get_surface(type, texture, i, level, &mipsurf) == D3D_OK)
123                 {
124                     hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
125                     IDirect3DSurface9_Release(topsurf);
126                     topsurf = mipsurf;
127
128                     if (FAILED(hr))
129                         break;
130
131                     level++;
132                 }
133
134                 IDirect3DSurface9_Release(topsurf);
135                 if (FAILED(hr))
136                     return hr;
137             }
138
139             return D3D_OK;
140         }
141
142         case D3DRTYPE_VOLUMETEXTURE:
143         {
144             D3DVOLUME_DESC desc;
145             int level, level_count;
146             IDirect3DVolume9 *top_volume, *mip_volume;
147             IDirect3DVolumeTexture9 *volume_texture = (IDirect3DVolumeTexture9*) texture;
148
149             IDirect3DVolumeTexture9_GetLevelDesc(volume_texture, srclevel, &desc);
150
151             if (filter == D3DX_DEFAULT)
152             {
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;
157             }
158
159             hr = IDirect3DVolumeTexture9_GetVolumeLevel(volume_texture, srclevel, &top_volume);
160             if (FAILED(hr))
161                 return hr;
162
163             level_count = IDirect3DVolumeTexture9_GetLevelCount(volume_texture);
164             for (level = srclevel + 1; level < level_count; level++)
165             {
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;
170
171                 if (FAILED(hr))
172                     break;
173             }
174
175             IDirect3DVolume9_Release(top_volume);
176             if (FAILED(hr))
177                 return hr;
178
179             return D3D_OK;
180         }
181
182         default:
183             return D3DERR_INVALIDCALL;
184     }
185 }
186
187 HRESULT WINAPI D3DXCheckTextureRequirements(struct IDirect3DDevice9 *device, UINT *width, UINT *height,
188         UINT *miplevels, DWORD usage, D3DFORMAT *format, D3DPOOL pool)
189 {
190     UINT w = (width && *width) ? *width : 1;
191     UINT h = (height && *height) ? *height : 1;
192     D3DCAPS9 caps;
193     D3DDEVICE_CREATION_PARAMETERS params;
194     IDirect3D9 *d3d = NULL;
195     D3DDISPLAYMODE mode;
196     HRESULT hr;
197     D3DFORMAT usedformat = D3DFMT_UNKNOWN;
198
199     TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
200
201     if (!device)
202         return D3DERR_INVALIDCALL;
203
204     /* usage */
205     if (usage == D3DX_DEFAULT)
206         usage = 0;
207     if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
208         return D3DERR_INVALIDCALL;
209
210     /* pool */
211     if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
212         return D3DERR_INVALIDCALL;
213
214     /* width and height */
215     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
216         return D3DERR_INVALIDCALL;
217
218     /* 256 x 256 default width/height */
219     if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
220         w = h = 256;
221     else if (w == D3DX_DEFAULT)
222         w = (height ? h : 256);
223     else if (h == D3DX_DEFAULT)
224         h = (width ? w : 256);
225
226     /* ensure width/height is power of 2 */
227     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
228         w = make_pow2(w);
229
230     if (w > caps.MaxTextureWidth)
231         w = caps.MaxTextureWidth;
232
233     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
234         h = make_pow2(h);
235
236     if (h > caps.MaxTextureHeight)
237         h = caps.MaxTextureHeight;
238
239     /* texture must be square? */
240     if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
241     {
242         if (w > h)
243             h = w;
244         else
245             w = h;
246     }
247
248     if (width)
249         *width = w;
250
251     if (height)
252         *height = h;
253
254     /* miplevels */
255     if (miplevels && (usage & D3DUSAGE_AUTOGENMIPMAP))
256     {
257         if (*miplevels > 1)
258             *miplevels = 0;
259     }
260     else if (miplevels)
261     {
262         UINT max_mipmaps = 1;
263
264         if (!width && !height)
265             max_mipmaps = 9;    /* number of mipmaps in a 256x256 texture */
266         else
267         {
268             UINT max_dimen = max(w, h);
269
270             while (max_dimen > 1)
271             {
272                 max_dimen >>= 1;
273                 max_mipmaps++;
274             }
275         }
276
277         if (*miplevels == 0 || *miplevels > max_mipmaps)
278             *miplevels = max_mipmaps;
279     }
280
281     /* format */
282     if (format)
283     {
284         TRACE("Requested format %x\n", *format);
285         usedformat = *format;
286     }
287
288     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
289
290     if (FAILED(hr))
291         goto cleanup;
292
293     hr = IDirect3DDevice9_GetCreationParameters(device, &params);
294
295     if (FAILED(hr))
296         goto cleanup;
297
298     hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
299
300     if (FAILED(hr))
301         goto cleanup;
302
303     if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
304         usedformat = D3DFMT_A8R8G8B8;
305
306     hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
307         usage, D3DRTYPE_TEXTURE, usedformat);
308
309     if (FAILED(hr))
310     {
311         /* Heuristic to choose the fallback format */
312         const struct pixel_format_desc *fmt = get_format_info(usedformat);
313         BOOL allow_24bits;
314         int bestscore = INT_MIN, i = 0, j;
315         unsigned int channels;
316         const struct pixel_format_desc *curfmt;
317
318         if (!fmt)
319         {
320             FIXME("Pixel format %x not handled\n", usedformat);
321             goto cleanup;
322         }
323
324         allow_24bits = fmt->bytes_per_pixel == 3;
325         channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
326             + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
327         usedformat = D3DFMT_UNKNOWN;
328
329         while ((curfmt = get_format_info_idx(i)))
330         {
331             unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
332                 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
333             int score;
334
335             i++;
336
337             if (curchannels < channels)
338                 continue;
339             if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
340                 continue;
341
342             hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
343                 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
344             if (FAILED(hr))
345                 continue;
346
347             /* This format can be used, let's evaluate it.
348                Weights chosen quite arbitrarily... */
349             score = 16 - 4 * (curchannels - channels);
350
351             for (j = 0; j < 4; j++)
352             {
353                 int diff = curfmt->bits[j] - fmt->bits[j];
354                 score += 16 - (diff < 0 ? -diff * 4 : diff);
355             }
356
357             if (score > bestscore)
358             {
359                 bestscore = score;
360                 usedformat = curfmt->format;
361             }
362         }
363         hr = D3D_OK;
364     }
365
366 cleanup:
367
368     if (d3d)
369         IDirect3D9_Release(d3d);
370
371     if (FAILED(hr))
372         return hr;
373
374     if (usedformat == D3DFMT_UNKNOWN)
375     {
376         WARN("Couldn't find a suitable pixel format\n");
377         return D3DERR_NOTAVAILABLE;
378     }
379
380     TRACE("Format chosen: %x\n", usedformat);
381     if (format)
382         *format = usedformat;
383
384     return D3D_OK;
385 }
386
387 HRESULT WINAPI D3DXCheckCubeTextureRequirements(struct IDirect3DDevice9 *device, UINT *size,
388         UINT *miplevels, DWORD usage, D3DFORMAT *format, D3DPOOL pool)
389 {
390     D3DCAPS9 caps;
391     UINT s = (size && *size) ? *size : 256;
392     HRESULT hr;
393
394     TRACE("(%p, %p, %p, %u, %p, %u)\n", device, size, miplevels, usage, format, pool);
395
396     if (s == D3DX_DEFAULT)
397         s = 256;
398
399     if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
400         return D3DERR_INVALIDCALL;
401
402     if (!(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP))
403         return D3DERR_NOTAVAILABLE;
404
405     /* ensure width/height is power of 2 */
406     if ((caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && (!is_pow2(s)))
407         s = make_pow2(s);
408
409     hr = D3DXCheckTextureRequirements(device, &s, &s, miplevels, usage, format, pool);
410
411     if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
412     {
413         if(miplevels)
414             *miplevels = 1;
415     }
416
417     if (size)
418         *size = s;
419
420     return hr;
421 }
422
423 HRESULT WINAPI D3DXCheckVolumeTextureRequirements(struct IDirect3DDevice9 *device, UINT *width, UINT *height,
424         UINT *depth, UINT *miplevels, DWORD usage, D3DFORMAT *format, D3DPOOL pool)
425 {
426     D3DCAPS9 caps;
427     UINT w = width ? *width : D3DX_DEFAULT;
428     UINT h = height ? *height : D3DX_DEFAULT;
429     UINT d = (depth && *depth) ? *depth : 1;
430     HRESULT hr;
431
432     TRACE("(%p, %p, %p, %p, %p, %u, %p, %u)\n", device, width, height, depth, miplevels,
433           usage, format, pool);
434
435     if (!device || FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
436         return D3DERR_INVALIDCALL;
437
438     if (!(caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP))
439         return D3DERR_NOTAVAILABLE;
440
441     hr = D3DXCheckTextureRequirements(device, &w, &h, NULL, usage, format, pool);
442     if (d == D3DX_DEFAULT)
443         d = 1;
444
445     /* ensure width/height is power of 2 */
446     if ((caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2) &&
447         (!is_pow2(w) || !is_pow2(h) || !is_pow2(d)))
448     {
449         w = make_pow2(w);
450         h = make_pow2(h);
451         d = make_pow2(d);
452     }
453
454     if (w > caps.MaxVolumeExtent)
455         w = caps.MaxVolumeExtent;
456     if (h > caps.MaxVolumeExtent)
457         h = caps.MaxVolumeExtent;
458     if (d > caps.MaxVolumeExtent)
459         d = caps.MaxVolumeExtent;
460
461     if (miplevels)
462     {
463         if (!(caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
464             *miplevels = 1;
465         else if ((usage & D3DUSAGE_AUTOGENMIPMAP))
466         {
467             if (*miplevels > 1)
468                 *miplevels = 0;
469         }
470         else
471         {
472             UINT max_mipmaps = 1;
473             UINT max_dimen = max(max(w, h), d);
474
475             while (max_dimen > 1)
476             {
477                 max_dimen >>= 1;
478                 max_mipmaps++;
479             }
480
481             if (*miplevels == 0 || *miplevels > max_mipmaps)
482                 *miplevels = max_mipmaps;
483         }
484     }
485
486     if (width)
487         *width = w;
488     if (height)
489         *height = h;
490     if (depth)
491         *depth = d;
492
493     return hr;
494 }
495
496 HRESULT WINAPI D3DXCreateTexture(struct IDirect3DDevice9 *device, UINT width, UINT height,
497         UINT miplevels, DWORD usage, D3DFORMAT format, D3DPOOL pool, struct IDirect3DTexture9 **texture)
498 {
499     HRESULT hr;
500
501     TRACE("device %p, width %u, height %u, miplevels %u, usage %#x, format %#x, pool %#x, texture %p.\n",
502             device, width, height, miplevels, usage, format, pool, texture);
503
504     if (!device || !texture)
505         return D3DERR_INVALIDCALL;
506
507     if (FAILED(hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool)))
508         return hr;
509
510     return IDirect3DDevice9_CreateTexture(device, width, height, miplevels, usage, format, pool, texture, NULL);
511 }
512
513 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(struct IDirect3DDevice9 *device, const void *srcdata,
514         UINT srcdatasize, UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
515         D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
516         PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
517 {
518     IDirect3DTexture9 **texptr;
519     IDirect3DTexture9 *buftex;
520     IDirect3DSurface9 *surface;
521     BOOL file_width = FALSE, file_height = FALSE;
522     BOOL file_format = FALSE, file_miplevels = FALSE;
523     BOOL dynamic_texture;
524     D3DXIMAGE_INFO imginfo;
525     UINT loaded_miplevels;
526     D3DCAPS9 caps;
527     HRESULT hr;
528
529     TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
530         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
531
532     /* check for invalid parameters */
533     if (!device || !texture || !srcdata || !srcdatasize)
534         return D3DERR_INVALIDCALL;
535
536     hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
537
538     if (FAILED(hr))
539     {
540         *texture = NULL;
541         return hr;
542     }
543
544     /* handle default values */
545     if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
546         width = imginfo.Width;
547
548     if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
549         height = imginfo.Height;
550
551     if (width == D3DX_DEFAULT)
552         width = make_pow2(imginfo.Width);
553
554     if (height == D3DX_DEFAULT)
555         height = make_pow2(imginfo.Height);
556
557     if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
558         format = imginfo.Format;
559
560     if (width == D3DX_FROM_FILE)
561     {
562         file_width = TRUE;
563         width = imginfo.Width;
564     }
565
566     if (height == D3DX_FROM_FILE)
567     {
568         file_height = TRUE;
569         height = imginfo.Height;
570     }
571
572     if (format == D3DFMT_FROM_FILE)
573     {
574         file_format = TRUE;
575         format = imginfo.Format;
576     }
577
578     if (miplevels == D3DX_FROM_FILE)
579     {
580         file_miplevels = TRUE;
581         miplevels = imginfo.MipLevels;
582     }
583
584     /* fix texture creation parameters */
585     hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
586
587     if (FAILED(hr))
588     {
589         *texture = NULL;
590         return hr;
591     }
592
593     if (imginfo.MipLevels < miplevels && (D3DFMT_DXT1 <= imginfo.Format && imginfo.Format <= D3DFMT_DXT5))
594     {
595         FIXME("Generation of mipmaps for compressed pixel formats is not implemented yet\n");
596         miplevels = imginfo.MipLevels;
597     }
598
599     if (((file_width) && (width != imginfo.Width))    ||
600         ((file_height) && (height != imginfo.Height)) ||
601         ((file_format) && (format != imginfo.Format)) ||
602         ((file_miplevels) && (miplevels != imginfo.MipLevels)))
603     {
604         return D3DERR_NOTAVAILABLE;
605     }
606
607     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
608         return D3DERR_INVALIDCALL;
609
610     /* Create the to-be-filled texture */
611     dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
612     if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
613     {
614         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
615         texptr = &buftex;
616     }
617     else
618     {
619         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
620         texptr = texture;
621     }
622
623     if (FAILED(hr))
624     {
625         *texture = NULL;
626         return hr;
627     }
628
629     /* Load the file */
630     if (imginfo.ImageFileFormat != D3DXIFF_DDS)
631     {
632         IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
633         hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
634         IDirect3DSurface9_Release(surface);
635     }
636     else
637     {
638         hr = load_texture_from_dds(*texptr, srcdata, palette, filter, colorkey, &imginfo);
639     }
640
641     if (FAILED(hr))
642     {
643         IDirect3DTexture9_Release(*texptr);
644         *texture = NULL;
645         return hr;
646     }
647
648     loaded_miplevels = min(IDirect3DTexture9_GetLevelCount(*texptr), imginfo.MipLevels);
649     hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, loaded_miplevels - 1, mipfilter);
650
651     if (FAILED(hr))
652     {
653         IDirect3DTexture9_Release(*texptr);
654         *texture = NULL;
655         return hr;
656     }
657
658     /* Move the data to the actual texture if necessary */
659     if (texptr == &buftex)
660     {
661         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
662
663         if (FAILED(hr))
664         {
665             IDirect3DTexture9_Release(buftex);
666             *texture = NULL;
667             return hr;
668         }
669
670         IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
671         IDirect3DTexture9_Release(buftex);
672     }
673
674     if (srcinfo)
675         *srcinfo = imginfo;
676
677     return D3D_OK;
678 }
679
680 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(struct IDirect3DDevice9 *device,
681         const void *srcdata, UINT srcdatasize, struct IDirect3DTexture9 **texture)
682 {
683     TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
684
685     return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
686                                                D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
687 }
688
689 HRESULT WINAPI D3DXCreateTextureFromFileExW(struct IDirect3DDevice9 *device, const WCHAR *srcfile,
690         UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
691         D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
692         PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
693 {
694     HRESULT hr;
695     DWORD size;
696     LPVOID buffer;
697
698     TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
699             device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
700             mipfilter, colorkey, srcinfo, palette, texture);
701
702     if (!srcfile)
703         return D3DERR_INVALIDCALL;
704
705     hr = map_view_of_file(srcfile, &buffer, &size);
706     if (FAILED(hr))
707         return D3DXERR_INVALIDDATA;
708
709     hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
710         filter, mipfilter, colorkey, srcinfo, palette, texture);
711
712     UnmapViewOfFile(buffer);
713
714     return hr;
715 }
716
717 HRESULT WINAPI D3DXCreateTextureFromFileExA(struct IDirect3DDevice9 *device, const char *srcfile,
718         UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
719         D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
720         PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
721 {
722     LPWSTR widename;
723     HRESULT hr;
724     DWORD len;
725
726     TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
727             device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
728             mipfilter, colorkey, srcinfo, palette, texture);
729
730     if (!device || !srcfile || !texture)
731         return D3DERR_INVALIDCALL;
732
733     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
734     widename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*widename));
735     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
736
737     hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
738                                       usage, format, pool, filter, mipfilter,
739                                       colorkey, srcinfo, palette, texture);
740
741     HeapFree(GetProcessHeap(), 0, widename);
742     return hr;
743 }
744
745 HRESULT WINAPI D3DXCreateTextureFromFileA(struct IDirect3DDevice9 *device,
746         const char *srcfile, struct IDirect3DTexture9 **texture)
747 {
748     TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
749
750     return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
751                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
752 }
753
754 HRESULT WINAPI D3DXCreateTextureFromFileW(struct IDirect3DDevice9 *device,
755         const WCHAR *srcfile, struct IDirect3DTexture9 **texture)
756 {
757     TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
758
759     return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
760                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
761 }
762
763
764 HRESULT WINAPI D3DXCreateTextureFromResourceA(struct IDirect3DDevice9 *device,
765         HMODULE srcmodule, const char *resource, struct IDirect3DTexture9 **texture)
766 {
767     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
768
769     return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
770                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
771 }
772
773 HRESULT WINAPI D3DXCreateTextureFromResourceW(struct IDirect3DDevice9 *device,
774         HMODULE srcmodule, const WCHAR *resource, struct IDirect3DTexture9 **texture)
775 {
776     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
777
778     return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
779                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
780 }
781
782 HRESULT WINAPI D3DXCreateTextureFromResourceExA(struct IDirect3DDevice9 *device, HMODULE srcmodule,
783         const char *resource, UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
784         D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
785         PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
786 {
787     HRSRC resinfo;
788
789     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
790
791     if (!device || !texture)
792         return D3DERR_INVALIDCALL;
793
794     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
795
796     if (resinfo)
797     {
798         LPVOID buffer;
799         HRESULT hr;
800         DWORD size;
801
802         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
803
804         if (FAILED(hr))
805             return D3DXERR_INVALIDDATA;
806
807         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
808                                                    height, miplevels, usage, format,
809                                                    pool, filter, mipfilter, colorkey,
810                                                    srcinfo, palette, texture);
811     }
812
813     /* Try loading the resource as bitmap data */
814     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
815
816     if (resinfo)
817     {
818         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
819         return E_NOTIMPL;
820     }
821
822     return D3DXERR_INVALIDDATA;
823 }
824
825 HRESULT WINAPI D3DXCreateTextureFromResourceExW(struct IDirect3DDevice9 *device, HMODULE srcmodule,
826         const WCHAR *resource, UINT width, UINT height, UINT miplevels, DWORD usage, D3DFORMAT format,
827         D3DPOOL pool, DWORD filter, DWORD mipfilter, D3DCOLOR colorkey, D3DXIMAGE_INFO *srcinfo,
828         PALETTEENTRY *palette, struct IDirect3DTexture9 **texture)
829 {
830     HRSRC resinfo;
831
832     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
833
834     if (!device || !texture)
835         return D3DERR_INVALIDCALL;
836
837     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
838
839     if (resinfo)
840     {
841         LPVOID buffer;
842         HRESULT hr;
843         DWORD size;
844
845         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
846
847         if (FAILED(hr))
848             return D3DXERR_INVALIDDATA;
849
850         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
851                                                    height, miplevels, usage, format,
852                                                    pool, filter, mipfilter, colorkey,
853                                                    srcinfo, palette, texture);
854     }
855
856     /* Try loading the resource as bitmap data */
857     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
858
859     if (resinfo)
860     {
861         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
862         return E_NOTIMPL;
863     }
864
865     return D3DXERR_INVALIDDATA;
866 }
867
868 HRESULT WINAPI D3DXCreateCubeTexture(struct IDirect3DDevice9 *device, UINT size, UINT miplevels,
869         DWORD usage, D3DFORMAT format, D3DPOOL pool, struct IDirect3DCubeTexture9 **texture)
870 {
871     HRESULT hr;
872
873     TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
874         pool, texture);
875
876     if (!device || !texture)
877         return D3DERR_INVALIDCALL;
878
879     hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
880
881     if (FAILED(hr))
882     {
883         TRACE("D3DXCheckCubeTextureRequirements failed\n");
884         return hr;
885     }
886
887     return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
888 }
889
890 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(struct IDirect3DDevice9 *device,
891         const void *data, UINT datasize, struct IDirect3DCubeTexture9 **texture)
892 {
893     TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
894
895     return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
896         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
897 }
898
899 HRESULT WINAPI D3DXCreateVolumeTexture(struct IDirect3DDevice9 *device, UINT width, UINT height, UINT depth,
900         UINT miplevels, DWORD usage, D3DFORMAT format, D3DPOOL pool, struct IDirect3DVolumeTexture9 **texture)
901 {
902     HRESULT hr;
903
904     TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
905           miplevels, usage, format, pool, texture);
906
907     if (!device || !texture)
908         return D3DERR_INVALIDCALL;
909
910     hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
911                                             &miplevels, usage, &format, pool);
912
913     if (FAILED(hr))
914     {
915         TRACE("D3DXCheckVolumeTextureRequirements failed\n");
916         return hr;
917     }
918
919     return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
920                                                 usage, format, pool, texture, NULL);
921 }
922
923 HRESULT WINAPI D3DXCreateVolumeTextureFromFileA(IDirect3DDevice9 *device,
924                                                 const char *filename,
925                                                 IDirect3DVolumeTexture9 **volume_texture)
926 {
927     int len;
928     HRESULT hr;
929     void *data;
930     DWORD data_size;
931     WCHAR *filenameW;
932
933     TRACE("(%p, %s, %p): relay\n",
934             device, debugstr_a(filename), volume_texture);
935
936     if (!filename) return D3DERR_INVALIDCALL;
937
938     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
939     filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
940     if (!filenameW) return E_OUTOFMEMORY;
941     MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
942
943     hr = map_view_of_file(filenameW, &data, &data_size);
944     HeapFree(GetProcessHeap(), 0, filenameW);
945     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
946
947     hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
948             D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
949
950     UnmapViewOfFile(data);
951     return hr;
952 }
953
954 HRESULT WINAPI D3DXCreateVolumeTextureFromFileW(IDirect3DDevice9 *device,
955                                                 const WCHAR *filename,
956                                                 IDirect3DVolumeTexture9 **volume_texture)
957 {
958     HRESULT hr;
959     void *data;
960     DWORD data_size;
961
962     TRACE("(%p, %s, %p): relay\n",
963             device, debugstr_w(filename), volume_texture);
964
965     if (!filename) return D3DERR_INVALIDCALL;
966
967     hr = map_view_of_file(filename, &data, &data_size);
968     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
969
970     hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
971             D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, volume_texture);
972
973     UnmapViewOfFile(data);
974     return hr;
975 }
976
977 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExA(IDirect3DDevice9 *device,
978                                                   const char *filename,
979                                                   UINT width,
980                                                   UINT height,
981                                                   UINT depth,
982                                                   UINT mip_levels,
983                                                   DWORD usage,
984                                                   D3DFORMAT format,
985                                                   D3DPOOL pool,
986                                                   DWORD filter,
987                                                   DWORD mip_filter,
988                                                   D3DCOLOR color_key,
989                                                   D3DXIMAGE_INFO *src_info,
990                                                   PALETTEENTRY *palette,
991                                                   IDirect3DVolumeTexture9 **volume_texture)
992 {
993     int len;
994     HRESULT hr;
995     WCHAR *filenameW;
996     void *data;
997     DWORD data_size;
998
999     TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1000             device, debugstr_a(filename), width, height, depth, mip_levels,
1001             usage, format, pool, filter, mip_filter, color_key, src_info,
1002             palette, volume_texture);
1003
1004     if (!filename) return D3DERR_INVALIDCALL;
1005
1006     len = MultiByteToWideChar(CP_ACP, 0, filename, -1, NULL, 0);
1007     filenameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1008     if (!filenameW) return E_OUTOFMEMORY;
1009     MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, len);
1010
1011     hr = map_view_of_file(filenameW, &data, &data_size);
1012     HeapFree(GetProcessHeap(), 0, filenameW);
1013     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1014
1015     hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1016             mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1017             volume_texture);
1018
1019     UnmapViewOfFile(data);
1020     return hr;
1021 }
1022
1023 HRESULT WINAPI D3DXCreateVolumeTextureFromFileExW(IDirect3DDevice9 *device,
1024                                                   const WCHAR *filename,
1025                                                   UINT width,
1026                                                   UINT height,
1027                                                   UINT depth,
1028                                                   UINT mip_levels,
1029                                                   DWORD usage,
1030                                                   D3DFORMAT format,
1031                                                   D3DPOOL pool,
1032                                                   DWORD filter,
1033                                                   DWORD mip_filter,
1034                                                   D3DCOLOR color_key,
1035                                                   D3DXIMAGE_INFO *src_info,
1036                                                   PALETTEENTRY *palette,
1037                                                   IDirect3DVolumeTexture9 **volume_texture)
1038 {
1039     HRESULT hr;
1040     void *data;
1041     DWORD data_size;
1042
1043     TRACE("(%p, %s, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1044             device, debugstr_w(filename), width, height, depth, mip_levels,
1045             usage, format, pool, filter, mip_filter, color_key, src_info,
1046             palette, volume_texture);
1047
1048     if (!filename) return D3DERR_INVALIDCALL;
1049
1050     hr = map_view_of_file(filename, &data, &data_size);
1051     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1052
1053     hr = D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, width, height, depth,
1054             mip_levels, usage, format, pool, filter, mip_filter, color_key, src_info, palette,
1055             volume_texture);
1056
1057     UnmapViewOfFile(data);
1058     return hr;
1059 }
1060
1061 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(IDirect3DDevice9 *device,
1062                                                        const void *data,
1063                                                        UINT data_size,
1064                                                        IDirect3DVolumeTexture9 **volume_texture)
1065 {
1066     TRACE("(%p, %p, %u, %p): relay\n", device, data, data_size, volume_texture);
1067
1068     return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1069         D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
1070         0, NULL, NULL, volume_texture);
1071 }
1072
1073 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1074                                                          const void *data,
1075                                                          UINT data_size,
1076                                                          UINT width,
1077                                                          UINT height,
1078                                                          UINT depth,
1079                                                          UINT mip_levels,
1080                                                          DWORD usage,
1081                                                          D3DFORMAT format,
1082                                                          D3DPOOL pool,
1083                                                          DWORD filter,
1084                                                          DWORD mip_filter,
1085                                                          D3DCOLOR color_key,
1086                                                          D3DXIMAGE_INFO *info,
1087                                                          PALETTEENTRY *palette,
1088                                                          IDirect3DVolumeTexture9 **volume_texture)
1089 {
1090     HRESULT hr;
1091     D3DCAPS9 caps;
1092     D3DXIMAGE_INFO image_info;
1093     BOOL dynamic_texture;
1094     BOOL file_width = FALSE;
1095     BOOL file_height = FALSE;
1096     BOOL file_depth = FALSE;
1097     BOOL file_format = FALSE;
1098     BOOL file_mip_levels = FALSE;
1099     IDirect3DVolumeTexture9 *tex, *buftex;
1100
1101     TRACE("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n",
1102             device, data, data_size, width, height, depth, mip_levels, usage, format, pool,
1103             filter, mip_filter, color_key, info, palette, volume_texture);
1104
1105     if (!device || !data || !data_size || !volume_texture)
1106         return D3DERR_INVALIDCALL;
1107
1108     hr = D3DXGetImageInfoFromFileInMemory(data, data_size, &image_info);
1109     if (FAILED(hr)) return hr;
1110
1111     if (image_info.ImageFileFormat != D3DXIFF_DDS)
1112         return D3DXERR_INVALIDDATA;
1113
1114     if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
1115         width = image_info.Width;
1116     if (width == D3DX_DEFAULT)
1117         width = make_pow2(image_info.Width);
1118
1119     if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
1120         height = image_info.Height;
1121     if (height == D3DX_DEFAULT)
1122         height = make_pow2(image_info.Height);
1123
1124     if (depth == 0 || depth == D3DX_DEFAULT_NONPOW2)
1125         depth = image_info.Depth;
1126     if (depth == D3DX_DEFAULT)
1127         depth = make_pow2(image_info.Depth);
1128
1129     if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1130         format = image_info.Format;
1131
1132     if (width == D3DX_FROM_FILE)
1133     {
1134         file_width = TRUE;
1135         width = image_info.Width;
1136     }
1137
1138     if (height == D3DX_FROM_FILE)
1139     {
1140         file_height = TRUE;
1141         height = image_info.Height;
1142     }
1143
1144     if (depth == D3DX_FROM_FILE)
1145     {
1146         file_depth = TRUE;
1147         depth = image_info.Depth;
1148     }
1149
1150     if (format == D3DFMT_FROM_FILE)
1151     {
1152         file_format = TRUE;
1153         format = image_info.Format;
1154     }
1155
1156     if (mip_levels == D3DX_FROM_FILE)
1157     {
1158         file_mip_levels = TRUE;
1159         mip_levels = image_info.MipLevels;
1160     }
1161
1162     hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth, &mip_levels, usage, &format, pool);
1163     if (FAILED(hr)) return hr;
1164
1165     if ((file_width && width != image_info.Width)
1166             || (file_height && height != image_info.Height)
1167             || (file_depth && depth != image_info.Depth)
1168             || (file_format && format != image_info.Format)
1169             || (file_mip_levels && mip_levels != image_info.MipLevels))
1170         return D3DERR_NOTAVAILABLE;
1171
1172     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1173     if (FAILED(hr))
1174         return D3DERR_INVALIDCALL;
1175
1176     if (mip_levels > image_info.MipLevels)
1177     {
1178         FIXME("Generation of mipmaps for volume textures is not implemented yet\n");
1179         mip_levels = image_info.MipLevels;
1180     }
1181
1182     dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1183     if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1184     {
1185         hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1186         tex = buftex;
1187     }
1188     else
1189     {
1190         hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1191         buftex = NULL;
1192     }
1193
1194     if (FAILED(hr)) return hr;
1195
1196     hr = load_volume_texture_from_dds(tex, data, palette, filter, color_key, &image_info);
1197     if (FAILED(hr))
1198     {
1199         IDirect3DVolumeTexture9_Release(tex);
1200         return hr;
1201     }
1202
1203     if (buftex)
1204     {
1205         hr = D3DXCreateVolumeTexture(device, width, height, depth, mip_levels, usage, format, pool, &tex);
1206         if (FAILED(hr))
1207         {
1208             IDirect3DVolumeTexture9_Release(buftex);
1209             return hr;
1210         }
1211
1212         IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1213         IDirect3DVolumeTexture9_Release(buftex);
1214     }
1215
1216     if (info)
1217         *info = image_info;
1218
1219     *volume_texture = tex;
1220     return D3D_OK;
1221 }
1222
1223 HRESULT WINAPI D3DXFillTexture(struct IDirect3DTexture9 *texture, LPD3DXFILL2D function, void *funcdata)
1224 {
1225     DWORD miplevels;
1226     DWORD m, i, x, y, c, v;
1227     D3DSURFACE_DESC desc;
1228     D3DLOCKED_RECT lock_rect;
1229     D3DXVECTOR4 value;
1230     D3DXVECTOR2 coord, size;
1231     const struct pixel_format_desc *format;
1232     BYTE *data, *pos;
1233     BYTE byte, mask;
1234     float comp_value;
1235
1236     if (texture == NULL || function == NULL)
1237         return D3DERR_INVALIDCALL;
1238
1239     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1240
1241     for (m = 0; m < miplevels; m++)
1242     {
1243         if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1244             return D3DERR_INVALIDCALL;
1245
1246         format = get_format_info(desc.Format);
1247         if (format->type != FORMAT_ARGB)
1248         {
1249             FIXME("Unsupported texture format %#x\n", desc.Format);
1250             return D3DERR_INVALIDCALL;
1251         }
1252
1253         if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1254             return D3DERR_INVALIDCALL;
1255
1256         size.x = 1.0f / desc.Width;
1257         size.y = 1.0f / desc.Height;
1258
1259         data = lock_rect.pBits;
1260
1261         for (y = 0; y < desc.Height; y++)
1262         {
1263             /* The callback function expects the coordinates of the center
1264                of the texel */
1265             coord.y = (y + 0.5f) / desc.Height;
1266
1267             for (x = 0; x < desc.Width; x++)
1268             {
1269                 coord.x = (x + 0.5f) / desc.Width;
1270
1271                 function(&value, &coord, &size, funcdata);
1272
1273                 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1274
1275                 for (i = 0; i < format->bytes_per_pixel; i++)
1276                     pos[i] = 0;
1277
1278                 for (c = 0; c < 4; c++)
1279                 {
1280                     switch (c)
1281                     {
1282                         case 0: /* Alpha */
1283                             comp_value = value.w;
1284                             break;
1285                         case 1: /* Red */
1286                             comp_value = value.x;
1287                             break;
1288                         case 2: /* Green */
1289                             comp_value = value.y;
1290                             break;
1291                         case 3: /* Blue */
1292                             comp_value = value.z;
1293                             break;
1294                     }
1295
1296                     v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1297
1298                     for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1299                     {
1300                         mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1301                         byte = (v << format->shift[c] >> i) & mask;
1302                         pos[i / 8] |= byte;
1303                     }
1304                 }
1305             }
1306         }
1307         IDirect3DTexture9_UnlockRect(texture, m);
1308     }
1309
1310     return D3D_OK;
1311 }
1312
1313 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(IDirect3DDevice9 *device,
1314                                                        const void *src_data,
1315                                                        UINT src_data_size,
1316                                                        UINT size,
1317                                                        UINT mip_levels,
1318                                                        DWORD usage,
1319                                                        D3DFORMAT format,
1320                                                        D3DPOOL pool,
1321                                                        DWORD filter,
1322                                                        DWORD mip_filter,
1323                                                        D3DCOLOR color_key,
1324                                                        D3DXIMAGE_INFO *src_info,
1325                                                        PALETTEENTRY *palette,
1326                                                        IDirect3DCubeTexture9 **cube_texture)
1327 {
1328     HRESULT hr;
1329     D3DCAPS9 caps;
1330     UINT loaded_miplevels;
1331     D3DXIMAGE_INFO img_info;
1332     BOOL dynamic_texture;
1333     BOOL file_size = FALSE;
1334     BOOL file_format = FALSE;
1335     BOOL file_mip_levels = FALSE;
1336     IDirect3DCubeTexture9 *tex, *buftex;
1337
1338     TRACE("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p)\n", device,
1339         src_data, src_data_size, size, mip_levels, usage, format, pool, filter, mip_filter,
1340         color_key, src_info, palette, cube_texture);
1341
1342     if (!device || !cube_texture || !src_data || !src_data_size)
1343         return D3DERR_INVALIDCALL;
1344
1345     hr = D3DXGetImageInfoFromFileInMemory(src_data, src_data_size, &img_info);
1346     if (FAILED(hr))
1347         return hr;
1348
1349     if (img_info.ImageFileFormat != D3DXIFF_DDS)
1350         return D3DXERR_INVALIDDATA;
1351
1352     if (img_info.Width != img_info.Height)
1353         return D3DXERR_INVALIDDATA;
1354
1355     if (size == 0 || size == D3DX_DEFAULT_NONPOW2)
1356         size = img_info.Width;
1357     if (size == D3DX_DEFAULT)
1358         size = make_pow2(img_info.Width);
1359
1360     if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
1361         format = img_info.Format;
1362
1363     if (size == D3DX_FROM_FILE)
1364     {
1365         file_size = TRUE;
1366         size = img_info.Width;
1367     }
1368
1369     if (format == D3DFMT_FROM_FILE)
1370     {
1371         file_format = TRUE;
1372         format = img_info.Format;
1373     }
1374
1375     if (mip_levels == D3DX_FROM_FILE)
1376     {
1377         file_mip_levels = TRUE;
1378         mip_levels = img_info.MipLevels;
1379     }
1380
1381     hr = D3DXCheckCubeTextureRequirements(device, &size, &mip_levels, usage, &format, pool);
1382     if (FAILED(hr))
1383         return hr;
1384
1385     if ((file_size && size != img_info.Width)
1386             || (file_format && format != img_info.Format)
1387             || (file_mip_levels && mip_levels != img_info.MipLevels))
1388         return D3DERR_NOTAVAILABLE;
1389
1390     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1391     if (FAILED(hr))
1392         return D3DERR_INVALIDCALL;
1393
1394     if (mip_levels > img_info.MipLevels && (D3DFMT_DXT1 <= img_info.Format && img_info.Format <= D3DFMT_DXT5))
1395     {
1396         FIXME("Generation of mipmaps for compressed pixel formats not supported yet\n");
1397         mip_levels = img_info.MipLevels;
1398     }
1399
1400     dynamic_texture = (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (usage & D3DUSAGE_DYNAMIC);
1401     if (pool == D3DPOOL_DEFAULT && !dynamic_texture)
1402     {
1403         hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
1404         tex = buftex;
1405     }
1406     else
1407     {
1408         hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1409         buftex = NULL;
1410     }
1411     if (FAILED(hr))
1412         return hr;
1413
1414     hr = load_cube_texture_from_dds(tex, src_data, palette, filter, color_key, &img_info);
1415     if (FAILED(hr))
1416     {
1417         IDirect3DCubeTexture9_Release(tex);
1418         return hr;
1419     }
1420
1421     loaded_miplevels = min(IDirect3DCubeTexture9_GetLevelCount(tex), img_info.MipLevels);
1422     hr = D3DXFilterTexture((IDirect3DBaseTexture9*) tex, palette, loaded_miplevels - 1, mip_filter);
1423     if (FAILED(hr))
1424     {
1425         IDirect3DCubeTexture9_Release(tex);
1426         return hr;
1427     }
1428
1429     if (buftex)
1430     {
1431         hr = D3DXCreateCubeTexture(device, size, mip_levels, usage, format, pool, &tex);
1432         if (FAILED(hr))
1433         {
1434             IDirect3DCubeTexture9_Release(buftex);
1435             return hr;
1436         }
1437
1438         IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9 *)buftex, (IDirect3DBaseTexture9 *)tex);
1439         IDirect3DCubeTexture9_Release(buftex);
1440     }
1441
1442     if (src_info)
1443         *src_info = img_info;
1444
1445     *cube_texture = tex;
1446     return D3D_OK;
1447 }
1448
1449
1450 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1451                                               const char *src_filename,
1452                                               IDirect3DCubeTexture9 **cube_texture)
1453 {
1454     int len;
1455     HRESULT hr;
1456     WCHAR *filename;
1457     void *data;
1458     DWORD data_size;
1459
1460     TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1461
1462     if (!src_filename) return D3DERR_INVALIDCALL;
1463
1464     len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1465     filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1466     if (!filename) return E_OUTOFMEMORY;
1467     MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1468
1469     hr = map_view_of_file(filename, &data, &data_size);
1470     if (FAILED(hr))
1471     {
1472         HeapFree(GetProcessHeap(), 0, filename);
1473         return D3DXERR_INVALIDDATA;
1474     }
1475
1476     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1477         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1478
1479     UnmapViewOfFile(data);
1480     HeapFree(GetProcessHeap(), 0, filename);
1481     return hr;
1482 }
1483
1484 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1485                                               const WCHAR *src_filename,
1486                                               IDirect3DCubeTexture9 **cube_texture)
1487 {
1488     HRESULT hr;
1489     void *data;
1490     DWORD data_size;
1491
1492     TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1493
1494     hr = map_view_of_file(src_filename, &data, &data_size);
1495     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1496
1497     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1498         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1499
1500     UnmapViewOfFile(data);
1501     return hr;
1502 }
1503
1504 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1505                                                 const char *src_filename,
1506                                                 UINT size,
1507                                                 UINT mip_levels,
1508                                                 DWORD usage,
1509                                                 D3DFORMAT format,
1510                                                 D3DPOOL pool,
1511                                                 DWORD filter,
1512                                                 DWORD mip_filter,
1513                                                 D3DCOLOR color_key,
1514                                                 D3DXIMAGE_INFO *image_info,
1515                                                 PALETTEENTRY *palette,
1516                                                 IDirect3DCubeTexture9 **cube_texture)
1517 {
1518     int len;
1519     HRESULT hr;
1520     WCHAR *filename;
1521     void *data;
1522     DWORD data_size;
1523
1524     TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1525             device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1526             pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1527
1528     if (!src_filename) return D3DERR_INVALIDCALL;
1529
1530     len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1531     filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1532     if (!filename) return E_OUTOFMEMORY;
1533     MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1534
1535     hr = map_view_of_file(filename, &data, &data_size);
1536     if (FAILED(hr))
1537     {
1538         HeapFree(GetProcessHeap(), 0, filename);
1539         return D3DXERR_INVALIDDATA;
1540     }
1541
1542     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1543         usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1544
1545     UnmapViewOfFile(data);
1546     HeapFree(GetProcessHeap(), 0, filename);
1547     return hr;
1548 }
1549
1550 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1551                                                 const WCHAR *src_filename,
1552                                                 UINT size,
1553                                                 UINT mip_levels,
1554                                                 DWORD usage,
1555                                                 D3DFORMAT format,
1556                                                 D3DPOOL pool,
1557                                                 DWORD filter,
1558                                                 DWORD mip_filter,
1559                                                 D3DCOLOR color_key,
1560                                                 D3DXIMAGE_INFO *image_info,
1561                                                 PALETTEENTRY *palette,
1562                                                 IDirect3DCubeTexture9 **cube_texture)
1563 {
1564     HRESULT hr;
1565     void *data;
1566     DWORD data_size;
1567
1568     TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1569             device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1570             pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1571
1572     hr = map_view_of_file(src_filename, &data, &data_size);
1573     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1574
1575     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1576         usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1577
1578     UnmapViewOfFile(data);
1579     return hr;
1580 }
1581
1582 enum cube_coord
1583 {
1584     XCOORD = 0,
1585     XCOORDINV = 1,
1586     YCOORD = 2,
1587     YCOORDINV = 3,
1588     ZERO = 4,
1589     ONE = 5
1590 };
1591
1592 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1593 {
1594     switch (coord)
1595     {
1596         case XCOORD:
1597             return x + 0.5f;
1598         case XCOORDINV:
1599             return size - x - 0.5f;
1600         case YCOORD:
1601             return y + 0.5f;
1602         case YCOORDINV:
1603             return size - y - 0.5f;
1604         case ZERO:
1605             return 0.0f;
1606         case ONE:
1607             return size;
1608        default:
1609            ERR("Unexpected coordinate value\n");
1610            return 0.0f;
1611     }
1612 }
1613
1614 HRESULT WINAPI D3DXFillCubeTexture(struct IDirect3DCubeTexture9 *texture, LPD3DXFILL3D function, void *funcdata)
1615 {
1616     DWORD miplevels;
1617     DWORD m, i, x, y, c, f, v;
1618     D3DSURFACE_DESC desc;
1619     D3DLOCKED_RECT lock_rect;
1620     D3DXVECTOR4 value;
1621     D3DXVECTOR3 coord, size;
1622     const struct pixel_format_desc *format;
1623     BYTE *data, *pos;
1624     BYTE byte, mask;
1625     float comp_value;
1626     static const enum cube_coord coordmap[6][3] =
1627         {
1628             {ONE, YCOORDINV, XCOORDINV},
1629             {ZERO, YCOORDINV, XCOORD},
1630             {XCOORD, ONE, YCOORD},
1631             {XCOORD, ZERO, YCOORDINV},
1632             {XCOORD, YCOORDINV, ONE},
1633             {XCOORDINV, YCOORDINV, ZERO}
1634         };
1635
1636     if (texture == NULL || function == NULL)
1637         return D3DERR_INVALIDCALL;
1638
1639     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1640
1641     for (m = 0; m < miplevels; m++)
1642     {
1643         if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1644             return D3DERR_INVALIDCALL;
1645
1646         format = get_format_info(desc.Format);
1647         if (format->type != FORMAT_ARGB)
1648         {
1649             FIXME("Unsupported texture format %#x\n", desc.Format);
1650             return D3DERR_INVALIDCALL;
1651         }
1652
1653         for (f = 0; f < 6; f++)
1654         {
1655             if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1656                 return D3DERR_INVALIDCALL;
1657
1658             size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1659             size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1660             size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1661
1662             data = lock_rect.pBits;
1663
1664             for (y = 0; y < desc.Height; y++)
1665             {
1666                 for (x = 0; x < desc.Width; x++)
1667                 {
1668                     coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1669                     coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1670                     coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1671
1672                     function(&value, &coord, &size, funcdata);
1673
1674                     pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1675
1676                     for (i = 0; i < format->bytes_per_pixel; i++)
1677                         pos[i] = 0;
1678
1679                     for (c = 0; c < 4; c++)
1680                     {
1681                         switch (c)
1682                         {
1683                             case 0: /* Alpha */
1684                                 comp_value = value.w;
1685                                 break;
1686                             case 1: /* Red */
1687                                 comp_value = value.x;
1688                                 break;
1689                             case 2: /* Green */
1690                                 comp_value = value.y;
1691                                 break;
1692                             case 3: /* Blue */
1693                                 comp_value = value.z;
1694                                 break;
1695                         }
1696
1697                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1698
1699                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1700                         {
1701                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1702                             byte = (v << format->shift[c] >> i) & mask;
1703                             pos[i / 8] |= byte;
1704                         }
1705                     }
1706                 }
1707             }
1708             IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1709         }
1710     }
1711
1712     return D3D_OK;
1713 }
1714
1715 HRESULT WINAPI D3DXFillVolumeTexture(struct IDirect3DVolumeTexture9 *texture, LPD3DXFILL3D function, void *funcdata)
1716 {
1717     DWORD miplevels;
1718     DWORD m, i, x, y, z, c, v;
1719     D3DVOLUME_DESC desc;
1720     D3DLOCKED_BOX lock_box;
1721     D3DXVECTOR4 value;
1722     D3DXVECTOR3 coord, size;
1723     const struct pixel_format_desc *format;
1724     BYTE *data, *pos;
1725     BYTE byte, mask;
1726     float comp_value;
1727
1728     if (texture == NULL || function == NULL)
1729         return D3DERR_INVALIDCALL;
1730
1731     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1732
1733     for (m = 0; m < miplevels; m++)
1734     {
1735         if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1736             return D3DERR_INVALIDCALL;
1737
1738         format = get_format_info(desc.Format);
1739         if (format->type != FORMAT_ARGB)
1740         {
1741             FIXME("Unsupported texture format %#x\n", desc.Format);
1742             return D3DERR_INVALIDCALL;
1743         }
1744
1745         if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1746             return D3DERR_INVALIDCALL;
1747
1748         size.x = 1.0f / desc.Width;
1749         size.y = 1.0f / desc.Height;
1750         size.z = 1.0f / desc.Depth;
1751
1752         data = lock_box.pBits;
1753
1754         for (z = 0; z < desc.Depth; z++)
1755         {
1756             /* The callback function expects the coordinates of the center
1757                of the texel */
1758             coord.z = (z + 0.5f) / desc.Depth;
1759
1760             for (y = 0; y < desc.Height; y++)
1761             {
1762                 coord.y = (y + 0.5f) / desc.Height;
1763
1764                 for (x = 0; x < desc.Width; x++)
1765                 {
1766                     coord.x = (x + 0.5f) / desc.Width;
1767
1768                     function(&value, &coord, &size, funcdata);
1769
1770                     pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1771
1772                     for (i = 0; i < format->bytes_per_pixel; i++)
1773                         pos[i] = 0;
1774
1775                     for (c = 0; c < 4; c++)
1776                     {
1777                         switch (c)
1778                         {
1779                             case 0: /* Alpha */
1780                                 comp_value = value.w;
1781                                 break;
1782                             case 1: /* Red */
1783                                 comp_value = value.x;
1784                                 break;
1785                             case 2: /* Green */
1786                                 comp_value = value.y;
1787                                 break;
1788                             case 3: /* Blue */
1789                                 comp_value = value.z;
1790                                 break;
1791                         }
1792
1793                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1794
1795                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1796                         {
1797                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1798                             byte = (v << format->shift[c] >> i) & mask;
1799                             pos[i / 8] |= byte;
1800                         }
1801                     }
1802                 }
1803             }
1804         }
1805         IDirect3DVolumeTexture9_UnlockBox(texture, m);
1806     }
1807
1808     return D3D_OK;
1809 }
1810
1811 HRESULT WINAPI D3DXSaveTextureToFileA(const char *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1812         IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1813 {
1814     int len;
1815     WCHAR *filename;
1816     HRESULT hr;
1817     ID3DXBuffer *buffer;
1818
1819     TRACE("(%s, %#x, %p, %p): relay\n",
1820             wine_dbgstr_a(dst_filename), file_format, src_texture, src_palette);
1821
1822     if (!dst_filename) return D3DERR_INVALIDCALL;
1823
1824     len = MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, NULL, 0);
1825     filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1826     if (!filename) return E_OUTOFMEMORY;
1827     MultiByteToWideChar(CP_ACP, 0, dst_filename, -1, filename, len);
1828
1829     hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1830     if (SUCCEEDED(hr))
1831     {
1832         hr = write_buffer_to_file(filename, buffer);
1833         ID3DXBuffer_Release(buffer);
1834     }
1835
1836     HeapFree(GetProcessHeap(), 0, filename);
1837     return hr;
1838 }
1839
1840 HRESULT WINAPI D3DXSaveTextureToFileW(const WCHAR *dst_filename, D3DXIMAGE_FILEFORMAT file_format,
1841         IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1842 {
1843     HRESULT hr;
1844     ID3DXBuffer *buffer;
1845
1846     TRACE("(%s, %#x, %p, %p): relay\n",
1847         wine_dbgstr_w(dst_filename), file_format, src_texture, src_palette);
1848
1849     if (!dst_filename) return D3DERR_INVALIDCALL;
1850
1851     hr = D3DXSaveTextureToFileInMemory(&buffer, file_format, src_texture, src_palette);
1852     if (SUCCEEDED(hr))
1853     {
1854         hr = write_buffer_to_file(dst_filename, buffer);
1855         ID3DXBuffer_Release(buffer);
1856     }
1857
1858     return hr;
1859 }
1860
1861 HRESULT WINAPI D3DXSaveTextureToFileInMemory(ID3DXBuffer **dst_buffer, D3DXIMAGE_FILEFORMAT file_format,
1862         IDirect3DBaseTexture9 *src_texture, const PALETTEENTRY *src_palette)
1863 {
1864     HRESULT hr;
1865     D3DRESOURCETYPE type;
1866     IDirect3DSurface9 *surface;
1867
1868     TRACE("(%p, %#x, %p, %p)\n",
1869         dst_buffer, file_format, src_texture, src_palette);
1870
1871     if (!dst_buffer || !src_texture) return D3DERR_INVALIDCALL;
1872
1873     if (file_format == D3DXIFF_DDS)
1874     {
1875         FIXME("DDS file format isn't supported yet\n");
1876         return E_NOTIMPL;
1877     }
1878
1879     type = IDirect3DBaseTexture9_GetType(src_texture);
1880     switch (type)
1881     {
1882         case D3DRTYPE_TEXTURE:
1883         case D3DRTYPE_CUBETEXTURE:
1884             hr = get_surface(type, src_texture, D3DCUBEMAP_FACE_POSITIVE_X, 0, &surface);
1885             break;
1886         case D3DRTYPE_VOLUMETEXTURE:
1887             FIXME("Volume textures aren't supported yet\n");
1888             return E_NOTIMPL;
1889         default:
1890             return D3DERR_INVALIDCALL;
1891     }
1892
1893     if (SUCCEEDED(hr))
1894     {
1895         hr = D3DXSaveSurfaceToFileInMemory(dst_buffer, file_format, surface, src_palette, NULL);
1896         IDirect3DSurface9_Release(surface);
1897     }
1898
1899     return hr;
1900 }