psb_surface_attrib.c revision 684f0e29e29ca32fad49439cfe0392417361d34d
1/* 2 * Copyright (c) 2011 Intel Corporation. All Rights Reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sub license, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the 13 * next paragraph) shall be included in all copies or substantial portions 14 * of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26#include <sys/mman.h> 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <sys/ioctl.h> 30#include <fcntl.h> 31#include <linux/ion.h> 32#include <va/va_tpi.h> 33#include "psb_drv_video.h" 34#include "psb_drv_debug.h" 35#include "psb_surface.h" 36#include "psb_surface_attrib.h" 37 38 39#define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData; 40 41#define CONFIG(id) ((object_config_p) object_heap_lookup( &driver_data->config_heap, id )) 42#define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id )) 43#define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id )) 44#define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id )) 45 46 47/* 48 * Create surface 49 */ 50VAStatus psb_surface_create_from_ub( 51 psb_driver_data_p driver_data, 52 int width, int height, int fourcc, 53 VASurfaceAttributeTPI *graphic_buffers, 54 psb_surface_p psb_surface, /* out */ 55 void *vaddr, 56 unsigned flags 57) 58{ 59 int ret = 0; 60 61 if (fourcc == VA_FOURCC_NV12) { 62 if ((width <= 0) || (width * height > 5120 * 5120) || (height <= 0)) { 63 return VA_STATUS_ERROR_ALLOCATION_FAILED; 64 } 65 66 psb_surface->stride = graphic_buffers->luma_stride; 67 if (0) { 68 ; 69 } else if (512 == graphic_buffers->luma_stride) { 70 psb_surface->stride_mode = STRIDE_512; 71 } else if (1024 == graphic_buffers->luma_stride) { 72 psb_surface->stride_mode = STRIDE_1024; 73 } else if (1280 == graphic_buffers->luma_stride) { 74 psb_surface->stride_mode = STRIDE_1280; 75#ifdef PSBVIDEO_MSVDX_DEC_TILING 76 if (graphic_buffers->tiling) { 77 psb_surface->stride_mode = STRIDE_2048; 78 psb_surface->stride = 2048; 79 } 80#endif 81 } else if (2048 == graphic_buffers->luma_stride) { 82 psb_surface->stride_mode = STRIDE_2048; 83 } else if (4096 == graphic_buffers->luma_stride) { 84 psb_surface->stride_mode = STRIDE_4096; 85 } else { 86 psb_surface->stride_mode = STRIDE_NA; 87 } 88 if (psb_surface->stride != graphic_buffers->luma_stride) { 89 return VA_STATUS_ERROR_ALLOCATION_FAILED; 90 } 91 92 psb_surface->luma_offset = 0; 93 psb_surface->chroma_offset = psb_surface->stride * height; 94 psb_surface->size = (psb_surface->stride * height * 3) / 2; 95 psb_surface->extra_info[4] = VA_FOURCC_NV12; 96 } else { 97 return VA_STATUS_ERROR_ALLOCATION_FAILED; 98 } 99#ifdef PSBVIDEO_MSVDX_DEC_TILING 100 if (graphic_buffers->tiling) 101 ret = psb_buffer_create_from_ub(driver_data, psb_surface->size, 102 psb_bt_mmu_tiling, &psb_surface->buf, 103 vaddr, 0); 104 else 105#endif 106 ret = psb_buffer_create_from_ub(driver_data, psb_surface->size, 107 psb_bt_surface, &psb_surface->buf, 108 vaddr, flags); 109 110 return ret ? VA_STATUS_ERROR_ALLOCATION_FAILED : VA_STATUS_SUCCESS; 111} 112 113#if 0 114VAStatus psb_CreateSurfaceFromV4L2Buf( 115 VADriverContextP ctx, 116 int v4l2_fd, /* file descriptor of V4L2 device */ 117 struct v4l2_format *v4l2_fmt, /* format of V4L2 */ 118 struct v4l2_buffer *v4l2_buf, /* V4L2 buffer */ 119 VASurfaceID *surface /* out */ 120) 121{ 122 INIT_DRIVER_DATA; 123 VAStatus vaStatus = VA_STATUS_SUCCESS; 124 int surfaceID; 125 object_surface_p obj_surface; 126 psb_surface_p psb_surface; 127 int width, height, buf_stride, buf_offset, size; 128 unsigned long *user_ptr = NULL; 129 130 if (IS_MRST(driver_data) == 0 && IS_MFLD(driver_data) == 0) { 131 drv_debug_msg(VIDEO_DEBUG_ERROR, "CreateSurfaceFromV4L2Buf isn't supported on non-MRST platform\n"); 132 return VA_STATUS_ERROR_UNKNOWN; 133 } 134 135 /* Todo: 136 * sanity check if the v4l2 device on MRST is supported 137 */ 138 if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) { 139 unsigned long tmp = (unsigned long)(v4l2_buf->m.userptr); 140 141 if (tmp & 0xfff) { 142 drv_debug_msg(VIDEO_DEBUG_ERROR, "The buffer address 0x%08x must be page aligned\n", tmp); 143 return VA_STATUS_ERROR_UNKNOWN; 144 } 145 } 146 147 surfaceID = object_heap_allocate(&driver_data->surface_heap); 148 obj_surface = SURFACE(surfaceID); 149 CHECK_ALLOCATION(obj_surface); 150 151 MEMSET_OBJECT(obj_surface, struct object_surface_s); 152 153 width = v4l2_fmt->fmt.pix.width; 154 height = v4l2_fmt->fmt.pix.height; 155 156 buf_stride = width; /* ? */ 157 buf_offset = v4l2_buf->m.offset; 158 size = v4l2_buf->length; 159 160 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create Surface from V4L2 buffer: %dx%d, stride=%d, buffer offset=0x%08x, size=%d\n", 161 width, height, buf_stride, buf_offset, size); 162 163 obj_surface->surface_id = surfaceID; 164 *surface = surfaceID; 165 obj_surface->context_id = -1; 166 obj_surface->width = width; 167 obj_surface->height = height; 168 obj_surface->subpictures = NULL; 169 obj_surface->subpic_count = 0; 170 obj_surface->derived_imgcnt = 0; 171 obj_surface->display_timestamp = 0; 172 173 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 174 if (NULL == psb_surface) { 175 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 176 obj_surface->surface_id = VA_INVALID_SURFACE; 177 178 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 179 180 DEBUG_FAILURE; 181 182 return vaStatus; 183 } 184 185#if PSB_MFLD_DUMMY_CODE 186 /* current assume it is NV12 */ 187 if (IS_MRST(driver_data)) 188 vaStatus = psb_surface_create_camera(driver_data, width, height, buf_stride, size, psb_surface, 1, buf_offset); 189 else { 190 if (V4L2_MEMORY_USERPTR == v4l2_buf->memory) 191 user_ptr = (unsigned long *)(v4l2_buf->m.userptr); 192 else { 193 user_ptr = mmap(NULL /* start anywhere */ , 194 v4l2_buf->length, 195 PROT_READ , 196 MAP_SHARED /* recommended */ , 197 v4l2_fd, v4l2_buf->m.offset); 198 } 199 200 if (NULL != user_ptr && MAP_FAILED != user_ptr) 201 vaStatus = psb_surface_create_camera_from_ub(driver_data, width, height, 202 buf_stride, size, psb_surface, 1, buf_offset, user_ptr); 203 else { 204 DEBUG_FAILURE; 205 vaStatus = VA_STATUS_ERROR_UNKNOWN; 206 } 207 } 208#else 209 vaStatus = VA_STATUS_ERROR_UNKNOWN; 210#endif 211 212 213 if (VA_STATUS_SUCCESS != vaStatus) { 214 free(psb_surface); 215 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 216 obj_surface->surface_id = VA_INVALID_SURFACE; 217 218 DEBUG_FAILURE; 219 220 return vaStatus; 221 } 222 223 memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); 224 psb_surface->extra_info[4] = VA_FOURCC_NV12; /* temp treat is as IYUV */ 225 226 obj_surface->psb_surface = psb_surface; 227 228 /* Error recovery */ 229 if (VA_STATUS_SUCCESS != vaStatus) { 230 object_surface_p obj_surface = SURFACE(*surface); 231 psb__destroy_surface(driver_data, obj_surface); 232 *surface = VA_INVALID_SURFACE; 233 } 234 235 return vaStatus; 236} 237#endif 238 239 240VAStatus psb_CreateSurfacesForUserPtr( 241 VADriverContextP ctx, 242 int Width, 243 int Height, 244 int format, 245 int num_surfaces, 246 VASurfaceID *surface_list, /* out */ 247 unsigned size, /* total buffer size need to be allocated */ 248 unsigned int fourcc, /* expected fourcc */ 249 unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ 250 unsigned int chroma_u_stride, /* chroma stride */ 251 unsigned int chroma_v_stride, 252 unsigned int luma_offset, /* could be 0 */ 253 unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ 254 unsigned int chroma_v_offset 255) 256{ 257 INIT_DRIVER_DATA 258 VAStatus vaStatus = VA_STATUS_SUCCESS; 259 int i, height_origin; 260 unsigned long buffer_stride; 261 262 /* silient compiler warning */ 263 unsigned int width = (unsigned int)Width; 264 unsigned int height = (unsigned int)Height; 265 266 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x" 267 "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x" 268 "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d" 269 "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n", 270 width, height, format, 271 num_surfaces, size, fourcc, 272 luma_stride, chroma_u_stride, chroma_v_stride, 273 luma_offset, chroma_u_offset, chroma_v_offset); 274 275 CHECK_INVALID_PARAM(num_surfaces <= 0); 276 CHECK_SURFACE(surface_list); 277 278 /* We only support one format */ 279 if ((VA_RT_FORMAT_YUV420 != format) 280 && (VA_RT_FORMAT_YUV422 != format)) { 281 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 282 DEBUG_FAILURE; 283 return vaStatus; 284 } 285 286 /* We only support NV12/YV12 */ 287 if (((VA_RT_FORMAT_YUV420 == format) && (fourcc != VA_FOURCC_NV12)) || 288 ((VA_RT_FORMAT_YUV422 == format) && (fourcc != VA_FOURCC_YV16))) { 289 drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12/YV16 format\n"); 290 return VA_STATUS_ERROR_UNKNOWN; 291 } 292 /* 293 vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); 294 CHECK_VASTATUS(); 295 */ 296 297 CHECK_INVALID_PARAM((size < width * height * 1.5) || 298 (luma_stride < width) || 299 (chroma_u_stride * 2 < width) || 300 (chroma_v_stride * 2 < width) || 301 (chroma_u_offset < luma_offset + width * height) || 302 (chroma_v_offset < luma_offset + width * height)); 303 304 height_origin = height; 305 306 for (i = 0; i < num_surfaces; i++) { 307 int surfaceID; 308 object_surface_p obj_surface; 309 psb_surface_p psb_surface; 310 311 surfaceID = object_heap_allocate(&driver_data->surface_heap); 312 obj_surface = SURFACE(surfaceID); 313 if (NULL == obj_surface) { 314 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 315 DEBUG_FAILURE; 316 break; 317 } 318 MEMSET_OBJECT(obj_surface, struct object_surface_s); 319 320 obj_surface->surface_id = surfaceID; 321 surface_list[i] = surfaceID; 322 obj_surface->context_id = -1; 323 obj_surface->width = width; 324 obj_surface->height = height; 325 obj_surface->width_r = width; 326 obj_surface->height_r = height; 327 obj_surface->height_origin = height_origin; 328 329 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 330 if (NULL == psb_surface) { 331 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 332 obj_surface->surface_id = VA_INVALID_SURFACE; 333 334 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 335 336 DEBUG_FAILURE; 337 break; 338 } 339 340 switch (format) { 341 case VA_RT_FORMAT_YUV422: 342 fourcc = VA_FOURCC_YV16; 343 break; 344 case VA_RT_FORMAT_YUV420: 345 default: 346 fourcc = VA_FOURCC_NV12; 347 break; 348 } 349 350 vaStatus = psb_surface_create_for_userptr(driver_data, width, height, 351 size, 352 fourcc, 353 luma_stride, 354 chroma_u_stride, 355 chroma_v_stride, 356 luma_offset, 357 chroma_u_offset, 358 chroma_v_offset, 359 psb_surface 360 ); 361 362 if (VA_STATUS_SUCCESS != vaStatus) { 363 free(psb_surface); 364 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 365 obj_surface->surface_id = VA_INVALID_SURFACE; 366 367 DEBUG_FAILURE; 368 break; 369 } 370 buffer_stride = psb_surface->stride; 371 /* by default, surface fourcc is NV12 */ 372 memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); 373 psb_surface->extra_info[4] = fourcc; 374 375 obj_surface->psb_surface = psb_surface; 376 } 377 378 /* Error recovery */ 379 if (VA_STATUS_SUCCESS != vaStatus) { 380 /* surface_list[i-1] was the last successful allocation */ 381 for (; i--;) { 382 object_surface_p obj_surface = SURFACE(surface_list[i]); 383 psb__destroy_surface(driver_data, obj_surface); 384 surface_list[i] = VA_INVALID_SURFACE; 385 } 386 } 387 388 389 return vaStatus; 390} 391 392VAStatus psb_CreateSurfaceFromKBuf( 393 VADriverContextP ctx, 394 int _width, 395 int _height, 396 int format, 397 VASurfaceID *surface, /* out */ 398 unsigned int kbuf_handle, /* kernel buffer handle*/ 399 unsigned size, /* kernel buffer size */ 400 unsigned int kBuf_fourcc, /* expected fourcc */ 401 unsigned int luma_stride, /* luma stride, could be width aligned with a special value */ 402 unsigned int chroma_u_stride, /* chroma stride */ 403 unsigned int chroma_v_stride, 404 unsigned int luma_offset, /* could be 0 */ 405 unsigned int chroma_u_offset, /* UV offset from the beginning of the memory */ 406 unsigned int chroma_v_offset 407) 408{ 409 INIT_DRIVER_DATA 410 VAStatus vaStatus = VA_STATUS_SUCCESS; 411 unsigned long buffer_stride; 412 413 /* silient compiler warning */ 414 unsigned int width = (unsigned int)_width; 415 unsigned int height = (unsigned int)_height; 416 417 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create surface: width %d, height %d, format 0x%08x" 418 "\n\t\t\t\t\tnum_surface %d, buffer size %d, fourcc 0x%08x" 419 "\n\t\t\t\t\tluma_stride %d, chroma u stride %d, chroma v stride %d" 420 "\n\t\t\t\t\tluma_offset %d, chroma u offset %d, chroma v offset %d\n", 421 width, height, format, 422 size, kBuf_fourcc, 423 luma_stride, chroma_u_stride, chroma_v_stride, 424 luma_offset, chroma_u_offset, chroma_v_offset); 425 426 CHECK_SURFACE(surface); 427 428 /* We only support one format */ 429 if ((VA_RT_FORMAT_YUV420 != format) 430 && (VA_RT_FORMAT_YUV422 != format)) { 431 vaStatus = VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; 432 DEBUG_FAILURE; 433 return vaStatus; 434 } 435 436 /* We only support NV12/YV12 */ 437 438 if (((VA_RT_FORMAT_YUV420 == format) && (kBuf_fourcc != VA_FOURCC_NV12)) || 439 ((VA_RT_FORMAT_YUV422 == format) && (kBuf_fourcc != VA_FOURCC_YV16))) { 440 drv_debug_msg(VIDEO_DEBUG_ERROR, "Only support NV12/YV16 format\n"); 441 return VA_STATUS_ERROR_UNKNOWN; 442 } 443 /* 444 vaStatus = psb__checkSurfaceDimensions(driver_data, width, height); 445 CHECK_VASTATUS(); 446 */ 447 448 CHECK_INVALID_PARAM((size < width * height * 1.5) || 449 (luma_stride < width) || 450 (chroma_u_stride * 2 < width) || 451 (chroma_v_stride * 2 < width) || 452 (chroma_u_offset < luma_offset + width * height) || 453 (chroma_v_offset < luma_offset + width * height)); 454 455 int surfaceID; 456 object_surface_p obj_surface; 457 psb_surface_p psb_surface; 458 459 surfaceID = object_heap_allocate(&driver_data->surface_heap); 460 obj_surface = SURFACE(surfaceID); 461 CHECK_ALLOCATION(obj_surface); 462 463 MEMSET_OBJECT(obj_surface, struct object_surface_s); 464 465 obj_surface->surface_id = surfaceID; 466 *surface = surfaceID; 467 obj_surface->context_id = -1; 468 obj_surface->width = width; 469 obj_surface->height = height; 470 obj_surface->width_r = width; 471 obj_surface->height_r = height; 472 obj_surface->height_origin = height; 473 474 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 475 if (NULL == psb_surface) { 476 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 477 obj_surface->surface_id = VA_INVALID_SURFACE; 478 479 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 480 481 DEBUG_FAILURE; 482 return vaStatus; 483 } 484 485 vaStatus = psb_surface_create_from_kbuf(driver_data, width, height, 486 size, 487 kBuf_fourcc, 488 kbuf_handle, 489 luma_stride, 490 chroma_u_stride, 491 chroma_v_stride, 492 luma_offset, 493 chroma_u_offset, 494 chroma_v_offset, 495 psb_surface); 496 497 if (VA_STATUS_SUCCESS != vaStatus) { 498 free(psb_surface); 499 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 500 obj_surface->surface_id = VA_INVALID_SURFACE; 501 502 DEBUG_FAILURE; 503 return vaStatus; 504 } 505 buffer_stride = psb_surface->stride; 506 /* by default, surface fourcc is NV12 */ 507 memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); 508 psb_surface->extra_info[4] = kBuf_fourcc; 509 obj_surface->psb_surface = psb_surface; 510 511 /* Error recovery */ 512 if (VA_STATUS_SUCCESS != vaStatus) { 513 object_surface_p obj_surface = SURFACE(surfaceID); 514 psb__destroy_surface(driver_data, obj_surface); 515 *surface = VA_INVALID_SURFACE; 516 } 517 518 return vaStatus; 519} 520 521VAStatus psb_CreateSurfaceFromUserspace( 522 VADriverContextP ctx, 523 int width, 524 int height, 525 int format, 526 int num_surfaces, 527 VASurfaceID *surface_list, /* out */ 528 VASurfaceAttributeTPI *attribute_tpi 529) 530{ 531 INIT_DRIVER_DATA; 532 VAStatus vaStatus = VA_STATUS_SUCCESS; 533 unsigned int *vaddr; 534 unsigned long fourcc; 535 int surfaceID; 536 object_surface_p obj_surface; 537 psb_surface_p psb_surface; 538 int i; 539 540 switch (format) { 541 case VA_RT_FORMAT_YUV422: 542 fourcc = VA_FOURCC_YV16; 543 break; 544 case VA_RT_FORMAT_YUV420: 545 default: 546 fourcc = VA_FOURCC_NV12; 547 break; 548 } 549 550 for (i=0; i < num_surfaces; i++) { 551 vaddr = attribute_tpi->buffers[i]; 552 surfaceID = object_heap_allocate(&driver_data->surface_heap); 553 obj_surface = SURFACE(surfaceID); 554 if (NULL == obj_surface) { 555 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 556 DEBUG_FAILURE; 557 break; 558 } 559 MEMSET_OBJECT(obj_surface, struct object_surface_s); 560 561 obj_surface->surface_id = surfaceID; 562 surface_list[i] = surfaceID; 563 obj_surface->context_id = -1; 564 obj_surface->width = attribute_tpi->width; 565 obj_surface->height = attribute_tpi->height; 566 obj_surface->width_r = attribute_tpi->width; 567 obj_surface->height_r = attribute_tpi->height; 568 569 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 570 if (NULL == psb_surface) { 571 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 572 obj_surface->surface_id = VA_INVALID_SURFACE; 573 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 574 DEBUG_FAILURE; 575 break; 576 } 577 578 if (attribute_tpi->type == VAExternalMemoryNoneCacheUserPointer) 579 vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, 580 attribute_tpi, psb_surface, vaddr, PSB_USER_BUFFER_UNCACHED); 581 else 582 vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, 583 attribute_tpi, psb_surface, vaddr, 0); 584 obj_surface->psb_surface = psb_surface; 585 586 if (VA_STATUS_SUCCESS != vaStatus) { 587 free(psb_surface); 588 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 589 obj_surface->surface_id = VA_INVALID_SURFACE; 590 DEBUG_FAILURE; 591 break; 592 } 593 /* by default, surface fourcc is NV12 */ 594 memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); 595 psb_surface->extra_info[4] = fourcc; 596 obj_surface->psb_surface = psb_surface; 597 598 /* Error recovery */ 599 if (VA_STATUS_SUCCESS != vaStatus) { 600 object_surface_p obj_surface = SURFACE(surfaceID); 601 psb__destroy_surface(driver_data, obj_surface); 602 } 603 } 604 605 return vaStatus; 606} 607 608VAStatus psb_CreateSurfaceFromION( 609 VADriverContextP ctx, 610 int width, 611 int height, 612 int format, 613 int num_surfaces, 614 VASurfaceID *surface_list, /* out */ 615 VASurfaceAttributeTPI *attribute_tpi 616) 617{ 618 INIT_DRIVER_DATA; 619 VAStatus vaStatus = VA_STATUS_SUCCESS; 620 unsigned int *vaddr = NULL; 621 unsigned long fourcc; 622 int surfaceID; 623 object_surface_p obj_surface; 624 psb_surface_p psb_surface; 625 int i; 626 unsigned int source_size = 0; 627 int ion_fd = 0; 628 int ion_ret = 0; 629 struct ion_fd_data ion_source_share; 630 631 switch (format) { 632 case VA_RT_FORMAT_YUV422: 633 fourcc = VA_FOURCC_YV16; 634 break; 635 case VA_RT_FORMAT_YUV420: 636 default: 637 fourcc = VA_FOURCC_NV12; 638 break; 639 } 640 641 ion_fd = open("/dev/ion", O_RDWR); 642 if (ion_fd < 0) { 643 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to open the ion device!\n", __FUNCTION__); 644 return VA_STATUS_ERROR_UNKNOWN; 645 } 646 647 for (i=0; i < num_surfaces; i++) { 648 ion_source_share.handle = NULL; 649 ion_source_share.fd = (int)(attribute_tpi->buffers[i]); 650 ion_ret = ioctl(ion_fd, ION_IOC_IMPORT, &ion_source_share); 651 if ((ion_ret < 0) || (NULL == ion_source_share.handle)) { 652 close(ion_fd); 653 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to import the ion fd!\n", __FUNCTION__); 654 return VA_STATUS_ERROR_UNKNOWN; 655 } 656 657 if (VA_FOURCC_NV12 == fourcc) 658 source_size = attribute_tpi->width * attribute_tpi->height * 1.5; 659 else 660 source_size = attribute_tpi->width * attribute_tpi->height * 2; 661 662 vaddr = mmap(NULL, source_size, PROT_READ|PROT_WRITE, MAP_SHARED, ion_source_share.fd, 0); 663 if (MAP_FAILED == vaddr) { 664 close(ion_fd); 665 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Fail to mmap the ion buffer!\n", __FUNCTION__); 666 return VA_STATUS_ERROR_UNKNOWN; 667 } 668 669 surfaceID = object_heap_allocate(&driver_data->surface_heap); 670 obj_surface = SURFACE(surfaceID); 671 if (NULL == obj_surface) { 672 close(ion_fd); 673 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 674 DEBUG_FAILURE; 675 break; 676 } 677 MEMSET_OBJECT(obj_surface, struct object_surface_s); 678 679 obj_surface->surface_id = surfaceID; 680 surface_list[i] = surfaceID; 681 obj_surface->context_id = -1; 682 obj_surface->width = attribute_tpi->width; 683 obj_surface->height = attribute_tpi->height; 684 obj_surface->width_r = attribute_tpi->width; 685 obj_surface->height_r = attribute_tpi->height; 686 687 psb_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s)); 688 if (NULL == psb_surface) { 689 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 690 obj_surface->surface_id = VA_INVALID_SURFACE; 691 close(ion_fd); 692 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; 693 DEBUG_FAILURE; 694 break; 695 } 696 697 vaStatus = psb_surface_create_from_ub(driver_data, width, height, fourcc, 698 attribute_tpi, psb_surface, vaddr, 0); 699 obj_surface->psb_surface = psb_surface; 700 701 if (VA_STATUS_SUCCESS != vaStatus) { 702 free(psb_surface); 703 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_surface); 704 obj_surface->surface_id = VA_INVALID_SURFACE; 705 close(ion_fd); 706 DEBUG_FAILURE; 707 break; 708 } 709 /* by default, surface fourcc is NV12 */ 710 memset(psb_surface->extra_info, 0, sizeof(psb_surface->extra_info)); 711 psb_surface->extra_info[4] = fourcc; 712 obj_surface->psb_surface = psb_surface; 713 714 /* Error recovery */ 715 if (VA_STATUS_SUCCESS != vaStatus) { 716 object_surface_p obj_surface = SURFACE(surfaceID); 717 psb__destroy_surface(driver_data, obj_surface); 718 close(ion_fd); 719 } 720 721 vaddr = NULL; 722 } 723 724 close(ion_fd); 725 return vaStatus; 726} 727 728VAStatus psb_CreateSurfacesWithAttribute( 729 VADriverContextP ctx, 730 int width, 731 int height, 732 int format, 733 int num_surfaces, 734 VASurfaceID *surface_list, /* out */ 735 VASurfaceAttributeTPI *attribute_tpi 736) 737{ 738 VAStatus vaStatus = VA_STATUS_SUCCESS; 739 int i, height_origin; 740 741 CHECK_INVALID_PARAM(attribute_tpi == NULL); 742 743 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create %d surface(%dx%d) with type %d\n", 744 num_surfaces, width, height, attribute_tpi->type); 745 746 attribute_tpi->tiling = 0; /* FIXME libmix doesn't clear this flag */ 747 switch (attribute_tpi->type) { 748 case VAExternalMemoryNULL: 749 vaStatus = psb_CreateSurfacesForUserPtr(ctx, width, height, format, num_surfaces, surface_list, 750 attribute_tpi->size, attribute_tpi->pixel_format, 751 attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride, 752 attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset, 753 attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset); 754 return vaStatus; 755 case VAExternalMemoryNoneCacheUserPointer: 756 case VAExternalMemoryUserPointer: 757 vaStatus = psb_CreateSurfaceFromUserspace(ctx, width, height, 758 format, num_surfaces, surface_list, 759 attribute_tpi); 760 return vaStatus; 761 case VAExternalMemoryKernelDRMBufffer: 762 for (i=0; i < num_surfaces; i++) { 763 vaStatus = psb_CreateSurfaceFromKBuf( 764 ctx, width, height, format, &surface_list[i], 765 attribute_tpi->buffers[i], 766 attribute_tpi->size, attribute_tpi->pixel_format, 767 attribute_tpi->luma_stride, attribute_tpi->chroma_u_stride, 768 attribute_tpi->chroma_v_stride, attribute_tpi->luma_offset, 769 attribute_tpi->chroma_u_offset, attribute_tpi->chroma_v_offset); 770 CHECK_VASTATUS(); 771 } 772 return vaStatus; 773 case VAExternalMemoryAndroidGrallocBuffer: 774 vaStatus = psb_CreateSurfacesFromGralloc(ctx, width, height, 775 format, num_surfaces, surface_list, 776 attribute_tpi); 777 return vaStatus; 778 case VAExternalMemoryIONSharedFD: 779 vaStatus = psb_CreateSurfaceFromION(ctx, width, height, 780 format, num_surfaces, surface_list, 781 attribute_tpi); 782 return vaStatus; 783 default: 784 return VA_STATUS_ERROR_INVALID_PARAMETER; 785 } 786 787 return VA_STATUS_ERROR_INVALID_PARAMETER; 788} 789