1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /*#define LOG_NDEBUG 0*/ 18 #define LOG_TAG "SEC_Overlay" 19 20 #include <hardware/hardware.h> 21 #include <hardware/overlay.h> 22 23 extern "C" { 24 #include "v4l2_utils.h" 25 } 26 27 #include <pthread.h> 28 #include <fcntl.h> 29 #include <errno.h> 30 #include <sys/types.h> 31 #include <sys/stat.h> 32 #include <sys/mman.h> 33 #include <unistd.h> 34 #include <linux/videodev.h> 35 36 #include <cutils/log.h> 37 #include <cutils/ashmem.h> 38 #include <cutils/atomic.h> 39 40 #include "linux/fb.h" 41 42 /*****************************************************************************/ 43 44 #define LOG_FUNCTION_NAME LOGV(" %s %s", __FILE__, __func__) 45 46 #define NUM_OVERLAY_BUFFERS_REQUESTED (3) 47 /* OVRLYSHM on phone keypad*/ 48 #define SHARED_DATA_MARKER (0x68759746) 49 50 /* These values should come from Surface Flinger */ 51 unsigned int g_lcd_width = 480; 52 unsigned int g_lcd_height = 800; 53 unsigned int g_lcd_bpp = 32; 54 55 #define CACHEABLE_BUFFERS 0x1 56 57 /* shared with Camera/Video Playback HAL */ 58 #define ALL_BUFFERS_FLUSHED -66 59 60 uint32_t phyAddr; 61 s5p_fimc_t g_s5p_fimc; 62 63 typedef struct 64 { 65 uint32_t posX; 66 uint32_t posY; 67 uint32_t posW; 68 uint32_t posH; 69 uint32_t rotation; 70 uint32_t flip; 71 72 uint32_t posX_org; 73 uint32_t posY_org; 74 uint32_t posW_org; 75 uint32_t posH_org; 76 77 } overlay_ctrl_t; 78 79 typedef struct 80 { 81 uint32_t cropX; 82 uint32_t cropY; 83 uint32_t cropW; 84 uint32_t cropH; 85 } overlay_data_t; 86 87 typedef struct 88 { 89 uint32_t marker; 90 uint32_t size; 91 92 volatile int32_t refCnt; 93 94 uint32_t controlReady; /* Only updated by the control side */ 95 uint32_t dataReady; /* Only updated by the data side */ 96 97 pthread_mutex_t lock; 98 pthread_mutexattr_t attr; 99 100 uint32_t streamEn; 101 uint32_t streamingReset; 102 103 uint32_t dispW; 104 uint32_t dispH; 105 106 } overlay_shared_t; 107 108 /* Only one instance is created per platform */ 109 struct overlay_control_context_t { 110 struct overlay_control_device_t device; 111 /* our private state goes below here */ 112 struct overlay_t* overlay_video1; 113 struct overlay_t* overlay_video2; 114 }; 115 116 /* A separate instance is created per overlay data side user*/ 117 struct overlay_data_context_t { 118 struct overlay_data_device_t device; 119 /* our private state goes below here */ 120 int ctl_fd; 121 int shared_fd; 122 int shared_size; 123 int width; 124 int height; 125 int format; 126 int num_buffers; 127 size_t *buffers_len; 128 void **buffers; 129 130 overlay_data_t data; 131 overlay_shared_t *shared; 132 struct mapping_data *mapping_data; 133 /* Need to count Qd buffers 134 to be sure we don't block DQ'ing when exiting */ 135 int qd_buf_count; 136 int cacheable_buffers; 137 138 bool zerocopy; 139 }; 140 141 static int create_shared_data(overlay_shared_t **shared); 142 static void destroy_shared_data(int shared_fd, overlay_shared_t *shared, 143 bool closefd); 144 static int open_shared_data(overlay_data_context_t *ctx); 145 static void close_shared_data(overlay_data_context_t *ctx); 146 enum { LOCK_REQUIRED = 1, NO_LOCK_NEEDED = 0 }; 147 static int enable_streaming(overlay_shared_t *shared, int ovly_fd, 148 int lock_required ); 149 150 static int overlay_device_open(const struct hw_module_t* module, 151 const char* name, struct hw_device_t** device); 152 153 static int check_fimc_dst_constraints(s5p_fimc_t *s5p_fimc, 154 unsigned int rotation); 155 static int check_fimc_src_constraints(s5p_fimc_t *s5p_fimc); 156 157 static struct hw_module_methods_t overlay_module_methods = { 158 open: overlay_device_open 159 }; 160 161 struct overlay_module_t HAL_MODULE_INFO_SYM = { 162 common: { 163 tag: HARDWARE_MODULE_TAG, 164 version_major: 1, 165 version_minor: 0, 166 id: OVERLAY_HARDWARE_MODULE_ID, 167 name: "SEC Overlay module", 168 author: "The Android Open Source Project", 169 methods: &overlay_module_methods, 170 } 171 }; 172 173 /*****************************************************************************/ 174 175 /* 176 * This is the overlay_t object, it is returned to the user and represents 177 * an overlay. here we use a subclass, where we can store our own state. 178 * This handles will be passed across processes and possibly given to other 179 * HAL modules (for instance video decode modules). 180 */ 181 struct handle_t : public native_handle { 182 /* add the data fields we need here, for instance: */ 183 int ctl_fd; 184 int shared_fd; 185 int width; 186 int height; 187 int format; 188 int num_buffers; 189 int shared_size; 190 }; 191 192 static int handle_format(const overlay_handle_t overlay) { 193 return static_cast<const struct handle_t *>(overlay)->format; 194 } 195 196 static int handle_ctl_fd(const overlay_handle_t overlay) { 197 return static_cast<const struct handle_t *>(overlay)->ctl_fd; 198 } 199 200 static int handle_shared_fd(const overlay_handle_t overlay) { 201 return static_cast<const struct handle_t *>(overlay)->shared_fd; 202 } 203 204 static int handle_num_buffers(const overlay_handle_t overlay) { 205 return static_cast<const struct handle_t *>(overlay)->num_buffers; 206 } 207 208 static int handle_width(const overlay_handle_t overlay) { 209 return static_cast<const struct handle_t *>(overlay)->width; 210 } 211 212 static int handle_height(const overlay_handle_t overlay) { 213 return static_cast<const struct handle_t *>(overlay)->height; 214 } 215 216 static int handle_shared_size(const overlay_handle_t overlay) { 217 return static_cast<const struct handle_t *>(overlay)->shared_size; 218 } 219 220 /* A separate instance of this class is created per overlay */ 221 class overlay_object : public overlay_t 222 { 223 handle_t mHandle; 224 225 overlay_ctrl_t mCtl; 226 overlay_ctrl_t mCtlStage; 227 overlay_shared_t *mShared; 228 229 static overlay_handle_t getHandleRef(struct overlay_t* overlay) { 230 /* returns a reference to the handle, caller doesn't take ownership */ 231 return &(static_cast<overlay_object *>(overlay)->mHandle); 232 } 233 234 public: 235 overlay_object(int ctl_fd, int shared_fd, int shared_size, int w, int h, 236 int format, int num_buffers) { 237 this->overlay_t::getHandleRef = getHandleRef; 238 mHandle.version = sizeof(native_handle); 239 mHandle.numFds = 2; 240 mHandle.numInts = 5; /* extra ints we have in our handle */ 241 mHandle.ctl_fd = ctl_fd; 242 mHandle.shared_fd = shared_fd; 243 mHandle.width = w; 244 mHandle.height = h; 245 mHandle.format = format; 246 mHandle.num_buffers = num_buffers; 247 mHandle.shared_size = shared_size; 248 this->w = w; 249 this->h = h; 250 this->format = format; 251 252 memset( &mCtl, 0, sizeof( mCtl ) ); 253 memset( &mCtlStage, 0, sizeof( mCtlStage ) ); 254 } 255 256 int ctl_fd() { return mHandle.ctl_fd; } 257 int shared_fd() { return mHandle.shared_fd; } 258 overlay_ctrl_t* data() { return &mCtl; } 259 overlay_ctrl_t* staging() { return &mCtlStage; } 260 overlay_shared_t* getShared() { return mShared; } 261 void setShared( overlay_shared_t *p ) { mShared = p; } 262 }; 263 264 /***************************************************************************** 265 * Local Functions 266 *****************************************************************************/ 267 268 static int create_shared_data(overlay_shared_t **shared) 269 { 270 int fd; 271 /* assuming sizeof(overlay_shared_t) < a single page */ 272 int size = getpagesize(); 273 overlay_shared_t *p; 274 275 if ((fd = ashmem_create_region("overlay_data", size)) < 0) { 276 LOGE("Failed to Create Overlay Shared Data!\n"); 277 return fd; 278 } 279 280 p = (overlay_shared_t*)mmap(NULL, size, PROT_READ | PROT_WRITE, 281 MAP_SHARED, fd, 0); 282 if (p == MAP_FAILED) { 283 LOGE("Failed to Map Overlay Shared Data!\n"); 284 close(fd); 285 return -1; 286 } 287 288 memset(p, 0, size); 289 p->marker = SHARED_DATA_MARKER; 290 p->size = size; 291 p->refCnt = 1; 292 if (pthread_mutexattr_init(&p->attr) != 0) { 293 LOGE("Failed to initialize overlay mutex attr"); 294 goto MutexAttrErr; 295 } 296 if (pthread_mutexattr_setpshared(&p->attr, PTHREAD_PROCESS_SHARED) != 0) { 297 LOGE("Failed to set the overlay mutex attr to be shared across-processes"); 298 goto MutexAttrSetErr; 299 } 300 if (pthread_mutex_init(&p->lock, &p->attr) != 0) { 301 LOGE("Failed to initialize overlay mutex\n"); 302 goto MutexErr; 303 } 304 305 *shared = p; 306 return fd; 307 308 MutexErr: 309 MutexAttrSetErr: 310 pthread_mutexattr_destroy(&p->attr); 311 MutexAttrErr: 312 munmap(p, size); 313 close(fd); 314 return -1; 315 } 316 317 static void destroy_shared_data(int shared_fd, overlay_shared_t *shared, 318 bool closefd ) 319 { 320 if (shared == NULL) 321 return; 322 323 /* Last side deallocated releases the mutex, otherwise the remaining */ 324 /* side will deadlock trying to use an already released mutex */ 325 if (android_atomic_dec(&shared->refCnt) == 1) { 326 if (pthread_mutex_destroy(&shared->lock)) { 327 LOGE("Failed to uninitialize overlay mutex!\n"); 328 } 329 330 if (pthread_mutexattr_destroy(&shared->attr)) { 331 LOGE("Failed to uninitialize the overlay mutex attr!\n"); 332 } 333 shared->marker = 0; 334 } 335 336 if (munmap(shared, shared->size)) { 337 LOGE("Failed to Unmap Overlay Shared Data!\n"); 338 } 339 340 if (closefd && close(shared_fd)) { 341 LOGE("Failed to Close Overlay Shared Data!\n"); 342 } 343 } 344 345 static int open_shared_data( overlay_data_context_t *ctx ) 346 { 347 int rc = -1; 348 int mode = PROT_READ | PROT_WRITE; 349 int fd = ctx->shared_fd; 350 int size = ctx->shared_size; 351 352 if (ctx->shared != NULL) { 353 /* Already open, return success */ 354 LOGI("Overlay Shared Data Already Open\n"); 355 return 0; 356 } 357 ctx->shared = (overlay_shared_t*)mmap(0, size, mode, MAP_SHARED, fd, 0); 358 359 if (ctx->shared == MAP_FAILED) { 360 LOGE("Failed to Map Overlay Shared Data!\n"); 361 } else if ( ctx->shared->marker != SHARED_DATA_MARKER ) { 362 LOGE("Invalid Overlay Shared Marker!\n"); 363 munmap( ctx->shared, size); 364 } else if ( (int)ctx->shared->size != size ) { 365 LOGE("Invalid Overlay Shared Size!\n"); 366 munmap(ctx->shared, size); 367 } else { 368 android_atomic_inc(&ctx->shared->refCnt); 369 rc = 0; 370 } 371 372 return rc; 373 } 374 375 static void close_shared_data(overlay_data_context_t *ctx) 376 { 377 destroy_shared_data(ctx->shared_fd, ctx->shared, false); 378 ctx->shared = NULL; 379 } 380 381 static int enable_streaming_locked(overlay_shared_t *shared, int ovly_fd) 382 { 383 int rc = 0; 384 385 if (!shared->controlReady || !shared->dataReady) { 386 LOGI("Postponing Stream Enable/%d/%d\n", shared->controlReady, 387 shared->dataReady); 388 } else { 389 shared->streamEn = 1; 390 rc = v4l2_overlay_stream_on(ovly_fd); 391 if (rc) { 392 LOGE("Stream Enable Failed!/%d\n", rc); 393 shared->streamEn = 0; 394 } 395 } 396 397 return rc; 398 } 399 400 static int enable_streaming(overlay_shared_t *shared, int ovly_fd) 401 { 402 int ret; 403 404 pthread_mutex_lock(&shared->lock); 405 ret = enable_streaming_locked(shared, ovly_fd); 406 pthread_mutex_unlock(&shared->lock); 407 return ret; 408 } 409 410 static int disable_streaming_locked(overlay_shared_t *shared, int ovly_fd) 411 { 412 int ret = 0; 413 414 if (shared->streamEn) { 415 ret = v4l2_overlay_stream_off( ovly_fd ); 416 if (ret) { 417 LOGE("Stream Off Failed!/%d\n", ret); 418 } else { 419 shared->streamingReset = 1; 420 shared->streamEn = 0; 421 } 422 } 423 424 return ret; 425 } 426 427 static void set_color_space(unsigned int overlay_color_format, unsigned int *v4l2_color_format) 428 { 429 switch (overlay_color_format) { 430 case OVERLAY_FORMAT_RGB_565: 431 *v4l2_color_format = V4L2_PIX_FMT_RGB565; 432 break; 433 434 case OVERLAY_FORMAT_YCbYCr_422_I: 435 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: 436 *v4l2_color_format = V4L2_PIX_FMT_YUYV; 437 break; 438 439 case OVERLAY_FORMAT_CbYCrY_422_I: 440 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: 441 *v4l2_color_format = V4L2_PIX_FMT_UYVY; 442 break; 443 444 case HAL_PIXEL_FORMAT_YCbCr_420_P: 445 *v4l2_color_format = V4L2_PIX_FMT_YUV420; 446 break; 447 448 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: 449 *v4l2_color_format = V4L2_PIX_FMT_NV12T; 450 break; 451 452 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: 453 *v4l2_color_format = V4L2_PIX_FMT_NV21; 454 break; 455 456 default : 457 LOGE("unsupported pixel format (0x%x)", overlay_color_format); 458 *v4l2_color_format = -1; 459 } 460 } 461 462 /**************************************************************************** 463 * Control module 464 *****************************************************************************/ 465 466 static int overlay_get(struct overlay_control_device_t *dev, int name) 467 { 468 int result = -1; 469 470 switch (name) { 471 /* 0 = no limit */ 472 case OVERLAY_MINIFICATION_LIMIT: result = 0; break; 473 /* 0 = no limit */ 474 case OVERLAY_MAGNIFICATION_LIMIT: result = 0; break; 475 /* 0 = infinite */ 476 case OVERLAY_SCALING_FRAC_BITS: result = 0; break; 477 /* 90 rotation steps (for instance) */ 478 case OVERLAY_ROTATION_STEP_DEG: result = 90; break; 479 /* 1-pixel alignment */ 480 case OVERLAY_HORIZONTAL_ALIGNMENT: result = 1; break; 481 /* 1-pixel alignment */ 482 case OVERLAY_VERTICAL_ALIGNMENT: result = 1; break; 483 /* 1-pixel alignment */ 484 case OVERLAY_WIDTH_ALIGNMENT: result = 1; break; 485 case OVERLAY_HEIGHT_ALIGNMENT: break; 486 } 487 488 return result; 489 } 490 491 static int get_fb_var_screeninfo( struct fb_var_screeninfo *info ) 492 { 493 int fd = -1; 494 int i=0; 495 char name[64]; 496 int ret = 0; 497 498 char const * const device_template[] = { 499 "/dev/graphics/fb%u", 500 "/dev/fb%u", 501 0 }; 502 503 while ((fd==-1) && device_template[i]) { 504 snprintf(name, 64, device_template[i], 0); 505 fd = open(name, O_RDWR, 0); 506 i++; 507 } 508 509 if (fd < 0) 510 ret = -EINVAL; 511 512 if (ioctl(fd, FBIOGET_VSCREENINFO, info) == -1) 513 ret = -EINVAL; 514 515 if (fd > 0) 516 close(fd); 517 518 return 0; 519 } 520 static overlay_t* overlay_createOverlay(struct overlay_control_device_t *dev, 521 uint32_t w, uint32_t h, int32_t format) 522 { 523 LOGD("overlay_createOverlay:IN w=%d h=%d format=%d\n", w, h, format); 524 LOG_FUNCTION_NAME; 525 526 overlay_object *overlay; 527 overlay_control_context_t *ctx = (overlay_control_context_t *)dev; 528 overlay_shared_t *shared; 529 530 int ret; 531 uint32_t num = NUM_OVERLAY_BUFFERS_REQUESTED; 532 int fd; 533 int shared_fd; 534 struct fb_var_screeninfo info; 535 bool zerocopy = false; 536 537 phyAddr = 0; 538 539 if (format == OVERLAY_FORMAT_DEFAULT) { 540 LOGV("format == OVERLAY_FORMAT_DEFAULT\n"); 541 LOGV("set to HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP\n"); 542 format = HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP; 543 } 544 545 if (ctx->overlay_video1) { 546 LOGE("Error - overlays already in use\n"); 547 return NULL; 548 } 549 550 shared_fd = create_shared_data(&shared); 551 if (shared_fd < 0) { 552 LOGE("Failed to create shared data"); 553 return NULL; 554 } 555 556 fd = v4l2_overlay_open(V4L2_OVERLAY_PLANE_VIDEO1); 557 if (fd < 0) { 558 LOGE("Failed to open overlay device : %s\n", strerror(errno)); 559 goto error; 560 } 561 562 g_s5p_fimc.params.src.full_width = w; 563 g_s5p_fimc.params.src.full_height = h; 564 g_s5p_fimc.params.src.width = w; 565 g_s5p_fimc.params.src.height = h; 566 set_color_space(format, &g_s5p_fimc.params.src.color_space); 567 ret = check_fimc_src_constraints(&g_s5p_fimc); 568 if(ret != 0) { 569 if(ret < 0) { 570 LOGE("Not supported source image size"); 571 goto error1; 572 } else { 573 LOGD("src width, height are changed [w= %d, h= %d]->[w=%d, h= %d]" 574 , w, h, g_s5p_fimc.params.src.width 575 , g_s5p_fimc.params.src.height); 576 w = g_s5p_fimc.params.src.width; 577 h = g_s5p_fimc.params.src.height; 578 } 579 } 580 581 if (v4l2_overlay_init(fd, w, h, format, phyAddr)) { 582 LOGE("Failed initializing overlays\n"); 583 goto error1; 584 } 585 586 if (v4l2_overlay_set_crop(fd, 0, 0, w, h)) { 587 LOGE("Failed defaulting crop window\n"); 588 goto error1; 589 } 590 591 if (v4l2_overlay_set_flip(fd, 0)) { 592 LOGE("Failed defaulting flip\n"); 593 goto error1; 594 } 595 596 if (v4l2_overlay_set_rotation(fd, 0, 0)) { 597 LOGE("Failed defaulting rotation\n"); 598 goto error1; 599 } 600 601 if (format >= HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP 602 && format < HAL_PIXEL_FORMAT_CUSTOM_MAX) 603 zerocopy = true; 604 605 if (v4l2_overlay_req_buf(fd, &num, 0, (int)zerocopy)) { 606 LOGE("Failed requesting buffers\n"); 607 goto error1; 608 } 609 610 v4l2_overlay_init_fimc(fd, &g_s5p_fimc); 611 612 overlay = new overlay_object(fd, shared_fd, shared->size, 613 w, h, format, num); 614 if (overlay == NULL) { 615 LOGE("Failed to create overlay object\n"); 616 goto error1; 617 } 618 ctx->overlay_video1 = overlay; 619 620 overlay->setShared(shared); 621 622 shared->controlReady = 0; 623 shared->streamEn = 0; 624 shared->streamingReset = 0; 625 626 /* get lcd size from kernel framebuffer */ 627 if(get_fb_var_screeninfo(&info) == 0) { 628 shared->dispW = info.xres; 629 shared->dispH = info.yres; 630 g_lcd_width = info.xres; 631 g_lcd_height = info.yres; 632 g_lcd_bpp = info.bits_per_pixel; 633 } else { 634 shared->dispW = g_lcd_width; /* Need to determine this properly */ 635 shared->dispH = g_lcd_height; /* Need to determine this properly */ 636 } 637 638 LOGI("Opened video1/fd=%d/obj=%08lx/shm=%d/size=%d", fd, 639 (unsigned long)overlay, shared_fd, shared->size); 640 641 return overlay; 642 643 error1: 644 close(fd); 645 error: 646 destroy_shared_data(shared_fd, shared, true); 647 return NULL; 648 } 649 650 static void overlay_destroyOverlay(struct overlay_control_device_t *dev, 651 overlay_t* overlay) 652 { 653 LOGD("overlay_destroyOverlay:IN dev (%p) and overlay (%p)", dev, overlay); 654 LOG_FUNCTION_NAME; 655 656 overlay_control_context_t *ctx = (overlay_control_context_t *)dev; 657 overlay_object *obj = static_cast<overlay_object *>(overlay); 658 659 int rc; 660 int fd = obj->ctl_fd(); 661 uint32_t num = 0; 662 663 overlay_shared_t *shared = obj->getShared(); 664 665 if (shared == NULL) { 666 LOGE("Overlay was already destroyed - nothing needs to be done\n"); 667 return; 668 } 669 670 pthread_mutex_lock(&shared->lock); 671 672 disable_streaming_locked(shared, fd); 673 674 pthread_mutex_unlock(&shared->lock); 675 676 destroy_shared_data(obj->shared_fd(), shared, true); 677 obj->setShared(NULL); 678 679 if (v4l2_overlay_req_buf(fd, &num, 0, 0)) { 680 LOGE("Failed requesting buffers\n"); 681 } 682 683 LOGI("Destroying overlay/fd=%d/obj=%08lx", fd, (unsigned long)overlay); 684 685 if (close(fd)) { 686 LOGE( "Error closing overly fd/%d\n", errno); 687 } 688 689 if (overlay) { 690 if (ctx->overlay_video1 == overlay) 691 ctx->overlay_video1 = NULL; 692 delete overlay; 693 overlay = NULL; 694 } 695 LOGD("overlay_destroyOverlay:OUT"); 696 } 697 698 static int overlay_setPosition(struct overlay_control_device_t *dev, 699 overlay_t* overlay, int x, int y, uint32_t w, 700 uint32_t h) 701 { 702 LOG_FUNCTION_NAME; 703 704 overlay_object *obj = static_cast<overlay_object *>(overlay); 705 706 overlay_ctrl_t *stage = obj->staging(); 707 overlay_shared_t *shared = obj->getShared(); 708 709 int rc = 0; 710 int temp_x = x, temp_y = y, temp_w = w, temp_h = h; 711 712 /* 713 * This logic here is to return an error if the rectangle is not fully 714 * within the display, unless we have not received a valid position yet, 715 * in which case we will do our best to adjust the rectangle to be within 716 * the display. 717 */ 718 719 /* Require a minimum size */ 720 if (temp_w < 16) 721 temp_w = 16; 722 if (temp_h < 8) 723 temp_h = 8; 724 725 if (!shared->controlReady) { 726 if ( temp_x < 0 ) temp_x = 0; 727 if ( temp_y < 0 ) temp_y = 0; 728 if ( temp_w > shared->dispW ) temp_w = shared->dispW; 729 if ( temp_h > shared->dispH ) temp_h = shared->dispH; 730 if ( (temp_x + temp_w) > shared->dispW ) temp_w = shared->dispW - temp_x; 731 if ( (temp_y + temp_h) > shared->dispH ) temp_h = shared->dispH - temp_y; 732 } else if (temp_x < 0 || temp_y < 0 || (temp_x + temp_w) > shared->dispW || 733 (temp_y + temp_h) > shared->dispH) { 734 /* Return an error */ 735 rc = -1; 736 } 737 738 if (rc == 0) { 739 stage->posX = temp_x; 740 stage->posY = temp_y; 741 stage->posW = temp_w; 742 stage->posH = temp_h; 743 744 stage->posX_org = x; 745 stage->posY_org = y; 746 stage->posW_org = w; 747 stage->posH_org = h; 748 } 749 750 return rc; 751 } 752 753 static int overlay_getPosition(struct overlay_control_device_t *dev, 754 overlay_t* overlay, int* x, int* y, uint32_t* w, 755 uint32_t* h) 756 { 757 LOG_FUNCTION_NAME; 758 759 overlay_object *obj = static_cast<overlay_object *>(overlay); 760 overlay_ctrl_t *stage = obj->staging(); 761 762 *x = stage->posX_org; 763 *y = stage->posY_org; 764 *w = stage->posW_org; 765 *h = stage->posH_org; 766 767 return 0; 768 } 769 770 static int overlay_setParameter(struct overlay_control_device_t *dev, 771 overlay_t* overlay, int param, int value) 772 { 773 LOG_FUNCTION_NAME; 774 775 overlay_ctrl_t *stage = static_cast<overlay_object *>(overlay)->staging(); 776 int rc = 0; 777 778 switch (param) { 779 case OVERLAY_DITHER: 780 break; 781 782 case OVERLAY_TRANSFORM: 783 switch ( value ) 784 { 785 case 0: 786 stage->rotation = 0; 787 stage->flip = 0; 788 break; 789 case OVERLAY_TRANSFORM_ROT_90: 790 stage->rotation = 90; 791 stage->flip = 0; 792 break; 793 case OVERLAY_TRANSFORM_ROT_180: 794 stage->rotation = 180; 795 stage->flip = 0; 796 break; 797 case OVERLAY_TRANSFORM_ROT_270: 798 stage->rotation = 270; 799 stage->flip = 0; 800 break; 801 // FIMC VFLIP = android overlay FLIP_H. 802 case OVERLAY_TRANSFORM_FLIP_H: 803 stage->rotation = 0; 804 stage->flip = V4L2_CID_VFLIP; 805 break; 806 case OVERLAY_TRANSFORM_FLIP_V: 807 stage->rotation = 0; 808 stage->flip = V4L2_CID_HFLIP; 809 break; 810 // FIMC rotates first but android flips first. 811 case OVERLAY_TRANSFORM_ROT_90+OVERLAY_TRANSFORM_FLIP_H: 812 stage->rotation = 90; 813 stage->flip = V4L2_CID_HFLIP; 814 break; 815 case OVERLAY_TRANSFORM_ROT_90+OVERLAY_TRANSFORM_FLIP_V: 816 stage->rotation = 90; 817 stage->flip = V4L2_CID_VFLIP; 818 break; 819 820 default: 821 rc = -EINVAL; 822 break; 823 } 824 break; 825 } 826 827 return rc; 828 } 829 830 static int overlay_stage(struct overlay_control_device_t *dev, 831 overlay_t* overlay) { 832 return 0; 833 } 834 835 static int overlay_commit(struct overlay_control_device_t *dev, 836 overlay_t* overlay) { 837 LOG_FUNCTION_NAME; 838 839 overlay_object *obj = static_cast<overlay_object *>(overlay); 840 841 overlay_ctrl_t *data = obj->data(); 842 overlay_ctrl_t *stage = obj->staging(); 843 overlay_shared_t *shared = obj->getShared(); 844 845 int ret = 0; 846 int fd = obj->ctl_fd(); 847 848 if (shared == NULL) { 849 LOGI("Shared Data Not Init'd!\n"); 850 return -1; 851 } 852 853 pthread_mutex_lock(&shared->lock); 854 855 if (!shared->controlReady) { 856 shared->controlReady = 1; 857 } 858 859 g_s5p_fimc.params.dst.full_width = g_lcd_width; 860 g_s5p_fimc.params.dst.full_height = g_lcd_height; 861 g_s5p_fimc.params.dst.width = stage->posW; 862 g_s5p_fimc.params.dst.height = stage->posH; 863 if (g_lcd_bpp == 32) 864 g_s5p_fimc.params.dst.color_space = V4L2_PIX_FMT_RGB32; 865 else 866 g_s5p_fimc.params.dst.color_space = V4L2_PIX_FMT_RGB565; 867 ret = check_fimc_dst_constraints(&g_s5p_fimc, stage->rotation); 868 if (ret != 0) { 869 if (ret < 0) { 870 LOGE("Unsupported destination image size"); 871 goto end; 872 } else { 873 LOGD("dst width, height have changed [w= %d, h= %d] -> [w=%d, h= %d]", 874 stage->posW, stage->posH, g_s5p_fimc.params.dst.width, 875 g_s5p_fimc.params.dst.height); 876 stage->posW = g_s5p_fimc.params.dst.width; 877 stage->posH = g_s5p_fimc.params.dst.height; 878 } 879 } 880 881 if (data->posX == stage->posX && data->posY == stage->posY && 882 data->posW == stage->posW && data->posH == stage->posH && 883 data->rotation == stage->rotation && 884 data->flip == stage->flip) { 885 LOGI("Nothing to do!\n"); 886 goto end; 887 } 888 889 LOGV("Position/X%d/Y%d/W%d/H%d\n", data->posX, data->posY, data->posW, 890 data->posH); 891 LOGV("Adjusted Position/X%d/Y%d/W%d/H%d\n", stage->posX, stage->posY, 892 stage->posW, stage->posH); 893 LOGV("Rotation/%d\n", stage->rotation ); 894 895 if ((ret = disable_streaming_locked(shared, fd))) 896 goto end; 897 898 if (stage->flip != data->flip) { 899 ret = v4l2_overlay_set_flip(fd, stage->flip); 900 if (ret) { 901 LOGE("Set Flip Failed!/%d\n", ret); 902 goto end; 903 } 904 } 905 906 if (stage->rotation != data->rotation) { 907 ret = v4l2_overlay_set_rotation(fd, stage->rotation, 0); 908 if (ret) { 909 LOGE("Set Rotation Failed!/%d\n", ret); 910 goto end; 911 } 912 v4l2_overlay_s_fbuf(fd, stage->rotation); 913 } 914 915 ret = v4l2_overlay_set_position(fd, stage->posX, stage->posY, 916 stage->posW, stage->posH, stage->rotation); 917 if (ret) { 918 LOGE("Set Position Failed!/%d\n", ret); 919 goto end; 920 } 921 922 data->posX = stage->posX; 923 data->posY = stage->posY; 924 data->posW = stage->posW; 925 data->posH = stage->posH; 926 data->rotation = stage->rotation; 927 data->flip = stage->flip; 928 929 ret = enable_streaming_locked(shared, fd); 930 931 end: 932 pthread_mutex_unlock(&shared->lock); 933 934 return ret; 935 } 936 937 static int overlay_control_close(struct hw_device_t *dev) 938 { 939 LOG_FUNCTION_NAME; 940 941 struct overlay_control_context_t* ctx = 942 (struct overlay_control_context_t*)dev; 943 overlay_object *overlay_v1; 944 945 if (ctx) { 946 overlay_v1 = static_cast<overlay_object *>(ctx->overlay_video1); 947 948 overlay_destroyOverlay((struct overlay_control_device_t *)ctx, 949 overlay_v1); 950 951 free(ctx); 952 } 953 return 0; 954 } 955 956 static int get_pixel_format_type(unsigned int pixelformat) 957 { 958 switch(pixelformat) { 959 case V4L2_PIX_FMT_RGB32: 960 case V4L2_PIX_FMT_RGB565: 961 return PFT_RGB; 962 963 case V4L2_PIX_FMT_NV12: 964 case V4L2_PIX_FMT_NV12T: 965 case V4L2_PIX_FMT_NV21: 966 case V4L2_PIX_FMT_YUV420: 967 return PFT_YUV420; 968 969 case V4L2_PIX_FMT_YUYV: 970 case V4L2_PIX_FMT_UYVY: 971 case V4L2_PIX_FMT_YVYU: 972 case V4L2_PIX_FMT_VYUY: 973 case V4L2_PIX_FMT_NV16: 974 case V4L2_PIX_FMT_NV61: 975 case V4L2_PIX_FMT_YUV422P: 976 return PFT_YUV422; 977 978 default: 979 return PFT_YUV444; 980 } 981 } 982 983 /* check the constraints of destination image size */ 984 static int check_fimc_dst_constraints(s5p_fimc_t *s5p_fimc, 985 unsigned int rotation) 986 { 987 int tmp = 0; 988 989 if((s5p_fimc->params.dst.height > 0) && (s5p_fimc->params.dst.height < 16)) 990 s5p_fimc->params.dst.height = 16; 991 992 if(s5p_fimc->params.dst.width%8 != 0) { 993 tmp = s5p_fimc->params.dst.width - (s5p_fimc->params.dst.width%8); 994 if(tmp <= 0) 995 return -1; 996 else 997 s5p_fimc->params.dst.width = tmp; 998 } 999 1000 return 1; 1001 } 1002 /* check the constraints of source image size */ 1003 static int check_fimc_src_constraints(s5p_fimc_t *s5p_fimc) 1004 { 1005 int format_type = 0; 1006 1007 if(s5p_fimc->params.src.full_width < 16 || 1008 s5p_fimc->params.src.full_height < 8 ) 1009 return -1; 1010 1011 if(s5p_fimc->hw_ver == 0x50) { 1012 format_type = get_pixel_format_type(s5p_fimc->params.src.color_space); 1013 switch (format_type) { 1014 case PFT_YUV420: 1015 if (s5p_fimc->params.src.height%2 != 0) 1016 s5p_fimc->params.src.height = s5p_fimc->params.src.height 1017 - (s5p_fimc->params.src.height)%2; 1018 1019 if (s5p_fimc->params.src.width%2 != 0) 1020 s5p_fimc->params.src.width = s5p_fimc->params.src.width 1021 - (s5p_fimc->params.src.width)%2; 1022 break; 1023 1024 case PFT_YUV422: 1025 if (s5p_fimc->params.src.width%2 != 0) 1026 s5p_fimc->params.src.width = s5p_fimc->params.src.width 1027 - (s5p_fimc->params.src.width)%2; 1028 } 1029 } else { 1030 if (s5p_fimc->params.src.height < 8) { 1031 s5p_fimc->params.src.height = 8; 1032 } 1033 1034 if (s5p_fimc->params.src.width%16 != 0) { 1035 s5p_fimc->params.src.width = s5p_fimc->params.src.width 1036 - (s5p_fimc->params.src.width)%16; 1037 } 1038 } 1039 1040 return 1; 1041 } 1042 1043 /**************************************************************************** 1044 * Data module 1045 *****************************************************************************/ 1046 1047 int overlay_initialize(struct overlay_data_device_t *dev, 1048 overlay_handle_t handle) 1049 { 1050 LOG_FUNCTION_NAME; 1051 1052 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1053 struct stat stat; 1054 1055 int i; 1056 int rc = -1; 1057 1058 ctx->num_buffers = handle_num_buffers(handle); 1059 ctx->width = handle_width(handle); 1060 ctx->height = handle_height(handle); 1061 ctx->format = handle_format(handle); 1062 ctx->ctl_fd = handle_ctl_fd(handle); 1063 ctx->shared_fd = handle_shared_fd(handle); 1064 ctx->shared_size = handle_shared_size(handle); 1065 ctx->shared = NULL; 1066 ctx->qd_buf_count = 0; 1067 ctx->cacheable_buffers = 0; 1068 1069 if (ctx->format >= HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP 1070 && ctx->format < HAL_PIXEL_FORMAT_CUSTOM_MAX) 1071 ctx->zerocopy = true; 1072 else 1073 ctx->zerocopy = false; 1074 1075 if (fstat(ctx->ctl_fd, &stat)) { 1076 LOGE("Error = %s from %s\n", strerror(errno), "overlay initialize"); 1077 return -1; 1078 } 1079 1080 if (open_shared_data(ctx)) { 1081 return -1; 1082 } 1083 1084 ctx->shared->dataReady = 0; 1085 1086 ctx->mapping_data = new struct mapping_data; 1087 ctx->buffers = new void* [ctx->num_buffers]; 1088 ctx->buffers_len = new size_t[ctx->num_buffers]; 1089 1090 if (!ctx->buffers || !ctx->buffers_len || !ctx->mapping_data) { 1091 LOGE("Failed alloc'ing buffer arrays\n"); 1092 goto error; 1093 } else { 1094 1095 /* 1096 * in the zero copy case, 1097 * don't need to mmap buffer for source 1098 */ 1099 if (ctx->zerocopy) 1100 rc = 0; 1101 else { 1102 for (i = 0; i < ctx->num_buffers; i++) { 1103 rc = v4l2_overlay_map_buf(ctx->ctl_fd, i, &ctx->buffers[i], 1104 &ctx->buffers_len[i]); 1105 if (rc) { 1106 LOGE("Failed mapping buffers\n"); 1107 goto error; 1108 } 1109 } 1110 } 1111 } 1112 1113 v4l2_overlay_init_fimc(ctx->ctl_fd, &g_s5p_fimc); 1114 1115 return ( rc ); 1116 1117 error: 1118 1119 if(ctx->mapping_data) 1120 delete (ctx->mapping_data); 1121 if(ctx->buffers) 1122 delete [] ctx->buffers; 1123 if(ctx->buffers_len) 1124 delete [] ctx->buffers_len; 1125 1126 close_shared_data( ctx ); 1127 1128 return -1; 1129 } 1130 1131 static int overlay_resizeInput(struct overlay_data_device_t *dev, uint32_t w, 1132 uint32_t h) 1133 { 1134 int rc = -1; 1135 int ret = 0; 1136 1137 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1138 1139 if ((ctx->width == (int)w) && (ctx->width == (int)h)) { 1140 LOGV("same as current width and height. so do nothing"); 1141 return 0; 1142 } 1143 1144 if (!ctx->shared) { 1145 LOGI("Shared Data Not Init'd!\n"); 1146 return -1; 1147 } 1148 1149 if (ctx->shared->dataReady) { 1150 LOGV("Either setCrop() or queueBuffer() was called prior to this!" 1151 "Therefore failing this call.\n"); 1152 return -1; 1153 } 1154 1155 pthread_mutex_lock(&ctx->shared->lock); 1156 1157 if ((rc = disable_streaming_locked(ctx->shared, ctx->ctl_fd))) 1158 goto end; 1159 1160 if (!ctx->zerocopy) { 1161 for (int i = 0; i < ctx->num_buffers; i++) { 1162 v4l2_overlay_unmap_buf(ctx->buffers[i], ctx->buffers_len[i]); 1163 } 1164 } 1165 1166 g_s5p_fimc.params.src.full_width = w; 1167 g_s5p_fimc.params.src.full_height = h; 1168 g_s5p_fimc.params.src.width = w; 1169 g_s5p_fimc.params.src.height = h; 1170 set_color_space(ctx->format, &g_s5p_fimc.params.src.color_space); 1171 ret = check_fimc_src_constraints(&g_s5p_fimc); 1172 1173 if(ret != 0) { 1174 if(ret < 0) { 1175 LOGE("Not supported source image size"); 1176 goto end; 1177 } else { 1178 LOGD("src width, height are changed [w= %d, h= %d] -> [w=%d, h= %d]" 1179 , w, h, g_s5p_fimc.params.src.width 1180 , g_s5p_fimc.params.src.height); 1181 w = g_s5p_fimc.params.src.width; 1182 h = g_s5p_fimc.params.src.height; 1183 } 1184 } 1185 1186 rc = v4l2_overlay_init(ctx->ctl_fd, w, h, ctx->format, phyAddr); 1187 if (rc) { 1188 LOGE("Error initializing overlay"); 1189 goto end; 1190 } 1191 rc = v4l2_overlay_set_crop(ctx->ctl_fd, 0, 0, w, h); 1192 if (rc) { 1193 LOGE("Error setting crop window\n"); 1194 goto end; 1195 } 1196 rc = v4l2_overlay_req_buf(ctx->ctl_fd, (uint32_t *)(&ctx->num_buffers), 1197 ctx->cacheable_buffers, (int)ctx->zerocopy); 1198 if (rc) { 1199 LOGE("Error creating buffers"); 1200 goto end; 1201 } 1202 1203 if (!ctx->zerocopy) { 1204 for (int i = 0; i < ctx->num_buffers; i++) 1205 v4l2_overlay_map_buf(ctx->ctl_fd, i, &ctx->buffers[i], 1206 &ctx->buffers_len[i]); 1207 } 1208 1209 rc = enable_streaming_locked(ctx->shared, ctx->ctl_fd); 1210 1211 end: 1212 pthread_mutex_unlock(&ctx->shared->lock); 1213 1214 return rc; 1215 } 1216 1217 1218 static int overlay_data_setParameter(struct overlay_data_device_t *dev, 1219 int param, int value) 1220 { 1221 int ret = 0; 1222 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1223 1224 if (ctx->shared == NULL) { 1225 LOGI("Shared Data Not Init'd!\n"); 1226 return -1; 1227 } 1228 1229 if (ctx->shared->dataReady) { 1230 LOGI("Too late. Cant set it now!\n"); 1231 return -1; 1232 } 1233 1234 if (param == CACHEABLE_BUFFERS) 1235 ctx->cacheable_buffers = value; 1236 1237 return ( ret ); 1238 } 1239 1240 1241 static int overlay_setCrop(struct overlay_data_device_t *dev, uint32_t x, 1242 uint32_t y, uint32_t w, uint32_t h) { 1243 LOG_FUNCTION_NAME; 1244 1245 int rc = 0; 1246 int cnt = 0; 1247 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1248 1249 if (ctx->shared == NULL) { 1250 LOGI("Shared Data Not Init'd!\n"); 1251 return -1; 1252 } 1253 1254 pthread_mutex_lock(&ctx->shared->lock); 1255 1256 ctx->shared->dataReady = 1; 1257 1258 if (ctx->data.cropX == x && ctx->data.cropY == y && ctx->data.cropW == w 1259 && ctx->data.cropH == h) { 1260 goto end; 1261 } 1262 1263 ctx->data.cropX = x; 1264 ctx->data.cropY = y; 1265 ctx->data.cropW = w; 1266 ctx->data.cropH = h; 1267 1268 LOGV("Crop Win/X%d/Y%d/W%d/H%d\n", x, y, w, h ); 1269 1270 if ((rc = disable_streaming_locked(ctx->shared, ctx->ctl_fd))) 1271 goto end; 1272 1273 rc = v4l2_overlay_set_crop(ctx->ctl_fd, x, y, w, h); 1274 if (rc) { 1275 LOGE("Set Crop Window Failed!/%d\n", rc); 1276 } 1277 1278 rc = enable_streaming_locked(ctx->shared, ctx->ctl_fd); 1279 1280 end: 1281 pthread_mutex_unlock(&ctx->shared->lock); 1282 return rc; 1283 } 1284 1285 static int overlay_getCrop(struct overlay_data_device_t *dev , uint32_t* x, 1286 uint32_t* y, uint32_t* w, uint32_t* h) { 1287 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1288 1289 return v4l2_overlay_get_crop(ctx->ctl_fd, x, y, w, h); 1290 } 1291 1292 int overlay_dequeueBuffer(struct overlay_data_device_t *dev, 1293 overlay_buffer_t *buffer) { 1294 /* blocks until a buffer is available and return an opaque structure 1295 * representing this buffer. 1296 */ 1297 1298 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1299 1300 int rc=0; 1301 int i = -1; 1302 uint32_t num = 0; 1303 int cnt = 0; 1304 1305 pthread_mutex_lock(&ctx->shared->lock); 1306 if ( ctx->shared->streamingReset ) { 1307 ctx->shared->streamingReset = 0; 1308 pthread_mutex_unlock(&ctx->shared->lock); 1309 return ALL_BUFFERS_FLUSHED; 1310 } 1311 pthread_mutex_unlock(&ctx->shared->lock); 1312 1313 /* If we are not streaming dequeue will fail, 1314 skip to prevent error printouts */ 1315 if (ctx->shared->streamEn && ctx->qd_buf_count) { 1316 if ((rc = v4l2_overlay_dq_buf( ctx->ctl_fd, &i ,ctx->zerocopy)) != 0) { 1317 LOGE("Failed to DQ/%d\n", rc); 1318 } 1319 else if (i < 0 || i > ctx->num_buffers) { 1320 rc = -EINVAL; 1321 } else { 1322 *((int *)buffer) = i; 1323 ctx->qd_buf_count --; 1324 } 1325 } else { 1326 rc = -1; 1327 } 1328 1329 return rc; 1330 } 1331 1332 int overlay_queueBuffer(struct overlay_data_device_t *dev, 1333 overlay_buffer_t buffer) { 1334 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1335 1336 int cnt = 0; 1337 1338 pthread_mutex_lock(&ctx->shared->lock); 1339 if ( ctx->shared->streamingReset ) { 1340 ctx->shared->streamingReset = 0; 1341 pthread_mutex_unlock(&ctx->shared->lock); 1342 return ALL_BUFFERS_FLUSHED; 1343 } 1344 pthread_mutex_unlock(&ctx->shared->lock); 1345 1346 /* Catch the case where the data side had no need to set the crop window */ 1347 if (!ctx->shared->dataReady) { 1348 ctx->shared->dataReady = 1; 1349 enable_streaming(ctx->shared, ctx->ctl_fd); 1350 } 1351 1352 if (!ctx->shared->controlReady) return -1; 1353 int rc = v4l2_overlay_q_buf( ctx->ctl_fd, (int)buffer, (int) ctx->zerocopy ); 1354 if (rc == 0 && ctx->qd_buf_count < ctx->num_buffers) { 1355 ctx->qd_buf_count ++; 1356 } 1357 1358 return rc; 1359 } 1360 1361 void *overlay_getBufferAddress(struct overlay_data_device_t *dev, 1362 overlay_buffer_t buffer) 1363 { 1364 LOG_FUNCTION_NAME; 1365 1366 /* this may fail (NULL) if this feature is not supported. In that case, 1367 * presumably, there is some other HAL module that can fill the buffer, 1368 * using a DSP for instance 1369 */ 1370 int ret; 1371 struct v4l2_buffer buf; 1372 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1373 1374 if (ctx->zerocopy) 1375 return NULL; 1376 1377 if ((int)buffer >= 0 && (int)buffer < ctx->num_buffers) 1378 return (void*) ctx->buffers[(int)buffer]; 1379 else 1380 return NULL; 1381 } 1382 1383 int overlay_getBufferCount(struct overlay_data_device_t *dev) 1384 { 1385 LOG_FUNCTION_NAME; 1386 1387 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1388 1389 return (ctx->num_buffers); 1390 } 1391 1392 static int overlay_data_close(struct hw_device_t *dev) { 1393 1394 LOG_FUNCTION_NAME; 1395 1396 struct overlay_data_context_t* ctx = (struct overlay_data_context_t*)dev; 1397 int rc; 1398 1399 if (ctx) { 1400 overlay_data_device_t *overlay_dev = &ctx->device; 1401 int buf; 1402 int i; 1403 1404 pthread_mutex_lock(&ctx->shared->lock); 1405 1406 if (!ctx->zerocopy) 1407 for (i = 0; i < ctx->num_buffers; i++) { 1408 LOGV("Unmap Buffer/%d/%08lx/%d", i, (unsigned long)ctx->buffers[i], 1409 ctx->buffers_len[i] ); 1410 rc = v4l2_overlay_unmap_buf(ctx->buffers[i], ctx->buffers_len[i]); 1411 if (rc != 0) { 1412 LOGE("Error unmapping the buffer/%d/%d", i, rc); 1413 } 1414 } 1415 1416 delete (ctx->mapping_data); 1417 delete [] ctx->buffers; 1418 delete [] ctx->buffers_len; 1419 1420 pthread_mutex_unlock(&ctx->shared->lock); 1421 1422 ctx->shared->dataReady = 0; 1423 close_shared_data( ctx ); 1424 1425 free(ctx); 1426 } 1427 1428 return 0; 1429 } 1430 1431 /*****************************************************************************/ 1432 1433 static int overlay_device_open(const struct hw_module_t* module, 1434 const char* name, struct hw_device_t** device) 1435 { 1436 LOG_FUNCTION_NAME; 1437 int status = -EINVAL; 1438 1439 if (!strcmp(name, OVERLAY_HARDWARE_CONTROL)) { 1440 struct overlay_control_context_t *dev; 1441 dev = (overlay_control_context_t*)malloc(sizeof(*dev)); 1442 1443 /* initialize our state here */ 1444 memset(dev, 0, sizeof(*dev)); 1445 1446 /* initialize the procs */ 1447 dev->device.common.tag = HARDWARE_DEVICE_TAG; 1448 dev->device.common.version = 0; 1449 dev->device.common.module = const_cast<hw_module_t*>(module); 1450 dev->device.common.close = overlay_control_close; 1451 1452 dev->device.get = overlay_get; 1453 dev->device.createOverlay = overlay_createOverlay; 1454 dev->device.destroyOverlay = overlay_destroyOverlay; 1455 dev->device.setPosition = overlay_setPosition; 1456 dev->device.getPosition = overlay_getPosition; 1457 dev->device.setParameter = overlay_setParameter; 1458 dev->device.stage = overlay_stage; 1459 dev->device.commit = overlay_commit; 1460 1461 *device = &dev->device.common; 1462 status = 0; 1463 } else if (!strcmp(name, OVERLAY_HARDWARE_DATA)) { 1464 struct overlay_data_context_t *dev; 1465 dev = (overlay_data_context_t*)malloc(sizeof(*dev)); 1466 1467 /* initialize our state here */ 1468 memset(dev, 0, sizeof(*dev)); 1469 1470 /* initialize the procs */ 1471 dev->device.common.tag = HARDWARE_DEVICE_TAG; 1472 dev->device.common.version = 0; 1473 dev->device.common.module = const_cast<hw_module_t*>(module); 1474 dev->device.common.close = overlay_data_close; 1475 1476 dev->device.initialize = overlay_initialize; 1477 dev->device.resizeInput = overlay_resizeInput; 1478 dev->device.setCrop = overlay_setCrop; 1479 dev->device.getCrop = overlay_getCrop; 1480 dev->device.setParameter = overlay_data_setParameter; 1481 dev->device.dequeueBuffer = overlay_dequeueBuffer; 1482 dev->device.queueBuffer = overlay_queueBuffer; 1483 dev->device.getBufferAddress = overlay_getBufferAddress; 1484 dev->device.getBufferCount = overlay_getBufferCount; 1485 1486 *device = &dev->device.common; 1487 status = 0; 1488 } 1489 return status; 1490 } 1491