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