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
22 #include "wine/port.h"
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
32 #include "wine/debug.h"
33 #include "ddraw_private.h"
34 #include "opengl_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip
);
38 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps
);
40 /** Creation/Destruction functions */
43 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl
*This
,
45 const DDSURFACEDESC2
*pDDSD
)
47 TRACE("(%p)->(%p,%p)\n", This
, pDD
, pDDSD
);
49 if (pDDSD
!= &This
->surface_desc
) {
50 This
->surface_desc
.dwSize
= sizeof(This
->surface_desc
);
51 DD_STRUCT_COPY_BYSIZE(&(This
->surface_desc
),pDDSD
);
53 This
->uniqueness_value
= 1; /* unchecked */
56 This
->local
.lpSurfMore
= &This
->more
;
57 This
->local
.lpGbl
= &This
->global
;
58 This
->local
.dwProcessId
= GetCurrentProcessId();
59 This
->local
.dwFlags
= 0; /* FIXME */
60 This
->local
.ddsCaps
.dwCaps
= This
->surface_desc
.ddsCaps
.dwCaps
;
61 /* FIXME: more local stuff */
62 This
->more
.lpDD_lcl
= &pDD
->local
;
63 This
->more
.ddsCapsEx
.dwCaps2
= This
->surface_desc
.ddsCaps
.dwCaps2
;
64 This
->more
.ddsCapsEx
.dwCaps3
= This
->surface_desc
.ddsCaps
.dwCaps3
;
65 This
->more
.ddsCapsEx
.dwCaps4
= This
->surface_desc
.ddsCaps
.dwCaps4
;
66 /* FIXME: more more stuff */
67 This
->gmore
= &This
->global_more
;
68 This
->global
.u3
.lpDD
= pDD
->local
.lpGbl
;
69 /* FIXME: more global stuff */
71 This
->final_release
= Main_DirectDrawSurface_final_release
;
72 This
->late_allocate
= Main_DirectDrawSurface_late_allocate
;
73 This
->attach
= Main_DirectDrawSurface_attach
;
74 This
->detach
= Main_DirectDrawSurface_detach
;
75 This
->lock_update
= Main_DirectDrawSurface_lock_update
;
76 This
->unlock_update
= Main_DirectDrawSurface_unlock_update
;
77 This
->lose_surface
= Main_DirectDrawSurface_lose_surface
;
78 This
->set_palette
= Main_DirectDrawSurface_set_palette
;
79 This
->update_palette
= Main_DirectDrawSurface_update_palette
;
80 This
->get_display_window
= Main_DirectDrawSurface_get_display_window
;
81 This
->get_gamma_ramp
= Main_DirectDrawSurface_get_gamma_ramp
;
82 This
->set_gamma_ramp
= Main_DirectDrawSurface_set_gamma_ramp
;
84 ICOM_INIT_INTERFACE(This
, IDirectDrawSurface3
,
85 DDRAW_IDDS3_Thunk_VTable
);
86 ICOM_INIT_INTERFACE(This
, IDirectDrawGammaControl
,
89 /* There is no generic implementation of IDDS7 or texture */
91 Main_DirectDraw_AddSurface(pDD
, This
);
95 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl
* This
)
97 Main_DirectDraw_RemoveSurface(This
->ddraw_owner
, This
);
100 HRESULT
Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl
* This
)
105 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl
* This
)
108 IDirectDrawPalette_Release(ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
));
109 This
->palette
= NULL
;
111 This
->final_release(This
);
112 if (This
->private != This
+1) HeapFree(GetProcessHeap(), 0, This
->private);
113 if (This
->tex_private
) HeapFree(GetProcessHeap(), 0, This
->tex_private
);
114 HeapFree(GetProcessHeap(), 0, This
);
117 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl
* This
)
119 WARN("destroying surface %p with refcnt %lu\n", This
, This
->ref
);
120 Main_DirectDrawSurface_Destroy(This
);
123 ULONG WINAPI
Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface
)
125 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
126 ULONG ref
= InterlockedDecrement(&This
->ref
);
128 TRACE("(%p)->(): decreasing from %ld\n", This
, ref
+ 1);
132 if (This
->aux_release
)
133 This
->aux_release(This
->aux_ctx
, This
->aux_data
);
134 Main_DirectDrawSurface_Destroy(This
);
136 TRACE("released surface %p\n", This
);
144 ULONG WINAPI
Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface
)
146 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
147 ULONG ref
= InterlockedIncrement(&This
->ref
);
149 TRACE("(%p)->(): increasing from %ld\n", This
, ref
- 1);
155 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface
, REFIID riid
,
158 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
159 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(riid
), ppObj
);
164 return DDERR_INVALIDPARAMS
;
166 if (IsEqualGUID(&IID_IUnknown
, riid
)
167 || IsEqualGUID(&IID_IDirectDrawSurface7
, riid
)
168 || IsEqualGUID(&IID_IDirectDrawSurface4
, riid
))
170 InterlockedIncrement(&This
->ref
);
171 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface7
);
174 else if (IsEqualGUID(&IID_IDirectDrawSurface
, riid
)
175 || IsEqualGUID(&IID_IDirectDrawSurface2
, riid
)
176 || IsEqualGUID(&IID_IDirectDrawSurface3
, riid
))
178 InterlockedIncrement(&This
->ref
);
179 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawSurface3
);
182 else if (IsEqualGUID(&IID_IDirectDrawGammaControl
, riid
))
184 InterlockedIncrement(&This
->ref
);
185 *ppObj
= ICOM_INTERFACE(This
, IDirectDrawGammaControl
);
189 /* interfaces following here require OpenGL */
190 if( !opengl_initialized
)
191 return E_NOINTERFACE
;
193 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL
, riid
) ||
194 IsEqualGUID( &IID_IDirect3DHALDevice
, riid
) )
196 IDirect3DDeviceImpl
*d3ddevimpl
;
199 ret_value
= d3ddevice_create(&d3ddevimpl
, This
->ddraw_owner
, This
, 1);
200 if (FAILED(ret_value
)) return ret_value
;
202 *ppObj
= ICOM_INTERFACE(d3ddevimpl
, IDirect3DDevice
);
203 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj
);
205 InterlockedIncrement(&This
->ref
); /* No idea if this is correct.. Need to check using real Windows */
208 else if (IsEqualGUID( &IID_IDirect3DTexture
, riid
) ||
209 IsEqualGUID( &IID_IDirect3DTexture2
, riid
))
211 HRESULT ret_value
= S_OK
;
213 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
214 application I know creating a texture without this flag set and it will prevent
215 bugs in other parts of Wine.
217 This
->surface_desc
.ddsCaps
.dwCaps
|= DDSCAPS_TEXTURE
;
219 /* In case the texture surface was created before the D3D creation */
220 if (This
->tex_private
== NULL
) {
221 if (This
->ddraw_owner
->d3d_private
== NULL
) {
222 ERR("Texture created with no D3D object yet.. Not supported !\n");
223 return E_NOINTERFACE
;
226 ret_value
= This
->ddraw_owner
->d3d_create_texture(This
->ddraw_owner
, This
, FALSE
, This
->mip_main
);
227 if (FAILED(ret_value
)) return ret_value
;
229 if (IsEqualGUID( &IID_IDirect3DTexture
, riid
)) {
230 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture
);
231 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj
);
233 *ppObj
= ICOM_INTERFACE(This
, IDirect3DTexture2
);
234 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj
);
236 InterlockedIncrement(&This
->ref
);
241 return E_NOINTERFACE
;
247 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl
*This
,
248 IDirectDrawSurfaceImpl
*to
)
253 BOOL
Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl
*This
)
259 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
,
265 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl
* This
,
271 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl
* This
)
276 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl
* This
,
277 IDirectDrawPaletteImpl
* pal
)
282 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl
* This
,
283 IDirectDrawPaletteImpl
* pal
,
284 DWORD dwStart
, DWORD dwCount
,
285 LPPALETTEENTRY palent
)
290 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl
* This
)
296 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
298 LPDDGAMMARAMP lpGammaRamp
)
302 hr
= This
->get_dc(This
, &hDC
);
303 if (FAILED(hr
)) return hr
;
304 hr
= GetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
305 This
->release_dc(This
, hDC
);
310 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl
* This
,
312 LPDDGAMMARAMP lpGammaRamp
)
316 hr
= This
->get_dc(This
, &hDC
);
317 if (FAILED(hr
)) return hr
;
318 hr
= SetDeviceGammaRamp(hDC
, lpGammaRamp
) ? DD_OK
: DDERR_UNSUPPORTED
;
319 This
->release_dc(This
, hDC
);
324 /*** Interface functions */
327 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
328 LPDIRECTDRAWSURFACE7 pAttach
)
330 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
331 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
332 IDirectDrawSurface7
, pAttach
);
334 TRACE("(%p)->(%p)\n",This
,pAttach
);
336 /* Does windows check this? */
338 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
340 /* Does windows check this? */
341 if (surf
->ddraw_owner
!= This
->ddraw_owner
)
342 return DDERR_CANNOTATTACHSURFACE
; /* unchecked */
344 if (surf
->surface_owner
!= NULL
)
345 return DDERR_SURFACEALREADYATTACHED
; /* unchecked */
347 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
348 * But apparently backbuffers and mipmaps can be attached too. */
350 /* Set MIPMAPSUBLEVEL if this seems to be one */
351 if (This
->surface_desc
.ddsCaps
.dwCaps
&
352 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
353 surf
->surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
354 /* FIXME: we should probably also add to dwMipMapCount of this
355 * and all parent surfaces (update create_texture if you do) */
358 /* Callback to allow the surface to do something special now that it is
359 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
360 if (!surf
->attach(surf
, This
))
361 return DDERR_CANNOTATTACHSURFACE
;
363 /* check: Where should it go in the chain? This puts it on the head. */
365 This
->attached
->prev_attached
= surf
;
366 surf
->next_attached
= This
->attached
;
367 surf
->prev_attached
= NULL
;
368 This
->attached
= surf
;
369 surf
->surface_owner
= This
;
371 IDirectDrawSurface7_AddRef(pAttach
);
376 /* MSDN: "not currently implemented." */
378 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface
,
381 TRACE("(%p)->(%p)\n",iface
,pRect
);
382 return DDERR_UNSUPPORTED
; /* unchecked */
385 /* MSDN: "not currently implemented." */
387 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface
,
388 LPDDBLTBATCH pBatch
, DWORD dwCount
,
391 TRACE("(%p)->(%p,%ld,%08lx)\n",iface
,pBatch
,dwCount
,dwFlags
);
392 return DDERR_UNSUPPORTED
; /* unchecked */
396 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface
)
398 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
399 volatile IDirectDrawSurfaceImpl
* vThis
= This
;
401 TRACE("(%p)\n",This
);
402 /* A uniquness value of 0 is apparently special.
403 * This needs to be checked. */
406 DWORD old_uniqueness_value
= vThis
->uniqueness_value
;
407 DWORD new_uniqueness_value
= old_uniqueness_value
+1;
409 if (old_uniqueness_value
== 0) break;
410 if (new_uniqueness_value
== 0) new_uniqueness_value
= 1;
412 if (InterlockedCompareExchange((LONG
*)&vThis
->uniqueness_value
,
413 old_uniqueness_value
,
414 new_uniqueness_value
)
415 == old_uniqueness_value
)
423 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
425 LPDIRECTDRAWSURFACE7 pAttach
)
427 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
428 IDirectDrawSurfaceImpl
* surf
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
429 IDirectDrawSurface7
, pAttach
);
431 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pAttach
);
433 if (!surf
|| (surf
->surface_owner
!= This
))
434 return DDERR_SURFACENOTATTACHED
; /* unchecked */
438 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
439 if (This
->surface_desc
.ddsCaps
.dwCaps
&
440 surf
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) {
441 surf
->surface_desc
.ddsCaps
.dwCaps2
&= ~DDSCAPS2_MIPMAPSUBLEVEL
;
442 /* FIXME: we should probably also subtract from dwMipMapCount of this
443 * and all parent surfaces */
446 if (surf
->next_attached
)
447 surf
->next_attached
->prev_attached
= surf
->prev_attached
;
448 if (surf
->prev_attached
)
449 surf
->prev_attached
->next_attached
= surf
->next_attached
;
450 if (This
->attached
== surf
)
451 This
->attached
= surf
->next_attached
;
453 IDirectDrawSurface7_Release(pAttach
);
459 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface
,
461 LPDDENUMSURFACESCALLBACK7 cb
)
463 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
464 IDirectDrawSurfaceImpl
* surf
;
467 TRACE("(%p)->(%p,%p)\n",This
,context
,cb
);
469 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
471 LPDIRECTDRAWSURFACE7 isurf
= ICOM_INTERFACE(surf
, IDirectDrawSurface7
);
473 if (TRACE_ON(ddraw
)) {
474 TRACE(" => enumerating surface %p (priv. %p) with description:\n", isurf
, surf
);
475 DDRAW_dump_surface_desc(&surf
->surface_desc
);
478 IDirectDrawSurface7_AddRef(isurf
);
479 desc
= surf
->surface_desc
;
480 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
481 if (cb(isurf
, &desc
, context
) == DDENUMRET_CANCEL
)
485 TRACE(" end of enumeration.\n");
491 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface
,
492 DWORD dwFlags
, LPVOID context
,
493 LPDDENUMSURFACESCALLBACK7 cb
)
495 TRACE("(%p)->(%08lx,%p,%p)\n",iface
,dwFlags
,context
,cb
);
499 BOOL
Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl
* front
,
500 IDirectDrawSurfaceImpl
* back
,
503 /* uniqueness_value? */
504 /* This is necessary. But is it safe? */
506 HDC tmp
= front
->hDC
;
507 front
->hDC
= back
->hDC
;
512 BOOL tmp
= front
->dc_in_use
;
513 front
->dc_in_use
= back
->dc_in_use
;
514 back
->dc_in_use
= tmp
;
518 FLATPTR tmp
= front
->global
.fpVidMem
;
519 front
->global
.fpVidMem
= back
->global
.fpVidMem
;
520 back
->global
.fpVidMem
= tmp
;
524 ULONG_PTR tmp
= front
->global_more
.hKernelSurface
;
525 front
->global_more
.hKernelSurface
= back
->global_more
.hKernelSurface
;
526 back
->global_more
.hKernelSurface
= tmp
;
532 /* This is unnecessarely complicated :-) */
533 #define MEASUREMENT_WINDOW 5
534 #define NUMBER_OF_WINDOWS 10
536 static LONGLONG perf_freq
;
537 static LONGLONG perf_storage
[NUMBER_OF_WINDOWS
];
538 static LONGLONG prev_time
= 0;
539 static unsigned int current_window
;
540 static unsigned int measurements_in_window
;
541 static unsigned int valid_windows
;
544 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface
,
545 LPDIRECTDRAWSURFACE7 override
, DWORD dwFlags
)
547 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
548 IDirectDrawSurfaceImpl
* target
;
551 TRACE("(%p)->(%p,%08lx)\n",This
,override
,dwFlags
);
553 if (TRACE_ON(ddraw_fps
)) {
554 LONGLONG current_time
;
555 LONGLONG frame_duration
;
556 QueryPerformanceCounter((LARGE_INTEGER
*) ¤t_time
);
558 if (prev_time
!= 0) {
559 LONGLONG total_time
= 0;
562 frame_duration
= current_time
- prev_time
;
563 prev_time
= current_time
;
565 perf_storage
[current_window
] += frame_duration
;
566 measurements_in_window
++;
568 if (measurements_in_window
>= MEASUREMENT_WINDOW
) {
572 if (valid_windows
< NUMBER_OF_WINDOWS
) {
574 tot_meas
= valid_windows
* MEASUREMENT_WINDOW
;
575 for (i
= 0; i
< valid_windows
; i
++) {
576 total_time
+= perf_storage
[i
];
580 tot_meas
= NUMBER_OF_WINDOWS
* MEASUREMENT_WINDOW
;
581 for (i
= 0; i
< NUMBER_OF_WINDOWS
; i
++) {
582 total_time
+= perf_storage
[i
];
586 TRACE_(ddraw_fps
)(" %9.5f\n", (double) (perf_freq
* tot_meas
) / (double) total_time
);
588 if (current_window
>= NUMBER_OF_WINDOWS
) {
591 perf_storage
[current_window
] = 0;
592 measurements_in_window
= 0;
595 prev_time
= current_time
;
596 memset(perf_storage
, 0, sizeof(perf_storage
));
599 measurements_in_window
= 0;
600 QueryPerformanceFrequency((LARGE_INTEGER
*) &perf_freq
);
604 /* MSDN: "This method can be called only for a surface that has the
605 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
606 if ((This
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
607 != (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
))
608 return DDERR_NOTFLIPPABLE
;
611 if (This
->aux_flip(This
->aux_ctx
, This
->aux_data
))
614 /* 1. find the flip target */
615 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
616 if (override
== NULL
)
618 static DDSCAPS2 back_caps
= { DDSCAPS_BACKBUFFER
};
619 LPDIRECTDRAWSURFACE7 tgt
;
621 hr
= IDirectDrawSurface7_GetAttachedSurface(iface
, &back_caps
, &tgt
);
622 if (FAILED(hr
)) return DDERR_NOTFLIPPABLE
; /* unchecked */
624 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
626 IDirectDrawSurface7_Release(tgt
);
630 BOOL on_chain
= FALSE
;
631 IDirectDrawSurfaceImpl
* surf
;
633 /* MSDN: "The method fails if the specified [override] surface is not
634 * a member of the flipping chain." */
636 /* Verify that override is on this flip chain. We assume that
637 * surf is the head of the flipping chain, because it's the front
639 target
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
,
642 /* Either target is (indirectly) attached to This or This is
643 * (indirectly) attached to target. */
644 for (surf
= target
; surf
!= NULL
; surf
= surf
->surface_owner
)
654 return DDERR_INVALIDPARAMS
; /* unchecked */
657 TRACE("flip to backbuffer: %p\n",target
);
658 if (TRACE_ON(ddraw_flip
)) {
659 static unsigned int flip_count
= 0;
660 IDirectDrawPaletteImpl
*palette
;
664 /* Hack for paletted games... */
665 palette
= target
->palette
;
666 target
->palette
= This
->palette
;
668 sprintf(buf
, "flip_%08d.ppm", flip_count
++);
669 TRACE_(ddraw_flip
)("Dumping file %s to disk.\n", buf
);
670 f
= fopen(buf
, "wb");
671 DDRAW_dump_surface_to_disk(target
, f
, 8);
672 target
->palette
= palette
;
675 if (This
->flip_data(This
, target
, dwFlags
))
676 This
->flip_update(This
, dwFlags
);
681 static PrivateData
* find_private_data(IDirectDrawSurfaceImpl
*This
,
685 for (data
= This
->private_data
; data
!= NULL
; data
= data
->next
)
687 if (IsEqualGUID(&data
->tag
, tag
)) break;
694 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface
, REFGUID tag
)
696 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
699 data
= find_private_data(This
, tag
);
700 if (data
== NULL
) return DDERR_NOTFOUND
;
703 data
->prev
->next
= data
->next
;
705 data
->next
->prev
= data
->prev
;
707 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
709 if (data
->ptr
.object
!= NULL
)
710 IUnknown_Release(data
->ptr
.object
);
713 HeapFree(GetProcessHeap(), 0, data
->ptr
.data
);
715 HeapFree(GetProcessHeap(), 0, data
);
721 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface
,
723 LPDIRECTDRAWSURFACE7
* ppSurface
)
725 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
726 IDirectDrawSurfaceImpl
* surf
;
727 IDirectDrawSurfaceImpl
* found
= NULL
;
730 if (TRACE_ON(ddraw
)) {
731 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This
,pCaps
->dwCaps
, pCaps
->dwCaps2
,
732 pCaps
->dwCaps3
, pCaps
->dwCaps4
, ppSurface
);
733 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps
); TRACE("\n");
737 if ((This
->ddraw_owner
->local
.dwLocalFlags
& DDRAWILCL_DIRECTDRAW7
) == 0) {
738 /* As this is not a DirectDraw7 application, remove the garbage that some games
739 put in the new fields of the DDSCAPS2 structure. */
740 our_caps
.dwCaps2
= 0;
741 our_caps
.dwCaps3
= 0;
742 our_caps
.dwCaps4
= 0;
743 if (TRACE_ON(ddraw
)) {
744 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps
); TRACE("\n");
748 for (surf
= This
->attached
; surf
!= NULL
; surf
= surf
->next_attached
)
750 if (TRACE_ON(ddraw
)) {
751 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx\n", surf
,
752 surf
->surface_desc
.ddsCaps
.dwCaps
,
753 surf
->surface_desc
.ddsCaps
.dwCaps2
,
754 surf
->surface_desc
.ddsCaps
.dwCaps3
,
755 surf
->surface_desc
.ddsCaps
.dwCaps4
);
756 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf
->surface_desc
.ddsCaps
)); TRACE("\n");
758 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& our_caps
.dwCaps
) == our_caps
.dwCaps
) &&
759 ((surf
->surface_desc
.ddsCaps
.dwCaps2
& our_caps
.dwCaps2
) == our_caps
.dwCaps2
))
761 /* MSDN: "This method fails if more than one surface is attached
762 * that matches the capabilities requested." */
765 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
766 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
767 to be correct, given what 3DMark expects from MipMapped surfaces.
768 We shall just continue instead. */
776 TRACE("Did not find any valid surface\n");
777 return DDERR_NOTFOUND
;
780 *ppSurface
= ICOM_INTERFACE(found
, IDirectDrawSurface7
);
782 if (TRACE_ON(ddraw
)) {
783 TRACE("Returning surface %p with description :\n", *ppSurface
);
784 DDRAW_dump_surface_desc(&(found
->surface_desc
));
787 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
788 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found
, IDirectDrawSurface7
));
793 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
795 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
800 case DDGBS_ISBLTDONE
:
804 return DDERR_INVALIDPARAMS
;
809 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface
, LPDDSCAPS2 pCaps
)
811 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
813 TRACE("(%p)->(%p)\n",This
,pCaps
);
814 *pCaps
= This
->surface_desc
.ddsCaps
;
819 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface
,
820 LPDIRECTDRAWCLIPPER
* ppClipper
)
822 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
824 TRACE("(%p)->(%p)\n",This
,ppClipper
);
825 if (This
->clipper
== NULL
)
826 return DDERR_NOCLIPPERATTACHED
;
828 *ppClipper
= ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
);
829 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This
->clipper
,
830 IDirectDrawClipper
));
835 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
,
838 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
839 * isn't there? That's like saying that an int isn't there. (Which MS
840 * has done in other docs.) */
842 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
844 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
845 if (TRACE_ON(ddraw
)) {
846 TRACE(" - colorkey flags : ");
847 DDRAW_dump_colorkeyflag(dwFlags
);
853 *pCKey
= This
->surface_desc
.ddckCKDestBlt
;
856 case DDCKEY_DESTOVERLAY
:
857 *pCKey
= This
->surface_desc
.u3
.ddckCKDestOverlay
;
861 *pCKey
= This
->surface_desc
.ddckCKSrcBlt
;
864 case DDCKEY_SRCOVERLAY
:
865 *pCKey
= This
->surface_desc
.ddckCKSrcOverlay
;
869 return DDERR_INVALIDPARAMS
;
875 /* XXX We need to do something with the DC if the surface gets lost. */
877 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface
, HDC
*phDC
)
881 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
883 TRACE("(%p)->(%p)\n",This
,phDC
);
891 return DDERR_DCALREADYCREATED
;
895 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
896 * thread has it locked, but GetDC does not. */
897 ddsd
.dwSize
= sizeof(ddsd
);
898 hr
= IDirectDrawSurface7_Lock(iface
, NULL
, &ddsd
, 0, 0);
905 hr
= This
->get_dc(This
, &This
->hDC
);
907 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) &&
908 (This
->palette
== NULL
)) {
909 IDirectDrawImpl
*ddraw
= This
->ddraw_owner
;
910 IDirectDrawSurfaceImpl
*surf
;
912 for (surf
= ddraw
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
) {
913 if (((surf
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_PRIMARYSURFACE
| DDSCAPS_FRONTBUFFER
)) &&
914 (surf
->palette
!= NULL
)) {
916 IDirectDrawPaletteImpl
*pal
= surf
->palette
;
918 for (n
=0; n
<256; n
++) {
919 col
[n
].rgbRed
= pal
->palents
[n
].peRed
;
920 col
[n
].rgbGreen
= pal
->palents
[n
].peGreen
;
921 col
[n
].rgbBlue
= pal
->palents
[n
].peBlue
;
922 col
[n
].rgbReserved
= 0;
924 SetDIBColorTable(This
->hDC
, 0, 256, col
);
933 TRACE("returning %p\n",This
->hDC
);
936 This
->dc_in_use
= TRUE
;
938 else WARN("No DC! Prepare for trouble\n");
945 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface
, LPVOID
* pDD
)
947 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
949 TRACE("(%p)->(%p)\n",This
,pDD
);
950 *pDD
= ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
);
951 IDirectDraw7_AddRef(ICOM_INTERFACE(This
->ddraw_owner
, IDirectDraw7
));
956 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
958 /* XXX: DDERR_INVALIDSURFACETYPE */
960 TRACE("(%p)->(%08lx)\n",iface
,dwFlags
);
964 case DDGFS_ISFLIPDONE
:
968 return DDERR_INVALIDPARAMS
;
973 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface
, LPDWORD pdwMaxLOD
)
975 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
977 TRACE("(%p)->(%p)\n",This
,pdwMaxLOD
);
980 *pdwMaxLOD
= This
->max_lod
;
985 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
986 LPLONG pX
, LPLONG pY
)
988 return DDERR_NOTAOVERLAYSURFACE
;
992 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface
,
993 LPDIRECTDRAWPALETTE
* ppPalette
)
995 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
997 TRACE("(%p)->(%p)\n",This
,ppPalette
);
998 if (This
->palette
== NULL
)
999 return DDERR_NOPALETTEATTACHED
;
1001 *ppPalette
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
1002 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This
->palette
,
1003 IDirectDrawPalette
));
1008 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface
,
1009 LPDDPIXELFORMAT pDDPixelFormat
)
1011 /* What is DDERR_INVALIDSURFACETYPE for here? */
1012 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1014 TRACE("(%p)->(%p)\n",This
,pDDPixelFormat
);
1015 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat
,&This
->surface_desc
.u4
.ddpfPixelFormat
);
1020 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface
,
1021 LPDWORD pdwPriority
)
1023 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1025 TRACE("(%p)->(%p)\n",This
,pdwPriority
);
1026 CHECK_TEXTURE(This
);
1028 *pdwPriority
= This
->priority
;
1033 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
1034 REFGUID tag
, LPVOID pBuffer
,
1035 LPDWORD pcbBufferSize
)
1037 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1040 TRACE("(%p)->(%p), size = %ld\n", This
, pBuffer
, *pcbBufferSize
);
1042 data
= find_private_data(This
, tag
);
1043 if (data
== NULL
) return DDERR_NOTFOUND
;
1045 /* This may not be right. */
1046 if ((data
->flags
& DDSPD_VOLATILE
)
1047 && data
->uniqueness_value
!= This
->uniqueness_value
)
1048 return DDERR_EXPIRED
;
1050 if (*pcbBufferSize
< data
->size
)
1052 *pcbBufferSize
= data
->size
;
1053 return DDERR_MOREDATA
;
1056 if (data
->flags
& DDSPD_IUNKNOWNPTR
)
1058 *(LPUNKNOWN
*)pBuffer
= data
->ptr
.object
;
1059 IUnknown_AddRef(data
->ptr
.object
);
1063 memcpy(pBuffer
, data
->ptr
.data
, data
->size
);
1070 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface
,
1071 LPDDSURFACEDESC2 pDDSD
)
1073 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1075 TRACE("(%p)->(%p)\n",This
,pDDSD
);
1076 if ((pDDSD
->dwSize
< sizeof(DDSURFACEDESC
)) ||
1077 (pDDSD
->dwSize
> sizeof(DDSURFACEDESC2
))) {
1078 ERR("Impossible/Strange struct size %ld.\n",pDDSD
->dwSize
);
1079 return DDERR_GENERIC
;
1082 DD_STRUCT_COPY_BYSIZE(pDDSD
,&This
->surface_desc
);
1083 if (TRACE_ON(ddraw
)) {
1084 DDRAW_dump_surface_desc(pDDSD
);
1090 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface
,
1093 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1095 TRACE("(%p)->(%p)\n",This
,pValue
);
1096 *pValue
= This
->uniqueness_value
;
1101 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface
,
1102 LPDIRECTDRAW pDD
, LPDDSURFACEDESC2 pDDSD
)
1104 TRACE("(%p)->(%p,%p)\n",iface
,pDD
,pDDSD
);
1105 return DDERR_ALREADYINITIALIZED
;
1109 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface
)
1111 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1113 TRACE("(%p) is%s lost\n",This
, (This
->lost
? "" : " not"));
1114 return This
->lost
? DDERR_SURFACELOST
: DD_OK
;
1118 /* XXX This doesn't actually do any locking or keep track of the locked
1119 * rectangles. The behaviour is poorly documented. */
1121 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface
, LPRECT prect
,
1122 LPDDSURFACEDESC2 pDDSD
, DWORD flags
, HANDLE h
)
1124 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1126 if (TRACE_ON(ddraw
)) {
1127 TRACE("(%p)->Lock(%p,%p,%08lx,%p)\n",This
,prect
,pDDSD
,flags
,h
);
1128 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags
);
1130 if (WARN_ON(ddraw
)) {
1131 if (flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
)) {
1132 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags
& ~(DDLOCK_WAIT
|DDLOCK_READONLY
|DDLOCK_WRITEONLY
));
1136 return DDERR_INVALIDPARAMS
;
1138 if (NULL
== pDDSD
) {
1139 return DDERR_INVALIDPARAMS
;
1142 /* If the surface is already locked, return busy */
1144 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1145 return DDERR_SURFACEBUSY
;
1148 /* First, copy the Surface description */
1149 DD_STRUCT_COPY_BYSIZE(pDDSD
,&(This
->surface_desc
));
1151 /* Used to optimize the D3D Device locking */
1152 This
->lastlocktype
= flags
& (DDLOCK_READONLY
|DDLOCK_WRITEONLY
);
1154 /* If asked only for a part, change the surface pointer.
1155 * (Not documented.) */
1156 if (prect
!= NULL
) {
1157 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1158 prect
->left
,prect
->top
,prect
->right
,prect
->bottom
);
1159 /* First do some sanity checkings on the rectangle we receive.
1160 DungeonSiege seems to gives us once a very bad rectangle for example */
1161 if ((prect
->top
< 0) ||
1162 (prect
->left
< 0) ||
1163 (prect
->bottom
< 0) ||
1164 (prect
->right
< 0) ||
1165 (prect
->left
>= prect
->right
) ||
1166 (prect
->top
>= prect
->bottom
) ||
1167 (prect
->left
>= This
->surface_desc
.dwWidth
) ||
1168 (prect
->right
> This
->surface_desc
.dwWidth
) ||
1169 (prect
->top
>= This
->surface_desc
.dwHeight
) ||
1170 (prect
->bottom
> This
->surface_desc
.dwHeight
)) {
1171 ERR(" Invalid values in LPRECT !!!\n");
1172 return DDERR_INVALIDPARAMS
;
1175 This
->lock_update(This
, prect
, flags
);
1177 if (pDDSD
->u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) {
1179 switch(pDDSD
->u4
.ddpfPixelFormat
.dwFourCC
) {
1180 case MAKE_FOURCC('D','X','T','1') : blksize
= 8; break;
1181 case MAKE_FOURCC('D','X','T','3') : blksize
= 16; break;
1182 case MAKE_FOURCC('D','X','T','5') : blksize
= 16; break;
1183 default: return DDERR_INVALIDPIXELFORMAT
;
1185 pDDSD
->lpSurface
= (char *)This
->surface_desc
.lpSurface
1186 + prect
->top
/4 * (pDDSD
->dwWidth
+3)/4 * blksize
1187 + prect
->left
/4 * blksize
;
1189 pDDSD
->lpSurface
= (char *)This
->surface_desc
.lpSurface
1190 + prect
->top
* This
->surface_desc
.u1
.lPitch
1191 + prect
->left
* GET_BPP(This
->surface_desc
);
1193 This
->lock_update(This
, NULL
, flags
);
1196 This
->locked
= TRUE
;
1198 TRACE("locked surface returning description :\n");
1199 if (TRACE_ON(ddraw
)) DDRAW_dump_surface_desc(pDDSD
);
1205 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1207 /* Some surface types should return DDERR_CANTPAGELOCK. */
1212 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface
, DWORD dwFlags
)
1214 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1215 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1220 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface
, HDC hDC
)
1223 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1225 TRACE("(%p)->(%p)\n",This
,hDC
);
1227 if (!This
->dc_in_use
|| This
->hDC
!= hDC
)
1228 return DDERR_INVALIDPARAMS
;
1230 This
->release_dc(This
, hDC
);
1232 hr
= IDirectDrawSurface7_Unlock(iface
, NULL
);
1233 if (FAILED(hr
)) return hr
;
1235 This
->dc_in_use
= FALSE
;
1244 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface
,
1245 LPDIRECTDRAWCLIPPER pDDClipper
)
1247 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1249 TRACE("(%p)->(%p)\n",This
,pDDClipper
);
1250 if (pDDClipper
== ICOM_INTERFACE(This
->clipper
, IDirectDrawClipper
))
1253 if (This
->clipper
!= NULL
)
1254 IDirectDrawClipper_Release(ICOM_INTERFACE(This
->clipper
,
1255 IDirectDrawClipper
));
1257 This
->clipper
= ICOM_OBJECT(IDirectDrawClipperImpl
, IDirectDrawClipper
,
1259 if (pDDClipper
!= NULL
)
1260 IDirectDrawClipper_AddRef(pDDClipper
);
1266 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface
,
1267 DWORD dwFlags
, LPDDCOLORKEY pCKey
)
1269 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1271 TRACE("(%p)->(%08lx,%p)\n",This
,dwFlags
,pCKey
);
1273 if (TRACE_ON(ddraw
)) {
1274 TRACE(" - colorkey flags : ");
1275 DDRAW_dump_colorkeyflag(dwFlags
);
1278 if ((dwFlags
& DDCKEY_COLORSPACE
) != 0) {
1279 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags
);
1280 return DDERR_INVALIDPARAMS
;
1283 /* TODO: investigate if this function can take multiple bits set at the same
1284 time (ie setting multiple colorkey values at the same time with only
1288 switch (dwFlags
& ~DDCKEY_COLORSPACE
) {
1289 case DDCKEY_DESTBLT
:
1290 This
->surface_desc
.ddckCKDestBlt
= *pCKey
;
1291 This
->surface_desc
.dwFlags
|= DDSD_CKDESTBLT
;
1294 case DDCKEY_DESTOVERLAY
:
1295 This
->surface_desc
.u3
.ddckCKDestOverlay
= *pCKey
;
1296 This
->surface_desc
.dwFlags
|= DDSD_CKDESTOVERLAY
;
1299 case DDCKEY_SRCOVERLAY
:
1300 This
->surface_desc
.ddckCKSrcOverlay
= *pCKey
;
1301 This
->surface_desc
.dwFlags
|= DDSD_CKSRCOVERLAY
;
1305 This
->surface_desc
.ddckCKSrcBlt
= *pCKey
;
1306 This
->surface_desc
.dwFlags
|= DDSD_CKSRCBLT
;
1310 return DDERR_INVALIDPARAMS
;
1313 switch (dwFlags
& ~DDCKEY_COLORSPACE
) {
1314 case DDCKEY_DESTBLT
:
1315 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTBLT
;
1318 case DDCKEY_DESTOVERLAY
:
1319 This
->surface_desc
.dwFlags
&= ~DDSD_CKDESTOVERLAY
;
1322 case DDCKEY_SRCOVERLAY
:
1323 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCOVERLAY
;
1327 This
->surface_desc
.dwFlags
&= ~DDSD_CKSRCBLT
;
1331 return DDERR_INVALIDPARAMS
;
1335 if (This
->aux_setcolorkey_cb
) This
->aux_setcolorkey_cb(This
, dwFlags
, pCKey
);
1341 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface
, DWORD dwMaxLOD
)
1343 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1345 TRACE("(%p)->(%08lx)\n",This
,dwMaxLOD
);
1346 CHECK_TEXTURE(This
);
1348 This
->max_lod
= dwMaxLOD
;
1353 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface
,
1356 return DDERR_NOTAOVERLAYSURFACE
;
1360 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface
,
1361 LPDIRECTDRAWPALETTE pPalette
)
1363 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1364 IDirectDrawPalette
*pal_to_rel
= NULL
;
1366 TRACE("(%p)->(%p)\n",This
,pPalette
);
1367 if (pPalette
== ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
))
1370 if (This
->palette
!= NULL
) {
1371 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1372 This
->palette
->global
.dwFlags
&= ~DDPCAPS_PRIMARYSURFACE
;
1373 pal_to_rel
= ICOM_INTERFACE(This
->palette
, IDirectDrawPalette
);
1376 This
->palette
= ICOM_OBJECT(IDirectDrawPaletteImpl
, IDirectDrawPalette
,
1378 if (pPalette
!= NULL
) {
1379 IDirectDrawPalette_AddRef(pPalette
);
1380 if (This
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
1381 This
->palette
->global
.dwFlags
|= DDPCAPS_PRIMARYSURFACE
;
1384 This
->set_palette(This
, This
->palette
);
1386 /* Do the palette release at the end to prevent doing some 'loop' when removing
1387 * the surface maintaining the last reference on a palette.
1389 if (pal_to_rel
!= NULL
)
1390 IDirectDrawPalette_Release(pal_to_rel
);
1396 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface
,
1399 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1401 TRACE("(%p)->(%08lx)\n",This
,dwPriority
);
1402 CHECK_TEXTURE(This
);
1404 This
->priority
= dwPriority
;
1408 /* Be careful when locking this: it is risky to call the object's AddRef
1409 * or Release holding a lock. */
1411 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface
,
1412 REFGUID tag
, LPVOID pData
,
1413 DWORD cbSize
, DWORD dwFlags
)
1416 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1418 TRACE("(%p)->(%p), size=%ld\n", This
, pData
, cbSize
);
1420 data
= find_private_data(This
, tag
);
1423 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
1424 if (data
== NULL
) return DDERR_OUTOFMEMORY
;
1427 data
->flags
= dwFlags
;
1428 data
->uniqueness_value
= This
->uniqueness_value
;
1430 if (dwFlags
& DDSPD_IUNKNOWNPTR
)
1432 data
->ptr
.object
= (LPUNKNOWN
)pData
;
1433 data
->size
= sizeof(LPUNKNOWN
);
1434 IUnknown_AddRef(data
->ptr
.object
);
1438 data
->ptr
.data
= HeapAlloc(GetProcessHeap(), 0, cbSize
);
1439 if (data
->ptr
.data
== NULL
)
1441 HeapFree(GetProcessHeap(), 0, data
);
1442 return DDERR_OUTOFMEMORY
;
1445 data
->size
= cbSize
;
1446 memcpy(data
->ptr
.data
, pData
, data
->size
);
1450 data
->next
= This
->private_data
;
1452 if (This
->private_data
)
1453 This
->private_data
->prev
= data
;
1454 This
->private_data
= data
;
1460 /* I don't actually know how windows handles this case. The only
1461 * reason I don't just call FreePrivateData is because I want to
1462 * guarantee SetPrivateData working when using LPUNKNOWN or data
1463 * that is no larger than the old data. */
1465 FIXME("Replacing existing private data not implemented yet.\n");
1470 /* SetSurfaceDesc */
1473 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface
, LPRECT pRect
)
1475 IDirectDrawSurfaceImpl
*This
= (IDirectDrawSurfaceImpl
*)iface
;
1477 TRACE("(%p)->Unlock(%p)\n",This
,pRect
);
1479 if (!This
->locked
) {
1480 WARN("Surface not locked - returing DDERR_NOTLOCKED\n");
1481 return DDERR_NOTLOCKED
;
1484 This
->locked
= FALSE
;
1485 This
->unlock_update(This
, pRect
);
1486 if (This
->aux_unlock
)
1487 This
->aux_unlock(This
->aux_ctx
, This
->aux_data
, pRect
);
1493 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface
,
1495 LPDIRECTDRAWSURFACE7 pDstSurface
,
1496 LPRECT pDstRect
, DWORD dwFlags
,
1499 return DDERR_UNSUPPORTED
;
1502 /* MSDN: "not currently implemented." */
1504 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface
,
1507 return DDERR_UNSUPPORTED
;
1511 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface
,
1513 LPDIRECTDRAWSURFACE7 pDDSRef
)
1515 return DDERR_NOTAOVERLAYSURFACE
;