wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / ddraw / clipper.c
blob760b22d303b57baf7e7d2e8f29d861f93ceca858
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);
42 return FALSE;
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);
48 return FALSE;
51 return TRUE;
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;
68 return S_OK;
71 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
72 *object = NULL;
74 return E_NOINTERFACE;
77 static ULONG WINAPI ddraw_clipper_AddRef(IDirectDrawClipper *iface)
79 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
80 ULONG refcount;
82 if (!ddraw_clipper_is_valid(clipper))
84 WARN("Invalid clipper, returning 0.\n");
85 return 0;
88 refcount = InterlockedIncrement(&clipper->ref);
89 TRACE("%p increasing refcount to %u.\n", clipper, refcount);
90 return refcount;
93 static ULONG WINAPI ddraw_clipper_Release(IDirectDrawClipper *iface)
95 struct ddraw_clipper *clipper = impl_from_IDirectDrawClipper(iface);
96 ULONG refcount;
98 if (!ddraw_clipper_is_valid(clipper))
100 WARN("Invalid clipper, returning 0.\n");
101 return 0;
104 refcount = InterlockedDecrement(&clipper->ref);
106 TRACE("%p decreasing refcount to %u.\n", clipper, refcount);
108 if (!refcount)
110 if (clipper->region)
111 DeleteObject(clipper->region);
112 clipper->IDirectDrawClipper_iface.lpVtbl = NULL; /* Should help with detecting freed clippers. */
113 heap_free(clipper);
116 return refcount;
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;
128 if (flags)
130 FIXME("flags %#x, not supported.\n", flags);
131 return DDERR_INVALIDPARAMS;
134 wined3d_mutex_lock();
135 clipper->window = window;
136 wined3d_mutex_unlock();
138 return DD_OK;
141 static HRGN get_window_region(HWND window)
143 POINT origin;
144 HRGN rgn;
145 HDC dc;
147 if (!(dc = GetDC(window)))
149 WARN("Failed to get dc.\n");
150 return NULL;
153 if (!(rgn = CreateRectRgn(0, 0, 0, 0)))
155 ERR("Failed to create region.\n");
156 ReleaseDC(window, dc);
157 return NULL;
160 if (GetRandomRgn(dc, rgn, SYSRGN) != 1)
162 ERR("Failed to get window region.\n");
163 DeleteObject(rgn);
164 ReleaseDC(window, dc);
165 return NULL;
168 if (GetVersion() & 0x80000000)
170 GetDCOrgEx(dc, &origin);
171 OffsetRgn(rgn, origin.x, origin.y);
174 ReleaseDC(window, dc);
175 return rgn;
178 /*****************************************************************************
179 * IDirectDrawClipper::GetClipList
181 * Retrieve a copy of the clip list
183 * Arguments:
184 * rect: Rectangle to be used to clip the clip list or NULL for the
185 * entire clip list.
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
188 * the entire clip.
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
191 * in bytes.
193 * RETURNS
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);
200 HRGN region;
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();
210 if (clipper->window)
212 if (!(region = get_window_region(clipper->window)))
214 wined3d_mutex_unlock();
215 WARN("Failed to get window region.\n");
216 return E_FAIL;
219 else
221 if (!(region = clipper->region))
223 wined3d_mutex_unlock();
224 WARN("No clip list set.\n");
225 return DDERR_NOCLIPLIST;
229 if (rect)
231 HRGN clip_region;
233 if (!(clip_region = CreateRectRgnIndirect(rect)))
235 wined3d_mutex_unlock();
236 ERR("Failed to create region.\n");
237 if (clipper->window)
238 DeleteObject(region);
239 return E_FAIL;
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);
247 if (clipper->window)
248 DeleteObject(region);
249 return E_FAIL;
252 if (clipper->window)
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();
262 return DD_OK;
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
271 * happy.
273 * PARAMS
274 * region Pointer to a LRGNDATA structure or NULL
275 * flags not used, must be 0
276 * RETURNS
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();
290 if (clipper->window)
292 wined3d_mutex_unlock();
293 return DDERR_CLIPPERISUSINGHWND;
296 if (clipper->region)
297 DeleteObject(clipper->region);
298 if (!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");
304 return E_FAIL;
307 wined3d_mutex_unlock();
309 return DD_OK;
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();
325 return DD_OK;
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();
348 return DD_OK;
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? */
361 *changed = FALSE;
363 return DD_OK;
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;
382 clipper->ref = 1;
384 return DD_OK;
387 struct ddraw_clipper *unsafe_impl_from_IDirectDrawClipper(IDirectDrawClipper *iface)
389 if (!iface)
390 return NULL;
391 assert(iface->lpVtbl == &ddraw_clipper_vtbl);
393 return impl_from_IDirectDrawClipper(iface);