2 * Copyright 2009 Tony Wasserka
3 * Copyright 2010 Christian Costa
4 * Copyright 2010 Owen Rudge for CodeWeavers
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.
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.
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
21 #include "wine/unicode.h"
22 #include "wine/debug.h"
23 #include "d3dx9_36_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
27 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
28 static BOOL
is_pow2(UINT num
)
30 return !(num
& (num
- 1));
33 /* Returns the smallest power of 2 which is greater than or equal to num */
34 static UINT
make_pow2(UINT num
)
38 /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */
39 if (num
>= 0x80000000)
48 HRESULT WINAPI
D3DXFilterTexture(LPDIRECT3DBASETEXTURE9 texture
,
49 CONST PALETTEENTRY
*palette
,
53 UINT level
= srclevel
+ 1;
56 TRACE("(%p, %p, %d, %d)\n", texture
, palette
, srclevel
, filter
);
59 return D3DERR_INVALIDCALL
;
61 if ((filter
& 0xFFFF) > D3DX_FILTER_BOX
&& filter
!= D3DX_DEFAULT
)
62 return D3DERR_INVALIDCALL
;
64 if (srclevel
>= IDirect3DBaseTexture9_GetLevelCount(texture
))
65 return D3DERR_INVALIDCALL
;
67 switch (IDirect3DBaseTexture9_GetType(texture
))
69 case D3DRTYPE_TEXTURE
:
71 IDirect3DSurface9
*topsurf
, *mipsurf
;
74 if (filter
== D3DX_DEFAULT
)
76 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9
*) texture
, srclevel
, &desc
);
78 if (is_pow2(desc
.Width
) && is_pow2(desc
.Height
))
79 filter
= D3DX_FILTER_BOX
;
81 filter
= D3DX_FILTER_BOX
| D3DX_FILTER_DITHER
;
84 hr
= IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9
*) texture
, srclevel
, &topsurf
);
87 return D3DERR_INVALIDCALL
;
89 while (IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9
*) texture
, level
, &mipsurf
) == D3D_OK
)
91 hr
= D3DXLoadSurfaceFromSurface(mipsurf
, palette
, NULL
, topsurf
, palette
, NULL
, filter
, 0);
92 IDirect3DSurface9_Release(mipsurf
);
100 IDirect3DSurface9_Release(topsurf
);
102 if (level
== srclevel
+ 1)
103 return D3DERR_INVALIDCALL
;
109 FIXME("Implement volume and cube texture filtering\n");
114 HRESULT WINAPI
D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device
,
122 UINT w
= (width
&& *width
) ? *width
: 1;
123 UINT h
= (height
&& *height
) ? *height
: 1;
126 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device
, width
, height
, miplevels
, usage
, format
, pool
);
129 return D3DERR_INVALIDCALL
;
132 if ((usage
!= D3DX_DEFAULT
) &&
133 (usage
& (D3DUSAGE_WRITEONLY
| D3DUSAGE_DONOTCLIP
| D3DUSAGE_POINTS
| D3DUSAGE_RTPATCHES
| D3DUSAGE_NPATCHES
)))
134 return D3DERR_INVALIDCALL
;
137 if ((pool
!= D3DPOOL_DEFAULT
) && (pool
!= D3DPOOL_MANAGED
) && (pool
!= D3DPOOL_SYSTEMMEM
) && (pool
!= D3DPOOL_SCRATCH
))
138 return D3DERR_INVALIDCALL
;
140 /* width and height */
141 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device
, &caps
)))
142 return D3DERR_INVALIDCALL
;
144 /* 256 x 256 default width/height */
145 if ((w
== D3DX_DEFAULT
) && (h
== D3DX_DEFAULT
))
147 else if (w
== D3DX_DEFAULT
)
148 w
= (height
? h
: 256);
149 else if (h
== D3DX_DEFAULT
)
150 h
= (width
? w
: 256);
152 /* ensure width/height is power of 2 */
153 if ((caps
.TextureCaps
& D3DPTEXTURECAPS_POW2
) && (!is_pow2(w
)))
156 if (w
> caps
.MaxTextureWidth
)
157 w
= caps
.MaxTextureWidth
;
159 if ((caps
.TextureCaps
& D3DPTEXTURECAPS_POW2
) && (!is_pow2(h
)))
162 if (h
> caps
.MaxTextureHeight
)
163 h
= caps
.MaxTextureHeight
;
165 /* texture must be square? */
166 if (caps
.TextureCaps
& D3DPTEXTURECAPS_SQUAREONLY
)
183 UINT max_mipmaps
= 1;
185 if (!width
&& !height
)
186 max_mipmaps
= 9; /* number of mipmaps in a 256x256 texture */
189 UINT max_dimen
= max(w
, h
);
191 while (max_dimen
> 1)
198 if (*miplevels
== 0 || *miplevels
> max_mipmaps
)
199 *miplevels
= max_mipmaps
;
205 D3DDEVICE_CREATION_PARAMETERS params
;
206 IDirect3D9
*d3d
= NULL
;
210 hr
= IDirect3DDevice9_GetDirect3D(device
, &d3d
);
215 hr
= IDirect3DDevice9_GetCreationParameters(device
, ¶ms
);
220 hr
= IDirect3DDevice9_GetDisplayMode(device
, 0, &mode
);
225 if ((*format
== D3DFMT_UNKNOWN
) || (*format
== D3DX_DEFAULT
))
226 *format
= D3DFMT_A8R8G8B8
;
228 hr
= IDirect3D9_CheckDeviceFormat(d3d
, params
.AdapterOrdinal
, params
.DeviceType
, mode
.Format
, usage
,
229 D3DRTYPE_TEXTURE
, *format
);
232 FIXME("Pixel format adjustment not implemented yet\n");
237 IDirect3D9_Release(d3d
);
240 return D3DERR_INVALIDCALL
;
246 HRESULT WINAPI
D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice
,
253 LPDIRECT3DTEXTURE9
*ppTexture
)
257 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice
, width
, height
, miplevels
, usage
, format
,
260 if (!pDevice
|| !ppTexture
)
261 return D3DERR_INVALIDCALL
;
263 hr
= D3DXCheckTextureRequirements(pDevice
, &width
, &height
, &miplevels
, usage
, &format
, pool
);
268 return IDirect3DDevice9_CreateTexture(pDevice
, width
, height
, miplevels
, usage
, format
, pool
, ppTexture
, NULL
);
271 HRESULT WINAPI
D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device
,
283 D3DXIMAGE_INFO
* srcinfo
,
284 PALETTEENTRY
* palette
,
285 LPDIRECT3DTEXTURE9
* texture
)
287 IDirect3DTexture9
**texptr
;
288 IDirect3DTexture9
*buftex
;
289 IDirect3DSurface9
*surface
;
290 BOOL file_width
= FALSE
, file_height
= FALSE
;
291 BOOL file_format
= FALSE
, file_miplevels
= FALSE
;
292 D3DXIMAGE_INFO imginfo
;
296 TRACE("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p)\n", device
, srcdata
, srcdatasize
, width
,
297 height
, miplevels
, usage
, format
, pool
, filter
, mipfilter
, colorkey
, srcinfo
, palette
, texture
);
299 /* check for invalid parameters */
300 if (!device
|| !texture
|| !srcdata
|| !srcdatasize
)
301 return D3DERR_INVALIDCALL
;
303 hr
= D3DXGetImageInfoFromFileInMemory(srcdata
, srcdatasize
, &imginfo
);
311 /* handle default values */
312 if (width
== 0 || width
== D3DX_DEFAULT_NONPOW2
)
313 width
= imginfo
.Width
;
315 if (height
== 0 || height
== D3DX_DEFAULT_NONPOW2
)
316 height
= imginfo
.Height
;
318 if (width
== D3DX_DEFAULT
)
319 width
= make_pow2(imginfo
.Width
);
321 if (height
== D3DX_DEFAULT
)
322 height
= make_pow2(imginfo
.Height
);
324 if (format
== D3DFMT_UNKNOWN
|| format
== D3DX_DEFAULT
)
325 format
= imginfo
.Format
;
327 if (width
== D3DX_FROM_FILE
)
330 width
= imginfo
.Width
;
333 if (height
== D3DX_FROM_FILE
)
336 height
= imginfo
.Height
;
339 if (format
== D3DFMT_FROM_FILE
)
342 format
= imginfo
.Format
;
345 if (miplevels
== D3DX_FROM_FILE
)
347 file_miplevels
= TRUE
;
348 miplevels
= imginfo
.MipLevels
;
351 /* fix texture creation parameters */
352 hr
= D3DXCheckTextureRequirements(device
, &width
, &height
, &miplevels
, usage
, &format
, pool
);
360 if (((file_width
) && (width
!= imginfo
.Width
)) ||
361 ((file_height
) && (height
!= imginfo
.Height
)) ||
362 ((file_format
) && (format
!= imginfo
.Format
)) ||
363 ((file_miplevels
) && (miplevels
!= imginfo
.MipLevels
)))
365 return D3DERR_NOTAVAILABLE
;
368 if (FAILED(IDirect3DDevice9_GetDeviceCaps(device
, &caps
)))
369 return D3DERR_INVALIDCALL
;
371 /* Create the to-be-filled texture */
372 if ((caps
.Caps2
& D3DCAPS2_DYNAMICTEXTURES
) && (pool
!= D3DPOOL_DEFAULT
) && (usage
!= D3DUSAGE_DYNAMIC
))
374 hr
= D3DXCreateTexture(device
, width
, height
, miplevels
, usage
, format
, pool
, texture
);
379 hr
= D3DXCreateTexture(device
, width
, height
, miplevels
, usage
, format
, D3DPOOL_SYSTEMMEM
, &buftex
);
390 IDirect3DTexture9_GetSurfaceLevel(*texptr
, 0, &surface
);
391 hr
= D3DXLoadSurfaceFromFileInMemory(surface
, palette
, NULL
, srcdata
, srcdatasize
, NULL
, filter
, colorkey
, NULL
);
392 IDirect3DSurface9_Release(surface
);
396 IDirect3DTexture9_Release(*texptr
);
401 hr
= D3DXFilterTexture((IDirect3DBaseTexture9
*) *texptr
, palette
, 0, mipfilter
);
405 IDirect3DTexture9_Release(*texptr
);
410 /* Move the data to the actual texture if necessary */
411 if (texptr
== &buftex
)
413 hr
= D3DXCreateTexture(device
, width
, height
, miplevels
, usage
, format
, pool
, texture
);
417 IDirect3DTexture9_Release(buftex
);
422 IDirect3DDevice9_UpdateTexture(device
, (IDirect3DBaseTexture9
*)buftex
, (IDirect3DBaseTexture9
*)(*texture
));
423 IDirect3DTexture9_Release(buftex
);
432 HRESULT WINAPI
D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device
,
435 LPDIRECT3DTEXTURE9
*texture
)
437 TRACE("(%p, %p, %d, %p)\n", device
, srcdata
, srcdatasize
, texture
);
439 return D3DXCreateTextureFromFileInMemoryEx(device
, srcdata
, srcdatasize
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, D3DFMT_UNKNOWN
,
440 D3DPOOL_MANAGED
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, NULL
, NULL
, texture
);
443 HRESULT WINAPI
D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device
,
454 D3DXIMAGE_INFO
*srcinfo
,
455 PALETTEENTRY
*palette
,
456 LPDIRECT3DTEXTURE9
*texture
)
462 TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device
, debugstr_w(srcfile
), width
,
463 height
, miplevels
, usage
, format
, pool
, filter
, mipfilter
, colorkey
, srcinfo
, palette
, texture
);
466 return D3DERR_INVALIDCALL
;
468 hr
= map_view_of_file(srcfile
, &buffer
, &size
);
470 return D3DXERR_INVALIDDATA
;
472 hr
= D3DXCreateTextureFromFileInMemoryEx(device
, buffer
, size
, width
, height
, miplevels
, usage
, format
, pool
,
473 filter
, mipfilter
, colorkey
, srcinfo
, palette
, texture
);
475 UnmapViewOfFile(buffer
);
480 HRESULT WINAPI
D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device
,
491 D3DXIMAGE_INFO
*srcinfo
,
492 PALETTEENTRY
*palette
,
493 LPDIRECT3DTEXTURE9
*texture
)
499 TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device
, debugstr_a(srcfile
), width
,
500 height
, miplevels
, usage
, format
, pool
, filter
, mipfilter
, colorkey
, srcinfo
, palette
, texture
);
502 if (!device
|| !srcfile
|| !texture
)
503 return D3DERR_INVALIDCALL
;
505 len
= MultiByteToWideChar(CP_ACP
, 0, srcfile
, -1, NULL
, 0);
506 widename
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
* sizeof(WCHAR
));
507 MultiByteToWideChar(CP_ACP
, 0, srcfile
, -1, widename
, len
);
509 hr
= D3DXCreateTextureFromFileExW(device
, widename
, width
, height
, miplevels
,
510 usage
, format
, pool
, filter
, mipfilter
,
511 colorkey
, srcinfo
, palette
, texture
);
513 HeapFree(GetProcessHeap(), 0, widename
);
517 HRESULT WINAPI
D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device
,
519 LPDIRECT3DTEXTURE9
*texture
)
521 TRACE("(%p, %s, %p)\n", device
, debugstr_a(srcfile
), texture
);
523 return D3DXCreateTextureFromFileExA(device
, srcfile
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, D3DFMT_UNKNOWN
,
524 D3DPOOL_MANAGED
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, NULL
, NULL
, texture
);
527 HRESULT WINAPI
D3DXCreateTextureFromFileW(LPDIRECT3DDEVICE9 device
,
529 LPDIRECT3DTEXTURE9
*texture
)
531 TRACE("(%p, %s, %p)\n", device
, debugstr_w(srcfile
), texture
);
533 return D3DXCreateTextureFromFileExW(device
, srcfile
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, D3DFMT_UNKNOWN
,
534 D3DPOOL_MANAGED
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, NULL
, NULL
, texture
);
538 HRESULT WINAPI
D3DXCreateTextureFromResourceA(LPDIRECT3DDEVICE9 device
,
541 LPDIRECT3DTEXTURE9
*texture
)
543 TRACE("(%p, %s): relay\n", srcmodule
, debugstr_a(resource
));
545 return D3DXCreateTextureFromResourceExA(device
, srcmodule
, resource
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, D3DFMT_UNKNOWN
,
546 D3DPOOL_MANAGED
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, NULL
, NULL
, texture
);
549 HRESULT WINAPI
D3DXCreateTextureFromResourceW(LPDIRECT3DDEVICE9 device
,
552 LPDIRECT3DTEXTURE9
*texture
)
554 TRACE("(%p, %s): relay\n", srcmodule
, debugstr_w(resource
));
556 return D3DXCreateTextureFromResourceExW(device
, srcmodule
, resource
, D3DX_DEFAULT
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, D3DFMT_UNKNOWN
,
557 D3DPOOL_MANAGED
, D3DX_DEFAULT
, D3DX_DEFAULT
, 0, NULL
, NULL
, texture
);
560 HRESULT WINAPI
D3DXCreateTextureFromResourceExA(LPDIRECT3DDEVICE9 device
,
572 D3DXIMAGE_INFO
*srcinfo
,
573 PALETTEENTRY
*palette
,
574 LPDIRECT3DTEXTURE9
*texture
)
578 TRACE("(%p, %s): relay\n", srcmodule
, debugstr_a(resource
));
580 if (!device
|| !texture
)
581 return D3DERR_INVALIDCALL
;
583 resinfo
= FindResourceA(srcmodule
, resource
, (LPCSTR
) RT_RCDATA
);
591 hr
= load_resource_into_memory(srcmodule
, resinfo
, &buffer
, &size
);
594 return D3DXERR_INVALIDDATA
;
596 return D3DXCreateTextureFromFileInMemoryEx(device
, buffer
, size
, width
,
597 height
, miplevels
, usage
, format
,
598 pool
, filter
, mipfilter
, colorkey
,
599 srcinfo
, palette
, texture
);
602 /* Try loading the resource as bitmap data */
603 resinfo
= FindResourceA(srcmodule
, resource
, (LPCSTR
) RT_BITMAP
);
607 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
611 return D3DXERR_INVALIDDATA
;
614 HRESULT WINAPI
D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device
,
626 D3DXIMAGE_INFO
*srcinfo
,
627 PALETTEENTRY
*palette
,
628 LPDIRECT3DTEXTURE9
*texture
)
632 TRACE("(%p, %s): relay\n", srcmodule
, debugstr_w(resource
));
634 if (!device
|| !texture
)
635 return D3DERR_INVALIDCALL
;
637 resinfo
= FindResourceW(srcmodule
, resource
, (LPCWSTR
) RT_RCDATA
);
645 hr
= load_resource_into_memory(srcmodule
, resinfo
, &buffer
, &size
);
648 return D3DXERR_INVALIDDATA
;
650 return D3DXCreateTextureFromFileInMemoryEx(device
, buffer
, size
, width
,
651 height
, miplevels
, usage
, format
,
652 pool
, filter
, mipfilter
, colorkey
,
653 srcinfo
, palette
, texture
);
656 /* Try loading the resource as bitmap data */
657 resinfo
= FindResourceW(srcmodule
, resource
, (LPCWSTR
) RT_BITMAP
);
661 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
665 return D3DXERR_INVALIDDATA
;