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
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
29 #include "mesa_private.h"
30 #include "wine/debug.h"
31 #include "ddraw_private.h"
32 #include "dsurface/main.h"
33 #include "ddraw/main.h"
34 #include "dsurface/thunks.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
37 WINE_DECLARE_DEBUG_CHANNEL(ddraw_flip);
39 /** Creation/Destruction functions */
42 Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
44 const DDSURFACEDESC2 *pDDSD)
46 TRACE("(%p)->(%p,%p)\n", This, pDD, pDDSD);
48 if (pDDSD != &This->surface_desc) {
49 This->surface_desc.dwSize = sizeof(This->surface_desc);
50 DD_STRUCT_COPY_BYSIZE(&(This->surface_desc),pDDSD);
52 This->uniqueness_value = 1; /* unchecked */
55 This->local.lpSurfMore = &This->more;
56 This->local.lpGbl = &This->global;
57 This->local.dwProcessId = GetCurrentProcessId();
58 This->local.dwFlags = 0; /* FIXME */
59 This->local.ddsCaps.dwCaps = This->surface_desc.ddsCaps.dwCaps;
60 /* FIXME: more local stuff */
61 This->more.lpDD_lcl = &pDD->local;
62 This->more.ddsCapsEx.dwCaps2 = This->surface_desc.ddsCaps.dwCaps2;
63 This->more.ddsCapsEx.dwCaps3 = This->surface_desc.ddsCaps.dwCaps3;
64 This->more.ddsCapsEx.dwCaps4 = This->surface_desc.ddsCaps.dwCaps4;
65 /* FIXME: more more stuff */
66 This->gmore = &This->global_more;
67 This->global.u3.lpDD = pDD->local.lpGbl;
68 /* FIXME: more global stuff */
70 This->final_release = Main_DirectDrawSurface_final_release;
71 This->late_allocate = Main_DirectDrawSurface_late_allocate;
72 This->attach = Main_DirectDrawSurface_attach;
73 This->detach = Main_DirectDrawSurface_detach;
74 This->lock_update = Main_DirectDrawSurface_lock_update;
75 This->unlock_update = Main_DirectDrawSurface_unlock_update;
76 This->lose_surface = Main_DirectDrawSurface_lose_surface;
77 This->set_palette = Main_DirectDrawSurface_set_palette;
78 This->update_palette = Main_DirectDrawSurface_update_palette;
79 This->get_display_window = Main_DirectDrawSurface_get_display_window;
80 This->get_gamma_ramp = Main_DirectDrawSurface_get_gamma_ramp;
81 This->set_gamma_ramp = Main_DirectDrawSurface_set_gamma_ramp;
83 ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
84 DDRAW_IDDS3_Thunk_VTable);
85 ICOM_INIT_INTERFACE(This, IDirectDrawGammaControl,
88 /* There is no generic implementation of IDDS7 or texture */
90 Main_DirectDraw_AddSurface(pDD, This);
94 void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
96 Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
99 HRESULT Main_DirectDrawSurface_late_allocate(IDirectDrawSurfaceImpl* This)
104 static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
107 IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette, IDirectDrawPalette));
108 This->palette = NULL;
110 This->final_release(This);
111 if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
112 if (This->tex_private) HeapFree(GetProcessHeap(), 0, This->tex_private);
113 HeapFree(GetProcessHeap(), 0, This);
116 void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
118 WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
119 Main_DirectDrawSurface_Destroy(This);
122 ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
124 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
126 TRACE("(%p)->(): decreasing from %ld\n", This, This->ref);
128 if (--This->ref == 0)
130 if (This->aux_release)
131 This->aux_release(This->aux_ctx, This->aux_data);
132 Main_DirectDrawSurface_Destroy(This);
134 TRACE("released surface %p\n", This);
142 ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
144 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
146 TRACE("(%p)->(): increasing from %ld\n", This, This->ref);
152 Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
155 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
156 TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
160 if (IsEqualGUID(&IID_IUnknown, riid)
161 || IsEqualGUID(&IID_IDirectDrawSurface7, riid)
162 || IsEqualGUID(&IID_IDirectDrawSurface4, riid))
165 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
168 else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
169 || IsEqualGUID(&IID_IDirectDrawSurface2, riid)
170 || IsEqualGUID(&IID_IDirectDrawSurface3, riid))
173 *ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
176 else if (IsEqualGUID(&IID_IDirectDrawGammaControl, riid))
179 *ppObj = ICOM_INTERFACE(This, IDirectDrawGammaControl);
183 /* interfaces following here require OpenGL */
184 if( !opengl_initialized )
185 return E_NOINTERFACE;
187 if ( IsEqualGUID( &IID_D3DDEVICE_OpenGL, riid ) ||
188 IsEqualGUID( &IID_IDirect3DHALDevice, riid) )
190 IDirect3DDeviceImpl *d3ddevimpl;
193 ret_value = d3ddevice_create(&d3ddevimpl, This->ddraw_owner, This, TRUE);
194 if (FAILED(ret_value)) return ret_value;
196 *ppObj = ICOM_INTERFACE(d3ddevimpl, IDirect3DDevice);
197 TRACE(" returning Direct3DDevice interface at %p.\n", *ppObj);
199 This->ref++; /* No idea if this is correct.. Need to check using real Windows */
202 else if (IsEqualGUID( &IID_IDirect3DTexture, riid ) ||
203 IsEqualGUID( &IID_IDirect3DTexture2, riid ))
205 HRESULT ret_value = S_OK;
207 /* Note: this is not exactly how Windows does it... But this seems not to hurt the only
208 application I know creating a texture without this flag set and it will prevent
209 bugs in other parts of Wine.
211 This->surface_desc.ddsCaps.dwCaps |= DDSCAPS_TEXTURE;
213 /* In case the texture surface was created before the D3D creation */
214 if (This->tex_private == NULL) {
215 if (This->ddraw_owner->d3d_private == NULL) {
216 ERR("Texture created with no D3D object yet.. Not supported !\n");
217 return E_NOINTERFACE;
220 ret_value = This->ddraw_owner->d3d_create_texture(This->ddraw_owner, This, FALSE, This->mip_main);
221 if (FAILED(ret_value)) return ret_value;
223 if (IsEqualGUID( &IID_IDirect3DTexture, riid )) {
224 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture);
225 TRACE(" returning Direct3DTexture interface at %p.\n", *ppObj);
227 *ppObj = ICOM_INTERFACE(This, IDirect3DTexture2);
228 TRACE(" returning Direct3DTexture2 interface at %p.\n", *ppObj);
235 return E_NOINTERFACE;
241 Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
242 IDirectDrawSurfaceImpl *to)
247 BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
253 Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect,
259 Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
265 Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
270 Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
271 IDirectDrawPaletteImpl* pal)
276 Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
277 IDirectDrawPaletteImpl* pal,
278 DWORD dwStart, DWORD dwCount,
279 LPPALETTEENTRY palent)
284 Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
290 Main_DirectDrawSurface_get_gamma_ramp(IDirectDrawSurfaceImpl* This,
292 LPDDGAMMARAMP lpGammaRamp)
296 hr = This->get_dc(This, &hDC);
297 if (FAILED(hr)) return hr;
298 hr = GetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
299 This->release_dc(This, hDC);
304 Main_DirectDrawSurface_set_gamma_ramp(IDirectDrawSurfaceImpl* This,
306 LPDDGAMMARAMP lpGammaRamp)
310 hr = This->get_dc(This, &hDC);
311 if (FAILED(hr)) return hr;
312 hr = SetDeviceGammaRamp(hDC, lpGammaRamp) ? DD_OK : DDERR_UNSUPPORTED;
313 This->release_dc(This, hDC);
318 /*** Interface functions */
321 Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
322 LPDIRECTDRAWSURFACE7 pAttach)
324 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
325 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
326 IDirectDrawSurface7, pAttach);
328 TRACE("(%p)->(%p)\n",This,pAttach);
330 /* Does windows check this? */
332 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
334 /* Does windows check this? */
335 if (surf->ddraw_owner != This->ddraw_owner)
336 return DDERR_CANNOTATTACHSURFACE; /* unchecked */
338 if (surf->surface_owner != NULL)
339 return DDERR_SURFACEALREADYATTACHED; /* unchecked */
341 /* TODO MSDN: "You can attach only z-buffer surfaces with this method."
342 * But apparently backbuffers and mipmaps can be attached too. */
344 /* Set MIPMAPSUBLEVEL if this seems to be one */
345 if (This->surface_desc.ddsCaps.dwCaps &
346 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
347 surf->surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
348 /* FIXME: we should probably also add to dwMipMapCount of this
349 * and all parent surfaces (update create_texture if you do) */
352 /* Callback to allow the surface to do something special now that it is
353 * attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
354 if (!surf->attach(surf, This))
355 return DDERR_CANNOTATTACHSURFACE;
357 /* check: Where should it go in the chain? This puts it on the head. */
359 This->attached->prev_attached = surf;
360 surf->next_attached = This->attached;
361 surf->prev_attached = NULL;
362 This->attached = surf;
363 surf->surface_owner = This;
365 IDirectDrawSurface7_AddRef(pAttach);
370 /* MSDN: "not currently implemented." */
372 Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
375 TRACE("(%p)->(%p)\n",iface,pRect);
376 return DDERR_UNSUPPORTED; /* unchecked */
379 /* MSDN: "not currently implemented." */
381 Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
382 LPDDBLTBATCH pBatch, DWORD dwCount,
385 TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
386 return DDERR_UNSUPPORTED; /* unchecked */
390 Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
392 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
393 volatile IDirectDrawSurfaceImpl* vThis = This;
395 TRACE("(%p)\n",This);
396 /* A uniquness value of 0 is apparently special.
397 * This needs to be checked. */
400 DWORD old_uniqueness_value = vThis->uniqueness_value;
401 DWORD new_uniqueness_value = old_uniqueness_value+1;
403 if (old_uniqueness_value == 0) break;
404 if (new_uniqueness_value == 0) new_uniqueness_value = 1;
406 if (InterlockedCompareExchange((LONG*)&vThis->uniqueness_value,
407 old_uniqueness_value,
408 new_uniqueness_value)
409 == old_uniqueness_value)
417 Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
419 LPDIRECTDRAWSURFACE7 pAttach)
421 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
422 IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
423 IDirectDrawSurface7, pAttach);
425 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
427 if (!surf || (surf->surface_owner != This))
428 return DDERR_SURFACENOTATTACHED; /* unchecked */
432 /* Remove MIPMAPSUBLEVEL if this seemed to be one */
433 if (This->surface_desc.ddsCaps.dwCaps &
434 surf->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) {
435 surf->surface_desc.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
436 /* FIXME: we should probably also subtract from dwMipMapCount of this
437 * and all parent surfaces */
440 if (surf->next_attached)
441 surf->next_attached->prev_attached = surf->prev_attached;
442 if (surf->prev_attached)
443 surf->prev_attached->next_attached = surf->next_attached;
444 if (This->attached == surf)
445 This->attached = surf->next_attached;
447 IDirectDrawSurface7_Release(pAttach);
453 Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
455 LPDDENUMSURFACESCALLBACK7 cb)
457 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
458 IDirectDrawSurfaceImpl* surf;
460 TRACE("(%p)->(%p,%p)\n",This,context,cb);
462 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
464 /* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
465 if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
466 context) == DDENUMRET_CANCEL)
474 Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
475 DWORD dwFlags, LPVOID context,
476 LPDDENUMSURFACESCALLBACK7 cb)
478 TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
482 BOOL Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
483 IDirectDrawSurfaceImpl* back,
486 /* uniqueness_value? */
487 /* This is necessary. But is it safe? */
489 HDC tmp = front->hDC;
490 front->hDC = back->hDC;
495 BOOL tmp = front->dc_in_use;
496 front->dc_in_use = back->dc_in_use;
497 back->dc_in_use = tmp;
501 FLATPTR tmp = front->global.fpVidMem;
502 front->global.fpVidMem = back->global.fpVidMem;
503 back->global.fpVidMem = tmp;
507 ULONG_PTR tmp = front->global_more.hKernelSurface;
508 front->global_more.hKernelSurface = back->global_more.hKernelSurface;
509 back->global_more.hKernelSurface = tmp;
516 Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
517 LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
519 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
520 IDirectDrawSurfaceImpl* target;
523 TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
525 /* MSDN: "This method can be called only for a surface that has the
526 * DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
527 if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
528 != (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
529 return DDERR_NOTFLIPPABLE;
532 if (This->aux_flip(This->aux_ctx, This->aux_data))
535 /* 1. find the flip target */
536 /* XXX I don't think this algorithm works for more than 1 backbuffer. */
537 if (override == NULL)
539 static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
540 LPDIRECTDRAWSURFACE7 tgt;
542 hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
543 if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
545 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
547 IDirectDrawSurface7_Release(tgt);
551 BOOL on_chain = FALSE;
552 IDirectDrawSurfaceImpl* surf;
554 /* MSDN: "The method fails if the specified [override] surface is not
555 * a member of the flipping chain." */
557 /* Verify that override is on this flip chain. We assume that
558 * surf is the head of the flipping chain, because it's the front
560 target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
563 /* Either target is (indirectly) attached to This or This is
564 * (indirectly) attached to target. */
565 for (surf = target; surf != NULL; surf = surf->surface_owner)
575 return DDERR_INVALIDPARAMS; /* unchecked */
578 TRACE("flip to backbuffer: %p\n",target);
579 if (TRACE_ON(ddraw_flip)) {
580 static unsigned int flip_count = 0;
581 IDirectDrawPaletteImpl *palette;
585 /* Hack for paletted games... */
586 palette = target->palette;
587 target->palette = This->palette;
589 sprintf(buf, "flip_%08d.ppm", flip_count++);
590 TRACE_(ddraw_flip)("Dumping file %s to disk.\n", buf);
591 f = fopen(buf, "wb");
592 DDRAW_dump_surface_to_disk(target, f, 8);
593 target->palette = palette;
596 if (This->flip_data(This, target, dwFlags))
597 This->flip_update(This, dwFlags);
602 static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
606 for (data = This->private_data; data != NULL; data = data->next)
608 if (IsEqualGUID(&data->tag, tag)) break;
615 Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
617 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
620 data = find_private_data(This, tag);
621 if (data == NULL) return DDERR_NOTFOUND;
624 data->prev->next = data->next;
626 data->next->prev = data->prev;
628 if (data->flags & DDSPD_IUNKNOWNPTR)
630 if (data->ptr.object != NULL)
631 IUnknown_Release(data->ptr.object);
634 HeapFree(GetProcessHeap(), 0, data->ptr.data);
636 HeapFree(GetProcessHeap(), 0, data);
642 Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
644 LPDIRECTDRAWSURFACE7* ppSurface)
646 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
647 IDirectDrawSurfaceImpl* surf;
648 IDirectDrawSurfaceImpl* found = NULL;
651 if (TRACE_ON(ddraw)) {
652 TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
653 pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
654 TRACE(" Caps are : "); DDRAW_dump_DDSCAPS2(pCaps); TRACE("\n");
658 if ((This->ddraw_owner->local.dwLocalFlags & DDRAWILCL_DIRECTDRAW7) == 0) {
659 /* As this is not a DirectDraw7 application, remove the garbage that some games
660 put in the new fields of the DDSCAPS2 structure. */
661 our_caps.dwCaps2 = 0;
662 our_caps.dwCaps3 = 0;
663 our_caps.dwCaps4 = 0;
664 if (TRACE_ON(ddraw)) {
665 TRACE(" Real caps are : "); DDRAW_dump_DDSCAPS2(&our_caps); TRACE("\n");
669 for (surf = This->attached; surf != NULL; surf = surf->next_attached)
671 if (TRACE_ON(ddraw)) {
672 TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
673 surf->surface_desc.ddsCaps.dwCaps,
674 surf->surface_desc.ddsCaps.dwCaps2,
675 surf->surface_desc.ddsCaps.dwCaps3,
676 surf->surface_desc.ddsCaps.dwCaps4);
677 TRACE(" Surface caps are : "); DDRAW_dump_DDSCAPS2(&(surf->surface_desc.ddsCaps)); TRACE("\n");
679 if (((surf->surface_desc.ddsCaps.dwCaps & our_caps.dwCaps) == our_caps.dwCaps) &&
680 ((surf->surface_desc.ddsCaps.dwCaps2 & our_caps.dwCaps2) == our_caps.dwCaps2))
682 /* MSDN: "This method fails if more than one surface is attached
683 * that matches the capabilities requested." */
686 FIXME("More than one attached surface matches requested caps. What should we do here?\n");
687 /* Previous code returned 'DDERR_NOTFOUND'. That appears not
688 to be correct, given what 3DMark expects from MipMapped surfaces.
689 We shall just continue instead. */
697 TRACE("Did not find any valid surface\n");
698 return DDERR_NOTFOUND;
701 *ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
703 if (TRACE_ON(ddraw)) {
704 TRACE("Returning surface %p with description : \n", *ppSurface);
705 DDRAW_dump_surface_desc(&(found->surface_desc));
708 /* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
709 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
714 Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
716 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
721 case DDGBS_ISBLTDONE:
725 return DDERR_INVALIDPARAMS;
730 Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
732 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
734 TRACE("(%p)->(%p)\n",This,pCaps);
735 *pCaps = This->surface_desc.ddsCaps;
740 Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
741 LPDIRECTDRAWCLIPPER* ppClipper)
743 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
745 TRACE("(%p)->(%p)\n",This,ppClipper);
746 if (This->clipper == NULL)
747 return DDERR_NOCLIPPERATTACHED;
749 *ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
750 IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
751 IDirectDrawClipper));
756 Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
759 /* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
760 * isn't there? That's like saying that an int isn't there. (Which MS
761 * has done in other docs.) */
763 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
765 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
766 if (TRACE_ON(ddraw)) {
767 TRACE(" - colorkey flags : ");
768 DDRAW_dump_colorkeyflag(dwFlags);
774 *pCKey = This->surface_desc.ddckCKDestBlt;
777 case DDCKEY_DESTOVERLAY:
778 *pCKey = This->surface_desc.u3.ddckCKDestOverlay;
782 *pCKey = This->surface_desc.ddckCKSrcBlt;
785 case DDCKEY_SRCOVERLAY:
786 *pCKey = This->surface_desc.ddckCKSrcOverlay;
790 return DDERR_INVALIDPARAMS;
796 /* XXX We need to do something with the DC if the surface gets lost. */
798 Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
802 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
804 TRACE("(%p)->(%p)\n",This,phDC);
812 return DDERR_DCALREADYCREATED;
816 * Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
817 * thread has it locked, but GetDC does not. */
818 ddsd.dwSize = sizeof(ddsd);
819 hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
826 hr = This->get_dc(This, &This->hDC);
829 TRACE("returning %p\n",This->hDC);
832 This->dc_in_use = TRUE;
834 else WARN("No DC! Prepare for trouble\n");
841 Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
843 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
845 TRACE("(%p)->(%p)\n",This,pDD);
846 *pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
847 IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
852 Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
854 /* XXX: DDERR_INVALIDSURFACETYPE */
856 TRACE("(%p)->(%08lx)\n",iface,dwFlags);
860 case DDGFS_ISFLIPDONE:
864 return DDERR_INVALIDPARAMS;
869 Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
871 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
873 TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
876 *pdwMaxLOD = This->max_lod;
881 Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
882 LPLONG pX, LPLONG pY)
884 return DDERR_NOTAOVERLAYSURFACE;
888 Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
889 LPDIRECTDRAWPALETTE* ppPalette)
891 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
893 TRACE("(%p)->(%p)\n",This,ppPalette);
894 if (This->palette == NULL)
895 return DDERR_NOPALETTEATTACHED;
897 *ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
898 IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
899 IDirectDrawPalette));
904 Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
905 LPDDPIXELFORMAT pDDPixelFormat)
907 /* What is DDERR_INVALIDSURFACETYPE for here? */
908 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
910 TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
911 DD_STRUCT_COPY_BYSIZE(pDDPixelFormat,&This->surface_desc.u4.ddpfPixelFormat);
916 Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
919 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
921 TRACE("(%p)->(%p)\n",This,pdwPriority);
924 *pdwPriority = This->priority;
929 Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
930 REFGUID tag, LPVOID pBuffer,
931 LPDWORD pcbBufferSize)
933 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
936 data = find_private_data(This, tag);
937 if (data == NULL) return DDERR_NOTFOUND;
939 /* This may not be right. */
940 if ((data->flags & DDSPD_VOLATILE)
941 && data->uniqueness_value != This->uniqueness_value)
942 return DDERR_EXPIRED;
944 if (*pcbBufferSize < data->size)
946 *pcbBufferSize = data->size;
947 return DDERR_MOREDATA;
950 if (data->flags & DDSPD_IUNKNOWNPTR)
952 *(LPUNKNOWN *)pBuffer = data->ptr.object;
953 IUnknown_AddRef(data->ptr.object);
957 memcpy(pBuffer, data->ptr.data, data->size);
964 Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
965 LPDDSURFACEDESC2 pDDSD)
967 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
969 TRACE("(%p)->(%p)\n",This,pDDSD);
970 if ((pDDSD->dwSize < sizeof(DDSURFACEDESC)) ||
971 (pDDSD->dwSize > sizeof(DDSURFACEDESC2))) {
972 ERR("Impossible/Strange struct size %ld.\n",pDDSD->dwSize);
973 return DDERR_GENERIC;
976 DD_STRUCT_COPY_BYSIZE(pDDSD,&This->surface_desc);
977 if (TRACE_ON(ddraw)) {
978 DDRAW_dump_surface_desc(pDDSD);
984 Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
987 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
989 TRACE("(%p)->(%p)\n",This,pValue);
990 *pValue = This->uniqueness_value;
995 Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
996 LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
998 TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
999 return DDERR_ALREADYINITIALIZED;
1003 Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
1005 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1007 TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
1008 return This->lost ? DDERR_SURFACELOST : DD_OK;
1012 /* XXX This doesn't actually do any locking or keep track of the locked
1013 * rectangles. The behaviour is poorly documented. */
1015 Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
1016 LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
1018 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1020 if (TRACE_ON(ddraw)) {
1021 TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
1022 TRACE(" - locking flags : "); DDRAW_dump_lockflag(flags);
1024 if (WARN_ON(ddraw)) {
1025 if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY)) {
1026 WARN(" - unsupported locking flag : "); DDRAW_dump_lockflag(flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY));
1030 /* First, copy the Surface description */
1031 DD_STRUCT_COPY_BYSIZE(pDDSD,&(This->surface_desc));
1033 /* Used to optimize the D3D Device locking */
1034 This->lastlocktype = flags & (DDLOCK_READONLY|DDLOCK_WRITEONLY);
1036 /* If asked only for a part, change the surface pointer.
1037 * (Not documented.) */
1038 if (prect != NULL) {
1039 TRACE(" lprect: %ldx%ld-%ldx%ld\n",
1040 prect->left,prect->top,prect->right,prect->bottom);
1041 /* First do some sanity checkings on the rectangle we receive.
1042 DungeonSiege seems to gives us once a very bad rectangle for example */
1043 if ((prect->top < 0) ||
1044 (prect->left < 0) ||
1045 (prect->bottom < 0) ||
1046 (prect->right < 0) ||
1047 (prect->left >= prect->right) ||
1048 (prect->top >= prect->bottom) ||
1049 (prect->left >= This->surface_desc.dwWidth) ||
1050 (prect->right > This->surface_desc.dwWidth) ||
1051 (prect->top >= This->surface_desc.dwHeight) ||
1052 (prect->bottom > This->surface_desc.dwHeight)) {
1053 ERR(" Invalid values in LPRECT !!!\n");
1054 return DDERR_INVALIDPARAMS;
1057 This->lock_update(This, prect, flags);
1059 pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
1060 + prect->top * This->surface_desc.u1.lPitch
1061 + prect->left * GET_BPP(This->surface_desc);
1063 This->lock_update(This, NULL, flags);
1066 TRACE("locked surface returning description : \n");
1067 if (TRACE_ON(ddraw)) DDRAW_dump_surface_desc(pDDSD);
1073 Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1075 /* Some surface types should return DDERR_CANTPAGELOCK. */
1080 Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
1082 /* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
1083 * keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
1088 Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
1091 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1093 TRACE("(%p)->(%p)\n",This,hDC);
1095 if (!This->dc_in_use || This->hDC != hDC)
1096 return DDERR_INVALIDPARAMS;
1098 This->release_dc(This, hDC);
1100 hr = IDirectDrawSurface7_Unlock(iface, NULL);
1101 if (FAILED(hr)) return hr;
1103 This->dc_in_use = FALSE;
1112 Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
1113 LPDIRECTDRAWCLIPPER pDDClipper)
1115 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1117 TRACE("(%p)->(%p)\n",This,pDDClipper);
1118 if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
1121 if (This->clipper != NULL)
1122 IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
1123 IDirectDrawClipper));
1125 This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
1127 if (pDDClipper != NULL)
1128 IDirectDrawClipper_AddRef(pDDClipper);
1134 Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
1135 DWORD dwFlags, LPDDCOLORKEY pCKey)
1137 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1139 TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
1141 if (TRACE_ON(ddraw)) {
1142 TRACE(" - colorkey flags : ");
1143 DDRAW_dump_colorkeyflag(dwFlags);
1146 if ((dwFlags & DDCKEY_COLORSPACE) != 0) {
1147 FIXME(" colorkey value not supported (%08lx) !\n", dwFlags);
1148 return DDERR_INVALIDPARAMS;
1151 /* TODO: investigate if this function can take multiple bits set at the same
1152 time (ie setting multiple colorkey values at the same time with only
1156 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1157 case DDCKEY_DESTBLT:
1158 This->surface_desc.ddckCKDestBlt = *pCKey;
1159 This->surface_desc.dwFlags |= DDSD_CKDESTBLT;
1162 case DDCKEY_DESTOVERLAY:
1163 This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
1164 This->surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
1167 case DDCKEY_SRCOVERLAY:
1168 This->surface_desc.ddckCKSrcOverlay = *pCKey;
1169 This->surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
1173 This->surface_desc.ddckCKSrcBlt = *pCKey;
1174 This->surface_desc.dwFlags |= DDSD_CKSRCBLT;
1178 return DDERR_INVALIDPARAMS;
1181 switch (dwFlags & ~DDCKEY_COLORSPACE) {
1182 case DDCKEY_DESTBLT:
1183 This->surface_desc.dwFlags &= ~DDSD_CKDESTBLT;
1186 case DDCKEY_DESTOVERLAY:
1187 This->surface_desc.dwFlags &= ~DDSD_CKDESTOVERLAY;
1190 case DDCKEY_SRCOVERLAY:
1191 This->surface_desc.dwFlags &= ~DDSD_CKSRCOVERLAY;
1195 This->surface_desc.dwFlags &= ~DDSD_CKSRCBLT;
1199 return DDERR_INVALIDPARAMS;
1203 if (This->aux_setcolorkey_cb) This->aux_setcolorkey_cb(This, dwFlags, pCKey);
1209 Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
1211 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1213 TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
1214 CHECK_TEXTURE(This);
1216 This->max_lod = dwMaxLOD;
1221 Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
1224 return DDERR_NOTAOVERLAYSURFACE;
1228 Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
1229 LPDIRECTDRAWPALETTE pPalette)
1231 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1232 IDirectDrawPalette *pal_to_rel = NULL;
1234 TRACE("(%p)->(%p)\n",This,pPalette);
1235 if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
1238 if (This->palette != NULL) {
1239 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1240 This->palette->global.dwFlags &= ~DDPCAPS_PRIMARYSURFACE;
1241 pal_to_rel = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
1244 This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
1246 if (pPalette != NULL) {
1247 IDirectDrawPalette_AddRef(pPalette);
1248 if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
1249 This->palette->global.dwFlags |= DDPCAPS_PRIMARYSURFACE;
1252 This->set_palette(This, This->palette);
1254 /* Do the palette release at the end to prevent doing some 'loop' when removing
1255 * the surface maintaining the last reference on a palette.
1257 if (pal_to_rel != NULL)
1258 IDirectDrawPalette_Release(pal_to_rel);
1264 Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
1267 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1269 TRACE("(%p)->(%08lx)\n",This,dwPriority);
1270 CHECK_TEXTURE(This);
1272 This->priority = dwPriority;
1276 /* Be careful when locking this: it is risky to call the object's AddRef
1277 * or Release holding a lock. */
1279 Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
1280 REFGUID tag, LPVOID pData,
1281 DWORD cbSize, DWORD dwFlags)
1284 ICOM_THIS(IDirectDrawSurfaceImpl, iface);
1286 data = find_private_data(This, tag);
1289 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
1290 if (data == NULL) return DDERR_OUTOFMEMORY;
1293 data->flags = dwFlags;
1294 data->uniqueness_value = This->uniqueness_value;
1296 if (dwFlags & DDSPD_IUNKNOWNPTR)
1298 data->ptr.object = (LPUNKNOWN)pData;
1299 data->size = sizeof(LPUNKNOWN);
1300 IUnknown_AddRef(data->ptr.object);
1304 data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
1305 if (data->ptr.data == NULL)
1307 HeapFree(GetProcessHeap(), 0, data);
1308 return DDERR_OUTOFMEMORY;
1313 data->next = This->private_data;
1315 if (This->private_data)
1316 This->private_data->prev = data;
1317 This->private_data = data;
1323 /* I don't actually know how windows handles this case. The only
1324 * reason I don't just call FreePrivateData is because I want to
1325 * guarantee SetPrivateData working when using LPUNKNOWN or data
1326 * that is no larger than the old data. */
1332 /* SetSurfaceDesc */
1335 Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
1337 ICOM_THIS(IDirectDrawSurfaceImpl,iface);
1339 TRACE("(%p)->Unlock(%p)\n",This,pRect);
1341 This->unlock_update(This, pRect);
1342 if (This->aux_unlock)
1343 This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
1349 Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
1351 LPDIRECTDRAWSURFACE7 pDstSurface,
1352 LPRECT pDstRect, DWORD dwFlags,
1355 return DDERR_UNSUPPORTED;
1358 /* MSDN: "not currently implemented." */
1360 Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
1363 return DDERR_UNSUPPORTED;
1367 Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
1369 LPDIRECTDRAWSURFACE7 pDDSRef)
1371 return DDERR_NOTAOVERLAYSURFACE;