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,
172 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
178 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
183 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
184 IDirectDrawPaletteImpl* pal)
189 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
190 IDirectDrawPaletteImpl* pal,
191 DWORD dwStart, DWORD dwCount,
192 LPPALETTEENTRY palent)
197 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
203 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
205 LPDDGAMMARAMP lpGammaRamp)
209 hr = This->get_dc(This, &hDC);
210 if (FAILED(hr)) return hr;
211 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
212 This->release_dc(This, hDC);
217 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
219 LPDDGAMMARAMP lpGammaRamp)
223 hr = This->get_dc(This, &hDC);
224 if (FAILED(hr)) return hr;
225 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
226 This->release_dc(This, hDC);
231 /*** Interface functions */
234 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
235 LPDIRECTDRAWSURFACE7 pAttach)
237 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
238 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
239 IDirectDrawSurface7, pAttach);
241 TRACE("(%p)->(%p)\n",This,pAttach);
243 /* Does windows check this? */
245 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
247 /* Does windows check this? */
248 if (surf->ddraw_owner != This->ddraw_owner)
249 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
251 if (surf->surface_owner != NULL)
252 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
254 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
255 * But apparently backbuffers and mipmaps can be attached too. */
257 /* Set MIPMAPSUBLEVEL if this seems to be one */
258 if (This->surface_desc.ddsCaps.dwCaps &
259 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
260 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
261 /* FIXME: we should probably also add to dwMipMapCount of this
262 * and all parent surfaces (update create_texture if you do) */
265 /* Callback to allow the surface to do something special now that it is
266 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
267 if (!surf->attach(surf, This))
268 return DDERR_CANNOTATTACHSURFACE;
270 /* check: Where should it go in the chain? This puts it on the head. */
272 This->attached->prev_attached = surf;
273 surf->next_attached = This->attached;
274 surf->prev_attached = NULL;
275 This->attached = surf;
276 surf->surface_owner = This;
278 IDirectDrawSurface7_AddRef(pAttach);
283 /* MSDN: "not currently implemented." */
285 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
288 TRACE("(%p)->(%p)\n",iface,pRect);
289 return DDERR_UNSUPPORTED; /* unchecked */
292 /* MSDN: "not currently implemented." */
294 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
295 LPDDBLTBATCH pBatch, DWORD dwCount,
298 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
299 return DDERR_UNSUPPORTED; /* unchecked */
303 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
305 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
306 volatile IDirectDrawSurfaceImpl* vThis = This;
308 TRACE("(%p)\n",This);
309 /* A uniquness value of 0 is apparently special.
310 * This needs to be checked. */
313 DWORD old_uniqueness_value = vThis->uniqueness_value;
314 DWORD new_uniqueness_value = old_uniqueness_value+1;
316 if (old_uniqueness_value == 0) break;
317 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
319 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
320 old_uniqueness_value,
321 new_uniqueness_value)
322 == old_uniqueness_value)
330 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
332 LPDIRECTDRAWSURFACE7 pAttach)
334 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
335 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
336 IDirectDrawSurface7, pAttach);
338 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
340 if (!surf || (surf->surface_owner != This))
341 return DDERR_SURFACENOTATTACHED; /* unchecked */
345 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
346 if (This->surface_desc.ddsCaps.dwCaps &
347 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
348 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
349 /* FIXME: we should probably also subtract from dwMipMapCount of this
350 * and all parent surfaces */
353 if (surf->next_attached)
354 surf->next_attached->prev_attached = surf->prev_attached;
355 if (surf->prev_attached)
356 surf->prev_attached->next_attached = surf->next_attached;
357 if (This->attached == surf)
358 This->attached = surf->next_attached;
360 IDirectDrawSurface7_Release(pAttach);
366 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
368 LPDDENUMSURFACESCALLBACK7 cb)
370 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
371 IDirectDrawSurfaceImpl* surf;
373 TRACE("(%p)->(%p,%p)\n",This,context,cb);
375 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
377 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
378 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
379 context) == DDENUMRET_CANCEL)
387 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
388 DWORD dwFlags, LPVOID context,
389 LPDDENUMSURFACESCALLBACK7 cb)
391 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
395 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
396 IDirectDrawSurfaceImpl* back,
399 /* uniqueness_value? */
400 /* This is necessary. But is it safe? */
402 HDC tmp = front->hDC;
403 front->hDC = back->hDC;
408 BOOL tmp = front->dc_in_use;
409 front->dc_in_use = back->dc_in_use;
410 back->dc_in_use = tmp;
414 FLATPTR tmp = front->global.fpVidMem;
415 front->global.fpVidMem = back->global.fpVidMem;
416 back->global.fpVidMem = tmp;
420 ULONG_PTR tmp = front->global_more.hKernelSurface;
421 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
422 back->global_more.hKernelSurface = tmp;
429 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
430 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
432 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
433 IDirectDrawSurfaceImpl* target;
436 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
438 /* MSDN: "This method can be called only for a surface that has the
439 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
440 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
441 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
442 return DDERR_NOTFLIPPABLE;
445 if (This->aux_flip(This->aux_ctx, This->aux_data))
448 /* 1. find the flip target */
449 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
450 if (override == NULL)
452 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
453 LPDIRECTDRAWSURFACE7 tgt;
455 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
456 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
458 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
460 IDirectDrawSurface7_Release(tgt);
464 BOOL on_chain = FALSE;
465 IDirectDrawSurfaceImpl* surf;
467 /* MSDN: "The method fails if the specified [override] surface is not
468 * a member of the flipping chain." */
470 /* Verify that override is on this flip chain. We assume that
471 * surf is the head of the flipping chain, because it's the front
473 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
476 /* Either target is (indirectly) attached to This or This is
477 * (indirectly) attached to target. */
478 for (surf = target; surf != NULL; surf = surf->surface_owner)
488 return DDERR_INVALIDPARAMS; /* unchecked */
491 TRACE("flip to backbuffer: %p\n",target);
492 if (This->flip_data(This, target, dwFlags))
493 This->flip_update(This, dwFlags);
498 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
502 for (data = This->private_data; data != NULL; data = data->next)
504 if (IsEqualGUID(&data->tag, tag)) break;
511 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
513 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
516 data = find_private_data(This, tag);
517 if (data == NULL) return DDERR_NOTFOUND;
520 data->prev->next = data->next;
522 data->next->prev = data->prev;
524 if (data->flags & DDSPD_IUNKNOWNPTR)
526 if (data->ptr.object != NULL)
527 IUnknown_Release(data->ptr.object);
530 HeapFree(GetProcessHeap(), 0, data->ptr.data);
532 HeapFree(GetProcessHeap(), 0, data);
538 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
540 LPDIRECTDRAWSURFACE7* ppSurface)
542 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
543 IDirectDrawSurfaceImpl* surf;
544 IDirectDrawSurfaceImpl* found = NULL;
546 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
547 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
549 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
551 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
552 surf->surface_desc.ddsCaps.dwCaps,
553 surf->surface_desc.ddsCaps.dwCaps2,
554 surf->surface_desc.ddsCaps.dwCaps3,
555 surf->surface_desc.ddsCaps.dwCaps4);
556 if (((surf->surface_desc.ddsCaps.dwCaps & pCaps->dwCaps) == pCaps->dwCaps)
557 && ((surf->surface_desc.ddsCaps.dwCaps2 & pCaps->dwCaps2) == pCaps->dwCaps2))
559 /* MSDN: "This method fails if more than one surface is attached
560 * that matches the capabilities requested." */
563 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
564 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
565 to be correct, given what 3DMark expects from MipMapped surfaces.
566 We shall just continue instead. */
574 return DDERR_NOTFOUND;
576 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
578 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
579 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
584 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
586 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
591 case DDGBS_ISBLTDONE:
595 return DDERR_INVALIDPARAMS;
600 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
602 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
604 TRACE("(%p)->(%p)\n",This,pCaps);
605 *pCaps = This->surface_desc.ddsCaps;
610 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
611 LPDIRECTDRAWCLIPPER* ppClipper)
613 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
615 TRACE("(%p)->(%p)\n",This,ppClipper);
616 if (This->clipper == NULL)
617 return DDERR_NOCLIPPERATTACHED;
619 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
620 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
621 IDirectDrawClipper));
626 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
629 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
630 * isn't there? That's like saying that an int isn't there. (Which MS
631 * has done in other docs.) */
633 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
635 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
639 *pCKey = This->surface_desc.ddckCKDestBlt;
642 case DDCKEY_DESTOVERLAY:
643 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
647 *pCKey = This->surface_desc.ddckCKSrcBlt;
650 case DDCKEY_SRCOVERLAY:
651 *pCKey = This->surface_desc.ddckCKSrcOverlay;
655 return DDERR_INVALIDPARAMS;
661 /* XXX We need to do something with the DC if the surface gets lost. */
663 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
667 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
669 TRACE("(%p)->(%p)\n",This,phDC);
677 return DDERR_DCALREADYCREATED;
681 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
682 * thread has it locked, but GetDC does not. */
683 ddsd.dwSize = sizeof(ddsd);
684 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, DDLOCK_READONLY, 0);
691 hr = This->get_dc(This, &This->hDC);
694 TRACE("returning %08x\n",This->hDC);
697 This->dc_in_use = TRUE;
699 else WARN("No DC! Prepare for trouble\n");
706 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
708 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
710 TRACE("(%p)->(%p)\n",This,pDD);
711 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
712 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
717 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
719 /* XXX: DDERR_INVALIDSURFACETYPE */
721 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
725 case DDGFS_ISFLIPDONE:
729 return DDERR_INVALIDPARAMS;
734 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
736 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
738 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
741 *pdwMaxLOD = This->max_lod;
746 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
747 LPLONG pX, LPLONG pY)
749 return DDERR_NOTAOVERLAYSURFACE;
753 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
754 LPDIRECTDRAWPALETTE* ppPalette)
756 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
758 TRACE("(%p)->(%p)\n",This,ppPalette);
759 if (This->palette == NULL)
760 return DDERR_NOPALETTEATTACHED;
762 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
763 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
764 IDirectDrawPalette));
769 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
770 LPDDPIXELFORMAT pDDPixelFormat)
772 /* What is DDERR_INVALIDSURFACETYPE for here? */
773 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
775 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
776 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
781 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
784 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
786 TRACE("(%p)->(%p)\n",This,pdwPriority);
789 *pdwPriority = This->priority;
794 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
795 REFGUID tag, LPVOID pBuffer,
796 LPDWORD pcbBufferSize)
798 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
801 data = find_private_data(This, tag);
802 if (data == NULL) return DDERR_NOTFOUND;
804 /* This may not be right. */
805 if ((data->flags & DDSPD_VOLATILE)
806 && data->uniqueness_value != This->uniqueness_value)
807 return DDERR_EXPIRED;
809 if (*pcbBufferSize < data->size)
811 *pcbBufferSize = data->size;
812 return DDERR_MOREDATA;
815 if (data->flags & DDSPD_IUNKNOWNPTR)
817 *(LPUNKNOWN *)pBuffer = data->ptr.object;
818 IUnknown_AddRef(data->ptr.object);
822 memcpy(pBuffer, data->ptr.data, data->size);
829 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
830 LPDDSURFACEDESC2 pDDSD)
832 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
834 TRACE("(%p)->(%p)\n",This,pDDSD);
835 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
836 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
837 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
838 return DDERR_GENERIC;
841 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
846 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
849 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
851 TRACE("(%p)->(%p)\n",This,pValue);
852 *pValue = This->uniqueness_value;
857 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
858 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
860 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
861 return DDERR_ALREADYINITIALIZED;
865 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
867 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
869 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
870 return This->lost ? DDERR_SURFACELOST : DD_OK;
874 /* XXX This doesn't actually do any locking or keep track of the locked
875 * rectangles. The behaviour is poorly documented. */
877 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
878 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
880 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
882 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
884 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
885 WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
886 This,prect,pDDSD,flags,(DWORD)h);
888 /* First, copy the Surface description */
889 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
891 TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
892 pDDSD->dwHeight,pDDSD->dwWidth,pDDSD->u1.lPitch);
894 /* If asked only for a part, change the surface pointer.
895 * (Not documented.) */
897 TRACE(" lprect: %dx%d-%dx%d\n",
898 prect->top,prect->left,prect->bottom,prect->right
900 if ((prect->top < 0) ||
902 (prect->bottom < 0) ||
903 (prect->right < 0)) {
904 ERR(" Negative values in LPRECT !!!\n");
905 return DDERR_INVALIDPARAMS;
908 This->lock_update(This, prect, flags);
910 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
911 + prect->top * This->surface_desc.u1.lPitch
912 + prect->left * GET_BPP(This->surface_desc);
914 This->lock_update(This, NULL, flags);
921 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
923 /* Some surface types should return DDERR_CANTPAGELOCK. */
928 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
930 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
931 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
936 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
939 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
941 TRACE("(%p)->(%08x)\n",This,hDC);
943 if (!This->dc_in_use || This->hDC != hDC)
944 return DDERR_INVALIDPARAMS;
946 This->release_dc(This, hDC);
948 hr = IDirectDrawSurface7_Unlock(iface, NULL);
949 if (FAILED(hr)) return hr;
951 This->dc_in_use = FALSE;
960 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
961 LPDIRECTDRAWCLIPPER pDDClipper)
963 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
965 TRACE("(%p)->(%p)\n",This,pDDClipper);
966 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
969 if (This->clipper != NULL)
970 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
971 IDirectDrawClipper));
973 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
975 if (pDDClipper != NULL)
976 IDirectDrawClipper_AddRef(pDDClipper);
982 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
983 DWORD dwFlags, LPDDCOLORKEY pCKey)
985 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
987 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
990 FIXME("supposedly removing color key %lu\n",
991 dwFlags & ~DDCKEY_COLORSPACE);
995 switch (dwFlags & ~DDCKEY_COLORSPACE)
998 This->surface_desc.ddckCKDestBlt = *pCKey;
1001 case DDCKEY_DESTOVERLAY:
1002 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1005 case DDCKEY_SRCOVERLAY:
1006 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1010 This->surface_desc.ddckCKSrcBlt = *pCKey;
1014 return DDERR_INVALIDPARAMS;
1021 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1023 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1025 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1026 CHECK_TEXTURE(This);
1028 This->max_lod = dwMaxLOD;
1033 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1036 return DDERR_NOTAOVERLAYSURFACE;
1040 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1041 LPDIRECTDRAWPALETTE pPalette)
1043 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1045 TRACE("(%p)->(%p)\n",This,pPalette);
1046 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1049 if (This->palette != NULL) {
1050 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1051 This->palette->flags &= ~DDPCAPS_PRIMARYSURFACE;
1052 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
1053 IDirectDrawPalette));
1056 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1058 if (pPalette != NULL) {
1059 IDirectDrawPalette_AddRef(pPalette);
1060 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1061 This->palette->flags |= DDPCAPS_PRIMARYSURFACE;
1064 This->set_palette(This, This->palette);
1070 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1073 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1075 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1076 CHECK_TEXTURE(This);
1078 This->priority = dwPriority;
1082 /* Be careful when locking this: it is risky to call the object's AddRef
1083 * or Release holding a lock. */
1085 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1086 REFGUID tag, LPVOID pData,
1087 DWORD cbSize, DWORD dwFlags)
1090 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1092 data = find_private_data(This, tag);
1095 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1096 if (data == NULL) return DDERR_OUTOFMEMORY;
1099 data->flags = dwFlags;
1100 data->uniqueness_value = This->uniqueness_value;
1102 if (dwFlags & DDSPD_IUNKNOWNPTR)
1104 data->ptr.object = (LPUNKNOWN)pData;
1105 data->size = sizeof(LPUNKNOWN);
1106 IUnknown_AddRef(data->ptr.object);
1110 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1111 if (data->ptr.data == NULL)
1113 HeapFree(GetProcessHeap(), 0, data);
1114 return DDERR_OUTOFMEMORY;
1119 data->next = This->private_data;
1121 if (This->private_data)
1122 This->private_data->prev = data;
1123 This->private_data = data;
1129 /* I don't actually know how windows handles this case. The only
1130 * reason I don't just call FreePrivateData is because I want to
1131 * guarantee SetPrivateData working when using LPUNKNOWN or data
1132 * that is no larger than the old data. */
1138 /* SetSurfaceDesc */
1141 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1143 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1145 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1147 This->unlock_update(This, pRect);
1148 if (This->aux_unlock)
1149 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1155 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1157 LPDIRECTDRAWSURFACE7 pDstSurface,
1158 LPRECT pDstRect, DWORD dwFlags,
1161 return DDERR_UNSUPPORTED;
1164 /* MSDN: "not currently implemented." */
1166 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1169 return DDERR_UNSUPPORTED;
1173 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1175 LPDIRECTDRAWSURFACE7 pDDSRef)
1177 return DDERR_NOTAOVERLAYSURFACE;