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