1 /* DirectDrawClipper implementation
3 * Copyright 2000 (c) Marcus Meissner
4 * Copyright 2000 (c) TransGaming Technologies Inc.
5 * Copyright 2006 (c) Stefan Dösinger
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
25 #include "ddraw_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
29 static inline struct ddraw_clipper
*impl_from_IDirectDrawClipper(IDirectDrawClipper
*iface
)
31 return CONTAINING_RECORD(iface
, struct ddraw_clipper
, IDirectDrawClipper_iface
);
34 static HRESULT WINAPI
ddraw_clipper_QueryInterface(IDirectDrawClipper
*iface
, REFIID iid
, void **object
)
36 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
38 TRACE("iface %p, iid %s, object %p.\n", iface
, debugstr_guid(iid
), object
);
40 if (IsEqualGUID(&IID_IDirectDrawClipper
, iid
)
41 || IsEqualGUID(&IID_IUnknown
, iid
))
43 IDirectDrawClipper_AddRef(&clipper
->IDirectDrawClipper_iface
);
44 *object
= &clipper
->IDirectDrawClipper_iface
;
48 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
54 static ULONG WINAPI
ddraw_clipper_AddRef(IDirectDrawClipper
*iface
)
56 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
57 ULONG refcount
= InterlockedIncrement(&clipper
->ref
);
59 TRACE("%p increasing refcount to %u.\n", clipper
, refcount
);
64 static ULONG WINAPI
ddraw_clipper_Release(IDirectDrawClipper
*iface
)
66 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
67 ULONG refcount
= InterlockedDecrement(&clipper
->ref
);
69 TRACE("%p decreasing refcount to %u.\n", clipper
, refcount
);
74 DeleteObject(clipper
->region
);
75 HeapFree(GetProcessHeap(), 0, clipper
);
81 static HRESULT WINAPI
ddraw_clipper_SetHWnd(IDirectDrawClipper
*iface
, DWORD flags
, HWND window
)
83 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
85 TRACE("iface %p, flags %#x, window %p.\n", iface
, flags
, window
);
89 FIXME("flags %#x, not supported.\n", flags
);
90 return DDERR_INVALIDPARAMS
;
94 clipper
->window
= window
;
95 wined3d_mutex_unlock();
100 static HRGN
get_window_region(HWND window
)
102 POINT origin
= {0, 0};
105 if (!GetClientRect(window
, &client_rect
))
107 /* This can happen if the window is destroyed, for example. */
108 WARN("Failed to get client rect.\n");
112 if (!ClientToScreen(window
, &origin
))
114 ERR("Failed to translate origin.\n");
118 if (!OffsetRect(&client_rect
, origin
.x
, origin
.y
))
120 ERR("Failed to translate client rect.\n");
124 return CreateRectRgnIndirect(&client_rect
);
127 /*****************************************************************************
128 * IDirectDrawClipper::GetClipList
130 * Retrieve a copy of the clip list
133 * rect: Rectangle to be used to clip the clip list or NULL for the
135 * clip_list: structure for the resulting copy of the clip list.
136 * If NULL, fills Size up to the number of bytes necessary to hold
138 * clip_list_size: Size of resulting clip list; size of the buffer at clip_list
139 * or, if clip_list is NULL, receives the required size of the buffer
143 * Either DD_OK or DDERR_*
144 ************************************************************************/
145 static HRESULT WINAPI
ddraw_clipper_GetClipList(IDirectDrawClipper
*iface
, RECT
*rect
,
146 RGNDATA
*clip_list
, DWORD
*clip_list_size
)
148 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
151 TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n",
152 iface
, wine_dbgstr_rect(rect
), clip_list
, clip_list_size
);
154 wined3d_mutex_lock();
158 if (!(region
= get_window_region(clipper
->window
)))
160 wined3d_mutex_unlock();
161 WARN("Failed to get window region.\n");
167 if (!(region
= clipper
->region
))
169 wined3d_mutex_unlock();
170 WARN("No clip list set.\n");
171 return DDERR_NOCLIPLIST
;
179 if (!(clip_region
= CreateRectRgnIndirect(rect
)))
181 wined3d_mutex_unlock();
182 ERR("Failed to create region.\n");
184 DeleteObject(region
);
188 if (CombineRgn(clip_region
, region
, clip_region
, RGN_AND
) == ERROR
)
190 wined3d_mutex_unlock();
191 ERR("Failed to combine regions.\n");
192 DeleteObject(clip_region
);
194 DeleteObject(region
);
199 DeleteObject(region
);
200 region
= clip_region
;
203 *clip_list_size
= GetRegionData(region
, *clip_list_size
, clip_list
);
204 if (rect
|| clipper
->window
)
205 DeleteObject(region
);
207 wined3d_mutex_unlock();
211 /*****************************************************************************
212 * IDirectDrawClipper::SetClipList
214 * Sets or deletes (if region is NULL) the clip list
216 * This implementation is a stub and returns DD_OK always to make the app
220 * region Pointer to a LRGNDATA structure or NULL
221 * flags not used, must be 0
223 * Either DD_OK or DDERR_*
224 *****************************************************************************/
225 static HRESULT WINAPI
ddraw_clipper_SetClipList(IDirectDrawClipper
*iface
, RGNDATA
*region
, DWORD flags
)
227 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
229 TRACE("iface %p, region %p, flags %#x.\n", iface
, region
, flags
);
231 wined3d_mutex_lock();
235 wined3d_mutex_unlock();
236 return DDERR_CLIPPERISUSINGHWND
;
240 DeleteObject(clipper
->region
);
242 clipper
->region
= NULL
;
243 else if (!(clipper
->region
= ExtCreateRegion(NULL
, 0, region
)))
245 wined3d_mutex_unlock();
246 ERR("Failed to create region.\n");
250 wined3d_mutex_unlock();
255 static HRESULT WINAPI
ddraw_clipper_GetHWnd(IDirectDrawClipper
*iface
, HWND
*window
)
257 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
259 TRACE("iface %p, window %p.\n", iface
, window
);
261 wined3d_mutex_lock();
262 *window
= clipper
->window
;
263 wined3d_mutex_unlock();
268 static HRESULT WINAPI
ddraw_clipper_Initialize(IDirectDrawClipper
*iface
,
269 IDirectDraw
*ddraw
, DWORD flags
)
271 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
273 TRACE("iface %p, ddraw %p, flags %#x.\n", iface
, ddraw
, flags
);
275 wined3d_mutex_lock();
276 if (clipper
->initialized
)
278 wined3d_mutex_unlock();
279 return DDERR_ALREADYINITIALIZED
;
282 clipper
->initialized
= TRUE
;
283 wined3d_mutex_unlock();
288 static HRESULT WINAPI
ddraw_clipper_IsClipListChanged(IDirectDrawClipper
*iface
, BOOL
*changed
)
290 FIXME("iface %p, changed %p stub!\n", iface
, changed
);
292 /* XXX What is safest? */
298 static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl
=
300 ddraw_clipper_QueryInterface
,
301 ddraw_clipper_AddRef
,
302 ddraw_clipper_Release
,
303 ddraw_clipper_GetClipList
,
304 ddraw_clipper_GetHWnd
,
305 ddraw_clipper_Initialize
,
306 ddraw_clipper_IsClipListChanged
,
307 ddraw_clipper_SetClipList
,
308 ddraw_clipper_SetHWnd
,
311 HRESULT
ddraw_clipper_init(struct ddraw_clipper
*clipper
)
313 clipper
->IDirectDrawClipper_iface
.lpVtbl
= &ddraw_clipper_vtbl
;
319 struct ddraw_clipper
*unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper
*iface
)
323 assert(iface
->lpVtbl
== &ddraw_clipper_vtbl
);
325 return impl_from_IDirectDrawClipper(iface
);