2006-06-09 17:36:12 +00:00
|
|
|
/* DirectDrawClipper implementation
|
2000-04-09 14:30:50 +00:00
|
|
|
*
|
2006-06-09 17:36:12 +00:00
|
|
|
* Copyright 2000 (c) Marcus Meissner
|
|
|
|
* Copyright 2000 (c) TransGaming Technologies Inc.
|
2008-10-18 17:19:45 +00:00
|
|
|
* Copyright 2006 (c) Stefan Dösinger
|
2002-03-09 23:29:33 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-05-18 12:49:52 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
2000-04-09 14:30:50 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
2010-08-18 17:26:20 +00:00
|
|
|
#include "wine/port.h"
|
2001-07-18 21:04:23 +00:00
|
|
|
|
2000-04-09 14:30:50 +00:00
|
|
|
#include "ddraw_private.h"
|
|
|
|
|
2002-03-09 23:29:33 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
|
2000-04-09 14:30:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static inline struct ddraw_clipper *impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
return CONTAINING_RECORD(iface, struct ddraw_clipper, IDirectDrawClipper_iface);
|
2011-06-20 09:20:41 +00:00
|
|
|
}
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_QueryInterface(IDirectDrawClipper *iface, REFIID iid, void **object)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
2010-08-19 16:57:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
|
2010-08-19 16:57:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
if (IsEqualGUID(&IID_IDirectDrawClipper, iid)
|
|
|
|
|| IsEqualGUID(&IID_IUnknown, iid))
|
2006-06-09 17:36:12 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
IDirectDrawClipper_AddRef(&clipper->IDirectDrawClipper_iface);
|
|
|
|
*object = &clipper->IDirectDrawClipper_iface;
|
2009-01-21 08:56:13 +00:00
|
|
|
return S_OK;
|
2006-06-09 17:36:12 +00:00
|
|
|
}
|
2010-09-08 09:24:49 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
|
|
|
|
*object = NULL;
|
|
|
|
|
2010-09-08 09:24:49 +00:00
|
|
|
return E_NOINTERFACE;
|
2006-06-09 17:36:12 +00:00
|
|
|
}
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static ULONG WINAPI ddraw_clipper_AddRef(IDirectDrawClipper *iface)
|
2006-06-09 17:36:12 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
|
|
|
ULONG refcount = InterlockedIncrement(&clipper->ref);
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("%p increasing refcount to %u.\n", clipper, refcount);
|
2000-04-09 14:30:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
return refcount;
|
2000-04-09 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static ULONG WINAPI ddraw_clipper_Release(IDirectDrawClipper *iface)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
|
|
|
ULONG refcount = InterlockedDecrement(&clipper->ref);
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("%p decreasing refcount to %u.\n", clipper, refcount);
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
if (!refcount)
|
2012-01-06 10:20:04 +00:00
|
|
|
{
|
|
|
|
if (clipper->region)
|
|
|
|
DeleteObject(clipper->region);
|
2011-12-12 19:53:55 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, clipper);
|
2012-01-06 10:20:04 +00:00
|
|
|
}
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
return refcount;
|
|
|
|
}
|
2006-06-09 17:36:12 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_SetHWnd(IDirectDrawClipper *iface, DWORD flags, HWND window)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
2010-08-19 16:57:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("iface %p, flags %#x, window %p.\n", iface, flags, window);
|
|
|
|
|
|
|
|
if (flags)
|
|
|
|
{
|
|
|
|
FIXME("flags %#x, not supported.\n", flags);
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
2000-04-09 14:30:50 +00:00
|
|
|
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_lock();
|
2011-12-12 19:53:55 +00:00
|
|
|
clipper->window = window;
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_unlock();
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
return DD_OK;
|
2000-04-09 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2012-01-06 10:20:03 +00:00
|
|
|
static HRGN get_window_region(HWND window)
|
|
|
|
{
|
2012-02-03 21:00:27 +00:00
|
|
|
POINT origin;
|
|
|
|
HRGN rgn;
|
|
|
|
HDC dc;
|
2012-01-06 10:20:03 +00:00
|
|
|
|
2012-02-03 21:00:27 +00:00
|
|
|
if (!(dc = GetDC(window)))
|
2012-01-06 10:20:03 +00:00
|
|
|
{
|
2012-02-03 21:00:27 +00:00
|
|
|
WARN("Failed to get dc.\n");
|
2012-01-06 10:20:03 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-03 21:00:27 +00:00
|
|
|
if (!(rgn = CreateRectRgn(0, 0, 0, 0)))
|
2012-01-06 10:20:03 +00:00
|
|
|
{
|
2012-02-03 21:00:27 +00:00
|
|
|
ERR("Failed to create region.\n");
|
|
|
|
ReleaseDC(window, dc);
|
2012-01-06 10:20:03 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-03 21:00:27 +00:00
|
|
|
if (GetRandomRgn(dc, rgn, SYSRGN) != 1)
|
2012-01-06 10:20:03 +00:00
|
|
|
{
|
2012-02-03 21:00:27 +00:00
|
|
|
ERR("Failed to get window region.\n");
|
|
|
|
DeleteObject(rgn);
|
|
|
|
ReleaseDC(window, dc);
|
2012-01-06 10:20:03 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-03 21:00:27 +00:00
|
|
|
if (GetVersion() & 0x80000000)
|
|
|
|
{
|
|
|
|
GetDCOrgEx(dc, &origin);
|
|
|
|
OffsetRgn(rgn, origin.x, origin.y);
|
|
|
|
}
|
|
|
|
|
2012-02-08 21:35:11 +00:00
|
|
|
ReleaseDC(window, dc);
|
2012-02-03 21:00:27 +00:00
|
|
|
return rgn;
|
2012-01-06 10:20:03 +00:00
|
|
|
}
|
|
|
|
|
2006-06-09 17:36:12 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectDrawClipper::GetClipList
|
|
|
|
*
|
|
|
|
* Retrieve a copy of the clip list
|
|
|
|
*
|
|
|
|
* Arguments:
|
2011-12-12 19:53:55 +00:00
|
|
|
* rect: Rectangle to be used to clip the clip list or NULL for the
|
|
|
|
* entire clip list.
|
|
|
|
* clip_list: structure for the resulting copy of the clip list.
|
|
|
|
* If NULL, fills Size up to the number of bytes necessary to hold
|
|
|
|
* the entire clip.
|
|
|
|
* clip_list_size: Size of resulting clip list; size of the buffer at clip_list
|
|
|
|
* or, if clip_list is NULL, receives the required size of the buffer
|
|
|
|
* in bytes.
|
2006-06-09 17:36:12 +00:00
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* Either DD_OK or DDERR_*
|
|
|
|
************************************************************************/
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_GetClipList(IDirectDrawClipper *iface, RECT *rect,
|
|
|
|
RGNDATA *clip_list, DWORD *clip_list_size)
|
2004-08-24 20:14:26 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
2012-01-06 10:20:03 +00:00
|
|
|
HRGN region;
|
2010-08-19 16:57:50 +00:00
|
|
|
|
|
|
|
TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n",
|
2011-12-12 19:53:55 +00:00
|
|
|
iface, wine_dbgstr_rect(rect), clip_list, clip_list_size);
|
2004-08-24 20:14:26 +00:00
|
|
|
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_lock();
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
if (clipper->window)
|
|
|
|
{
|
2012-01-06 10:20:03 +00:00
|
|
|
if (!(region = get_window_region(clipper->window)))
|
|
|
|
{
|
|
|
|
wined3d_mutex_unlock();
|
2012-01-09 21:16:48 +00:00
|
|
|
WARN("Failed to get window region.\n");
|
2012-01-06 10:20:03 +00:00
|
|
|
return E_FAIL;
|
|
|
|
}
|
2012-01-06 10:20:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(region = clipper->region))
|
2011-12-12 19:53:55 +00:00
|
|
|
{
|
2012-01-06 10:20:04 +00:00
|
|
|
wined3d_mutex_unlock();
|
|
|
|
WARN("No clip list set.\n");
|
|
|
|
return DDERR_NOCLIPLIST;
|
|
|
|
}
|
|
|
|
}
|
2012-01-06 10:20:03 +00:00
|
|
|
|
2012-01-06 10:20:04 +00:00
|
|
|
if (rect)
|
|
|
|
{
|
|
|
|
HRGN clip_region;
|
|
|
|
|
|
|
|
if (!(clip_region = CreateRectRgnIndirect(rect)))
|
|
|
|
{
|
|
|
|
wined3d_mutex_unlock();
|
|
|
|
ERR("Failed to create region.\n");
|
|
|
|
if (clipper->window)
|
2012-01-06 10:20:03 +00:00
|
|
|
DeleteObject(region);
|
2012-01-06 10:20:04 +00:00
|
|
|
return E_FAIL;
|
|
|
|
}
|
2012-01-06 10:20:03 +00:00
|
|
|
|
2012-01-06 10:20:04 +00:00
|
|
|
if (CombineRgn(clip_region, region, clip_region, RGN_AND) == ERROR)
|
|
|
|
{
|
|
|
|
wined3d_mutex_unlock();
|
|
|
|
ERR("Failed to combine regions.\n");
|
2012-01-06 10:20:03 +00:00
|
|
|
DeleteObject(clip_region);
|
2012-01-06 10:20:04 +00:00
|
|
|
if (clipper->window)
|
2012-01-06 10:20:03 +00:00
|
|
|
DeleteObject(region);
|
2012-01-06 10:20:04 +00:00
|
|
|
return E_FAIL;
|
2011-12-12 19:53:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-08 20:14:57 +00:00
|
|
|
if (clipper->window)
|
|
|
|
DeleteObject(region);
|
2012-01-06 10:20:04 +00:00
|
|
|
region = clip_region;
|
2011-12-12 19:53:55 +00:00
|
|
|
}
|
|
|
|
|
2012-01-06 10:20:04 +00:00
|
|
|
*clip_list_size = GetRegionData(region, *clip_list_size, clip_list);
|
|
|
|
if (rect || clipper->window)
|
|
|
|
DeleteObject(region);
|
2011-12-12 19:53:55 +00:00
|
|
|
|
|
|
|
wined3d_mutex_unlock();
|
2012-01-06 10:20:04 +00:00
|
|
|
return DD_OK;
|
2000-04-09 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2006-06-09 17:36:12 +00:00
|
|
|
/*****************************************************************************
|
|
|
|
* IDirectDrawClipper::SetClipList
|
|
|
|
*
|
2011-12-12 19:53:55 +00:00
|
|
|
* Sets or deletes (if region is NULL) the clip list
|
2006-06-09 17:36:12 +00:00
|
|
|
*
|
2006-06-23 16:18:02 +00:00
|
|
|
* This implementation is a stub and returns DD_OK always to make the app
|
2006-06-09 17:36:12 +00:00
|
|
|
* happy.
|
|
|
|
*
|
|
|
|
* PARAMS
|
2011-12-12 19:53:55 +00:00
|
|
|
* region Pointer to a LRGNDATA structure or NULL
|
|
|
|
* flags not used, must be 0
|
2006-06-09 17:36:12 +00:00
|
|
|
* RETURNS
|
|
|
|
* Either DD_OK or DDERR_*
|
|
|
|
*****************************************************************************/
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_SetClipList(IDirectDrawClipper *iface, RGNDATA *region, DWORD flags)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2012-01-04 22:34:53 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
|
|
|
|
2012-01-06 10:20:04 +00:00
|
|
|
TRACE("iface %p, region %p, flags %#x.\n", iface, region, flags);
|
|
|
|
|
|
|
|
wined3d_mutex_lock();
|
2011-11-13 18:52:24 +00:00
|
|
|
|
2012-01-04 22:34:53 +00:00
|
|
|
if (clipper->window)
|
2012-01-06 10:20:04 +00:00
|
|
|
{
|
|
|
|
wined3d_mutex_unlock();
|
2012-01-04 22:34:53 +00:00
|
|
|
return DDERR_CLIPPERISUSINGHWND;
|
2012-01-06 10:20:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (clipper->region)
|
|
|
|
DeleteObject(clipper->region);
|
2012-01-09 21:16:49 +00:00
|
|
|
if (!region)
|
|
|
|
clipper->region = NULL;
|
|
|
|
else if (!(clipper->region = ExtCreateRegion(NULL, 0, region)))
|
2012-01-06 10:20:04 +00:00
|
|
|
{
|
|
|
|
wined3d_mutex_unlock();
|
2012-01-09 21:16:49 +00:00
|
|
|
ERR("Failed to create region.\n");
|
2012-01-06 10:20:04 +00:00
|
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wined3d_mutex_unlock();
|
2012-01-04 22:34:53 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
return DD_OK;
|
2000-04-09 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_GetHWnd(IDirectDrawClipper *iface, HWND *window)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
2010-08-19 16:57:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("iface %p, window %p.\n", iface, window);
|
2000-04-09 14:30:50 +00:00
|
|
|
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_lock();
|
2011-12-12 19:53:55 +00:00
|
|
|
*window = clipper->window;
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_unlock();
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
return DD_OK;
|
2000-04-09 14:30:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_Initialize(IDirectDrawClipper *iface,
|
|
|
|
IDirectDraw *ddraw, DWORD flags)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
|
2010-08-19 16:57:50 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
TRACE("iface %p, ddraw %p, flags %#x.\n", iface, ddraw, flags);
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_lock();
|
2011-12-12 19:53:55 +00:00
|
|
|
if (clipper->initialized)
|
2007-05-20 21:51:26 +00:00
|
|
|
{
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_unlock();
|
2007-05-20 21:51:26 +00:00
|
|
|
return DDERR_ALREADYINITIALIZED;
|
|
|
|
}
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
clipper->initialized = TRUE;
|
2011-11-13 18:52:24 +00:00
|
|
|
wined3d_mutex_unlock();
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2000-04-09 14:30:50 +00:00
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
static HRESULT WINAPI ddraw_clipper_IsClipListChanged(IDirectDrawClipper *iface, BOOL *changed)
|
2011-06-20 09:20:41 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
FIXME("iface %p, changed %p stub!\n", iface, changed);
|
2001-01-04 22:44:55 +00:00
|
|
|
|
|
|
|
/* XXX What is safest? */
|
2011-12-12 19:53:55 +00:00
|
|
|
*changed = FALSE;
|
2001-01-04 22:44:55 +00:00
|
|
|
|
2000-04-09 14:30:50 +00:00
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
2010-08-18 17:26:25 +00:00
|
|
|
static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl =
|
2000-04-09 14:30:50 +00:00
|
|
|
{
|
2011-12-12 19:53:55 +00:00
|
|
|
ddraw_clipper_QueryInterface,
|
|
|
|
ddraw_clipper_AddRef,
|
|
|
|
ddraw_clipper_Release,
|
|
|
|
ddraw_clipper_GetClipList,
|
|
|
|
ddraw_clipper_GetHWnd,
|
|
|
|
ddraw_clipper_Initialize,
|
|
|
|
ddraw_clipper_IsClipListChanged,
|
|
|
|
ddraw_clipper_SetClipList,
|
|
|
|
ddraw_clipper_SetHWnd,
|
2000-04-09 14:30:50 +00:00
|
|
|
};
|
2010-08-18 17:26:25 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
HRESULT ddraw_clipper_init(struct ddraw_clipper *clipper)
|
2010-08-18 17:26:25 +00:00
|
|
|
{
|
2011-06-20 09:20:41 +00:00
|
|
|
clipper->IDirectDrawClipper_iface.lpVtbl = &ddraw_clipper_vtbl;
|
2010-08-18 17:26:25 +00:00
|
|
|
clipper->ref = 1;
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
2011-06-20 09:22:55 +00:00
|
|
|
|
2011-12-12 19:53:55 +00:00
|
|
|
struct ddraw_clipper *unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
|
2011-06-20 09:22:55 +00:00
|
|
|
{
|
|
|
|
if (!iface)
|
|
|
|
return NULL;
|
|
|
|
assert(iface->lpVtbl == &ddraw_clipper_vtbl);
|
|
|
|
|
|
|
|
return impl_from_IDirectDrawClipper(iface);
|
|
|
|
}
|