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.
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->local.lpSurfMore = &This->more;
36 This->local.lpGbl = &This->global;
37 This->local.dwProcessId = GetCurrentProcessId();
38 This->local.dwFlags = 0; /* FIXME */
39 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
40 /* FIXME: more local stuff */
41 This->more.lpDD_lcl = &pDD->local;
42 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
43 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
44 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
45 /* FIXME: more more stuff */
46 This->gmore = &This->global_more;
47 This->global.u3.lpDD = pDD->local.lpGbl;
48 /* FIXME: more global stuff */
50 This->final_release = Main_DirectDrawSurface_final_release;
51 This->late_allocate = Main_DirectDrawSurface_late_allocate;
52 This->attach = Main_DirectDrawSurface_attach;
53 This->detach = Main_DirectDrawSurface_detach;
54 This->lock_update = Main_DirectDrawSurface_lock_update;
55 This->unlock_update = Main_DirectDrawSurface_unlock_update;
56 This->lose_surface = Main_DirectDrawSurface_lose_surface;
57 This->set_palette = Main_DirectDrawSurface_set_palette;
58 This->update_palette = Main_DirectDrawSurface_update_palette;
59 This->get_display_window = Main_DirectDrawSurface_get_display_window;
60 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
61 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
63 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
64 DDRAW_IDDS3_Thunk_VTable);
65 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
67 /* There is no generic implementation of IDDS7 */
69 Main_DirectDraw_AddSurface(pDD, This);
73 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
75 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
78 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
83 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
85 This->final_release(This);
86 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
87 HeapFree(GetProcessHeap(), 0, This);
90 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
92 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
93 Main_DirectDrawSurface_Destroy(This);
96 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
98 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
100 if (--This->ref == 0)
102 if (This->aux_release)
103 This->aux_release(This->aux_ctx, This->aux_data);
104 Main_DirectDrawSurface_Destroy(This);
111 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
113 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
119 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
122 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
123 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
125 if (IsEqualGUID(&IID_IUnknown, riid)
126 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
127 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
130 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
133 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
134 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
135 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
138 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
141 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
144 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
148 return E_NOINTERFACE;
154 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
155 IDirectDrawSurfaceImpl *to)
160 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
166 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
171 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
177 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
182 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
183 IDirectDrawPaletteImpl* pal)
188 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
189 IDirectDrawPaletteImpl* pal,
190 DWORD dwStart, DWORD dwCount,
191 LPPALETTEENTRY palent)
196 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
202 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
204 LPDDGAMMARAMP lpGammaRamp)
208 hr = This->get_dc(This, &hDC);
209 if (FAILED(hr)) return hr;
210 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
211 This->release_dc(This, hDC);
216 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
218 LPDDGAMMARAMP lpGammaRamp)
222 hr = This->get_dc(This, &hDC);
223 if (FAILED(hr)) return hr;
224 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
225 This->release_dc(This, hDC);
230 /*** Interface functions */
233 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
234 LPDIRECTDRAWSURFACE7 pAttach)
236 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
237 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
238 IDirectDrawSurface7, pAttach);
240 TRACE("(%p)->(%p)\n",This,pAttach);
242 /* Does windows check this? */
244 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
246 /* Does windows check this? */
247 if (surf->ddraw_owner != This->ddraw_owner)
248 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
250 if (surf->surface_owner != NULL)
251 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
253 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
254 * But apparently backbuffers and mipmaps can be attached too. */
256 /* Callback to allow the surface to do something special now that it is
257 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
258 if (!surf->attach(surf, This))
259 return DDERR_CANNOTATTACHSURFACE;
261 /* check: Where should it go in the chain? This puts it on the head. */
263 This->attached->prev_attached = surf;
264 surf->next_attached = This->attached;
265 surf->prev_attached = NULL;
266 This->attached = surf;
267 surf->surface_owner = This;
269 IDirectDrawSurface7_AddRef(pAttach);
274 /* MSDN: "not currently implemented." */
276 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
279 TRACE("(%p)->(%p)\n",iface,pRect);
280 return DDERR_UNSUPPORTED; /* unchecked */
283 /* MSDN: "not currently implemented." */
285 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
286 LPDDBLTBATCH pBatch, DWORD dwCount,
289 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
290 return DDERR_UNSUPPORTED; /* unchecked */
294 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
296 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
297 volatile IDirectDrawSurfaceImpl* vThis = This;
299 TRACE("(%p)\n",This);
300 /* A uniquness value of 0 is apparently special.
301 * This needs to be checked. */
304 DWORD old_uniqueness_value = vThis->uniqueness_value;
305 DWORD new_uniqueness_value = old_uniqueness_value+1;
307 if (old_uniqueness_value == 0) break;
308 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
310 if (InterlockedCompareExchange((PVOID*)&vThis->uniqueness_value,
311 (PVOID)old_uniqueness_value,
312 (PVOID)new_uniqueness_value)
313 == (PVOID)old_uniqueness_value)
321 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
323 LPDIRECTDRAWSURFACE7 pAttach)
325 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
326 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
327 IDirectDrawSurface7, pAttach);
329 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
331 if (!surf || (surf->surface_owner != This))
332 return DDERR_SURFACENOTATTACHED; /* unchecked */
336 if (surf->next_attached)
337 surf->next_attached->prev_attached = surf->prev_attached;
338 if (surf->prev_attached)
339 surf->prev_attached->next_attached = surf->next_attached;
340 if (This->attached == surf)
341 This->attached = surf->next_attached;
343 IDirectDrawSurface7_Release(pAttach);
349 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
351 LPDDENUMSURFACESCALLBACK7 cb)
353 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
354 IDirectDrawSurfaceImpl* surf;
356 TRACE("(%p)->(%p,%p)\n",This,context,cb);
358 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
360 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
361 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
362 context) == DDENUMRET_CANCEL)
370 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
371 DWORD dwFlags, LPVOID context,
372 LPDDENUMSURFACESCALLBACK7 cb)
374 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
378 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
379 IDirectDrawSurfaceImpl* back,
382 /* uniqueness_value? */
383 /* This is necessary. But is it safe? */
385 HDC tmp = front->hDC;
386 front->hDC = back->hDC;
391 BOOL tmp = front->dc_in_use;
392 front->dc_in_use = back->dc_in_use;
393 back->dc_in_use = tmp;
400 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
401 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
403 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
404 IDirectDrawSurfaceImpl* target;
407 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
409 /* MSDN: "This method can be called only for a surface that has the
410 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
411 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
412 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
413 return DDERR_NOTFLIPPABLE;
416 if (This->aux_flip(This->aux_ctx, This->aux_data))
419 /* 1. find the flip target */
420 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
421 if (override == NULL)
423 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
424 LPDIRECTDRAWSURFACE7 tgt;
426 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
427 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
429 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
431 IDirectDrawSurface7_Release(tgt);
435 BOOL on_chain = FALSE;
436 IDirectDrawSurfaceImpl* surf;
438 /* MSDN: "The method fails if the specified [override] surface is not
439 * a member of the flipping chain." */
441 /* Verify that override is on this flip chain. We assume that
442 * surf is the head of the flipping chain, because it's the front
444 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
447 /* Either target is (indirectly) attached to This or This is
448 * (indirectly) attached to target. */
449 for (surf = target; surf != NULL; surf = surf->surface_owner)
459 return DDERR_INVALIDPARAMS; /* unchecked */
462 TRACE("flip to backbuffer: %p\n",target);
463 if (This->flip_data(This, target, dwFlags))
464 This->flip_update(This, dwFlags);
469 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
473 for (data = This->private_data; data != NULL; data = data->next)
475 if (IsEqualGUID(&data->tag, tag)) break;
482 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
484 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
487 data = find_private_data(This, tag);
488 if (data == NULL) return DDERR_NOTFOUND;
491 data->prev->next = data->next;
493 data->next->prev = data->prev;
495 if (data->flags & DDSPD_IUNKNOWNPTR)
497 if (data->ptr.object != NULL)
498 IUnknown_Release(data->ptr.object);
501 HeapFree(GetProcessHeap(), 0, data->ptr.data);
503 HeapFree(GetProcessHeap(), 0, data);
509 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
511 LPDIRECTDRAWSURFACE7* ppSurface)
513 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
514 IDirectDrawSurfaceImpl* surf;
515 IDirectDrawSurfaceImpl* found = NULL;
517 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
518 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
520 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
522 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
523 surf->surface_desc.ddsCaps.dwCaps,
524 surf->surface_desc.ddsCaps.dwCaps2,
525 surf->surface_desc.ddsCaps.dwCaps3,
526 surf->surface_desc.ddsCaps.dwCaps4);
527 if (((surf->surface_desc.ddsCaps.dwCaps & pCaps->dwCaps) == pCaps->dwCaps)
528 && ((surf->surface_desc.ddsCaps.dwCaps2 & pCaps->dwCaps2) == pCaps->dwCaps2))
530 /* MSDN: "This method fails if more than one surface is attached
531 * that matches the capabilities requested." */
534 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
535 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
536 to be correct, given what 3DMark expects from MipMapped surfaces.
537 We shall just continue instead. */
545 return DDERR_NOTFOUND;
547 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
549 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
550 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
555 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
557 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
562 case DDGBS_ISBLTDONE:
566 return DDERR_INVALIDPARAMS;
571 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
573 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
575 TRACE("(%p)->(%p)\n",This,pCaps);
576 *pCaps = This->surface_desc.ddsCaps;
581 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
582 LPDIRECTDRAWCLIPPER* ppClipper)
584 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
586 TRACE("(%p)->(%p)\n",This,ppClipper);
587 if (This->clipper == NULL)
588 return DDERR_NOCLIPPERATTACHED;
590 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
591 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
592 IDirectDrawClipper));
597 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
600 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
601 * isn't there? That's like saying that an int isn't there. (Which MS
602 * has done in other docs.) */
604 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
606 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
610 *pCKey = This->surface_desc.ddckCKDestBlt;
613 case DDCKEY_DESTOVERLAY:
614 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
618 *pCKey = This->surface_desc.ddckCKSrcBlt;
621 case DDCKEY_SRCOVERLAY:
622 *pCKey = This->surface_desc.ddckCKSrcOverlay;
626 return DDERR_INVALIDPARAMS;
632 /* XXX We need to do something with the DC if the surface gets lost. */
634 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
638 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
640 TRACE("(%p)->(%p)\n",This,phDC);
648 return DDERR_DCALREADYCREATED;
652 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
653 * thread has it locked, but GetDC does not. */
654 ddsd.dwSize = sizeof(ddsd);
655 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
662 hr = This->get_dc(This, &This->hDC);
665 TRACE("returning %08x\n",This->hDC);
668 This->dc_in_use = TRUE;
670 else WARN("No DC! Prepare for trouble\n");
677 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
679 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
681 TRACE("(%p)->(%p)\n",This,pDD);
682 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
683 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
688 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
690 /* XXX: DDERR_INVALIDSURFACETYPE */
692 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
696 case DDGFS_ISFLIPDONE:
700 return DDERR_INVALIDPARAMS;
705 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
707 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
709 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
712 *pdwMaxLOD = This->max_lod;
717 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
718 LPLONG pX, LPLONG pY)
720 return DDERR_NOTAOVERLAYSURFACE;
724 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
725 LPDIRECTDRAWPALETTE* ppPalette)
727 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
729 TRACE("(%p)->(%p)\n",This,ppPalette);
730 if (This->palette == NULL)
731 return DDERR_NOPALETTEATTACHED;
733 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
734 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
735 IDirectDrawPalette));
740 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
741 LPDDPIXELFORMAT pDDPixelFormat)
743 /* What is DDERR_INVALIDSURFACETYPE for here? */
744 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
746 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
747 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
752 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
755 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
757 TRACE("(%p)->(%p)\n",This,pdwPriority);
760 *pdwPriority = This->priority;
765 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
766 REFGUID tag, LPVOID pBuffer,
767 LPDWORD pcbBufferSize)
769 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
772 data = find_private_data(This, tag);
773 if (data == NULL) return DDERR_NOTFOUND;
775 /* This may not be right. */
776 if ((data->flags & DDSPD_VOLATILE)
777 && data->uniqueness_value != This->uniqueness_value)
778 return DDERR_EXPIRED;
780 if (*pcbBufferSize < data->size)
782 *pcbBufferSize = data->size;
783 return DDERR_MOREDATA;
786 if (data->flags & DDSPD_IUNKNOWNPTR)
788 *(LPUNKNOWN *)pBuffer = data->ptr.object;
789 IUnknown_AddRef(data->ptr.object);
793 memcpy(pBuffer, data->ptr.data, data->size);
800 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
801 LPDDSURFACEDESC2 pDDSD)
803 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
805 TRACE("(%p)->(%p)\n",This,pDDSD);
806 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
807 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
808 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
809 return DDERR_GENERIC;
812 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
817 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
820 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
822 TRACE("(%p)->(%p)\n",This,pValue);
823 *pValue = This->uniqueness_value;
828 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
829 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
831 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
832 return DDERR_ALREADYINITIALIZED;
836 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
838 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
840 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
841 return This->lost ? DDERR_SURFACELOST : DD_OK;
845 /* XXX This doesn't actually do any locking or keep track of the locked
846 * rectangles. The behaviour is poorly documented. */
848 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
849 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
851 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
853 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
855 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
856 WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
857 This,prect,pDDSD,flags,(DWORD)h);
859 /* First, copy the Surface description */
860 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
862 TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
863 pDDSD->dwHeight,pDDSD->dwWidth,pDDSD->u1.lPitch);
865 /* If asked only for a part, change the surface pointer.
866 * (Not documented.) */
868 TRACE(" lprect: %dx%d-%dx%d\n",
869 prect->top,prect->left,prect->bottom,prect->right
871 if ((prect->top < 0) ||
873 (prect->bottom < 0) ||
874 (prect->right < 0)) {
875 ERR(" Negative values in LPRECT !!!\n");
876 return DDERR_INVALIDPARAMS;
879 This->lock_update(This, prect);
881 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
882 + prect->top * This->surface_desc.u1.lPitch
883 + prect->left * GET_BPP(This->surface_desc);
890 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
892 /* Some surface types should return DDERR_CANTPAGELOCK. */
897 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
899 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
900 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
905 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
908 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
910 TRACE("(%p)->(%08x)\n",This,hDC);
912 if (!This->dc_in_use || This->hDC != hDC)
913 return DDERR_INVALIDPARAMS;
915 This->release_dc(This, hDC);
917 hr = IDirectDrawSurface7_Unlock(iface, NULL);
918 if (FAILED(hr)) return hr;
920 This->dc_in_use = FALSE;
929 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
930 LPDIRECTDRAWCLIPPER pDDClipper)
932 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
934 TRACE("(%p)->(%p)\n",This,pDDClipper);
935 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
938 if (This->clipper != NULL)
939 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
940 IDirectDrawClipper));
942 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
944 if (pDDClipper != NULL)
945 IDirectDrawClipper_AddRef(pDDClipper);
951 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
952 DWORD dwFlags, LPDDCOLORKEY pCKey)
954 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
956 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
959 FIXME("supposedly removing color key %lu\n",
960 dwFlags & ~DDCKEY_COLORSPACE);
964 switch (dwFlags & ~DDCKEY_COLORSPACE)
967 This->surface_desc.ddckCKDestBlt = *pCKey;
970 case DDCKEY_DESTOVERLAY:
971 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
974 case DDCKEY_SRCOVERLAY:
975 This->surface_desc.ddckCKSrcOverlay = *pCKey;
979 This->surface_desc.ddckCKSrcBlt = *pCKey;
983 return DDERR_INVALIDPARAMS;
990 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
992 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
994 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
997 This->max_lod = dwMaxLOD;
1002 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1005 return DDERR_NOTAOVERLAYSURFACE;
1009 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1010 LPDIRECTDRAWPALETTE pPalette)
1012 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1014 TRACE("(%p)->(%p)\n",This,pPalette);
1015 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1018 if (This->palette != NULL) {
1019 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1020 This->palette->flags &= ~DDPCAPS_PRIMARYSURFACE;
1021 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
1022 IDirectDrawPalette));
1025 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1027 if (pPalette != NULL) {
1028 IDirectDrawPalette_AddRef(pPalette);
1029 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1030 This->palette->flags |= DDPCAPS_PRIMARYSURFACE;
1033 This->set_palette(This, This->palette);
1039 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1042 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1044 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1045 CHECK_TEXTURE(This);
1047 This->priority = dwPriority;
1051 /* Be careful when locking this: it is risky to call the object's AddRef
1052 * or Release holding a lock. */
1054 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1055 REFGUID tag, LPVOID pData,
1056 DWORD cbSize, DWORD dwFlags)
1059 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1061 data = find_private_data(This, tag);
1064 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1065 if (data == NULL) return DDERR_OUTOFMEMORY;
1068 data->flags = dwFlags;
1069 data->uniqueness_value = This->uniqueness_value;
1071 if (dwFlags & DDSPD_IUNKNOWNPTR)
1073 data->ptr.object = (LPUNKNOWN)pData;
1074 data->size = sizeof(LPUNKNOWN);
1075 IUnknown_AddRef(data->ptr.object);
1079 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1080 if (data->ptr.data == NULL)
1082 HeapFree(GetProcessHeap(), 0, data);
1083 return DDERR_OUTOFMEMORY;
1088 data->next = This->private_data;
1090 if (This->private_data)
1091 This->private_data->prev = data;
1092 This->private_data = data;
1098 /* I don't actually know how windows handles this case. The only
1099 * reason I don't just call FreePrivateData is because I want to
1100 * guarantee SetPrivateData working when using LPUNKNOWN or data
1101 * that is no larger than the old data. */
1107 /* SetSurfaceDesc */
1110 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1112 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1114 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1116 This->unlock_update(This, pRect);
1117 if (This->aux_unlock)
1118 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1124 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1126 LPDIRECTDRAWSURFACE7 pDstSurface,
1127 LPRECT pDstRect, DWORD dwFlags,
1130 return DDERR_UNSUPPORTED;
1133 /* MSDN: "not currently implemented." */
1135 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1138 return DDERR_UNSUPPORTED;
1142 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1144 LPDIRECTDRAWSURFACE7 pDDSRef)
1146 return DDERR_NOTAOVERLAYSURFACE;