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