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