Added traces in GetPrivateData and SetPrivateData.
[wine/hacks.git] / dlls / ddraw / dsurface / main.c
bloba33e27be13b6664e61681ad1a0a73d6bd74c1b6d
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
21 #include "config.h"
23 #include <assert.h>
24 #include <string.h>
26 #define COBJMACROS
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
30 #include "winerror.h"
31 #include "mesa_private.h"
32 #include "wine/debug.h"
33 #include "ddraw_private.h"
34 #include "dsurface/main.h"
35 #include "ddraw/main.h"
36 #include "dsurface/thunks.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
39 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
42 /** Creation/Destruction functions */
44 HRESULT
45 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
46 IDirectDrawImpl *pDD,
47 const DDSURFACEDESC2 *pDDSD)
49 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
51 if (pDDSD != &This->surface_desc) {
52 This->surface_desc.dwSize = sizeof(This->surface_desc);
53 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
55 This->uniqueness_value = 1; /* unchecked */
56 This->ref = 1;
58 This->local.lpSurfMore = &This->more;
59 This->local.lpGbl = &This->global;
60 This->local.dwProcessId = GetCurrentProcessId();
61 This->local.dwFlags = 0; /* FIXME */
62 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
63 /* FIXME: more local stuff */
64 This->more.lpDD_lcl = &pDD->local;
65 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
66 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
67 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
68 /* FIXME: more more stuff */
69 This->gmore = &This->global_more;
70 This->global.u3.lpDD = pDD->local.lpGbl;
71 /* FIXME: more global stuff */
73 This->final_release = Main_DirectDrawSurface_final_release;
74 This->late_allocate = Main_DirectDrawSurface_late_allocate;
75 This->attach = Main_DirectDrawSurface_attach;
76 This->detach = Main_DirectDrawSurface_detach;
77 This->lock_update = Main_DirectDrawSurface_lock_update;
78 This->unlock_update = Main_DirectDrawSurface_unlock_update;
79 This->lose_surface = Main_DirectDrawSurface_lose_surface;
80 This->set_palette = Main_DirectDrawSurface_set_palette;
81 This->update_palette = Main_DirectDrawSurface_update_palette;
82 This->get_display_window = Main_DirectDrawSurface_get_display_window;
83 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
84 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
86 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
87 DDRAW_IDDS3_Thunk_VTable);
88 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
89 DDRAW_IDDGC_VTable);
91 /* There is no generic implementation of IDDS7 or texture */
93 Main_DirectDraw_AddSurface(pDD, This);
94 return DD_OK;
97 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
99 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
102 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
104 return DD_OK;
107 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
109 if (This->palette) {
110 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
111 This->palette = NULL;
113 This->final_release(This);
114 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
115 if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
116 HeapFree(GetProcessHeap(), 0, This);
119 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
121 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
122 Main_DirectDrawSurface_Destroy(This);
125 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
127 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
128 ULONG ref = InterlockedDecrement(&This->ref);
130 TRACE("(%p)->(): decreasing from %ld\n", This, ref + 1);
132 if (ref == 0)
134 if (This->aux_release)
135 This->aux_release(This->aux_ctx, This->aux_data);
136 Main_DirectDrawSurface_Destroy(This);
138 TRACE("released surface %p\n", This);
140 return 0;
143 return ref;
146 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
148 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
149 ULONG ref = InterlockedIncrement(&This->ref);
151 TRACE("(%p)->(): increasing from %ld\n", This, ref - 1);
153 return ref;
156 HRESULT WINAPI
157 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
158 LPVOID* ppObj)
160 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
161 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
163 *ppObj = NULL;
165 if (IsEqualGUID(&IID_IUnknown, riid)
166 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
167 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
169 InterlockedIncrement(&This->ref);
170 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
171 return S_OK;
173 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
174 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
175 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
177 InterlockedIncrement(&This->ref);
178 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
179 return S_OK;
181 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
183 InterlockedIncrement(&This->ref);
184 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
185 return S_OK;
187 #ifdef HAVE_OPENGL
188 /* interfaces following here require OpenGL */
189 if( !opengl_initialized )
190 return E_NOINTERFACE;
192 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
193 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
195 IDirect3DDeviceImpl *d3ddevimpl;
196 HRESULT ret_value;
198 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, 1);
199 if (FAILED(ret_value)) return ret_value;
201 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
202 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
204 InterlockedIncrement(&This->ref); /* No idea if this is correct.. Need to check using real Windows */
205 return ret_value;
207 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
208 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
210 HRESULT ret_value = S_OK;
212 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
213 application I know creating a texture without this flag set and it will prevent
214 bugs in other parts of Wine.
216 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
218 /* In case the texture surface was created before the D3D creation */
219 if (This->tex_private == NULL) {
220 if (This->ddraw_owner->d3d_private == NULL) {
221 ERR("Texture created with no D3D object yet.. Not supported !\n");
222 return E_NOINTERFACE;
225 ret_value = This->ddraw_owner->d3d_create_texture(This->ddraw_owner, This, FALSE, This->mip_main);
226 if (FAILED(ret_value)) return ret_value;
228 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
229 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
230 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
231 } else {
232 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
233 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
235 InterlockedIncrement(&This->ref);
236 return ret_value;
238 #endif
240 return E_NOINTERFACE;
243 /*** Callbacks */
245 BOOL
246 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
247 IDirectDrawSurfaceImpl *to)
249 return TRUE;
252 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
254 return TRUE;
257 void
258 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
259 DWORD dwFlags)
263 void
264 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
265 LPCRECT pRect)
269 void
270 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
274 void
275 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
276 IDirectDrawPaletteImpl* pal)
280 void
281 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
282 IDirectDrawPaletteImpl* pal,
283 DWORD dwStart, DWORD dwCount,
284 LPPALETTEENTRY palent)
288 HWND
289 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
291 return 0;
294 HRESULT
295 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
296 DWORD dwFlags,
297 LPDDGAMMARAMP lpGammaRamp)
299 HDC hDC;
300 HRESULT hr;
301 hr = This->get_dc(This, &hDC);
302 if (FAILED(hr)) return hr;
303 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
304 This->release_dc(This, hDC);
305 return hr;
308 HRESULT
309 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
310 DWORD dwFlags,
311 LPDDGAMMARAMP lpGammaRamp)
313 HDC hDC;
314 HRESULT hr;
315 hr = This->get_dc(This, &hDC);
316 if (FAILED(hr)) return hr;
317 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
318 This->release_dc(This, hDC);
319 return hr;
323 /*** Interface functions */
325 HRESULT WINAPI
326 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
327 LPDIRECTDRAWSURFACE7 pAttach)
329 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
330 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
331 IDirectDrawSurface7, pAttach);
333 TRACE("(%p)->(%p)\n",This,pAttach);
335 /* Does windows check this? */
336 if (surf == This)
337 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
339 /* Does windows check this? */
340 if (surf->ddraw_owner != This->ddraw_owner)
341 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
343 if (surf->surface_owner != NULL)
344 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
346 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
347 * But apparently backbuffers and mipmaps can be attached too. */
349 /* Set MIPMAPSUBLEVEL if this seems to be one */
350 if (This->surface_desc.ddsCaps.dwCaps &
351 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
352 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
353 /* FIXME: we should probably also add to dwMipMapCount of this
354 * and all parent surfaces (update create_texture if you do) */
357 /* Callback to allow the surface to do something special now that it is
358 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
359 if (!surf->attach(surf, This))
360 return DDERR_CANNOTATTACHSURFACE;
362 /* check: Where should it go in the chain? This puts it on the head. */
363 if (This->attached)
364 This->attached->prev_attached = surf;
365 surf->next_attached = This->attached;
366 surf->prev_attached = NULL;
367 This->attached = surf;
368 surf->surface_owner = This;
370 IDirectDrawSurface7_AddRef(pAttach);
372 return DD_OK;
375 /* MSDN: "not currently implemented." */
376 HRESULT WINAPI
377 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
378 LPRECT pRect)
380 TRACE("(%p)->(%p)\n",iface,pRect);
381 return DDERR_UNSUPPORTED; /* unchecked */
384 /* MSDN: "not currently implemented." */
385 HRESULT WINAPI
386 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
387 LPDDBLTBATCH pBatch, DWORD dwCount,
388 DWORD dwFlags)
390 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
391 return DDERR_UNSUPPORTED; /* unchecked */
394 HRESULT WINAPI
395 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
397 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
398 volatile IDirectDrawSurfaceImpl* vThis = This;
400 TRACE("(%p)\n",This);
401 /* A uniquness value of 0 is apparently special.
402 * This needs to be checked. */
403 while (1)
405 DWORD old_uniqueness_value = vThis->uniqueness_value;
406 DWORD new_uniqueness_value = old_uniqueness_value+1;
408 if (old_uniqueness_value == 0) break;
409 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
411 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
412 old_uniqueness_value,
413 new_uniqueness_value)
414 == old_uniqueness_value)
415 break;
418 return DD_OK;
421 HRESULT WINAPI
422 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
423 DWORD dwFlags,
424 LPDIRECTDRAWSURFACE7 pAttach)
426 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
427 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
428 IDirectDrawSurface7, pAttach);
430 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
432 if (!surf || (surf->surface_owner != This))
433 return DDERR_SURFACENOTATTACHED; /* unchecked */
435 surf->detach(surf);
437 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
438 if (This->surface_desc.ddsCaps.dwCaps &
439 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
440 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
441 /* FIXME: we should probably also subtract from dwMipMapCount of this
442 * and all parent surfaces */
445 if (surf->next_attached)
446 surf->next_attached->prev_attached = surf->prev_attached;
447 if (surf->prev_attached)
448 surf->prev_attached->next_attached = surf->next_attached;
449 if (This->attached == surf)
450 This->attached = surf->next_attached;
452 IDirectDrawSurface7_Release(pAttach);
454 return DD_OK;
457 HRESULT WINAPI
458 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
459 LPVOID context,
460 LPDDENUMSURFACESCALLBACK7 cb)
462 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
463 IDirectDrawSurfaceImpl* surf;
465 TRACE("(%p)->(%p,%p)\n",This,context,cb);
467 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
469 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
470 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
471 context) == DDENUMRET_CANCEL)
472 break;
475 return DD_OK;
478 HRESULT WINAPI
479 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
480 DWORD dwFlags, LPVOID context,
481 LPDDENUMSURFACESCALLBACK7 cb)
483 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
484 return DD_OK;
487 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
488 IDirectDrawSurfaceImpl* back,
489 DWORD dwFlags)
491 /* uniqueness_value? */
492 /* This is necessary. But is it safe? */
494 HDC tmp = front->hDC;
495 front->hDC = back->hDC;
496 back->hDC = tmp;
500 BOOL tmp = front->dc_in_use;
501 front->dc_in_use = back->dc_in_use;
502 back->dc_in_use = tmp;
506 FLATPTR tmp = front->global.fpVidMem;
507 front->global.fpVidMem = back->global.fpVidMem;
508 back->global.fpVidMem = tmp;
512 ULONG_PTR tmp = front->global_more.hKernelSurface;
513 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
514 back->global_more.hKernelSurface = tmp;
517 return TRUE;
520 /* This is unnecessarely complicated :-) */
521 #define MEASUREMENT_WINDOW 5
522 #define NUMBER_OF_WINDOWS 10
524 static LONGLONG perf_freq;
525 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
526 static LONGLONG prev_time = 0;
527 static unsigned int current_window;
528 static unsigned int measurements_in_window;
529 static unsigned int valid_windows;
531 HRESULT WINAPI
532 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
533 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
535 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
536 IDirectDrawSurfaceImpl* target;
537 HRESULT hr;
539 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
541 if (TRACE_ON(ddraw_fps)) {
542 LONGLONG current_time;
543 LONGLONG frame_duration;
544 QueryPerformanceCounter((LARGE_INTEGER *) &current_time);
546 if (prev_time != 0) {
547 LONGLONG total_time = 0;
548 int tot_meas;
550 frame_duration = current_time - prev_time;
551 prev_time = current_time;
553 perf_storage[current_window] += frame_duration;
554 measurements_in_window++;
556 if (measurements_in_window >= MEASUREMENT_WINDOW) {
557 current_window++;
558 valid_windows++;
560 if (valid_windows < NUMBER_OF_WINDOWS) {
561 unsigned int i;
562 tot_meas = valid_windows * MEASUREMENT_WINDOW;
563 for (i = 0; i < valid_windows; i++) {
564 total_time += perf_storage[i];
566 } else {
567 int i;
568 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
569 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
570 total_time += perf_storage[i];
574 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
576 if (current_window >= NUMBER_OF_WINDOWS) {
577 current_window = 0;
579 perf_storage[current_window] = 0;
580 measurements_in_window = 0;
582 } else {
583 prev_time = current_time;
584 memset(perf_storage, 0, sizeof(perf_storage));
585 current_window = 0;
586 valid_windows = 0;
587 measurements_in_window = 0;
588 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
592 /* MSDN: "This method can be called only for a surface that has the
593 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
594 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
595 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
596 return DDERR_NOTFLIPPABLE;
598 if (This->aux_flip)
599 if (This->aux_flip(This->aux_ctx, This->aux_data))
600 return DD_OK;
602 /* 1. find the flip target */
603 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
604 if (override == NULL)
606 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
607 LPDIRECTDRAWSURFACE7 tgt;
609 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
610 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
612 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
613 tgt);
614 IDirectDrawSurface7_Release(tgt);
616 else
618 BOOL on_chain = FALSE;
619 IDirectDrawSurfaceImpl* surf;
621 /* MSDN: "The method fails if the specified [override] surface is not
622 * a member of the flipping chain." */
624 /* Verify that override is on this flip chain. We assume that
625 * surf is the head of the flipping chain, because it's the front
626 * buffer. */
627 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
628 override);
630 /* Either target is (indirectly) attached to This or This is
631 * (indirectly) attached to target. */
632 for (surf = target; surf != NULL; surf = surf->surface_owner)
634 if (surf == This)
636 on_chain = TRUE;
637 break;
641 if (!on_chain)
642 return DDERR_INVALIDPARAMS; /* unchecked */
645 TRACE("flip to backbuffer: %p\n",target);
646 if (TRACE_ON(ddraw_flip)) {
647 static unsigned int flip_count = 0;
648 IDirectDrawPaletteImpl *palette;
649 char buf[32];
650 FILE *f;
652 /* Hack for paletted games... */
653 palette = target->palette;
654 target->palette = This->palette;
656 sprintf(buf, "flip_%08d.ppm", flip_count++);
657 TRACE_(ddraw_flip)("Dumping file %s to disk.\n", buf);
658 f = fopen(buf, "wb");
659 DDRAW_dump_surface_to_disk(target, f, 8);
660 target->palette = palette;
663 if (This->flip_data(This, target, dwFlags))
664 This->flip_update(This, dwFlags);
666 return DD_OK;
669 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
670 REFGUID tag)
672 PrivateData* data;
673 for (data = This->private_data; data != NULL; data = data->next)
675 if (IsEqualGUID(&data->tag, tag)) break;
678 return data;
681 HRESULT WINAPI
682 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
684 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
685 PrivateData *data;
687 data = find_private_data(This, tag);
688 if (data == NULL) return DDERR_NOTFOUND;
690 if (data->prev)
691 data->prev->next = data->next;
692 if (data->next)
693 data->next->prev = data->prev;
695 if (data->flags & DDSPD_IUNKNOWNPTR)
697 if (data->ptr.object != NULL)
698 IUnknown_Release(data->ptr.object);
700 else
701 HeapFree(GetProcessHeap(), 0, data->ptr.data);
703 HeapFree(GetProcessHeap(), 0, data);
705 return DD_OK;
708 HRESULT WINAPI
709 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
710 LPDDSCAPS2 pCaps,
711 LPDIRECTDRAWSURFACE7* ppSurface)
713 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
714 IDirectDrawSurfaceImpl* surf;
715 IDirectDrawSurfaceImpl* found = NULL;
716 DDSCAPS2 our_caps;
718 if (TRACE_ON(ddraw)) {
719 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
720 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
721 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); TRACE("\n");
724 our_caps = *pCaps;
725 if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
726 /* As this is not a DirectDraw7 application, remove the garbage that some games
727 put in the new fields of the DDSCAPS2 structure. */
728 our_caps.dwCaps2 = 0;
729 our_caps.dwCaps3 = 0;
730 our_caps.dwCaps4 = 0;
731 if (TRACE_ON(ddraw)) {
732 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); TRACE("\n");
736 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
738 if (TRACE_ON(ddraw)) {
739 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
740 surf->surface_desc.ddsCaps.dwCaps,
741 surf->surface_desc.ddsCaps.dwCaps2,
742 surf->surface_desc.ddsCaps.dwCaps3,
743 surf->surface_desc.ddsCaps.dwCaps4);
744 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); TRACE("\n");
746 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
747 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
749 /* MSDN: "This method fails if more than one surface is attached
750 * that matches the capabilities requested." */
751 if (found != NULL)
753 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
754 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
755 to be correct, given what 3DMark expects from MipMapped surfaces.
756 We shall just continue instead. */
759 found = surf;
763 if (found == NULL) {
764 TRACE("Did not find any valid surface\n");
765 return DDERR_NOTFOUND;
768 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
770 if (TRACE_ON(ddraw)) {
771 TRACE("Returning surface %p with description : \n", *ppSurface);
772 DDRAW_dump_surface_desc(&(found->surface_desc));
775 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
776 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
777 return DD_OK;
780 HRESULT WINAPI
781 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
783 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
785 switch (dwFlags)
787 case DDGBS_CANBLT:
788 case DDGBS_ISBLTDONE:
789 return DD_OK;
791 default:
792 return DDERR_INVALIDPARAMS;
796 HRESULT WINAPI
797 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
799 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
801 TRACE("(%p)->(%p)\n",This,pCaps);
802 *pCaps = This->surface_desc.ddsCaps;
803 return DD_OK;
806 HRESULT WINAPI
807 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
808 LPDIRECTDRAWCLIPPER* ppClipper)
810 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
812 TRACE("(%p)->(%p)\n",This,ppClipper);
813 if (This->clipper == NULL)
814 return DDERR_NOCLIPPERATTACHED;
816 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
817 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
818 IDirectDrawClipper));
819 return DD_OK;
822 HRESULT WINAPI
823 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
824 LPDDCOLORKEY pCKey)
826 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
827 * isn't there? That's like saying that an int isn't there. (Which MS
828 * has done in other docs.) */
830 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
832 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
833 if (TRACE_ON(ddraw)) {
834 TRACE(" - colorkey flags : ");
835 DDRAW_dump_colorkeyflag(dwFlags);
838 switch (dwFlags)
840 case DDCKEY_DESTBLT:
841 *pCKey = This->surface_desc.ddckCKDestBlt;
842 break;
844 case DDCKEY_DESTOVERLAY:
845 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
846 break;
848 case DDCKEY_SRCBLT:
849 *pCKey = This->surface_desc.ddckCKSrcBlt;
850 break;
852 case DDCKEY_SRCOVERLAY:
853 *pCKey = This->surface_desc.ddckCKSrcOverlay;
854 break;
856 default:
857 return DDERR_INVALIDPARAMS;
860 return DD_OK;
863 /* XXX We need to do something with the DC if the surface gets lost. */
864 HRESULT WINAPI
865 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
867 DDSURFACEDESC2 ddsd;
868 HRESULT hr;
869 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
871 TRACE("(%p)->(%p)\n",This,phDC);
872 CHECK_LOST(This);
874 LOCK_OBJECT(This);
876 if (This->dc_in_use)
878 UNLOCK_OBJECT(This);
879 return DDERR_DCALREADYCREATED;
882 /* Lock as per MSDN.
883 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
884 * thread has it locked, but GetDC does not. */
885 ddsd.dwSize = sizeof(ddsd);
886 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
887 if (FAILED(hr))
889 UNLOCK_OBJECT(This);
890 return hr;
893 hr = This->get_dc(This, &This->hDC);
894 if (SUCCEEDED(hr))
896 TRACE("returning %p\n",This->hDC);
898 *phDC = This->hDC;
899 This->dc_in_use = TRUE;
901 else WARN("No DC! Prepare for trouble\n");
903 UNLOCK_OBJECT(This);
904 return hr;
907 HRESULT WINAPI
908 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
910 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
912 TRACE("(%p)->(%p)\n",This,pDD);
913 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
914 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
915 return DD_OK;
918 HRESULT WINAPI
919 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
921 /* XXX: DDERR_INVALIDSURFACETYPE */
923 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
924 switch (dwFlags)
926 case DDGFS_CANFLIP:
927 case DDGFS_ISFLIPDONE:
928 return DD_OK;
930 default:
931 return DDERR_INVALIDPARAMS;
935 HRESULT WINAPI
936 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
938 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
940 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
941 CHECK_TEXTURE(This);
943 *pdwMaxLOD = This->max_lod;
944 return DD_OK;
947 HRESULT WINAPI
948 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
949 LPLONG pX, LPLONG pY)
951 return DDERR_NOTAOVERLAYSURFACE;
954 HRESULT WINAPI
955 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
956 LPDIRECTDRAWPALETTE* ppPalette)
958 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
960 TRACE("(%p)->(%p)\n",This,ppPalette);
961 if (This->palette == NULL)
962 return DDERR_NOPALETTEATTACHED;
964 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
965 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
966 IDirectDrawPalette));
967 return DD_OK;
970 HRESULT WINAPI
971 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
972 LPDDPIXELFORMAT pDDPixelFormat)
974 /* What is DDERR_INVALIDSURFACETYPE for here? */
975 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
977 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
978 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
979 return DD_OK;
982 HRESULT WINAPI
983 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
984 LPDWORD pdwPriority)
986 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
988 TRACE("(%p)->(%p)\n",This,pdwPriority);
989 CHECK_TEXTURE(This);
991 *pdwPriority = This->priority;
992 return DD_OK;
995 HRESULT WINAPI
996 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
997 REFGUID tag, LPVOID pBuffer,
998 LPDWORD pcbBufferSize)
1000 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1001 PrivateData* data;
1003 TRACE("(%p)->(%p), size = %ld\n", This, pBuffer, *pcbBufferSize);
1005 data = find_private_data(This, tag);
1006 if (data == NULL) return DDERR_NOTFOUND;
1008 /* This may not be right. */
1009 if ((data->flags & DDSPD_VOLATILE)
1010 && data->uniqueness_value != This->uniqueness_value)
1011 return DDERR_EXPIRED;
1013 if (*pcbBufferSize < data->size)
1015 *pcbBufferSize = data->size;
1016 return DDERR_MOREDATA;
1019 if (data->flags & DDSPD_IUNKNOWNPTR)
1021 *(LPUNKNOWN *)pBuffer = data->ptr.object;
1022 IUnknown_AddRef(data->ptr.object);
1024 else
1026 memcpy(pBuffer, data->ptr.data, data->size);
1029 return DD_OK;
1032 HRESULT WINAPI
1033 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
1034 LPDDSURFACEDESC2 pDDSD)
1036 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1038 TRACE("(%p)->(%p)\n",This,pDDSD);
1039 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
1040 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
1041 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
1042 return DDERR_GENERIC;
1045 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
1046 if (TRACE_ON(ddraw)) {
1047 DDRAW_dump_surface_desc(pDDSD);
1049 return DD_OK;
1052 HRESULT WINAPI
1053 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
1054 LPDWORD pValue)
1056 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1058 TRACE("(%p)->(%p)\n",This,pValue);
1059 *pValue = This->uniqueness_value;
1060 return DD_OK;
1063 HRESULT WINAPI
1064 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
1065 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
1067 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
1068 return DDERR_ALREADYINITIALIZED;
1071 HRESULT WINAPI
1072 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1074 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1076 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1077 return This->lost ? DDERR_SURFACELOST : DD_OK;
1081 /* XXX This doesn't actually do any locking or keep track of the locked
1082 * rectangles. The behaviour is poorly documented. */
1083 HRESULT WINAPI
1084 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
1085 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
1087 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1089 if (TRACE_ON(ddraw)) {
1090 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
1091 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
1093 if (WARN_ON(ddraw)) {
1094 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
1095 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
1099 /* If the surface is already locked, return busy */
1100 if (This->locked) {
1101 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1102 return DDERR_SURFACEBUSY;
1105 /* First, copy the Surface description */
1106 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1108 /* Used to optimize the D3D Device locking */
1109 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1111 /* If asked only for a part, change the surface pointer.
1112 * (Not documented.) */
1113 if (prect != NULL) {
1114 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1115 prect->left,prect->top,prect->right,prect->bottom);
1116 /* First do some sanity checkings on the rectangle we receive.
1117 DungeonSiege seems to gives us once a very bad rectangle for example */
1118 if ((prect->top < 0) ||
1119 (prect->left < 0) ||
1120 (prect->bottom < 0) ||
1121 (prect->right < 0) ||
1122 (prect->left >= prect->right) ||
1123 (prect->top >= prect->bottom) ||
1124 (prect->left >= This->surface_desc.dwWidth) ||
1125 (prect->right > This->surface_desc.dwWidth) ||
1126 (prect->top >= This->surface_desc.dwHeight) ||
1127 (prect->bottom > This->surface_desc.dwHeight)) {
1128 ERR(" Invalid values in LPRECT !!!\n");
1129 return DDERR_INVALIDPARAMS;
1132 This->lock_update(This, prect, flags);
1134 if (pDDSD->u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
1135 int blksize;
1136 switch(pDDSD->u4.ddpfPixelFormat.dwFourCC) {
1137 case MAKE_FOURCC('D','X','T','1') : blksize = 8; break;
1138 case MAKE_FOURCC('D','X','T','3') : blksize = 16; break;
1139 case MAKE_FOURCC('D','X','T','5') : blksize = 16; break;
1140 default: return DDERR_INVALIDPIXELFORMAT;
1142 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1143 + prect->top/4 * (pDDSD->dwWidth+3)/4 * blksize
1144 + prect->left/4 * blksize;
1145 } else
1146 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1147 + prect->top * This->surface_desc.u1.lPitch
1148 + prect->left * GET_BPP(This->surface_desc);
1149 } else {
1150 This->lock_update(This, NULL, flags);
1153 This->locked = TRUE;
1155 TRACE("locked surface returning description : \n");
1156 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1158 return DD_OK;
1161 HRESULT WINAPI
1162 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1164 /* Some surface types should return DDERR_CANTPAGELOCK. */
1165 return DD_OK;
1168 HRESULT WINAPI
1169 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1171 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1172 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1173 return DD_OK;
1176 HRESULT WINAPI
1177 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1179 HRESULT hr;
1180 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1182 TRACE("(%p)->(%p)\n",This,hDC);
1184 if (!This->dc_in_use || This->hDC != hDC)
1185 return DDERR_INVALIDPARAMS;
1187 This->release_dc(This, hDC);
1189 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1190 if (FAILED(hr)) return hr;
1192 This->dc_in_use = FALSE;
1193 This->hDC = 0;
1195 return DD_OK;
1198 /* Restore */
1200 HRESULT WINAPI
1201 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1202 LPDIRECTDRAWCLIPPER pDDClipper)
1204 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1206 TRACE("(%p)->(%p)\n",This,pDDClipper);
1207 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1208 return DD_OK;
1210 if (This->clipper != NULL)
1211 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1212 IDirectDrawClipper));
1214 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1215 pDDClipper);
1216 if (pDDClipper != NULL)
1217 IDirectDrawClipper_AddRef(pDDClipper);
1219 return DD_OK;
1222 HRESULT WINAPI
1223 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1224 DWORD dwFlags, LPDDCOLORKEY pCKey)
1226 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1228 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1230 if (TRACE_ON(ddraw)) {
1231 TRACE(" - colorkey flags : ");
1232 DDRAW_dump_colorkeyflag(dwFlags);
1235 if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1236 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1237 return DDERR_INVALIDPARAMS;
1240 /* TODO: investigate if this function can take multiple bits set at the same
1241 time (ie setting multiple colorkey values at the same time with only
1242 one API call).
1244 if (pCKey) {
1245 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1246 case DDCKEY_DESTBLT:
1247 This->surface_desc.ddckCKDestBlt = *pCKey;
1248 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1249 break;
1251 case DDCKEY_DESTOVERLAY:
1252 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1253 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1254 break;
1256 case DDCKEY_SRCOVERLAY:
1257 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1258 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1259 break;
1261 case DDCKEY_SRCBLT:
1262 This->surface_desc.ddckCKSrcBlt = *pCKey;
1263 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1264 break;
1266 default:
1267 return DDERR_INVALIDPARAMS;
1269 } else {
1270 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1271 case DDCKEY_DESTBLT:
1272 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1273 break;
1275 case DDCKEY_DESTOVERLAY:
1276 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1277 break;
1279 case DDCKEY_SRCOVERLAY:
1280 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1281 break;
1283 case DDCKEY_SRCBLT:
1284 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1285 break;
1287 default:
1288 return DDERR_INVALIDPARAMS;
1292 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1294 return DD_OK;
1297 HRESULT WINAPI
1298 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1300 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1302 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1303 CHECK_TEXTURE(This);
1305 This->max_lod = dwMaxLOD;
1306 return DD_OK;
1309 HRESULT WINAPI
1310 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1311 LONG X, LONG Y)
1313 return DDERR_NOTAOVERLAYSURFACE;
1316 HRESULT WINAPI
1317 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1318 LPDIRECTDRAWPALETTE pPalette)
1320 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1321 IDirectDrawPalette *pal_to_rel = NULL;
1323 TRACE("(%p)->(%p)\n",This,pPalette);
1324 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1325 return DD_OK;
1327 if (This->palette != NULL) {
1328 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1329 This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1330 pal_to_rel = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
1333 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1334 pPalette);
1335 if (pPalette != NULL) {
1336 IDirectDrawPalette_AddRef(pPalette);
1337 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1338 This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1341 This->set_palette(This, This->palette);
1343 /* Do the palette release at the end to prevent doing some 'loop' when removing
1344 * the surface maintaining the last reference on a palette.
1346 if (pal_to_rel != NULL)
1347 IDirectDrawPalette_Release(pal_to_rel);
1349 return DD_OK;
1352 HRESULT WINAPI
1353 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1354 DWORD dwPriority)
1356 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1358 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1359 CHECK_TEXTURE(This);
1361 This->priority = dwPriority;
1362 return DD_OK;
1365 /* Be careful when locking this: it is risky to call the object's AddRef
1366 * or Release holding a lock. */
1367 HRESULT WINAPI
1368 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1369 REFGUID tag, LPVOID pData,
1370 DWORD cbSize, DWORD dwFlags)
1372 PrivateData* data;
1373 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1375 TRACE("(%p)->(%p), size=%ld\n", This, pData, cbSize);
1377 data = find_private_data(This, tag);
1378 if (data == NULL)
1380 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1381 if (data == NULL) return DDERR_OUTOFMEMORY;
1383 data->tag = *tag;
1384 data->flags = dwFlags;
1385 data->uniqueness_value = This->uniqueness_value;
1387 if (dwFlags & DDSPD_IUNKNOWNPTR)
1389 data->ptr.object = (LPUNKNOWN)pData;
1390 data->size = sizeof(LPUNKNOWN);
1391 IUnknown_AddRef(data->ptr.object);
1393 else
1395 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1396 if (data->ptr.data == NULL)
1398 HeapFree(GetProcessHeap(), 0, data);
1399 return DDERR_OUTOFMEMORY;
1402 data->size = cbSize;
1403 memcpy(data->ptr.data, pData, data->size);
1406 /* link it in */
1407 data->next = This->private_data;
1408 data->prev = NULL;
1409 if (This->private_data)
1410 This->private_data->prev = data;
1411 This->private_data = data;
1413 return DD_OK;
1415 else
1417 /* I don't actually know how windows handles this case. The only
1418 * reason I don't just call FreePrivateData is because I want to
1419 * guarantee SetPrivateData working when using LPUNKNOWN or data
1420 * that is no larger than the old data. */
1422 FIXME("Replacing existing private data not implemented yet.\n");
1423 return E_FAIL;
1427 /* SetSurfaceDesc */
1429 HRESULT WINAPI
1430 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1432 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1434 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1436 if (!This->locked) {
1437 WARN("Surface not locked - returing DDERR_NOTLOCKED\n");
1438 return DDERR_NOTLOCKED;
1441 This->locked = FALSE;
1442 This->unlock_update(This, pRect);
1443 if (This->aux_unlock)
1444 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1446 return DD_OK;
1449 HRESULT WINAPI
1450 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1451 LPRECT pSrcRect,
1452 LPDIRECTDRAWSURFACE7 pDstSurface,
1453 LPRECT pDstRect, DWORD dwFlags,
1454 LPDDOVERLAYFX pFX)
1456 return DDERR_UNSUPPORTED;
1459 /* MSDN: "not currently implemented." */
1460 HRESULT WINAPI
1461 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1462 DWORD dwFlags)
1464 return DDERR_UNSUPPORTED;
1467 HRESULT WINAPI
1468 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1469 DWORD dwFlags,
1470 LPDIRECTDRAWSURFACE7 pDDSRef)
1472 return DDERR_NOTAOVERLAYSURFACE;