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