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