d3d11: Remove null dxgi object checks.
[wine.git] / dlls / winegstreamer / wg_allocator.c
blobc31751ce83f1cbf3d16ffd4474d8b5b3f4fe69b6
1 /*
2 * GStreamer memory allocator
4 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #if 0
22 #pragma makedep unix
23 #endif
25 #include "config.h"
27 #include <assert.h>
28 #include <stdarg.h>
30 #include <gst/gst.h>
31 #include <gst/video/video.h>
32 #include <gst/audio/audio.h>
34 #include "unix_private.h"
36 #include "wine/list.h"
38 GST_DEBUG_CATEGORY_EXTERN(wine);
39 #define GST_CAT_DEFAULT wine
41 typedef struct
43 GstMemory parent;
44 struct list entry;
46 GstMemory *unix_memory;
47 GstMapInfo unix_map_info;
49 struct wg_sample *sample;
50 gsize written;
51 } WgMemory;
53 typedef struct
55 GstAllocator parent;
57 wg_allocator_request_sample_cb request_sample;
58 void *request_sample_context;
60 pthread_mutex_t mutex;
61 pthread_cond_t release_cond;
62 struct list memory_list;
63 } WgAllocator;
65 typedef struct
67 GstAllocatorClass parent_class;
68 } WgAllocatorClass;
70 G_DEFINE_TYPE(WgAllocator, wg_allocator, GST_TYPE_ALLOCATOR);
72 static gpointer wg_allocator_map(GstMemory *gst_memory, GstMapInfo *info, gsize maxsize)
74 WgAllocator *allocator = (WgAllocator *)gst_memory->allocator;
75 WgMemory *memory = (WgMemory *)gst_memory;
77 if (gst_memory->parent)
78 return wg_allocator_map(gst_memory->parent, info, maxsize);
80 GST_LOG("memory %p, info %p, maxsize %#zx", memory, info, maxsize);
82 pthread_mutex_lock(&allocator->mutex);
84 if (!memory->sample)
85 info->data = memory->unix_map_info.data;
86 else
88 InterlockedIncrement(&memory->sample->refcount);
89 info->data = memory->sample->data;
91 if (info->flags & GST_MAP_WRITE)
92 memory->written = max(memory->written, maxsize);
94 pthread_mutex_unlock(&allocator->mutex);
96 GST_INFO("Mapped memory %p to %p", memory, info->data);
97 return info->data;
100 static void wg_allocator_unmap(GstMemory *gst_memory, GstMapInfo *info)
102 WgAllocator *allocator = (WgAllocator *)gst_memory->allocator;
103 WgMemory *memory = (WgMemory *)gst_memory;
105 if (gst_memory->parent)
106 return wg_allocator_unmap(gst_memory->parent, info);
108 GST_LOG("memory %p, info %p", memory, info);
110 pthread_mutex_lock(&allocator->mutex);
112 if (memory->sample && info->data == memory->sample->data)
114 InterlockedDecrement(&memory->sample->refcount);
115 pthread_cond_signal(&allocator->release_cond);
118 pthread_mutex_unlock(&allocator->mutex);
121 static void wg_allocator_init(WgAllocator *allocator)
123 GST_LOG("allocator %p", allocator);
125 allocator->parent.mem_type = "Wine";
127 allocator->parent.mem_map_full = wg_allocator_map;
128 allocator->parent.mem_unmap_full = wg_allocator_unmap;
130 GST_OBJECT_FLAG_SET(allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
132 pthread_mutex_init(&allocator->mutex, NULL);
133 pthread_cond_init(&allocator->release_cond, NULL);
134 list_init(&allocator->memory_list);
137 static void wg_allocator_finalize(GObject *object)
139 WgAllocator *allocator = (WgAllocator *)object;
141 GST_LOG("allocator %p", allocator);
143 pthread_cond_destroy(&allocator->release_cond);
144 pthread_mutex_destroy(&allocator->mutex);
146 G_OBJECT_CLASS(wg_allocator_parent_class)->finalize(object);
149 static GstMemory *wg_allocator_alloc(GstAllocator *gst_allocator, gsize size,
150 GstAllocationParams *params)
152 WgAllocator *allocator = (WgAllocator *)gst_allocator;
153 WgMemory *memory;
155 GST_LOG("allocator %p, size %#zx, params %p", allocator, size, params);
157 memory = g_slice_new0(WgMemory);
158 gst_memory_init(GST_MEMORY_CAST(memory), 0, GST_ALLOCATOR_CAST(allocator),
159 NULL, size, 0, 0, size);
160 memory->unix_memory = gst_allocator_alloc(NULL, size, params);
161 gst_memory_map(memory->unix_memory, &memory->unix_map_info, GST_MAP_WRITE);
163 pthread_mutex_lock(&allocator->mutex);
165 memory->sample = allocator->request_sample(size, allocator->request_sample_context);
166 list_add_tail(&allocator->memory_list, &memory->entry);
168 pthread_mutex_unlock(&allocator->mutex);
170 GST_INFO("Allocated memory %p, sample %p, unix_memory %p, data %p", memory,
171 memory->sample, memory->unix_memory, memory->unix_map_info.data);
172 return (GstMemory *)memory;
175 static void wg_allocator_free(GstAllocator *gst_allocator, GstMemory *gst_memory)
177 WgAllocator *allocator = (WgAllocator *)gst_allocator;
178 WgMemory *memory = (WgMemory *)gst_memory;
180 GST_LOG("allocator %p, memory %p", allocator, memory);
182 pthread_mutex_lock(&allocator->mutex);
184 if (memory->sample)
185 InterlockedDecrement(&memory->sample->refcount);
186 memory->sample = NULL;
188 list_remove(&memory->entry);
190 pthread_mutex_unlock(&allocator->mutex);
192 gst_memory_unmap(memory->unix_memory, &memory->unix_map_info);
193 gst_memory_unref(memory->unix_memory);
194 g_slice_free(WgMemory, memory);
197 static void wg_allocator_class_init(WgAllocatorClass *klass)
199 GstAllocatorClass *parent_class = (GstAllocatorClass *)klass;
200 GObjectClass *root_class = (GObjectClass *)klass;
202 GST_LOG("klass %p", klass);
204 parent_class->alloc = wg_allocator_alloc;
205 parent_class->free = wg_allocator_free;
206 root_class->finalize = wg_allocator_finalize;
209 GstAllocator *wg_allocator_create(wg_allocator_request_sample_cb request_sample, void *request_sample_context)
211 WgAllocator *allocator;
213 if (!(allocator = g_object_new(wg_allocator_get_type(), NULL)))
214 return NULL;
216 allocator->request_sample = request_sample;
217 allocator->request_sample_context = request_sample_context;
218 return GST_ALLOCATOR(allocator);
221 static void release_memory_sample(WgAllocator *allocator, WgMemory *memory, bool discard_data)
223 struct wg_sample *sample;
225 if (!(sample = memory->sample))
226 return;
228 while (sample->refcount > 1)
230 GST_WARNING("Waiting for sample %p to be unmapped", sample);
231 pthread_cond_wait(&allocator->release_cond, &allocator->mutex);
233 InterlockedDecrement(&sample->refcount);
235 if (memory->written && !discard_data)
237 GST_WARNING("Copying %#zx bytes from sample %p, back to memory %p", memory->written, sample, memory);
238 memcpy(memory->unix_map_info.data, memory->sample->data, memory->written);
241 memory->sample = NULL;
242 GST_INFO("Released sample %p from memory %p", sample, memory);
245 void wg_allocator_destroy(GstAllocator *gst_allocator)
247 WgAllocator *allocator = (WgAllocator *)gst_allocator;
248 WgMemory *memory;
250 GST_LOG("allocator %p", allocator);
252 pthread_mutex_lock(&allocator->mutex);
253 LIST_FOR_EACH_ENTRY(memory, &allocator->memory_list, WgMemory, entry)
254 release_memory_sample(allocator, memory, true);
255 pthread_mutex_unlock(&allocator->mutex);
257 g_object_unref(allocator);
259 GST_INFO("Destroyed buffer allocator %p", allocator);
262 static WgMemory *find_sample_memory(WgAllocator *allocator, struct wg_sample *sample)
264 WgMemory *memory;
266 LIST_FOR_EACH_ENTRY(memory, &allocator->memory_list, WgMemory, entry)
267 if (memory->sample == sample)
268 return memory;
270 return NULL;
273 void wg_allocator_release_sample(GstAllocator *gst_allocator, struct wg_sample *sample,
274 bool discard_data)
276 WgAllocator *allocator = (WgAllocator *)gst_allocator;
277 WgMemory *memory;
279 GST_LOG("allocator %p, sample %p, discard_data %u", allocator, sample, discard_data);
281 pthread_mutex_lock(&allocator->mutex);
282 if ((memory = find_sample_memory(allocator, sample)))
283 release_memory_sample(allocator, memory, discard_data);
284 else if (sample->refcount)
285 GST_ERROR("Couldn't find memory for sample %p", sample);
286 pthread_mutex_unlock(&allocator->mutex);