mciqtz32: Fix mciOpen.
[wine/multimedia.git] / dlls / ddraw / texture.c
blob2fc5d5076ed00003eb782bdbeb759dca64779f82
1 /* Direct3D Texture
2 * Copyright (c) 1998 Lionel ULMER
3 * Copyright (c) 2006 Stefan DÖSINGER
5 * This file contains the implementation of interface Direct3DTexture2.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdlib.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winerror.h"
36 #include "wingdi.h"
37 #include "wine/exception.h"
39 #include "ddraw.h"
40 #include "d3d.h"
42 #include "ddraw_private.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
48 /*****************************************************************************
49 * IUnknown interfaces. They are thunks to IDirectDrawSurface7
50 *****************************************************************************/
51 static HRESULT WINAPI
52 Thunk_IDirect3DTextureImpl_2_QueryInterface(IDirect3DTexture2 *iface,
53 REFIID riid,
54 void **obj)
56 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
57 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", This, debugstr_guid(riid), obj);
58 return IDirectDrawSurface7_QueryInterface((IDirectDrawSurface7 *)This, riid, obj);
61 static HRESULT WINAPI
62 Thunk_IDirect3DTextureImpl_1_QueryInterface(IDirect3DTexture *iface,
63 REFIID riid,
64 void **obj)
66 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
67 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", This, debugstr_guid(riid), obj);
69 return IDirectDrawSurface7_QueryInterface((IDirectDrawSurface7 *)This, riid, obj);
72 static ULONG WINAPI
73 Thunk_IDirect3DTextureImpl_2_AddRef(IDirect3DTexture2 *iface)
75 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
76 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
78 return IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)This);
81 static ULONG WINAPI
82 Thunk_IDirect3DTextureImpl_1_AddRef(IDirect3DTexture *iface)
84 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
85 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
87 return IDirectDrawSurface7_AddRef((IDirectDrawSurface7 *)This);
90 static ULONG WINAPI
91 Thunk_IDirect3DTextureImpl_2_Release(IDirect3DTexture2 *iface)
93 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
94 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
96 return IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This);
100 static ULONG WINAPI
101 Thunk_IDirect3DTextureImpl_1_Release(IDirect3DTexture *iface)
103 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
104 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
106 return IDirectDrawSurface7_Release((IDirectDrawSurface7 *)This);
109 /*****************************************************************************
110 * IDirect3DTexture interface
111 *****************************************************************************/
113 /*****************************************************************************
114 * IDirect3DTexture1::Initialize
116 * The sdk says it's not implemented
118 * Params:
121 * Returns
122 * DDERR_UNSUPPORTED
124 *****************************************************************************/
125 static HRESULT WINAPI
126 IDirect3DTextureImpl_1_Initialize(IDirect3DTexture *iface,
127 IDirect3DDevice *Direct3DDevice,
128 IDirectDrawSurface *DDSurface)
130 TRACE("(%p)->(%p,%p) Not implemented\n", iface, Direct3DDevice, DDSurface);
131 return DDERR_UNSUPPORTED; /* Unchecked */
134 /*****************************************************************************
135 * IDirect3DTexture2::PaletteChanged
137 * Informs the texture about a palette change
139 * Params:
140 * Start: Start index of the change
141 * Count: The number of changed entries
143 * Returns
144 * D3D_OK, because it's a stub
146 *****************************************************************************/
147 static HRESULT WINAPI
148 IDirect3DTextureImpl_PaletteChanged(IDirect3DTexture2 *iface,
149 DWORD Start,
150 DWORD Count)
152 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
153 FIXME("(%p)->(%08x,%08x): stub!\n", This, Start, Count);
154 return D3D_OK;
157 static HRESULT WINAPI
158 Thunk_IDirect3DTextureImpl_1_PaletteChanged(IDirect3DTexture *iface,
159 DWORD Start,
160 DWORD Count)
162 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
163 TRACE("(%p)->(%08x,%08x) thunking to IDirect3DTexture2 interface.\n", This, Start, Count);
165 return IDirect3DTexture2_PaletteChanged((IDirect3DTexture2 *)&This->IDirect3DTexture2_vtbl, Start, Count);
169 /*****************************************************************************
170 * IDirect3DTexture::Unload
172 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
175 * Returns:
176 * DDERR_UNSUPPORTED
178 *****************************************************************************/
179 static HRESULT WINAPI
180 IDirect3DTextureImpl_1_Unload(IDirect3DTexture *iface)
182 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
183 TRACE("(%p)->(): not implemented!\n", This);
184 return DDERR_UNSUPPORTED;
187 /*****************************************************************************
188 * IDirect3DTexture2::GetHandle
190 * Returns handle for the texture. At the moment, the interface
191 * to the IWineD3DTexture is used.
193 * Params:
194 * Direct3DDevice2: Device this handle is assigned to
195 * Handle: Address to store the handle at.
197 * Returns:
198 * D3D_OK
200 *****************************************************************************/
201 static HRESULT WINAPI
202 IDirect3DTextureImpl_GetHandle(IDirect3DTexture2 *iface,
203 IDirect3DDevice2 *Direct3DDevice2,
204 D3DTEXTUREHANDLE *lpHandle)
206 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
207 IDirect3DDeviceImpl *d3d = device_from_device2(Direct3DDevice2);
209 TRACE("(%p)->(%p,%p)\n", This, d3d, lpHandle);
211 EnterCriticalSection(&ddraw_cs);
212 if(!This->Handle)
214 DWORD h = ddraw_allocate_handle(&d3d->handle_table, This, DDRAW_HANDLE_SURFACE);
215 if (h == DDRAW_INVALID_HANDLE)
217 ERR("Failed to allocate a texture handle.\n");
218 LeaveCriticalSection(&ddraw_cs);
219 return DDERR_OUTOFMEMORY;
222 This->Handle = h + 1;
224 *lpHandle = This->Handle;
226 TRACE(" returning handle %08x.\n", *lpHandle);
228 LeaveCriticalSection(&ddraw_cs);
229 return D3D_OK;
232 static HRESULT WINAPI
233 Thunk_IDirect3DTextureImpl_1_GetHandle(IDirect3DTexture *iface,
234 LPDIRECT3DDEVICE lpDirect3DDevice,
235 LPD3DTEXTUREHANDLE lpHandle)
237 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
238 IDirect3DDeviceImpl *d3d = device_from_device1(lpDirect3DDevice);
239 IDirect3DTexture2 *d3d_texture2 = (IDirect3DTexture2 *)&This->IDirect3DTexture2_vtbl;
240 IDirect3DDevice2 *d3d_device2 = (IDirect3DDevice2 *)&d3d->IDirect3DDevice2_vtbl;
242 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", This, d3d, lpHandle);
244 return IDirect3DTexture2_GetHandle(d3d_texture2, d3d_device2, lpHandle);
248 /*****************************************************************************
249 * get_sub_mimaplevel
251 * Helper function that returns the next mipmap level
253 * tex_ptr: Surface of which to return the next level
255 *****************************************************************************/
256 static IDirectDrawSurfaceImpl *
257 get_sub_mimaplevel(IDirectDrawSurfaceImpl *tex_ptr)
259 /* Now go down the mipmap chain to the next surface */
260 static DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
261 LPDIRECTDRAWSURFACE7 next_level;
262 IDirectDrawSurfaceImpl *surf_ptr;
263 HRESULT hr;
265 hr = IDirectDrawSurface7_GetAttachedSurface((IDirectDrawSurface7 *)tex_ptr, &mipmap_caps, &next_level);
266 if (FAILED(hr)) return NULL;
268 surf_ptr = (IDirectDrawSurfaceImpl *)next_level;
269 IDirectDrawSurface7_Release(next_level);
271 return surf_ptr;
274 /*****************************************************************************
275 * IDirect3DTexture2::Load
277 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
279 * This function isn't relayed to WineD3D because the whole interface is
280 * implemented in DDraw only. For speed improvements a implementation which
281 * takes OpenGL more into account could be placed into WineD3D.
283 * Params:
284 * D3DTexture2: Address of the texture to load
286 * Returns:
287 * D3D_OK on success
288 * D3DERR_TEXTURE_LOAD_FAILED.
290 *****************************************************************************/
291 static HRESULT WINAPI
292 IDirect3DTextureImpl_Load(IDirect3DTexture2 *iface,
293 IDirect3DTexture2 *D3DTexture2)
295 IDirectDrawSurfaceImpl *This = surface_from_texture2(iface);
296 IDirectDrawSurfaceImpl *src_ptr = surface_from_texture2(D3DTexture2);
297 HRESULT ret_value = D3D_OK;
298 if(src_ptr == This)
300 TRACE("copying surface %p to surface %p, why?\n", src_ptr, This);
301 return ret_value;
304 TRACE("(%p)->(%p)\n", This, src_ptr);
305 EnterCriticalSection(&ddraw_cs);
307 if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
308 (src_ptr->surface_desc.u2.dwMipMapCount != This->surface_desc.u2.dwMipMapCount))
310 ERR("Trying to load surfaces with different mip-map counts !\n");
313 while(1)
315 IWineD3DPalette *wine_pal, *wine_pal_src;
316 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
317 DDSURFACEDESC *src_d, *dst_d;
319 TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, This, src_ptr->mipmap_level);
321 /* Suppress the ALLOCONLOAD flag */
322 This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
324 /* Get the palettes */
325 ret_value = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wine_pal);
326 if( ret_value != D3D_OK)
328 ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
329 LeaveCriticalSection(&ddraw_cs);
330 return D3DERR_TEXTURE_LOAD_FAILED;
332 if(wine_pal)
334 ret_value = IWineD3DPalette_GetParent(wine_pal, (IUnknown **) &pal);
335 if(ret_value != D3D_OK)
337 ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
338 LeaveCriticalSection(&ddraw_cs);
339 return D3DERR_TEXTURE_LOAD_FAILED;
343 ret_value = IWineD3DSurface_GetPalette(src_ptr->WineD3DSurface, &wine_pal_src);
344 if( ret_value != D3D_OK)
346 ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
347 LeaveCriticalSection(&ddraw_cs);
348 return D3DERR_TEXTURE_LOAD_FAILED;
350 if(wine_pal_src)
352 ret_value = IWineD3DPalette_GetParent(wine_pal_src, (IUnknown **) &pal_src);
353 if(ret_value != D3D_OK)
355 ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
356 if (pal) IDirectDrawPalette_Release(pal);
357 LeaveCriticalSection(&ddraw_cs);
358 return D3DERR_TEXTURE_LOAD_FAILED;
362 if (pal_src != NULL)
364 PALETTEENTRY palent[256];
366 if (pal == NULL)
368 IDirectDrawPalette_Release(pal_src);
369 LeaveCriticalSection(&ddraw_cs);
370 return DDERR_NOPALETTEATTACHED;
372 IDirectDrawPalette_GetEntries(pal_src, 0, 0, 256, palent);
373 IDirectDrawPalette_SetEntries(pal, 0, 0, 256, palent);
376 if (pal) IDirectDrawPalette_Release(pal);
377 if (pal_src) IDirectDrawPalette_Release(pal_src);
379 /* Copy one surface on the other */
380 dst_d = (DDSURFACEDESC *)&(This->surface_desc);
381 src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc);
383 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight))
385 /* Should also check for same pixel format, u1.lPitch, ... */
386 ERR("Error in surface sizes\n");
387 LeaveCriticalSection(&ddraw_cs);
388 return D3DERR_TEXTURE_LOAD_FAILED;
390 else
392 WINED3DLOCKED_RECT pSrcRect, pDstRect;
394 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
395 /* I should put a macro for the calculus of bpp */
397 /* Copy also the ColorKeying stuff */
398 if (src_d->dwFlags & DDSD_CKSRCBLT)
400 dst_d->dwFlags |= DDSD_CKSRCBLT;
401 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
402 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
405 /* Copy the main memory texture into the surface that corresponds to the OpenGL
406 texture object. */
408 ret_value = IWineD3DSurface_LockRect(src_ptr->WineD3DSurface, &pSrcRect, NULL, 0);
409 if(ret_value != D3D_OK)
411 ERR(" (%p) Locking the source surface failed\n", This);
412 LeaveCriticalSection(&ddraw_cs);
413 return D3DERR_TEXTURE_LOAD_FAILED;
416 ret_value = IWineD3DSurface_LockRect(This->WineD3DSurface, &pDstRect, NULL, 0);
417 if(ret_value != D3D_OK)
419 ERR(" (%p) Locking the destination surface failed\n", This);
420 IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
421 LeaveCriticalSection(&ddraw_cs);
422 return D3DERR_TEXTURE_LOAD_FAILED;
425 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
426 memcpy(pDstRect.pBits, pSrcRect.pBits, src_ptr->surface_desc.u1.dwLinearSize);
427 else
428 memcpy(pDstRect.pBits, pSrcRect.pBits, pSrcRect.Pitch * src_d->dwHeight);
430 IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
431 IWineD3DSurface_UnlockRect(This->WineD3DSurface);
434 if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
436 src_ptr = get_sub_mimaplevel(src_ptr);
438 else
440 src_ptr = NULL;
442 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
444 This = get_sub_mimaplevel(This);
446 else
448 This = NULL;
451 if ((src_ptr == NULL) || (This == NULL))
453 if (src_ptr != This)
455 ERR(" Loading surface with different mipmap structure !!!\n");
457 break;
461 LeaveCriticalSection(&ddraw_cs);
462 return ret_value;
465 static HRESULT WINAPI
466 Thunk_IDirect3DTextureImpl_1_Load(IDirect3DTexture *iface,
467 IDirect3DTexture *D3DTexture)
469 IDirectDrawSurfaceImpl *This = surface_from_texture1(iface);
470 IDirectDrawSurfaceImpl *Texture = surface_from_texture1(D3DTexture);
471 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", This, Texture);
473 return IDirect3DTexture2_Load((IDirect3DTexture2 *)&This->IDirect3DTexture2_vtbl,
474 D3DTexture ? (IDirect3DTexture2 *)&surface_from_texture1(D3DTexture)->IDirect3DTexture2_vtbl : NULL);
477 /*****************************************************************************
478 * The VTables
479 *****************************************************************************/
480 const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl =
482 Thunk_IDirect3DTextureImpl_2_QueryInterface,
483 Thunk_IDirect3DTextureImpl_2_AddRef,
484 Thunk_IDirect3DTextureImpl_2_Release,
485 IDirect3DTextureImpl_GetHandle,
486 IDirect3DTextureImpl_PaletteChanged,
487 IDirect3DTextureImpl_Load,
491 const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl =
493 Thunk_IDirect3DTextureImpl_1_QueryInterface,
494 Thunk_IDirect3DTextureImpl_1_AddRef,
495 Thunk_IDirect3DTextureImpl_1_Release,
496 IDirect3DTextureImpl_1_Initialize,
497 Thunk_IDirect3DTextureImpl_1_GetHandle,
498 Thunk_IDirect3DTextureImpl_1_PaletteChanged,
499 Thunk_IDirect3DTextureImpl_1_Load,
500 IDirect3DTextureImpl_1_Unload,