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