1 /* DirectDrawSurface base implementation
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 * Copyright 2000-2001 TransGaming Technologies Inc.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
29 #include "mesa_private.h"
30 #include "wine/debug.h"
31 #include "ddraw_private.h"
32 #include "dsurface/main.h"
33 #include "ddraw/main.h"
34 #include "dsurface/thunks.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip
);
39 /** Creation/Destruction functions */
42 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl
*This
,
44 const DDSURFACEDESC2
*pDDSD
)
46 TRACE("(%p)->(%p,%p)\n", This
, pDD
, pDDSD
);
48 if (pDDSD
!= &This
->surface_desc
) {
49 This
->surface_desc
.dwSize
= sizeof(This
->surface_desc
);
50 DD_STRUCT_COPY_BYSIZE(&(This
->surface_desc
),pDDSD
);
52 This
->uniqueness_value
= 1; /* unchecked */
55 This
->local
.lpSurfMore
= &This
->more
;
56 This
->local
.lpGbl
= &This
->global
;
57 This
->local
.dwProcessId
= GetCurrentProcessId();
58 This
->local
.dwFlags
= 0; /* FIXME */
59 This
->local
.ddsCaps
.dwCaps
= This
->surface_desc
.ddsCaps
.dwCaps
;
60 /* FIXME: more local stuff */
61 This
->more
.lpDD_lcl
= &pDD
->local
;
62 This
->more
.ddsCapsEx
.dwCaps2
= This
->surface_desc
.ddsCaps
.dwCaps2
;
63 This
->more
.ddsCapsEx
.dwCaps3
= This
->surface_desc
.ddsCaps
.dwCaps3
;
64 This
->more
.ddsCapsEx
.dwCaps4
= This
->surface_desc
.ddsCaps
.dwCaps4
;
65 /* FIXME: more more stuff */
66 This
->gmore
= &This
->global_more
;
67 This
->global
.u3
.lpDD
= pDD
->local
.lpGbl
;
68 /* FIXME: more global stuff */
70 This
->final_release
= Main_DirectDrawSurface_final_release
;
71 This
->late_allocate
= Main_DirectDrawSurface_late_allocate
;
72 This
->attach
= Main_DirectDrawSurface_attach
;
73 This
->detach
= Main_DirectDrawSurface_detach
;
74 This
->lock_update
= Main_DirectDrawSurface_lock_update
;
75 This
->unlock_update
= Main_DirectDrawSurface_unlock_update
;
76 This
->lose_surface
= Main_DirectDrawSurface_lose_surface
;
77 This
->set_palette
= Main_DirectDrawSurface_set_palette
;
78 This
->update_palette
= Main_DirectDrawSurface_update_palette
;
79 This
->get_display_window
= Main_DirectDrawSurface_get_display_window
;
80 This
->get_gamma_ramp
= Main_DirectDrawSurface_get_gamma_ramp
;
81 This
->set_gamma_ramp
= Main_DirectDrawSurface_set_gamma_ramp
;
83 ICOM_INIT_INTERFACE(This
, IDirectDrawSurface3
,
84 DDRAW_IDDS3_Thunk_VTable
);
85 ICOM_INIT_INTERFACE(This
, IDirectDrawGammaControl
,
88 /* There is no generic implementation of IDDS7 or texture */
90 Main_DirectDraw_AddSurface(pDD
, This
);
94 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl
* This
)
96 Main_DirectDraw_RemoveSurface(This
->ddraw_owner
, This
);
99 HRESULT
Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl
* This
)
104 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl
* This
)
107 IDirectDrawPalette_Release(ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
));
108 This
->palette
= NULL
;
110 This
->final_release(This
);
111 if (This
->private != This
+1) HeapFree(GetProcessHeap(), 0, This
->private);
112 if (This
->tex_private
) HeapFree(GetProcessHeap(), 0, This
->tex_private
);
113 HeapFree(GetProcessHeap(), 0, This
);
116 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl
* This
)
118 WARN("destroying surface %p with refcnt %lu\n", This
, This
->ref
);
119 Main_DirectDrawSurface_Destroy(This
);
122 ULONG WINAPI
Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface
)
124 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
126 TRACE("(%p)->(): decreasing from %ld\n", This
, This
->ref
);
128 if (--This
->ref
== 0)
130 if (This
->aux_release
)
131 This
->aux_release(This
->aux_ctx
, This
->aux_data
);
132 Main_DirectDrawSurface_Destroy(This
);
134 TRACE("released surface %p\n", This
);
142 ULONG WINAPI
Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface
)
144 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
146 TRACE("(%p)->(): increasing from %ld\n", This
, This
->ref
);
152 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface
, REFIID riid
,
155 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
156 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppObj
);
160 if (IsEqualGUID(&IID_IUnknown
, riid
)
161 || IsEqualGUID(&IID_IDirectDrawSurface7
, riid
)
162 || IsEqualGUID(&IID_IDirectDrawSurface4
, riid
))
165 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface7
);
168 else if (IsEqualGUID(&IID_IDirectDrawSurface
, riid
)
169 || IsEqualGUID(&IID_IDirectDrawSurface2
, riid
)
170 || IsEqualGUID(&IID_IDirectDrawSurface3
, riid
))
173 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface3
);
176 else if (IsEqualGUID(&IID_IDirectDrawGammaControl
, riid
))
179 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawGammaControl
);
183 /* interfaces following here require OpenGL */
184 if( !opengl_initialized
)
185 return E_NOINTERFACE
;
187 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL
, riid
) ||
188 IsEqualGUID( &IID_IDirect3DHALDevice
, riid
) )
190 IDirect3DDeviceImpl
*d3ddevimpl
;
193 ret_value
= d3ddevice_create(&d3ddevimpl
, This
->ddraw_owner
, This
, TRUE
);
194 if (FAILED(ret_value
)) return ret_value
;
196 *ppObj
= ICOM_INTERFACE(d3ddevimpl
, IDirect3DDevice
);
197 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj
);
199 This
->ref
++; /* No idea if this is correct.. Need to check using real Windows */
202 else if (IsEqualGUID( &IID_IDirect3DTexture
, riid
) ||
203 IsEqualGUID( &IID_IDirect3DTexture2
, riid
))
205 HRESULT ret_value
= S_OK
;
207 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
208 application I know creating a texture without this flag set and it will prevent
209 bugs in other parts of Wine.
211 This
->surface_desc
.ddsCaps
.dwCaps
|= DDSCAPS_TEXTURE
;
213 /* In case the texture surface was created before the D3D creation */
214 if (This
->tex_private
== NULL
) {
215 if (This
->ddraw_owner
->d3d_private
== NULL
) {
216 ERR("Texture created with no D3D object yet.. Not supported !\n");
217 return E_NOINTERFACE
;
220 ret_value
= This
->ddraw_owner
->d3d_create_texture(This
->ddraw_owner
, This
, FALSE
, This
->mip_main
);
221 if (FAILED(ret_value
)) return ret_value
;
223 if (IsEqualGUID( &IID_IDirect3DTexture
, riid
)) {
224 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture
);
225 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj
);
227 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture2
);
228 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj
);
235 return E_NOINTERFACE
;
241 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl
*This
,
242 IDirectDrawSurfaceImpl
*to
)
247 BOOL
Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl
*This
)
253 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
,
259 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl
* This
,
265 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl
* This
)
270 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl
* This
,
271 IDirectDrawPaletteImpl
* pal
)
276 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl
* This
,
277 IDirectDrawPaletteImpl
* pal
,
278 DWORD dwStart
, DWORD dwCount
,
279 LPPALETTEENTRY palent
)
284 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl
* This
)
290 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
292 LPDDGAMMARAMP lpGammaRamp
)
296 hr
= This
->get_dc(This
, &hDC
);
297 if (FAILED(hr
)) return hr
;
298 hr
= GetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
299 This
->release_dc(This
, hDC
);
304 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
306 LPDDGAMMARAMP lpGammaRamp
)
310 hr
= This
->get_dc(This
, &hDC
);
311 if (FAILED(hr
)) return hr
;
312 hr
= SetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
313 This
->release_dc(This
, hDC
);
318 /*** Interface functions */
321 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
322 LPDIRECTDRAWSURFACE7 pAttach
)
324 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
325 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
326 IDirectDrawSurface7
, pAttach
);
328 TRACE("(%p)->(%p)\n",This
,pAttach
);
330 /* Does windows check this? */
332 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
334 /* Does windows check this? */
335 if (surf
->ddraw_owner
!= This
->ddraw_owner
)
336 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
338 if (surf
->surface_owner
!= NULL
)
339 return DDERR_SURFACEALREADYATTACHED
; /* unchecked */
341 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
342 * But apparently backbuffers and mipmaps can be attached too. */
344 /* Set MIPMAPSUBLEVEL if this seems to be one */
345 if (This
->surface_desc
.ddsCaps
.dwCaps
&
346 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
347 surf
->surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
348 /* FIXME: we should probably also add to dwMipMapCount of this
349 * and all parent surfaces (update create_texture if you do) */
352 /* Callback to allow the surface to do something special now that it is
353 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
354 if (!surf
->attach(surf
, This
))
355 return DDERR_CANNOTATTACHSURFACE
;
357 /* check: Where should it go in the chain? This puts it on the head. */
359 This
->attached
->prev_attached
= surf
;
360 surf
->next_attached
= This
->attached
;
361 surf
->prev_attached
= NULL
;
362 This
->attached
= surf
;
363 surf
->surface_owner
= This
;
365 IDirectDrawSurface7_AddRef(pAttach
);
370 /* MSDN: "not currently implemented." */
372 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface
,
375 TRACE("(%p)->(%p)\n",iface
,pRect
);
376 return DDERR_UNSUPPORTED
; /* unchecked */
379 /* MSDN: "not currently implemented." */
381 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface
,
382 LPDDBLTBATCH pBatch
, DWORD dwCount
,
385 TRACE("(%p)->(%p,%ld,%08lx)\n",iface
,pBatch
,dwCount
,dwFlags
);
386 return DDERR_UNSUPPORTED
; /* unchecked */
390 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface
)
392 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
393 volatile IDirectDrawSurfaceImpl
* vThis
= This
;
395 TRACE("(%p)\n",This
);
396 /* A uniquness value of 0 is apparently special.
397 * This needs to be checked. */
400 DWORD old_uniqueness_value
= vThis
->uniqueness_value
;
401 DWORD new_uniqueness_value
= old_uniqueness_value
+1;
403 if (old_uniqueness_value
== 0) break;
404 if (new_uniqueness_value
== 0) new_uniqueness_value
= 1;
406 if (InterlockedCompareExchange((LONG
*)&vThis
->uniqueness_value
,
407 old_uniqueness_value
,
408 new_uniqueness_value
)
409 == old_uniqueness_value
)
417 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
419 LPDIRECTDRAWSURFACE7 pAttach
)
421 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
422 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
423 IDirectDrawSurface7
, pAttach
);
425 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pAttach
);
427 if (!surf
|| (surf
->surface_owner
!= This
))
428 return DDERR_SURFACENOTATTACHED
; /* unchecked */
432 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
433 if (This
->surface_desc
.ddsCaps
.dwCaps
&
434 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
435 surf
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
436 /* FIXME: we should probably also subtract from dwMipMapCount of this
437 * and all parent surfaces */
440 if (surf
->next_attached
)
441 surf
->next_attached
->prev_attached
= surf
->prev_attached
;
442 if (surf
->prev_attached
)
443 surf
->prev_attached
->next_attached
= surf
->next_attached
;
444 if (This
->attached
== surf
)
445 This
->attached
= surf
->next_attached
;
447 IDirectDrawSurface7_Release(pAttach
);
453 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface
,
455 LPDDENUMSURFACESCALLBACK7 cb
)
457 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
458 IDirectDrawSurfaceImpl
* surf
;
460 TRACE("(%p)->(%p,%p)\n",This
,context
,cb
);
462 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
464 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
465 if (cb(ICOM_INTERFACE(surf
, IDirectDrawSurface7
), &surf
->surface_desc
,
466 context
) == DDENUMRET_CANCEL
)
474 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface
,
475 DWORD dwFlags
, LPVOID context
,
476 LPDDENUMSURFACESCALLBACK7 cb
)
478 TRACE("(%p)->(%08lx,%p,%p)\n",iface
,dwFlags
,context
,cb
);
482 BOOL
Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl
* front
,
483 IDirectDrawSurfaceImpl
* back
,
486 /* uniqueness_value? */
487 /* This is necessary. But is it safe? */
489 HDC tmp
= front
->hDC
;
490 front
->hDC
= back
->hDC
;
495 BOOL tmp
= front
->dc_in_use
;
496 front
->dc_in_use
= back
->dc_in_use
;
497 back
->dc_in_use
= tmp
;
501 FLATPTR tmp
= front
->global
.fpVidMem
;
502 front
->global
.fpVidMem
= back
->global
.fpVidMem
;
503 back
->global
.fpVidMem
= tmp
;
507 ULONG_PTR tmp
= front
->global_more
.hKernelSurface
;
508 front
->global_more
.hKernelSurface
= back
->global_more
.hKernelSurface
;
509 back
->global_more
.hKernelSurface
= tmp
;
516 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface
,
517 LPDIRECTDRAWSURFACE7 override
, DWORD dwFlags
)
519 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
520 IDirectDrawSurfaceImpl
* target
;
523 TRACE("(%p)->(%p,%08lx)\n",This
,override
,dwFlags
);
525 /* MSDN: "This method can be called only for a surface that has the
526 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
527 if ((This
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
528 != (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
529 return DDERR_NOTFLIPPABLE
;
532 if (This
->aux_flip(This
->aux_ctx
, This
->aux_data
))
535 /* 1. find the flip target */
536 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
537 if (override
== NULL
)
539 static DDSCAPS2 back_caps
= { DDSCAPS_BACKBUFFER
};
540 LPDIRECTDRAWSURFACE7 tgt
;
542 hr
= IDirectDrawSurface7_GetAttachedSurface(iface
, &back_caps
, &tgt
);
543 if (FAILED(hr
)) return DDERR_NOTFLIPPABLE
; /* unchecked */
545 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
547 IDirectDrawSurface7_Release(tgt
);
551 BOOL on_chain
= FALSE
;
552 IDirectDrawSurfaceImpl
* surf
;
554 /* MSDN: "The method fails if the specified [override] surface is not
555 * a member of the flipping chain." */
557 /* Verify that override is on this flip chain. We assume that
558 * surf is the head of the flipping chain, because it's the front
560 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
563 /* Either target is (indirectly) attached to This or This is
564 * (indirectly) attached to target. */
565 for (surf
= target
; surf
!= NULL
; surf
= surf
->surface_owner
)
575 return DDERR_INVALIDPARAMS
; /* unchecked */
578 TRACE("flip to backbuffer: %p\n",target
);
579 if (TRACE_ON(ddraw_flip
)) {
580 static unsigned int flip_count
= 0;
581 IDirectDrawPaletteImpl
*palette
;
585 /* Hack for paletted games... */
586 palette
= target
->palette
;
587 target
->palette
= This
->palette
;
589 sprintf(buf
, "flip_%08d.ppm", flip_count
++);
590 TRACE_(ddraw_flip
)("Dumping file %s to disk.\n", buf
);
591 f
= fopen(buf
, "wb");
592 DDRAW_dump_surface_to_disk(target
, f
, 8);
593 target
->palette
= palette
;
596 if (This
->flip_data(This
, target
, dwFlags
))
597 This
->flip_update(This
, dwFlags
);
602 static PrivateData
* find_private_data(IDirectDrawSurfaceImpl
*This
,
606 for (data
= This
->private_data
; data
!= NULL
; data
= data
->next
)
608 if (IsEqualGUID(&data
->tag
, tag
)) break;
615 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface
, REFGUID tag
)
617 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
620 data
= find_private_data(This
, tag
);
621 if (data
== NULL
) return DDERR_NOTFOUND
;
624 data
->prev
->next
= data
->next
;
626 data
->next
->prev
= data
->prev
;
628 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
630 if (data
->ptr
.object
!= NULL
)
631 IUnknown_Release(data
->ptr
.object
);
634 HeapFree(GetProcessHeap(), 0, data
->ptr
.data
);
636 HeapFree(GetProcessHeap(), 0, data
);
642 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
644 LPDIRECTDRAWSURFACE7
* ppSurface
)
646 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
647 IDirectDrawSurfaceImpl
* surf
;
648 IDirectDrawSurfaceImpl
* found
= NULL
;
651 if (TRACE_ON(ddraw
)) {
652 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This
,pCaps
->dwCaps
, pCaps
->dwCaps2
,
653 pCaps
->dwCaps3
, pCaps
->dwCaps4
, ppSurface
);
654 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps
); TRACE("\n");
658 if ((This
->ddraw_owner
->local
.dwLocalFlags
& DDRAWILCL_DIRECTDRAW7
) == 0) {
659 /* As this is not a DirectDraw7 application, remove the garbage that some games
660 put in the new fields of the DDSCAPS2 structure. */
661 our_caps
.dwCaps2
= 0;
662 our_caps
.dwCaps3
= 0;
663 our_caps
.dwCaps4
= 0;
664 if (TRACE_ON(ddraw
)) {
665 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps
); TRACE("\n");
669 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
671 if (TRACE_ON(ddraw
)) {
672 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf
,
673 surf
->surface_desc
.ddsCaps
.dwCaps
,
674 surf
->surface_desc
.ddsCaps
.dwCaps2
,
675 surf
->surface_desc
.ddsCaps
.dwCaps3
,
676 surf
->surface_desc
.ddsCaps
.dwCaps4
);
677 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf
->surface_desc
.ddsCaps
)); TRACE("\n");
679 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
680 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
))
682 /* MSDN: "This method fails if more than one surface is attached
683 * that matches the capabilities requested." */
686 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
687 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
688 to be correct, given what 3DMark expects from MipMapped surfaces.
689 We shall just continue instead. */
697 TRACE("Did not find any valid surface\n");
698 return DDERR_NOTFOUND
;
701 *ppSurface
= ICOM_INTERFACE(found
, IDirectDrawSurface7
);
703 if (TRACE_ON(ddraw
)) {
704 TRACE("Returning surface %p with description : \n", *ppSurface
);
705 DDRAW_dump_surface_desc(&(found
->surface_desc
));
708 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
709 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found
, IDirectDrawSurface7
));
714 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
716 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
721 case DDGBS_ISBLTDONE
:
725 return DDERR_INVALIDPARAMS
;
730 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface
, LPDDSCAPS2 pCaps
)
732 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
734 TRACE("(%p)->(%p)\n",This
,pCaps
);
735 *pCaps
= This
->surface_desc
.ddsCaps
;
740 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface
,
741 LPDIRECTDRAWCLIPPER
* ppClipper
)
743 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
745 TRACE("(%p)->(%p)\n",This
,ppClipper
);
746 if (This
->clipper
== NULL
)
747 return DDERR_NOCLIPPERATTACHED
;
749 *ppClipper
= ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
);
750 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This
->clipper
,
751 IDirectDrawClipper
));
756 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
,
759 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
760 * isn't there? That's like saying that an int isn't there. (Which MS
761 * has done in other docs.) */
763 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
765 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
766 if (TRACE_ON(ddraw
)) {
767 TRACE(" - colorkey flags : ");
768 DDRAW_dump_colorkeyflag(dwFlags
);
774 *pCKey
= This
->surface_desc
.ddckCKDestBlt
;
777 case DDCKEY_DESTOVERLAY
:
778 *pCKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
782 *pCKey
= This
->surface_desc
.ddckCKSrcBlt
;
785 case DDCKEY_SRCOVERLAY
:
786 *pCKey
= This
->surface_desc
.ddckCKSrcOverlay
;
790 return DDERR_INVALIDPARAMS
;
796 /* XXX We need to do something with the DC if the surface gets lost. */
798 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface
, HDC
*phDC
)
802 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
804 TRACE("(%p)->(%p)\n",This
,phDC
);
812 return DDERR_DCALREADYCREATED
;
816 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
817 * thread has it locked, but GetDC does not. */
818 ddsd
.dwSize
= sizeof(ddsd
);
819 hr
= IDirectDrawSurface7_Lock(iface
, NULL
, &ddsd
, 0, 0);
826 hr
= This
->get_dc(This
, &This
->hDC
);
829 TRACE("returning %p\n",This
->hDC
);
832 This
->dc_in_use
= TRUE
;
834 else WARN("No DC! Prepare for trouble\n");
841 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface
, LPVOID
* pDD
)
843 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
845 TRACE("(%p)->(%p)\n",This
,pDD
);
846 *pDD
= ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
);
847 IDirectDraw7_AddRef(ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
));
852 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
854 /* XXX: DDERR_INVALIDSURFACETYPE */
856 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
860 case DDGFS_ISFLIPDONE
:
864 return DDERR_INVALIDPARAMS
;
869 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface
, LPDWORD pdwMaxLOD
)
871 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
873 TRACE("(%p)->(%p)\n",This
,pdwMaxLOD
);
876 *pdwMaxLOD
= This
->max_lod
;
881 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
882 LPLONG pX
, LPLONG pY
)
884 return DDERR_NOTAOVERLAYSURFACE
;
888 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface
,
889 LPDIRECTDRAWPALETTE
* ppPalette
)
891 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
893 TRACE("(%p)->(%p)\n",This
,ppPalette
);
894 if (This
->palette
== NULL
)
895 return DDERR_NOPALETTEATTACHED
;
897 *ppPalette
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
898 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This
->palette
,
899 IDirectDrawPalette
));
904 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface
,
905 LPDDPIXELFORMAT pDDPixelFormat
)
907 /* What is DDERR_INVALIDSURFACETYPE for here? */
908 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
910 TRACE("(%p)->(%p)\n",This
,pDDPixelFormat
);
911 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat
,&This
->surface_desc
.u4
.ddpfPixelFormat
);
916 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface
,
919 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
921 TRACE("(%p)->(%p)\n",This
,pdwPriority
);
924 *pdwPriority
= This
->priority
;
929 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
930 REFGUID tag
, LPVOID pBuffer
,
931 LPDWORD pcbBufferSize
)
933 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
936 data
= find_private_data(This
, tag
);
937 if (data
== NULL
) return DDERR_NOTFOUND
;
939 /* This may not be right. */
940 if ((data
->flags
& DDSPD_VOLATILE
)
941 && data
->uniqueness_value
!= This
->uniqueness_value
)
942 return DDERR_EXPIRED
;
944 if (*pcbBufferSize
< data
->size
)
946 *pcbBufferSize
= data
->size
;
947 return DDERR_MOREDATA
;
950 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
952 *(LPUNKNOWN
*)pBuffer
= data
->ptr
.object
;
953 IUnknown_AddRef(data
->ptr
.object
);
957 memcpy(pBuffer
, data
->ptr
.data
, data
->size
);
964 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface
,
965 LPDDSURFACEDESC2 pDDSD
)
967 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
969 TRACE("(%p)->(%p)\n",This
,pDDSD
);
970 if ((pDDSD
->dwSize
< sizeof(DDSURFACEDESC
)) ||
971 (pDDSD
->dwSize
> sizeof(DDSURFACEDESC2
))) {
972 ERR("Impossible/Strange struct size %ld.\n",pDDSD
->dwSize
);
973 return DDERR_GENERIC
;
976 DD_STRUCT_COPY_BYSIZE(pDDSD
,&This
->surface_desc
);
977 if (TRACE_ON(ddraw
)) {
978 DDRAW_dump_surface_desc(pDDSD
);
984 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface
,
987 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
989 TRACE("(%p)->(%p)\n",This
,pValue
);
990 *pValue
= This
->uniqueness_value
;
995 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface
,
996 LPDIRECTDRAW pDD
, LPDDSURFACEDESC2 pDDSD
)
998 TRACE("(%p)->(%p,%p)\n",iface
,pDD
,pDDSD
);
999 return DDERR_ALREADYINITIALIZED
;
1003 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface
)
1005 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1007 TRACE("(%p) is%s lost\n",This
, (This
->lost
? "" : " not"));
1008 return This
->lost
? DDERR_SURFACELOST
: DD_OK
;
1012 /* XXX This doesn't actually do any locking or keep track of the locked
1013 * rectangles. The behaviour is poorly documented. */
1015 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface
, LPRECT prect
,
1016 LPDDSURFACEDESC2 pDDSD
, DWORD flags
, HANDLE h
)
1018 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1020 if (TRACE_ON(ddraw
)) {
1021 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This
,prect
,pDDSD
,flags
,(DWORD
)h
);
1022 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags
);
1024 if (WARN_ON(ddraw
)) {
1025 if (flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
)) {
1026 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
));
1030 /* First, copy the Surface description */
1031 DD_STRUCT_COPY_BYSIZE(pDDSD
,&(This
->surface_desc
));
1033 /* Used to optimize the D3D Device locking */
1034 This
->lastlocktype
= flags
& (DDLOCK_READONLY
|DDLOCK_WRITEONLY
);
1036 /* If asked only for a part, change the surface pointer.
1037 * (Not documented.) */
1038 if (prect
!= NULL
) {
1039 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1040 prect
->left
,prect
->top
,prect
->right
,prect
->bottom
);
1041 /* First do some sanity checkings on the rectangle we receive.
1042 DungeonSiege seems to gives us once a very bad rectangle for example */
1043 if ((prect
->top
< 0) ||
1044 (prect
->left
< 0) ||
1045 (prect
->bottom
< 0) ||
1046 (prect
->right
< 0) ||
1047 (prect
->left
>= prect
->right
) ||
1048 (prect
->top
>= prect
->bottom
) ||
1049 (prect
->left
>= This
->surface_desc
.dwWidth
) ||
1050 (prect
->right
> This
->surface_desc
.dwWidth
) ||
1051 (prect
->top
>= This
->surface_desc
.dwHeight
) ||
1052 (prect
->bottom
> This
->surface_desc
.dwHeight
)) {
1053 ERR(" Invalid values in LPRECT !!!\n");
1054 return DDERR_INVALIDPARAMS
;
1057 This
->lock_update(This
, prect
, flags
);
1059 pDDSD
->lpSurface
= (char *)This
->surface_desc
.lpSurface
1060 + prect
->top
* This
->surface_desc
.u1
.lPitch
1061 + prect
->left
* GET_BPP(This
->surface_desc
);
1063 This
->lock_update(This
, NULL
, flags
);
1066 TRACE("locked surface returning description : \n");
1067 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(pDDSD
);
1073 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1075 /* Some surface types should return DDERR_CANTPAGELOCK. */
1080 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1082 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1083 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1088 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface
, HDC hDC
)
1091 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1093 TRACE("(%p)->(%p)\n",This
,hDC
);
1095 if (!This
->dc_in_use
|| This
->hDC
!= hDC
)
1096 return DDERR_INVALIDPARAMS
;
1098 This
->release_dc(This
, hDC
);
1100 hr
= IDirectDrawSurface7_Unlock(iface
, NULL
);
1101 if (FAILED(hr
)) return hr
;
1103 This
->dc_in_use
= FALSE
;
1112 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface
,
1113 LPDIRECTDRAWCLIPPER pDDClipper
)
1115 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1117 TRACE("(%p)->(%p)\n",This
,pDDClipper
);
1118 if (pDDClipper
== ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
))
1121 if (This
->clipper
!= NULL
)
1122 IDirectDrawClipper_Release(ICOM_INTERFACE(This
->clipper
,
1123 IDirectDrawClipper
));
1125 This
->clipper
= ICOM_OBJECT(IDirectDrawClipperImpl
, IDirectDrawClipper
,
1127 if (pDDClipper
!= NULL
)
1128 IDirectDrawClipper_AddRef(pDDClipper
);
1134 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface
,
1135 DWORD dwFlags
, LPDDCOLORKEY pCKey
)
1137 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1139 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
1141 if (TRACE_ON(ddraw
)) {
1142 TRACE(" - colorkey flags : ");
1143 DDRAW_dump_colorkeyflag(dwFlags
);
1146 if ((dwFlags
& DDCKEY_COLORSPACE
) != 0) {
1147 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags
);
1148 return DDERR_INVALIDPARAMS
;
1151 /* TODO: investigate if this function can take multiple bits set at the same
1152 time (ie setting multiple colorkey values at the same time with only
1156 switch (dwFlags
& ~DDCKEY_COLORSPACE
) {
1157 case DDCKEY_DESTBLT
:
1158 This
->surface_desc
.ddckCKDestBlt
= *pCKey
;
1159 This
->surface_desc
.dwFlags
|= DDSD_CKDESTBLT
;
1162 case DDCKEY_DESTOVERLAY
:
1163 This
->surface_desc
.u3
.ddckCKDestOverlay
= *pCKey
;
1164 This
->surface_desc
.dwFlags
|= DDSD_CKDESTOVERLAY
;
1167 case DDCKEY_SRCOVERLAY
:
1168 This
->surface_desc
.ddckCKSrcOverlay
= *pCKey
;
1169 This
->surface_desc
.dwFlags
|= DDSD_CKSRCOVERLAY
;
1173 This
->surface_desc
.ddckCKSrcBlt
= *pCKey
;
1174 This
->surface_desc
.dwFlags
|= DDSD_CKSRCBLT
;
1178 return DDERR_INVALIDPARAMS
;
1181 switch (dwFlags
& ~DDCKEY_COLORSPACE
) {
1182 case DDCKEY_DESTBLT
:
1183 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTBLT
;
1186 case DDCKEY_DESTOVERLAY
:
1187 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTOVERLAY
;
1190 case DDCKEY_SRCOVERLAY
:
1191 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCOVERLAY
;
1195 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCBLT
;
1199 return DDERR_INVALIDPARAMS
;
1203 if (This
->aux_setcolorkey_cb
) This
->aux_setcolorkey_cb(This
, dwFlags
, pCKey
);
1209 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface
, DWORD dwMaxLOD
)
1211 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1213 TRACE("(%p)->(%08lx)\n",This
,dwMaxLOD
);
1214 CHECK_TEXTURE(This
);
1216 This
->max_lod
= dwMaxLOD
;
1221 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
1224 return DDERR_NOTAOVERLAYSURFACE
;
1228 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface
,
1229 LPDIRECTDRAWPALETTE pPalette
)
1231 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1232 IDirectDrawPalette
*pal_to_rel
= NULL
;
1234 TRACE("(%p)->(%p)\n",This
,pPalette
);
1235 if (pPalette
== ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
))
1238 if (This
->palette
!= NULL
) {
1239 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1240 This
->palette
->global
.dwFlags
&= ~DDPCAPS_PRIMARYSURFACE
;
1241 pal_to_rel
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
1244 This
->palette
= ICOM_OBJECT(IDirectDrawPaletteImpl
, IDirectDrawPalette
,
1246 if (pPalette
!= NULL
) {
1247 IDirectDrawPalette_AddRef(pPalette
);
1248 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1249 This
->palette
->global
.dwFlags
|= DDPCAPS_PRIMARYSURFACE
;
1252 This
->set_palette(This
, This
->palette
);
1254 /* Do the palette release at the end to prevent doing some 'loop' when removing
1255 * the surface maintaining the last reference on a palette.
1257 if (pal_to_rel
!= NULL
)
1258 IDirectDrawPalette_Release(pal_to_rel
);
1264 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface
,
1267 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1269 TRACE("(%p)->(%08lx)\n",This
,dwPriority
);
1270 CHECK_TEXTURE(This
);
1272 This
->priority
= dwPriority
;
1276 /* Be careful when locking this: it is risky to call the object's AddRef
1277 * or Release holding a lock. */
1279 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
1280 REFGUID tag
, LPVOID pData
,
1281 DWORD cbSize
, DWORD dwFlags
)
1284 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1286 data
= find_private_data(This
, tag
);
1289 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
1290 if (data
== NULL
) return DDERR_OUTOFMEMORY
;
1293 data
->flags
= dwFlags
;
1294 data
->uniqueness_value
= This
->uniqueness_value
;
1296 if (dwFlags
& DDSPD_IUNKNOWNPTR
)
1298 data
->ptr
.object
= (LPUNKNOWN
)pData
;
1299 data
->size
= sizeof(LPUNKNOWN
);
1300 IUnknown_AddRef(data
->ptr
.object
);
1304 data
->ptr
.data
= HeapAlloc(GetProcessHeap(), 0, cbSize
);
1305 if (data
->ptr
.data
== NULL
)
1307 HeapFree(GetProcessHeap(), 0, data
);
1308 return DDERR_OUTOFMEMORY
;
1313 data
->next
= This
->private_data
;
1315 if (This
->private_data
)
1316 This
->private_data
->prev
= data
;
1317 This
->private_data
= data
;
1323 /* I don't actually know how windows handles this case. The only
1324 * reason I don't just call FreePrivateData is because I want to
1325 * guarantee SetPrivateData working when using LPUNKNOWN or data
1326 * that is no larger than the old data. */
1332 /* SetSurfaceDesc */
1335 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface
, LPRECT pRect
)
1337 ICOM_THIS(IDirectDrawSurfaceImpl
,iface
);
1339 TRACE("(%p)->Unlock(%p)\n",This
,pRect
);
1341 This
->unlock_update(This
, pRect
);
1342 if (This
->aux_unlock
)
1343 This
->aux_unlock(This
->aux_ctx
, This
->aux_data
, pRect
);
1349 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface
,
1351 LPDIRECTDRAWSURFACE7 pDstSurface
,
1352 LPRECT pDstRect
, DWORD dwFlags
,
1355 return DDERR_UNSUPPORTED
;
1358 /* MSDN: "not currently implemented." */
1360 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface
,
1363 return DDERR_UNSUPPORTED
;
1367 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface
,
1369 LPDIRECTDRAWSURFACE7 pDDSRef
)
1371 return DDERR_NOTAOVERLAYSURFACE
;