d3dx9: Forward D3DXCreateCubeTextureFromFile functions to D3DXCreateCubeTextureFromFi...
[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     D3DCAPS9 caps;
508     HRESULT hr;
509
510     TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
511         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
512
513     /* check for invalid parameters */
514     if (!device || !texture || !srcdata || !srcdatasize)
515         return D3DERR_INVALIDCALL;
516
517     hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
518
519     if (FAILED(hr))
520     {
521         *texture = NULL;
522         return hr;
523     }
524
525     /* handle default values */
526     if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
527         width = imginfo.Width;
528
529     if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
530         height = imginfo.Height;
531
532     if (width == D3DX_DEFAULT)
533         width = make_pow2(imginfo.Width);
534
535     if (height == D3DX_DEFAULT)
536         height = make_pow2(imginfo.Height);
537
538     if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
539         format = imginfo.Format;
540
541     if (width == D3DX_FROM_FILE)
542     {
543         file_width = TRUE;
544         width = imginfo.Width;
545     }
546
547     if (height == D3DX_FROM_FILE)
548     {
549         file_height = TRUE;
550         height = imginfo.Height;
551     }
552
553     if (format == D3DFMT_FROM_FILE)
554     {
555         file_format = TRUE;
556         format = imginfo.Format;
557     }
558
559     if (miplevels == D3DX_FROM_FILE)
560     {
561         file_miplevels = TRUE;
562         miplevels = imginfo.MipLevels;
563     }
564
565     /* fix texture creation parameters */
566     hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
567
568     if (FAILED(hr))
569     {
570         *texture = NULL;
571         return hr;
572     }
573
574     if (((file_width) && (width != imginfo.Width))    ||
575         ((file_height) && (height != imginfo.Height)) ||
576         ((file_format) && (format != imginfo.Format)) ||
577         ((file_miplevels) && (miplevels != imginfo.MipLevels)))
578     {
579         return D3DERR_NOTAVAILABLE;
580     }
581
582     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
583         return D3DERR_INVALIDCALL;
584
585     /* Create the to-be-filled texture */
586     if ((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (pool != D3DPOOL_DEFAULT) && (usage != D3DUSAGE_DYNAMIC))
587     {
588         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
589         texptr = texture;
590     }
591     else
592     {
593         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
594         texptr = &buftex;
595     }
596
597     if (FAILED(hr))
598     {
599         *texture = NULL;
600         return hr;
601     }
602
603     /* Load the file */
604     IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
605     hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
606     IDirect3DSurface9_Release(surface);
607
608     if (FAILED(hr))
609     {
610         IDirect3DTexture9_Release(*texptr);
611         *texture = NULL;
612         return hr;
613     }
614
615     hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, 0, mipfilter);
616
617     if (FAILED(hr))
618     {
619         IDirect3DTexture9_Release(*texptr);
620         *texture = NULL;
621         return hr;
622     }
623
624     /* Move the data to the actual texture if necessary */
625     if (texptr == &buftex)
626     {
627         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
628
629         if (FAILED(hr))
630         {
631             IDirect3DTexture9_Release(buftex);
632             *texture = NULL;
633             return hr;
634         }
635
636         IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
637         IDirect3DTexture9_Release(buftex);
638     }
639
640     if (srcinfo)
641         *srcinfo = imginfo;
642
643     return D3D_OK;
644 }
645
646 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
647                                                  LPCVOID srcdata,
648                                                  UINT srcdatasize,
649                                                  LPDIRECT3DTEXTURE9 *texture)
650 {
651     TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
652
653     return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
654                                                D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
655 }
656
657 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
658                                             LPCWSTR srcfile,
659                                             UINT width,
660                                             UINT height,
661                                             UINT miplevels,
662                                             DWORD usage,
663                                             D3DFORMAT format,
664                                             D3DPOOL pool,
665                                             DWORD filter,
666                                             DWORD mipfilter,
667                                             D3DCOLOR colorkey,
668                                             D3DXIMAGE_INFO *srcinfo,
669                                             PALETTEENTRY *palette,
670                                             LPDIRECT3DTEXTURE9 *texture)
671 {
672     HRESULT hr;
673     DWORD size;
674     LPVOID buffer;
675
676     TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
677             device, debugstr_w(srcfile), width, height, miplevels, usage, format, pool, filter,
678             mipfilter, colorkey, srcinfo, palette, texture);
679
680     if (!srcfile)
681         return D3DERR_INVALIDCALL;
682
683     hr = map_view_of_file(srcfile, &buffer, &size);
684     if (FAILED(hr))
685         return D3DXERR_INVALIDDATA;
686
687     hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
688         filter, mipfilter, colorkey, srcinfo, palette, texture);
689
690     UnmapViewOfFile(buffer);
691
692     return hr;
693 }
694
695 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
696                                             LPCSTR srcfile,
697                                             UINT width,
698                                             UINT height,
699                                             UINT miplevels,
700                                             DWORD usage,
701                                             D3DFORMAT format,
702                                             D3DPOOL pool,
703                                             DWORD filter,
704                                             DWORD mipfilter,
705                                             D3DCOLOR colorkey,
706                                             D3DXIMAGE_INFO *srcinfo,
707                                             PALETTEENTRY *palette,
708                                             LPDIRECT3DTEXTURE9 *texture)
709 {
710     LPWSTR widename;
711     HRESULT hr;
712     DWORD len;
713
714     TRACE("(%p, %s, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n",
715             device, debugstr_a(srcfile), width, height, miplevels, usage, format, pool, filter,
716             mipfilter, colorkey, srcinfo, palette, texture);
717
718     if (!device || !srcfile || !texture)
719         return D3DERR_INVALIDCALL;
720
721     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
722     widename = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
723     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
724
725     hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
726                                       usage, format, pool, filter, mipfilter,
727                                       colorkey, srcinfo, palette, texture);
728
729     HeapFree(GetProcessHeap(), 0, widename);
730     return hr;
731 }
732
733 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
734                                           LPCSTR srcfile,
735                                           LPDIRECT3DTEXTURE9 *texture)
736 {
737     TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
738
739     return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
740                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
741 }
742
743 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
744                                           LPCWSTR srcfile,
745                                           LPDIRECT3DTEXTURE9 *texture)
746 {
747     TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
748
749     return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
750                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
751 }
752
753
754 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
755                                               HMODULE srcmodule,
756                                               LPCSTR resource,
757                                               LPDIRECT3DTEXTURE9 *texture)
758 {
759     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
760
761     return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
762                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
763 }
764
765 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
766                                               HMODULE srcmodule,
767                                               LPCWSTR resource,
768                                               LPDIRECT3DTEXTURE9 *texture)
769 {
770     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
771
772     return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
773                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
774 }
775
776 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
777                                                 HMODULE srcmodule,
778                                                 LPCSTR resource,
779                                                 UINT width,
780                                                 UINT height,
781                                                 UINT miplevels,
782                                                 DWORD usage,
783                                                 D3DFORMAT format,
784                                                 D3DPOOL pool,
785                                                 DWORD filter,
786                                                 DWORD mipfilter,
787                                                 D3DCOLOR colorkey,
788                                                 D3DXIMAGE_INFO *srcinfo,
789                                                 PALETTEENTRY *palette,
790                                                 LPDIRECT3DTEXTURE9 *texture)
791 {
792     HRSRC resinfo;
793
794     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
795
796     if (!device || !texture)
797         return D3DERR_INVALIDCALL;
798
799     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
800
801     if (resinfo)
802     {
803         LPVOID buffer;
804         HRESULT hr;
805         DWORD size;
806
807         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
808
809         if (FAILED(hr))
810             return D3DXERR_INVALIDDATA;
811
812         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
813                                                    height, miplevels, usage, format,
814                                                    pool, filter, mipfilter, colorkey,
815                                                    srcinfo, palette, texture);
816     }
817
818     /* Try loading the resource as bitmap data */
819     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
820
821     if (resinfo)
822     {
823         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
824         return E_NOTIMPL;
825     }
826
827     return D3DXERR_INVALIDDATA;
828 }
829
830 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
831                                                 HMODULE srcmodule,
832                                                 LPCWSTR resource,
833                                                 UINT width,
834                                                 UINT height,
835                                                 UINT miplevels,
836                                                 DWORD usage,
837                                                 D3DFORMAT format,
838                                                 D3DPOOL pool,
839                                                 DWORD filter,
840                                                 DWORD mipfilter,
841                                                 D3DCOLOR colorkey,
842                                                 D3DXIMAGE_INFO *srcinfo,
843                                                 PALETTEENTRY *palette,
844                                                 LPDIRECT3DTEXTURE9 *texture)
845 {
846     HRSRC resinfo;
847
848     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
849
850     if (!device || !texture)
851         return D3DERR_INVALIDCALL;
852
853     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
854
855     if (resinfo)
856     {
857         LPVOID buffer;
858         HRESULT hr;
859         DWORD size;
860
861         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
862
863         if (FAILED(hr))
864             return D3DXERR_INVALIDDATA;
865
866         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
867                                                    height, miplevels, usage, format,
868                                                    pool, filter, mipfilter, colorkey,
869                                                    srcinfo, palette, texture);
870     }
871
872     /* Try loading the resource as bitmap data */
873     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
874
875     if (resinfo)
876     {
877         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
878         return E_NOTIMPL;
879     }
880
881     return D3DXERR_INVALIDDATA;
882 }
883
884 HRESULT WINAPI D3DXCreateCubeTexture(LPDIRECT3DDEVICE9 device,
885                                      UINT size,
886                                      UINT miplevels,
887                                      DWORD usage,
888                                      D3DFORMAT format,
889                                      D3DPOOL pool,
890                                      LPDIRECT3DCUBETEXTURE9 *texture)
891 {
892     HRESULT hr;
893
894     TRACE("(%p, %u, %u, %#x, %#x, %#x, %p)\n", device, size, miplevels, usage, format,
895         pool, texture);
896
897     if (!device || !texture)
898         return D3DERR_INVALIDCALL;
899
900     hr = D3DXCheckCubeTextureRequirements(device, &size, &miplevels, usage, &format, pool);
901
902     if (FAILED(hr))
903     {
904         TRACE("D3DXCheckCubeTextureRequirements failed\n");
905         return hr;
906     }
907
908     return IDirect3DDevice9_CreateCubeTexture(device, size, miplevels, usage, format, pool, texture, NULL);
909 }
910
911 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
912                                                      LPCVOID data,
913                                                      UINT datasize,
914                                                      LPDIRECT3DCUBETEXTURE9 *texture)
915 {
916     TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
917
918     return D3DXCreateCubeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
919         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
920 }
921
922 HRESULT WINAPI D3DXCreateVolumeTexture(LPDIRECT3DDEVICE9 device,
923                                        UINT width,
924                                        UINT height,
925                                        UINT depth,
926                                        UINT miplevels,
927                                        DWORD usage,
928                                        D3DFORMAT format,
929                                        D3DPOOL pool,
930                                        LPDIRECT3DVOLUMETEXTURE9 *texture)
931 {
932     HRESULT hr;
933
934     TRACE("(%p, %u, %u, %u, %u, %#x, %#x, %#x, %p)\n", device, width, height, depth,
935           miplevels, usage, format, pool, texture);
936
937     if (!device || !texture)
938         return D3DERR_INVALIDCALL;
939
940     hr = D3DXCheckVolumeTextureRequirements(device, &width, &height, &depth,
941                                             &miplevels, usage, &format, pool);
942
943     if (FAILED(hr))
944     {
945         TRACE("D3DXCheckVolumeTextureRequirements failed\n");
946         return hr;
947     }
948
949     return IDirect3DDevice9_CreateVolumeTexture(device, width, height, depth, miplevels,
950                                                 usage, format, pool, texture, NULL);
951 }
952
953 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
954                                                       LPCVOID data,
955                                                       UINT datasize,
956                                                       LPDIRECT3DVOLUMETEXTURE9 *texture)
957 {
958     TRACE("(%p, %p, %u, %p)\n", device, data, datasize, texture);
959
960     return D3DXCreateVolumeTextureFromFileInMemoryEx(device, data, datasize, D3DX_DEFAULT, D3DX_DEFAULT,
961         D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT,
962         0, NULL, NULL, texture);
963 }
964
965 HRESULT WINAPI D3DXCreateVolumeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
966                                                          LPCVOID data,
967                                                          UINT datasize,
968                                                          UINT width,
969                                                          UINT height,
970                                                          UINT depth,
971                                                          UINT miplevels,
972                                                          DWORD usage,
973                                                          D3DFORMAT format,
974                                                          D3DPOOL pool,
975                                                          DWORD filter,
976                                                          DWORD mipfilter,
977                                                          D3DCOLOR colorkey,
978                                                          D3DXIMAGE_INFO *imageinfo,
979                                                          PALETTEENTRY *palette,
980                                                          LPDIRECT3DVOLUMETEXTURE9 *texture)
981 {
982     FIXME("(%p, %p, %u, %u, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p) : stub\n",
983         device, data, datasize, width, height, depth, miplevels, usage, format, pool,
984         filter, mipfilter, colorkey, imageinfo, palette, texture);
985
986     return E_NOTIMPL;
987 }
988
989 HRESULT WINAPI D3DXFillTexture(LPDIRECT3DTEXTURE9 texture,
990                                LPD3DXFILL2D function,
991                                LPVOID funcdata)
992 {
993     DWORD miplevels;
994     DWORD m, i, x, y, c, v;
995     D3DSURFACE_DESC desc;
996     D3DLOCKED_RECT lock_rect;
997     D3DXVECTOR4 value;
998     D3DXVECTOR2 coord, size;
999     const PixelFormatDesc *format;
1000     BYTE *data, *pos;
1001     BYTE byte, mask;
1002     float comp_value;
1003
1004     if (texture == NULL || function == NULL)
1005         return D3DERR_INVALIDCALL;
1006
1007     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1008
1009     for (m = 0; m < miplevels; m++)
1010     {
1011         if (FAILED(IDirect3DTexture9_GetLevelDesc(texture, m, &desc)))
1012             return D3DERR_INVALIDCALL;
1013
1014         format = get_format_info(desc.Format);
1015         if (format->format == D3DFMT_UNKNOWN)
1016         {
1017             FIXME("Unsupported texture format %#x\n", desc.Format);
1018             return D3DERR_INVALIDCALL;
1019         }
1020
1021         if (FAILED(IDirect3DTexture9_LockRect(texture, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1022             return D3DERR_INVALIDCALL;
1023
1024         size.x = 1.0f / desc.Width;
1025         size.y = 1.0f / desc.Height;
1026
1027         data = lock_rect.pBits;
1028
1029         for (y = 0; y < desc.Height; y++)
1030         {
1031             /* The callback function expects the coordinates of the center
1032                of the texel */
1033             coord.y = (y + 0.5f) / desc.Height;
1034
1035             for (x = 0; x < desc.Width; x++)
1036             {
1037                 coord.x = (x + 0.5f) / desc.Width;
1038
1039                 function(&value, &coord, &size, funcdata);
1040
1041                 pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1042
1043                 for (i = 0; i < format->bytes_per_pixel; i++)
1044                     pos[i] = 0;
1045
1046                 for (c = 0; c < 4; c++)
1047                 {
1048                     switch (c)
1049                     {
1050                         case 0: /* Alpha */
1051                             comp_value = value.w;
1052                             break;
1053                         case 1: /* Red */
1054                             comp_value = value.x;
1055                             break;
1056                         case 2: /* Green */
1057                             comp_value = value.y;
1058                             break;
1059                         case 3: /* Blue */
1060                             comp_value = value.z;
1061                             break;
1062                     }
1063
1064                     v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1065
1066                     for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1067                     {
1068                         mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1069                         byte = (v << format->shift[c] >> i) & mask;
1070                         pos[i / 8] |= byte;
1071                     }
1072                 }
1073             }
1074         }
1075         IDirect3DTexture9_UnlockRect(texture, m);
1076     }
1077
1078     return D3D_OK;
1079 }
1080
1081 HRESULT WINAPI D3DXCreateCubeTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 pDevice, LPCVOID pSrcData, UINT SrcDataSize,
1082         UINT Size, UINT MipLevels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, DWORD Filter, DWORD MipFilter, D3DCOLOR ColorKey,
1083         D3DXIMAGE_INFO *pSrcInfo, PALETTEENTRY *pPalette, LPDIRECT3DCUBETEXTURE9 *ppCubeTexture)
1084 {
1085     FIXME("(%p, %p, %u, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): stub\n", pDevice, pSrcData, SrcDataSize, Size, MipLevels,
1086             Usage, Format, Pool, Filter, MipFilter, ColorKey, pSrcInfo, pPalette, ppCubeTexture);
1087
1088     return E_NOTIMPL;
1089 }
1090
1091 HRESULT WINAPI D3DXCreateCubeTextureFromFileA(IDirect3DDevice9 *device,
1092                                               const char *src_filename,
1093                                               IDirect3DCubeTexture9 **cube_texture)
1094 {
1095     int len;
1096     HRESULT hr;
1097     WCHAR *filename;
1098     void *data;
1099     DWORD data_size;
1100
1101     TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_a(src_filename), cube_texture);
1102
1103     if (!src_filename) return D3DERR_INVALIDCALL;
1104
1105     len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1106     filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1107     if (!filename) return E_OUTOFMEMORY;
1108     MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1109
1110     hr = map_view_of_file(filename, &data, &data_size);
1111     if (FAILED(hr))
1112     {
1113         HeapFree(GetProcessHeap(), 0, filename);
1114         return D3DXERR_INVALIDDATA;
1115     }
1116
1117     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1118         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1119
1120     UnmapViewOfFile(data);
1121     HeapFree(GetProcessHeap(), 0, filename);
1122     return hr;
1123 }
1124
1125 HRESULT WINAPI D3DXCreateCubeTextureFromFileW(IDirect3DDevice9 *device,
1126                                               const WCHAR *src_filename,
1127                                               IDirect3DCubeTexture9 **cube_texture)
1128 {
1129     HRESULT hr;
1130     void *data;
1131     DWORD data_size;
1132
1133     TRACE("(%p, %s, %p): relay\n", device, wine_dbgstr_w(src_filename), cube_texture);
1134
1135     hr = map_view_of_file(src_filename, &data, &data_size);
1136     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1137
1138     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, D3DX_DEFAULT, D3DX_DEFAULT,
1139         0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, cube_texture);
1140
1141     UnmapViewOfFile(data);
1142     return hr;
1143 }
1144
1145 HRESULT WINAPI D3DXCreateCubeTextureFromFileExA(IDirect3DDevice9 *device,
1146                                                 const char *src_filename,
1147                                                 UINT size,
1148                                                 UINT mip_levels,
1149                                                 DWORD usage,
1150                                                 D3DFORMAT format,
1151                                                 D3DPOOL pool,
1152                                                 DWORD filter,
1153                                                 DWORD mip_filter,
1154                                                 D3DCOLOR color_key,
1155                                                 D3DXIMAGE_INFO *image_info,
1156                                                 PALETTEENTRY *palette,
1157                                                 IDirect3DCubeTexture9 **cube_texture)
1158 {
1159     int len;
1160     HRESULT hr;
1161     WCHAR *filename;
1162     void *data;
1163     DWORD data_size;
1164
1165     TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1166             device, wine_dbgstr_a(src_filename), size, mip_levels, usage, format,
1167             pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1168
1169     if (!src_filename) return D3DERR_INVALIDCALL;
1170
1171     len = MultiByteToWideChar(CP_ACP, 0, src_filename, -1, NULL, 0);
1172     filename = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1173     if (!filename) return E_OUTOFMEMORY;
1174     MultiByteToWideChar(CP_ACP, 0, src_filename, -1, filename, len);
1175
1176     hr = map_view_of_file(filename, &data, &data_size);
1177     if (FAILED(hr))
1178     {
1179         HeapFree(GetProcessHeap(), 0, filename);
1180         return D3DXERR_INVALIDDATA;
1181     }
1182
1183     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1184         usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1185
1186     UnmapViewOfFile(data);
1187     HeapFree(GetProcessHeap(), 0, filename);
1188     return hr;
1189 }
1190
1191 HRESULT WINAPI D3DXCreateCubeTextureFromFileExW(IDirect3DDevice9 *device,
1192                                                 const WCHAR *src_filename,
1193                                                 UINT size,
1194                                                 UINT mip_levels,
1195                                                 DWORD usage,
1196                                                 D3DFORMAT format,
1197                                                 D3DPOOL pool,
1198                                                 DWORD filter,
1199                                                 DWORD mip_filter,
1200                                                 D3DCOLOR color_key,
1201                                                 D3DXIMAGE_INFO *image_info,
1202                                                 PALETTEENTRY *palette,
1203                                                 IDirect3DCubeTexture9 **cube_texture)
1204 {
1205     HRESULT hr;
1206     void *data;
1207     DWORD data_size;
1208
1209     TRACE("(%p, %s, %u, %u, %#x, %#x, %#x, %#x, %#x, %#x, %p, %p, %p): relay\n",
1210             device, wine_dbgstr_w(src_filename), size, mip_levels, usage, format,
1211             pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1212
1213     hr = map_view_of_file(src_filename, &data, &data_size);
1214     if (FAILED(hr)) return D3DXERR_INVALIDDATA;
1215
1216     hr = D3DXCreateCubeTextureFromFileInMemoryEx(device, data, data_size, size, mip_levels,
1217         usage, format, pool, filter, mip_filter, color_key, image_info, palette, cube_texture);
1218
1219     UnmapViewOfFile(data);
1220     return hr;
1221 }
1222
1223 enum cube_coord
1224 {
1225     XCOORD = 0,
1226     XCOORDINV = 1,
1227     YCOORD = 2,
1228     YCOORDINV = 3,
1229     ZERO = 4,
1230     ONE = 5
1231 };
1232
1233 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1234 {
1235     switch (coord)
1236     {
1237         case XCOORD:
1238             return x + 0.5f;
1239         case XCOORDINV:
1240             return size - x - 0.5f;
1241         case YCOORD:
1242             return y + 0.5f;
1243         case YCOORDINV:
1244             return size - y - 0.5f;
1245         case ZERO:
1246             return 0.0f;
1247         case ONE:
1248             return size;
1249        default:
1250            ERR("Unexpected coordinate value\n");
1251            return 0.0f;
1252     }
1253 }
1254
1255 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1256                                    LPD3DXFILL3D function,
1257                                    LPVOID funcdata)
1258 {
1259     DWORD miplevels;
1260     DWORD m, i, x, y, c, f, v;
1261     D3DSURFACE_DESC desc;
1262     D3DLOCKED_RECT lock_rect;
1263     D3DXVECTOR4 value;
1264     D3DXVECTOR3 coord, size;
1265     const PixelFormatDesc *format;
1266     BYTE *data, *pos;
1267     BYTE byte, mask;
1268     float comp_value;
1269     static const enum cube_coord coordmap[6][3] =
1270         {
1271             {ONE, YCOORDINV, XCOORDINV},
1272             {ZERO, YCOORDINV, XCOORD},
1273             {XCOORD, ONE, YCOORD},
1274             {XCOORD, ZERO, YCOORDINV},
1275             {XCOORD, YCOORDINV, ONE},
1276             {XCOORDINV, YCOORDINV, ZERO}
1277         };
1278
1279     if (texture == NULL || function == NULL)
1280         return D3DERR_INVALIDCALL;
1281
1282     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1283
1284     for (m = 0; m < miplevels; m++)
1285     {
1286         if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1287             return D3DERR_INVALIDCALL;
1288
1289         format = get_format_info(desc.Format);
1290         if (format->format == D3DFMT_UNKNOWN)
1291         {
1292             FIXME("Unsupported texture format %#x\n", desc.Format);
1293             return D3DERR_INVALIDCALL;
1294         }
1295
1296         for (f = 0; f < 6; f++)
1297         {
1298             if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1299                 return D3DERR_INVALIDCALL;
1300
1301             size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1302             size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1303             size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1304
1305             data = lock_rect.pBits;
1306
1307             for (y = 0; y < desc.Height; y++)
1308             {
1309                 for (x = 0; x < desc.Width; x++)
1310                 {
1311                     coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1312                     coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1313                     coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1314
1315                     function(&value, &coord, &size, funcdata);
1316
1317                     pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1318
1319                     for (i = 0; i < format->bytes_per_pixel; i++)
1320                         pos[i] = 0;
1321
1322                     for (c = 0; c < 4; c++)
1323                     {
1324                         switch (c)
1325                         {
1326                             case 0: /* Alpha */
1327                                 comp_value = value.w;
1328                                 break;
1329                             case 1: /* Red */
1330                                 comp_value = value.x;
1331                                 break;
1332                             case 2: /* Green */
1333                                 comp_value = value.y;
1334                                 break;
1335                             case 3: /* Blue */
1336                                 comp_value = value.z;
1337                                 break;
1338                         }
1339
1340                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1341
1342                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1343                         {
1344                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1345                             byte = (v << format->shift[c] >> i) & mask;
1346                             pos[i / 8] |= byte;
1347                         }
1348                     }
1349                 }
1350             }
1351             IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1352         }
1353     }
1354
1355     return D3D_OK;
1356 }
1357
1358 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1359                                      LPD3DXFILL3D function,
1360                                      LPVOID funcdata)
1361 {
1362     DWORD miplevels;
1363     DWORD m, i, x, y, z, c, v;
1364     D3DVOLUME_DESC desc;
1365     D3DLOCKED_BOX lock_box;
1366     D3DXVECTOR4 value;
1367     D3DXVECTOR3 coord, size;
1368     const PixelFormatDesc *format;
1369     BYTE *data, *pos;
1370     BYTE byte, mask;
1371     float comp_value;
1372
1373     if (texture == NULL || function == NULL)
1374         return D3DERR_INVALIDCALL;
1375
1376     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1377
1378     for (m = 0; m < miplevels; m++)
1379     {
1380         if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1381             return D3DERR_INVALIDCALL;
1382
1383         format = get_format_info(desc.Format);
1384         if (format->format == D3DFMT_UNKNOWN)
1385         {
1386             FIXME("Unsupported texture format %#x\n", desc.Format);
1387             return D3DERR_INVALIDCALL;
1388         }
1389
1390         if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1391             return D3DERR_INVALIDCALL;
1392
1393         size.x = 1.0f / desc.Width;
1394         size.y = 1.0f / desc.Height;
1395         size.z = 1.0f / desc.Depth;
1396
1397         data = lock_box.pBits;
1398
1399         for (z = 0; z < desc.Depth; z++)
1400         {
1401             /* The callback function expects the coordinates of the center
1402                of the texel */
1403             coord.z = (z + 0.5f) / desc.Depth;
1404
1405             for (y = 0; y < desc.Height; y++)
1406             {
1407                 coord.y = (y + 0.5f) / desc.Height;
1408
1409                 for (x = 0; x < desc.Width; x++)
1410                 {
1411                     coord.x = (x + 0.5f) / desc.Width;
1412
1413                     function(&value, &coord, &size, funcdata);
1414
1415                     pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1416
1417                     for (i = 0; i < format->bytes_per_pixel; i++)
1418                         pos[i] = 0;
1419
1420                     for (c = 0; c < 4; c++)
1421                     {
1422                         switch (c)
1423                         {
1424                             case 0: /* Alpha */
1425                                 comp_value = value.w;
1426                                 break;
1427                             case 1: /* Red */
1428                                 comp_value = value.x;
1429                                 break;
1430                             case 2: /* Green */
1431                                 comp_value = value.y;
1432                                 break;
1433                             case 3: /* Blue */
1434                                 comp_value = value.z;
1435                                 break;
1436                         }
1437
1438                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1439
1440                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1441                         {
1442                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1443                             byte = (v << format->shift[c] >> i) & mask;
1444                             pos[i / 8] |= byte;
1445                         }
1446                     }
1447                 }
1448             }
1449         }
1450         IDirect3DVolumeTexture9_UnlockBox(texture, m);
1451     }
1452
1453     return D3D_OK;
1454 }