1c2c66affSColin Finck /*
2c2c66affSColin Finck * IDirect3DSurface9 implementation
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2002-2005 Jason Edmeades
5c2c66affSColin Finck * Raphael Junqueira
6c2c66affSColin Finck *
7c2c66affSColin Finck * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck * License as published by the Free Software Foundation; either
10c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck *
12c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15c2c66affSColin Finck * Lesser General Public License for more details.
16c2c66affSColin Finck *
17c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck */
21c2c66affSColin Finck
22*9987f029SAmine Khaldi #include "config.h"
23c2c66affSColin Finck #include "d3d9_private.h"
24c2c66affSColin Finck
25*9987f029SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
26*9987f029SAmine Khaldi
impl_from_IDirect3DSurface9(IDirect3DSurface9 * iface)27c2c66affSColin Finck static inline struct d3d9_surface *impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
28c2c66affSColin Finck {
29c2c66affSColin Finck return CONTAINING_RECORD(iface, struct d3d9_surface, IDirect3DSurface9_iface);
30c2c66affSColin Finck }
31c2c66affSColin Finck
d3d9_surface_QueryInterface(IDirect3DSurface9 * iface,REFIID riid,void ** out)32c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_QueryInterface(IDirect3DSurface9 *iface, REFIID riid, void **out)
33c2c66affSColin Finck {
34c2c66affSColin Finck TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
35c2c66affSColin Finck
36c2c66affSColin Finck if (IsEqualGUID(riid, &IID_IDirect3DSurface9)
37c2c66affSColin Finck || IsEqualGUID(riid, &IID_IDirect3DResource9)
38c2c66affSColin Finck || IsEqualGUID(riid, &IID_IUnknown))
39c2c66affSColin Finck {
40c2c66affSColin Finck IDirect3DSurface9_AddRef(iface);
41c2c66affSColin Finck *out = iface;
42c2c66affSColin Finck return S_OK;
43c2c66affSColin Finck }
44c2c66affSColin Finck
45c2c66affSColin Finck WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
46c2c66affSColin Finck
47c2c66affSColin Finck *out = NULL;
48c2c66affSColin Finck return E_NOINTERFACE;
49c2c66affSColin Finck }
50c2c66affSColin Finck
d3d9_surface_AddRef(IDirect3DSurface9 * iface)51c2c66affSColin Finck static ULONG WINAPI d3d9_surface_AddRef(IDirect3DSurface9 *iface)
52c2c66affSColin Finck {
53c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
54c2c66affSColin Finck ULONG refcount;
55c2c66affSColin Finck
56c2c66affSColin Finck TRACE("iface %p.\n", iface);
57c2c66affSColin Finck
58c2c66affSColin Finck if (surface->texture)
59c2c66affSColin Finck {
60c2c66affSColin Finck TRACE("Forwarding to %p.\n", surface->texture);
61c2c66affSColin Finck return IDirect3DBaseTexture9_AddRef(&surface->texture->IDirect3DBaseTexture9_iface);
62c2c66affSColin Finck }
63c2c66affSColin Finck
64c2c66affSColin Finck refcount = InterlockedIncrement(&surface->resource.refcount);
65c2c66affSColin Finck TRACE("%p increasing refcount to %u.\n", iface, refcount);
66c2c66affSColin Finck
67c2c66affSColin Finck if (refcount == 1)
68c2c66affSColin Finck {
69c2c66affSColin Finck if (surface->parent_device)
70c2c66affSColin Finck IDirect3DDevice9Ex_AddRef(surface->parent_device);
71c2c66affSColin Finck wined3d_mutex_lock();
72c2c66affSColin Finck if (surface->wined3d_rtv)
73c2c66affSColin Finck wined3d_rendertarget_view_incref(surface->wined3d_rtv);
74c2c66affSColin Finck wined3d_texture_incref(surface->wined3d_texture);
75c2c66affSColin Finck wined3d_mutex_unlock();
76c2c66affSColin Finck }
77c2c66affSColin Finck
78c2c66affSColin Finck return refcount;
79c2c66affSColin Finck }
80c2c66affSColin Finck
d3d9_surface_Release(IDirect3DSurface9 * iface)81c2c66affSColin Finck static ULONG WINAPI d3d9_surface_Release(IDirect3DSurface9 *iface)
82c2c66affSColin Finck {
83c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
84c2c66affSColin Finck ULONG refcount;
85c2c66affSColin Finck
86c2c66affSColin Finck TRACE("iface %p.\n", iface);
87c2c66affSColin Finck
88c2c66affSColin Finck if (surface->texture)
89c2c66affSColin Finck {
90c2c66affSColin Finck TRACE("Forwarding to %p.\n", surface->texture);
91c2c66affSColin Finck return IDirect3DBaseTexture9_Release(&surface->texture->IDirect3DBaseTexture9_iface);
92c2c66affSColin Finck }
93c2c66affSColin Finck
94c2c66affSColin Finck if (!surface->resource.refcount)
95c2c66affSColin Finck {
96c2c66affSColin Finck WARN("Surface does not have any references.\n");
97c2c66affSColin Finck return 0;
98c2c66affSColin Finck }
99c2c66affSColin Finck
100c2c66affSColin Finck refcount = InterlockedDecrement(&surface->resource.refcount);
101c2c66affSColin Finck TRACE("%p decreasing refcount to %u.\n", iface, refcount);
102c2c66affSColin Finck
103c2c66affSColin Finck if (!refcount)
104c2c66affSColin Finck {
105c2c66affSColin Finck IDirect3DDevice9Ex *parent_device = surface->parent_device;
106c2c66affSColin Finck
107c2c66affSColin Finck wined3d_mutex_lock();
108c2c66affSColin Finck if (surface->wined3d_rtv)
109c2c66affSColin Finck wined3d_rendertarget_view_decref(surface->wined3d_rtv);
110c2c66affSColin Finck wined3d_texture_decref(surface->wined3d_texture);
111c2c66affSColin Finck wined3d_mutex_unlock();
112c2c66affSColin Finck
113c2c66affSColin Finck /* Release the device last, as it may cause the device to be destroyed. */
114c2c66affSColin Finck if (parent_device)
115c2c66affSColin Finck IDirect3DDevice9Ex_Release(parent_device);
116c2c66affSColin Finck }
117c2c66affSColin Finck
118c2c66affSColin Finck return refcount;
119c2c66affSColin Finck }
120c2c66affSColin Finck
d3d9_surface_GetDevice(IDirect3DSurface9 * iface,IDirect3DDevice9 ** device)121c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_GetDevice(IDirect3DSurface9 *iface, IDirect3DDevice9 **device)
122c2c66affSColin Finck {
123c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
124c2c66affSColin Finck
125c2c66affSColin Finck TRACE("iface %p, device %p.\n", iface, device);
126c2c66affSColin Finck
127c2c66affSColin Finck if (surface->texture)
128c2c66affSColin Finck return IDirect3DBaseTexture9_GetDevice(&surface->texture->IDirect3DBaseTexture9_iface, device);
129c2c66affSColin Finck
130c2c66affSColin Finck *device = (IDirect3DDevice9 *)surface->parent_device;
131c2c66affSColin Finck IDirect3DDevice9_AddRef(*device);
132c2c66affSColin Finck
133c2c66affSColin Finck TRACE("Returning device %p.\n", *device);
134c2c66affSColin Finck
135c2c66affSColin Finck return D3D_OK;
136c2c66affSColin Finck }
137c2c66affSColin Finck
d3d9_surface_SetPrivateData(IDirect3DSurface9 * iface,REFGUID guid,const void * data,DWORD data_size,DWORD flags)138c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_SetPrivateData(IDirect3DSurface9 *iface, REFGUID guid,
139c2c66affSColin Finck const void *data, DWORD data_size, DWORD flags)
140c2c66affSColin Finck {
141c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
142c2c66affSColin Finck TRACE("iface %p, guid %s, data %p, data_size %u, flags %#x.\n",
143c2c66affSColin Finck iface, debugstr_guid(guid), data, data_size, flags);
144c2c66affSColin Finck
145c2c66affSColin Finck return d3d9_resource_set_private_data(&surface->resource, guid, data, data_size, flags);
146c2c66affSColin Finck }
147c2c66affSColin Finck
d3d9_surface_GetPrivateData(IDirect3DSurface9 * iface,REFGUID guid,void * data,DWORD * data_size)148c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_GetPrivateData(IDirect3DSurface9 *iface, REFGUID guid,
149c2c66affSColin Finck void *data, DWORD *data_size)
150c2c66affSColin Finck {
151c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
152c2c66affSColin Finck TRACE("iface %p, guid %s, data %p, data_size %p.\n",
153c2c66affSColin Finck iface, debugstr_guid(guid), data, data_size);
154c2c66affSColin Finck
155c2c66affSColin Finck return d3d9_resource_get_private_data(&surface->resource, guid, data, data_size);
156c2c66affSColin Finck }
157c2c66affSColin Finck
d3d9_surface_FreePrivateData(IDirect3DSurface9 * iface,REFGUID guid)158c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_FreePrivateData(IDirect3DSurface9 *iface, REFGUID guid)
159c2c66affSColin Finck {
160c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
161c2c66affSColin Finck TRACE("iface %p, guid %s.\n", iface, debugstr_guid(guid));
162c2c66affSColin Finck
163c2c66affSColin Finck return d3d9_resource_free_private_data(&surface->resource, guid);
164c2c66affSColin Finck }
165c2c66affSColin Finck
d3d9_surface_SetPriority(IDirect3DSurface9 * iface,DWORD priority)166c2c66affSColin Finck static DWORD WINAPI d3d9_surface_SetPriority(IDirect3DSurface9 *iface, DWORD priority)
167c2c66affSColin Finck {
168c2c66affSColin Finck TRACE("iface %p, priority %u. Ignored on surfaces.\n", iface, priority);
169c2c66affSColin Finck return 0;
170c2c66affSColin Finck }
171c2c66affSColin Finck
d3d9_surface_GetPriority(IDirect3DSurface9 * iface)172c2c66affSColin Finck static DWORD WINAPI d3d9_surface_GetPriority(IDirect3DSurface9 *iface)
173c2c66affSColin Finck {
174c2c66affSColin Finck TRACE("iface %p. Ignored on surfaces.\n", iface);
175c2c66affSColin Finck return 0;
176c2c66affSColin Finck }
177c2c66affSColin Finck
d3d9_surface_PreLoad(IDirect3DSurface9 * iface)178c2c66affSColin Finck static void WINAPI d3d9_surface_PreLoad(IDirect3DSurface9 *iface)
179c2c66affSColin Finck {
180c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
181c2c66affSColin Finck
182c2c66affSColin Finck TRACE("iface %p.\n", iface);
183c2c66affSColin Finck
184c2c66affSColin Finck wined3d_mutex_lock();
185c2c66affSColin Finck wined3d_resource_preload(wined3d_texture_get_resource(surface->wined3d_texture));
186c2c66affSColin Finck wined3d_mutex_unlock();
187c2c66affSColin Finck }
188c2c66affSColin Finck
d3d9_surface_GetType(IDirect3DSurface9 * iface)189c2c66affSColin Finck static D3DRESOURCETYPE WINAPI d3d9_surface_GetType(IDirect3DSurface9 *iface)
190c2c66affSColin Finck {
191c2c66affSColin Finck TRACE("iface %p.\n", iface);
192c2c66affSColin Finck
193c2c66affSColin Finck return D3DRTYPE_SURFACE;
194c2c66affSColin Finck }
195c2c66affSColin Finck
d3d9_surface_GetContainer(IDirect3DSurface9 * iface,REFIID riid,void ** container)196c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_GetContainer(IDirect3DSurface9 *iface, REFIID riid, void **container)
197c2c66affSColin Finck {
198c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
199c2c66affSColin Finck HRESULT hr;
200c2c66affSColin Finck
201c2c66affSColin Finck TRACE("iface %p, riid %s, container %p.\n", iface, debugstr_guid(riid), container);
202c2c66affSColin Finck
203c2c66affSColin Finck if (!surface->container)
204c2c66affSColin Finck return E_NOINTERFACE;
205c2c66affSColin Finck
206c2c66affSColin Finck hr = IUnknown_QueryInterface(surface->container, riid, container);
207c2c66affSColin Finck
208c2c66affSColin Finck TRACE("Returning %p.\n", *container);
209c2c66affSColin Finck
210c2c66affSColin Finck return hr;
211c2c66affSColin Finck }
212c2c66affSColin Finck
d3d9_surface_GetDesc(IDirect3DSurface9 * iface,D3DSURFACE_DESC * desc)213c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_GetDesc(IDirect3DSurface9 *iface, D3DSURFACE_DESC *desc)
214c2c66affSColin Finck {
215c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
216c2c66affSColin Finck struct wined3d_sub_resource_desc wined3d_desc;
217c2c66affSColin Finck
218c2c66affSColin Finck TRACE("iface %p, desc %p.\n", iface, desc);
219c2c66affSColin Finck
220c2c66affSColin Finck wined3d_mutex_lock();
221c2c66affSColin Finck wined3d_texture_get_sub_resource_desc(surface->wined3d_texture, surface->sub_resource_idx, &wined3d_desc);
222c2c66affSColin Finck wined3d_mutex_unlock();
223c2c66affSColin Finck
224c2c66affSColin Finck desc->Format = d3dformat_from_wined3dformat(wined3d_desc.format);
225c2c66affSColin Finck desc->Type = D3DRTYPE_SURFACE;
226*9987f029SAmine Khaldi desc->Usage = d3dusage_from_wined3dusage(wined3d_desc.usage);
227*9987f029SAmine Khaldi desc->Pool = d3dpool_from_wined3daccess(wined3d_desc.access, wined3d_desc.usage);
228c2c66affSColin Finck desc->MultiSampleType = wined3d_desc.multisample_type;
229c2c66affSColin Finck desc->MultiSampleQuality = wined3d_desc.multisample_quality;
230c2c66affSColin Finck desc->Width = wined3d_desc.width;
231c2c66affSColin Finck desc->Height = wined3d_desc.height;
232c2c66affSColin Finck
233c2c66affSColin Finck return D3D_OK;
234c2c66affSColin Finck }
235c2c66affSColin Finck
d3d9_surface_LockRect(IDirect3DSurface9 * iface,D3DLOCKED_RECT * locked_rect,const RECT * rect,DWORD flags)236c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_LockRect(IDirect3DSurface9 *iface,
237c2c66affSColin Finck D3DLOCKED_RECT *locked_rect, const RECT *rect, DWORD flags)
238c2c66affSColin Finck {
239c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
240c2c66affSColin Finck struct wined3d_box box;
241c2c66affSColin Finck struct wined3d_map_desc map_desc;
242c2c66affSColin Finck HRESULT hr;
243c2c66affSColin Finck
244c2c66affSColin Finck TRACE("iface %p, locked_rect %p, rect %s, flags %#x.\n",
245c2c66affSColin Finck iface, locked_rect, wine_dbgstr_rect(rect), flags);
246c2c66affSColin Finck
247c2c66affSColin Finck if (rect)
248c2c66affSColin Finck wined3d_box_set(&box, rect->left, rect->top, rect->right, rect->bottom, 0, 1);
249c2c66affSColin Finck
250c2c66affSColin Finck wined3d_mutex_lock();
251c2c66affSColin Finck hr = wined3d_resource_map(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx,
252*9987f029SAmine Khaldi &map_desc, rect ? &box : NULL, wined3dmapflags_from_d3dmapflags(flags));
253c2c66affSColin Finck wined3d_mutex_unlock();
254c2c66affSColin Finck
255c2c66affSColin Finck if (SUCCEEDED(hr))
256c2c66affSColin Finck {
257c2c66affSColin Finck locked_rect->Pitch = map_desc.row_pitch;
258c2c66affSColin Finck locked_rect->pBits = map_desc.data;
259c2c66affSColin Finck }
260c2c66affSColin Finck
261c2c66affSColin Finck return hr;
262c2c66affSColin Finck }
263c2c66affSColin Finck
d3d9_surface_UnlockRect(IDirect3DSurface9 * iface)264c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_UnlockRect(IDirect3DSurface9 *iface)
265c2c66affSColin Finck {
266c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
267c2c66affSColin Finck HRESULT hr;
268c2c66affSColin Finck
269c2c66affSColin Finck TRACE("iface %p.\n", iface);
270c2c66affSColin Finck
271c2c66affSColin Finck wined3d_mutex_lock();
272c2c66affSColin Finck hr = wined3d_resource_unmap(wined3d_texture_get_resource(surface->wined3d_texture), surface->sub_resource_idx);
273*9987f029SAmine Khaldi if (SUCCEEDED(hr) && surface->texture)
274*9987f029SAmine Khaldi d3d9_texture_flag_auto_gen_mipmap(surface->texture);
275c2c66affSColin Finck wined3d_mutex_unlock();
276c2c66affSColin Finck
277c2c66affSColin Finck if (hr == WINEDDERR_NOTLOCKED)
278c2c66affSColin Finck {
279c2c66affSColin Finck D3DRESOURCETYPE type;
280c2c66affSColin Finck if (surface->texture)
281c2c66affSColin Finck type = IDirect3DBaseTexture9_GetType(&surface->texture->IDirect3DBaseTexture9_iface);
282c2c66affSColin Finck else
283c2c66affSColin Finck type = D3DRTYPE_SURFACE;
284c2c66affSColin Finck hr = type == D3DRTYPE_TEXTURE ? D3D_OK : D3DERR_INVALIDCALL;
285c2c66affSColin Finck }
286c2c66affSColin Finck return hr;
287c2c66affSColin Finck }
288c2c66affSColin Finck
d3d9_surface_GetDC(IDirect3DSurface9 * iface,HDC * dc)289c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_GetDC(IDirect3DSurface9 *iface, HDC *dc)
290c2c66affSColin Finck {
291c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
292c2c66affSColin Finck HRESULT hr;
293c2c66affSColin Finck
294c2c66affSColin Finck TRACE("iface %p, dc %p.\n", iface, dc);
295c2c66affSColin Finck
296c2c66affSColin Finck wined3d_mutex_lock();
297c2c66affSColin Finck hr = wined3d_texture_get_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
298c2c66affSColin Finck wined3d_mutex_unlock();
299c2c66affSColin Finck
300c2c66affSColin Finck return hr;
301c2c66affSColin Finck }
302c2c66affSColin Finck
d3d9_surface_ReleaseDC(IDirect3DSurface9 * iface,HDC dc)303c2c66affSColin Finck static HRESULT WINAPI d3d9_surface_ReleaseDC(IDirect3DSurface9 *iface, HDC dc)
304c2c66affSColin Finck {
305c2c66affSColin Finck struct d3d9_surface *surface = impl_from_IDirect3DSurface9(iface);
306c2c66affSColin Finck HRESULT hr;
307c2c66affSColin Finck
308c2c66affSColin Finck TRACE("iface %p, dc %p.\n", iface, dc);
309c2c66affSColin Finck
310c2c66affSColin Finck wined3d_mutex_lock();
311c2c66affSColin Finck hr = wined3d_texture_release_dc(surface->wined3d_texture, surface->sub_resource_idx, dc);
312*9987f029SAmine Khaldi if (SUCCEEDED(hr) && surface->texture)
313*9987f029SAmine Khaldi d3d9_texture_flag_auto_gen_mipmap(surface->texture);
314c2c66affSColin Finck wined3d_mutex_unlock();
315c2c66affSColin Finck
316c2c66affSColin Finck return hr;
317c2c66affSColin Finck }
318c2c66affSColin Finck
319c2c66affSColin Finck static const struct IDirect3DSurface9Vtbl d3d9_surface_vtbl =
320c2c66affSColin Finck {
321c2c66affSColin Finck /* IUnknown */
322c2c66affSColin Finck d3d9_surface_QueryInterface,
323c2c66affSColin Finck d3d9_surface_AddRef,
324c2c66affSColin Finck d3d9_surface_Release,
325c2c66affSColin Finck /* IDirect3DResource9 */
326c2c66affSColin Finck d3d9_surface_GetDevice,
327c2c66affSColin Finck d3d9_surface_SetPrivateData,
328c2c66affSColin Finck d3d9_surface_GetPrivateData,
329c2c66affSColin Finck d3d9_surface_FreePrivateData,
330c2c66affSColin Finck d3d9_surface_SetPriority,
331c2c66affSColin Finck d3d9_surface_GetPriority,
332c2c66affSColin Finck d3d9_surface_PreLoad,
333c2c66affSColin Finck d3d9_surface_GetType,
334c2c66affSColin Finck /* IDirect3DSurface9 */
335c2c66affSColin Finck d3d9_surface_GetContainer,
336c2c66affSColin Finck d3d9_surface_GetDesc,
337c2c66affSColin Finck d3d9_surface_LockRect,
338c2c66affSColin Finck d3d9_surface_UnlockRect,
339c2c66affSColin Finck d3d9_surface_GetDC,
340c2c66affSColin Finck d3d9_surface_ReleaseDC,
341c2c66affSColin Finck };
342c2c66affSColin Finck
surface_wined3d_object_destroyed(void * parent)343c2c66affSColin Finck static void STDMETHODCALLTYPE surface_wined3d_object_destroyed(void *parent)
344c2c66affSColin Finck {
345c2c66affSColin Finck struct d3d9_surface *surface = parent;
346c2c66affSColin Finck d3d9_resource_cleanup(&surface->resource);
347*9987f029SAmine Khaldi heap_free(surface);
348c2c66affSColin Finck }
349c2c66affSColin Finck
350c2c66affSColin Finck static const struct wined3d_parent_ops d3d9_surface_wined3d_parent_ops =
351c2c66affSColin Finck {
352c2c66affSColin Finck surface_wined3d_object_destroyed,
353c2c66affSColin Finck };
354c2c66affSColin Finck
surface_init(struct d3d9_surface * surface,struct wined3d_texture * wined3d_texture,unsigned int sub_resource_idx,const struct wined3d_parent_ops ** parent_ops)355c2c66affSColin Finck void surface_init(struct d3d9_surface *surface, struct wined3d_texture *wined3d_texture,
356c2c66affSColin Finck unsigned int sub_resource_idx, const struct wined3d_parent_ops **parent_ops)
357c2c66affSColin Finck {
358c2c66affSColin Finck IDirect3DBaseTexture9 *texture;
359c2c66affSColin Finck
360c2c66affSColin Finck surface->IDirect3DSurface9_iface.lpVtbl = &d3d9_surface_vtbl;
361c2c66affSColin Finck d3d9_resource_init(&surface->resource);
362c2c66affSColin Finck surface->resource.refcount = 0;
363c2c66affSColin Finck list_init(&surface->rtv_entry);
364c2c66affSColin Finck surface->container = wined3d_texture_get_parent(wined3d_texture);
365c2c66affSColin Finck surface->wined3d_texture = wined3d_texture;
366c2c66affSColin Finck surface->sub_resource_idx = sub_resource_idx;
367c2c66affSColin Finck
368c2c66affSColin Finck if (surface->container && SUCCEEDED(IUnknown_QueryInterface(surface->container,
369c2c66affSColin Finck &IID_IDirect3DBaseTexture9, (void **)&texture)))
370c2c66affSColin Finck {
371c2c66affSColin Finck surface->texture = unsafe_impl_from_IDirect3DBaseTexture9(texture);
372c2c66affSColin Finck IDirect3DBaseTexture9_Release(texture);
373c2c66affSColin Finck }
374c2c66affSColin Finck
375c2c66affSColin Finck *parent_ops = &d3d9_surface_wined3d_parent_ops;
376c2c66affSColin Finck }
377c2c66affSColin Finck
view_wined3d_object_destroyed(void * parent)378c2c66affSColin Finck static void STDMETHODCALLTYPE view_wined3d_object_destroyed(void *parent)
379c2c66affSColin Finck {
380c2c66affSColin Finck struct d3d9_surface *surface = parent;
381c2c66affSColin Finck
382c2c66affSColin Finck /* If the surface reference count drops to zero, we release our reference
383c2c66affSColin Finck * to the view, but don't clear the pointer yet, in case e.g. a
384c2c66affSColin Finck * GetRenderTarget() call brings the surface back before the view is
385c2c66affSColin Finck * actually destroyed. When the view is destroyed, we need to clear the
386c2c66affSColin Finck * pointer, or a subsequent surface AddRef() would reference it again.
387c2c66affSColin Finck *
388c2c66affSColin Finck * This is safe because as long as the view still has a reference to the
389c2c66affSColin Finck * texture, the surface is also still alive, and we're called before the
390c2c66affSColin Finck * view releases that reference. */
391c2c66affSColin Finck surface->wined3d_rtv = NULL;
392c2c66affSColin Finck list_remove(&surface->rtv_entry);
393c2c66affSColin Finck }
394c2c66affSColin Finck
395c2c66affSColin Finck static const struct wined3d_parent_ops d3d9_view_wined3d_parent_ops =
396c2c66affSColin Finck {
397c2c66affSColin Finck view_wined3d_object_destroyed,
398c2c66affSColin Finck };
399c2c66affSColin Finck
d3d9_surface_get_device(const struct d3d9_surface * surface)400c2c66affSColin Finck struct d3d9_device *d3d9_surface_get_device(const struct d3d9_surface *surface)
401c2c66affSColin Finck {
402c2c66affSColin Finck IDirect3DDevice9Ex *device;
403c2c66affSColin Finck device = surface->texture ? surface->texture->parent_device : surface->parent_device;
404c2c66affSColin Finck return impl_from_IDirect3DDevice9Ex(device);
405c2c66affSColin Finck }
406c2c66affSColin Finck
d3d9_surface_acquire_rendertarget_view(struct d3d9_surface * surface)407c2c66affSColin Finck struct wined3d_rendertarget_view *d3d9_surface_acquire_rendertarget_view(struct d3d9_surface *surface)
408c2c66affSColin Finck {
409c2c66affSColin Finck HRESULT hr;
410c2c66affSColin Finck
411c2c66affSColin Finck /* The surface reference count can be equal to 0 when this function is
412c2c66affSColin Finck * called. In order to properly manage the render target view reference
413c2c66affSColin Finck * count, we temporarily increment the surface reference count. */
414c2c66affSColin Finck d3d9_surface_AddRef(&surface->IDirect3DSurface9_iface);
415c2c66affSColin Finck
416c2c66affSColin Finck if (surface->wined3d_rtv)
417c2c66affSColin Finck return surface->wined3d_rtv;
418c2c66affSColin Finck
419c2c66affSColin Finck if (FAILED(hr = wined3d_rendertarget_view_create_from_sub_resource(surface->wined3d_texture,
420c2c66affSColin Finck surface->sub_resource_idx, surface, &d3d9_view_wined3d_parent_ops, &surface->wined3d_rtv)))
421c2c66affSColin Finck {
422c2c66affSColin Finck ERR("Failed to create rendertarget view, hr %#x.\n", hr);
423c2c66affSColin Finck d3d9_surface_Release(&surface->IDirect3DSurface9_iface);
424c2c66affSColin Finck return NULL;
425c2c66affSColin Finck }
426c2c66affSColin Finck
427c2c66affSColin Finck if (surface->texture)
428c2c66affSColin Finck list_add_head(&surface->texture->rtv_list, &surface->rtv_entry);
429c2c66affSColin Finck
430c2c66affSColin Finck return surface->wined3d_rtv;
431c2c66affSColin Finck }
432c2c66affSColin Finck
d3d9_surface_release_rendertarget_view(struct d3d9_surface * surface,struct wined3d_rendertarget_view * rtv)433c2c66affSColin Finck void d3d9_surface_release_rendertarget_view(struct d3d9_surface *surface,
434c2c66affSColin Finck struct wined3d_rendertarget_view *rtv)
435c2c66affSColin Finck {
436c2c66affSColin Finck if (rtv)
437c2c66affSColin Finck d3d9_surface_Release(&surface->IDirect3DSurface9_iface);
438c2c66affSColin Finck }
439c2c66affSColin Finck
unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 * iface)440c2c66affSColin Finck struct d3d9_surface *unsafe_impl_from_IDirect3DSurface9(IDirect3DSurface9 *iface)
441c2c66affSColin Finck {
442c2c66affSColin Finck if (!iface)
443c2c66affSColin Finck return NULL;
444c2c66affSColin Finck assert(iface->lpVtbl == &d3d9_surface_vtbl);
445c2c66affSColin Finck
446c2c66affSColin Finck return impl_from_IDirect3DSurface9(iface);
447c2c66affSColin Finck }
448