windowscodecs: Handle TIFF's with RowsPerStrip greater than Height.
[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 D3DXFilterTexture(LPDIRECT3DBASETEXTURE9 texture,
48                                  CONST PALETTEENTRY *palette,
49                                  UINT srclevel,
50                                  DWORD filter)
51 {
52     UINT level = srclevel + 1;
53     HRESULT hr;
54
55     TRACE("(%p, %p, %d, %d)\n", texture, palette, srclevel, filter);
56
57     if (!texture)
58         return D3DERR_INVALIDCALL;
59
60     if ((filter & 0xFFFF) > D3DX_FILTER_BOX && filter != D3DX_DEFAULT)
61         return D3DERR_INVALIDCALL;
62
63     if (srclevel >= IDirect3DBaseTexture9_GetLevelCount(texture))
64         return D3DERR_INVALIDCALL;
65
66     switch (IDirect3DBaseTexture9_GetType(texture))
67     {
68         case D3DRTYPE_TEXTURE:
69         {
70             IDirect3DSurface9 *topsurf, *mipsurf;
71             D3DSURFACE_DESC desc;
72
73             if (filter == D3DX_DEFAULT)
74             {
75                 IDirect3DTexture9_GetLevelDesc((IDirect3DTexture9*) texture, srclevel, &desc);
76
77                 if (is_pow2(desc.Width) && is_pow2(desc.Height))
78                     filter = D3DX_FILTER_BOX;
79                 else
80                     filter = D3DX_FILTER_BOX | D3DX_FILTER_DITHER;
81             }
82
83             hr = IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) texture, srclevel, &topsurf);
84
85             if (FAILED(hr))
86                 return D3DERR_INVALIDCALL;
87
88             while (IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9*) texture, level, &mipsurf) == D3D_OK)
89             {
90                 hr = D3DXLoadSurfaceFromSurface(mipsurf, palette, NULL, topsurf, palette, NULL, filter, 0);
91                 IDirect3DSurface9_Release(mipsurf);
92
93                 if (FAILED(hr))
94                     break;
95
96                 level++;
97             }
98
99             IDirect3DSurface9_Release(topsurf);
100
101             if (level == srclevel + 1)
102                 return D3DERR_INVALIDCALL;
103
104             return D3D_OK;
105         }
106
107         default:
108             FIXME("Implement volume and cube texture filtering\n");
109             return E_NOTIMPL;
110     }
111 }
112
113 HRESULT WINAPI D3DXCheckTextureRequirements(LPDIRECT3DDEVICE9 device,
114                                             UINT* width,
115                                             UINT* height,
116                                             UINT* miplevels,
117                                             DWORD usage,
118                                             D3DFORMAT* format,
119                                             D3DPOOL pool)
120 {
121     UINT w = (width && *width) ? *width : 1;
122     UINT h = (height && *height) ? *height : 1;
123     D3DCAPS9 caps;
124
125     TRACE("(%p, %p, %p, %p, %u, %p, %u)\n", device, width, height, miplevels, usage, format, pool);
126
127     if (!device)
128         return D3DERR_INVALIDCALL;
129
130     /* usage */
131     if ((usage != D3DX_DEFAULT) &&
132         (usage & (D3DUSAGE_WRITEONLY | D3DUSAGE_DONOTCLIP | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES | D3DUSAGE_NPATCHES)))
133         return D3DERR_INVALIDCALL;
134
135     /* pool */
136     if ((pool != D3DPOOL_DEFAULT) && (pool != D3DPOOL_MANAGED) && (pool != D3DPOOL_SYSTEMMEM) && (pool != D3DPOOL_SCRATCH))
137         return D3DERR_INVALIDCALL;
138
139     /* width and height */
140     if (FAILED(IDirect3DDevice9_GetDeviceCaps(device, &caps)))
141         return D3DERR_INVALIDCALL;
142
143     /* 256 x 256 default width/height */
144     if ((w == D3DX_DEFAULT) && (h == D3DX_DEFAULT))
145         w = h = 256;
146     else if (w == D3DX_DEFAULT)
147         w = (height ? h : 256);
148     else if (h == D3DX_DEFAULT)
149         h = (width ? w : 256);
150
151     /* ensure width/height is power of 2 */
152     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(w)))
153         w = make_pow2(w);
154
155     if (w > caps.MaxTextureWidth)
156         w = caps.MaxTextureWidth;
157
158     if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && (!is_pow2(h)))
159         h = make_pow2(h);
160
161     if (h > caps.MaxTextureHeight)
162         h = caps.MaxTextureHeight;
163
164     /* texture must be square? */
165     if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)
166     {
167         if (w > h)
168             h = w;
169         else
170             w = h;
171     }
172
173     if (width)
174         *width = w;
175
176     if (height)
177         *height = h;
178
179     /* miplevels */
180     if (miplevels)
181     {
182         UINT max_mipmaps = 1;
183
184         if (!width && !height)
185             max_mipmaps = 9;    /* number of mipmaps in a 256x256 texture */
186         else
187         {
188             UINT max_dimen = max(w, h);
189
190             while (max_dimen > 1)
191             {
192                 max_dimen >>= 1;
193                 max_mipmaps++;
194             }
195         }
196
197         if (*miplevels == 0 || *miplevels > max_mipmaps)
198             *miplevels = max_mipmaps;
199     }
200
201     /* format */
202     if (format)
203     {
204         D3DDEVICE_CREATION_PARAMETERS params;
205         IDirect3D9 *d3d = NULL;
206         D3DDISPLAYMODE mode;
207         HRESULT hr;
208
209         hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
210
211         if (FAILED(hr))
212             goto cleanup;
213
214         hr = IDirect3DDevice9_GetCreationParameters(device, &params);
215
216         if (FAILED(hr))
217             goto cleanup;
218
219         hr = IDirect3DDevice9_GetDisplayMode(device, 0, &mode);
220
221         if (FAILED(hr))
222             goto cleanup;
223
224         if ((*format == D3DFMT_UNKNOWN) || (*format == D3DX_DEFAULT))
225             *format = D3DFMT_A8R8G8B8;
226
227         hr = IDirect3D9_CheckDeviceFormat(d3d, params.AdapterOrdinal, params.DeviceType, mode.Format, usage,
228             D3DRTYPE_TEXTURE, *format);
229
230         if (FAILED(hr))
231             FIXME("Pixel format adjustment not implemented yet\n");
232
233 cleanup:
234
235         if (d3d)
236             IDirect3D9_Release(d3d);
237
238         if (FAILED(hr))
239             return D3DERR_INVALIDCALL;
240     }
241
242     return D3D_OK;
243 }
244
245 HRESULT WINAPI D3DXCreateTexture(LPDIRECT3DDEVICE9 pDevice,
246                                  UINT width,
247                                  UINT height,
248                                  UINT miplevels,
249                                  DWORD usage,
250                                  D3DFORMAT format,
251                                  D3DPOOL pool,
252                                  LPDIRECT3DTEXTURE9 *ppTexture)
253 {
254     HRESULT hr;
255
256     TRACE("(%p, %u, %u, %u, %x, %x, %x, %p)\n", pDevice, width, height, miplevels, usage, format,
257         pool, ppTexture);
258
259     if (!pDevice || !ppTexture)
260         return D3DERR_INVALIDCALL;
261
262     hr = D3DXCheckTextureRequirements(pDevice, &width, &height, &miplevels, usage, &format, pool);
263
264     if (FAILED(hr))
265         return hr;
266
267     return IDirect3DDevice9_CreateTexture(pDevice, width, height, miplevels, usage, format, pool, ppTexture, NULL);
268 }
269
270 HRESULT WINAPI D3DXCreateTextureFromFileInMemoryEx(LPDIRECT3DDEVICE9 device,
271                                                    LPCVOID srcdata,
272                                                    UINT srcdatasize,
273                                                    UINT width,
274                                                    UINT height,
275                                                    UINT miplevels,
276                                                    DWORD usage,
277                                                    D3DFORMAT format,
278                                                    D3DPOOL pool,
279                                                    DWORD filter,
280                                                    DWORD mipfilter,
281                                                    D3DCOLOR colorkey,
282                                                    D3DXIMAGE_INFO* srcinfo,
283                                                    PALETTEENTRY* palette,
284                                                    LPDIRECT3DTEXTURE9* texture)
285 {
286     FIXME("(%p, %p, %u, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): stub\n", device, srcdata, srcdatasize, width,
287         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
288
289     return E_NOTIMPL;
290 }
291
292 HRESULT WINAPI D3DXCreateTextureFromFileExW(LPDIRECT3DDEVICE9 device,
293                                             LPCWSTR srcfile,
294                                             UINT width,
295                                             UINT height,
296                                             UINT miplevels,
297                                             DWORD usage,
298                                             D3DFORMAT format,
299                                             D3DPOOL pool,
300                                             DWORD filter,
301                                             DWORD mipfilter,
302                                             D3DCOLOR colorkey,
303                                             D3DXIMAGE_INFO *srcinfo,
304                                             PALETTEENTRY *palette,
305                                             LPDIRECT3DTEXTURE9 *texture)
306 {
307     HRESULT hr;
308     DWORD size;
309     LPVOID buffer;
310
311     TRACE("(%p, %p, %u, %u, %u, %x, %x, %x, %u, %u, %x, %p, %p, %p): relay\n", device, debugstr_w(srcfile), width,
312         height, miplevels, usage, format, pool, filter, mipfilter, colorkey, srcinfo, palette, texture);
313
314     if (!srcfile)
315         return D3DERR_INVALIDCALL;
316
317     hr = map_view_of_file(srcfile, &buffer, &size);
318     if (FAILED(hr))
319         return D3DXERR_INVALIDDATA;
320
321     hr = D3DXCreateTextureFromFileInMemoryEx(device, buffer, size, width, height, miplevels, usage, format, pool,
322         filter, mipfilter, colorkey, srcinfo, palette, texture);
323
324     UnmapViewOfFile(buffer);
325
326     return hr;
327 }
328
329 HRESULT WINAPI D3DXCreateTextureFromFileA(LPDIRECT3DDEVICE9 device,
330                                           LPCSTR srcfile,
331                                           LPDIRECT3DTEXTURE9 *texture)
332 {
333     FIXME("(%p, %s, %p): stub\n", device, debugstr_a(srcfile), texture);
334
335     return E_NOTIMPL;
336 }