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 "wine/debug.h"
28 #include "ddraw_private.h"
29 #include "dsurface/main.h"
30 #include "ddraw/main.h"
31 #include "dsurface/thunks.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
35 /** Creation/Destruction functions */
38 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl
*This
,
40 const DDSURFACEDESC2
*pDDSD
)
42 if (pDDSD
!= &This
->surface_desc
) {
43 This
->surface_desc
.dwSize
= sizeof(This
->surface_desc
);
44 DD_STRUCT_COPY_BYSIZE(&(This
->surface_desc
),pDDSD
);
46 This
->uniqueness_value
= 1; /* unchecked */
49 This
->local
.lpSurfMore
= &This
->more
;
50 This
->local
.lpGbl
= &This
->global
;
51 This
->local
.dwProcessId
= GetCurrentProcessId();
52 This
->local
.dwFlags
= 0; /* FIXME */
53 This
->local
.ddsCaps
.dwCaps
= This
->surface_desc
.ddsCaps
.dwCaps
;
54 /* FIXME: more local stuff */
55 This
->more
.lpDD_lcl
= &pDD
->local
;
56 This
->more
.ddsCapsEx
.dwCaps2
= This
->surface_desc
.ddsCaps
.dwCaps2
;
57 This
->more
.ddsCapsEx
.dwCaps3
= This
->surface_desc
.ddsCaps
.dwCaps3
;
58 This
->more
.ddsCapsEx
.dwCaps4
= This
->surface_desc
.ddsCaps
.dwCaps4
;
59 /* FIXME: more more stuff */
60 This
->gmore
= &This
->global_more
;
61 This
->global
.u3
.lpDD
= pDD
->local
.lpGbl
;
62 /* FIXME: more global stuff */
64 This
->final_release
= Main_DirectDrawSurface_final_release
;
65 This
->late_allocate
= Main_DirectDrawSurface_late_allocate
;
66 This
->attach
= Main_DirectDrawSurface_attach
;
67 This
->detach
= Main_DirectDrawSurface_detach
;
68 This
->lock_update
= Main_DirectDrawSurface_lock_update
;
69 This
->unlock_update
= Main_DirectDrawSurface_unlock_update
;
70 This
->lose_surface
= Main_DirectDrawSurface_lose_surface
;
71 This
->set_palette
= Main_DirectDrawSurface_set_palette
;
72 This
->update_palette
= Main_DirectDrawSurface_update_palette
;
73 This
->get_display_window
= Main_DirectDrawSurface_get_display_window
;
74 This
->get_gamma_ramp
= Main_DirectDrawSurface_get_gamma_ramp
;
75 This
->set_gamma_ramp
= Main_DirectDrawSurface_set_gamma_ramp
;
77 ICOM_INIT_INTERFACE(This
, IDirectDrawSurface3
,
78 DDRAW_IDDS3_Thunk_VTable
);
79 ICOM_INIT_INTERFACE(This
, IDirectDrawGammaControl
,
81 /* There is no generic implementation of IDDS7 */
83 Main_DirectDraw_AddSurface(pDD
, This
);
87 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl
* This
)
89 Main_DirectDraw_RemoveSurface(This
->ddraw_owner
, This
);
92 HRESULT
Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl
* This
)
97 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl
* This
)
99 This
->final_release(This
);
100 if (This
->private != This
+1) HeapFree(GetProcessHeap(), 0, This
->private);
101 HeapFree(GetProcessHeap(), 0, This
);
104 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl
* This
)
106 WARN("destroying surface %p with refcnt %lu\n", This
, This
->ref
);
107 Main_DirectDrawSurface_Destroy(This
);
110 ULONG WINAPI
Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface
)
112 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
114 if (--This
->ref
== 0)
116 if (This
->aux_release
)
117 This
->aux_release(This
->aux_ctx
, This
->aux_data
);
118 Main_DirectDrawSurface_Destroy(This
);
125 ULONG WINAPI
Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface
)
127 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
133 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface
, REFIID riid
,
136 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
137 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppObj
);
139 if (IsEqualGUID(&IID_IUnknown
, riid
)
140 || IsEqualGUID(&IID_IDirectDrawSurface7
, riid
)
141 || IsEqualGUID(&IID_IDirectDrawSurface4
, riid
))
144 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface7
);
147 else if (IsEqualGUID(&IID_IDirectDrawSurface
, riid
)
148 || IsEqualGUID(&IID_IDirectDrawSurface2
, riid
)
149 || IsEqualGUID(&IID_IDirectDrawSurface3
, riid
))
152 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface3
);
155 else if (IsEqualGUID(&IID_IDirectDrawGammaControl
, riid
))
158 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawGammaControl
);
162 return E_NOINTERFACE
;
168 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl
*This
,
169 IDirectDrawSurfaceImpl
*to
)
174 BOOL
Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl
*This
)
180 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
,
186 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl
* This
,
192 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl
* This
)
197 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl
* This
,
198 IDirectDrawPaletteImpl
* pal
)
203 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl
* This
,
204 IDirectDrawPaletteImpl
* pal
,
205 DWORD dwStart
, DWORD dwCount
,
206 LPPALETTEENTRY palent
)
211 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl
* This
)
217 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
219 LPDDGAMMARAMP lpGammaRamp
)
223 hr
= This
->get_dc(This
, &hDC
);
224 if (FAILED(hr
)) return hr
;
225 hr
= GetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
226 This
->release_dc(This
, hDC
);
231 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
233 LPDDGAMMARAMP lpGammaRamp
)
237 hr
= This
->get_dc(This
, &hDC
);
238 if (FAILED(hr
)) return hr
;
239 hr
= SetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
240 This
->release_dc(This
, hDC
);
245 /*** Interface functions */
248 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
249 LPDIRECTDRAWSURFACE7 pAttach
)
251 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
252 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
253 IDirectDrawSurface7
, pAttach
);
255 TRACE("(%p)->(%p)\n",This
,pAttach
);
257 /* Does windows check this? */
259 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
261 /* Does windows check this? */
262 if (surf
->ddraw_owner
!= This
->ddraw_owner
)
263 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
265 if (surf
->surface_owner
!= NULL
)
266 return DDERR_SURFACEALREADYATTACHED
; /* unchecked */
268 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
269 * But apparently backbuffers and mipmaps can be attached too. */
271 /* Set MIPMAPSUBLEVEL if this seems to be one */
272 if (This
->surface_desc
.ddsCaps
.dwCaps
&
273 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
274 surf
->surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
275 /* FIXME: we should probably also add to dwMipMapCount of this
276 * and all parent surfaces (update create_texture if you do) */
279 /* Callback to allow the surface to do something special now that it is
280 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
281 if (!surf
->attach(surf
, This
))
282 return DDERR_CANNOTATTACHSURFACE
;
284 /* check: Where should it go in the chain? This puts it on the head. */
286 This
->attached
->prev_attached
= surf
;
287 surf
->next_attached
= This
->attached
;
288 surf
->prev_attached
= NULL
;
289 This
->attached
= surf
;
290 surf
->surface_owner
= This
;
292 IDirectDrawSurface7_AddRef(pAttach
);
297 /* MSDN: "not currently implemented." */
299 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface
,
302 TRACE("(%p)->(%p)\n",iface
,pRect
);
303 return DDERR_UNSUPPORTED
; /* unchecked */
306 /* MSDN: "not currently implemented." */
308 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface
,
309 LPDDBLTBATCH pBatch
, DWORD dwCount
,
312 TRACE("(%p)->(%p,%ld,%08lx)\n",iface
,pBatch
,dwCount
,dwFlags
);
313 return DDERR_UNSUPPORTED
; /* unchecked */
317 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface
)
319 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
320 volatile IDirectDrawSurfaceImpl
* vThis
= This
;
322 TRACE("(%p)\n",This
);
323 /* A uniquness value of 0 is apparently special.
324 * This needs to be checked. */
327 DWORD old_uniqueness_value
= vThis
->uniqueness_value
;
328 DWORD new_uniqueness_value
= old_uniqueness_value
+1;
330 if (old_uniqueness_value
== 0) break;
331 if (new_uniqueness_value
== 0) new_uniqueness_value
= 1;
333 if (InterlockedCompareExchange((LONG
*)&vThis
->uniqueness_value
,
334 old_uniqueness_value
,
335 new_uniqueness_value
)
336 == old_uniqueness_value
)
344 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
346 LPDIRECTDRAWSURFACE7 pAttach
)
348 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
349 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
350 IDirectDrawSurface7
, pAttach
);
352 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pAttach
);
354 if (!surf
|| (surf
->surface_owner
!= This
))
355 return DDERR_SURFACENOTATTACHED
; /* unchecked */
359 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
360 if (This
->surface_desc
.ddsCaps
.dwCaps
&
361 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
362 surf
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
363 /* FIXME: we should probably also subtract from dwMipMapCount of this
364 * and all parent surfaces */
367 if (surf
->next_attached
)
368 surf
->next_attached
->prev_attached
= surf
->prev_attached
;
369 if (surf
->prev_attached
)
370 surf
->prev_attached
->next_attached
= surf
->next_attached
;
371 if (This
->attached
== surf
)
372 This
->attached
= surf
->next_attached
;
374 IDirectDrawSurface7_Release(pAttach
);
380 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface
,
382 LPDDENUMSURFACESCALLBACK7 cb
)
384 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
385 IDirectDrawSurfaceImpl
* surf
;
387 TRACE("(%p)->(%p,%p)\n",This
,context
,cb
);
389 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
391 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
392 if (cb(ICOM_INTERFACE(surf
, IDirectDrawSurface7
), &surf
->surface_desc
,
393 context
) == DDENUMRET_CANCEL
)
401 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface
,
402 DWORD dwFlags
, LPVOID context
,
403 LPDDENUMSURFACESCALLBACK7 cb
)
405 TRACE("(%p)->(%08lx,%p,%p)\n",iface
,dwFlags
,context
,cb
);
409 BOOL
Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl
* front
,
410 IDirectDrawSurfaceImpl
* back
,
413 /* uniqueness_value? */
414 /* This is necessary. But is it safe? */
416 HDC tmp
= front
->hDC
;
417 front
->hDC
= back
->hDC
;
422 BOOL tmp
= front
->dc_in_use
;
423 front
->dc_in_use
= back
->dc_in_use
;
424 back
->dc_in_use
= tmp
;
428 FLATPTR tmp
= front
->global
.fpVidMem
;
429 front
->global
.fpVidMem
= back
->global
.fpVidMem
;
430 back
->global
.fpVidMem
= tmp
;
434 ULONG_PTR tmp
= front
->global_more
.hKernelSurface
;
435 front
->global_more
.hKernelSurface
= back
->global_more
.hKernelSurface
;
436 back
->global_more
.hKernelSurface
= tmp
;
443 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface
,
444 LPDIRECTDRAWSURFACE7 override
, DWORD dwFlags
)
446 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
447 IDirectDrawSurfaceImpl
* target
;
450 TRACE("(%p)->(%p,%08lx)\n",This
,override
,dwFlags
);
452 /* MSDN: "This method can be called only for a surface that has the
453 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
454 if ((This
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
455 != (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
456 return DDERR_NOTFLIPPABLE
;
459 if (This
->aux_flip(This
->aux_ctx
, This
->aux_data
))
462 /* 1. find the flip target */
463 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
464 if (override
== NULL
)
466 static DDSCAPS2 back_caps
= { DDSCAPS_BACKBUFFER
};
467 LPDIRECTDRAWSURFACE7 tgt
;
469 hr
= IDirectDrawSurface7_GetAttachedSurface(iface
, &back_caps
, &tgt
);
470 if (FAILED(hr
)) return DDERR_NOTFLIPPABLE
; /* unchecked */
472 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
474 IDirectDrawSurface7_Release(tgt
);
478 BOOL on_chain
= FALSE
;
479 IDirectDrawSurfaceImpl
* surf
;
481 /* MSDN: "The method fails if the specified [override] surface is not
482 * a member of the flipping chain." */
484 /* Verify that override is on this flip chain. We assume that
485 * surf is the head of the flipping chain, because it's the front
487 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
490 /* Either target is (indirectly) attached to This or This is
491 * (indirectly) attached to target. */
492 for (surf
= target
; surf
!= NULL
; surf
= surf
->surface_owner
)
502 return DDERR_INVALIDPARAMS
; /* unchecked */
505 TRACE("flip to backbuffer: %p\n",target
);
506 if (This
->flip_data(This
, target
, dwFlags
))
507 This
->flip_update(This
, dwFlags
);
512 static PrivateData
* find_private_data(IDirectDrawSurfaceImpl
*This
,
516 for (data
= This
->private_data
; data
!= NULL
; data
= data
->next
)
518 if (IsEqualGUID(&data
->tag
, tag
)) break;
525 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface
, REFGUID tag
)
527 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
530 data
= find_private_data(This
, tag
);
531 if (data
== NULL
) return DDERR_NOTFOUND
;
534 data
->prev
->next
= data
->next
;
536 data
->next
->prev
= data
->prev
;
538 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
540 if (data
->ptr
.object
!= NULL
)
541 IUnknown_Release(data
->ptr
.object
);
544 HeapFree(GetProcessHeap(), 0, data
->ptr
.data
);
546 HeapFree(GetProcessHeap(), 0, data
);
552 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
554 LPDIRECTDRAWSURFACE7
* ppSurface
)
556 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
557 IDirectDrawSurfaceImpl
* surf
;
558 IDirectDrawSurfaceImpl
* found
= NULL
;
560 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This
,pCaps
->dwCaps
, pCaps
->dwCaps2
,
561 pCaps
->dwCaps3
, pCaps
->dwCaps4
, ppSurface
);
563 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
565 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf
,
566 surf
->surface_desc
.ddsCaps
.dwCaps
,
567 surf
->surface_desc
.ddsCaps
.dwCaps2
,
568 surf
->surface_desc
.ddsCaps
.dwCaps3
,
569 surf
->surface_desc
.ddsCaps
.dwCaps4
);
570 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& pCaps
->dwCaps
) == pCaps
->dwCaps
)
571 && ((surf
->surface_desc
.ddsCaps
.dwCaps2
& pCaps
->dwCaps2
) == pCaps
->dwCaps2
))
573 /* MSDN: "This method fails if more than one surface is attached
574 * that matches the capabilities requested." */
577 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
578 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
579 to be correct, given what 3DMark expects from MipMapped surfaces.
580 We shall just continue instead. */
588 return DDERR_NOTFOUND
;
590 *ppSurface
= ICOM_INTERFACE(found
, IDirectDrawSurface7
);
592 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
593 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found
, IDirectDrawSurface7
));
598 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
600 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
605 case DDGBS_ISBLTDONE
:
609 return DDERR_INVALIDPARAMS
;
614 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface
, LPDDSCAPS2 pCaps
)
616 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
618 TRACE("(%p)->(%p)\n",This
,pCaps
);
619 *pCaps
= This
->surface_desc
.ddsCaps
;
624 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface
,
625 LPDIRECTDRAWCLIPPER
* ppClipper
)
627 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
629 TRACE("(%p)->(%p)\n",This
,ppClipper
);
630 if (This
->clipper
== NULL
)
631 return DDERR_NOCLIPPERATTACHED
;
633 *ppClipper
= ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
);
634 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This
->clipper
,
635 IDirectDrawClipper
));
640 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
,
643 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
644 * isn't there? That's like saying that an int isn't there. (Which MS
645 * has done in other docs.) */
647 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
649 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
653 *pCKey
= This
->surface_desc
.ddckCKDestBlt
;
656 case DDCKEY_DESTOVERLAY
:
657 *pCKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
661 *pCKey
= This
->surface_desc
.ddckCKSrcBlt
;
664 case DDCKEY_SRCOVERLAY
:
665 *pCKey
= This
->surface_desc
.ddckCKSrcOverlay
;
669 return DDERR_INVALIDPARAMS
;
675 /* XXX We need to do something with the DC if the surface gets lost. */
677 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface
, HDC
*phDC
)
681 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
683 TRACE("(%p)->(%p)\n",This
,phDC
);
691 return DDERR_DCALREADYCREATED
;
695 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
696 * thread has it locked, but GetDC does not. */
697 ddsd
.dwSize
= sizeof(ddsd
);
698 hr
= IDirectDrawSurface7_Lock(iface
, NULL
, &ddsd
, DDLOCK_READONLY
, 0);
705 hr
= This
->get_dc(This
, &This
->hDC
);
708 TRACE("returning %08x\n",This
->hDC
);
711 This
->dc_in_use
= TRUE
;
713 else WARN("No DC! Prepare for trouble\n");
720 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface
, LPVOID
* pDD
)
722 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
724 TRACE("(%p)->(%p)\n",This
,pDD
);
725 *pDD
= ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
);
726 IDirectDraw7_AddRef(ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
));
731 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
733 /* XXX: DDERR_INVALIDSURFACETYPE */
735 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
739 case DDGFS_ISFLIPDONE
:
743 return DDERR_INVALIDPARAMS
;
748 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface
, LPDWORD pdwMaxLOD
)
750 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
752 TRACE("(%p)->(%p)\n",This
,pdwMaxLOD
);
755 *pdwMaxLOD
= This
->max_lod
;
760 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
761 LPLONG pX
, LPLONG pY
)
763 return DDERR_NOTAOVERLAYSURFACE
;
767 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface
,
768 LPDIRECTDRAWPALETTE
* ppPalette
)
770 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
772 TRACE("(%p)->(%p)\n",This
,ppPalette
);
773 if (This
->palette
== NULL
)
774 return DDERR_NOPALETTEATTACHED
;
776 *ppPalette
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
777 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This
->palette
,
778 IDirectDrawPalette
));
783 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface
,
784 LPDDPIXELFORMAT pDDPixelFormat
)
786 /* What is DDERR_INVALIDSURFACETYPE for here? */
787 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
789 TRACE("(%p)->(%p)\n",This
,pDDPixelFormat
);
790 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat
,&This
->surface_desc
.u4
.ddpfPixelFormat
);
795 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface
,
798 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
800 TRACE("(%p)->(%p)\n",This
,pdwPriority
);
803 *pdwPriority
= This
->priority
;
808 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
809 REFGUID tag
, LPVOID pBuffer
,
810 LPDWORD pcbBufferSize
)
812 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
815 data
= find_private_data(This
, tag
);
816 if (data
== NULL
) return DDERR_NOTFOUND
;
818 /* This may not be right. */
819 if ((data
->flags
& DDSPD_VOLATILE
)
820 && data
->uniqueness_value
!= This
->uniqueness_value
)
821 return DDERR_EXPIRED
;
823 if (*pcbBufferSize
< data
->size
)
825 *pcbBufferSize
= data
->size
;
826 return DDERR_MOREDATA
;
829 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
831 *(LPUNKNOWN
*)pBuffer
= data
->ptr
.object
;
832 IUnknown_AddRef(data
->ptr
.object
);
836 memcpy(pBuffer
, data
->ptr
.data
, data
->size
);
843 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface
,
844 LPDDSURFACEDESC2 pDDSD
)
846 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
848 TRACE("(%p)->(%p)\n",This
,pDDSD
);
849 if ((pDDSD
->dwSize
< sizeof(DDSURFACEDESC
)) ||
850 (pDDSD
->dwSize
> sizeof(DDSURFACEDESC2
))) {
851 ERR("Impossible/Strange struct size %ld.\n",pDDSD
->dwSize
);
852 return DDERR_GENERIC
;
855 DD_STRUCT_COPY_BYSIZE(pDDSD
,&This
->surface_desc
);
856 if (TRACE_ON(ddraw
)) {
857 DDRAW_dump_surface_desc(pDDSD
);
863 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface
,
866 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
868 TRACE("(%p)->(%p)\n",This
,pValue
);
869 *pValue
= This
->uniqueness_value
;
874 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface
,
875 LPDIRECTDRAW pDD
, LPDDSURFACEDESC2 pDDSD
)
877 TRACE("(%p)->(%p,%p)\n",iface
,pDD
,pDDSD
);
878 return DDERR_ALREADYINITIALIZED
;
882 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface
)
884 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
886 TRACE("(%p) is%s lost\n",This
, (This
->lost
? "" : " not"));
887 return This
->lost
? DDERR_SURFACELOST
: DD_OK
;
891 /* XXX This doesn't actually do any locking or keep track of the locked
892 * rectangles. The behaviour is poorly documented. */
894 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface
, LPRECT prect
,
895 LPDDSURFACEDESC2 pDDSD
, DWORD flags
, HANDLE h
)
897 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
899 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This
,prect
,pDDSD
,flags
,(DWORD
)h
);
901 if (flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
))
902 WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
903 This
,prect
,pDDSD
,flags
,(DWORD
)h
);
905 /* First, copy the Surface description */
906 DD_STRUCT_COPY_BYSIZE(pDDSD
,&(This
->surface_desc
));
908 TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
909 pDDSD
->dwHeight
,pDDSD
->dwWidth
,pDDSD
->u1
.lPitch
);
911 /* If asked only for a part, change the surface pointer.
912 * (Not documented.) */
914 TRACE(" lprect: %dx%d-%dx%d\n",
915 prect
->top
,prect
->left
,prect
->bottom
,prect
->right
917 if ((prect
->top
< 0) ||
919 (prect
->bottom
< 0) ||
920 (prect
->right
< 0)) {
921 ERR(" Negative values in LPRECT !!!\n");
922 return DDERR_INVALIDPARAMS
;
925 This
->lock_update(This
, prect
, flags
);
927 pDDSD
->lpSurface
= (char *)This
->surface_desc
.lpSurface
928 + prect
->top
* This
->surface_desc
.u1
.lPitch
929 + prect
->left
* GET_BPP(This
->surface_desc
);
931 This
->lock_update(This
, NULL
, flags
);
938 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
940 /* Some surface types should return DDERR_CANTPAGELOCK. */
945 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
947 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
948 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
953 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface
, HDC hDC
)
956 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
958 TRACE("(%p)->(%08x)\n",This
,hDC
);
960 if (!This
->dc_in_use
|| This
->hDC
!= hDC
)
961 return DDERR_INVALIDPARAMS
;
963 This
->release_dc(This
, hDC
);
965 hr
= IDirectDrawSurface7_Unlock(iface
, NULL
);
966 if (FAILED(hr
)) return hr
;
968 This
->dc_in_use
= FALSE
;
977 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface
,
978 LPDIRECTDRAWCLIPPER pDDClipper
)
980 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
982 TRACE("(%p)->(%p)\n",This
,pDDClipper
);
983 if (pDDClipper
== ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
))
986 if (This
->clipper
!= NULL
)
987 IDirectDrawClipper_Release(ICOM_INTERFACE(This
->clipper
,
988 IDirectDrawClipper
));
990 This
->clipper
= ICOM_OBJECT(IDirectDrawClipperImpl
, IDirectDrawClipper
,
992 if (pDDClipper
!= NULL
)
993 IDirectDrawClipper_AddRef(pDDClipper
);
999 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface
,
1000 DWORD dwFlags
, LPDDCOLORKEY pCKey
)
1002 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1004 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
1007 FIXME("supposedly removing color key %lu\n",
1008 dwFlags
& ~DDCKEY_COLORSPACE
);
1012 switch (dwFlags
& ~DDCKEY_COLORSPACE
)
1014 case DDCKEY_DESTBLT
:
1015 This
->surface_desc
.ddckCKDestBlt
= *pCKey
;
1018 case DDCKEY_DESTOVERLAY
:
1019 This
->surface_desc
.u3
.ddckCKDestOverlay
= *pCKey
;
1022 case DDCKEY_SRCOVERLAY
:
1023 This
->surface_desc
.ddckCKSrcOverlay
= *pCKey
;
1027 This
->surface_desc
.ddckCKSrcBlt
= *pCKey
;
1031 return DDERR_INVALIDPARAMS
;
1038 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface
, DWORD dwMaxLOD
)
1040 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1042 TRACE("(%p)->(%08lx)\n",This
,dwMaxLOD
);
1043 CHECK_TEXTURE(This
);
1045 This
->max_lod
= dwMaxLOD
;
1050 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
1053 return DDERR_NOTAOVERLAYSURFACE
;
1057 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface
,
1058 LPDIRECTDRAWPALETTE pPalette
)
1060 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1062 TRACE("(%p)->(%p)\n",This
,pPalette
);
1063 if (pPalette
== ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
))
1066 if (This
->palette
!= NULL
) {
1067 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1068 This
->palette
->global
.dwFlags
&= ~DDPCAPS_PRIMARYSURFACE
;
1069 IDirectDrawPalette_Release(ICOM_INTERFACE(This
->palette
,
1070 IDirectDrawPalette
));
1073 This
->palette
= ICOM_OBJECT(IDirectDrawPaletteImpl
, IDirectDrawPalette
,
1075 if (pPalette
!= NULL
) {
1076 IDirectDrawPalette_AddRef(pPalette
);
1077 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1078 This
->palette
->global
.dwFlags
|= DDPCAPS_PRIMARYSURFACE
;
1081 This
->set_palette(This
, This
->palette
);
1087 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface
,
1090 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1092 TRACE("(%p)->(%08lx)\n",This
,dwPriority
);
1093 CHECK_TEXTURE(This
);
1095 This
->priority
= dwPriority
;
1099 /* Be careful when locking this: it is risky to call the object's AddRef
1100 * or Release holding a lock. */
1102 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
1103 REFGUID tag
, LPVOID pData
,
1104 DWORD cbSize
, DWORD dwFlags
)
1107 ICOM_THIS(IDirectDrawSurfaceImpl
, iface
);
1109 data
= find_private_data(This
, tag
);
1112 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
1113 if (data
== NULL
) return DDERR_OUTOFMEMORY
;
1116 data
->flags
= dwFlags
;
1117 data
->uniqueness_value
= This
->uniqueness_value
;
1119 if (dwFlags
& DDSPD_IUNKNOWNPTR
)
1121 data
->ptr
.object
= (LPUNKNOWN
)pData
;
1122 data
->size
= sizeof(LPUNKNOWN
);
1123 IUnknown_AddRef(data
->ptr
.object
);
1127 data
->ptr
.data
= HeapAlloc(GetProcessHeap(), 0, cbSize
);
1128 if (data
->ptr
.data
== NULL
)
1130 HeapFree(GetProcessHeap(), 0, data
);
1131 return DDERR_OUTOFMEMORY
;
1136 data
->next
= This
->private_data
;
1138 if (This
->private_data
)
1139 This
->private_data
->prev
= data
;
1140 This
->private_data
= data
;
1146 /* I don't actually know how windows handles this case. The only
1147 * reason I don't just call FreePrivateData is because I want to
1148 * guarantee SetPrivateData working when using LPUNKNOWN or data
1149 * that is no larger than the old data. */
1155 /* SetSurfaceDesc */
1158 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface
, LPRECT pRect
)
1160 ICOM_THIS(IDirectDrawSurfaceImpl
,iface
);
1162 TRACE("(%p)->Unlock(%p)\n",This
,pRect
);
1164 This
->unlock_update(This
, pRect
);
1165 if (This
->aux_unlock
)
1166 This
->aux_unlock(This
->aux_ctx
, This
->aux_data
, pRect
);
1172 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface
,
1174 LPDIRECTDRAWSURFACE7 pDstSurface
,
1175 LPRECT pDstRect
, DWORD dwFlags
,
1178 return DDERR_UNSUPPORTED
;
1181 /* MSDN: "not currently implemented." */
1183 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface
,
1186 return DDERR_UNSUPPORTED
;
1190 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface
,
1192 LPDIRECTDRAWSURFACE7 pDDSRef
)
1194 return DDERR_NOTAOVERLAYSURFACE
;