1 | /*
|
---|
2 | * Copyright 2002-2004 Jason Edmeades
|
---|
3 | * Copyright 2003-2004 Raphael Junqueira
|
---|
4 | * Copyright 2004 Christian Costa
|
---|
5 | * Copyright 2005 Oliver Stieber
|
---|
6 | * Copyright 2009-2010 Henri Verbeet for CodeWeavers
|
---|
7 | *
|
---|
8 | * This library is free software; you can redistribute it and/or
|
---|
9 | * modify it under the terms of the GNU Lesser General Public
|
---|
10 | * License as published by the Free Software Foundation; either
|
---|
11 | * version 2.1 of the License, or (at your option) any later version.
|
---|
12 | *
|
---|
13 | * This library is distributed in the hope that it will be useful,
|
---|
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
16 | * Lesser General Public License for more details.
|
---|
17 | *
|
---|
18 | * You should have received a copy of the GNU Lesser General Public
|
---|
19 | * License along with this library; if not, write to the Free Software
|
---|
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
---|
21 | */
|
---|
22 |
|
---|
23 | /*
|
---|
24 | * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
25 | * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
|
---|
26 | * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
27 | * a choice of LGPL license versions is made available with the language indicating
|
---|
28 | * that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
29 | * of the LGPL is applied is otherwise unspecified.
|
---|
30 | */
|
---|
31 |
|
---|
32 | #include "config.h"
|
---|
33 | #include "wine/port.h"
|
---|
34 | #include "wined3d_private.h"
|
---|
35 |
|
---|
36 | WINE_DEFAULT_DEBUG_CHANNEL(d3d);
|
---|
37 |
|
---|
38 | struct private_data
|
---|
39 | {
|
---|
40 | struct list entry;
|
---|
41 |
|
---|
42 | GUID tag;
|
---|
43 | DWORD flags; /* DDSPD_* */
|
---|
44 |
|
---|
45 | union
|
---|
46 | {
|
---|
47 | void *data;
|
---|
48 | IUnknown *object;
|
---|
49 | } ptr;
|
---|
50 |
|
---|
51 | DWORD size;
|
---|
52 | };
|
---|
53 |
|
---|
54 | static DWORD resource_access_from_pool(enum wined3d_pool pool)
|
---|
55 | {
|
---|
56 | switch (pool)
|
---|
57 | {
|
---|
58 | case WINED3D_POOL_DEFAULT:
|
---|
59 | return WINED3D_RESOURCE_ACCESS_GPU;
|
---|
60 |
|
---|
61 | case WINED3D_POOL_MANAGED:
|
---|
62 | return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU;
|
---|
63 |
|
---|
64 | case WINED3D_POOL_SYSTEM_MEM:
|
---|
65 | return WINED3D_RESOURCE_ACCESS_CPU;
|
---|
66 |
|
---|
67 | case WINED3D_POOL_SCRATCH:
|
---|
68 | return WINED3D_RESOURCE_ACCESS_SCRATCH;
|
---|
69 |
|
---|
70 | default:
|
---|
71 | FIXME("Unhandled pool %#x.\n", pool);
|
---|
72 | return 0;
|
---|
73 | }
|
---|
74 | }
|
---|
75 |
|
---|
76 | static void resource_check_usage(DWORD usage)
|
---|
77 | {
|
---|
78 | static const DWORD handled = WINED3DUSAGE_RENDERTARGET
|
---|
79 | | WINED3DUSAGE_DEPTHSTENCIL
|
---|
80 | | WINED3DUSAGE_DYNAMIC
|
---|
81 | | WINED3DUSAGE_AUTOGENMIPMAP
|
---|
82 | | WINED3DUSAGE_STATICDECL
|
---|
83 | | WINED3DUSAGE_OVERLAY;
|
---|
84 |
|
---|
85 | if (usage & ~handled)
|
---|
86 | FIXME("Unhandled usage flags %#x.\n", usage & ~handled);
|
---|
87 | }
|
---|
88 |
|
---|
89 | HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device,
|
---|
90 | enum wined3d_resource_type type, const struct wined3d_format *format,
|
---|
91 | enum wined3d_multisample_type multisample_type, UINT multisample_quality,
|
---|
92 | DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size,
|
---|
93 | void *parent, const struct wined3d_parent_ops *parent_ops,
|
---|
94 | const struct wined3d_resource_ops *resource_ops
|
---|
95 | #ifdef VBOX_WITH_WDDM
|
---|
96 | , HANDLE *shared_handle
|
---|
97 | , void *pvClientMem
|
---|
98 | #endif
|
---|
99 | )
|
---|
100 | {
|
---|
101 | const struct wined3d *d3d = device->wined3d;
|
---|
102 |
|
---|
103 | resource->ref = 1;
|
---|
104 | resource->device = device;
|
---|
105 | resource->type = type;
|
---|
106 | resource->format = format;
|
---|
107 | resource->multisample_type = multisample_type;
|
---|
108 | resource->multisample_quality = multisample_quality;
|
---|
109 | resource->usage = usage;
|
---|
110 | resource->pool = pool;
|
---|
111 | resource->access_flags = resource_access_from_pool(pool);
|
---|
112 | if (usage & WINED3DUSAGE_DYNAMIC)
|
---|
113 | resource->access_flags |= WINED3D_RESOURCE_ACCESS_CPU;
|
---|
114 | resource->width = width;
|
---|
115 | resource->height = height;
|
---|
116 | resource->depth = depth;
|
---|
117 | resource->size = size;
|
---|
118 | resource->priority = 0;
|
---|
119 | resource->parent = parent;
|
---|
120 | resource->parent_ops = parent_ops;
|
---|
121 | resource->resource_ops = resource_ops;
|
---|
122 | list_init(&resource->privateData);
|
---|
123 |
|
---|
124 | resource_check_usage(usage);
|
---|
125 |
|
---|
126 | #ifdef VBOX_WITH_WDDM
|
---|
127 | resource->sharerc_handle = 0;
|
---|
128 | resource->sharerc_flags = 0;
|
---|
129 | resource->sharerc_locks = 0;
|
---|
130 | if (pool == WINED3D_POOL_SYSTEM_MEM && pvClientMem)
|
---|
131 | {
|
---|
132 | resource->allocatedMemory = pvClientMem;
|
---|
133 | resource->heapMemory = NULL;
|
---|
134 | }
|
---|
135 | else
|
---|
136 | #endif
|
---|
137 | {
|
---|
138 | #ifdef VBOX_WITH_WDDM
|
---|
139 | if (pool == WINED3D_POOL_DEFAULT && shared_handle)
|
---|
140 | {
|
---|
141 | resource->sharerc_handle = (DWORD)*shared_handle;
|
---|
142 | resource->sharerc_flags = VBOXSHRC_F_SHARED;
|
---|
143 | if (*shared_handle)
|
---|
144 | resource->sharerc_flags |= VBOXSHRC_F_SHARED_OPENED;
|
---|
145 | }
|
---|
146 | #endif
|
---|
147 |
|
---|
148 | if (size)
|
---|
149 | {
|
---|
150 | resource->heapMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + RESOURCE_ALIGNMENT);
|
---|
151 | if (!resource->heapMemory)
|
---|
152 | {
|
---|
153 | ERR("Out of memory!\n");
|
---|
154 | return WINED3DERR_OUTOFVIDEOMEMORY;
|
---|
155 | }
|
---|
156 | }
|
---|
157 | else
|
---|
158 | {
|
---|
159 | resource->heapMemory = NULL;
|
---|
160 | }
|
---|
161 | resource->allocatedMemory = (BYTE *)(((ULONG_PTR)resource->heapMemory
|
---|
162 | + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
|
---|
163 | }
|
---|
164 |
|
---|
165 | #ifndef VBOX_WITH_WDDM
|
---|
166 | /* Check that we have enough video ram left */
|
---|
167 | if (pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
|
---|
168 | {
|
---|
169 | if (size > wined3d_device_get_available_texture_mem(device))
|
---|
170 | {
|
---|
171 | ERR("Out of adapter memory\n");
|
---|
172 | HeapFree(GetProcessHeap(), 0, resource->heapMemory);
|
---|
173 | return WINED3DERR_OUTOFVIDEOMEMORY;
|
---|
174 | }
|
---|
175 | adapter_adjust_memory(device->adapter, size);
|
---|
176 | }
|
---|
177 | #endif
|
---|
178 |
|
---|
179 | device_resource_add(device, resource);
|
---|
180 |
|
---|
181 | return WINED3D_OK;
|
---|
182 | }
|
---|
183 |
|
---|
184 | void resource_cleanup(struct wined3d_resource *resource)
|
---|
185 | {
|
---|
186 | const struct wined3d *d3d = resource->device->wined3d;
|
---|
187 | struct private_data *data;
|
---|
188 | struct list *e1, *e2;
|
---|
189 | HRESULT hr;
|
---|
190 |
|
---|
191 | TRACE("Cleaning up resource %p.\n", resource);
|
---|
192 | #ifndef VBOX_WITH_WDDM
|
---|
193 | if (resource->pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
|
---|
194 | {
|
---|
195 | TRACE("Decrementing device memory pool by %u.\n", resource->size);
|
---|
196 | adapter_adjust_memory(resource->device->adapter, 0 - resource->size);
|
---|
197 | }
|
---|
198 | #endif
|
---|
199 |
|
---|
200 | LIST_FOR_EACH_SAFE(e1, e2, &resource->privateData)
|
---|
201 | {
|
---|
202 | data = LIST_ENTRY(e1, struct private_data, entry);
|
---|
203 | hr = wined3d_resource_free_private_data(resource, &data->tag);
|
---|
204 | if (FAILED(hr))
|
---|
205 | ERR("Failed to free private data when destroying resource %p, hr = %#x.\n", resource, hr);
|
---|
206 | }
|
---|
207 |
|
---|
208 | HeapFree(GetProcessHeap(), 0, resource->heapMemory);
|
---|
209 | resource->allocatedMemory = 0;
|
---|
210 | resource->heapMemory = 0;
|
---|
211 |
|
---|
212 | device_resource_released(resource->device, resource);
|
---|
213 | }
|
---|
214 |
|
---|
215 | void resource_unload(struct wined3d_resource *resource)
|
---|
216 | {
|
---|
217 | if (resource->map_count)
|
---|
218 | ERR("Resource %p is being unloaded while mapped.\n", resource);
|
---|
219 |
|
---|
220 | context_resource_unloaded(resource->device,
|
---|
221 | resource, resource->type);
|
---|
222 | }
|
---|
223 |
|
---|
224 | static struct private_data *resource_find_private_data(const struct wined3d_resource *resource, REFGUID tag)
|
---|
225 | {
|
---|
226 | struct private_data *data;
|
---|
227 | struct list *entry;
|
---|
228 |
|
---|
229 | TRACE("Searching for private data %s\n", debugstr_guid(tag));
|
---|
230 | LIST_FOR_EACH(entry, &resource->privateData)
|
---|
231 | {
|
---|
232 | data = LIST_ENTRY(entry, struct private_data, entry);
|
---|
233 | if (IsEqualGUID(&data->tag, tag)) {
|
---|
234 | TRACE("Found %p\n", data);
|
---|
235 | return data;
|
---|
236 | }
|
---|
237 | }
|
---|
238 | TRACE("Not found\n");
|
---|
239 | return NULL;
|
---|
240 | }
|
---|
241 |
|
---|
242 | HRESULT CDECL wined3d_resource_set_private_data(struct wined3d_resource *resource, REFGUID guid,
|
---|
243 | const void *data, DWORD data_size, DWORD flags)
|
---|
244 | {
|
---|
245 | struct private_data *d;
|
---|
246 |
|
---|
247 | TRACE("resource %p, riid %s, data %p, data_size %u, flags %#x.\n",
|
---|
248 | resource, debugstr_guid(guid), data, data_size, flags);
|
---|
249 |
|
---|
250 | wined3d_resource_free_private_data(resource, guid);
|
---|
251 |
|
---|
252 | d = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*d));
|
---|
253 | if (!d) return E_OUTOFMEMORY;
|
---|
254 |
|
---|
255 | d->tag = *guid;
|
---|
256 | d->flags = flags;
|
---|
257 |
|
---|
258 | if (flags & WINED3DSPD_IUNKNOWN)
|
---|
259 | {
|
---|
260 | if (data_size != sizeof(IUnknown *))
|
---|
261 | {
|
---|
262 | WARN("IUnknown data with size %u, returning WINED3DERR_INVALIDCALL.\n", data_size);
|
---|
263 | HeapFree(GetProcessHeap(), 0, d);
|
---|
264 | return WINED3DERR_INVALIDCALL;
|
---|
265 | }
|
---|
266 | d->ptr.object = (IUnknown *)data;
|
---|
267 | d->size = sizeof(IUnknown *);
|
---|
268 | IUnknown_AddRef(d->ptr.object);
|
---|
269 | }
|
---|
270 | else
|
---|
271 | {
|
---|
272 | d->ptr.data = HeapAlloc(GetProcessHeap(), 0, data_size);
|
---|
273 | if (!d->ptr.data)
|
---|
274 | {
|
---|
275 | HeapFree(GetProcessHeap(), 0, d);
|
---|
276 | return E_OUTOFMEMORY;
|
---|
277 | }
|
---|
278 | d->size = data_size;
|
---|
279 | memcpy(d->ptr.data, data, data_size);
|
---|
280 | }
|
---|
281 | list_add_tail(&resource->privateData, &d->entry);
|
---|
282 |
|
---|
283 | return WINED3D_OK;
|
---|
284 | }
|
---|
285 |
|
---|
286 | HRESULT CDECL wined3d_resource_get_private_data(const struct wined3d_resource *resource, REFGUID guid,
|
---|
287 | void *data, DWORD *data_size)
|
---|
288 | {
|
---|
289 | const struct private_data *d;
|
---|
290 |
|
---|
291 | TRACE("resource %p, guid %s, data %p, data_size %p.\n",
|
---|
292 | resource, debugstr_guid(guid), data, data_size);
|
---|
293 |
|
---|
294 | d = resource_find_private_data(resource, guid);
|
---|
295 | if (!d) return WINED3DERR_NOTFOUND;
|
---|
296 |
|
---|
297 | if (*data_size < d->size)
|
---|
298 | {
|
---|
299 | *data_size = d->size;
|
---|
300 | return WINED3DERR_MOREDATA;
|
---|
301 | }
|
---|
302 |
|
---|
303 | if (d->flags & WINED3DSPD_IUNKNOWN)
|
---|
304 | {
|
---|
305 | *(IUnknown **)data = d->ptr.object;
|
---|
306 | if (resource->device->wined3d->dxVersion != 7)
|
---|
307 | {
|
---|
308 | /* D3D8 and D3D9 addref the private data, DDraw does not. This
|
---|
309 | * can't be handled in ddraw because it doesn't know if the
|
---|
310 | * pointer returned is an IUnknown * or just a blob. */
|
---|
311 | IUnknown_AddRef(d->ptr.object);
|
---|
312 | }
|
---|
313 | }
|
---|
314 | else
|
---|
315 | {
|
---|
316 | memcpy(data, d->ptr.data, d->size);
|
---|
317 | }
|
---|
318 |
|
---|
319 | return WINED3D_OK;
|
---|
320 | }
|
---|
321 | HRESULT CDECL wined3d_resource_free_private_data(struct wined3d_resource *resource, REFGUID guid)
|
---|
322 | {
|
---|
323 | struct private_data *data;
|
---|
324 |
|
---|
325 | TRACE("resource %p, guid %s.\n", resource, debugstr_guid(guid));
|
---|
326 |
|
---|
327 | data = resource_find_private_data(resource, guid);
|
---|
328 | if (!data) return WINED3DERR_NOTFOUND;
|
---|
329 |
|
---|
330 | if (data->flags & WINED3DSPD_IUNKNOWN)
|
---|
331 | {
|
---|
332 | if (data->ptr.object)
|
---|
333 | IUnknown_Release(data->ptr.object);
|
---|
334 | }
|
---|
335 | else
|
---|
336 | {
|
---|
337 | HeapFree(GetProcessHeap(), 0, data->ptr.data);
|
---|
338 | }
|
---|
339 | list_remove(&data->entry);
|
---|
340 |
|
---|
341 | HeapFree(GetProcessHeap(), 0, data);
|
---|
342 |
|
---|
343 | return WINED3D_OK;
|
---|
344 | }
|
---|
345 |
|
---|
346 | DWORD resource_set_priority(struct wined3d_resource *resource, DWORD priority)
|
---|
347 | {
|
---|
348 | DWORD prev = resource->priority;
|
---|
349 | resource->priority = priority;
|
---|
350 | TRACE("resource %p, new priority %u, returning old priority %u.\n", resource, priority, prev);
|
---|
351 | return prev;
|
---|
352 | }
|
---|
353 |
|
---|
354 | DWORD resource_get_priority(const struct wined3d_resource *resource)
|
---|
355 | {
|
---|
356 | TRACE("resource %p, returning %u.\n", resource, resource->priority);
|
---|
357 | return resource->priority;
|
---|
358 | }
|
---|
359 |
|
---|
360 | void * CDECL wined3d_resource_get_parent(const struct wined3d_resource *resource)
|
---|
361 | {
|
---|
362 | return resource->parent;
|
---|
363 | }
|
---|
364 |
|
---|
365 | void CDECL wined3d_resource_get_desc(const struct wined3d_resource *resource, struct wined3d_resource_desc *desc)
|
---|
366 | {
|
---|
367 | desc->resource_type = resource->type;
|
---|
368 | desc->format = resource->format->id;
|
---|
369 | desc->multisample_type = resource->multisample_type;
|
---|
370 | desc->multisample_quality = resource->multisample_quality;
|
---|
371 | desc->usage = resource->usage;
|
---|
372 | desc->pool = resource->pool;
|
---|
373 | desc->width = resource->width;
|
---|
374 | desc->height = resource->height;
|
---|
375 | desc->depth = resource->depth;
|
---|
376 | desc->size = resource->size;
|
---|
377 | }
|
---|