Sweden-Number/dlls/ddraw/dsurface/main.c

1077 lines
27 KiB
C

/* DirectDrawSurface base implementation
*
* Copyright 1997-2000 Marcus Meissner
* Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
* Copyright 2000 TransGaming Technologies Inc.
*/
#include "config.h"
#include "winerror.h"
#include <assert.h>
#include <string.h>
#include "debugtools.h"
#include "ddraw_private.h"
#include "dsurface/main.h"
#include "ddraw/main.h"
#include "dsurface/thunks.h"
DEFAULT_DEBUG_CHANNEL(ddraw);
/** Creation/Destruction functions */
HRESULT
Main_DirectDrawSurface_Construct(IDirectDrawSurfaceImpl *This,
IDirectDrawImpl *pDD,
const DDSURFACEDESC2 *pDDSD)
{
if (pDDSD != &This->surface_desc)
This->surface_desc = *pDDSD;
This->uniqueness_value = 1; /* unchecked */
This->ref = 1;
This->final_release = Main_DirectDrawSurface_final_release;
This->attach = Main_DirectDrawSurface_attach;
This->detach = Main_DirectDrawSurface_detach;
This->lock_update = Main_DirectDrawSurface_lock_update;
This->unlock_update = Main_DirectDrawSurface_unlock_update;
This->lose_surface = Main_DirectDrawSurface_lose_surface;
This->set_palette = Main_DirectDrawSurface_set_palette;
This->update_palette = Main_DirectDrawSurface_update_palette;
This->get_display_window = Main_DirectDrawSurface_get_display_window;
ICOM_INIT_INTERFACE(This, IDirectDrawSurface3,
DDRAW_IDDS3_Thunk_VTable);
/* There is no generic implementation of IDDS7 */
Main_DirectDraw_AddSurface(pDD, This);
return DD_OK;
}
void Main_DirectDrawSurface_final_release(IDirectDrawSurfaceImpl* This)
{
Main_DirectDraw_RemoveSurface(This->ddraw_owner, This);
}
static void Main_DirectDrawSurface_Destroy(IDirectDrawSurfaceImpl* This)
{
This->final_release(This);
if (This->private != This+1) HeapFree(GetProcessHeap(), 0, This->private);
HeapFree(GetProcessHeap(), 0, This);
}
void Main_DirectDrawSurface_ForceDestroy(IDirectDrawSurfaceImpl* This)
{
WARN("destroying surface %p with refcnt %lu\n", This, This->ref);
Main_DirectDrawSurface_Destroy(This);
}
ULONG WINAPI Main_DirectDrawSurface_Release(LPDIRECTDRAWSURFACE7 iface)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
if (--This->ref == 0)
{
if (This->aux_release)
This->aux_release(This->aux_ctx, This->aux_data);
Main_DirectDrawSurface_Destroy(This);
return 0;
}
return This->ref;
}
ULONG WINAPI Main_DirectDrawSurface_AddRef(LPDIRECTDRAWSURFACE7 iface)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
return ++This->ref;
}
HRESULT WINAPI
Main_DirectDrawSurface_QueryInterface(LPDIRECTDRAWSURFACE7 iface, REFIID riid,
LPVOID* ppObj)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppObj);
if (IsEqualGUID(&IID_IUnknown, riid)
|| IsEqualGUID(&IID_IDirectDrawSurface7, riid)
|| IsEqualGUID(&IID_IDirectDrawSurface4, riid))
{
This->ref++;
*ppObj = ICOM_INTERFACE(This, IDirectDrawSurface7);
return S_OK;
}
else if (IsEqualGUID(&IID_IDirectDrawSurface, riid)
|| IsEqualGUID(&IID_IDirectDrawSurface2, riid)
|| IsEqualGUID(&IID_IDirectDrawSurface3, riid))
{
This->ref++;
*ppObj = ICOM_INTERFACE(This, IDirectDrawSurface3);
return S_OK;
}
else
return E_NOINTERFACE;
}
/*** Callbacks */
BOOL
Main_DirectDrawSurface_attach(IDirectDrawSurfaceImpl *This,
IDirectDrawSurfaceImpl *to)
{
return TRUE;
}
BOOL Main_DirectDrawSurface_detach(IDirectDrawSurfaceImpl *This)
{
return TRUE;
}
void
Main_DirectDrawSurface_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
{
}
void
Main_DirectDrawSurface_unlock_update(IDirectDrawSurfaceImpl* This,
LPCRECT pRect)
{
}
void
Main_DirectDrawSurface_lose_surface(IDirectDrawSurfaceImpl* This)
{
}
void
Main_DirectDrawSurface_set_palette(IDirectDrawSurfaceImpl* This,
IDirectDrawPaletteImpl* pal)
{
}
void
Main_DirectDrawSurface_update_palette(IDirectDrawSurfaceImpl* This,
IDirectDrawPaletteImpl* pal,
DWORD dwStart, DWORD dwCount,
LPPALETTEENTRY palent)
{
}
HWND
Main_DirectDrawSurface_get_display_window(IDirectDrawSurfaceImpl* This)
{
return 0;
}
/*** Interface functions */
HRESULT WINAPI
Main_DirectDrawSurface_AddAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWSURFACE7 pAttach)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
IDirectDrawSurface7, pAttach);
TRACE("(%p)->(%p)\n",This,pAttach);
/* Does windows check this? */
if (surf == This)
return DDERR_CANNOTATTACHSURFACE; /* unchecked */
/* Does windows check this? */
if (surf->ddraw_owner != This->ddraw_owner)
return DDERR_CANNOTATTACHSURFACE; /* unchecked */
if (surf->surface_owner != NULL)
return DDERR_SURFACEALREADYATTACHED; /* unchecked */
/* TODO MSDN: "You can attach only z-buffer surfaces with this method."
* But apparently backbuffers and mipmaps can be attached too. */
/* Callback to allow the surface to do something special now that it is
* attached. (e.g. maybe the Z-buffer tells the renderer to use it.) */
if (!surf->attach(surf, This))
return DDERR_CANNOTATTACHSURFACE;
/* check: Where should it go in the chain? This puts it on the head. */
if (This->attached)
This->attached->prev_attached = surf;
surf->next_attached = This->attached;
surf->prev_attached = NULL;
This->attached = surf;
surf->surface_owner = This;
IDirectDrawSurface7_AddRef(pAttach);
return DD_OK;
}
/* MSDN: "not currently implemented." */
HRESULT WINAPI
Main_DirectDrawSurface_AddOverlayDirtyRect(LPDIRECTDRAWSURFACE7 iface,
LPRECT pRect)
{
TRACE("(%p)->(%p)\n",iface,pRect);
return DDERR_UNSUPPORTED; /* unchecked */
}
/* MSDN: "not currently implemented." */
HRESULT WINAPI
Main_DirectDrawSurface_BltBatch(LPDIRECTDRAWSURFACE7 iface,
LPDDBLTBATCH pBatch, DWORD dwCount,
DWORD dwFlags)
{
TRACE("(%p)->(%p,%ld,%08lx)\n",iface,pBatch,dwCount,dwFlags);
return DDERR_UNSUPPORTED; /* unchecked */
}
HRESULT WINAPI
Main_DirectDrawSurface_ChangeUniquenessValue(LPDIRECTDRAWSURFACE7 iface)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
volatile IDirectDrawSurfaceImpl* vThis = This;
TRACE("(%p)\n",This);
/* A uniquness value of 0 is apparently special.
* This needs to be checked. */
while (1)
{
DWORD old_uniqueness_value = vThis->uniqueness_value;
DWORD new_uniqueness_value = old_uniqueness_value+1;
if (old_uniqueness_value == 0) break;
if (new_uniqueness_value == 0) new_uniqueness_value = 1;
if (InterlockedCompareExchange((PVOID*)&vThis->uniqueness_value,
(PVOID)old_uniqueness_value,
(PVOID)new_uniqueness_value)
== (PVOID)old_uniqueness_value)
break;
}
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_DeleteAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
DWORD dwFlags,
LPDIRECTDRAWSURFACE7 pAttach)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
IDirectDrawSurface7, pAttach);
TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach);
if (!surf || (surf->surface_owner != This))
return DDERR_SURFACENOTATTACHED; /* unchecked */
surf->detach(surf);
if (surf->next_attached)
surf->next_attached->prev_attached = surf->prev_attached;
if (surf->prev_attached)
surf->prev_attached->next_attached = surf->next_attached;
if (This->attached == surf)
This->attached = surf->next_attached;
IDirectDrawSurface7_Release(pAttach);
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE7 iface,
LPVOID context,
LPDDENUMSURFACESCALLBACK7 cb)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
IDirectDrawSurfaceImpl* surf;
TRACE("(%p)->(%p,%p)\n",This,context,cb);
for (surf = This->attached; surf != NULL; surf = surf->next_attached)
{
/* check: != DDENUMRET_OK or == DDENUMRET_CANCEL? */
if (cb(ICOM_INTERFACE(surf, IDirectDrawSurface7), &surf->surface_desc,
context) == DDENUMRET_CANCEL)
break;
}
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_EnumOverlayZOrders(LPDIRECTDRAWSURFACE7 iface,
DWORD dwFlags, LPVOID context,
LPDDENUMSURFACESCALLBACK7 cb)
{
TRACE("(%p)->(%08lx,%p,%p)\n",iface,dwFlags,context,cb);
return DD_OK;
}
void Main_DirectDrawSurface_flip_data(IDirectDrawSurfaceImpl* front,
IDirectDrawSurfaceImpl* back)
{
/* uniqueness_value? */
/* This is necessary. But is it safe? */
{
HDC tmp = front->hDC;
front->hDC = back->hDC;
back->hDC = tmp;
}
{
BOOL tmp = front->dc_in_use;
front->dc_in_use = back->dc_in_use;
back->dc_in_use = tmp;
}
}
HRESULT WINAPI
Main_DirectDrawSurface_Flip(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWSURFACE7 override, DWORD dwFlags)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
IDirectDrawSurfaceImpl* target;
HRESULT hr;
TRACE("(%p)->(%p,%08lx)\n",This,override,dwFlags);
/* MSDN: "This method can be called only for a surface that has the
* DDSCAPS_FLIP and DDSCAPS_FRONTBUFFER capabilities." */
if ((This->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
!= (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER))
return DDERR_NOTFLIPPABLE;
if (This->aux_flip)
if (This->aux_flip(This->aux_ctx, This->aux_data))
return DD_OK;
/* 1. find the flip target */
/* XXX I don't think this algorithm works for more than 1 backbuffer. */
if (override == NULL)
{
static DDSCAPS2 back_caps = { DDSCAPS_BACKBUFFER };
LPDIRECTDRAWSURFACE7 tgt;
hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt);
if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */
target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
tgt);
IDirectDrawSurface7_Release(tgt);
}
else
{
BOOL on_chain = FALSE;
IDirectDrawSurfaceImpl* surf;
/* MSDN: "The method fails if the specified [override] surface is not
* a member of the flipping chain." */
/* Verify that override is on this flip chain. We assume that
* surf is the head of the flipping chain, because it's the front
* buffer. */
target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7,
override);
/* Either target is (indirectly) attached to This or This is
* (indirectly) attached to target. */
for (surf = target; surf != NULL; surf = surf->surface_owner)
{
if (surf == This)
{
on_chain = TRUE;
break;
}
}
if (!on_chain)
return DDERR_INVALIDPARAMS; /* unchecked */
}
TRACE("flip to backbuffer: %p\n",target);
This->flip_data(This, target);
This->flip_update(This);
return DD_OK;
}
static PrivateData* find_private_data(IDirectDrawSurfaceImpl *This,
REFGUID tag)
{
PrivateData* data;
for (data = This->private_data; data != NULL; data = data->next)
{
if (IsEqualGUID(&data->tag, tag)) break;
}
return data;
}
HRESULT WINAPI
Main_DirectDrawSurface_FreePrivateData(LPDIRECTDRAWSURFACE7 iface, REFGUID tag)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
PrivateData *data;
data = find_private_data(This, tag);
if (data == NULL) return DDERR_NOTFOUND;
if (data->prev)
data->prev->next = data->next;
if (data->next)
data->next->prev = data->prev;
if (data->flags & DDSPD_IUNKNOWNPTR)
{
if (data->ptr.object != NULL)
IUnknown_Release(data->ptr.object);
}
else
HeapFree(GetProcessHeap(), 0, data->ptr.data);
HeapFree(GetProcessHeap(), 0, data);
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetAttachedSurface(LPDIRECTDRAWSURFACE7 iface,
LPDDSCAPS2 pCaps,
LPDIRECTDRAWSURFACE7* ppSurface)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
IDirectDrawSurfaceImpl* surf;
IDirectDrawSurfaceImpl* found = NULL;
TRACE("(%p)->Looking for caps: %lx,%lx,%lx,%lx output: %p\n",This,pCaps->dwCaps, pCaps->dwCaps2,
pCaps->dwCaps3, pCaps->dwCaps4, ppSurface);
for (surf = This->attached; surf != NULL; surf = surf->next_attached)
{
TRACE("Surface: (%p) caps: %lx,%lx,%lx,%lx \n",surf ,
surf->surface_desc.ddsCaps.dwCaps,
surf->surface_desc.ddsCaps.dwCaps2,
surf->surface_desc.ddsCaps.dwCaps3,
surf->surface_desc.ddsCaps.dwCaps4);
if (((surf->surface_desc.ddsCaps.dwCaps & pCaps->dwCaps) == pCaps->dwCaps)
&& ((surf->surface_desc.ddsCaps.dwCaps2 & pCaps->dwCaps2) == pCaps->dwCaps2))
{
/* MSDN: "This method fails if more than one surface is attached
* that matches the capabilities requested." */
if (found != NULL)
{
FIXME("More than one attached surface matches requested caps. What should we do here?\n");
/* Previous code returned 'DDERR_NOTFOUND'. That appears not
to be correct, given what 3DMark expects from MipMapped surfaces.
We shall just continue instead. */
}
found = surf;
}
}
if (found == NULL)
return DDERR_NOTFOUND;
*ppSurface = ICOM_INTERFACE(found, IDirectDrawSurface7);
/* XXX d3dframe.cpp sometimes AddRefs things that it gets from us. */
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(found, IDirectDrawSurface7));
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetBltStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
{
TRACE("(%p)->(%08lx)\n",iface,dwFlags);
switch (dwFlags)
{
case DDGBS_CANBLT:
case DDGBS_ISBLTDONE:
return DD_OK;
default:
return DDERR_INVALIDPARAMS;
}
}
HRESULT WINAPI
Main_DirectDrawSurface_GetCaps(LPDIRECTDRAWSURFACE7 iface, LPDDSCAPS2 pCaps)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pCaps);
*pCaps = This->surface_desc.ddsCaps;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetClipper(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWCLIPPER* ppClipper)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,ppClipper);
if (This->clipper == NULL)
return DDERR_NOCLIPPERATTACHED;
*ppClipper = ICOM_INTERFACE(This->clipper, IDirectDrawClipper);
IDirectDrawClipper_AddRef(ICOM_INTERFACE(This->clipper,
IDirectDrawClipper));
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetColorKey(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags,
LPDDCOLORKEY pCKey)
{
/* There is a DDERR_NOCOLORKEY error, but how do we know if a color key
* isn't there? That's like saying that an int isn't there. (Which MS
* has done in other docs.) */
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
switch (dwFlags)
{
case DDCKEY_DESTBLT:
*pCKey = This->surface_desc.ddckCKDestBlt;
break;
case DDCKEY_DESTOVERLAY:
*pCKey = This->surface_desc.u3.ddckCKDestOverlay;
break;
case DDCKEY_SRCBLT:
*pCKey = This->surface_desc.ddckCKSrcBlt;
break;
case DDCKEY_SRCOVERLAY:
*pCKey = This->surface_desc.ddckCKSrcOverlay;
break;
default:
return DDERR_INVALIDPARAMS;
}
return DD_OK;
}
/* XXX We need to do something with the DC if the surface gets lost. */
HRESULT WINAPI
Main_DirectDrawSurface_GetDC(LPDIRECTDRAWSURFACE7 iface, HDC *phDC)
{
DDSURFACEDESC2 ddsd;
HRESULT hr;
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,phDC);
CHECK_LOST(This);
LOCK_OBJECT(This);
if (This->dc_in_use)
{
UNLOCK_OBJECT(This);
return DDERR_DCALREADYCREATED;
}
/* Lock as per MSDN.
* Strange: Lock lists DDERR_SURFACEBUSY as an error, meaning that another
* thread has it locked, but GetDC does not. */
ddsd.dwSize = sizeof(ddsd);
hr = IDirectDrawSurface7_Lock(iface, NULL, &ddsd, 0, 0);
if (FAILED(hr))
{
UNLOCK_OBJECT(This);
return hr;
}
hr = This->get_dc(This, &This->hDC);
if (SUCCEEDED(hr))
{
TRACE("returning %08x\n",This->hDC);
*phDC = This->hDC;
This->dc_in_use = TRUE;
}
else WARN("No DC! Prepare for trouble\n");
UNLOCK_OBJECT(This);
return hr;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetDDInterface(LPDIRECTDRAWSURFACE7 iface, LPVOID* pDD)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pDD);
*pDD = ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7);
IDirectDraw7_AddRef(ICOM_INTERFACE(This->ddraw_owner, IDirectDraw7));
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetFlipStatus(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
{
/* XXX: DDERR_INVALIDSURFACETYPE */
TRACE("(%p)->(%08lx)\n",iface,dwFlags);
switch (dwFlags)
{
case DDGFS_CANFLIP:
case DDGFS_ISFLIPDONE:
return DD_OK;
default:
return DDERR_INVALIDPARAMS;
}
}
HRESULT WINAPI
Main_DirectDrawSurface_GetLOD(LPDIRECTDRAWSURFACE7 iface, LPDWORD pdwMaxLOD)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pdwMaxLOD);
CHECK_TEXTURE(This);
*pdwMaxLOD = This->max_lod;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
LPLONG pX, LPLONG pY)
{
return DDERR_NOTAOVERLAYSURFACE;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetPalette(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWPALETTE* ppPalette)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,ppPalette);
if (This->palette == NULL)
return DDERR_NOPALETTEATTACHED;
*ppPalette = ICOM_INTERFACE(This->palette, IDirectDrawPalette);
IDirectDrawPalette_AddRef(ICOM_INTERFACE(This->palette,
IDirectDrawPalette));
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetPixelFormat(LPDIRECTDRAWSURFACE7 iface,
LPDDPIXELFORMAT pDDPixelFormat)
{
/* What is DDERR_INVALIDSURFACETYPE for here? */
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pDDPixelFormat);
*pDDPixelFormat = This->surface_desc.u4.ddpfPixelFormat;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetPriority(LPDIRECTDRAWSURFACE7 iface,
LPDWORD pdwPriority)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pdwPriority);
CHECK_TEXTURE(This);
*pdwPriority = This->priority;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetPrivateData(LPDIRECTDRAWSURFACE7 iface,
REFGUID tag, LPVOID pBuffer,
LPDWORD pcbBufferSize)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
PrivateData* data;
data = find_private_data(This, tag);
if (data == NULL) return DDERR_NOTFOUND;
/* This may not be right. */
if ((data->flags & DDSPD_VOLATILE)
&& data->uniqueness_value != This->uniqueness_value)
return DDERR_EXPIRED;
if (*pcbBufferSize < data->size)
{
*pcbBufferSize = data->size;
return DDERR_MOREDATA;
}
if (data->flags & DDSPD_IUNKNOWNPTR)
{
*(LPUNKNOWN *)pBuffer = data->ptr.object;
IUnknown_AddRef(data->ptr.object);
}
else
{
memcpy(pBuffer, data->ptr.data, data->size);
}
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetSurfaceDesc(LPDIRECTDRAWSURFACE7 iface,
LPDDSURFACEDESC2 pDDSD)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pDDSD);
*pDDSD = This->surface_desc;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_GetUniquenessValue(LPDIRECTDRAWSURFACE7 iface,
LPDWORD pValue)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pValue);
*pValue = This->uniqueness_value;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_Initialize(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAW pDD, LPDDSURFACEDESC2 pDDSD)
{
TRACE("(%p)->(%p,%p)\n",iface,pDD,pDDSD);
return DDERR_ALREADYINITIALIZED;
}
HRESULT WINAPI
Main_DirectDrawSurface_IsLost(LPDIRECTDRAWSURFACE7 iface)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p) is%s lost\n",This, (This->lost ? "" : " not"));
return This->lost ? DDERR_SURFACELOST : DD_OK;
}
/* XXX This doesn't actually do any locking or keep track of the locked
* rectangles. The behaviour is poorly documented. */
HRESULT WINAPI
Main_DirectDrawSurface_Lock(LPDIRECTDRAWSURFACE7 iface, LPRECT prect,
LPDDSURFACEDESC2 pDDSD, DWORD flags, HANDLE h)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",This,prect,pDDSD,flags,(DWORD)h);
if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
This,prect,pDDSD,flags,(DWORD)h);
/* First, copy the Surface description */
memcpy(pDDSD, &(This->surface_desc), pDDSD->dwSize);
TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
pDDSD->dwHeight,pDDSD->dwWidth,pDDSD->u1.lPitch);
/* If asked only for a part, change the surface pointer.
* (Not documented.) */
if (prect != NULL) {
TRACE(" lprect: %dx%d-%dx%d\n",
prect->top,prect->left,prect->bottom,prect->right
);
if ((prect->top < 0) ||
(prect->left < 0) ||
(prect->bottom < 0) ||
(prect->right < 0)) {
ERR(" Negative values in LPRECT !!!\n");
return DDERR_INVALIDPARAMS;
}
This->lock_update(This, prect);
pDDSD->lpSurface = (char *)This->surface_desc.lpSurface
+ prect->top * This->surface_desc.u1.lPitch
+ prect->left * GET_BPP(This->surface_desc);
}
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_PageLock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
{
/* Some surface types should return DDERR_CANTPAGELOCK. */
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_PageUnlock(LPDIRECTDRAWSURFACE7 iface, DWORD dwFlags)
{
/* Some surface types should return DDERR_CANTPAGEUNLOCK, and we should
* keep track so we can return DDERR_NOTPAGELOCKED as appropriate. */
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_ReleaseDC(LPDIRECTDRAWSURFACE7 iface, HDC hDC)
{
HRESULT hr;
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%08x)\n",This,hDC);
if (!This->dc_in_use || This->hDC != hDC)
return DDERR_INVALIDPARAMS;
This->release_dc(This, hDC);
hr = IDirectDrawSurface7_Unlock(iface, NULL);
if (FAILED(hr)) return hr;
This->dc_in_use = FALSE;
This->hDC = 0;
return DD_OK;
}
/* Restore */
HRESULT WINAPI
Main_DirectDrawSurface_SetClipper(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWCLIPPER pDDClipper)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pDDClipper);
if (pDDClipper == ICOM_INTERFACE(This->clipper, IDirectDrawClipper))
return DD_OK;
if (This->clipper != NULL)
IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper,
IDirectDrawClipper));
This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper,
pDDClipper);
if (pDDClipper != NULL)
IDirectDrawClipper_AddRef(pDDClipper);
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_SetColorKey(LPDIRECTDRAWSURFACE7 iface,
DWORD dwFlags, LPDDCOLORKEY pCKey)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pCKey);
if (pCKey == NULL)
{
FIXME("supposedly removing color key %lu\n",
dwFlags & ~DDCKEY_COLORSPACE);
return DD_OK;
}
switch (dwFlags & ~DDCKEY_COLORSPACE)
{
case DDCKEY_DESTBLT:
This->surface_desc.ddckCKDestBlt = *pCKey;
break;
case DDCKEY_DESTOVERLAY:
This->surface_desc.u3.ddckCKDestOverlay = *pCKey;
break;
case DDCKEY_SRCOVERLAY:
This->surface_desc.ddckCKSrcOverlay = *pCKey;
break;
case DDCKEY_SRCBLT:
This->surface_desc.ddckCKSrcBlt = *pCKey;
break;
default:
return DDERR_INVALIDPARAMS;
}
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_SetLOD(LPDIRECTDRAWSURFACE7 iface, DWORD dwMaxLOD)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%08lx)\n",This,dwMaxLOD);
CHECK_TEXTURE(This);
This->max_lod = dwMaxLOD;
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_SetOverlayPosition(LPDIRECTDRAWSURFACE7 iface,
LONG X, LONG Y)
{
return DDERR_NOTAOVERLAYSURFACE;
}
HRESULT WINAPI
Main_DirectDrawSurface_SetPalette(LPDIRECTDRAWSURFACE7 iface,
LPDIRECTDRAWPALETTE pPalette)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%p)\n",This,pPalette);
if (pPalette == ICOM_INTERFACE(This->palette, IDirectDrawPalette))
return DD_OK;
if (This->palette != NULL) {
if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
This->palette->flags &= ~DDPCAPS_PRIMARYSURFACE;
IDirectDrawPalette_Release(ICOM_INTERFACE(This->palette,
IDirectDrawPalette));
}
This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette,
pPalette);
if (pPalette != NULL) {
IDirectDrawPalette_AddRef(pPalette);
if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
This->palette->flags |= DDPCAPS_PRIMARYSURFACE;
}
This->set_palette(This, This->palette);
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_SetPriority(LPDIRECTDRAWSURFACE7 iface,
DWORD dwPriority)
{
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
TRACE("(%p)->(%08lx)\n",This,dwPriority);
CHECK_TEXTURE(This);
This->priority = dwPriority;
return DD_OK;
}
/* Be careful when locking this: it is risky to call the object's AddRef
* or Release holding a lock. */
HRESULT WINAPI
Main_DirectDrawSurface_SetPrivateData(LPDIRECTDRAWSURFACE7 iface,
REFGUID tag, LPVOID pData,
DWORD cbSize, DWORD dwFlags)
{
PrivateData* data;
ICOM_THIS(IDirectDrawSurfaceImpl, iface);
data = find_private_data(This, tag);
if (data == NULL)
{
data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
if (data == NULL) return DDERR_OUTOFMEMORY;
data->tag = *tag;
data->flags = dwFlags;
data->uniqueness_value = This->uniqueness_value;
if (dwFlags & DDSPD_IUNKNOWNPTR)
{
data->ptr.object = (LPUNKNOWN)pData;
data->size = sizeof(LPUNKNOWN);
IUnknown_AddRef(data->ptr.object);
}
else
{
data->ptr.data = HeapAlloc(GetProcessHeap(), 0, cbSize);
if (data->ptr.data == NULL)
{
HeapFree(GetProcessHeap(), 0, data);
return DDERR_OUTOFMEMORY;
}
}
/* link it in */
data->next = This->private_data;
data->prev = NULL;
if (This->private_data)
This->private_data->prev = data;
This->private_data = data;
return DD_OK;
}
else
{
/* I don't actually know how windows handles this case. The only
* reason I don't just call FreePrivateData is because I want to
* guarantee SetPrivateData working when using LPUNKNOWN or data
* that is no larger than the old data. */
return E_FAIL;
}
}
/* SetSurfaceDesc */
HRESULT WINAPI
Main_DirectDrawSurface_Unlock(LPDIRECTDRAWSURFACE7 iface, LPRECT pRect)
{
ICOM_THIS(IDirectDrawSurfaceImpl,iface);
TRACE("(%p)->Unlock(%p)\n",This,pRect);
This->unlock_update(This, pRect);
if (This->aux_unlock)
This->aux_unlock(This->aux_ctx, This->aux_data, pRect);
return DD_OK;
}
HRESULT WINAPI
Main_DirectDrawSurface_UpdateOverlay(LPDIRECTDRAWSURFACE7 iface,
LPRECT pSrcRect,
LPDIRECTDRAWSURFACE7 pDstSurface,
LPRECT pDstRect, DWORD dwFlags,
LPDDOVERLAYFX pFX)
{
return DDERR_UNSUPPORTED;
}
/* MSDN: "not currently implemented." */
HRESULT WINAPI
Main_DirectDrawSurface_UpdateOverlayDisplay(LPDIRECTDRAWSURFACE7 iface,
DWORD dwFlags)
{
return DDERR_UNSUPPORTED;
}
HRESULT WINAPI
Main_DirectDrawSurface_UpdateOverlayZOrder(LPDIRECTDRAWSURFACE7 iface,
DWORD dwFlags,
LPDIRECTDRAWSURFACE7 pDDSRef)
{
return DDERR_NOTAOVERLAYSURFACE;
}