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