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