ddraw: Implement proper handle management.
[wine/wine-kai.git] / dlls / ddraw / texture.c
blobc3a2717267add35d8cc700dd1172b35c6575b8d6
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 "winnls.h"
36 #include "winerror.h"
37 #include "wingdi.h"
38 #include "wine/exception.h"
39 #include "excpt.h"
41 #include "ddraw.h"
42 #include "d3d.h"
44 #include "ddraw_private.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(d3d7);
48 WINE_DECLARE_DEBUG_CHANNEL(ddraw_thunk);
50 /*****************************************************************************
51 * IUnknown interfaces. They are thunks to IDirectDrawSurface7
52 *****************************************************************************/
53 static HRESULT WINAPI
54 Thunk_IDirect3DTextureImpl_2_QueryInterface(IDirect3DTexture2 *iface,
55 REFIID riid,
56 void **obj)
58 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
59 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", This, debugstr_guid(riid), obj);
60 return IDirectDrawSurface7_QueryInterface(ICOM_INTERFACE(This, IDirectDrawSurface7),
61 riid,
62 obj);
65 static HRESULT WINAPI
66 Thunk_IDirect3DTextureImpl_1_QueryInterface(IDirect3DTexture *iface,
67 REFIID riid,
68 void **obj)
70 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
71 TRACE("(%p)->(%s,%p) thunking to IDirectDrawSurface7 interface.\n", This, debugstr_guid(riid), obj);
73 return IDirectDrawSurface7_QueryInterface(ICOM_INTERFACE(This, IDirectDrawSurface7),
74 riid,
75 obj);
78 static ULONG WINAPI
79 Thunk_IDirect3DTextureImpl_2_AddRef(IDirect3DTexture2 *iface)
81 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
82 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
84 return IDirectDrawSurface7_AddRef(ICOM_INTERFACE(This, IDirectDrawSurface7));
87 static ULONG WINAPI
88 Thunk_IDirect3DTextureImpl_1_AddRef(IDirect3DTexture *iface)
90 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
91 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
93 return IDirectDrawSurface7_AddRef(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
96 static ULONG WINAPI
97 Thunk_IDirect3DTextureImpl_2_Release(IDirect3DTexture2 *iface)
99 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
100 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
102 return IDirectDrawSurface7_Release(ICOM_INTERFACE(This, IDirectDrawSurface7));
106 static ULONG WINAPI
107 Thunk_IDirect3DTextureImpl_1_Release(IDirect3DTexture *iface)
109 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
110 TRACE("(%p)->() thunking to IDirectDrawSurface7 interface.\n", This);
112 return IDirectDrawSurface7_Release(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirectDrawSurface7, iface));
115 /*****************************************************************************
116 * IDirect3DTexture interface
117 *****************************************************************************/
119 /*****************************************************************************
120 * IDirect3DTexture1::Initialize
122 * The sdk says it's not implemented
124 * Params:
127 * Returns
128 * DDERR_UNSUPPORTED
130 *****************************************************************************/
131 static HRESULT WINAPI
132 IDirect3DTextureImpl_1_Initialize(IDirect3DTexture *iface,
133 IDirect3DDevice *Direct3DDevice,
134 IDirectDrawSurface *DDSurface)
136 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
137 IDirect3DDeviceImpl *d3d = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice, Direct3DDevice);
138 IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface3, DDSurface);
139 TRACE("(%p)->(%p,%p) Not implemented\n", This, d3d, surf);
140 return DDERR_UNSUPPORTED; /* Unchecked */
143 /*****************************************************************************
144 * IDirect3DTexture2::PaletteChanged
146 * Informs the texture about a palette change
148 * Params:
149 * Start: Start index of the change
150 * Count: The number of changed entries
152 * Returns
153 * D3D_OK, because it's a stub
155 *****************************************************************************/
156 static HRESULT WINAPI
157 IDirect3DTextureImpl_PaletteChanged(IDirect3DTexture2 *iface,
158 DWORD Start,
159 DWORD Count)
161 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
162 FIXME("(%p)->(%08lx,%08lx): stub!\n", This, Start, Count);
163 return D3D_OK;
166 static HRESULT WINAPI
167 Thunk_IDirect3DTextureImpl_1_PaletteChanged(IDirect3DTexture *iface,
168 DWORD Start,
169 DWORD Count)
171 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
172 TRACE("(%p)->(%08lx,%08lx) thunking to IDirect3DTexture2 interface.\n", This, Start, Count);
174 return IDirect3DTexture2_PaletteChanged(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
175 Start,
176 Count);
180 /*****************************************************************************
181 * IDirect3DTexture::Unload
183 * DX5 SDK: "The IDirect3DTexture2::Unload method is not implemented
186 * Returns:
187 * DDERR_UNSUPPORTED
189 *****************************************************************************/
190 static HRESULT WINAPI
191 IDirect3DTextureImpl_1_Unload(IDirect3DTexture *iface)
193 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
194 TRACE("(%p)->(): not implemented!\n", This);
195 return DDERR_UNSUPPORTED;
198 /*****************************************************************************
199 * IDirect3DTexture2::GetHandle
201 * Returns handle for the texture. At the moment, the interface
202 * to the IWineD3DTexture is used.
204 * Params:
205 * Direct3DDevice2: Device this handle is assigned to
206 * Handle: Address to store the handle at.
208 * Returns:
209 * D3D_OK
211 *****************************************************************************/
212 static HRESULT WINAPI
213 IDirect3DTextureImpl_GetHandle(IDirect3DTexture2 *iface,
214 IDirect3DDevice2 *Direct3DDevice2,
215 D3DTEXTUREHANDLE *lpHandle)
217 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
218 IDirect3DDeviceImpl *d3d = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice2, Direct3DDevice2);
220 TRACE("(%p)->(%p,%p)\n", This, d3d, lpHandle);
222 if(!This->Handle)
224 This->Handle = IDirect3DDeviceImpl_CreateHandle(d3d);
225 if(This->Handle)
227 d3d->Handles[This->Handle - 1].ptr = This;
228 d3d->Handles[This->Handle - 1].type = DDrawHandle_Texture;
231 *lpHandle = This->Handle;
233 TRACE(" returning handle %08lx.\n", *lpHandle);
235 return D3D_OK;
238 static HRESULT WINAPI
239 Thunk_IDirect3DTextureImpl_1_GetHandle(IDirect3DTexture *iface,
240 LPDIRECT3DDEVICE lpDirect3DDevice,
241 LPD3DTEXTUREHANDLE lpHandle)
243 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
244 IDirect3DDeviceImpl *d3d = ICOM_OBJECT(IDirect3DDeviceImpl, IDirect3DDevice, lpDirect3DDevice);
245 TRACE_(ddraw_thunk)("(%p)->(%p,%p) thunking to IDirect3DTexture2 interface.\n", This, d3d, lpHandle);
247 return IDirect3DTexture2_GetHandle(ICOM_INTERFACE(This, IDirect3DTexture2),
248 ICOM_INTERFACE(d3d, IDirect3DDevice2),
249 lpHandle);
253 /*****************************************************************************
254 * get_sub_mimaplevel
256 * Helper function that returns the next mipmap level
258 * tex_ptr: Surface of which to return the next level
260 *****************************************************************************/
261 static IDirectDrawSurfaceImpl *
262 get_sub_mimaplevel(IDirectDrawSurfaceImpl *tex_ptr)
264 /* Now go down the mipmap chain to the next surface */
265 static const DDSCAPS2 mipmap_caps = { DDSCAPS_MIPMAP | DDSCAPS_TEXTURE, 0, 0, 0 };
266 LPDIRECTDRAWSURFACE7 next_level;
267 IDirectDrawSurfaceImpl *surf_ptr;
268 HRESULT hr;
270 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(tex_ptr, IDirectDrawSurface7),
271 (DDSCAPS2 *) &mipmap_caps, &next_level);
272 if (FAILED(hr)) return NULL;
274 surf_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, next_level);
275 IDirectDrawSurface7_Release(next_level);
277 return surf_ptr;
280 /*****************************************************************************
281 * IDirect3DTexture2::Load
283 * Loads a texture created with the DDSCAPS_ALLOCONLOAD
285 * This function isn't relayed to WineD3D because the whole interface is
286 * implemented in DDraw only. For speed improvements a implementation which
287 * takes OpenGL more into account could be placed into WineD3D.
289 * Params:
290 * D3DTexture2: Address of the texture to load
292 * Returns:
293 * D3D_OK on success
294 * D3DERR_TEXTURE_LOAD_FAILED.
296 *****************************************************************************/
297 static HRESULT WINAPI
298 IDirect3DTextureImpl_Load(IDirect3DTexture2 *iface,
299 IDirect3DTexture2 *D3DTexture2)
301 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture2, iface);
302 IDirectDrawSurfaceImpl *src_ptr = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, D3DTexture2);
303 IWineD3DPalette *wine_pal, *wine_pal_src;
304 IDirectDrawPalette *pal = NULL, *pal_src = NULL;
305 IDirectDrawPaletteImpl *pal_impl, *pal_impl_src;
306 HRESULT ret_value = D3D_OK;
308 TRACE("(%p)->(%p)\n", This, src_ptr);
310 if (((src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
311 (src_ptr->surface_desc.u2.dwMipMapCount != This->surface_desc.u2.dwMipMapCount))
313 ERR("Trying to load surfaces with different mip-map counts !\n");
316 while(1)
318 DDSURFACEDESC *src_d, *dst_d;
320 TRACE(" copying surface %p to surface %p (mipmap level %d)\n", src_ptr, This, src_ptr->mipmap_level);
322 if ( This->surface_desc.ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD )
323 /* If the surface is not allocated and its location is not yet specified,
324 force it to video memory */
325 if ( !(This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) )
326 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
328 /* Suppress the ALLOCONLOAD flag */
329 This->surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_ALLOCONLOAD;
331 /* Get the palettes */
332 ret_value = IWineD3DSurface_GetPalette(This->WineD3DSurface, &wine_pal);
333 if( ret_value != D3D_OK)
335 ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
336 return D3DERR_TEXTURE_LOAD_FAILED;
338 if(wine_pal)
340 ret_value = IWineD3DPalette_GetParent(wine_pal, (IUnknown **) &pal);
341 if(ret_value != D3D_OK)
343 ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
344 return D3DERR_TEXTURE_LOAD_FAILED;
346 pal_impl = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, pal);
348 else
350 pal_impl = NULL;
353 ret_value = IWineD3DSurface_GetPalette(src_ptr->WineD3DSurface, &wine_pal_src);
354 if( ret_value != D3D_OK)
356 ERR("IWineD3DSurface::GetPalette failed! This is unexpected\n");
357 return D3DERR_TEXTURE_LOAD_FAILED;
359 if(wine_pal_src)
361 ret_value = IWineD3DPalette_GetParent(wine_pal_src, (IUnknown **) &pal_src);
362 if(ret_value != D3D_OK)
364 ERR("IWineD3DPalette::GetParent failed! This is unexpected\n");
365 return D3DERR_TEXTURE_LOAD_FAILED;
367 pal_impl_src = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, pal_src);
369 else
371 pal_impl_src = NULL;
374 /* After seeing some logs, not sure at all about this... */
375 if (pal_impl == NULL)
377 IWineD3DSurface_SetPalette(This->WineD3DSurface, wine_pal);
378 if (pal_impl_src != NULL) IDirectDrawPalette_AddRef(ICOM_INTERFACE(pal_impl_src, IDirectDrawPalette));
380 else
382 if (pal_impl_src != NULL)
384 PALETTEENTRY palent[256];
385 IDirectDrawPalette_GetEntries(ICOM_INTERFACE(pal_impl_src, IDirectDrawPalette),
386 0, 0, 256, palent);
387 IDirectDrawPalette_SetEntries(ICOM_INTERFACE(pal_impl, IDirectDrawPalette),
388 0, 0, 256, palent);
392 /* Copy one surface on the other */
393 dst_d = (DDSURFACEDESC *)&(This->surface_desc);
394 src_d = (DDSURFACEDESC *)&(src_ptr->surface_desc);
396 if ((src_d->dwWidth != dst_d->dwWidth) || (src_d->dwHeight != dst_d->dwHeight))
398 /* Should also check for same pixel format, u1.lPitch, ... */
399 ERR("Error in surface sizes\n");
400 return D3DERR_TEXTURE_LOAD_FAILED;
402 else
404 WINED3DLOCKED_RECT pSrcRect, pDstRect;
406 /* LPDIRECT3DDEVICE2 d3dd = (LPDIRECT3DDEVICE2) This->D3Ddevice; */
407 /* I should put a macro for the calculus of bpp */
409 /* Copy also the ColorKeying stuff */
410 if (src_d->dwFlags & DDSD_CKSRCBLT)
412 dst_d->dwFlags |= DDSD_CKSRCBLT;
413 dst_d->ddckCKSrcBlt.dwColorSpaceLowValue = src_d->ddckCKSrcBlt.dwColorSpaceLowValue;
414 dst_d->ddckCKSrcBlt.dwColorSpaceHighValue = src_d->ddckCKSrcBlt.dwColorSpaceHighValue;
417 /* Copy the main memory texture into the surface that corresponds to the OpenGL
418 texture object. */
420 ret_value = IWineD3DSurface_LockRect(src_ptr->WineD3DSurface, &pSrcRect, NULL, 0);
421 if(ret_value != D3D_OK)
423 ERR(" (%p) Locking the source surface failed\n", This);
424 return D3DERR_TEXTURE_LOAD_FAILED;
427 ret_value = IWineD3DSurface_LockRect(This->WineD3DSurface, &pDstRect, NULL, 0);
428 if(ret_value != D3D_OK)
430 ERR(" (%p) Locking the destination surface failed\n", This);
431 IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
432 return D3DERR_TEXTURE_LOAD_FAILED;
435 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC)
436 memcpy(pDstRect.pBits, pSrcRect.pBits, src_ptr->surface_desc.u1.dwLinearSize);
437 else
438 memcpy(pDstRect.pBits, pSrcRect.pBits, pSrcRect.Pitch * src_d->dwHeight);
440 IWineD3DSurface_UnlockRect(src_ptr->WineD3DSurface);
441 IWineD3DSurface_UnlockRect(This->WineD3DSurface);
444 if (src_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
446 src_ptr = get_sub_mimaplevel(src_ptr);
448 else
450 src_ptr = NULL;
452 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
454 This = get_sub_mimaplevel(This);
456 else
458 This = NULL;
461 if ((src_ptr == NULL) || (This == NULL))
463 if (src_ptr != This)
465 ERR(" Loading surface with different mipmap structure !!!\n");
467 break;
471 return ret_value;
474 static HRESULT WINAPI
475 Thunk_IDirect3DTextureImpl_1_Load(IDirect3DTexture *iface,
476 IDirect3DTexture *D3DTexture)
478 ICOM_THIS_FROM(IDirectDrawSurfaceImpl, IDirect3DTexture, iface);
479 IDirectDrawSurfaceImpl *Texture = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture, D3DTexture);
480 TRACE("(%p)->(%p) thunking to IDirect3DTexture2 interface.\n", This, Texture);
482 return IDirect3DTexture2_Load(COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, iface),
483 COM_INTERFACE_CAST(IDirectDrawSurfaceImpl, IDirect3DTexture, IDirect3DTexture2, D3DTexture));
486 /*****************************************************************************
487 * The VTables
488 *****************************************************************************/
489 const IDirect3DTexture2Vtbl IDirect3DTexture2_Vtbl =
491 Thunk_IDirect3DTextureImpl_2_QueryInterface,
492 Thunk_IDirect3DTextureImpl_2_AddRef,
493 Thunk_IDirect3DTextureImpl_2_Release,
494 IDirect3DTextureImpl_GetHandle,
495 IDirect3DTextureImpl_PaletteChanged,
496 IDirect3DTextureImpl_Load,
500 const IDirect3DTextureVtbl IDirect3DTexture1_Vtbl =
502 Thunk_IDirect3DTextureImpl_1_QueryInterface,
503 Thunk_IDirect3DTextureImpl_1_AddRef,
504 Thunk_IDirect3DTextureImpl_1_Release,
505 IDirect3DTextureImpl_1_Initialize,
506 Thunk_IDirect3DTextureImpl_1_GetHandle,
507 Thunk_IDirect3DTextureImpl_1_PaletteChanged,
508 Thunk_IDirect3DTextureImpl_1_Load,
509 IDirect3DTextureImpl_1_Unload,