d3dx9/tests: Implement additional texture requirement tests.
[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/debug.h"
22 #include "d3dx9_36_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
25
26 /* Returns TRUE if num is a power of 2, FALSE if not, or if 0 */
27 BOOL is_pow2(UINT num)
28 {
29     return !(num & (num - 1));
30 }
31
32 /* Returns the smallest power of 2 which is greater than or equal to num */
33 UINT make_pow2(UINT num)
34 {
35     UINT result = 1;
36
37     /* In the unlikely event somebody passes a large value, make sure we don't enter an infinite loop */
38     if (num >= 0x80000000)
39         return 0x80000000;
40
41     while (result < num)
42         result <<= 1;
43
44     return result;
45 }
46
47 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
48                                             UINT* width,
49                                             UINT* height,
50                                             UINT* miplevels,
51                                             DWORD usage,
52                                             D3DFORMAT* format,
53                                             D3DPOOL pool)
54 {
55     UINT w = (width && *width) ? *width : 1;
56     UINT h = (height && *height) ? *height : 1;
57     D3DCAPS9 caps;
58
59     TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
60
61     if (!device)
62         return D3DERR_INVALIDCALL;
63
64     /* usage */
65     if ((usage != D3DX_DEFAULT) &&
66         (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES)))
67         return D3DERR_INVALIDCALL;
68
69     /* pool */
70     if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
71         return D3DERR_INVALIDCALL;
72
73     /* width and height */
74     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
75         return D3DERR_INVALIDCALL;
76
77     /* 256 x 256 default width/height */
78     if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
79         w = h = 256;
80     else if (w == D3DX_DEFAULT)
81         w = (height ? h : 256);
82     else if (h == D3DX_DEFAULT)
83         h = (width ? w : 256);
84
85     /* ensure width/height is power of 2 */
86     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
87         w = make_pow2(w);
88
89     if (w > caps.MaxTextureWidth)
90         w = caps.MaxTextureWidth;
91
92     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
93         h = make_pow2(h);
94
95     if (h > caps.MaxTextureHeight)
96         h = caps.MaxTextureHeight;
97
98     /* texture must be square? */
99     if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
100     {
101         if (w > h)
102             h = w;
103         else
104             w = h;
105     }
106
107     if (width)
108         *width = w;
109
110     if (height)
111         *height = h;
112
113     /* miplevels */
114     if (miplevels)
115     {
116         UINT max_mipmaps = 1;
117
118         if (!width && !height)
119             max_mipmaps = 9;    /* number of mipmaps in a 256x256 texture */
120         else
121         {
122             UINT max_dimen = max(w, h);
123
124             while (max_dimen > 1)
125             {
126                 max_dimen >>= 1;
127                 max_mipmaps++;
128             }
129         }
130
131         if (*miplevels == 0 || *miplevels > max_mipmaps)
132             *miplevels = max_mipmaps;
133     }
134
135     /* format */
136     if (format)
137     {
138         D3DDEVICE_CREATION_PARAMETERS params;
139         IDirect3D9 *d3d = NULL;
140         D3DDISPLAYMODE mode;
141         HRESULT hr;
142
143         hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
144
145         if (FAILED(hr))
146             goto cleanup;
147
148         hr = IDirect3DDevice9_GetCreationParameters(device, &params);
149
150         if (FAILED(hr))
151             goto cleanup;
152
153         hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
154
155         if (FAILED(hr))
156             goto cleanup;
157
158         if ((*format == D3DFMT_UNKNOWN) || (*format == D3DX_DEFAULT))
159             *format = D3DFMT_A8R8G8B8;
160
161         hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format, usage,
162             D3DRTYPE_TEXTURE, *format);
163
164         if (FAILED(hr))
165             FIXME("Pixel format adjustment not implemented yet\n");
166
167 cleanup:
168
169         if (d3d)
170             IDirect3D9_Release(d3d);
171
172         if (FAILED(hr))
173             return D3DERR_INVALIDCALL;
174     }
175
176     return D3D_OK;
177 }
178
179 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
180                                  UINT width,
181                                  UINT height,
182                                  UINT miplevels,
183                                  DWORD usage,
184                                  D3DFORMAT format,
185                                  D3DPOOL pool,
186                                  LPDIRECT3DTEXTURE9 *ppTexture)
187 {
188     FIXME("(%p, %u, %u, %u, %x, %x, %x, %p): semi-stub\n", pDevice, width, height, miplevels, usage, format,
189         pool, ppTexture);
190
191     return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
192 }
193
194 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
195                                                    LPCVOID srcdata,
196                                                    UINT srcdatasize,
197                                                    UINT width,
198                                                    UINT height,
199                                                    UINT miplevels,
200                                                    DWORD usage,
201                                                    D3DFORMAT format,
202                                                    D3DPOOL pool,
203                                                    DWORD filter,
204                                                    DWORD mipfilter,
205                                                    D3DCOLOR colorkey,
206                                                    D3DXIMAGE_INFO* srcinfo,
207                                                    PALETTEENTRY* palette,
208                                                    LPDIRECT3DTEXTURE9* texture)
209 {
210     FIXME("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): stub\n", device, srcdata, srcdatasize, width,
211         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
212
213     return E_NOTIMPL;
214 }
215
216 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
217                                             LPCWSTR srcfile,
218                                             UINT width,
219                                             UINT height,
220                                             UINT miplevels,
221                                             DWORD usage,
222                                             D3DFORMAT format,
223                                             D3DPOOL pool,
224                                             DWORD filter,
225                                             DWORD mipfilter,
226                                             D3DCOLOR colorkey,
227                                             D3DXIMAGE_INFO *srcinfo,
228                                             PALETTEENTRY *palette,
229                                             LPDIRECT3DTEXTURE9 *texture)
230 {
231     HRESULT hr;
232     DWORD size;
233     LPVOID buffer;
234
235     TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_w(srcfile), width,
236         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
237
238     if (!srcfile)
239         return D3DERR_INVALIDCALL;
240
241     hr = map_view_of_file(srcfile, &buffer, &size);
242     if (FAILED(hr))
243         return D3DXERR_INVALIDDATA;
244
245     hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
246         filter, mipfilter, colorkey, srcinfo, palette, texture);
247
248     UnmapViewOfFile(buffer);
249
250     return hr;
251 }
252
253 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
254                                           LPCSTR srcfile,
255                                           LPDIRECT3DTEXTURE9 *texture)
256 {
257     FIXME("(%p, %s, %p): stub\n", device, debugstr_a(srcfile), texture);
258
259     return E_NOTIMPL;
260 }