d3dx9: Fix D3DXFilterTexture return value.
[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  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "wine/unicode.h"
22 #include "wine/debug.h"
23 #include "d3dx9_36_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
26
27 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
28 static BOOL is_pow2(UINT num)
29 {
30     return !(num & (num - 1));
31 }
32
33 /* Returns the smallest power of 2 which is greater than or equal to num */
34 static UINT make_pow2(UINT num)
35 {
36     UINT result = 1;
37
38     /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */
39     if (num >= 0x80000000)
40         return 0x80000000;
41
42     while (result < num)
43         result <<= 1;
44
45     return result;
46 }
47
48 HRESULT WINAPI D3DXFilterTexture(LPDIRECT3DBASETEXTURE9 texture,
49                                  CONST PALETTEENTRY *palette,
50                                  UINT srclevel,
51                                  DWORD filter)
52 {
53     UINT level = srclevel + 1;
54     HRESULT hr;
55
56     TRACE("(%p, %p, %d, %d)\n", texture, palette, srclevel, filter);
57
58     if (!texture)
59         return D3DERR_INVALIDCALL;
60
61     if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT)
62         return D3DERR_INVALIDCALL;
63
64     if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
65         return D3DERR_INVALIDCALL;
66
67     switch (IDirect3DBaseTexture9_GetType(texture))
68     {
69         case D3DRTYPE_TEXTURE:
70         {
71             IDirect3DSurface9 *topsurf, *mipsurf;
72             D3DSURFACE_DESC desc;
73
74             if (filter == D3DX_DEFAULT)
75             {
76                 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
77
78                 if (is_pow2(desc.Width) && is_pow2(desc.Height))
79                     filter = D3DX_FILTER_BOX;
80                 else
81                     filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
82             }
83
84             hr = IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) texture, srclevel, &topsurf);
85
86             if (FAILED(hr))
87                 return D3DERR_INVALIDCALL;
88
89             while (IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) texture, level, &mipsurf) == D3D_OK)
90             {
91                 hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
92                 IDirect3DSurface9_Release(mipsurf);
93
94                 if (FAILED(hr))
95                     break;
96
97                 level++;
98             }
99
100             IDirect3DSurface9_Release(topsurf);
101
102             return D3D_OK;
103         }
104
105         default:
106             FIXME("Implement volume and cube texture filtering\n");
107             return E_NOTIMPL;
108     }
109 }
110
111 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
112                                             UINT* width,
113                                             UINT* height,
114                                             UINT* miplevels,
115                                             DWORD usage,
116                                             D3DFORMAT* format,
117                                             D3DPOOL pool)
118 {
119     UINT w = (width && *width) ? *width : 1;
120     UINT h = (height && *height) ? *height : 1;
121     D3DCAPS9 caps;
122     D3DDEVICE_CREATION_PARAMETERS params;
123     IDirect3D9 *d3d = NULL;
124     D3DDISPLAYMODE mode;
125     HRESULT hr;
126     D3DFORMAT usedformat = D3DFMT_UNKNOWN;
127
128     TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
129
130     if (!device)
131         return D3DERR_INVALIDCALL;
132
133     /* usage */
134     if (usage == D3DX_DEFAULT)
135         usage = 0;
136     if (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES))
137         return D3DERR_INVALIDCALL;
138
139     /* pool */
140     if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
141         return D3DERR_INVALIDCALL;
142
143     /* width and height */
144     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
145         return D3DERR_INVALIDCALL;
146
147     /* 256 x 256 default width/height */
148     if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
149         w = h = 256;
150     else if (w == D3DX_DEFAULT)
151         w = (height ? h : 256);
152     else if (h == D3DX_DEFAULT)
153         h = (width ? w : 256);
154
155     /* ensure width/height is power of 2 */
156     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
157         w = make_pow2(w);
158
159     if (w > caps.MaxTextureWidth)
160         w = caps.MaxTextureWidth;
161
162     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
163         h = make_pow2(h);
164
165     if (h > caps.MaxTextureHeight)
166         h = caps.MaxTextureHeight;
167
168     /* texture must be square? */
169     if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
170     {
171         if (w > h)
172             h = w;
173         else
174             w = h;
175     }
176
177     if (width)
178         *width = w;
179
180     if (height)
181         *height = h;
182
183     /* miplevels */
184     if (miplevels)
185     {
186         UINT max_mipmaps = 1;
187
188         if (!width && !height)
189             max_mipmaps = 9;    /* number of mipmaps in a 256x256 texture */
190         else
191         {
192             UINT max_dimen = max(w, h);
193
194             while (max_dimen > 1)
195             {
196                 max_dimen >>= 1;
197                 max_mipmaps++;
198             }
199         }
200
201         if (*miplevels == 0 || *miplevels > max_mipmaps)
202             *miplevels = max_mipmaps;
203     }
204
205     /* format */
206     if (format)
207     {
208         TRACE("Requested format %x\n", *format);
209         usedformat = *format;
210     }
211
212     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
213
214     if (FAILED(hr))
215         goto cleanup;
216
217     hr = IDirect3DDevice9_GetCreationParameters(device, &params);
218
219     if (FAILED(hr))
220         goto cleanup;
221
222     hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
223
224     if (FAILED(hr))
225         goto cleanup;
226
227     if ((usedformat == D3DFMT_UNKNOWN) || (usedformat == D3DX_DEFAULT))
228         usedformat = D3DFMT_A8R8G8B8;
229
230     hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format,
231         usage, D3DRTYPE_TEXTURE, usedformat);
232
233     if (FAILED(hr))
234     {
235         /* Heuristic to choose the fallback format */
236         const PixelFormatDesc *fmt = get_format_info(usedformat);
237         BOOL allow_24bits;
238         int bestscore = INT_MIN, i = 0, j;
239         unsigned int channels;
240         const PixelFormatDesc *curfmt;
241
242         if (!fmt)
243         {
244             FIXME("Pixel format %x not handled\n", usedformat);
245             goto cleanup;
246         }
247
248         allow_24bits = fmt->bytes_per_pixel == 3;
249         channels = (fmt->bits[0] ? 1 : 0) + (fmt->bits[1] ? 1 : 0)
250             + (fmt->bits[2] ? 1 : 0) + (fmt->bits[3] ? 1 : 0);
251         usedformat = D3DFMT_UNKNOWN;
252
253         while ((curfmt = get_format_info_idx(i)))
254         {
255             unsigned int curchannels = (curfmt->bits[0] ? 1 : 0) + (curfmt->bits[1] ? 1 : 0)
256                 + (curfmt->bits[2] ? 1 : 0) + (curfmt->bits[3] ? 1 : 0);
257             int score;
258
259             i++;
260
261             if (curchannels < channels)
262                 continue;
263             if (curfmt->bytes_per_pixel == 3 && !allow_24bits)
264                 continue;
265
266             hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType,
267                 mode.Format, usage, D3DRTYPE_TEXTURE, curfmt->format);
268             if (FAILED(hr))
269                 continue;
270
271             /* This format can be used, let's evaluate it.
272                Weights chosen quite arbitrarily... */
273             score = 16 - 4 * (curchannels - channels);
274
275             for (j = 0; j < 4; j++)
276             {
277                 int diff = curfmt->bits[j] - fmt->bits[j];
278                 score += 16 - (diff < 0 ? -diff * 4 : diff);
279             }
280
281             if (score > bestscore)
282             {
283                 bestscore = score;
284                 usedformat = curfmt->format;
285             }
286         }
287         hr = D3D_OK;
288     }
289
290 cleanup:
291
292     if (d3d)
293         IDirect3D9_Release(d3d);
294
295     if (FAILED(hr))
296         return hr;
297
298     if (usedformat == D3DFMT_UNKNOWN)
299     {
300         WARN("Couldn't find a suitable pixel format\n");
301         return D3DERR_NOTAVAILABLE;
302     }
303
304     TRACE("Format chosen: %x\n", usedformat);
305     if (format)
306         *format = usedformat;
307
308     return D3D_OK;
309 }
310
311 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
312                                  UINT width,
313                                  UINT height,
314                                  UINT miplevels,
315                                  DWORD usage,
316                                  D3DFORMAT format,
317                                  D3DPOOL pool,
318                                  LPDIRECT3DTEXTURE9 *ppTexture)
319 {
320     HRESULT hr;
321
322     TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
323         pool, ppTexture);
324
325     if (!pDevice || !ppTexture)
326         return D3DERR_INVALIDCALL;
327
328     hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
329
330     if (FAILED(hr))
331         return hr;
332
333     return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
334 }
335
336 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
337                                                    LPCVOID srcdata,
338                                                    UINT srcdatasize,
339                                                    UINT width,
340                                                    UINT height,
341                                                    UINT miplevels,
342                                                    DWORD usage,
343                                                    D3DFORMAT format,
344                                                    D3DPOOL pool,
345                                                    DWORD filter,
346                                                    DWORD mipfilter,
347                                                    D3DCOLOR colorkey,
348                                                    D3DXIMAGE_INFO* srcinfo,
349                                                    PALETTEENTRY* palette,
350                                                    LPDIRECT3DTEXTURE9* texture)
351 {
352     IDirect3DTexture9 **texptr;
353     IDirect3DTexture9 *buftex;
354     IDirect3DSurface9 *surface;
355     BOOL file_width = FALSE, file_height = FALSE;
356     BOOL file_format = FALSE, file_miplevels = FALSE;
357     D3DXIMAGE_INFO imginfo;
358     D3DCAPS9 caps;
359     HRESULT hr;
360
361     TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device, srcdata, srcdatasize, width,
362         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
363
364     /* check for invalid parameters */
365     if (!device || !texture || !srcdata || !srcdatasize)
366         return D3DERR_INVALIDCALL;
367
368     hr = D3DXGetImageInfoFromFileInMemory(srcdata, srcdatasize, &imginfo);
369
370     if (FAILED(hr))
371     {
372         *texture = NULL;
373         return hr;
374     }
375
376     /* handle default values */
377     if (width == 0 || width == D3DX_DEFAULT_NONPOW2)
378         width = imginfo.Width;
379
380     if (height == 0 || height == D3DX_DEFAULT_NONPOW2)
381         height = imginfo.Height;
382
383     if (width == D3DX_DEFAULT)
384         width = make_pow2(imginfo.Width);
385
386     if (height == D3DX_DEFAULT)
387         height = make_pow2(imginfo.Height);
388
389     if (format == D3DFMT_UNKNOWN || format == D3DX_DEFAULT)
390         format = imginfo.Format;
391
392     if (width == D3DX_FROM_FILE)
393     {
394         file_width = TRUE;
395         width = imginfo.Width;
396     }
397
398     if (height == D3DX_FROM_FILE)
399     {
400         file_height = TRUE;
401         height = imginfo.Height;
402     }
403
404     if (format == D3DFMT_FROM_FILE)
405     {
406         file_format = TRUE;
407         format = imginfo.Format;
408     }
409
410     if (miplevels == D3DX_FROM_FILE)
411     {
412         file_miplevels = TRUE;
413         miplevels = imginfo.MipLevels;
414     }
415
416     /* fix texture creation parameters */
417     hr = D3DXCheckTextureRequirements(device, &width, &height, &miplevels, usage, &format, pool);
418
419     if (FAILED(hr))
420     {
421         *texture = NULL;
422         return hr;
423     }
424
425     if (((file_width) && (width != imginfo.Width))    ||
426         ((file_height) && (height != imginfo.Height)) ||
427         ((file_format) && (format != imginfo.Format)) ||
428         ((file_miplevels) && (miplevels != imginfo.MipLevels)))
429     {
430         return D3DERR_NOTAVAILABLE;
431     }
432
433     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
434         return D3DERR_INVALIDCALL;
435
436     /* Create the to-be-filled texture */
437     if ((caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) && (pool != D3DPOOL_DEFAULT) && (usage != D3DUSAGE_DYNAMIC))
438     {
439         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
440         texptr = texture;
441     }
442     else
443     {
444         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
445         texptr = &buftex;
446     }
447
448     if (FAILED(hr))
449     {
450         *texture = NULL;
451         return hr;
452     }
453
454     /* Load the file */
455     IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
456     hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
457     IDirect3DSurface9_Release(surface);
458
459     if (FAILED(hr))
460     {
461         IDirect3DTexture9_Release(*texptr);
462         *texture = NULL;
463         return hr;
464     }
465
466     hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, 0, mipfilter);
467
468     if (FAILED(hr))
469     {
470         IDirect3DTexture9_Release(*texptr);
471         *texture = NULL;
472         return hr;
473     }
474
475     /* Move the data to the actual texture if necessary */
476     if (texptr == &buftex)
477     {
478         hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, pool, texture);
479
480         if (FAILED(hr))
481         {
482             IDirect3DTexture9_Release(buftex);
483             *texture = NULL;
484             return hr;
485         }
486
487         IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
488         IDirect3DTexture9_Release(buftex);
489     }
490
491     if (srcinfo)
492         *srcinfo = imginfo;
493
494     return D3D_OK;
495 }
496
497 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
498                                                  LPCVOID srcdata,
499                                                  UINT srcdatasize,
500                                                  LPDIRECT3DTEXTURE9 *texture)
501 {
502     TRACE("(%p, %p, %d, %p)\n", device, srcdata, srcdatasize, texture);
503
504     return D3DXCreateTextureFromFileInMemoryEx(device, srcdata, srcdatasize, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
505                                                D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
506 }
507
508 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
509                                             LPCWSTR srcfile,
510                                             UINT width,
511                                             UINT height,
512                                             UINT miplevels,
513                                             DWORD usage,
514                                             D3DFORMAT format,
515                                             D3DPOOL pool,
516                                             DWORD filter,
517                                             DWORD mipfilter,
518                                             D3DCOLOR colorkey,
519                                             D3DXIMAGE_INFO *srcinfo,
520                                             PALETTEENTRY *palette,
521                                             LPDIRECT3DTEXTURE9 *texture)
522 {
523     HRESULT hr;
524     DWORD size;
525     LPVOID buffer;
526
527     TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_w(srcfile), width,
528         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
529
530     if (!srcfile)
531         return D3DERR_INVALIDCALL;
532
533     hr = map_view_of_file(srcfile, &buffer, &size);
534     if (FAILED(hr))
535         return D3DXERR_INVALIDDATA;
536
537     hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
538         filter, mipfilter, colorkey, srcinfo, palette, texture);
539
540     UnmapViewOfFile(buffer);
541
542     return hr;
543 }
544
545 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
546                                             LPCSTR srcfile,
547                                             UINT width,
548                                             UINT height,
549                                             UINT miplevels,
550                                             DWORD usage,
551                                             D3DFORMAT format,
552                                             D3DPOOL pool,
553                                             DWORD filter,
554                                             DWORD mipfilter,
555                                             D3DCOLOR colorkey,
556                                             D3DXIMAGE_INFO *srcinfo,
557                                             PALETTEENTRY *palette,
558                                             LPDIRECT3DTEXTURE9 *texture)
559 {
560     LPWSTR widename;
561     HRESULT hr;
562     DWORD len;
563
564     TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_a(srcfile), width,
565         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
566
567     if (!device || !srcfile || !texture)
568         return D3DERR_INVALIDCALL;
569
570     len = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0);
571     widename = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
572     MultiByteToWideChar(CP_ACP, 0, srcfile, -1, widename, len);
573
574     hr = D3DXCreateTextureFromFileExW(device, widename, width, height, miplevels,
575                                       usage, format, pool, filter, mipfilter,
576                                       colorkey, srcinfo, palette, texture);
577
578     HeapFree(GetProcessHeap(), 0, widename);
579     return hr;
580 }
581
582 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
583                                           LPCSTR srcfile,
584                                           LPDIRECT3DTEXTURE9 *texture)
585 {
586     TRACE("(%p, %s, %p)\n", device, debugstr_a(srcfile), texture);
587
588     return D3DXCreateTextureFromFileExA(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
589                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
590 }
591
592 HRESULT WINAPI D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device,
593                                           LPCWSTR srcfile,
594                                           LPDIRECT3DTEXTURE9 *texture)
595 {
596     TRACE("(%p, %s, %p)\n", device, debugstr_w(srcfile), texture);
597
598     return D3DXCreateTextureFromFileExW(device, srcfile, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
599                                         D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
600 }
601
602
603 HRESULT WINAPI D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device,
604                                               HMODULE srcmodule,
605                                               LPCSTR resource,
606                                               LPDIRECT3DTEXTURE9 *texture)
607 {
608     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
609
610     return D3DXCreateTextureFromResourceExA(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
611                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
612 }
613
614 HRESULT WINAPI D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device,
615                                               HMODULE srcmodule,
616                                               LPCWSTR resource,
617                                               LPDIRECT3DTEXTURE9 *texture)
618 {
619     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
620
621     return D3DXCreateTextureFromResourceExW(device, srcmodule, resource, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN,
622                                             D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, texture);
623 }
624
625 HRESULT WINAPI D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device,
626                                                 HMODULE srcmodule,
627                                                 LPCSTR resource,
628                                                 UINT width,
629                                                 UINT height,
630                                                 UINT miplevels,
631                                                 DWORD usage,
632                                                 D3DFORMAT format,
633                                                 D3DPOOL pool,
634                                                 DWORD filter,
635                                                 DWORD mipfilter,
636                                                 D3DCOLOR colorkey,
637                                                 D3DXIMAGE_INFO *srcinfo,
638                                                 PALETTEENTRY *palette,
639                                                 LPDIRECT3DTEXTURE9 *texture)
640 {
641     HRSRC resinfo;
642
643     TRACE("(%p, %s): relay\n", srcmodule, debugstr_a(resource));
644
645     if (!device || !texture)
646         return D3DERR_INVALIDCALL;
647
648     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_RCDATA);
649
650     if (resinfo)
651     {
652         LPVOID buffer;
653         HRESULT hr;
654         DWORD size;
655
656         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
657
658         if (FAILED(hr))
659             return D3DXERR_INVALIDDATA;
660
661         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
662                                                    height, miplevels, usage, format,
663                                                    pool, filter, mipfilter, colorkey,
664                                                    srcinfo, palette, texture);
665     }
666
667     /* Try loading the resource as bitmap data */
668     resinfo = FindResourceA(srcmodule, resource, (LPCSTR) RT_BITMAP);
669
670     if (resinfo)
671     {
672         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
673         return E_NOTIMPL;
674     }
675
676     return D3DXERR_INVALIDDATA;
677 }
678
679 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
680                                                 HMODULE srcmodule,
681                                                 LPCWSTR resource,
682                                                 UINT width,
683                                                 UINT height,
684                                                 UINT miplevels,
685                                                 DWORD usage,
686                                                 D3DFORMAT format,
687                                                 D3DPOOL pool,
688                                                 DWORD filter,
689                                                 DWORD mipfilter,
690                                                 D3DCOLOR colorkey,
691                                                 D3DXIMAGE_INFO *srcinfo,
692                                                 PALETTEENTRY *palette,
693                                                 LPDIRECT3DTEXTURE9 *texture)
694 {
695     HRSRC resinfo;
696
697     TRACE("(%p, %s): relay\n", srcmodule, debugstr_w(resource));
698
699     if (!device || !texture)
700         return D3DERR_INVALIDCALL;
701
702     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_RCDATA);
703
704     if (resinfo)
705     {
706         LPVOID buffer;
707         HRESULT hr;
708         DWORD size;
709
710         hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
711
712         if (FAILED(hr))
713             return D3DXERR_INVALIDDATA;
714
715         return D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width,
716                                                    height, miplevels, usage, format,
717                                                    pool, filter, mipfilter, colorkey,
718                                                    srcinfo, palette, texture);
719     }
720
721     /* Try loading the resource as bitmap data */
722     resinfo = FindResourceW(srcmodule, resource, (LPCWSTR) RT_BITMAP);
723
724     if (resinfo)
725     {
726         FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
727         return E_NOTIMPL;
728     }
729
730     return D3DXERR_INVALIDDATA;
731 }