ReactOS 0.4.17-dev-966-gf06eace
clipper.c
Go to the documentation of this file.
1/* DirectDrawClipper implementation
2 *
3 * Copyright 2000 (c) Marcus Meissner
4 * Copyright 2000 (c) TransGaming Technologies Inc.
5 * Copyright 2006 (c) Stefan Dösinger
6 *
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.
11 *
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.
16 *
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
20 */
21
22#include "ddraw_private.h"
23
25
26static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl;
27
28static inline struct ddraw_clipper *impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
29{
31}
32
34{
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. */
38
39 if (IsBadReadPtr(clipper, sizeof(*clipper)))
40 {
41 WARN("The application gave us an invalid clipper pointer %p.\n", clipper);
42 return FALSE;
43 }
44 if (clipper->IDirectDrawClipper_iface.lpVtbl != &ddraw_clipper_vtbl)
45 {
46 WARN("The clipper vtable is modified: %p, expected %p.\n",
48 return FALSE;
49 }
50
51 return TRUE;
52}
53
54static HRESULT WINAPI ddraw_clipper_QueryInterface(IDirectDrawClipper *iface, REFIID iid, void **object)
55{
56 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
57
58 TRACE("iface %p, iid %s, object %p.\n", iface, debugstr_guid(iid), object);
59
60 if (!ddraw_clipper_is_valid(clipper))
62
63 if (IsEqualGUID(&IID_IDirectDrawClipper, iid)
64 || IsEqualGUID(&IID_IUnknown, iid))
65 {
66 IDirectDrawClipper_AddRef(&clipper->IDirectDrawClipper_iface);
67 *object = &clipper->IDirectDrawClipper_iface;
68 return S_OK;
69 }
70
71 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
72 *object = NULL;
73
74 return E_NOINTERFACE;
75}
76
77static ULONG WINAPI ddraw_clipper_AddRef(IDirectDrawClipper *iface)
78{
79 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
80 ULONG refcount;
81
82 if (!ddraw_clipper_is_valid(clipper))
83 {
84 WARN("Invalid clipper, returning 0.\n");
85 return 0;
86 }
87
88 refcount = InterlockedIncrement(&clipper->ref);
89 TRACE("%p increasing refcount to %lu.\n", clipper, refcount);
90 return refcount;
91}
92
93static ULONG WINAPI ddraw_clipper_Release(IDirectDrawClipper *iface)
94{
95 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
96 ULONG refcount;
97
98 if (!ddraw_clipper_is_valid(clipper))
99 {
100 WARN("Invalid clipper, returning 0.\n");
101 return 0;
102 }
103
104 refcount = InterlockedDecrement(&clipper->ref);
105
106 TRACE("%p decreasing refcount to %lu.\n", clipper, refcount);
107
108 if (!refcount)
109 {
110 if (clipper->region)
111 DeleteObject(clipper->region);
112 /* make sure the object is no longer considered valid */
114 sizeof(clipper->IDirectDrawClipper_iface.lpVtbl) );
115 free(clipper);
116 }
117
118 return refcount;
119}
120
121static HRESULT WINAPI ddraw_clipper_SetHWnd(IDirectDrawClipper *iface, DWORD flags, HWND window)
122{
123 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
124
125 TRACE("iface %p, flags %#lx, window %p.\n", iface, flags, window);
126
127 if (!ddraw_clipper_is_valid(clipper))
128 return DDERR_INVALIDPARAMS;
129
130 if (flags)
131 {
132 FIXME("flags %#lx, not supported.\n", flags);
133 return DDERR_INVALIDPARAMS;
134 }
135
137 clipper->window = window;
139
140 return DD_OK;
141}
142
144{
146 HRGN rgn;
147 HDC dc;
148
149 if (!(dc = GetDC(window)))
150 {
151 WARN("Failed to get dc.\n");
152 return NULL;
153 }
154
155 if (!(rgn = CreateRectRgn(0, 0, 0, 0)))
156 {
157 ERR("Failed to create region.\n");
159 return NULL;
160 }
161
162 if (GetRandomRgn(dc, rgn, SYSRGN) != 1)
163 {
164 ERR("Failed to get window region.\n");
165 DeleteObject(rgn);
167 return NULL;
168 }
169
170 if (GetVersion() & 0x80000000)
171 {
173 OffsetRgn(rgn, origin.x, origin.y);
174 }
175
177 return rgn;
178}
179
180/*****************************************************************************
181 * IDirectDrawClipper::GetClipList
182 *
183 * Retrieve a copy of the clip list
184 *
185 * Arguments:
186 * rect: Rectangle to be used to clip the clip list or NULL for the
187 * entire clip list.
188 * clip_list: structure for the resulting copy of the clip list.
189 * If NULL, fills Size up to the number of bytes necessary to hold
190 * the entire clip.
191 * clip_list_size: Size of resulting clip list; size of the buffer at clip_list
192 * or, if clip_list is NULL, receives the required size of the buffer
193 * in bytes.
194 *
195 * RETURNS
196 * Either DD_OK or DDERR_*
197 ************************************************************************/
198static HRESULT WINAPI ddraw_clipper_GetClipList(IDirectDrawClipper *iface, RECT *rect,
199 RGNDATA *clip_list, DWORD *clip_list_size)
200{
201 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
202 HRGN region;
203
204 TRACE("iface %p, rect %s, clip_list %p, clip_list_size %p.\n",
205 iface, wine_dbgstr_rect(rect), clip_list, clip_list_size);
206
207 if (!ddraw_clipper_is_valid(clipper))
208 return DDERR_INVALIDPARAMS;
209
211
212 if (clipper->window)
213 {
214 if (!(region = get_window_region(clipper->window)))
215 {
217 WARN("Failed to get window region.\n");
218 return E_FAIL;
219 }
220 }
221 else
222 {
223 if (!(region = clipper->region))
224 {
226 WARN("No clip list set.\n");
227 return DDERR_NOCLIPLIST;
228 }
229 }
230
231 if (rect)
232 {
233 HRGN clip_region;
234
235 if (!(clip_region = CreateRectRgnIndirect(rect)))
236 {
238 ERR("Failed to create region.\n");
239 if (clipper->window)
241 return E_FAIL;
242 }
243
244 if (CombineRgn(clip_region, region, clip_region, RGN_AND) == ERROR)
245 {
247 ERR("Failed to combine regions.\n");
248 DeleteObject(clip_region);
249 if (clipper->window)
251 return E_FAIL;
252 }
253
254 if (clipper->window)
256 region = clip_region;
257 }
258
259 *clip_list_size = GetRegionData(region, *clip_list_size, clip_list);
260 if (rect || clipper->window)
262
264 return DD_OK;
265}
266
267/*****************************************************************************
268 * IDirectDrawClipper::SetClipList
269 *
270 * Sets or deletes (if region is NULL) the clip list
271 *
272 * This implementation is a stub and returns DD_OK always to make the app
273 * happy.
274 *
275 * PARAMS
276 * region Pointer to a LRGNDATA structure or NULL
277 * flags not used, must be 0
278 * RETURNS
279 * Either DD_OK or DDERR_*
280 *****************************************************************************/
282{
283 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
284
285 TRACE("iface %p, region %p, flags %#lx.\n", iface, region, flags);
286
287 if (!ddraw_clipper_is_valid(clipper))
288 return DDERR_INVALIDPARAMS;
289
291
292 if (clipper->window)
293 {
296 }
297
298 if (clipper->region)
299 DeleteObject(clipper->region);
300 if (!region)
301 clipper->region = NULL;
302 else if (!(clipper->region = ExtCreateRegion(NULL, 0, region)))
303 {
305 ERR("Failed to create region.\n");
306 return E_FAIL;
307 }
308
310
311 return DD_OK;
312}
313
314static HRESULT WINAPI ddraw_clipper_GetHWnd(IDirectDrawClipper *iface, HWND *window)
315{
316 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
317
318 TRACE("iface %p, window %p.\n", iface, window);
319
320 if (!ddraw_clipper_is_valid(clipper))
321 return DDERR_INVALIDPARAMS;
322
324 *window = clipper->window;
326
327 return DD_OK;
328}
329
330static HRESULT WINAPI ddraw_clipper_Initialize(IDirectDrawClipper *iface,
331 IDirectDraw *ddraw, DWORD flags)
332{
333 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
334
335 TRACE("iface %p, ddraw %p, flags %#lx.\n", iface, ddraw, flags);
336
337 if (!ddraw_clipper_is_valid(clipper))
338 return DDERR_INVALIDPARAMS;
339
341 if (clipper->initialized)
342 {
345 }
346
347 clipper->initialized = TRUE;
349
350 return DD_OK;
351}
352
353static HRESULT WINAPI ddraw_clipper_IsClipListChanged(IDirectDrawClipper *iface, BOOL *changed)
354{
355 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
356
357 FIXME("iface %p, changed %p stub!\n", iface, changed);
358
359 if (!ddraw_clipper_is_valid(clipper))
360 return DDERR_INVALIDPARAMS;
361
362 /* XXX What is safest? */
363 *changed = FALSE;
364
365 return DD_OK;
366}
367
368static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl =
369{
379};
380
382{
384 clipper->ref = 1;
385
386 return DD_OK;
387}
388
389struct ddraw_clipper *unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
390{
391 if (!iface)
392 return NULL;
393 assert(iface->lpVtbl == &ddraw_clipper_vtbl);
394
395 return impl_from_IDirectDrawClipper(iface);
396}
#define SYSRGN
Definition: GetRandomRgn.c:13
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
const GUID IID_IUnknown
RECT rect
Definition: combotst.c:67
HDC dc
Definition: cylfrac.c:34
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
static HRESULT WINAPI ddraw_clipper_GetHWnd(IDirectDrawClipper *iface, HWND *window)
Definition: clipper.c:314
static HRESULT WINAPI ddraw_clipper_GetClipList(IDirectDrawClipper *iface, RECT *rect, RGNDATA *clip_list, DWORD *clip_list_size)
Definition: clipper.c:198
static HRESULT WINAPI ddraw_clipper_IsClipListChanged(IDirectDrawClipper *iface, BOOL *changed)
Definition: clipper.c:353
static HRGN get_window_region(HWND window)
Definition: clipper.c:143
static HRESULT WINAPI ddraw_clipper_SetHWnd(IDirectDrawClipper *iface, DWORD flags, HWND window)
Definition: clipper.c:121
BOOL ddraw_clipper_is_valid(const struct ddraw_clipper *clipper)
Definition: clipper.c:33
HRESULT ddraw_clipper_init(struct ddraw_clipper *clipper)
Definition: clipper.c:381
static ULONG WINAPI ddraw_clipper_AddRef(IDirectDrawClipper *iface)
Definition: clipper.c:77
static ULONG WINAPI ddraw_clipper_Release(IDirectDrawClipper *iface)
Definition: clipper.c:93
struct ddraw_clipper * unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
Definition: clipper.c:389
static HRESULT WINAPI ddraw_clipper_SetClipList(IDirectDrawClipper *iface, RGNDATA *region, DWORD flags)
Definition: clipper.c:281
static const struct IDirectDrawClipperVtbl ddraw_clipper_vtbl
Definition: clipper.c:26
static struct ddraw_clipper * impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
Definition: clipper.c:28
static HRESULT WINAPI ddraw_clipper_Initialize(IDirectDrawClipper *iface, IDirectDraw *ddraw, DWORD flags)
Definition: clipper.c:330
static HRESULT WINAPI ddraw_clipper_QueryInterface(IDirectDrawClipper *iface, REFIID iid, void **object)
Definition: clipper.c:54
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:805
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
#define assert(_expr)
Definition: assert.h:32
#define ERROR(name)
Definition: error_private.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLbitfield flags
Definition: glext.h:7161
#define S_OK
Definition: intsafe.h:52
voidpf uLong int origin
Definition: ioapi.h:144
#define debugstr_guid
Definition: kernel32.h:35
static HDC
Definition: imagelist.c:88
static IHTMLWindow2 * window
Definition: events.c:77
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define REFIID
Definition: guiddef.h:118
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HDC WINAPI GetDC(_In_opt_ HWND)
#define DDERR_NOCLIPLIST
Definition: ddraw.h:89
#define DD_OK
Definition: ddraw.h:188
#define DDERR_INVALIDPARAMS
Definition: ddraw.h:81
#define DDERR_CLIPPERISUSINGHWND
Definition: ddraw.h:143
#define DDERR_ALREADYINITIALIZED
Definition: ddraw.h:69
#define TRACE(s)
Definition: solgame.cpp:4
Definition: dcommon.idl:28
IDirectDrawClipper IDirectDrawClipper_iface
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define SecureZeroMemory
Definition: winbase.h:1441
#define WINAPI
Definition: msvc.h:6
void WINAPI wined3d_mutex_unlock(void)
Definition: wined3d_main.c:544
void WINAPI wined3d_mutex_lock(void)
Definition: wined3d_main.c:539
#define E_NOINTERFACE
Definition: winerror.h:3479
HRGN WINAPI CreateRectRgn(_In_ int, _In_ int, _In_ int, _In_ int)
HRGN WINAPI ExtCreateRegion(_In_opt_ const XFORM *lpx, _In_ DWORD nCount, _In_reads_bytes_(nCount) const RGNDATA *lpData)
int WINAPI CombineRgn(_In_opt_ HRGN hrgnDest, _In_opt_ HRGN hrgnSrc1, _In_opt_ HRGN hrgnSrc2, _In_ int fnCombineMode)
#define RGN_AND
Definition: wingdi.h:356
int WINAPI OffsetRgn(_In_ HRGN, _In_ int, _In_ int)
int WINAPI GetRandomRgn(_In_ HDC, _In_ HRGN, _In_ INT)
DWORD WINAPI GetRegionData(_In_ HRGN hrgn, _In_ DWORD nCount, _Out_writes_bytes_to_opt_(nCount, return) LPRGNDATA lpRgnData)
HRGN WINAPI CreateRectRgnIndirect(_In_ LPCRECT)
BOOL WINAPI GetDCOrgEx(_In_ HDC, _Out_ LPPOINT)
Definition: coord.c:825