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
27 #include "mesa_private.h"
28 #include "wine/debug.h"
29 #include "ddraw_private.h"
30 #include "dsurface/main.h"
31 #include "ddraw/main.h"
32 #include "dsurface/thunks.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
36 /** Creation/Destruction functions */
39 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl
*This
,
41 const DDSURFACEDESC2
*pDDSD
)
43 TRACE("(%p)->(%p,%p)\n", This
, pDD
, pDDSD
);
45 if (pDDSD
!= &This
->surface_desc
) {
46 This
->surface_desc
.dwSize
= sizeof(This
->surface_desc
);
47 DD_STRUCT_COPY_BYSIZE(&(This
->surface_desc
),pDDSD
);
49 This
->uniqueness_value
= 1; /* unchecked */
52 This
->local
.lpSurfMore
= &This
->more
;
53 This
->local
.lpGbl
= &This
->global
;
54 This
->local
.dwProcessId
= GetCurrentProcessId();
55 This
->local
.dwFlags
= 0; /* FIXME */
56 This
->local
.ddsCaps
.dwCaps
= This
->surface_desc
.ddsCaps
.dwCaps
;
57 /* FIXME: more local stuff */
58 This
->more
.lpDD_lcl
= &pDD
->local
;
59 This
->more
.ddsCapsEx
.dwCaps2
= This
->surface_desc
.ddsCaps
.dwCaps2
;
60 This
->more
.ddsCapsEx
.dwCaps3
= This
->surface_desc
.ddsCaps
.dwCaps3
;
61 This
->more
.ddsCapsEx
.dwCaps4
= This
->surface_desc
.ddsCaps
.dwCaps4
;
62 /* FIXME: more more stuff */
63 This
->gmore
= &This
->global_more
;
64 This
->global
.u3
.lpDD
= pDD
->local
.lpGbl
;
65 /* FIXME: more global stuff */
67 This
->final_release
= Main_DirectDrawSurface_final_release
;
68 This
->late_allocate
= Main_DirectDrawSurface_late_allocate
;
69 This
->attach
= Main_DirectDrawSurface_attach
;
70 This
->detach
= Main_DirectDrawSurface_detach
;
71 This
->lock_update
= Main_DirectDrawSurface_lock_update
;
72 This
->unlock_update
= Main_DirectDrawSurface_unlock_update
;
73 This
->lose_surface
= Main_DirectDrawSurface_lose_surface
;
74 This
->set_palette
= Main_DirectDrawSurface_set_palette
;
75 This
->update_palette
= Main_DirectDrawSurface_update_palette
;
76 This
->get_display_window
= Main_DirectDrawSurface_get_display_window
;
77 This
->get_gamma_ramp
= Main_DirectDrawSurface_get_gamma_ramp
;
78 This
->set_gamma_ramp
= Main_DirectDrawSurface_set_gamma_ramp
;
80 ICOM_INIT_INTERFACE(This
, IDirectDrawSurface3
,
81 DDRAW_IDDS3_Thunk_VTable
);
82 ICOM_INIT_INTERFACE(This
, IDirectDrawGammaControl
,
85 /* There is no generic implementation of IDDS7 or texture */
87 Main_DirectDraw_AddSurface(pDD
, This
);
91 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl
* This
)
93 Main_DirectDraw_RemoveSurface(This
->ddraw_owner
, This
);
96 HRESULT
Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl
* This
)
101 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl
* This
)
103 This
->final_release(This
);
104 if (This
->private != This
+1) HeapFree(GetProcessHeap(), 0, This
->private);
105 if (This
->tex_private
) HeapFree(GetProcessHeap(), 0, This
->tex_private
);
106 HeapFree(GetProcessHeap(), 0, This
);
109 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl
* This
)
111 WARN("destroying surface %p with refcnt %lu\n", This
, This
->ref
);
112 Main_DirectDrawSurface_Destroy(This
);
115 ULONG WINAPI
Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface
)
117 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
119 TRACE("(%p)->(): decreasing from %ld\n", This
, This
->ref
);
121 if (--This
->ref
== 0)
123 if (This
->aux_release
)
124 This
->aux_release(This
->aux_ctx
, This
->aux_data
);
125 Main_DirectDrawSurface_Destroy(This
);
127 TRACE("released surface %p\n", This
);
135 ULONG WINAPI
Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface
)
137 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
139 TRACE("(%p)->(): increasing from %ld\n", This
, This
->ref
);
145 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface
, REFIID riid
,
148 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
149 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppObj
);
153 if (IsEqualGUID(&IID_IUnknown
, riid
)
154 || IsEqualGUID(&IID_IDirectDrawSurface7
, riid
)
155 || IsEqualGUID(&IID_IDirectDrawSurface4
, riid
))
158 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface7
);
161 else if (IsEqualGUID(&IID_IDirectDrawSurface
, riid
)
162 || IsEqualGUID(&IID_IDirectDrawSurface2
, riid
)
163 || IsEqualGUID(&IID_IDirectDrawSurface3
, riid
))
166 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface3
);
169 else if (IsEqualGUID(&IID_IDirectDrawGammaControl
, riid
))
172 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawGammaControl
);
176 else if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL
, riid
) ||
177 IsEqualGUID( &IID_IDirect3DHALDevice
, riid
) )
179 IDirect3DDeviceImpl
*d3ddevimpl
;
182 ret_value
= d3ddevice_create(&d3ddevimpl
, This
->ddraw_owner
->d3d
, This
);
183 if (FAILED(ret_value
)) return ret_value
;
185 *ppObj
= ICOM_INTERFACE(d3ddevimpl
, IDirect3DDevice
);
186 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj
);
188 This
->ref
++; /* No idea if this is correct.. Need to check using real Windows */
191 else if (IsEqualGUID( &IID_IDirect3DTexture
, riid
) ||
192 IsEqualGUID( &IID_IDirect3DTexture2
, riid
))
194 HRESULT ret_value
= S_OK
;
196 /* In case the texture surface was created before the D3D creation */
197 if ((This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
) == 0) return E_NOINTERFACE
;
198 /* Create a 'delayed' private field only if it is not an offscreen texture... */
199 if (This
->tex_private
== NULL
) {
200 if (This
->ddraw_owner
->d3d
== NULL
) {
201 ERR("Texture created with no D3D object yet.. Not supported !\n");
202 return E_NOINTERFACE
;
205 if (((This
->surface_desc
.dwFlags
& DDSD_MIPMAPCOUNT
) &&
206 (This
->surface_desc
.u2
.dwMipMapCount
> 1)) ||
207 (This
->surface_desc
.ddsCaps
.dwCaps2
& DDSCAPS2_MIPMAPSUBLEVEL
)) {
208 ERR(" need to fix mipmaping in this case !!\n");
211 ret_value
= This
->ddraw_owner
->d3d
->create_texture(This
->ddraw_owner
->d3d
, This
, FALSE
, NULL
, 0);
212 if (FAILED(ret_value
)) return ret_value
;
214 if (IsEqualGUID( &IID_IDirect3DTexture
, riid
)) {
215 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture
);
216 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj
);
218 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture2
);
219 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj
);
226 return E_NOINTERFACE
;
232 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl
*This
,
233 IDirectDrawSurfaceImpl
*to
)
238 BOOL
Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl
*This
)
244 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
,
250 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl
* This
,
256 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl
* This
)
261 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl
* This
,
262 IDirectDrawPaletteImpl
* pal
)
267 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl
* This
,
268 IDirectDrawPaletteImpl
* pal
,
269 DWORD dwStart
, DWORD dwCount
,
270 LPPALETTEENTRY palent
)
275 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl
* This
)
281 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
283 LPDDGAMMARAMP lpGammaRamp
)
287 hr
= This
->get_dc(This
, &hDC
);
288 if (FAILED(hr
)) return hr
;
289 hr
= GetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
290 This
->release_dc(This
, hDC
);
295 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
297 LPDDGAMMARAMP lpGammaRamp
)
301 hr
= This
->get_dc(This
, &hDC
);
302 if (FAILED(hr
)) return hr
;
303 hr
= SetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
304 This
->release_dc(This
, hDC
);
309 /*** Interface functions */
312 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
313 LPDIRECTDRAWSURFACE7 pAttach
)
315 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
316 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
317 IDirectDrawSurface7
, pAttach
);
319 TRACE("(%p)->(%p)\n",This
,pAttach
);
321 /* Does windows check this? */
323 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
325 /* Does windows check this? */
326 if (surf
->ddraw_owner
!= This
->ddraw_owner
)
327 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
329 if (surf
->surface_owner
!= NULL
)
330 return DDERR_SURFACEALREADYATTACHED
; /* unchecked */
332 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
333 * But apparently backbuffers and mipmaps can be attached too. */
335 /* Set MIPMAPSUBLEVEL if this seems to be one */
336 if (This
->surface_desc
.ddsCaps
.dwCaps
&
337 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
338 surf
->surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
339 /* FIXME: we should probably also add to dwMipMapCount of this
340 * and all parent surfaces (update create_texture if you do) */
343 /* Callback to allow the surface to do something special now that it is
344 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
345 if (!surf
->attach(surf
, This
))
346 return DDERR_CANNOTATTACHSURFACE
;
348 /* check: Where should it go in the chain? This puts it on the head. */
350 This
->attached
->prev_attached
= surf
;
351 surf
->next_attached
= This
->attached
;
352 surf
->prev_attached
= NULL
;
353 This
->attached
= surf
;
354 surf
->surface_owner
= This
;
356 IDirectDrawSurface7_AddRef(pAttach
);
361 /* MSDN: "not currently implemented." */
363 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface
,
366 TRACE("(%p)->(%p)\n",iface
,pRect
);
367 return DDERR_UNSUPPORTED
; /* unchecked */
370 /* MSDN: "not currently implemented." */
372 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface
,
373 LPDDBLTBATCH pBatch
, DWORD dwCount
,
376 TRACE("(%p)->(%p,%ld,%08lx)\n",iface
,pBatch
,dwCount
,dwFlags
);
377 return DDERR_UNSUPPORTED
; /* unchecked */
381 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface
)
383 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
384 volatile IDirectDrawSurfaceImpl
* vThis
= This
;
386 TRACE("(%p)\n",This
);
387 /* A uniquness value of 0 is apparently special.
388 * This needs to be checked. */
391 DWORD old_uniqueness_value
= vThis
->uniqueness_value
;
392 DWORD new_uniqueness_value
= old_uniqueness_value
+1;
394 if (old_uniqueness_value
== 0) break;
395 if (new_uniqueness_value
== 0) new_uniqueness_value
= 1;
397 if (InterlockedCompareExchange((LONG
*)&vThis
->uniqueness_value
,
398 old_uniqueness_value
,
399 new_uniqueness_value
)
400 == old_uniqueness_value
)
408 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
410 LPDIRECTDRAWSURFACE7 pAttach
)
412 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
413 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
414 IDirectDrawSurface7
, pAttach
);
416 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pAttach
);
418 if (!surf
|| (surf
->surface_owner
!= This
))
419 return DDERR_SURFACENOTATTACHED
; /* unchecked */
423 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
424 if (This
->surface_desc
.ddsCaps
.dwCaps
&
425 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
426 surf
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
427 /* FIXME: we should probably also subtract from dwMipMapCount of this
428 * and all parent surfaces */
431 if (surf
->next_attached
)
432 surf
->next_attached
->prev_attached
= surf
->prev_attached
;
433 if (surf
->prev_attached
)
434 surf
->prev_attached
->next_attached
= surf
->next_attached
;
435 if (This
->attached
== surf
)
436 This
->attached
= surf
->next_attached
;
438 IDirectDrawSurface7_Release(pAttach
);
444 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface
,
446 LPDDENUMSURFACESCALLBACK7 cb
)
448 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
449 IDirectDrawSurfaceImpl
* surf
;
451 TRACE("(%p)->(%p,%p)\n",This
,context
,cb
);
453 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
455 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
456 if (cb(ICOM_INTERFACE(surf
, IDirectDrawSurface7
), &surf
->surface_desc
,
457 context
) == DDENUMRET_CANCEL
)
465 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface
,
466 DWORD dwFlags
, LPVOID context
,
467 LPDDENUMSURFACESCALLBACK7 cb
)
469 TRACE("(%p)->(%08lx,%p,%p)\n",iface
,dwFlags
,context
,cb
);
473 BOOL
Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl
* front
,
474 IDirectDrawSurfaceImpl
* back
,
477 /* uniqueness_value? */
478 /* This is necessary. But is it safe? */
480 HDC tmp
= front
->hDC
;
481 front
->hDC
= back
->hDC
;
486 BOOL tmp
= front
->dc_in_use
;
487 front
->dc_in_use
= back
->dc_in_use
;
488 back
->dc_in_use
= tmp
;
492 FLATPTR tmp
= front
->global
.fpVidMem
;
493 front
->global
.fpVidMem
= back
->global
.fpVidMem
;
494 back
->global
.fpVidMem
= tmp
;
498 ULONG_PTR tmp
= front
->global_more
.hKernelSurface
;
499 front
->global_more
.hKernelSurface
= back
->global_more
.hKernelSurface
;
500 back
->global_more
.hKernelSurface
= tmp
;
507 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface
,
508 LPDIRECTDRAWSURFACE7 override
, DWORD dwFlags
)
510 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
511 IDirectDrawSurfaceImpl
* target
;
514 TRACE("(%p)->(%p,%08lx)\n",This
,override
,dwFlags
);
516 /* MSDN: "This method can be called only for a surface that has the
517 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
518 if ((This
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
519 != (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
520 return DDERR_NOTFLIPPABLE
;
523 if (This
->aux_flip(This
->aux_ctx
, This
->aux_data
))
526 /* 1. find the flip target */
527 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
528 if (override
== NULL
)
530 static DDSCAPS2 back_caps
= { DDSCAPS_BACKBUFFER
};
531 LPDIRECTDRAWSURFACE7 tgt
;
533 hr
= IDirectDrawSurface7_GetAttachedSurface(iface
, &back_caps
, &tgt
);
534 if (FAILED(hr
)) return DDERR_NOTFLIPPABLE
; /* unchecked */
536 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
538 IDirectDrawSurface7_Release(tgt
);
542 BOOL on_chain
= FALSE
;
543 IDirectDrawSurfaceImpl
* surf
;
545 /* MSDN: "The method fails if the specified [override] surface is not
546 * a member of the flipping chain." */
548 /* Verify that override is on this flip chain. We assume that
549 * surf is the head of the flipping chain, because it's the front
551 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
554 /* Either target is (indirectly) attached to This or This is
555 * (indirectly) attached to target. */
556 for (surf
= target
; surf
!= NULL
; surf
= surf
->surface_owner
)
566 return DDERR_INVALIDPARAMS
; /* unchecked */
569 TRACE("flip to backbuffer: %p\n",target
);
570 if (This
->flip_data(This
, target
, dwFlags
))
571 This
->flip_update(This
, dwFlags
);
576 static PrivateData
* find_private_data(IDirectDrawSurfaceImpl
*This
,
580 for (data
= This
->private_data
; data
!= NULL
; data
= data
->next
)
582 if (IsEqualGUID(&data
->tag
, tag
)) break;
589 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface
, REFGUID tag
)
591 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
594 data
= find_private_data(This
, tag
);
595 if (data
== NULL
) return DDERR_NOTFOUND
;
598 data
->prev
->next
= data
->next
;
600 data
->next
->prev
= data
->prev
;
602 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
604 if (data
->ptr
.object
!= NULL
)
605 IUnknown_Release(data
->ptr
.object
);
608 HeapFree(GetProcessHeap(), 0, data
->ptr
.data
);
610 HeapFree(GetProcessHeap(), 0, data
);
616 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
618 LPDIRECTDRAWSURFACE7
* ppSurface
)
620 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
621 IDirectDrawSurfaceImpl
* surf
;
622 IDirectDrawSurfaceImpl
* found
= NULL
;
625 if (TRACE_ON(ddraw
)) {
626 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This
,pCaps
->dwCaps
, pCaps
->dwCaps2
,
627 pCaps
->dwCaps3
, pCaps
->dwCaps4
, ppSurface
);
628 DPRINTF(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps
); DPRINTF("\n");
632 if ((This
->ddraw_owner
->local
.dwLocalFlags
& DDRAWILCL_DIRECTDRAW7
) == 0) {
633 /* As this is not a DirectDraw7 application, remove the garbage that some games
634 put in the new fields of the DDSCAPS2 structure. */
635 our_caps
.dwCaps2
= 0;
636 our_caps
.dwCaps3
= 0;
637 our_caps
.dwCaps4
= 0;
638 if (TRACE_ON(ddraw
)) {
639 DPRINTF(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps
); DPRINTF("\n");
643 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
645 if (TRACE_ON(ddraw
)) {
646 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf
,
647 surf
->surface_desc
.ddsCaps
.dwCaps
,
648 surf
->surface_desc
.ddsCaps
.dwCaps2
,
649 surf
->surface_desc
.ddsCaps
.dwCaps3
,
650 surf
->surface_desc
.ddsCaps
.dwCaps4
);
651 DPRINTF(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf
->surface_desc
.ddsCaps
)); DPRINTF("\n");
653 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
654 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
))
656 /* MSDN: "This method fails if more than one surface is attached
657 * that matches the capabilities requested." */
660 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
661 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
662 to be correct, given what 3DMark expects from MipMapped surfaces.
663 We shall just continue instead. */
671 TRACE("Did not find any valid surface\n");
672 return DDERR_NOTFOUND
;
675 *ppSurface
= ICOM_INTERFACE(found
, IDirectDrawSurface7
);
677 if (TRACE_ON(ddraw
)) {
678 TRACE("Returning surface %p with description : \n", *ppSurface
);
679 DDRAW_dump_surface_desc(&(found
->surface_desc
));
682 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
683 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found
, IDirectDrawSurface7
));
688 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
690 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
695 case DDGBS_ISBLTDONE
:
699 return DDERR_INVALIDPARAMS
;
704 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface
, LPDDSCAPS2 pCaps
)
706 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
708 TRACE("(%p)->(%p)\n",This
,pCaps
);
709 *pCaps
= This
->surface_desc
.ddsCaps
;
714 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface
,
715 LPDIRECTDRAWCLIPPER
* ppClipper
)
717 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
719 TRACE("(%p)->(%p)\n",This
,ppClipper
);
720 if (This
->clipper
== NULL
)
721 return DDERR_NOCLIPPERATTACHED
;
723 *ppClipper
= ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
);
724 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This
->clipper
,
725 IDirectDrawClipper
));
730 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
,
733 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
734 * isn't there? That's like saying that an int isn't there. (Which MS
735 * has done in other docs.) */
737 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
739 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
743 *pCKey
= This
->surface_desc
.ddckCKDestBlt
;
746 case DDCKEY_DESTOVERLAY
:
747 *pCKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
751 *pCKey
= This
->surface_desc
.ddckCKSrcBlt
;
754 case DDCKEY_SRCOVERLAY
:
755 *pCKey
= This
->surface_desc
.ddckCKSrcOverlay
;
759 return DDERR_INVALIDPARAMS
;
765 /* XXX We need to do something with the DC if the surface gets lost. */
767 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface
, HDC
*phDC
)
771 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
773 TRACE("(%p)->(%p)\n",This
,phDC
);
781 return DDERR_DCALREADYCREATED
;
785 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
786 * thread has it locked, but GetDC does not. */
787 ddsd
.dwSize
= sizeof(ddsd
);
788 hr
= IDirectDrawSurface7_Lock(iface
, NULL
, &ddsd
, DDLOCK_READONLY
, 0);
795 hr
= This
->get_dc(This
, &This
->hDC
);
798 TRACE("returning %p\n",This
->hDC
);
801 This
->dc_in_use
= TRUE
;
803 else WARN("No DC! Prepare for trouble\n");
810 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface
, LPVOID
* pDD
)
812 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
814 TRACE("(%p)->(%p)\n",This
,pDD
);
815 *pDD
= ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
);
816 IDirectDraw7_AddRef(ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
));
821 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
823 /* XXX: DDERR_INVALIDSURFACETYPE */
825 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
829 case DDGFS_ISFLIPDONE
:
833 return DDERR_INVALIDPARAMS
;
838 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface
, LPDWORD pdwMaxLOD
)
840 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
842 TRACE("(%p)->(%p)\n",This
,pdwMaxLOD
);
845 *pdwMaxLOD
= This
->max_lod
;
850 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
851 LPLONG pX
, LPLONG pY
)
853 return DDERR_NOTAOVERLAYSURFACE
;
857 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface
,
858 LPDIRECTDRAWPALETTE
* ppPalette
)
860 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
862 TRACE("(%p)->(%p)\n",This
,ppPalette
);
863 if (This
->palette
== NULL
)
864 return DDERR_NOPALETTEATTACHED
;
866 *ppPalette
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
867 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This
->palette
,
868 IDirectDrawPalette
));
873 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface
,
874 LPDDPIXELFORMAT pDDPixelFormat
)
876 /* What is DDERR_INVALIDSURFACETYPE for here? */
877 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
879 TRACE("(%p)->(%p)\n",This
,pDDPixelFormat
);
880 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat
,&This
->surface_desc
.u4
.ddpfPixelFormat
);
885 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface
,
888 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
890 TRACE("(%p)->(%p)\n",This
,pdwPriority
);
893 *pdwPriority
= This
->priority
;
898 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
899 REFGUID tag
, LPVOID pBuffer
,
900 LPDWORD pcbBufferSize
)
902 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
905 data
= find_private_data(This
, tag
);
906 if (data
== NULL
) return DDERR_NOTFOUND
;
908 /* This may not be right. */
909 if ((data
->flags
& DDSPD_VOLATILE
)
910 && data
->uniqueness_value
!= This
->uniqueness_value
)
911 return DDERR_EXPIRED
;
913 if (*pcbBufferSize
< data
->size
)
915 *pcbBufferSize
= data
->size
;
916 return DDERR_MOREDATA
;
919 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
921 *(LPUNKNOWN
*)pBuffer
= data
->ptr
.object
;
922 IUnknown_AddRef(data
->ptr
.object
);
926 memcpy(pBuffer
, data
->ptr
.data
, data
->size
);
933 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface
,
934 LPDDSURFACEDESC2 pDDSD
)
936 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
938 TRACE("(%p)->(%p)\n",This
,pDDSD
);
939 if ((pDDSD
->dwSize
< sizeof(DDSURFACEDESC
)) ||
940 (pDDSD
->dwSize
> sizeof(DDSURFACEDESC2
))) {
941 ERR("Impossible/Strange struct size %ld.\n",pDDSD
->dwSize
);
942 return DDERR_GENERIC
;
945 DD_STRUCT_COPY_BYSIZE(pDDSD
,&This
->surface_desc
);
946 if (TRACE_ON(ddraw
)) {
947 DDRAW_dump_surface_desc(pDDSD
);
953 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface
,
956 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
958 TRACE("(%p)->(%p)\n",This
,pValue
);
959 *pValue
= This
->uniqueness_value
;
964 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface
,
965 LPDIRECTDRAW pDD
, LPDDSURFACEDESC2 pDDSD
)
967 TRACE("(%p)->(%p,%p)\n",iface
,pDD
,pDDSD
);
968 return DDERR_ALREADYINITIALIZED
;
972 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface
)
974 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
976 TRACE("(%p) is%s lost\n",This
, (This
->lost
? "" : " not"));
977 return This
->lost
? DDERR_SURFACELOST
: DD_OK
;
981 /* XXX This doesn't actually do any locking or keep track of the locked
982 * rectangles. The behaviour is poorly documented. */
984 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface
, LPRECT prect
,
985 LPDDSURFACEDESC2 pDDSD
, DWORD flags
, HANDLE h
)
987 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
989 if (TRACE_ON(ddraw
)) {
990 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This
,prect
,pDDSD
,flags
,(DWORD
)h
);
991 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags
);
993 if (WARN_ON(ddraw
)) {
994 if (flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
)) {
995 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
));
999 /* First, copy the Surface description */
1000 DD_STRUCT_COPY_BYSIZE(pDDSD
,&(This
->surface_desc
));
1002 TRACE("locked surface returning description : \n");
1003 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(pDDSD
);
1005 /* Used to optimize the D3D Device locking */
1006 This
->lastlocktype
= flags
& (DDLOCK_READONLY
|DDLOCK_WRITEONLY
);
1008 /* If asked only for a part, change the surface pointer.
1009 * (Not documented.) */
1010 if (prect
!= NULL
) {
1011 TRACE(" lprect: %dx%d-%dx%d\n",
1012 prect
->top
,prect
->left
,prect
->bottom
,prect
->right
1014 if ((prect
->top
< 0) ||
1015 (prect
->left
< 0) ||
1016 (prect
->bottom
< 0) ||
1017 (prect
->right
< 0)) {
1018 ERR(" Negative values in LPRECT !!!\n");
1019 return DDERR_INVALIDPARAMS
;
1022 This
->lock_update(This
, prect
, flags
);
1024 pDDSD
->lpSurface
= (char *)This
->surface_desc
.lpSurface
1025 + prect
->top
* This
->surface_desc
.u1
.lPitch
1026 + prect
->left
* GET_BPP(This
->surface_desc
);
1028 This
->lock_update(This
, NULL
, flags
);
1035 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1037 /* Some surface types should return DDERR_CANTPAGELOCK. */
1042 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1044 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1045 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1050 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface
, HDC hDC
)
1053 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1055 TRACE("(%p)->(%p)\n",This
,hDC
);
1057 if (!This
->dc_in_use
|| This
->hDC
!= hDC
)
1058 return DDERR_INVALIDPARAMS
;
1060 This
->release_dc(This
, hDC
);
1062 hr
= IDirectDrawSurface7_Unlock(iface
, NULL
);
1063 if (FAILED(hr
)) return hr
;
1065 This
->dc_in_use
= FALSE
;
1074 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface
,
1075 LPDIRECTDRAWCLIPPER pDDClipper
)
1077 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1079 TRACE("(%p)->(%p)\n",This
,pDDClipper
);
1080 if (pDDClipper
== ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
))
1083 if (This
->clipper
!= NULL
)
1084 IDirectDrawClipper_Release(ICOM_INTERFACE(This
->clipper
,
1085 IDirectDrawClipper
));
1087 This
->clipper
= ICOM_OBJECT(IDirectDrawClipperImpl
, IDirectDrawClipper
,
1089 if (pDDClipper
!= NULL
)
1090 IDirectDrawClipper_AddRef(pDDClipper
);
1096 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface
,
1097 DWORD dwFlags
, LPDDCOLORKEY pCKey
)
1099 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1101 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
1104 FIXME("supposedly removing color key %lu\n",
1105 dwFlags
& ~DDCKEY_COLORSPACE
);
1109 switch (dwFlags
& ~DDCKEY_COLORSPACE
)
1111 case DDCKEY_DESTBLT
:
1112 This
->surface_desc
.ddckCKDestBlt
= *pCKey
;
1115 case DDCKEY_DESTOVERLAY
:
1116 This
->surface_desc
.u3
.ddckCKDestOverlay
= *pCKey
;
1119 case DDCKEY_SRCOVERLAY
:
1120 This
->surface_desc
.ddckCKSrcOverlay
= *pCKey
;
1124 This
->surface_desc
.ddckCKSrcBlt
= *pCKey
;
1128 return DDERR_INVALIDPARAMS
;
1135 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface
, DWORD dwMaxLOD
)
1137 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1139 TRACE("(%p)->(%08lx)\n",This
,dwMaxLOD
);
1140 CHECK_TEXTURE(This
);
1142 This
->max_lod
= dwMaxLOD
;
1147 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
1150 return DDERR_NOTAOVERLAYSURFACE
;
1154 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface
,
1155 LPDIRECTDRAWPALETTE pPalette
)
1157 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1159 TRACE("(%p)->(%p)\n",This
,pPalette
);
1160 if (pPalette
== ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
))
1163 if (This
->palette
!= NULL
) {
1164 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1165 This
->palette
->global
.dwFlags
&= ~DDPCAPS_PRIMARYSURFACE
;
1166 IDirectDrawPalette_Release(ICOM_INTERFACE(This
->palette
,
1167 IDirectDrawPalette
));
1170 This
->palette
= ICOM_OBJECT(IDirectDrawPaletteImpl
, IDirectDrawPalette
,
1172 if (pPalette
!= NULL
) {
1173 IDirectDrawPalette_AddRef(pPalette
);
1174 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1175 This
->palette
->global
.dwFlags
|= DDPCAPS_PRIMARYSURFACE
;
1178 This
->set_palette(This
, This
->palette
);
1184 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface
,
1187 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1189 TRACE("(%p)->(%08lx)\n",This
,dwPriority
);
1190 CHECK_TEXTURE(This
);
1192 This
->priority
= dwPriority
;
1196 /* Be careful when locking this: it is risky to call the object's AddRef
1197 * or Release holding a lock. */
1199 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
1200 REFGUID tag
, LPVOID pData
,
1201 DWORD cbSize
, DWORD dwFlags
)
1204 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1206 data
= find_private_data(This
, tag
);
1209 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
1210 if (data
== NULL
) return DDERR_OUTOFMEMORY
;
1213 data
->flags
= dwFlags
;
1214 data
->uniqueness_value
= This
->uniqueness_value
;
1216 if (dwFlags
& DDSPD_IUNKNOWNPTR
)
1218 data
->ptr
.object
= (LPUNKNOWN
)pData
;
1219 data
->size
= sizeof(LPUNKNOWN
);
1220 IUnknown_AddRef(data
->ptr
.object
);
1224 data
->ptr
.data
= HeapAlloc(GetProcessHeap(), 0, cbSize
);
1225 if (data
->ptr
.data
== NULL
)
1227 HeapFree(GetProcessHeap(), 0, data
);
1228 return DDERR_OUTOFMEMORY
;
1233 data
->next
= This
->private_data
;
1235 if (This
->private_data
)
1236 This
->private_data
->prev
= data
;
1237 This
->private_data
= data
;
1243 /* I don't actually know how windows handles this case. The only
1244 * reason I don't just call FreePrivateData is because I want to
1245 * guarantee SetPrivateData working when using LPUNKNOWN or data
1246 * that is no larger than the old data. */
1252 /* SetSurfaceDesc */
1255 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface
, LPRECT pRect
)
1257 ICOM_THIS(IDirectDrawSurfaceImpl
,iface
);
1259 TRACE("(%p)->Unlock(%p)\n",This
,pRect
);
1261 This
->unlock_update(This
, pRect
);
1262 if (This
->aux_unlock
)
1263 This
->aux_unlock(This
->aux_ctx
, This
->aux_data
, pRect
);
1269 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface
,
1271 LPDIRECTDRAWSURFACE7 pDstSurface
,
1272 LPRECT pDstRect
, DWORD dwFlags
,
1275 return DDERR_UNSUPPORTED
;
1278 /* MSDN: "not currently implemented." */
1280 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface
,
1283 return DDERR_UNSUPPORTED
;
1287 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface
,
1289 LPDIRECTDRAWSURFACE7 pDDSRef
)
1291 return DDERR_NOTAOVERLAYSURFACE
;