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