ntdll: Add a test for NtNotifyChangeDirectoryFile.
[wine/multimedia.git] / dlls / ddraw / surface_main.c
blobba113590fa5eb0a7895bf62a647241c75a3b8486
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"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <string.h>
27 #define COBJMACROS
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
31 #include "winerror.h"
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 */
42 HRESULT
43 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
44 IDirectDrawImpl *pDD,
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 */
54 This->ref = 1;
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,
87 DDRAW_IDDGC_VTable);
89 /* There is no generic implementation of IDDS7 or texture */
91 Main_DirectDraw_AddSurface(pDD, This);
92 return DD_OK;
95 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
97 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
100 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
102 return DD_OK;
105 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
107 if (This->palette) {
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);
130 if (ref == 0)
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);
138 return 0;
141 return ref;
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);
151 return ref;
154 HRESULT WINAPI
155 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
156 LPVOID* ppObj)
158 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
159 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
161 *ppObj = NULL;
163 if(!riid)
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);
172 return S_OK;
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);
180 return S_OK;
182 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
184 InterlockedIncrement(&This->ref);
185 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
186 return S_OK;
188 #ifdef HAVE_OPENGL
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;
197 HRESULT ret_value;
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 */
206 return ret_value;
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);
232 } else {
233 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
234 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
236 InterlockedIncrement(&This->ref);
237 return ret_value;
239 #endif
241 return E_NOINTERFACE;
244 /*** Callbacks */
246 BOOL
247 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
248 IDirectDrawSurfaceImpl *to)
250 return TRUE;
253 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
255 return TRUE;
258 void
259 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
260 DWORD dwFlags)
264 void
265 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
266 LPCRECT pRect)
270 void
271 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
275 void
276 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
277 IDirectDrawPaletteImpl* pal)
281 void
282 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
283 IDirectDrawPaletteImpl* pal,
284 DWORD dwStart, DWORD dwCount,
285 LPPALETTEENTRY palent)
289 HWND
290 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
292 return 0;
295 HRESULT
296 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
297 DWORD dwFlags,
298 LPDDGAMMARAMP lpGammaRamp)
300 HDC hDC;
301 HRESULT hr;
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);
306 return hr;
309 HRESULT
310 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
311 DWORD dwFlags,
312 LPDDGAMMARAMP lpGammaRamp)
314 HDC hDC;
315 HRESULT hr;
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);
320 return hr;
324 /*** Interface functions */
326 HRESULT WINAPI
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? */
337 if (surf == 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. */
364 if (This->attached)
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);
373 return DD_OK;
376 /* MSDN: "not currently implemented." */
377 HRESULT WINAPI
378 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
379 LPRECT pRect)
381 TRACE("(%p)->(%p)\n",iface,pRect);
382 return DDERR_UNSUPPORTED; /* unchecked */
385 /* MSDN: "not currently implemented." */
386 HRESULT WINAPI
387 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
388 LPDDBLTBATCH pBatch, DWORD dwCount,
389 DWORD dwFlags)
391 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
392 return DDERR_UNSUPPORTED; /* unchecked */
395 HRESULT WINAPI
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. */
404 while (1)
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)
416 break;
419 return DD_OK;
422 HRESULT WINAPI
423 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
424 DWORD dwFlags,
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 */
436 surf->detach(surf);
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);
455 return DD_OK;
458 HRESULT WINAPI
459 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
460 LPVOID context,
461 LPDDENUMSURFACESCALLBACK7 cb)
463 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
464 IDirectDrawSurfaceImpl* surf;
465 DDSURFACEDESC2 desc;
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)
482 break;
485 TRACE(" end of enumeration.\n");
487 return DD_OK;
490 HRESULT WINAPI
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);
496 return DD_OK;
499 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
500 IDirectDrawSurfaceImpl* back,
501 DWORD dwFlags)
503 /* uniqueness_value? */
504 /* This is necessary. But is it safe? */
506 HDC tmp = front->hDC;
507 front->hDC = back->hDC;
508 back->hDC = tmp;
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;
529 return TRUE;
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;
543 HRESULT WINAPI
544 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
545 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
547 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
548 IDirectDrawSurfaceImpl* target;
549 HRESULT hr;
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 *) &current_time);
558 if (prev_time != 0) {
559 LONGLONG total_time = 0;
560 int tot_meas;
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) {
569 current_window++;
570 valid_windows++;
572 if (valid_windows < NUMBER_OF_WINDOWS) {
573 unsigned int i;
574 tot_meas = valid_windows * MEASUREMENT_WINDOW;
575 for (i = 0; i < valid_windows; i++) {
576 total_time += perf_storage[i];
578 } else {
579 int 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) {
589 current_window = 0;
591 perf_storage[current_window] = 0;
592 measurements_in_window = 0;
594 } else {
595 prev_time = current_time;
596 memset(perf_storage, 0, sizeof(perf_storage));
597 current_window = 0;
598 valid_windows = 0;
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;
610 if (This->aux_flip)
611 if (This->aux_flip(This->aux_ctx, This->aux_data))
612 return DD_OK;
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,
625 tgt);
626 IDirectDrawSurface7_Release(tgt);
628 else
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
638 * buffer. */
639 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
640 override);
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)
646 if (surf == This)
648 on_chain = TRUE;
649 break;
653 if (!on_chain)
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;
661 char buf[32];
662 FILE *f;
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);
678 return DD_OK;
681 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
682 REFGUID tag)
684 PrivateData* data;
685 for (data = This->private_data; data != NULL; data = data->next)
687 if (IsEqualGUID(&data->tag, tag)) break;
690 return data;
693 HRESULT WINAPI
694 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
696 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
697 PrivateData *data;
699 data = find_private_data(This, tag);
700 if (data == NULL) return DDERR_NOTFOUND;
702 if (data->prev)
703 data->prev->next = data->next;
704 if (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);
712 else
713 HeapFree(GetProcessHeap(), 0, data->ptr.data);
715 HeapFree(GetProcessHeap(), 0, data);
717 return DD_OK;
720 HRESULT WINAPI
721 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
722 LPDDSCAPS2 pCaps,
723 LPDIRECTDRAWSURFACE7* ppSurface)
725 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
726 IDirectDrawSurfaceImpl* surf;
727 IDirectDrawSurfaceImpl* found = NULL;
728 DDSCAPS2 our_caps;
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");
736 our_caps = *pCaps;
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." */
763 if (found != NULL)
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. */
771 found = surf;
775 if (found == NULL) {
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));
789 return DD_OK;
792 HRESULT WINAPI
793 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
795 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
797 switch (dwFlags)
799 case DDGBS_CANBLT:
800 case DDGBS_ISBLTDONE:
801 return DD_OK;
803 default:
804 return DDERR_INVALIDPARAMS;
808 HRESULT WINAPI
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;
815 return DD_OK;
818 HRESULT WINAPI
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));
831 return DD_OK;
834 HRESULT WINAPI
835 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
836 LPDDCOLORKEY pCKey)
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);
850 switch (dwFlags)
852 case DDCKEY_DESTBLT:
853 *pCKey = This->surface_desc.ddckCKDestBlt;
854 break;
856 case DDCKEY_DESTOVERLAY:
857 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
858 break;
860 case DDCKEY_SRCBLT:
861 *pCKey = This->surface_desc.ddckCKSrcBlt;
862 break;
864 case DDCKEY_SRCOVERLAY:
865 *pCKey = This->surface_desc.ddckCKSrcOverlay;
866 break;
868 default:
869 return DDERR_INVALIDPARAMS;
872 return DD_OK;
875 /* XXX We need to do something with the DC if the surface gets lost. */
876 HRESULT WINAPI
877 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
879 DDSURFACEDESC2 ddsd;
880 HRESULT hr;
881 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
883 TRACE("(%p)->(%p)\n",This,phDC);
884 CHECK_LOST(This);
886 LOCK_OBJECT(This);
888 if (This->dc_in_use)
890 UNLOCK_OBJECT(This);
891 return DDERR_DCALREADYCREATED;
894 /* Lock as per MSDN.
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);
899 if (FAILED(hr))
901 UNLOCK_OBJECT(This);
902 return hr;
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)) {
915 RGBQUAD col[256];
916 IDirectDrawPaletteImpl *pal = surf->palette;
917 unsigned int n;
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);
925 break;
931 if (SUCCEEDED(hr))
933 TRACE("returning %p\n",This->hDC);
935 *phDC = This->hDC;
936 This->dc_in_use = TRUE;
938 else WARN("No DC! Prepare for trouble\n");
940 UNLOCK_OBJECT(This);
941 return hr;
944 HRESULT WINAPI
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));
952 return DD_OK;
955 HRESULT WINAPI
956 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
958 /* XXX: DDERR_INVALIDSURFACETYPE */
960 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
961 switch (dwFlags)
963 case DDGFS_CANFLIP:
964 case DDGFS_ISFLIPDONE:
965 return DD_OK;
967 default:
968 return DDERR_INVALIDPARAMS;
972 HRESULT WINAPI
973 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
975 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
977 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
978 CHECK_TEXTURE(This);
980 *pdwMaxLOD = This->max_lod;
981 return DD_OK;
984 HRESULT WINAPI
985 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
986 LPLONG pX, LPLONG pY)
988 return DDERR_NOTAOVERLAYSURFACE;
991 HRESULT WINAPI
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));
1004 return DD_OK;
1007 HRESULT WINAPI
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);
1016 return DD_OK;
1019 HRESULT WINAPI
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;
1029 return DD_OK;
1032 HRESULT WINAPI
1033 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1034 REFGUID tag, LPVOID pBuffer,
1035 LPDWORD pcbBufferSize)
1037 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1038 PrivateData* data;
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);
1061 else
1063 memcpy(pBuffer, data->ptr.data, data->size);
1066 return DD_OK;
1069 HRESULT WINAPI
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);
1086 return DD_OK;
1089 HRESULT WINAPI
1090 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
1091 LPDWORD pValue)
1093 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1095 TRACE("(%p)->(%p)\n",This,pValue);
1096 *pValue = This->uniqueness_value;
1097 return DD_OK;
1100 HRESULT WINAPI
1101 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
1102 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
1104 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
1105 return DDERR_ALREADYINITIALIZED;
1108 HRESULT WINAPI
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. */
1120 HRESULT WINAPI
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));
1135 if (NULL != h) {
1136 return DDERR_INVALIDPARAMS;
1138 if (NULL == pDDSD) {
1139 return DDERR_INVALIDPARAMS;
1142 /* If the surface is already locked, return busy */
1143 if (This->locked) {
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) {
1178 int blksize;
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;
1188 } else
1189 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1190 + prect->top * This->surface_desc.u1.lPitch
1191 + prect->left * GET_BPP(This->surface_desc);
1192 } else {
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);
1201 return DD_OK;
1204 HRESULT WINAPI
1205 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1207 /* Some surface types should return DDERR_CANTPAGELOCK. */
1208 return DD_OK;
1211 HRESULT WINAPI
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. */
1216 return DD_OK;
1219 HRESULT WINAPI
1220 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1222 HRESULT hr;
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;
1236 This->hDC = 0;
1238 return DD_OK;
1241 /* Restore */
1243 HRESULT WINAPI
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))
1251 return DD_OK;
1253 if (This->clipper != NULL)
1254 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1255 IDirectDrawClipper));
1257 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1258 pDDClipper);
1259 if (pDDClipper != NULL)
1260 IDirectDrawClipper_AddRef(pDDClipper);
1262 return DD_OK;
1265 HRESULT WINAPI
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
1285 one API call).
1287 if (pCKey) {
1288 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1289 case DDCKEY_DESTBLT:
1290 This->surface_desc.ddckCKDestBlt = *pCKey;
1291 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1292 break;
1294 case DDCKEY_DESTOVERLAY:
1295 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1296 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1297 break;
1299 case DDCKEY_SRCOVERLAY:
1300 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1301 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1302 break;
1304 case DDCKEY_SRCBLT:
1305 This->surface_desc.ddckCKSrcBlt = *pCKey;
1306 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1307 break;
1309 default:
1310 return DDERR_INVALIDPARAMS;
1312 } else {
1313 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1314 case DDCKEY_DESTBLT:
1315 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1316 break;
1318 case DDCKEY_DESTOVERLAY:
1319 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1320 break;
1322 case DDCKEY_SRCOVERLAY:
1323 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1324 break;
1326 case DDCKEY_SRCBLT:
1327 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1328 break;
1330 default:
1331 return DDERR_INVALIDPARAMS;
1335 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1337 return DD_OK;
1340 HRESULT WINAPI
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;
1349 return DD_OK;
1352 HRESULT WINAPI
1353 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1354 LONG X, LONG Y)
1356 return DDERR_NOTAOVERLAYSURFACE;
1359 HRESULT WINAPI
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))
1368 return DD_OK;
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,
1377 pPalette);
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);
1392 return DD_OK;
1395 HRESULT WINAPI
1396 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1397 DWORD dwPriority)
1399 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1401 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1402 CHECK_TEXTURE(This);
1404 This->priority = dwPriority;
1405 return DD_OK;
1408 /* Be careful when locking this: it is risky to call the object's AddRef
1409 * or Release holding a lock. */
1410 HRESULT WINAPI
1411 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1412 REFGUID tag, LPVOID pData,
1413 DWORD cbSize, DWORD dwFlags)
1415 PrivateData* data;
1416 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1418 TRACE("(%p)->(%p), size=%ld\n", This, pData, cbSize);
1420 data = find_private_data(This, tag);
1421 if (data == NULL)
1423 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1424 if (data == NULL) return DDERR_OUTOFMEMORY;
1426 data->tag = *tag;
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);
1436 else
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);
1449 /* link it in */
1450 data->next = This->private_data;
1451 data->prev = NULL;
1452 if (This->private_data)
1453 This->private_data->prev = data;
1454 This->private_data = data;
1456 return DD_OK;
1458 else
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");
1466 return E_FAIL;
1470 /* SetSurfaceDesc */
1472 HRESULT WINAPI
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);
1489 return DD_OK;
1492 HRESULT WINAPI
1493 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1494 LPRECT pSrcRect,
1495 LPDIRECTDRAWSURFACE7 pDstSurface,
1496 LPRECT pDstRect, DWORD dwFlags,
1497 LPDDOVERLAYFX pFX)
1499 return DDERR_UNSUPPORTED;
1502 /* MSDN: "not currently implemented." */
1503 HRESULT WINAPI
1504 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1505 DWORD dwFlags)
1507 return DDERR_UNSUPPORTED;
1510 HRESULT WINAPI
1511 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1512 DWORD dwFlags,
1513 LPDIRECTDRAWSURFACE7 pDDSRef)
1515 return DDERR_NOTAOVERLAYSURFACE;