Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/va/image.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
31
#include "util/u_memory.h"
32
#include "util/u_handle_table.h"
33
#include "util/u_surface.h"
34
#include "util/u_video.h"
35
#include "util/u_process.h"
36
37
#include "vl/vl_winsys.h"
38
#include "vl/vl_video_buffer.h"
39
40
#include "va_private.h"
41
42
static const VAImageFormat formats[] =
43
{
44
{VA_FOURCC('N','V','1','2')},
45
{VA_FOURCC('P','0','1','0')},
46
{VA_FOURCC('P','0','1','6')},
47
{VA_FOURCC('I','4','2','0')},
48
{VA_FOURCC('Y','V','1','2')},
49
{VA_FOURCC('Y','U','Y','V')},
50
{VA_FOURCC('Y','U','Y','2')},
51
{VA_FOURCC('U','Y','V','Y')},
52
{.fourcc = VA_FOURCC('B','G','R','A'), .byte_order = VA_LSB_FIRST, 32, 32,
53
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000},
54
{.fourcc = VA_FOURCC('R','G','B','A'), .byte_order = VA_LSB_FIRST, 32, 32,
55
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000},
56
{.fourcc = VA_FOURCC('B','G','R','X'), .byte_order = VA_LSB_FIRST, 32, 24,
57
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
58
{.fourcc = VA_FOURCC('R','G','B','X'), .byte_order = VA_LSB_FIRST, 32, 24,
59
0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}
60
};
61
62
static void
63
vlVaVideoSurfaceSize(vlVaSurface *p_surf, int component,
64
unsigned *width, unsigned *height)
65
{
66
*width = p_surf->templat.width;
67
*height = p_surf->templat.height;
68
69
vl_video_buffer_adjust_size(width, height, component,
70
pipe_format_to_chroma_format(p_surf->templat.buffer_format),
71
p_surf->templat.interlaced);
72
}
73
74
VAStatus
75
vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats)
76
{
77
struct pipe_screen *pscreen;
78
enum pipe_format format;
79
int i;
80
81
STATIC_ASSERT(ARRAY_SIZE(formats) == VL_VA_MAX_IMAGE_FORMATS);
82
83
if (!ctx)
84
return VA_STATUS_ERROR_INVALID_CONTEXT;
85
86
if (!(format_list && num_formats))
87
return VA_STATUS_ERROR_INVALID_PARAMETER;
88
89
*num_formats = 0;
90
pscreen = VL_VA_PSCREEN(ctx);
91
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
92
format = VaFourccToPipeFormat(formats[i].fourcc);
93
if (pscreen->is_video_format_supported(pscreen, format,
94
PIPE_VIDEO_PROFILE_UNKNOWN,
95
PIPE_VIDEO_ENTRYPOINT_BITSTREAM))
96
format_list[(*num_formats)++] = formats[i];
97
}
98
99
return VA_STATUS_SUCCESS;
100
}
101
102
VAStatus
103
vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image)
104
{
105
VAStatus status;
106
vlVaDriver *drv;
107
VAImage *img;
108
int w, h;
109
110
if (!ctx)
111
return VA_STATUS_ERROR_INVALID_CONTEXT;
112
113
if (!(format && image && width && height))
114
return VA_STATUS_ERROR_INVALID_PARAMETER;
115
116
drv = VL_VA_DRIVER(ctx);
117
118
img = CALLOC(1, sizeof(VAImage));
119
if (!img)
120
return VA_STATUS_ERROR_ALLOCATION_FAILED;
121
mtx_lock(&drv->mutex);
122
img->image_id = handle_table_add(drv->htab, img);
123
mtx_unlock(&drv->mutex);
124
125
img->format = *format;
126
img->width = width;
127
img->height = height;
128
w = align(width, 2);
129
h = align(height, 2);
130
131
switch (format->fourcc) {
132
case VA_FOURCC('N','V','1','2'):
133
img->num_planes = 2;
134
img->pitches[0] = w;
135
img->offsets[0] = 0;
136
img->pitches[1] = w;
137
img->offsets[1] = w * h;
138
img->data_size = w * h * 3 / 2;
139
break;
140
141
case VA_FOURCC('P','0','1','0'):
142
case VA_FOURCC('P','0','1','6'):
143
img->num_planes = 2;
144
img->pitches[0] = w * 2;
145
img->offsets[0] = 0;
146
img->pitches[1] = w * 2;
147
img->offsets[1] = w * h * 2;
148
img->data_size = w * h * 3;
149
break;
150
151
case VA_FOURCC('I','4','2','0'):
152
case VA_FOURCC('Y','V','1','2'):
153
img->num_planes = 3;
154
img->pitches[0] = w;
155
img->offsets[0] = 0;
156
img->pitches[1] = w / 2;
157
img->offsets[1] = w * h;
158
img->pitches[2] = w / 2;
159
img->offsets[2] = w * h * 5 / 4;
160
img->data_size = w * h * 3 / 2;
161
break;
162
163
case VA_FOURCC('U','Y','V','Y'):
164
case VA_FOURCC('Y','U','Y','V'):
165
case VA_FOURCC('Y','U','Y','2'):
166
img->num_planes = 1;
167
img->pitches[0] = w * 2;
168
img->offsets[0] = 0;
169
img->data_size = w * h * 2;
170
break;
171
172
case VA_FOURCC('B','G','R','A'):
173
case VA_FOURCC('R','G','B','A'):
174
case VA_FOURCC('B','G','R','X'):
175
case VA_FOURCC('R','G','B','X'):
176
img->num_planes = 1;
177
img->pitches[0] = w * 4;
178
img->offsets[0] = 0;
179
img->data_size = w * h * 4;
180
break;
181
182
default:
183
return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
184
}
185
186
status = vlVaCreateBuffer(ctx, 0, VAImageBufferType,
187
align(img->data_size, 16),
188
1, NULL, &img->buf);
189
if (status != VA_STATUS_SUCCESS)
190
return status;
191
*image = *img;
192
193
return status;
194
}
195
196
VAStatus
197
vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image)
198
{
199
vlVaDriver *drv;
200
vlVaSurface *surf;
201
vlVaBuffer *img_buf;
202
VAImage *img;
203
VAStatus status;
204
struct pipe_screen *screen;
205
struct pipe_surface **surfaces;
206
struct pipe_video_buffer *new_buffer = NULL;
207
int w;
208
int h;
209
int i;
210
unsigned stride = 0;
211
unsigned offset = 0;
212
213
/* This function is used by some programs to test for hardware decoding, but on
214
* AMD devices, the buffers default to interlaced, which causes this function to fail.
215
* Some programs expect this function to fail, while others, assume this means
216
* hardware acceleration is not available and give up without trying the fall-back
217
* vaCreateImage + vaPutImage
218
*/
219
const char *proc = util_get_process_name();
220
const char *derive_interlaced_allowlist[] = {
221
"vlc",
222
"h264encode",
223
"hevcencode"
224
};
225
226
if (!ctx)
227
return VA_STATUS_ERROR_INVALID_CONTEXT;
228
229
drv = VL_VA_DRIVER(ctx);
230
231
if (!drv)
232
return VA_STATUS_ERROR_INVALID_CONTEXT;
233
234
screen = VL_VA_PSCREEN(ctx);
235
236
if (!screen)
237
return VA_STATUS_ERROR_INVALID_CONTEXT;
238
239
surf = handle_table_get(drv->htab, surface);
240
241
if (!surf || !surf->buffer)
242
return VA_STATUS_ERROR_INVALID_SURFACE;
243
244
if (surf->buffer->interlaced) {
245
for (i = 0; i < ARRAY_SIZE(derive_interlaced_allowlist); i++)
246
if ((strcmp(derive_interlaced_allowlist[i], proc) == 0))
247
break;
248
249
if (i >= ARRAY_SIZE(derive_interlaced_allowlist) ||
250
!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_UNKNOWN,
251
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
252
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE))
253
return VA_STATUS_ERROR_OPERATION_FAILED;
254
}
255
256
surfaces = surf->buffer->get_surfaces(surf->buffer);
257
if (!surfaces || !surfaces[0]->texture)
258
return VA_STATUS_ERROR_ALLOCATION_FAILED;
259
260
img = CALLOC(1, sizeof(VAImage));
261
if (!img)
262
return VA_STATUS_ERROR_ALLOCATION_FAILED;
263
264
img->format.fourcc = PipeFormatToVaFourcc(surf->buffer->buffer_format);
265
img->buf = VA_INVALID_ID;
266
/* Use the visible dimensions. */
267
img->width = surf->templat.width;
268
img->height = surf->templat.height;
269
img->num_palette_entries = 0;
270
img->entry_bytes = 0;
271
/* Image data size is computed using internal dimensions. */
272
w = align(surf->buffer->width, 2);
273
h = align(surf->buffer->height, 2);
274
275
for (i = 0; i < ARRAY_SIZE(formats); ++i) {
276
if (img->format.fourcc == formats[i].fourcc) {
277
img->format = formats[i];
278
break;
279
}
280
}
281
282
mtx_lock(&drv->mutex);
283
if (screen->resource_get_info) {
284
screen->resource_get_info(screen, surfaces[0]->texture, &stride,
285
&offset);
286
if (!stride)
287
offset = 0;
288
}
289
290
img->num_planes = 1;
291
img->offsets[0] = offset;
292
293
switch (img->format.fourcc) {
294
case VA_FOURCC('U','Y','V','Y'):
295
case VA_FOURCC('Y','U','Y','V'):
296
img->pitches[0] = stride > 0 ? stride : w * 2;
297
assert(img->pitches[0] >= (w * 2));
298
img->data_size = img->pitches[0] * h;
299
break;
300
301
case VA_FOURCC('B','G','R','A'):
302
case VA_FOURCC('R','G','B','A'):
303
case VA_FOURCC('B','G','R','X'):
304
case VA_FOURCC('R','G','B','X'):
305
img->pitches[0] = stride > 0 ? stride : w * 4;
306
assert(img->pitches[0] >= (w * 4));
307
img->data_size = img->pitches[0] * h;
308
break;
309
310
case VA_FOURCC('N','V','1','2'):
311
case VA_FOURCC('P','0','1','0'):
312
case VA_FOURCC('P','0','1','6'):
313
if (surf->buffer->interlaced) {
314
struct u_rect src_rect, dst_rect;
315
struct pipe_video_buffer new_template;
316
317
new_template = surf->templat;
318
new_template.interlaced = false;
319
new_buffer = drv->pipe->create_video_buffer(drv->pipe, &new_template);
320
321
/* not all devices support non-interlaced buffers */
322
if (!new_buffer) {
323
status = VA_STATUS_ERROR_OPERATION_FAILED;
324
goto exit_on_error;
325
}
326
327
/* convert the interlaced to the progressive */
328
src_rect.x0 = dst_rect.x0 = 0;
329
src_rect.x1 = dst_rect.x1 = surf->templat.width;
330
src_rect.y0 = dst_rect.y0 = 0;
331
src_rect.y1 = dst_rect.y1 = surf->templat.height;
332
333
vl_compositor_yuv_deint_full(&drv->cstate, &drv->compositor,
334
surf->buffer, new_buffer,
335
&src_rect, &dst_rect,
336
VL_COMPOSITOR_WEAVE);
337
338
/* recalculate the values now that we have a new surface */
339
surfaces = surf->buffer->get_surfaces(new_buffer);
340
if (screen->resource_get_info) {
341
screen->resource_get_info(screen, surfaces[0]->texture, &stride,
342
&offset);
343
if (!stride)
344
offset = 0;
345
}
346
347
w = align(new_buffer->width, 2);
348
h = align(new_buffer->height, 2);
349
}
350
351
img->num_planes = 2;
352
img->pitches[0] = stride > 0 ? stride : w;
353
img->pitches[1] = stride > 0 ? stride : w;
354
img->offsets[1] = (stride > 0 ? stride : w) * h;
355
img->data_size = (stride > 0 ? stride : w) * h * 3 / 2;
356
break;
357
358
default:
359
/* VaDeriveImage only supports contiguous planes. But there is now a
360
more generic api vlVaExportSurfaceHandle. */
361
status = VA_STATUS_ERROR_OPERATION_FAILED;
362
goto exit_on_error;
363
}
364
365
img_buf = CALLOC(1, sizeof(vlVaBuffer));
366
if (!img_buf) {
367
status = VA_STATUS_ERROR_ALLOCATION_FAILED;
368
goto exit_on_error;
369
}
370
371
img->image_id = handle_table_add(drv->htab, img);
372
373
img_buf->type = VAImageBufferType;
374
img_buf->size = img->data_size;
375
img_buf->num_elements = 1;
376
377
pipe_resource_reference(&img_buf->derived_surface.resource, surfaces[0]->texture);
378
img_buf->derived_image_buffer = new_buffer;
379
380
img->buf = handle_table_add(VL_VA_DRIVER(ctx)->htab, img_buf);
381
mtx_unlock(&drv->mutex);
382
383
*image = *img;
384
385
return VA_STATUS_SUCCESS;
386
387
exit_on_error:
388
FREE(img);
389
mtx_unlock(&drv->mutex);
390
return status;
391
}
392
393
VAStatus
394
vlVaDestroyImage(VADriverContextP ctx, VAImageID image)
395
{
396
vlVaDriver *drv;
397
VAImage *vaimage;
398
VAStatus status;
399
400
if (!ctx)
401
return VA_STATUS_ERROR_INVALID_CONTEXT;
402
403
drv = VL_VA_DRIVER(ctx);
404
mtx_lock(&drv->mutex);
405
vaimage = handle_table_get(drv->htab, image);
406
if (!vaimage) {
407
mtx_unlock(&drv->mutex);
408
return VA_STATUS_ERROR_INVALID_IMAGE;
409
}
410
411
handle_table_remove(VL_VA_DRIVER(ctx)->htab, image);
412
mtx_unlock(&drv->mutex);
413
status = vlVaDestroyBuffer(ctx, vaimage->buf);
414
FREE(vaimage);
415
return status;
416
}
417
418
VAStatus
419
vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette)
420
{
421
if (!ctx)
422
return VA_STATUS_ERROR_INVALID_CONTEXT;
423
424
return VA_STATUS_ERROR_UNIMPLEMENTED;
425
}
426
427
VAStatus
428
vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y,
429
unsigned int width, unsigned int height, VAImageID image)
430
{
431
vlVaDriver *drv;
432
vlVaSurface *surf;
433
vlVaBuffer *img_buf;
434
VAImage *vaimage;
435
struct pipe_sampler_view **views;
436
enum pipe_format format;
437
bool convert = false;
438
void *data[3];
439
unsigned pitches[3], i, j;
440
441
if (!ctx)
442
return VA_STATUS_ERROR_INVALID_CONTEXT;
443
444
drv = VL_VA_DRIVER(ctx);
445
446
mtx_lock(&drv->mutex);
447
surf = handle_table_get(drv->htab, surface);
448
if (!surf || !surf->buffer) {
449
mtx_unlock(&drv->mutex);
450
return VA_STATUS_ERROR_INVALID_SURFACE;
451
}
452
453
vaimage = handle_table_get(drv->htab, image);
454
if (!vaimage) {
455
mtx_unlock(&drv->mutex);
456
return VA_STATUS_ERROR_INVALID_IMAGE;
457
}
458
459
if (x < 0 || y < 0) {
460
mtx_unlock(&drv->mutex);
461
return VA_STATUS_ERROR_INVALID_PARAMETER;
462
}
463
464
if (x + width > surf->templat.width ||
465
y + height > surf->templat.height) {
466
mtx_unlock(&drv->mutex);
467
return VA_STATUS_ERROR_INVALID_PARAMETER;
468
}
469
470
if (width > vaimage->width ||
471
height > vaimage->height) {
472
mtx_unlock(&drv->mutex);
473
return VA_STATUS_ERROR_INVALID_PARAMETER;
474
}
475
476
img_buf = handle_table_get(drv->htab, vaimage->buf);
477
if (!img_buf) {
478
mtx_unlock(&drv->mutex);
479
return VA_STATUS_ERROR_INVALID_BUFFER;
480
}
481
482
format = VaFourccToPipeFormat(vaimage->format.fourcc);
483
if (format == PIPE_FORMAT_NONE) {
484
mtx_unlock(&drv->mutex);
485
return VA_STATUS_ERROR_OPERATION_FAILED;
486
}
487
488
489
if (format != surf->buffer->buffer_format) {
490
/* support NV12 to YV12 and IYUV conversion now only */
491
if ((format == PIPE_FORMAT_YV12 &&
492
surf->buffer->buffer_format == PIPE_FORMAT_NV12) ||
493
(format == PIPE_FORMAT_IYUV &&
494
surf->buffer->buffer_format == PIPE_FORMAT_NV12))
495
convert = true;
496
else if (format == PIPE_FORMAT_NV12 &&
497
(surf->buffer->buffer_format == PIPE_FORMAT_P010 ||
498
surf->buffer->buffer_format == PIPE_FORMAT_P016)) {
499
mtx_unlock(&drv->mutex);
500
return VA_STATUS_ERROR_OPERATION_FAILED;
501
}
502
else {
503
mtx_unlock(&drv->mutex);
504
return VA_STATUS_ERROR_OPERATION_FAILED;
505
}
506
}
507
508
views = surf->buffer->get_sampler_view_planes(surf->buffer);
509
if (!views) {
510
mtx_unlock(&drv->mutex);
511
return VA_STATUS_ERROR_OPERATION_FAILED;
512
}
513
514
for (i = 0; i < vaimage->num_planes; i++) {
515
data[i] = img_buf->data + vaimage->offsets[i];
516
pitches[i] = vaimage->pitches[i];
517
}
518
if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
519
void *tmp_d;
520
unsigned tmp_p;
521
tmp_d = data[1];
522
data[1] = data[2];
523
data[2] = tmp_d;
524
tmp_p = pitches[1];
525
pitches[1] = pitches[2];
526
pitches[2] = tmp_p;
527
}
528
529
for (i = 0; i < vaimage->num_planes; i++) {
530
unsigned box_w = align(width, 2);
531
unsigned box_h = align(height, 2);
532
unsigned box_x = x & ~1;
533
unsigned box_y = y & ~1;
534
if (!views[i]) continue;
535
vl_video_buffer_adjust_size(&box_w, &box_h, i,
536
pipe_format_to_chroma_format(surf->templat.buffer_format),
537
surf->templat.interlaced);
538
vl_video_buffer_adjust_size(&box_x, &box_y, i,
539
pipe_format_to_chroma_format(surf->templat.buffer_format),
540
surf->templat.interlaced);
541
for (j = 0; j < views[i]->texture->array_size; ++j) {
542
struct pipe_box box = {box_x, box_y, j, box_w, box_h, 1};
543
struct pipe_transfer *transfer;
544
uint8_t *map;
545
map = drv->pipe->texture_map(drv->pipe, views[i]->texture, 0,
546
PIPE_MAP_READ, &box, &transfer);
547
if (!map) {
548
mtx_unlock(&drv->mutex);
549
return VA_STATUS_ERROR_OPERATION_FAILED;
550
}
551
552
if (i == 1 && convert) {
553
u_copy_nv12_to_yv12(data, pitches, i, j,
554
transfer->stride, views[i]->texture->array_size,
555
map, box.width, box.height);
556
} else {
557
util_copy_rect(data[i] + pitches[i] * j,
558
views[i]->texture->format,
559
pitches[i] * views[i]->texture->array_size, 0, 0,
560
box.width, box.height, map, transfer->stride, 0, 0);
561
}
562
pipe_texture_unmap(drv->pipe, transfer);
563
}
564
}
565
mtx_unlock(&drv->mutex);
566
567
return VA_STATUS_SUCCESS;
568
}
569
570
VAStatus
571
vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image,
572
int src_x, int src_y, unsigned int src_width, unsigned int src_height,
573
int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height)
574
{
575
vlVaDriver *drv;
576
vlVaSurface *surf;
577
vlVaBuffer *img_buf;
578
VAImage *vaimage;
579
struct pipe_sampler_view **views;
580
enum pipe_format format;
581
void *data[3];
582
unsigned pitches[3], i, j;
583
584
if (!ctx)
585
return VA_STATUS_ERROR_INVALID_CONTEXT;
586
587
drv = VL_VA_DRIVER(ctx);
588
mtx_lock(&drv->mutex);
589
590
surf = handle_table_get(drv->htab, surface);
591
if (!surf || !surf->buffer) {
592
mtx_unlock(&drv->mutex);
593
return VA_STATUS_ERROR_INVALID_SURFACE;
594
}
595
596
vaimage = handle_table_get(drv->htab, image);
597
if (!vaimage) {
598
mtx_unlock(&drv->mutex);
599
return VA_STATUS_ERROR_INVALID_IMAGE;
600
}
601
602
img_buf = handle_table_get(drv->htab, vaimage->buf);
603
if (!img_buf) {
604
mtx_unlock(&drv->mutex);
605
return VA_STATUS_ERROR_INVALID_BUFFER;
606
}
607
608
if (img_buf->derived_surface.resource) {
609
/* Attempting to transfer derived image to surface */
610
mtx_unlock(&drv->mutex);
611
return VA_STATUS_ERROR_UNIMPLEMENTED;
612
}
613
614
format = VaFourccToPipeFormat(vaimage->format.fourcc);
615
616
if (format == PIPE_FORMAT_NONE) {
617
mtx_unlock(&drv->mutex);
618
return VA_STATUS_ERROR_OPERATION_FAILED;
619
}
620
621
if ((format != surf->buffer->buffer_format) &&
622
((format != PIPE_FORMAT_YV12) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12)) &&
623
((format != PIPE_FORMAT_IYUV) || (surf->buffer->buffer_format != PIPE_FORMAT_NV12))) {
624
struct pipe_video_buffer *tmp_buf;
625
626
surf->templat.buffer_format = format;
627
if (format == PIPE_FORMAT_YUYV || format == PIPE_FORMAT_UYVY ||
628
format == PIPE_FORMAT_B8G8R8A8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM ||
629
format == PIPE_FORMAT_R8G8B8A8_UNORM || format == PIPE_FORMAT_R8G8B8X8_UNORM)
630
surf->templat.interlaced = false;
631
tmp_buf = drv->pipe->create_video_buffer(drv->pipe, &surf->templat);
632
633
if (!tmp_buf) {
634
mtx_unlock(&drv->mutex);
635
return VA_STATUS_ERROR_ALLOCATION_FAILED;
636
}
637
638
surf->buffer->destroy(surf->buffer);
639
surf->buffer = tmp_buf;
640
}
641
642
views = surf->buffer->get_sampler_view_planes(surf->buffer);
643
if (!views) {
644
mtx_unlock(&drv->mutex);
645
return VA_STATUS_ERROR_OPERATION_FAILED;
646
}
647
648
for (i = 0; i < vaimage->num_planes; i++) {
649
data[i] = img_buf->data + vaimage->offsets[i];
650
pitches[i] = vaimage->pitches[i];
651
}
652
if (vaimage->format.fourcc == VA_FOURCC('I','4','2','0')) {
653
void *tmp_d;
654
unsigned tmp_p;
655
tmp_d = data[1];
656
data[1] = data[2];
657
data[2] = tmp_d;
658
tmp_p = pitches[1];
659
pitches[1] = pitches[2];
660
pitches[2] = tmp_p;
661
}
662
663
for (i = 0; i < vaimage->num_planes; ++i) {
664
unsigned width, height;
665
struct pipe_resource *tex;
666
667
if (!views[i]) continue;
668
tex = views[i]->texture;
669
670
vlVaVideoSurfaceSize(surf, i, &width, &height);
671
for (j = 0; j < tex->array_size; ++j) {
672
struct pipe_box dst_box = {0, 0, j, width, height, 1};
673
674
if (((format == PIPE_FORMAT_YV12) || (format == PIPE_FORMAT_IYUV))
675
&& (surf->buffer->buffer_format == PIPE_FORMAT_NV12)
676
&& i == 1) {
677
struct pipe_transfer *transfer = NULL;
678
uint8_t *map = NULL;
679
680
map = drv->pipe->texture_map(drv->pipe,
681
tex,
682
0,
683
PIPE_MAP_WRITE |
684
PIPE_MAP_DISCARD_RANGE,
685
&dst_box, &transfer);
686
if (map == NULL) {
687
mtx_unlock(&drv->mutex);
688
return VA_STATUS_ERROR_OPERATION_FAILED;
689
}
690
691
u_copy_nv12_from_yv12((const void * const*) data, pitches, i, j,
692
transfer->stride, tex->array_size,
693
map, dst_box.width, dst_box.height);
694
pipe_texture_unmap(drv->pipe, transfer);
695
} else {
696
drv->pipe->texture_subdata(drv->pipe, tex, 0,
697
PIPE_MAP_WRITE, &dst_box,
698
data[i] + pitches[i] * j,
699
pitches[i] * views[i]->texture->array_size, 0);
700
}
701
}
702
}
703
drv->pipe->flush(drv->pipe, NULL, 0);
704
mtx_unlock(&drv->mutex);
705
706
return VA_STATUS_SUCCESS;
707
}
708
709