gameux/tests: Add test of storing and reading game statistics.
[wine.git] / dlls / d3dx9_36 / texture.c
blob2ebc85a4568491336130b66f529e41d219a9ee0c
1 /*
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)
36 UINT result = 1;
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;
42 while (result < num)
43 result <<= 1;
45 return result;
48 HRESULT WINAPI D3DXFilterTexture(LPDIRECT3DBASETEXTURE9 texture,
49 CONST PALETTEENTRY *palette,
50 UINT srclevel,
51 DWORD filter)
53 UINT level = srclevel + 1;
54 HRESULT hr;
56 TRACE("(%p, %p, %d, %d)\n", texture, palette, srclevel, filter);
58 if (!texture)
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;
72 D3DSURFACE_DESC desc;
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;
80 else
81 filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
84 hr = IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) texture, srclevel, &topsurf);
86 if (FAILED(hr))
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);
94 if (FAILED(hr))
95 break;
97 level++;
100 IDirect3DSurface9_Release(topsurf);
102 if (level == srclevel + 1)
103 return D3DERR_INVALIDCALL;
105 return D3D_OK;
108 default:
109 FIXME("Implement volume and cube texture filtering\n");
110 return E_NOTIMPL;
114 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
115 UINT* width,
116 UINT* height,
117 UINT* miplevels,
118 DWORD usage,
119 D3DFORMAT* format,
120 D3DPOOL pool)
122 UINT w = (width && *width) ? *width : 1;
123 UINT h = (height && *height) ? *height : 1;
124 D3DCAPS9 caps;
126 TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
128 if (!device)
129 return D3DERR_INVALIDCALL;
131 /* usage */
132 if ((usage != D3DX_DEFAULT) &&
133 (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES)))
134 return D3DERR_INVALIDCALL;
136 /* pool */
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))
146 w = h = 256;
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)))
154 w = make_pow2(w);
156 if (w > caps.MaxTextureWidth)
157 w = caps.MaxTextureWidth;
159 if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
160 h = make_pow2(h);
162 if (h > caps.MaxTextureHeight)
163 h = caps.MaxTextureHeight;
165 /* texture must be square? */
166 if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
168 if (w > h)
169 h = w;
170 else
171 w = h;
174 if (width)
175 *width = w;
177 if (height)
178 *height = h;
180 /* miplevels */
181 if (miplevels)
183 UINT max_mipmaps = 1;
185 if (!width && !height)
186 max_mipmaps = 9; /* number of mipmaps in a 256x256 texture */
187 else
189 UINT max_dimen = max(w, h);
191 while (max_dimen > 1)
193 max_dimen >>= 1;
194 max_mipmaps++;
198 if (*miplevels == 0 || *miplevels > max_mipmaps)
199 *miplevels = max_mipmaps;
202 /* format */
203 if (format)
205 D3DDEVICE_CREATION_PARAMETERS params;
206 IDirect3D9 *d3d = NULL;
207 D3DDISPLAYMODE mode;
208 HRESULT hr;
210 hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
212 if (FAILED(hr))
213 goto cleanup;
215 hr = IDirect3DDevice9_GetCreationParameters(device, &params);
217 if (FAILED(hr))
218 goto cleanup;
220 hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
222 if (FAILED(hr))
223 goto cleanup;
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);
231 if (FAILED(hr))
232 FIXME("Pixel format adjustment not implemented yet\n");
234 cleanup:
236 if (d3d)
237 IDirect3D9_Release(d3d);
239 if (FAILED(hr))
240 return D3DERR_INVALIDCALL;
243 return D3D_OK;
246 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
247 UINT width,
248 UINT height,
249 UINT miplevels,
250 DWORD usage,
251 D3DFORMAT format,
252 D3DPOOL pool,
253 LPDIRECT3DTEXTURE9 *ppTexture)
255 HRESULT hr;
257 TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
258 pool, ppTexture);
260 if (!pDevice || !ppTexture)
261 return D3DERR_INVALIDCALL;
263 hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
265 if (FAILED(hr))
266 return hr;
268 return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
271 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
272 LPCVOID srcdata,
273 UINT srcdatasize,
274 UINT width,
275 UINT height,
276 UINT miplevels,
277 DWORD usage,
278 D3DFORMAT format,
279 D3DPOOL pool,
280 DWORD filter,
281 DWORD mipfilter,
282 D3DCOLOR colorkey,
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;
293 D3DCAPS9 caps;
294 HRESULT hr;
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);
305 if (FAILED(hr))
307 *texture = NULL;
308 return hr;
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)
329 file_width = TRUE;
330 width = imginfo.Width;
333 if (height == D3DX_FROM_FILE)
335 file_height = TRUE;
336 height = imginfo.Height;
339 if (format == D3DFMT_FROM_FILE)
341 file_format = TRUE;
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);
354 if (FAILED(hr))
356 *texture = NULL;
357 return hr;
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);
375 texptr = texture;
377 else
379 hr = D3DXCreateTexture(device, width, height, miplevels, usage, format, D3DPOOL_SYSTEMMEM, &buftex);
380 texptr = &buftex;
383 if (FAILED(hr))
385 *texture = NULL;
386 return hr;
389 /* Load the file */
390 IDirect3DTexture9_GetSurfaceLevel(*texptr, 0, &surface);
391 hr = D3DXLoadSurfaceFromFileInMemory(surface, palette, NULL, srcdata, srcdatasize, NULL, filter, colorkey, NULL);
392 IDirect3DSurface9_Release(surface);
394 if (FAILED(hr))
396 IDirect3DTexture9_Release(*texptr);
397 *texture = NULL;
398 return hr;
401 hr = D3DXFilterTexture((IDirect3DBaseTexture9*) *texptr, palette, 0, mipfilter);
403 if (FAILED(hr))
405 IDirect3DTexture9_Release(*texptr);
406 *texture = NULL;
407 return hr;
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);
415 if (FAILED(hr))
417 IDirect3DTexture9_Release(buftex);
418 *texture = NULL;
419 return hr;
422 IDirect3DDevice9_UpdateTexture(device, (IDirect3DBaseTexture9*)buftex, (IDirect3DBaseTexture9*)(*texture));
423 IDirect3DTexture9_Release(buftex);
426 if (srcinfo)
427 *srcinfo = imginfo;
429 return D3D_OK;
432 HRESULT WINAPI D3DXCreateTextureFromFileInMemory(LPDIRECT3DDEVICE9 device,
433 LPCVOID srcdata,
434 UINT srcdatasize,
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,
444 LPCWSTR srcfile,
445 UINT width,
446 UINT height,
447 UINT miplevels,
448 DWORD usage,
449 D3DFORMAT format,
450 D3DPOOL pool,
451 DWORD filter,
452 DWORD mipfilter,
453 D3DCOLOR colorkey,
454 D3DXIMAGE_INFO *srcinfo,
455 PALETTEENTRY *palette,
456 LPDIRECT3DTEXTURE9 *texture)
458 HRESULT hr;
459 DWORD size;
460 LPVOID buffer;
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);
465 if (!srcfile)
466 return D3DERR_INVALIDCALL;
468 hr = map_view_of_file(srcfile, &buffer, &size);
469 if (FAILED(hr))
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);
477 return hr;
480 HRESULT WINAPI D3DXCreateTextureFromFileExA(LPDIRECT3DDEVICE9 device,
481 LPCSTR srcfile,
482 UINT width,
483 UINT height,
484 UINT miplevels,
485 DWORD usage,
486 D3DFORMAT format,
487 D3DPOOL pool,
488 DWORD filter,
489 DWORD mipfilter,
490 D3DCOLOR colorkey,
491 D3DXIMAGE_INFO *srcinfo,
492 PALETTEENTRY *palette,
493 LPDIRECT3DTEXTURE9 *texture)
495 LPWSTR widename;
496 HRESULT hr;
497 DWORD len;
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);
514 return hr;
517 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
518 LPCSTR srcfile,
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,
528 LPCWSTR srcfile,
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,
539 HMODULE srcmodule,
540 LPCSTR resource,
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,
550 HMODULE srcmodule,
551 LPCWSTR resource,
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,
561 HMODULE srcmodule,
562 LPCSTR resource,
563 UINT width,
564 UINT height,
565 UINT miplevels,
566 DWORD usage,
567 D3DFORMAT format,
568 D3DPOOL pool,
569 DWORD filter,
570 DWORD mipfilter,
571 D3DCOLOR colorkey,
572 D3DXIMAGE_INFO *srcinfo,
573 PALETTEENTRY *palette,
574 LPDIRECT3DTEXTURE9 *texture)
576 HRSRC resinfo;
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);
585 if (resinfo)
587 LPVOID buffer;
588 HRESULT hr;
589 DWORD size;
591 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
593 if (FAILED(hr))
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);
605 if (resinfo)
607 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
608 return E_NOTIMPL;
611 return D3DXERR_INVALIDDATA;
614 HRESULT WINAPI D3DXCreateTextureFromResourceExW(LPDIRECT3DDEVICE9 device,
615 HMODULE srcmodule,
616 LPCWSTR resource,
617 UINT width,
618 UINT height,
619 UINT miplevels,
620 DWORD usage,
621 D3DFORMAT format,
622 D3DPOOL pool,
623 DWORD filter,
624 DWORD mipfilter,
625 D3DCOLOR colorkey,
626 D3DXIMAGE_INFO *srcinfo,
627 PALETTEENTRY *palette,
628 LPDIRECT3DTEXTURE9 *texture)
630 HRSRC resinfo;
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);
639 if (resinfo)
641 LPVOID buffer;
642 HRESULT hr;
643 DWORD size;
645 hr = load_resource_into_memory(srcmodule, resinfo, &buffer, &size);
647 if (FAILED(hr))
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);
659 if (resinfo)
661 FIXME("Implement loading bitmaps from resource type RT_BITMAP\n");
662 return E_NOTIMPL;
665 return D3DXERR_INVALIDDATA;