d3dx9: Use proper size types in D3DXLoadSurfaceFromMemory().
[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 enum cube_coord
1092 {
1093     XCOORD = 0,
1094     XCOORDINV = 1,
1095     YCOORD = 2,
1096     YCOORDINV = 3,
1097     ZERO = 4,
1098     ONE = 5
1099 };
1100
1101 static float get_cube_coord(enum cube_coord coord, unsigned int x, unsigned int y, unsigned int size)
1102 {
1103     switch (coord)
1104     {
1105         case XCOORD:
1106             return x + 0.5f;
1107         case XCOORDINV:
1108             return size - x - 0.5f;
1109         case YCOORD:
1110             return y + 0.5f;
1111         case YCOORDINV:
1112             return size - y - 0.5f;
1113         case ZERO:
1114             return 0.0f;
1115         case ONE:
1116             return size;
1117        default:
1118            ERR("Unexpected coordinate value\n");
1119            return 0.0f;
1120     }
1121 }
1122
1123 HRESULT WINAPI D3DXFillCubeTexture(LPDIRECT3DCUBETEXTURE9 texture,
1124                                    LPD3DXFILL3D function,
1125                                    LPVOID funcdata)
1126 {
1127     DWORD miplevels;
1128     DWORD m, i, x, y, c, f, v;
1129     D3DSURFACE_DESC desc;
1130     D3DLOCKED_RECT lock_rect;
1131     D3DXVECTOR4 value;
1132     D3DXVECTOR3 coord, size;
1133     const PixelFormatDesc *format;
1134     BYTE *data, *pos;
1135     BYTE byte, mask;
1136     float comp_value;
1137     static const enum cube_coord coordmap[6][3] =
1138         {
1139             {ONE, YCOORDINV, XCOORDINV},
1140             {ZERO, YCOORDINV, XCOORD},
1141             {XCOORD, ONE, YCOORD},
1142             {XCOORD, ZERO, YCOORDINV},
1143             {XCOORD, YCOORDINV, ONE},
1144             {XCOORDINV, YCOORDINV, ZERO}
1145         };
1146
1147     if (texture == NULL || function == NULL)
1148         return D3DERR_INVALIDCALL;
1149
1150     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1151
1152     for (m = 0; m < miplevels; m++)
1153     {
1154         if (FAILED(IDirect3DCubeTexture9_GetLevelDesc(texture, m, &desc)))
1155             return D3DERR_INVALIDCALL;
1156
1157         format = get_format_info(desc.Format);
1158         if (format->format == D3DFMT_UNKNOWN)
1159         {
1160             FIXME("Unsupported texture format %#x\n", desc.Format);
1161             return D3DERR_INVALIDCALL;
1162         }
1163
1164         for (f = 0; f < 6; f++)
1165         {
1166             if (FAILED(IDirect3DCubeTexture9_LockRect(texture, f, m, &lock_rect, NULL, D3DLOCK_DISCARD)))
1167                 return D3DERR_INVALIDCALL;
1168
1169             size.x = (f == 0) || (f == 1) ? 0.0f : 2.0f / desc.Width;
1170             size.y = (f == 2) || (f == 3) ? 0.0f : 2.0f / desc.Width;
1171             size.z = (f == 4) || (f == 5) ? 0.0f : 2.0f / desc.Width;
1172
1173             data = lock_rect.pBits;
1174
1175             for (y = 0; y < desc.Height; y++)
1176             {
1177                 for (x = 0; x < desc.Width; x++)
1178                 {
1179                     coord.x = get_cube_coord(coordmap[f][0], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1180                     coord.y = get_cube_coord(coordmap[f][1], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1181                     coord.z = get_cube_coord(coordmap[f][2], x, y, desc.Width) / desc.Width * 2.0f - 1.0f;
1182
1183                     function(&value, &coord, &size, funcdata);
1184
1185                     pos = data + y * lock_rect.Pitch + x * format->bytes_per_pixel;
1186
1187                     for (i = 0; i < format->bytes_per_pixel; i++)
1188                         pos[i] = 0;
1189
1190                     for (c = 0; c < 4; c++)
1191                     {
1192                         switch (c)
1193                         {
1194                             case 0: /* Alpha */
1195                                 comp_value = value.w;
1196                                 break;
1197                             case 1: /* Red */
1198                                 comp_value = value.x;
1199                                 break;
1200                             case 2: /* Green */
1201                                 comp_value = value.y;
1202                                 break;
1203                             case 3: /* Blue */
1204                                 comp_value = value.z;
1205                                 break;
1206                         }
1207
1208                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1209
1210                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1211                         {
1212                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1213                             byte = (v << format->shift[c] >> i) & mask;
1214                             pos[i / 8] |= byte;
1215                         }
1216                     }
1217                 }
1218             }
1219             IDirect3DCubeTexture9_UnlockRect(texture, f, m);
1220         }
1221     }
1222
1223     return D3D_OK;
1224 }
1225
1226 HRESULT WINAPI D3DXFillVolumeTexture(LPDIRECT3DVOLUMETEXTURE9 texture,
1227                                      LPD3DXFILL3D function,
1228                                      LPVOID funcdata)
1229 {
1230     DWORD miplevels;
1231     DWORD m, i, x, y, z, c, v;
1232     D3DVOLUME_DESC desc;
1233     D3DLOCKED_BOX lock_box;
1234     D3DXVECTOR4 value;
1235     D3DXVECTOR3 coord, size;
1236     const PixelFormatDesc *format;
1237     BYTE *data, *pos;
1238     BYTE byte, mask;
1239     float comp_value;
1240
1241     if (texture == NULL || function == NULL)
1242         return D3DERR_INVALIDCALL;
1243
1244     miplevels = IDirect3DBaseTexture9_GetLevelCount(texture);
1245
1246     for (m = 0; m < miplevels; m++)
1247     {
1248         if (FAILED(IDirect3DVolumeTexture9_GetLevelDesc(texture, m, &desc)))
1249             return D3DERR_INVALIDCALL;
1250
1251         format = get_format_info(desc.Format);
1252         if (format->format == D3DFMT_UNKNOWN)
1253         {
1254             FIXME("Unsupported texture format %#x\n", desc.Format);
1255             return D3DERR_INVALIDCALL;
1256         }
1257
1258         if (FAILED(IDirect3DVolumeTexture9_LockBox(texture, m, &lock_box, NULL, D3DLOCK_DISCARD)))
1259             return D3DERR_INVALIDCALL;
1260
1261         size.x = 1.0f / desc.Width;
1262         size.y = 1.0f / desc.Height;
1263         size.z = 1.0f / desc.Depth;
1264
1265         data = lock_box.pBits;
1266
1267         for (z = 0; z < desc.Depth; z++)
1268         {
1269             /* The callback function expects the coordinates of the center
1270                of the texel */
1271             coord.z = (z + 0.5f) / desc.Depth;
1272
1273             for (y = 0; y < desc.Height; y++)
1274             {
1275                 coord.y = (y + 0.5f) / desc.Height;
1276
1277                 for (x = 0; x < desc.Width; x++)
1278                 {
1279                     coord.x = (x + 0.5f) / desc.Width;
1280
1281                     function(&value, &coord, &size, funcdata);
1282
1283                     pos = data + z * lock_box.SlicePitch + y * lock_box.RowPitch + x * format->bytes_per_pixel;
1284
1285                     for (i = 0; i < format->bytes_per_pixel; i++)
1286                         pos[i] = 0;
1287
1288                     for (c = 0; c < 4; c++)
1289                     {
1290                         switch (c)
1291                         {
1292                             case 0: /* Alpha */
1293                                 comp_value = value.w;
1294                                 break;
1295                             case 1: /* Red */
1296                                 comp_value = value.x;
1297                                 break;
1298                             case 2: /* Green */
1299                                 comp_value = value.y;
1300                                 break;
1301                             case 3: /* Blue */
1302                                 comp_value = value.z;
1303                                 break;
1304                         }
1305
1306                         v = comp_value * ((1 << format->bits[c]) - 1) + 0.5f;
1307
1308                         for (i = 0; i < format->bits[c] + format->shift[c]; i += 8)
1309                         {
1310                             mask = ((1 << format->bits[c]) - 1) << format->shift[c] >> i;
1311                             byte = (v << format->shift[c] >> i) & mask;
1312                             pos[i / 8] |= byte;
1313                         }
1314                     }
1315                 }
1316             }
1317         }
1318         IDirect3DVolumeTexture9_UnlockBox(texture, m);
1319     }
1320
1321     return D3D_OK;
1322 }