Make CONST_VTABLE the default in the Wine source.
[wine/dcerpc.git] / dlls / ddraw / surface_main.c
blob39566c433ea1f1dd0d21af3c646c0aa4111a2d92
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 "wine/debug.h"
32 #include "ddraw_private.h"
33 #include "opengl_private.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
36 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
39 /** Creation/Destruction functions */
41 HRESULT
42 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
43 IDirectDrawImpl *pDD,
44 const DDSURFACEDESC2 *pDDSD)
46 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
48 if (pDDSD != &This->surface_desc) {
49 This->surface_desc.dwSize = sizeof(This->surface_desc);
50 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
52 This->uniqueness_value = 1; /* unchecked */
53 This->ref = 1;
55 This->local.lpSurfMore = &This->more;
56 This->local.lpGbl = &This->global;
57 This->local.dwProcessId = GetCurrentProcessId();
58 This->local.dwFlags = 0; /* FIXME */
59 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
60 /* FIXME: more local stuff */
61 This->more.lpDD_lcl = &pDD->local;
62 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
63 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
64 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
65 /* FIXME: more more stuff */
66 This->gmore = &This->global_more;
67 This->global.u3.lpDD = pDD->local.lpGbl;
68 /* FIXME: more global stuff */
70 This->final_release = Main_DirectDrawSurface_final_release;
71 This->late_allocate = Main_DirectDrawSurface_late_allocate;
72 This->attach = Main_DirectDrawSurface_attach;
73 This->detach = Main_DirectDrawSurface_detach;
74 This->lock_update = Main_DirectDrawSurface_lock_update;
75 This->unlock_update = Main_DirectDrawSurface_unlock_update;
76 This->lose_surface = Main_DirectDrawSurface_lose_surface;
77 This->set_palette = Main_DirectDrawSurface_set_palette;
78 This->update_palette = Main_DirectDrawSurface_update_palette;
79 This->get_display_window = Main_DirectDrawSurface_get_display_window;
80 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
81 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
83 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
84 DDRAW_IDDS3_Thunk_VTable);
85 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
86 DDRAW_IDDGC_VTable);
88 /* There is no generic implementation of IDDS7 or texture */
90 Main_DirectDraw_AddSurface(pDD, This);
91 return DD_OK;
94 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
96 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
99 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
101 return DD_OK;
104 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
106 if (This->palette) {
107 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
108 This->palette = NULL;
110 This->final_release(This);
111 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
112 if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
113 HeapFree(GetProcessHeap(), 0, This);
116 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
118 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
119 Main_DirectDrawSurface_Destroy(This);
122 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
124 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
125 ULONG ref = InterlockedDecrement(&This->ref);
127 TRACE("(%p)->(): decreasing from %ld\n", This, ref + 1);
129 if (ref == 0)
131 if (This->aux_release)
132 This->aux_release(This->aux_ctx, This->aux_data);
133 Main_DirectDrawSurface_Destroy(This);
135 TRACE("released surface %p\n", This);
137 return 0;
140 return ref;
143 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
145 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
146 ULONG ref = InterlockedIncrement(&This->ref);
148 TRACE("(%p)->(): increasing from %ld\n", This, ref - 1);
150 return ref;
153 HRESULT WINAPI
154 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
155 LPVOID* ppObj)
157 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
158 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
160 *ppObj = NULL;
162 if (IsEqualGUID(&IID_IUnknown, riid)
163 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
164 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
166 InterlockedIncrement(&This->ref);
167 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
168 return S_OK;
170 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
171 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
172 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
174 InterlockedIncrement(&This->ref);
175 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
176 return S_OK;
178 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
180 InterlockedIncrement(&This->ref);
181 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
182 return S_OK;
184 #ifdef HAVE_OPENGL
185 /* interfaces following here require OpenGL */
186 if( !opengl_initialized )
187 return E_NOINTERFACE;
189 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
190 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
192 IDirect3DDeviceImpl *d3ddevimpl;
193 HRESULT ret_value;
195 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, 1);
196 if (FAILED(ret_value)) return ret_value;
198 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
199 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
201 InterlockedIncrement(&This->ref); /* No idea if this is correct.. Need to check using real Windows */
202 return ret_value;
204 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
205 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
207 HRESULT ret_value = S_OK;
209 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
210 application I know creating a texture without this flag set and it will prevent
211 bugs in other parts of Wine.
213 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
215 /* In case the texture surface was created before the D3D creation */
216 if (This->tex_private == NULL) {
217 if (This->ddraw_owner->d3d_private == NULL) {
218 ERR("Texture created with no D3D object yet.. Not supported !\n");
219 return E_NOINTERFACE;
222 ret_value = This->ddraw_owner->d3d_create_texture(This->ddraw_owner, This, FALSE, This->mip_main);
223 if (FAILED(ret_value)) return ret_value;
225 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
226 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
227 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
228 } else {
229 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
230 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
232 InterlockedIncrement(&This->ref);
233 return ret_value;
235 #endif
237 return E_NOINTERFACE;
240 /*** Callbacks */
242 BOOL
243 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
244 IDirectDrawSurfaceImpl *to)
246 return TRUE;
249 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
251 return TRUE;
254 void
255 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
256 DWORD dwFlags)
260 void
261 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
262 LPCRECT pRect)
266 void
267 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
271 void
272 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
273 IDirectDrawPaletteImpl* pal)
277 void
278 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
279 IDirectDrawPaletteImpl* pal,
280 DWORD dwStart, DWORD dwCount,
281 LPPALETTEENTRY palent)
285 HWND
286 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
288 return 0;
291 HRESULT
292 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
293 DWORD dwFlags,
294 LPDDGAMMARAMP lpGammaRamp)
296 HDC hDC;
297 HRESULT hr;
298 hr = This->get_dc(This, &hDC);
299 if (FAILED(hr)) return hr;
300 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
301 This->release_dc(This, hDC);
302 return hr;
305 HRESULT
306 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
307 DWORD dwFlags,
308 LPDDGAMMARAMP lpGammaRamp)
310 HDC hDC;
311 HRESULT hr;
312 hr = This->get_dc(This, &hDC);
313 if (FAILED(hr)) return hr;
314 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
315 This->release_dc(This, hDC);
316 return hr;
320 /*** Interface functions */
322 HRESULT WINAPI
323 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
324 LPDIRECTDRAWSURFACE7 pAttach)
326 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
327 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
328 IDirectDrawSurface7, pAttach);
330 TRACE("(%p)->(%p)\n",This,pAttach);
332 /* Does windows check this? */
333 if (surf == This)
334 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
336 /* Does windows check this? */
337 if (surf->ddraw_owner != This->ddraw_owner)
338 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
340 if (surf->surface_owner != NULL)
341 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
343 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
344 * But apparently backbuffers and mipmaps can be attached too. */
346 /* Set MIPMAPSUBLEVEL if this seems to be one */
347 if (This->surface_desc.ddsCaps.dwCaps &
348 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
349 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
350 /* FIXME: we should probably also add to dwMipMapCount of this
351 * and all parent surfaces (update create_texture if you do) */
354 /* Callback to allow the surface to do something special now that it is
355 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
356 if (!surf->attach(surf, This))
357 return DDERR_CANNOTATTACHSURFACE;
359 /* check: Where should it go in the chain? This puts it on the head. */
360 if (This->attached)
361 This->attached->prev_attached = surf;
362 surf->next_attached = This->attached;
363 surf->prev_attached = NULL;
364 This->attached = surf;
365 surf->surface_owner = This;
367 IDirectDrawSurface7_AddRef(pAttach);
369 return DD_OK;
372 /* MSDN: "not currently implemented." */
373 HRESULT WINAPI
374 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
375 LPRECT pRect)
377 TRACE("(%p)->(%p)\n",iface,pRect);
378 return DDERR_UNSUPPORTED; /* unchecked */
381 /* MSDN: "not currently implemented." */
382 HRESULT WINAPI
383 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
384 LPDDBLTBATCH pBatch, DWORD dwCount,
385 DWORD dwFlags)
387 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
388 return DDERR_UNSUPPORTED; /* unchecked */
391 HRESULT WINAPI
392 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
394 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
395 volatile IDirectDrawSurfaceImpl* vThis = This;
397 TRACE("(%p)\n",This);
398 /* A uniquness value of 0 is apparently special.
399 * This needs to be checked. */
400 while (1)
402 DWORD old_uniqueness_value = vThis->uniqueness_value;
403 DWORD new_uniqueness_value = old_uniqueness_value+1;
405 if (old_uniqueness_value == 0) break;
406 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
408 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
409 old_uniqueness_value,
410 new_uniqueness_value)
411 == old_uniqueness_value)
412 break;
415 return DD_OK;
418 HRESULT WINAPI
419 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
420 DWORD dwFlags,
421 LPDIRECTDRAWSURFACE7 pAttach)
423 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
424 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
425 IDirectDrawSurface7, pAttach);
427 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
429 if (!surf || (surf->surface_owner != This))
430 return DDERR_SURFACENOTATTACHED; /* unchecked */
432 surf->detach(surf);
434 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
435 if (This->surface_desc.ddsCaps.dwCaps &
436 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
437 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
438 /* FIXME: we should probably also subtract from dwMipMapCount of this
439 * and all parent surfaces */
442 if (surf->next_attached)
443 surf->next_attached->prev_attached = surf->prev_attached;
444 if (surf->prev_attached)
445 surf->prev_attached->next_attached = surf->next_attached;
446 if (This->attached == surf)
447 This->attached = surf->next_attached;
449 IDirectDrawSurface7_Release(pAttach);
451 return DD_OK;
454 HRESULT WINAPI
455 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
456 LPVOID context,
457 LPDDENUMSURFACESCALLBACK7 cb)
459 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
460 IDirectDrawSurfaceImpl* surf;
462 TRACE("(%p)->(%p,%p)\n",This,context,cb);
464 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
466 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
467 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
468 context) == DDENUMRET_CANCEL)
469 break;
472 return DD_OK;
475 HRESULT WINAPI
476 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
477 DWORD dwFlags, LPVOID context,
478 LPDDENUMSURFACESCALLBACK7 cb)
480 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
481 return DD_OK;
484 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
485 IDirectDrawSurfaceImpl* back,
486 DWORD dwFlags)
488 /* uniqueness_value? */
489 /* This is necessary. But is it safe? */
491 HDC tmp = front->hDC;
492 front->hDC = back->hDC;
493 back->hDC = tmp;
497 BOOL tmp = front->dc_in_use;
498 front->dc_in_use = back->dc_in_use;
499 back->dc_in_use = tmp;
503 FLATPTR tmp = front->global.fpVidMem;
504 front->global.fpVidMem = back->global.fpVidMem;
505 back->global.fpVidMem = tmp;
509 ULONG_PTR tmp = front->global_more.hKernelSurface;
510 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
511 back->global_more.hKernelSurface = tmp;
514 return TRUE;
517 /* This is unnecessarely complicated :-) */
518 #define MEASUREMENT_WINDOW 5
519 #define NUMBER_OF_WINDOWS 10
521 static LONGLONG perf_freq;
522 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
523 static LONGLONG prev_time = 0;
524 static unsigned int current_window;
525 static unsigned int measurements_in_window;
526 static unsigned int valid_windows;
528 HRESULT WINAPI
529 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
530 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
532 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
533 IDirectDrawSurfaceImpl* target;
534 HRESULT hr;
536 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
538 if (TRACE_ON(ddraw_fps)) {
539 LONGLONG current_time;
540 LONGLONG frame_duration;
541 QueryPerformanceCounter((LARGE_INTEGER *) &current_time);
543 if (prev_time != 0) {
544 LONGLONG total_time = 0;
545 int tot_meas;
547 frame_duration = current_time - prev_time;
548 prev_time = current_time;
550 perf_storage[current_window] += frame_duration;
551 measurements_in_window++;
553 if (measurements_in_window >= MEASUREMENT_WINDOW) {
554 current_window++;
555 valid_windows++;
557 if (valid_windows < NUMBER_OF_WINDOWS) {
558 unsigned int i;
559 tot_meas = valid_windows * MEASUREMENT_WINDOW;
560 for (i = 0; i < valid_windows; i++) {
561 total_time += perf_storage[i];
563 } else {
564 int i;
565 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
566 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
567 total_time += perf_storage[i];
571 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
573 if (current_window >= NUMBER_OF_WINDOWS) {
574 current_window = 0;
576 perf_storage[current_window] = 0;
577 measurements_in_window = 0;
579 } else {
580 prev_time = current_time;
581 memset(perf_storage, 0, sizeof(perf_storage));
582 current_window = 0;
583 valid_windows = 0;
584 measurements_in_window = 0;
585 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
589 /* MSDN: "This method can be called only for a surface that has the
590 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
591 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
592 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
593 return DDERR_NOTFLIPPABLE;
595 if (This->aux_flip)
596 if (This->aux_flip(This->aux_ctx, This->aux_data))
597 return DD_OK;
599 /* 1. find the flip target */
600 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
601 if (override == NULL)
603 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
604 LPDIRECTDRAWSURFACE7 tgt;
606 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
607 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
609 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
610 tgt);
611 IDirectDrawSurface7_Release(tgt);
613 else
615 BOOL on_chain = FALSE;
616 IDirectDrawSurfaceImpl* surf;
618 /* MSDN: "The method fails if the specified [override] surface is not
619 * a member of the flipping chain." */
621 /* Verify that override is on this flip chain. We assume that
622 * surf is the head of the flipping chain, because it's the front
623 * buffer. */
624 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
625 override);
627 /* Either target is (indirectly) attached to This or This is
628 * (indirectly) attached to target. */
629 for (surf = target; surf != NULL; surf = surf->surface_owner)
631 if (surf == This)
633 on_chain = TRUE;
634 break;
638 if (!on_chain)
639 return DDERR_INVALIDPARAMS; /* unchecked */
642 TRACE("flip to backbuffer: %p\n",target);
643 if (TRACE_ON(ddraw_flip)) {
644 static unsigned int flip_count = 0;
645 IDirectDrawPaletteImpl *palette;
646 char buf[32];
647 FILE *f;
649 /* Hack for paletted games... */
650 palette = target->palette;
651 target->palette = This->palette;
653 sprintf(buf, "flip_%08d.ppm", flip_count++);
654 TRACE_(ddraw_flip)("Dumping file %s to disk.\n", buf);
655 f = fopen(buf, "wb");
656 DDRAW_dump_surface_to_disk(target, f, 8);
657 target->palette = palette;
660 if (This->flip_data(This, target, dwFlags))
661 This->flip_update(This, dwFlags);
663 return DD_OK;
666 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
667 REFGUID tag)
669 PrivateData* data;
670 for (data = This->private_data; data != NULL; data = data->next)
672 if (IsEqualGUID(&data->tag, tag)) break;
675 return data;
678 HRESULT WINAPI
679 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
681 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
682 PrivateData *data;
684 data = find_private_data(This, tag);
685 if (data == NULL) return DDERR_NOTFOUND;
687 if (data->prev)
688 data->prev->next = data->next;
689 if (data->next)
690 data->next->prev = data->prev;
692 if (data->flags & DDSPD_IUNKNOWNPTR)
694 if (data->ptr.object != NULL)
695 IUnknown_Release(data->ptr.object);
697 else
698 HeapFree(GetProcessHeap(), 0, data->ptr.data);
700 HeapFree(GetProcessHeap(), 0, data);
702 return DD_OK;
705 HRESULT WINAPI
706 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
707 LPDDSCAPS2 pCaps,
708 LPDIRECTDRAWSURFACE7* ppSurface)
710 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
711 IDirectDrawSurfaceImpl* surf;
712 IDirectDrawSurfaceImpl* found = NULL;
713 DDSCAPS2 our_caps;
715 if (TRACE_ON(ddraw)) {
716 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
717 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
718 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); TRACE("\n");
721 our_caps = *pCaps;
722 if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
723 /* As this is not a DirectDraw7 application, remove the garbage that some games
724 put in the new fields of the DDSCAPS2 structure. */
725 our_caps.dwCaps2 = 0;
726 our_caps.dwCaps3 = 0;
727 our_caps.dwCaps4 = 0;
728 if (TRACE_ON(ddraw)) {
729 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); TRACE("\n");
733 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
735 if (TRACE_ON(ddraw)) {
736 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
737 surf->surface_desc.ddsCaps.dwCaps,
738 surf->surface_desc.ddsCaps.dwCaps2,
739 surf->surface_desc.ddsCaps.dwCaps3,
740 surf->surface_desc.ddsCaps.dwCaps4);
741 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); TRACE("\n");
743 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
744 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
746 /* MSDN: "This method fails if more than one surface is attached
747 * that matches the capabilities requested." */
748 if (found != NULL)
750 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
751 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
752 to be correct, given what 3DMark expects from MipMapped surfaces.
753 We shall just continue instead. */
756 found = surf;
760 if (found == NULL) {
761 TRACE("Did not find any valid surface\n");
762 return DDERR_NOTFOUND;
765 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
767 if (TRACE_ON(ddraw)) {
768 TRACE("Returning surface %p with description : \n", *ppSurface);
769 DDRAW_dump_surface_desc(&(found->surface_desc));
772 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
773 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
774 return DD_OK;
777 HRESULT WINAPI
778 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
780 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
782 switch (dwFlags)
784 case DDGBS_CANBLT:
785 case DDGBS_ISBLTDONE:
786 return DD_OK;
788 default:
789 return DDERR_INVALIDPARAMS;
793 HRESULT WINAPI
794 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
796 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
798 TRACE("(%p)->(%p)\n",This,pCaps);
799 *pCaps = This->surface_desc.ddsCaps;
800 return DD_OK;
803 HRESULT WINAPI
804 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
805 LPDIRECTDRAWCLIPPER* ppClipper)
807 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
809 TRACE("(%p)->(%p)\n",This,ppClipper);
810 if (This->clipper == NULL)
811 return DDERR_NOCLIPPERATTACHED;
813 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
814 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
815 IDirectDrawClipper));
816 return DD_OK;
819 HRESULT WINAPI
820 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
821 LPDDCOLORKEY pCKey)
823 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
824 * isn't there? That's like saying that an int isn't there. (Which MS
825 * has done in other docs.) */
827 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
829 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
830 if (TRACE_ON(ddraw)) {
831 TRACE(" - colorkey flags : ");
832 DDRAW_dump_colorkeyflag(dwFlags);
835 switch (dwFlags)
837 case DDCKEY_DESTBLT:
838 *pCKey = This->surface_desc.ddckCKDestBlt;
839 break;
841 case DDCKEY_DESTOVERLAY:
842 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
843 break;
845 case DDCKEY_SRCBLT:
846 *pCKey = This->surface_desc.ddckCKSrcBlt;
847 break;
849 case DDCKEY_SRCOVERLAY:
850 *pCKey = This->surface_desc.ddckCKSrcOverlay;
851 break;
853 default:
854 return DDERR_INVALIDPARAMS;
857 return DD_OK;
860 /* XXX We need to do something with the DC if the surface gets lost. */
861 HRESULT WINAPI
862 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
864 DDSURFACEDESC2 ddsd;
865 HRESULT hr;
866 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
868 TRACE("(%p)->(%p)\n",This,phDC);
869 CHECK_LOST(This);
871 LOCK_OBJECT(This);
873 if (This->dc_in_use)
875 UNLOCK_OBJECT(This);
876 return DDERR_DCALREADYCREATED;
879 /* Lock as per MSDN.
880 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
881 * thread has it locked, but GetDC does not. */
882 ddsd.dwSize = sizeof(ddsd);
883 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
884 if (FAILED(hr))
886 UNLOCK_OBJECT(This);
887 return hr;
890 hr = This->get_dc(This, &This->hDC);
891 if (SUCCEEDED(hr))
893 TRACE("returning %p\n",This->hDC);
895 *phDC = This->hDC;
896 This->dc_in_use = TRUE;
898 else WARN("No DC! Prepare for trouble\n");
900 UNLOCK_OBJECT(This);
901 return hr;
904 HRESULT WINAPI
905 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
907 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
909 TRACE("(%p)->(%p)\n",This,pDD);
910 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
911 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
912 return DD_OK;
915 HRESULT WINAPI
916 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
918 /* XXX: DDERR_INVALIDSURFACETYPE */
920 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
921 switch (dwFlags)
923 case DDGFS_CANFLIP:
924 case DDGFS_ISFLIPDONE:
925 return DD_OK;
927 default:
928 return DDERR_INVALIDPARAMS;
932 HRESULT WINAPI
933 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
935 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
937 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
938 CHECK_TEXTURE(This);
940 *pdwMaxLOD = This->max_lod;
941 return DD_OK;
944 HRESULT WINAPI
945 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
946 LPLONG pX, LPLONG pY)
948 return DDERR_NOTAOVERLAYSURFACE;
951 HRESULT WINAPI
952 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
953 LPDIRECTDRAWPALETTE* ppPalette)
955 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
957 TRACE("(%p)->(%p)\n",This,ppPalette);
958 if (This->palette == NULL)
959 return DDERR_NOPALETTEATTACHED;
961 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
962 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
963 IDirectDrawPalette));
964 return DD_OK;
967 HRESULT WINAPI
968 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
969 LPDDPIXELFORMAT pDDPixelFormat)
971 /* What is DDERR_INVALIDSURFACETYPE for here? */
972 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
974 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
975 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
976 return DD_OK;
979 HRESULT WINAPI
980 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
981 LPDWORD pdwPriority)
983 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
985 TRACE("(%p)->(%p)\n",This,pdwPriority);
986 CHECK_TEXTURE(This);
988 *pdwPriority = This->priority;
989 return DD_OK;
992 HRESULT WINAPI
993 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
994 REFGUID tag, LPVOID pBuffer,
995 LPDWORD pcbBufferSize)
997 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
998 PrivateData* data;
1000 TRACE("(%p)->(%p), size = %ld\n", This, pBuffer, *pcbBufferSize);
1002 data = find_private_data(This, tag);
1003 if (data == NULL) return DDERR_NOTFOUND;
1005 /* This may not be right. */
1006 if ((data->flags & DDSPD_VOLATILE)
1007 && data->uniqueness_value != This->uniqueness_value)
1008 return DDERR_EXPIRED;
1010 if (*pcbBufferSize < data->size)
1012 *pcbBufferSize = data->size;
1013 return DDERR_MOREDATA;
1016 if (data->flags & DDSPD_IUNKNOWNPTR)
1018 *(LPUNKNOWN *)pBuffer = data->ptr.object;
1019 IUnknown_AddRef(data->ptr.object);
1021 else
1023 memcpy(pBuffer, data->ptr.data, data->size);
1026 return DD_OK;
1029 HRESULT WINAPI
1030 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
1031 LPDDSURFACEDESC2 pDDSD)
1033 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1035 TRACE("(%p)->(%p)\n",This,pDDSD);
1036 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
1037 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
1038 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
1039 return DDERR_GENERIC;
1042 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
1043 if (TRACE_ON(ddraw)) {
1044 DDRAW_dump_surface_desc(pDDSD);
1046 return DD_OK;
1049 HRESULT WINAPI
1050 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
1051 LPDWORD pValue)
1053 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1055 TRACE("(%p)->(%p)\n",This,pValue);
1056 *pValue = This->uniqueness_value;
1057 return DD_OK;
1060 HRESULT WINAPI
1061 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
1062 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
1064 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
1065 return DDERR_ALREADYINITIALIZED;
1068 HRESULT WINAPI
1069 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1071 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1073 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1074 return This->lost ? DDERR_SURFACELOST : DD_OK;
1078 /* XXX This doesn't actually do any locking or keep track of the locked
1079 * rectangles. The behaviour is poorly documented. */
1080 HRESULT WINAPI
1081 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
1082 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
1084 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1086 if (TRACE_ON(ddraw)) {
1087 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
1088 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
1090 if (WARN_ON(ddraw)) {
1091 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
1092 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
1096 /* If the surface is already locked, return busy */
1097 if (This->locked) {
1098 WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
1099 return DDERR_SURFACEBUSY;
1102 /* First, copy the Surface description */
1103 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1105 /* Used to optimize the D3D Device locking */
1106 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1108 /* If asked only for a part, change the surface pointer.
1109 * (Not documented.) */
1110 if (prect != NULL) {
1111 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1112 prect->left,prect->top,prect->right,prect->bottom);
1113 /* First do some sanity checkings on the rectangle we receive.
1114 DungeonSiege seems to gives us once a very bad rectangle for example */
1115 if ((prect->top < 0) ||
1116 (prect->left < 0) ||
1117 (prect->bottom < 0) ||
1118 (prect->right < 0) ||
1119 (prect->left >= prect->right) ||
1120 (prect->top >= prect->bottom) ||
1121 (prect->left >= This->surface_desc.dwWidth) ||
1122 (prect->right > This->surface_desc.dwWidth) ||
1123 (prect->top >= This->surface_desc.dwHeight) ||
1124 (prect->bottom > This->surface_desc.dwHeight)) {
1125 ERR(" Invalid values in LPRECT !!!\n");
1126 return DDERR_INVALIDPARAMS;
1129 This->lock_update(This, prect, flags);
1131 if (pDDSD->u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
1132 int blksize;
1133 switch(pDDSD->u4.ddpfPixelFormat.dwFourCC) {
1134 case MAKE_FOURCC('D','X','T','1') : blksize = 8; break;
1135 case MAKE_FOURCC('D','X','T','3') : blksize = 16; break;
1136 case MAKE_FOURCC('D','X','T','5') : blksize = 16; break;
1137 default: return DDERR_INVALIDPIXELFORMAT;
1139 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1140 + prect->top/4 * (pDDSD->dwWidth+3)/4 * blksize
1141 + prect->left/4 * blksize;
1142 } else
1143 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1144 + prect->top * This->surface_desc.u1.lPitch
1145 + prect->left * GET_BPP(This->surface_desc);
1146 } else {
1147 This->lock_update(This, NULL, flags);
1150 This->locked = TRUE;
1152 TRACE("locked surface returning description : \n");
1153 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1155 return DD_OK;
1158 HRESULT WINAPI
1159 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1161 /* Some surface types should return DDERR_CANTPAGELOCK. */
1162 return DD_OK;
1165 HRESULT WINAPI
1166 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1168 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1169 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1170 return DD_OK;
1173 HRESULT WINAPI
1174 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1176 HRESULT hr;
1177 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1179 TRACE("(%p)->(%p)\n",This,hDC);
1181 if (!This->dc_in_use || This->hDC != hDC)
1182 return DDERR_INVALIDPARAMS;
1184 This->release_dc(This, hDC);
1186 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1187 if (FAILED(hr)) return hr;
1189 This->dc_in_use = FALSE;
1190 This->hDC = 0;
1192 return DD_OK;
1195 /* Restore */
1197 HRESULT WINAPI
1198 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1199 LPDIRECTDRAWCLIPPER pDDClipper)
1201 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1203 TRACE("(%p)->(%p)\n",This,pDDClipper);
1204 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1205 return DD_OK;
1207 if (This->clipper != NULL)
1208 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1209 IDirectDrawClipper));
1211 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1212 pDDClipper);
1213 if (pDDClipper != NULL)
1214 IDirectDrawClipper_AddRef(pDDClipper);
1216 return DD_OK;
1219 HRESULT WINAPI
1220 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1221 DWORD dwFlags, LPDDCOLORKEY pCKey)
1223 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1225 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1227 if (TRACE_ON(ddraw)) {
1228 TRACE(" - colorkey flags : ");
1229 DDRAW_dump_colorkeyflag(dwFlags);
1232 if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1233 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1234 return DDERR_INVALIDPARAMS;
1237 /* TODO: investigate if this function can take multiple bits set at the same
1238 time (ie setting multiple colorkey values at the same time with only
1239 one API call).
1241 if (pCKey) {
1242 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1243 case DDCKEY_DESTBLT:
1244 This->surface_desc.ddckCKDestBlt = *pCKey;
1245 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1246 break;
1248 case DDCKEY_DESTOVERLAY:
1249 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1250 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1251 break;
1253 case DDCKEY_SRCOVERLAY:
1254 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1255 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1256 break;
1258 case DDCKEY_SRCBLT:
1259 This->surface_desc.ddckCKSrcBlt = *pCKey;
1260 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1261 break;
1263 default:
1264 return DDERR_INVALIDPARAMS;
1266 } else {
1267 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1268 case DDCKEY_DESTBLT:
1269 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1270 break;
1272 case DDCKEY_DESTOVERLAY:
1273 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1274 break;
1276 case DDCKEY_SRCOVERLAY:
1277 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1278 break;
1280 case DDCKEY_SRCBLT:
1281 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1282 break;
1284 default:
1285 return DDERR_INVALIDPARAMS;
1289 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1291 return DD_OK;
1294 HRESULT WINAPI
1295 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1297 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1299 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1300 CHECK_TEXTURE(This);
1302 This->max_lod = dwMaxLOD;
1303 return DD_OK;
1306 HRESULT WINAPI
1307 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1308 LONG X, LONG Y)
1310 return DDERR_NOTAOVERLAYSURFACE;
1313 HRESULT WINAPI
1314 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1315 LPDIRECTDRAWPALETTE pPalette)
1317 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1318 IDirectDrawPalette *pal_to_rel = NULL;
1320 TRACE("(%p)->(%p)\n",This,pPalette);
1321 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1322 return DD_OK;
1324 if (This->palette != NULL) {
1325 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1326 This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1327 pal_to_rel = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
1330 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1331 pPalette);
1332 if (pPalette != NULL) {
1333 IDirectDrawPalette_AddRef(pPalette);
1334 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1335 This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1338 This->set_palette(This, This->palette);
1340 /* Do the palette release at the end to prevent doing some 'loop' when removing
1341 * the surface maintaining the last reference on a palette.
1343 if (pal_to_rel != NULL)
1344 IDirectDrawPalette_Release(pal_to_rel);
1346 return DD_OK;
1349 HRESULT WINAPI
1350 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1351 DWORD dwPriority)
1353 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1355 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1356 CHECK_TEXTURE(This);
1358 This->priority = dwPriority;
1359 return DD_OK;
1362 /* Be careful when locking this: it is risky to call the object's AddRef
1363 * or Release holding a lock. */
1364 HRESULT WINAPI
1365 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1366 REFGUID tag, LPVOID pData,
1367 DWORD cbSize, DWORD dwFlags)
1369 PrivateData* data;
1370 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1372 TRACE("(%p)->(%p), size=%ld\n", This, pData, cbSize);
1374 data = find_private_data(This, tag);
1375 if (data == NULL)
1377 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1378 if (data == NULL) return DDERR_OUTOFMEMORY;
1380 data->tag = *tag;
1381 data->flags = dwFlags;
1382 data->uniqueness_value = This->uniqueness_value;
1384 if (dwFlags & DDSPD_IUNKNOWNPTR)
1386 data->ptr.object = (LPUNKNOWN)pData;
1387 data->size = sizeof(LPUNKNOWN);
1388 IUnknown_AddRef(data->ptr.object);
1390 else
1392 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1393 if (data->ptr.data == NULL)
1395 HeapFree(GetProcessHeap(), 0, data);
1396 return DDERR_OUTOFMEMORY;
1399 data->size = cbSize;
1400 memcpy(data->ptr.data, pData, data->size);
1403 /* link it in */
1404 data->next = This->private_data;
1405 data->prev = NULL;
1406 if (This->private_data)
1407 This->private_data->prev = data;
1408 This->private_data = data;
1410 return DD_OK;
1412 else
1414 /* I don't actually know how windows handles this case. The only
1415 * reason I don't just call FreePrivateData is because I want to
1416 * guarantee SetPrivateData working when using LPUNKNOWN or data
1417 * that is no larger than the old data. */
1419 FIXME("Replacing existing private data not implemented yet.\n");
1420 return E_FAIL;
1424 /* SetSurfaceDesc */
1426 HRESULT WINAPI
1427 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1429 IDirectDrawSurfaceImpl *This = (IDirectDrawSurfaceImpl *)iface;
1431 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1433 if (!This->locked) {
1434 WARN("Surface not locked - returing DDERR_NOTLOCKED\n");
1435 return DDERR_NOTLOCKED;
1438 This->locked = FALSE;
1439 This->unlock_update(This, pRect);
1440 if (This->aux_unlock)
1441 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1443 return DD_OK;
1446 HRESULT WINAPI
1447 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1448 LPRECT pSrcRect,
1449 LPDIRECTDRAWSURFACE7 pDstSurface,
1450 LPRECT pDstRect, DWORD dwFlags,
1451 LPDDOVERLAYFX pFX)
1453 return DDERR_UNSUPPORTED;
1456 /* MSDN: "not currently implemented." */
1457 HRESULT WINAPI
1458 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1459 DWORD dwFlags)
1461 return DDERR_UNSUPPORTED;
1464 HRESULT WINAPI
1465 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1466 DWORD dwFlags,
1467 LPDIRECTDRAWSURFACE7 pDDSRef)
1469 return DDERR_NOTAOVERLAYSURFACE;