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