Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/va/buffer.c
4561 views
1
/**************************************************************************
2
*
3
* Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian.
4
* Copyright 2014 Advanced Micro Devices, Inc.
5
* All Rights Reserved.
6
*
7
* Permission is hereby granted, free of charge, to any person obtaining a
8
* copy of this software and associated documentation files (the
9
* "Software"), to deal in the Software without restriction, including
10
* without limitation the rights to use, copy, modify, merge, publish,
11
* distribute, sub license, and/or sell copies of the Software, and to
12
* permit persons to whom the Software is furnished to do so, subject to
13
* the following conditions:
14
*
15
* The above copyright notice and this permission notice (including the
16
* next paragraph) shall be included in all copies or substantial portions
17
* of the Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
23
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
*
27
**************************************************************************/
28
29
#include "pipe/p_screen.h"
30
#include "frontend/drm_driver.h"
31
#include "util/u_memory.h"
32
#include "util/u_handle_table.h"
33
#include "util/u_transfer.h"
34
#include "vl/vl_winsys.h"
35
36
#include "va_private.h"
37
38
VAStatus
39
vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type,
40
unsigned int size, unsigned int num_elements, void *data,
41
VABufferID *buf_id)
42
{
43
vlVaDriver *drv;
44
vlVaBuffer *buf;
45
46
if (!ctx)
47
return VA_STATUS_ERROR_INVALID_CONTEXT;
48
49
buf = CALLOC(1, sizeof(vlVaBuffer));
50
if (!buf)
51
return VA_STATUS_ERROR_ALLOCATION_FAILED;
52
53
buf->type = type;
54
buf->size = size;
55
buf->num_elements = num_elements;
56
buf->data = MALLOC(size * num_elements);
57
58
if (!buf->data) {
59
FREE(buf);
60
return VA_STATUS_ERROR_ALLOCATION_FAILED;
61
}
62
63
if (data)
64
memcpy(buf->data, data, size * num_elements);
65
66
drv = VL_VA_DRIVER(ctx);
67
mtx_lock(&drv->mutex);
68
*buf_id = handle_table_add(drv->htab, buf);
69
mtx_unlock(&drv->mutex);
70
71
return VA_STATUS_SUCCESS;
72
}
73
74
VAStatus
75
vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id,
76
unsigned int num_elements)
77
{
78
vlVaDriver *drv;
79
vlVaBuffer *buf;
80
81
if (!ctx)
82
return VA_STATUS_ERROR_INVALID_CONTEXT;
83
84
drv = VL_VA_DRIVER(ctx);
85
mtx_lock(&drv->mutex);
86
buf = handle_table_get(drv->htab, buf_id);
87
mtx_unlock(&drv->mutex);
88
if (!buf)
89
return VA_STATUS_ERROR_INVALID_BUFFER;
90
91
if (buf->derived_surface.resource)
92
return VA_STATUS_ERROR_INVALID_BUFFER;
93
94
buf->data = REALLOC(buf->data, buf->size * buf->num_elements,
95
buf->size * num_elements);
96
buf->num_elements = num_elements;
97
98
if (!buf->data)
99
return VA_STATUS_ERROR_ALLOCATION_FAILED;
100
101
return VA_STATUS_SUCCESS;
102
}
103
104
VAStatus
105
vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff)
106
{
107
vlVaDriver *drv;
108
vlVaBuffer *buf;
109
110
if (!ctx)
111
return VA_STATUS_ERROR_INVALID_CONTEXT;
112
113
drv = VL_VA_DRIVER(ctx);
114
if (!drv)
115
return VA_STATUS_ERROR_INVALID_CONTEXT;
116
117
if (!pbuff)
118
return VA_STATUS_ERROR_INVALID_PARAMETER;
119
120
mtx_lock(&drv->mutex);
121
buf = handle_table_get(drv->htab, buf_id);
122
if (!buf || buf->export_refcount > 0) {
123
mtx_unlock(&drv->mutex);
124
return VA_STATUS_ERROR_INVALID_BUFFER;
125
}
126
127
if (buf->derived_surface.resource) {
128
struct pipe_resource *resource;
129
struct pipe_box box = {};
130
131
resource = buf->derived_surface.resource;
132
box.width = resource->width0;
133
box.height = resource->height0;
134
box.depth = resource->depth0;
135
*pbuff = drv->pipe->buffer_map(drv->pipe, resource, 0, PIPE_MAP_WRITE,
136
&box, &buf->derived_surface.transfer);
137
mtx_unlock(&drv->mutex);
138
139
if (!buf->derived_surface.transfer || !*pbuff)
140
return VA_STATUS_ERROR_INVALID_BUFFER;
141
142
if (buf->type == VAEncCodedBufferType) {
143
((VACodedBufferSegment*)buf->data)->buf = *pbuff;
144
((VACodedBufferSegment*)buf->data)->size = buf->coded_size;
145
((VACodedBufferSegment*)buf->data)->next = NULL;
146
*pbuff = buf->data;
147
}
148
} else {
149
mtx_unlock(&drv->mutex);
150
*pbuff = buf->data;
151
}
152
153
return VA_STATUS_SUCCESS;
154
}
155
156
VAStatus
157
vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id)
158
{
159
vlVaDriver *drv;
160
vlVaBuffer *buf;
161
162
if (!ctx)
163
return VA_STATUS_ERROR_INVALID_CONTEXT;
164
165
drv = VL_VA_DRIVER(ctx);
166
if (!drv)
167
return VA_STATUS_ERROR_INVALID_CONTEXT;
168
169
mtx_lock(&drv->mutex);
170
buf = handle_table_get(drv->htab, buf_id);
171
if (!buf || buf->export_refcount > 0) {
172
mtx_unlock(&drv->mutex);
173
return VA_STATUS_ERROR_INVALID_BUFFER;
174
}
175
176
if (buf->derived_surface.resource) {
177
if (!buf->derived_surface.transfer) {
178
mtx_unlock(&drv->mutex);
179
return VA_STATUS_ERROR_INVALID_BUFFER;
180
}
181
182
pipe_buffer_unmap(drv->pipe, buf->derived_surface.transfer);
183
buf->derived_surface.transfer = NULL;
184
}
185
mtx_unlock(&drv->mutex);
186
187
return VA_STATUS_SUCCESS;
188
}
189
190
VAStatus
191
vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buf_id)
192
{
193
vlVaDriver *drv;
194
vlVaBuffer *buf;
195
196
if (!ctx)
197
return VA_STATUS_ERROR_INVALID_CONTEXT;
198
199
drv = VL_VA_DRIVER(ctx);
200
mtx_lock(&drv->mutex);
201
buf = handle_table_get(drv->htab, buf_id);
202
if (!buf) {
203
mtx_unlock(&drv->mutex);
204
return VA_STATUS_ERROR_INVALID_BUFFER;
205
}
206
207
if (buf->derived_surface.resource) {
208
pipe_resource_reference(&buf->derived_surface.resource, NULL);
209
210
if (buf->derived_image_buffer)
211
buf->derived_image_buffer->destroy(buf->derived_image_buffer);
212
}
213
214
FREE(buf->data);
215
FREE(buf);
216
handle_table_remove(VL_VA_DRIVER(ctx)->htab, buf_id);
217
mtx_unlock(&drv->mutex);
218
219
return VA_STATUS_SUCCESS;
220
}
221
222
VAStatus
223
vlVaBufferInfo(VADriverContextP ctx, VABufferID buf_id, VABufferType *type,
224
unsigned int *size, unsigned int *num_elements)
225
{
226
vlVaDriver *drv;
227
vlVaBuffer *buf;
228
229
if (!ctx)
230
return VA_STATUS_ERROR_INVALID_CONTEXT;
231
232
drv = VL_VA_DRIVER(ctx);
233
mtx_lock(&drv->mutex);
234
buf = handle_table_get(drv->htab, buf_id);
235
mtx_unlock(&drv->mutex);
236
if (!buf)
237
return VA_STATUS_ERROR_INVALID_BUFFER;
238
239
*type = buf->type;
240
*size = buf->size;
241
*num_elements = buf->num_elements;
242
243
return VA_STATUS_SUCCESS;
244
}
245
246
VAStatus
247
vlVaAcquireBufferHandle(VADriverContextP ctx, VABufferID buf_id,
248
VABufferInfo *out_buf_info)
249
{
250
vlVaDriver *drv;
251
uint32_t i;
252
uint32_t mem_type;
253
vlVaBuffer *buf ;
254
struct pipe_screen *screen;
255
256
/* List of supported memory types, in preferred order. */
257
static const uint32_t mem_types[] = {
258
VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME,
259
0
260
};
261
262
if (!ctx)
263
return VA_STATUS_ERROR_INVALID_CONTEXT;
264
265
drv = VL_VA_DRIVER(ctx);
266
screen = VL_VA_PSCREEN(ctx);
267
mtx_lock(&drv->mutex);
268
buf = handle_table_get(VL_VA_DRIVER(ctx)->htab, buf_id);
269
mtx_unlock(&drv->mutex);
270
271
if (!buf)
272
return VA_STATUS_ERROR_INVALID_BUFFER;
273
274
/* Only VA surface|image like buffers are supported for now .*/
275
if (buf->type != VAImageBufferType)
276
return VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
277
278
if (!out_buf_info)
279
return VA_STATUS_ERROR_INVALID_PARAMETER;
280
281
if (!out_buf_info->mem_type)
282
mem_type = mem_types[0];
283
else {
284
mem_type = 0;
285
for (i = 0; mem_types[i] != 0; i++) {
286
if (out_buf_info->mem_type & mem_types[i]) {
287
mem_type = out_buf_info->mem_type;
288
break;
289
}
290
}
291
if (!mem_type)
292
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
293
}
294
295
if (!buf->derived_surface.resource)
296
return VA_STATUS_ERROR_INVALID_BUFFER;
297
298
if (buf->export_refcount > 0) {
299
if (buf->export_state.mem_type != mem_type)
300
return VA_STATUS_ERROR_INVALID_PARAMETER;
301
} else {
302
VABufferInfo * const buf_info = &buf->export_state;
303
304
switch (mem_type) {
305
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME: {
306
struct winsys_handle whandle;
307
308
mtx_lock(&drv->mutex);
309
drv->pipe->flush(drv->pipe, NULL, 0);
310
311
memset(&whandle, 0, sizeof(whandle));
312
whandle.type = WINSYS_HANDLE_TYPE_FD;
313
314
if (!screen->resource_get_handle(screen, drv->pipe,
315
buf->derived_surface.resource,
316
&whandle, PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE)) {
317
mtx_unlock(&drv->mutex);
318
return VA_STATUS_ERROR_INVALID_BUFFER;
319
}
320
321
mtx_unlock(&drv->mutex);
322
323
buf_info->handle = (intptr_t)whandle.handle;
324
break;
325
}
326
default:
327
return VA_STATUS_ERROR_UNSUPPORTED_MEMORY_TYPE;
328
}
329
330
buf_info->type = buf->type;
331
buf_info->mem_type = mem_type;
332
buf_info->mem_size = buf->num_elements * buf->size;
333
}
334
335
buf->export_refcount++;
336
337
*out_buf_info = buf->export_state;
338
339
return VA_STATUS_SUCCESS;
340
}
341
342
VAStatus
343
vlVaReleaseBufferHandle(VADriverContextP ctx, VABufferID buf_id)
344
{
345
vlVaDriver *drv;
346
vlVaBuffer *buf;
347
348
if (!ctx)
349
return VA_STATUS_ERROR_INVALID_CONTEXT;
350
351
drv = VL_VA_DRIVER(ctx);
352
mtx_lock(&drv->mutex);
353
buf = handle_table_get(drv->htab, buf_id);
354
mtx_unlock(&drv->mutex);
355
356
if (!buf)
357
return VA_STATUS_ERROR_INVALID_BUFFER;
358
359
if (buf->export_refcount == 0)
360
return VA_STATUS_ERROR_INVALID_BUFFER;
361
362
if (--buf->export_refcount == 0) {
363
VABufferInfo * const buf_info = &buf->export_state;
364
365
switch (buf_info->mem_type) {
366
case VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME:
367
close((intptr_t)buf_info->handle);
368
break;
369
default:
370
return VA_STATUS_ERROR_INVALID_BUFFER;
371
}
372
373
buf_info->mem_type = 0;
374
}
375
376
return VA_STATUS_SUCCESS;
377
}
378
379