1 /* DirectDrawSurface base implementation
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 * Copyright 2000 TransGaming Technologies Inc.
13 #include "debugtools.h"
14 #include "ddraw_private.h"
15 #include "dsurface/main.h"
16 #include "ddraw/main.h"
17 #include "dsurface/thunks.h"
19 DEFAULT_DEBUG_CHANNEL(ddraw);
21 /** Creation/Destruction functions */
24 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
26 const DDSURFACEDESC2 *pDDSD)
28 if (pDDSD != &This->surface_desc) {
29 This->surface_desc.dwSize = sizeof(This->surface_desc);
30 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
32 This->uniqueness_value = 1; /* unchecked */
35 This->final_release = Main_DirectDrawSurface_final_release;
36 This->attach = Main_DirectDrawSurface_attach;
37 This->detach = Main_DirectDrawSurface_detach;
38 This->lock_update = Main_DirectDrawSurface_lock_update;
39 This->unlock_update = Main_DirectDrawSurface_unlock_update;
40 This->lose_surface = Main_DirectDrawSurface_lose_surface;
41 This->set_palette = Main_DirectDrawSurface_set_palette;
42 This->update_palette = Main_DirectDrawSurface_update_palette;
43 This->get_display_window = Main_DirectDrawSurface_get_display_window;
45 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
46 DDRAW_IDDS3_Thunk_VTable);
47 /* There is no generic implementation of IDDS7 */
49 Main_DirectDraw_AddSurface(pDD, This);
53 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
55 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
58 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
60 This->final_release(This);
61 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
62 HeapFree(GetProcessHeap(), 0, This);
65 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
67 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
68 Main_DirectDrawSurface_Destroy(This);
71 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
73 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
77 if (This->aux_release)
78 This->aux_release(This->aux_ctx, This->aux_data);
79 Main_DirectDrawSurface_Destroy(This);
86 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
88 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
94 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
97 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
98 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
100 if (IsEqualGUID(&IID_IUnknown, riid)
101 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
102 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
105 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
108 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
109 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
110 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
113 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
117 return E_NOINTERFACE;
123 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
124 IDirectDrawSurfaceImpl *to)
129 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
135 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
140 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
146 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
151 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
152 IDirectDrawPaletteImpl* pal)
157 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
158 IDirectDrawPaletteImpl* pal,
159 DWORD dwStart, DWORD dwCount,
160 LPPALETTEENTRY palent)
165 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
171 /*** Interface functions */
174 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
175 LPDIRECTDRAWSURFACE7 pAttach)
177 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
178 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
179 IDirectDrawSurface7, pAttach);
181 TRACE("(%p)->(%p)\n",This,pAttach);
183 /* Does windows check this? */
185 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
187 /* Does windows check this? */
188 if (surf->ddraw_owner != This->ddraw_owner)
189 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
191 if (surf->surface_owner != NULL)
192 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
194 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
195 * But apparently backbuffers and mipmaps can be attached too. */
197 /* Callback to allow the surface to do something special now that it is
198 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
199 if (!surf->attach(surf, This))
200 return DDERR_CANNOTATTACHSURFACE;
202 /* check: Where should it go in the chain? This puts it on the head. */
204 This->attached->prev_attached = surf;
205 surf->next_attached = This->attached;
206 surf->prev_attached = NULL;
207 This->attached = surf;
208 surf->surface_owner = This;
210 IDirectDrawSurface7_AddRef(pAttach);
215 /* MSDN: "not currently implemented." */
217 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
220 TRACE("(%p)->(%p)\n",iface,pRect);
221 return DDERR_UNSUPPORTED; /* unchecked */
224 /* MSDN: "not currently implemented." */
226 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
227 LPDDBLTBATCH pBatch, DWORD dwCount,
230 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
231 return DDERR_UNSUPPORTED; /* unchecked */
235 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
237 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
238 volatile IDirectDrawSurfaceImpl* vThis = This;
240 TRACE("(%p)\n",This);
241 /* A uniquness value of 0 is apparently special.
242 * This needs to be checked. */
245 DWORD old_uniqueness_value = vThis->uniqueness_value;
246 DWORD new_uniqueness_value = old_uniqueness_value+1;
248 if (old_uniqueness_value == 0) break;
249 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
251 if (InterlockedCompareExchange((PVOID*)&vThis->uniqueness_value,
252 (PVOID)old_uniqueness_value,
253 (PVOID)new_uniqueness_value)
254 == (PVOID)old_uniqueness_value)
262 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
264 LPDIRECTDRAWSURFACE7 pAttach)
266 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
267 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
268 IDirectDrawSurface7, pAttach);
270 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
272 if (!surf || (surf->surface_owner != This))
273 return DDERR_SURFACENOTATTACHED; /* unchecked */
277 if (surf->next_attached)
278 surf->next_attached->prev_attached = surf->prev_attached;
279 if (surf->prev_attached)
280 surf->prev_attached->next_attached = surf->next_attached;
281 if (This->attached == surf)
282 This->attached = surf->next_attached;
284 IDirectDrawSurface7_Release(pAttach);
290 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
292 LPDDENUMSURFACESCALLBACK7 cb)
294 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
295 IDirectDrawSurfaceImpl* surf;
297 TRACE("(%p)->(%p,%p)\n",This,context,cb);
299 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
301 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
302 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
303 context) == DDENUMRET_CANCEL)
311 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
312 DWORD dwFlags, LPVOID context,
313 LPDDENUMSURFACESCALLBACK7 cb)
315 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
319 void Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
320 IDirectDrawSurfaceImpl* back)
322 /* uniqueness_value? */
323 /* This is necessary. But is it safe? */
325 HDC tmp = front->hDC;
326 front->hDC = back->hDC;
331 BOOL tmp = front->dc_in_use;
332 front->dc_in_use = back->dc_in_use;
333 back->dc_in_use = tmp;
338 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
339 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
341 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
342 IDirectDrawSurfaceImpl* target;
345 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
347 /* MSDN: "This method can be called only for a surface that has the
348 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
349 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
350 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
351 return DDERR_NOTFLIPPABLE;
354 if (This->aux_flip(This->aux_ctx, This->aux_data))
357 /* 1. find the flip target */
358 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
359 if (override == NULL)
361 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
362 LPDIRECTDRAWSURFACE7 tgt;
364 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
365 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
367 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
369 IDirectDrawSurface7_Release(tgt);
373 BOOL on_chain = FALSE;
374 IDirectDrawSurfaceImpl* surf;
376 /* MSDN: "The method fails if the specified [override] surface is not
377 * a member of the flipping chain." */
379 /* Verify that override is on this flip chain. We assume that
380 * surf is the head of the flipping chain, because it's the front
382 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
385 /* Either target is (indirectly) attached to This or This is
386 * (indirectly) attached to target. */
387 for (surf = target; surf != NULL; surf = surf->surface_owner)
397 return DDERR_INVALIDPARAMS; /* unchecked */
400 TRACE("flip to backbuffer: %p\n",target);
401 This->flip_data(This, target);
402 This->flip_update(This);
407 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
411 for (data = This->private_data; data != NULL; data = data->next)
413 if (IsEqualGUID(&data->tag, tag)) break;
420 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
422 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
425 data = find_private_data(This, tag);
426 if (data == NULL) return DDERR_NOTFOUND;
429 data->prev->next = data->next;
431 data->next->prev = data->prev;
433 if (data->flags & DDSPD_IUNKNOWNPTR)
435 if (data->ptr.object != NULL)
436 IUnknown_Release(data->ptr.object);
439 HeapFree(GetProcessHeap(), 0, data->ptr.data);
441 HeapFree(GetProcessHeap(), 0, data);
447 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
449 LPDIRECTDRAWSURFACE7* ppSurface)
451 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
452 IDirectDrawSurfaceImpl* surf;
453 IDirectDrawSurfaceImpl* found = NULL;
455 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
456 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
458 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
460 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
461 surf->surface_desc.ddsCaps.dwCaps,
462 surf->surface_desc.ddsCaps.dwCaps2,
463 surf->surface_desc.ddsCaps.dwCaps3,
464 surf->surface_desc.ddsCaps.dwCaps4);
465 if (((surf->surface_desc.ddsCaps.dwCaps & pCaps->dwCaps) == pCaps->dwCaps)
466 && ((surf->surface_desc.ddsCaps.dwCaps2 & pCaps->dwCaps2) == pCaps->dwCaps2))
468 /* MSDN: "This method fails if more than one surface is attached
469 * that matches the capabilities requested." */
472 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
473 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
474 to be correct, given what 3DMark expects from MipMapped surfaces.
475 We shall just continue instead. */
483 return DDERR_NOTFOUND;
485 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
487 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
488 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
493 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
495 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
500 case DDGBS_ISBLTDONE:
504 return DDERR_INVALIDPARAMS;
509 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
511 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
513 TRACE("(%p)->(%p)\n",This,pCaps);
514 *pCaps = This->surface_desc.ddsCaps;
519 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
520 LPDIRECTDRAWCLIPPER* ppClipper)
522 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
524 TRACE("(%p)->(%p)\n",This,ppClipper);
525 if (This->clipper == NULL)
526 return DDERR_NOCLIPPERATTACHED;
528 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
529 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
530 IDirectDrawClipper));
535 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
538 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
539 * isn't there? That's like saying that an int isn't there. (Which MS
540 * has done in other docs.) */
542 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
544 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
548 *pCKey = This->surface_desc.ddckCKDestBlt;
551 case DDCKEY_DESTOVERLAY:
552 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
556 *pCKey = This->surface_desc.ddckCKSrcBlt;
559 case DDCKEY_SRCOVERLAY:
560 *pCKey = This->surface_desc.ddckCKSrcOverlay;
564 return DDERR_INVALIDPARAMS;
570 /* XXX We need to do something with the DC if the surface gets lost. */
572 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
576 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
578 TRACE("(%p)->(%p)\n",This,phDC);
586 return DDERR_DCALREADYCREATED;
590 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
591 * thread has it locked, but GetDC does not. */
592 ddsd.dwSize = sizeof(ddsd);
593 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
600 hr = This->get_dc(This, &This->hDC);
603 TRACE("returning %08x\n",This->hDC);
606 This->dc_in_use = TRUE;
608 else WARN("No DC! Prepare for trouble\n");
615 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
617 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
619 TRACE("(%p)->(%p)\n",This,pDD);
620 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
621 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
626 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
628 /* XXX: DDERR_INVALIDSURFACETYPE */
630 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
634 case DDGFS_ISFLIPDONE:
638 return DDERR_INVALIDPARAMS;
643 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
645 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
647 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
650 *pdwMaxLOD = This->max_lod;
655 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
656 LPLONG pX, LPLONG pY)
658 return DDERR_NOTAOVERLAYSURFACE;
662 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
663 LPDIRECTDRAWPALETTE* ppPalette)
665 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
667 TRACE("(%p)->(%p)\n",This,ppPalette);
668 if (This->palette == NULL)
669 return DDERR_NOPALETTEATTACHED;
671 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
672 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
673 IDirectDrawPalette));
678 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
679 LPDDPIXELFORMAT pDDPixelFormat)
681 /* What is DDERR_INVALIDSURFACETYPE for here? */
682 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
684 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
685 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
690 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
693 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
695 TRACE("(%p)->(%p)\n",This,pdwPriority);
698 *pdwPriority = This->priority;
703 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
704 REFGUID tag, LPVOID pBuffer,
705 LPDWORD pcbBufferSize)
707 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
710 data = find_private_data(This, tag);
711 if (data == NULL) return DDERR_NOTFOUND;
713 /* This may not be right. */
714 if ((data->flags & DDSPD_VOLATILE)
715 && data->uniqueness_value != This->uniqueness_value)
716 return DDERR_EXPIRED;
718 if (*pcbBufferSize < data->size)
720 *pcbBufferSize = data->size;
721 return DDERR_MOREDATA;
724 if (data->flags & DDSPD_IUNKNOWNPTR)
726 *(LPUNKNOWN *)pBuffer = data->ptr.object;
727 IUnknown_AddRef(data->ptr.object);
731 memcpy(pBuffer, data->ptr.data, data->size);
738 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
739 LPDDSURFACEDESC2 pDDSD)
741 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
743 TRACE("(%p)->(%p)\n",This,pDDSD);
744 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
745 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
746 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
747 return DDERR_GENERIC;
750 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
755 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
758 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
760 TRACE("(%p)->(%p)\n",This,pValue);
761 *pValue = This->uniqueness_value;
766 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
767 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
769 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
770 return DDERR_ALREADYINITIALIZED;
774 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
776 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
778 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
779 return This->lost ? DDERR_SURFACELOST : DD_OK;
783 /* XXX This doesn't actually do any locking or keep track of the locked
784 * rectangles. The behaviour is poorly documented. */
786 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
787 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
789 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
791 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
793 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
794 WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
795 This,prect,pDDSD,flags,(DWORD)h);
797 /* First, copy the Surface description */
798 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
800 TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
801 pDDSD->dwHeight,pDDSD->dwWidth,pDDSD->u1.lPitch);
803 /* If asked only for a part, change the surface pointer.
804 * (Not documented.) */
806 TRACE(" lprect: %dx%d-%dx%d\n",
807 prect->top,prect->left,prect->bottom,prect->right
809 if ((prect->top < 0) ||
811 (prect->bottom < 0) ||
812 (prect->right < 0)) {
813 ERR(" Negative values in LPRECT !!!\n");
814 return DDERR_INVALIDPARAMS;
817 This->lock_update(This, prect);
819 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
820 + prect->top * This->surface_desc.u1.lPitch
821 + prect->left * GET_BPP(This->surface_desc);
828 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
830 /* Some surface types should return DDERR_CANTPAGELOCK. */
835 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
837 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
838 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
843 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
846 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
848 TRACE("(%p)->(%08x)\n",This,hDC);
850 if (!This->dc_in_use || This->hDC != hDC)
851 return DDERR_INVALIDPARAMS;
853 This->release_dc(This, hDC);
855 hr = IDirectDrawSurface7_Unlock(iface, NULL);
856 if (FAILED(hr)) return hr;
858 This->dc_in_use = FALSE;
867 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
868 LPDIRECTDRAWCLIPPER pDDClipper)
870 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
872 TRACE("(%p)->(%p)\n",This,pDDClipper);
873 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
876 if (This->clipper != NULL)
877 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
878 IDirectDrawClipper));
880 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
882 if (pDDClipper != NULL)
883 IDirectDrawClipper_AddRef(pDDClipper);
889 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
890 DWORD dwFlags, LPDDCOLORKEY pCKey)
892 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
894 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
897 FIXME("supposedly removing color key %lu\n",
898 dwFlags & ~DDCKEY_COLORSPACE);
902 switch (dwFlags & ~DDCKEY_COLORSPACE)
905 This->surface_desc.ddckCKDestBlt = *pCKey;
908 case DDCKEY_DESTOVERLAY:
909 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
912 case DDCKEY_SRCOVERLAY:
913 This->surface_desc.ddckCKSrcOverlay = *pCKey;
917 This->surface_desc.ddckCKSrcBlt = *pCKey;
921 return DDERR_INVALIDPARAMS;
928 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
930 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
932 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
935 This->max_lod = dwMaxLOD;
940 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
943 return DDERR_NOTAOVERLAYSURFACE;
947 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
948 LPDIRECTDRAWPALETTE pPalette)
950 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
952 TRACE("(%p)->(%p)\n",This,pPalette);
953 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
956 if (This->palette != NULL) {
957 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
958 This->palette->flags &= ~DDPCAPS_PRIMARYSURFACE;
959 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
960 IDirectDrawPalette));
963 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
965 if (pPalette != NULL) {
966 IDirectDrawPalette_AddRef(pPalette);
967 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
968 This->palette->flags |= DDPCAPS_PRIMARYSURFACE;
971 This->set_palette(This, This->palette);
977 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
980 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
982 TRACE("(%p)->(%08lx)\n",This,dwPriority);
985 This->priority = dwPriority;
989 /* Be careful when locking this: it is risky to call the object's AddRef
990 * or Release holding a lock. */
992 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
993 REFGUID tag, LPVOID pData,
994 DWORD cbSize, DWORD dwFlags)
997 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
999 data = find_private_data(This, tag);
1002 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1003 if (data == NULL) return DDERR_OUTOFMEMORY;
1006 data->flags = dwFlags;
1007 data->uniqueness_value = This->uniqueness_value;
1009 if (dwFlags & DDSPD_IUNKNOWNPTR)
1011 data->ptr.object = (LPUNKNOWN)pData;
1012 data->size = sizeof(LPUNKNOWN);
1013 IUnknown_AddRef(data->ptr.object);
1017 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1018 if (data->ptr.data == NULL)
1020 HeapFree(GetProcessHeap(), 0, data);
1021 return DDERR_OUTOFMEMORY;
1026 data->next = This->private_data;
1028 if (This->private_data)
1029 This->private_data->prev = data;
1030 This->private_data = data;
1036 /* I don't actually know how windows handles this case. The only
1037 * reason I don't just call FreePrivateData is because I want to
1038 * guarantee SetPrivateData working when using LPUNKNOWN or data
1039 * that is no larger than the old data. */
1045 /* SetSurfaceDesc */
1048 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1050 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1052 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1054 This->unlock_update(This, pRect);
1055 if (This->aux_unlock)
1056 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1062 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1064 LPDIRECTDRAWSURFACE7 pDstSurface,
1065 LPRECT pDstRect, DWORD dwFlags,
1068 return DDERR_UNSUPPORTED;
1071 /* MSDN: "not currently implemented." */
1073 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1076 return DDERR_UNSUPPORTED;
1080 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1082 LPDIRECTDRAWSURFACE7 pDDSRef)
1084 return DDERR_NOTAOVERLAYSURFACE;