image.c revision 7ec681f3
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 42static 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 62static void 63vlVaVideoSurfaceSize(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 74VAStatus 75vlVaQueryImageFormats(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 102VAStatus 103vlVaCreateImage(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 196VAStatus 197vlVaDeriveImage(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 387exit_on_error: 388 FREE(img); 389 mtx_unlock(&drv->mutex); 390 return status; 391} 392 393VAStatus 394vlVaDestroyImage(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 418VAStatus 419vlVaSetImagePalette(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 427VAStatus 428vlVaGetImage(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 570VAStatus 571vlVaPutImage(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