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
22 #include "ddraw_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
26 static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl
;
28 static inline struct ddraw_clipper
*impl_from_IDirectDrawClipper(IDirectDrawClipper
*iface
)
30 return CONTAINING_RECORD(iface
, struct ddraw_clipper
, IDirectDrawClipper_iface
);
33 BOOL
ddraw_clipper_is_valid(const struct ddraw_clipper
*clipper
)
35 /* Native is very lenient when you invoke the clipper methods with a clipper pointer that
36 * points to something that is either not accessible or not a clipper, or if you break
37 * a clipper after assigning it to a surface. Deus Ex: Goty depends on this. */
39 if (IsBadReadPtr(clipper
, sizeof(*clipper
)))
41 WARN("The application gave us an invalid clipper pointer %p.\n", clipper
);
44 if (clipper
->IDirectDrawClipper_iface
.lpVtbl
!= &ddraw_clipper_vtbl
)
46 WARN("The clipper vtable is modified: %p, expected %p.\n",
47 clipper
->IDirectDrawClipper_iface
.lpVtbl
, &ddraw_clipper_vtbl
);
54 static HRESULT WINAPI
ddraw_clipper_QueryInterface(IDirectDrawClipper
*iface
, REFIID iid
, void **object
)
56 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
58 TRACE("iface %p, iid %s, object %p.\n", iface
, debugstr_guid(iid
), object
);
60 if (!ddraw_clipper_is_valid(clipper
))
61 return DDERR_INVALIDPARAMS
;
63 if (IsEqualGUID(&IID_IDirectDrawClipper
, iid
)
64 || IsEqualGUID(&IID_IUnknown
, iid
))
66 IDirectDrawClipper_AddRef(&clipper
->IDirectDrawClipper_iface
);
67 *object
= &clipper
->IDirectDrawClipper_iface
;
71 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
77 static ULONG WINAPI
ddraw_clipper_AddRef(IDirectDrawClipper
*iface
)
79 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
82 if (!ddraw_clipper_is_valid(clipper
))
84 WARN("Invalid clipper, returning 0.\n");
88 refcount
= InterlockedIncrement(&clipper
->ref
);
89 TRACE("%p increasing refcount to %u.\n", clipper
, refcount
);
93 static ULONG WINAPI
ddraw_clipper_Release(IDirectDrawClipper
*iface
)
95 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
98 if (!ddraw_clipper_is_valid(clipper
))
100 WARN("Invalid clipper, returning 0.\n");
104 refcount
= InterlockedDecrement(&clipper
->ref
);
106 TRACE("%p decreasing refcount to %u.\n", clipper
, refcount
);
111 DeleteObject(clipper
->region
);
112 clipper
->IDirectDrawClipper_iface
.lpVtbl
= NULL
; /* Should help with detecting freed clippers. */
119 static HRESULT WINAPI
ddraw_clipper_SetHWnd(IDirectDrawClipper
*iface
, DWORD flags
, HWND window
)
121 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
123 TRACE("iface %p, flags %#x, window %p.\n", iface
, flags
, window
);
125 if (!ddraw_clipper_is_valid(clipper
))
126 return DDERR_INVALIDPARAMS
;
130 FIXME("flags %#x, not supported.\n", flags
);
131 return DDERR_INVALIDPARAMS
;
134 wined3d_mutex_lock();
135 clipper
->window
= window
;
136 wined3d_mutex_unlock();
141 static HRGN
get_window_region(HWND window
)
147 if (!(dc
= GetDC(window
)))
149 WARN("Failed to get dc.\n");
153 if (!(rgn
= CreateRectRgn(0, 0, 0, 0)))
155 ERR("Failed to create region.\n");
156 ReleaseDC(window
, dc
);
160 if (GetRandomRgn(dc
, rgn
, SYSRGN
) != 1)
162 ERR("Failed to get window region.\n");
164 ReleaseDC(window
, dc
);
168 if (GetVersion() & 0x80000000)
170 GetDCOrgEx(dc
, &origin
);
171 OffsetRgn(rgn
, origin
.x
, origin
.y
);
174 ReleaseDC(window
, dc
);
178 /*****************************************************************************
179 * IDirectDrawClipper::GetClipList
181 * Retrieve a copy of the clip list
184 * rect: Rectangle to be used to clip the clip list or NULL for the
186 * clip_list: structure for the resulting copy of the clip list.
187 * If NULL, fills Size up to the number of bytes necessary to hold
189 * clip_list_size: Size of resulting clip list; size of the buffer at clip_list
190 * or, if clip_list is NULL, receives the required size of the buffer
194 * Either DD_OK or DDERR_*
195 ************************************************************************/
196 static HRESULT WINAPI
ddraw_clipper_GetClipList(IDirectDrawClipper
*iface
, RECT
*rect
,
197 RGNDATA
*clip_list
, DWORD
*clip_list_size
)
199 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
202 TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n",
203 iface
, wine_dbgstr_rect(rect
), clip_list
, clip_list_size
);
205 if (!ddraw_clipper_is_valid(clipper
))
206 return DDERR_INVALIDPARAMS
;
208 wined3d_mutex_lock();
212 if (!(region
= get_window_region(clipper
->window
)))
214 wined3d_mutex_unlock();
215 WARN("Failed to get window region.\n");
221 if (!(region
= clipper
->region
))
223 wined3d_mutex_unlock();
224 WARN("No clip list set.\n");
225 return DDERR_NOCLIPLIST
;
233 if (!(clip_region
= CreateRectRgnIndirect(rect
)))
235 wined3d_mutex_unlock();
236 ERR("Failed to create region.\n");
238 DeleteObject(region
);
242 if (CombineRgn(clip_region
, region
, clip_region
, RGN_AND
) == ERROR
)
244 wined3d_mutex_unlock();
245 ERR("Failed to combine regions.\n");
246 DeleteObject(clip_region
);
248 DeleteObject(region
);
253 DeleteObject(region
);
254 region
= clip_region
;
257 *clip_list_size
= GetRegionData(region
, *clip_list_size
, clip_list
);
258 if (rect
|| clipper
->window
)
259 DeleteObject(region
);
261 wined3d_mutex_unlock();
265 /*****************************************************************************
266 * IDirectDrawClipper::SetClipList
268 * Sets or deletes (if region is NULL) the clip list
270 * This implementation is a stub and returns DD_OK always to make the app
274 * region Pointer to a LRGNDATA structure or NULL
275 * flags not used, must be 0
277 * Either DD_OK or DDERR_*
278 *****************************************************************************/
279 static HRESULT WINAPI
ddraw_clipper_SetClipList(IDirectDrawClipper
*iface
, RGNDATA
*region
, DWORD flags
)
281 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
283 TRACE("iface %p, region %p, flags %#x.\n", iface
, region
, flags
);
285 if (!ddraw_clipper_is_valid(clipper
))
286 return DDERR_INVALIDPARAMS
;
288 wined3d_mutex_lock();
292 wined3d_mutex_unlock();
293 return DDERR_CLIPPERISUSINGHWND
;
297 DeleteObject(clipper
->region
);
299 clipper
->region
= NULL
;
300 else if (!(clipper
->region
= ExtCreateRegion(NULL
, 0, region
)))
302 wined3d_mutex_unlock();
303 ERR("Failed to create region.\n");
307 wined3d_mutex_unlock();
312 static HRESULT WINAPI
ddraw_clipper_GetHWnd(IDirectDrawClipper
*iface
, HWND
*window
)
314 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
316 TRACE("iface %p, window %p.\n", iface
, window
);
318 if (!ddraw_clipper_is_valid(clipper
))
319 return DDERR_INVALIDPARAMS
;
321 wined3d_mutex_lock();
322 *window
= clipper
->window
;
323 wined3d_mutex_unlock();
328 static HRESULT WINAPI
ddraw_clipper_Initialize(IDirectDrawClipper
*iface
,
329 IDirectDraw
*ddraw
, DWORD flags
)
331 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
333 TRACE("iface %p, ddraw %p, flags %#x.\n", iface
, ddraw
, flags
);
335 if (!ddraw_clipper_is_valid(clipper
))
336 return DDERR_INVALIDPARAMS
;
338 wined3d_mutex_lock();
339 if (clipper
->initialized
)
341 wined3d_mutex_unlock();
342 return DDERR_ALREADYINITIALIZED
;
345 clipper
->initialized
= TRUE
;
346 wined3d_mutex_unlock();
351 static HRESULT WINAPI
ddraw_clipper_IsClipListChanged(IDirectDrawClipper
*iface
, BOOL
*changed
)
353 struct ddraw_clipper
*clipper
= impl_from_IDirectDrawClipper(iface
);
355 FIXME("iface %p, changed %p stub!\n", iface
, changed
);
357 if (!ddraw_clipper_is_valid(clipper
))
358 return DDERR_INVALIDPARAMS
;
360 /* XXX What is safest? */
366 static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl
=
368 ddraw_clipper_QueryInterface
,
369 ddraw_clipper_AddRef
,
370 ddraw_clipper_Release
,
371 ddraw_clipper_GetClipList
,
372 ddraw_clipper_GetHWnd
,
373 ddraw_clipper_Initialize
,
374 ddraw_clipper_IsClipListChanged
,
375 ddraw_clipper_SetClipList
,
376 ddraw_clipper_SetHWnd
,
379 HRESULT
ddraw_clipper_init(struct ddraw_clipper
*clipper
)
381 clipper
->IDirectDrawClipper_iface
.lpVtbl
= &ddraw_clipper_vtbl
;
387 struct ddraw_clipper
*unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper
*iface
)
391 assert(iface
->lpVtbl
== &ddraw_clipper_vtbl
);
393 return impl_from_IDirectDrawClipper(iface
);