hwc.cpp revision a00c043512babb1d6f48a0a505f30b906fac8066
1/* 2 * Copyright (C) 2012 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#include <errno.h> 17#include <fcntl.h> 18#include <poll.h> 19#include <pthread.h> 20#include <stdio.h> 21#include <stdlib.h> 22 23#include <sys/ioctl.h> 24#include <sys/mman.h> 25#include <sys/time.h> 26#include <sys/resource.h> 27 28#include <s3c-fb.h> 29 30#include <EGL/egl.h> 31 32#define HWC_REMOVE_DEPRECATED_VERSIONS 1 33 34#include <cutils/log.h> 35#include <hardware/gralloc.h> 36#include <hardware/hardware.h> 37#include <hardware/hwcomposer.h> 38#include <hardware_legacy/uevent.h> 39#include <utils/Vector.h> 40 41#include <sync/sync.h> 42 43#include "ion.h" 44#include "gralloc_priv.h" 45#include "exynos_gscaler.h" 46#include "exynos_format.h" 47 48struct hwc_callback_entry { 49 void (*callback)(void *, private_handle_t *); 50 void *data; 51}; 52typedef android::Vector<struct hwc_callback_entry> hwc_callback_queue_t; 53 54const size_t NUM_HW_WINDOWS = 5; 55const size_t NO_FB_NEEDED = NUM_HW_WINDOWS + 1; 56const size_t MAX_PIXELS = 2560 * 1600 * 2; 57const size_t NUM_GSC_UNITS = 3; 58const size_t GSC_W_ALIGNMENT = 16; 59const size_t GSC_H_ALIGNMENT = 16; 60const int CAMERA_GSC_IDX = 2; 61 62struct exynos5_hwc_composer_device_1_t; 63 64struct exynos5_gsc_map_t { 65 enum { 66 GSC_NONE = 0, 67 GSC_M2M, 68 // TODO: GSC_LOCAL_PATH 69 } mode; 70 int idx; 71}; 72 73struct exynos5_hwc_post_data_t { 74 exynos5_hwc_composer_device_1_t *pdev; 75 int overlay_map[NUM_HW_WINDOWS]; 76 exynos5_gsc_map_t gsc_map[NUM_HW_WINDOWS]; 77 hwc_layer_1_t overlays[NUM_HW_WINDOWS]; 78 int num_overlays; 79 size_t fb_window; 80 int fence; 81 pthread_mutex_t completion_lock; 82 pthread_cond_t completion; 83}; 84 85const size_t NUM_GSC_DST_BUFS = 2; 86struct exynos5_gsc_data_t { 87 void *gsc; 88 exynos_gsc_img src_cfg; 89 exynos_gsc_img dst_cfg; 90 buffer_handle_t dst_buf[NUM_GSC_DST_BUFS]; 91 size_t current_buf; 92}; 93 94struct exynos5_hwc_composer_device_1_t { 95 hwc_composer_device_1_t base; 96 97 int fd; 98 int vsync_fd; 99 exynos5_hwc_post_data_t bufs; 100 101 const private_module_t *gralloc_module; 102 alloc_device_t *alloc_device; 103 hwc_procs_t *procs; 104 pthread_t vsync_thread; 105 106 bool hdmi_hpd; 107 bool hdmi_mirroring; 108 void *hdmi_gsc; 109 110 exynos5_gsc_data_t gsc[NUM_GSC_UNITS]; 111}; 112 113static void dump_handle(private_handle_t *h) 114{ 115 ALOGV("\t\tformat = %d, width = %u, height = %u, stride = %u", 116 h->format, h->width, h->height, h->stride); 117} 118 119static void dump_layer(hwc_layer_1_t const *l) 120{ 121 ALOGV("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, " 122 "{%d,%d,%d,%d}, {%d,%d,%d,%d}", 123 l->compositionType, l->flags, l->handle, l->transform, 124 l->blending, 125 l->sourceCrop.left, 126 l->sourceCrop.top, 127 l->sourceCrop.right, 128 l->sourceCrop.bottom, 129 l->displayFrame.left, 130 l->displayFrame.top, 131 l->displayFrame.right, 132 l->displayFrame.bottom); 133 134 if(l->handle && !(l->flags & HWC_SKIP_LAYER)) 135 dump_handle(private_handle_t::dynamicCast(l->handle)); 136} 137 138static void dump_config(s3c_fb_win_config &c) 139{ 140 ALOGV("\tstate = %u", c.state); 141 if (c.state == c.S3C_FB_WIN_STATE_BUFFER) { 142 ALOGV("\t\tfd = %d, offset = %u, stride = %u, " 143 "x = %d, y = %d, w = %u, h = %u, " 144 "format = %u", 145 c.fd, c.offset, c.stride, 146 c.x, c.y, c.w, c.h, 147 c.format); 148 } 149 else if (c.state == c.S3C_FB_WIN_STATE_COLOR) { 150 ALOGV("\t\tcolor = %u", c.color); 151 } 152} 153 154static void dump_gsc_img(exynos_gsc_img &c) 155{ 156 ALOGV("\tx = %u, y = %u, w = %u, h = %u, fw = %u, fh = %u", 157 c.x, c.y, c.w, c.h, c.fw, c.fh); 158 ALOGV("\taddr = {%u, %u, %u}, rot = %u, cacheable = %u, drmMode = %u", 159 c.yaddr, c.uaddr, c.vaddr, c.rot, c.cacheable, c.drmMode); 160} 161 162inline int WIDTH(const hwc_rect &rect) { return rect.right - rect.left; } 163inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; } 164template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; } 165template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; } 166 167static bool is_transformed(const hwc_layer_1_t &layer) 168{ 169 return layer.transform != 0; 170} 171 172static bool is_rotated(const hwc_layer_1_t &layer) 173{ 174 return (layer.transform & HAL_TRANSFORM_ROT_90) || 175 (layer.transform & HAL_TRANSFORM_ROT_180); 176} 177 178static bool is_scaled(const hwc_layer_1_t &layer) 179{ 180 return WIDTH(layer.displayFrame) != WIDTH(layer.sourceCrop) || 181 HEIGHT(layer.displayFrame) != HEIGHT(layer.sourceCrop); 182} 183 184static enum s3c_fb_pixel_format exynos5_format_to_s3c_format(int format) 185{ 186 switch (format) { 187 case HAL_PIXEL_FORMAT_RGBA_8888: 188 return S3C_FB_PIXEL_FORMAT_RGBA_8888; 189 case HAL_PIXEL_FORMAT_RGBX_8888: 190 return S3C_FB_PIXEL_FORMAT_RGBX_8888; 191 case HAL_PIXEL_FORMAT_RGBA_5551: 192 return S3C_FB_PIXEL_FORMAT_RGBA_5551; 193 case HAL_PIXEL_FORMAT_RGBA_4444: 194 return S3C_FB_PIXEL_FORMAT_RGBA_4444; 195 196 default: 197 return S3C_FB_PIXEL_FORMAT_MAX; 198 } 199} 200 201static bool exynos5_format_is_supported(int format) 202{ 203 return exynos5_format_to_s3c_format(format) < S3C_FB_PIXEL_FORMAT_MAX; 204} 205 206static bool exynos5_format_is_supported_by_gscaler(int format) 207{ 208 switch (format) { 209 case HAL_PIXEL_FORMAT_RGBX_8888: 210 case HAL_PIXEL_FORMAT_RGB_565: 211 case HAL_PIXEL_FORMAT_YV12: 212 case HAL_PIXEL_FORMAT_YCbCr_420_P: 213 case HAL_PIXEL_FORMAT_YCbCr_422_SP: 214 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP: 215 case HAL_PIXEL_FORMAT_YCbCr_420_SP: 216 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP: 217 case HAL_PIXEL_FORMAT_YCbCr_422_I: 218 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I: 219 case HAL_PIXEL_FORMAT_YCbCr_422_P: 220 case HAL_PIXEL_FORMAT_CbYCrY_422_I: 221 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I: 222 case HAL_PIXEL_FORMAT_YCrCb_422_SP: 223 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP: 224 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 225 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP: 226 case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: 227 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED: 228 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I: 229 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I: 230 return true; 231 232 default: 233 return false; 234 } 235} 236 237static bool exynos5_format_requires_gscaler(int format) 238{ 239 return exynos5_format_is_supported_by_gscaler(format) && 240 format != HAL_PIXEL_FORMAT_RGBX_8888; 241} 242 243static uint8_t exynos5_format_to_bpp(int format) 244{ 245 switch (format) { 246 case HAL_PIXEL_FORMAT_RGBA_8888: 247 case HAL_PIXEL_FORMAT_RGBX_8888: 248 return 32; 249 250 case HAL_PIXEL_FORMAT_RGBA_5551: 251 case HAL_PIXEL_FORMAT_RGBA_4444: 252 return 16; 253 254 default: 255 ALOGW("unrecognized pixel format %u", format); 256 return 0; 257 } 258} 259 260static bool exynos5_supports_gscaler(hwc_layer_1_t &layer, int format) 261{ 262 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); 263 264 int max_w = is_rotated(layer) ? 2048 : 4800; 265 int max_h = is_rotated(layer) ? 2048 : 3344; 266 267 bool rot90or270 = !!(layer.transform & HAL_TRANSFORM_ROT_90); 268 // n.b.: HAL_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_90 | 269 // HAL_TRANSFORM_ROT_180 270 271 return exynos5_format_is_supported_by_gscaler(format) && 272 handle->stride <= max_w && 273 handle->stride % GSC_W_ALIGNMENT == 0 && 274 handle->height <= max_h && 275 handle->height % GSC_H_ALIGNMENT == 0 && 276 // per 46.2 277 (!rot90or270 || layer.sourceCrop.top % 2 == 0) && 278 (!rot90or270 || layer.sourceCrop.left % 2 == 0); 279 // per 46.3.1.6 280} 281 282static int hdmi_enable(struct exynos5_hwc_composer_device_1_t *dev) 283{ 284 if (dev->hdmi_mirroring) 285 return 0; 286 287 exynos_gsc_img src_info; 288 exynos_gsc_img dst_info; 289 290 // TODO: Don't hardcode 291 int src_w = 2560; 292 int src_h = 1600; 293 int dst_w = 1920; 294 int dst_h = 1080; 295 296 dev->hdmi_gsc = exynos_gsc_create_exclusive(3, GSC_OUTPUT_MODE, GSC_OUT_TV); 297 if (!dev->hdmi_gsc) { 298 ALOGE("%s: exynos_gsc_create_exclusive failed", __func__); 299 return -ENODEV; 300 } 301 302 memset(&src_info, 0, sizeof(src_info)); 303 memset(&dst_info, 0, sizeof(dst_info)); 304 305 src_info.w = src_w; 306 src_info.h = src_h; 307 src_info.fw = src_w; 308 src_info.fh = src_h; 309 src_info.format = HAL_PIXEL_FORMAT_BGRA_8888; 310 311 dst_info.w = dst_w; 312 dst_info.h = dst_h; 313 dst_info.fw = dst_w; 314 dst_info.fh = dst_h; 315 dst_info.format = HAL_PIXEL_FORMAT_YV12; 316 317 int ret = exynos_gsc_config_exclusive(dev->hdmi_gsc, &src_info, &dst_info); 318 if (ret < 0) { 319 ALOGE("%s: exynos_gsc_config_exclusive failed %d", __func__, ret); 320 exynos_gsc_destroy(dev->hdmi_gsc); 321 dev->hdmi_gsc = NULL; 322 return ret; 323 } 324 325 dev->hdmi_mirroring = true; 326 return 0; 327} 328 329static void hdmi_disable(struct exynos5_hwc_composer_device_1_t *dev) 330{ 331 if (!dev->hdmi_mirroring) 332 return; 333 exynos_gsc_destroy(dev->hdmi_gsc); 334 dev->hdmi_gsc = NULL; 335 dev->hdmi_mirroring = false; 336} 337 338static int hdmi_output(struct exynos5_hwc_composer_device_1_t *dev, private_handle_t *fb) 339{ 340 exynos_gsc_img src_info; 341 exynos_gsc_img dst_info; 342 343 memset(&src_info, 0, sizeof(src_info)); 344 memset(&dst_info, 0, sizeof(dst_info)); 345 346 src_info.yaddr = fb->fd; 347 348 int ret = exynos_gsc_run_exclusive(dev->hdmi_gsc, &src_info, &dst_info); 349 if (ret < 0) { 350 ALOGE("%s: exynos_gsc_run_exclusive failed %d", __func__, ret); 351 return ret; 352 } 353 354 return 0; 355} 356 357bool exynos5_supports_overlay(hwc_layer_1_t &layer, size_t i) 358{ 359 if (layer.flags & HWC_SKIP_LAYER) { 360 ALOGV("\tlayer %u: skipping", i); 361 return false; 362 } 363 364 private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); 365 366 if (!handle) { 367 ALOGV("\tlayer %u: handle is NULL", i); 368 return false; 369 } 370 if (exynos5_format_requires_gscaler(handle->format)) { 371 if (!exynos5_supports_gscaler(layer, handle->format)) { 372 ALOGV("\tlayer %u: gscaler required but not supported", i); 373 return false; 374 } 375 } else { 376 if (!exynos5_format_is_supported(handle->format)) { 377 ALOGV("\tlayer %u: pixel format %u not supported", i, handle->format); 378 return false; 379 } 380 if (is_scaled(layer)) { 381 ALOGV("\tlayer %u: scaling not supported", i); 382 return false; 383 } 384 if (is_transformed(layer)) { 385 ALOGV("\tlayer %u: transformations not supported", i); 386 return false; 387 } 388 } 389 if (layer.blending != HWC_BLENDING_NONE) { 390 // TODO: support this 391 ALOGV("\tlayer %u: blending not supported", i); 392 return false; 393 } 394 395 return true; 396} 397 398inline bool intersect(const hwc_rect &r1, const hwc_rect &r2) 399{ 400 return !(r1.left > r2.right || 401 r1.right < r2.left || 402 r1.top > r2.bottom || 403 r1.bottom < r2.top); 404} 405 406inline hwc_rect intersection(const hwc_rect &r1, const hwc_rect &r2) 407{ 408 hwc_rect i; 409 i.top = max(r1.top, r2.top); 410 i.bottom = min(r1.bottom, r2.bottom); 411 i.left = max(r1.left, r2.left); 412 i.right = min(r1.right, r2.right); 413 return i; 414} 415 416static int exynos5_prepare(hwc_composer_device_1_t *dev, hwc_layer_list_1_t* list) 417{ 418 if (!list) 419 return 0; 420 421 ALOGV("preparing %u layers", list->numHwLayers); 422 423 exynos5_hwc_composer_device_1_t *pdev = 424 (exynos5_hwc_composer_device_1_t *)dev; 425 memset(pdev->bufs.overlays, 0, sizeof(pdev->bufs.overlays)); 426 memset(pdev->bufs.gsc_map, 0, sizeof(pdev->bufs.gsc_map)); 427 428 bool force_fb = false; 429 if (pdev->hdmi_hpd) { 430 hdmi_enable(pdev); 431 force_fb = true; 432 } else { 433 hdmi_disable(pdev); 434 } 435 436 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) 437 pdev->bufs.overlay_map[i] = -1; 438 439 bool fb_needed = false; 440 size_t first_fb = 0, last_fb = 0; 441 442 // find unsupported overlays 443 for (size_t i = 0; i < list->numHwLayers; i++) { 444 hwc_layer_1_t &layer = list->hwLayers[i]; 445 446 if (layer.compositionType == HWC_BACKGROUND && !force_fb) { 447 ALOGV("\tlayer %u: background supported", i); 448 dump_layer(&list->hwLayers[i]); 449 continue; 450 } 451 452 if (exynos5_supports_overlay(list->hwLayers[i], i) && !force_fb) { 453 ALOGV("\tlayer %u: overlay supported", i); 454 layer.compositionType = HWC_OVERLAY; 455 dump_layer(&list->hwLayers[i]); 456 continue; 457 } 458 459 if (!fb_needed) { 460 first_fb = i; 461 fb_needed = true; 462 } 463 last_fb = i; 464 layer.compositionType = HWC_FRAMEBUFFER; 465 466 dump_layer(&list->hwLayers[i]); 467 } 468 469 // can't composite overlays sandwiched between framebuffers 470 if (fb_needed) 471 for (size_t i = first_fb; i < last_fb; i++) 472 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; 473 474 // Incrementally try to add our supported layers to hardware windows. 475 // If adding a layer would violate a hardware constraint, force it 476 // into the framebuffer and try again. (Revisiting the entire list is 477 // necessary because adding a layer to the framebuffer can cause other 478 // windows to retroactively violate constraints.) 479 bool changed; 480 do { 481 android::Vector<hwc_rect> rects; 482 android::Vector<hwc_rect> overlaps; 483 size_t pixels_left, windows_left, gsc_left = NUM_GSC_UNITS; 484 485 if (fb_needed) { 486 hwc_rect_t fb_rect; 487 fb_rect.top = fb_rect.left = 0; 488 fb_rect.right = pdev->gralloc_module->xres - 1; 489 fb_rect.bottom = pdev->gralloc_module->yres - 1; 490 pixels_left = MAX_PIXELS - pdev->gralloc_module->xres * 491 pdev->gralloc_module->yres; 492 windows_left = NUM_HW_WINDOWS - 1; 493 rects.push_back(fb_rect); 494 } 495 else { 496 pixels_left = MAX_PIXELS; 497 windows_left = NUM_HW_WINDOWS; 498 } 499 if (pdev->hdmi_mirroring) 500 gsc_left--; 501 502 changed = false; 503 504 for (size_t i = 0; i < list->numHwLayers; i++) { 505 hwc_layer_1_t &layer = list->hwLayers[i]; 506 if (layer.flags & HWC_SKIP_LAYER) 507 continue; 508 509 private_handle_t *handle = private_handle_t::dynamicCast( 510 layer.handle); 511 512 // we've already accounted for the framebuffer above 513 if (layer.compositionType == HWC_FRAMEBUFFER) 514 continue; 515 516 // only layer 0 can be HWC_BACKGROUND, so we can 517 // unconditionally allow it without extra checks 518 if (layer.compositionType == HWC_BACKGROUND) { 519 windows_left--; 520 continue; 521 } 522 523 size_t pixels_needed = WIDTH(layer.displayFrame) * 524 HEIGHT(layer.displayFrame); 525 bool can_compose = windows_left && pixels_needed <= pixels_left; 526 bool gsc_required = exynos5_format_requires_gscaler(handle->format); 527 if (gsc_required) 528 can_compose = can_compose && gsc_left; 529 530 // hwc_rect_t right and bottom values are normally exclusive; 531 // the intersection logic is simpler if we make them inclusive 532 hwc_rect_t visible_rect = layer.displayFrame; 533 visible_rect.right--; visible_rect.bottom--; 534 535 // no more than 2 layers can overlap on a given pixel 536 for (size_t j = 0; can_compose && j < overlaps.size(); j++) { 537 if (intersect(visible_rect, overlaps.itemAt(j))) 538 can_compose = false; 539 } 540 541 if (!can_compose) { 542 layer.compositionType = HWC_FRAMEBUFFER; 543 if (!fb_needed) { 544 first_fb = last_fb = i; 545 fb_needed = true; 546 } 547 else { 548 first_fb = min(i, first_fb); 549 last_fb = max(i, last_fb); 550 } 551 changed = true; 552 break; 553 } 554 555 for (size_t j = 0; j < rects.size(); j++) { 556 const hwc_rect_t &other_rect = rects.itemAt(j); 557 if (intersect(visible_rect, other_rect)) 558 overlaps.push_back(intersection(visible_rect, other_rect)); 559 } 560 rects.push_back(visible_rect); 561 pixels_left -= pixels_needed; 562 windows_left--; 563 if (gsc_required) 564 gsc_left--; 565 } 566 567 if (changed) 568 for (size_t i = first_fb; i < last_fb; i++) 569 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; 570 } while(changed); 571 572 unsigned int nextWindow = 0; 573 int nextGsc = 0; 574 575 for (size_t i = 0; i < list->numHwLayers; i++) { 576 hwc_layer_1_t &layer = list->hwLayers[i]; 577 if (layer.flags & HWC_SKIP_LAYER) 578 continue; 579 580 if (fb_needed && i == first_fb) { 581 ALOGV("assigning framebuffer to window %u\n", 582 nextWindow); 583 nextWindow++; 584 continue; 585 } 586 587 if (layer.compositionType != HWC_FRAMEBUFFER) { 588 ALOGV("assigning layer %u to window %u", i, nextWindow); 589 pdev->bufs.overlay_map[nextWindow] = i; 590 if (layer.compositionType == HWC_OVERLAY) { 591 private_handle_t *handle = 592 private_handle_t::dynamicCast(layer.handle); 593 if (exynos5_format_requires_gscaler(handle->format)) { 594 ALOGV("\tusing gscaler %u", nextGsc); 595 pdev->bufs.gsc_map[i].mode = 596 exynos5_gsc_map_t::GSC_M2M; 597 pdev->bufs.gsc_map[i].idx = nextGsc++; 598 if (nextGsc == CAMERA_GSC_IDX) 599 nextGsc++; 600 } 601 } 602 nextWindow++; 603 } 604 } 605 606 for (size_t i = nextGsc; i < NUM_GSC_UNITS; i++) { 607 for (size_t j = 0; j < NUM_GSC_DST_BUFS; j++) 608 if (pdev->gsc[i].dst_buf[j]) 609 pdev->alloc_device->free(pdev->alloc_device, 610 pdev->gsc[i].dst_buf[j]); 611 memset(&pdev->gsc[i], 0, sizeof(pdev->gsc[i])); 612 } 613 614 if (fb_needed) 615 pdev->bufs.fb_window = first_fb; 616 else 617 pdev->bufs.fb_window = NO_FB_NEEDED; 618 619 return 0; 620} 621 622static inline bool gsc_dst_cfg_changed(exynos_gsc_img &c1, exynos_gsc_img &c2) 623{ 624 return c1.x != c2.x || 625 c1.y != c2.y || 626 c1.w != c2.w || 627 c1.h != c2.h || 628 c1.format != c2.format || 629 c1.rot != c2.rot || 630 c1.cacheable != c2.cacheable || 631 c1.drmMode != c2.drmMode; 632} 633 634static inline bool gsc_src_cfg_changed(exynos_gsc_img &c1, exynos_gsc_img &c2) 635{ 636 return gsc_dst_cfg_changed(c1, c2) || 637 c1.fw != c2.fw || 638 c1.fh != c2.fh; 639} 640 641static int exynos5_config_gsc_m2m(hwc_layer_1_t &layer, 642 alloc_device_t* alloc_device, exynos5_gsc_data_t *gsc_data, 643 int gsc_idx) 644{ 645 ALOGV("configuring gscaler %u for memory-to-memory", gsc_idx); 646 647 private_handle_t *src_handle = private_handle_t::dynamicCast(layer.handle); 648 buffer_handle_t dst_buf; 649 private_handle_t *dst_handle; 650 int ret = 0; 651 652 exynos_gsc_img src_cfg, dst_cfg; 653 memset(&src_cfg, 0, sizeof(src_cfg)); 654 memset(&dst_cfg, 0, sizeof(dst_cfg)); 655 656 src_cfg.x = layer.sourceCrop.left; 657 src_cfg.y = layer.sourceCrop.top; 658 src_cfg.w = WIDTH(layer.sourceCrop); 659 src_cfg.fw = src_handle->stride; 660 src_cfg.h = HEIGHT(layer.sourceCrop); 661 src_cfg.fh = src_handle->height; 662 src_cfg.yaddr = src_handle->fd; 663 src_cfg.uaddr = src_handle->fd1; 664 src_cfg.vaddr = src_handle->fd2; 665 src_cfg.format = src_handle->format; 666 667 dst_cfg.x = 0; 668 dst_cfg.y = 0; 669 dst_cfg.w = WIDTH(layer.displayFrame); 670 dst_cfg.h = HEIGHT(layer.displayFrame); 671 dst_cfg.format = HAL_PIXEL_FORMAT_BGRA_8888; 672 dst_cfg.rot = layer.transform; 673 674 ALOGV("source configuration:"); 675 dump_gsc_img(src_cfg); 676 677 if (gsc_src_cfg_changed(src_cfg, gsc_data->src_cfg) || 678 gsc_dst_cfg_changed(dst_cfg, gsc_data->dst_cfg)) { 679 int dst_stride; 680 int usage = GRALLOC_USAGE_SW_READ_NEVER | 681 GRALLOC_USAGE_SW_WRITE_NEVER | 682 GRALLOC_USAGE_HW_COMPOSER; 683 // TODO: add GRALLOC_USAGE_PROTECTED if source buffer is also protected 684 685 int w = ALIGN(WIDTH(layer.displayFrame), GSC_W_ALIGNMENT); 686 int h = ALIGN(HEIGHT(layer.displayFrame), GSC_H_ALIGNMENT); 687 688 for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { 689 if (gsc_data->dst_buf[i]) { 690 alloc_device->free(alloc_device, gsc_data->dst_buf[i]); 691 gsc_data->dst_buf[i] = NULL; 692 } 693 694 int ret = alloc_device->alloc(alloc_device, w, h, 695 HAL_PIXEL_FORMAT_RGBX_8888, usage, &gsc_data->dst_buf[i], 696 &dst_stride); 697 if (ret < 0) { 698 ALOGE("failed to allocate destination buffer: %s", 699 strerror(-ret)); 700 goto err_alloc; 701 } 702 } 703 704 gsc_data->current_buf = 0; 705 } 706 707 dst_buf = gsc_data->dst_buf[gsc_data->current_buf]; 708 dst_handle = private_handle_t::dynamicCast(dst_buf); 709 710 dst_cfg.fw = dst_handle->stride; 711 dst_cfg.fh = dst_handle->height; 712 dst_cfg.yaddr = dst_handle->fd; 713 714 ALOGV("destination configuration:"); 715 dump_gsc_img(dst_cfg); 716 717 gsc_data->gsc = exynos_gsc_create_exclusive(gsc_idx, GSC_M2M_MODE, 718 GSC_DUMMY); 719 if (!gsc_data->gsc) { 720 ALOGE("failed to create gscaler handle"); 721 ret = -1; 722 goto err_alloc; 723 } 724 725 ret = exynos_gsc_config_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg); 726 if (ret < 0) { 727 ALOGE("failed to configure gscaler %u", gsc_idx); 728 goto err_gsc_config; 729 } 730 731 ret = exynos_gsc_run_exclusive(gsc_data->gsc, &src_cfg, &dst_cfg); 732 if (ret < 0) { 733 ALOGE("failed to run gscaler %u", gsc_idx); 734 goto err_gsc_config; 735 } 736 737 gsc_data->src_cfg = src_cfg; 738 gsc_data->dst_cfg = dst_cfg; 739 740 return 0; 741 742err_gsc_config: 743 exynos_gsc_destroy(gsc_data->gsc); 744 gsc_data->gsc = NULL; 745err_alloc: 746 for (size_t i = 0; i < NUM_GSC_DST_BUFS; i++) { 747 if (gsc_data->dst_buf[i]) { 748 alloc_device->free(alloc_device, gsc_data->dst_buf[i]); 749 gsc_data->dst_buf[i] = NULL; 750 } 751 } 752 return ret; 753} 754 755static void exynos5_config_handle(private_handle_t *handle, 756 hwc_rect_t &sourceCrop, hwc_rect_t &displayFrame, 757 s3c_fb_win_config &cfg) 758{ 759 cfg.state = cfg.S3C_FB_WIN_STATE_BUFFER; 760 cfg.fd = handle->fd; 761 cfg.x = displayFrame.left; 762 cfg.y = displayFrame.top; 763 cfg.w = WIDTH(displayFrame); 764 cfg.h = HEIGHT(displayFrame); 765 cfg.format = exynos5_format_to_s3c_format(handle->format); 766 uint8_t bpp = exynos5_format_to_bpp(handle->format); 767 cfg.offset = (sourceCrop.top * handle->stride + sourceCrop.left) * bpp / 8; 768 cfg.stride = handle->stride * bpp / 8; 769} 770 771static void exynos5_config_overlay(hwc_layer_1_t *layer, s3c_fb_win_config &cfg, 772 const private_module_t *gralloc_module) 773{ 774 if (layer->compositionType == HWC_BACKGROUND) { 775 hwc_color_t color = layer->backgroundColor; 776 cfg.state = cfg.S3C_FB_WIN_STATE_COLOR; 777 cfg.color = (color.r << 16) | (color.g << 8) | color.b; 778 cfg.x = 0; 779 cfg.y = 0; 780 cfg.w = gralloc_module->xres; 781 cfg.h = gralloc_module->yres; 782 return; 783 } 784 785 private_handle_t *handle = private_handle_t::dynamicCast(layer->handle); 786 exynos5_config_handle(handle, layer->sourceCrop, layer->displayFrame, cfg); 787} 788 789static void exynos5_post_callback(void *data, private_handle_t *fb) 790{ 791 exynos5_hwc_post_data_t *pdata = (exynos5_hwc_post_data_t *)data; 792 793 struct s3c_fb_win_config_data win_data; 794 struct s3c_fb_win_config *config = win_data.config; 795 memset(config, 0, sizeof(win_data.config)); 796 797 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { 798 if ( pdata->overlay_map[i] != -1) { 799 hwc_layer_1_t &layer = pdata->overlays[i]; 800 private_handle_t *handle = 801 private_handle_t::dynamicCast(layer.handle); 802 803 if (layer.acquireFenceFd != -1) { 804 int err = sync_wait(layer.acquireFenceFd, 100); 805 if (err != 0) 806 ALOGW("fence for layer %zu didn't signal in 100 ms: %s", 807 i, strerror(errno)); 808 close(layer.acquireFenceFd); 809 } 810 811 if (pdata->gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) { 812 int gsc_idx = pdata->gsc_map[i].idx; 813 exynos5_config_gsc_m2m(layer, pdata->pdev->alloc_device, 814 &pdata->pdev->gsc[gsc_idx], gsc_idx); 815 } 816 } 817 } 818 819 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { 820 if (i == pdata->fb_window) { 821 hwc_rect_t rect = { 0, 0, fb->width, fb->height }; 822 exynos5_config_handle(fb, rect, rect, config[i]); 823 } else if ( pdata->overlay_map[i] != -1) { 824 hwc_layer_1_t &layer = pdata->overlays[i]; 825 private_handle_t *handle = 826 private_handle_t::dynamicCast(layer.handle); 827 828 if (pdata->gsc_map[i].mode == exynos5_gsc_map_t::GSC_M2M) { 829 int gsc_idx = pdata->gsc_map[i].idx; 830 exynos5_gsc_data_t &gsc = pdata->pdev->gsc[gsc_idx]; 831 832 if (!gsc.gsc) { 833 ALOGE("failed to queue gscaler %u input for layer %u", 834 gsc_idx, i); 835 continue; 836 } 837 838 int err = exynos_gsc_stop_exclusive(gsc.gsc); 839 exynos_gsc_destroy(gsc.gsc); 840 gsc.gsc = NULL; 841 if (err < 0) { 842 ALOGE("failed to dequeue gscaler output for layer %u", i); 843 continue; 844 } 845 846 buffer_handle_t dst_buf = gsc.dst_buf[gsc.current_buf]; 847 gsc.current_buf = (gsc.current_buf + 1) % NUM_GSC_DST_BUFS; 848 private_handle_t *dst_handle = 849 private_handle_t::dynamicCast(dst_buf); 850 exynos5_config_handle(dst_handle, layer.sourceCrop, 851 layer.displayFrame, config[i]); 852 } 853 else { 854 exynos5_config_overlay(&layer, config[i], 855 pdata->pdev->gralloc_module); 856 } 857 } 858 ALOGV("window %u configuration:", i); 859 dump_config(config[i]); 860 } 861 862 int ret = ioctl(pdata->pdev->fd, S3CFB_WIN_CONFIG, &win_data); 863 if (ret < 0) 864 ALOGE("ioctl S3CFB_WIN_CONFIG failed: %d", errno); 865 866 if (pdata->pdev->hdmi_mirroring) 867 hdmi_output(pdata->pdev, fb); 868 869 pthread_mutex_lock(&pdata->completion_lock); 870 pdata->fence = win_data.fence; 871 pthread_cond_signal(&pdata->completion); 872 pthread_mutex_unlock(&pdata->completion_lock); 873} 874 875static int exynos5_set(struct hwc_composer_device_1 *dev, hwc_display_t dpy, 876 hwc_surface_t sur, hwc_layer_list_1_t* list) 877{ 878 exynos5_hwc_composer_device_1_t *pdev = 879 (exynos5_hwc_composer_device_1_t *)dev; 880 881 if (!dpy || !sur) 882 return 0; 883 884 hwc_callback_queue_t *queue = NULL; 885 pthread_mutex_t *lock = NULL; 886 exynos5_hwc_post_data_t *data = NULL; 887 888 if (list) { 889 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { 890 if (pdev->bufs.overlay_map[i] != -1) { 891 pdev->bufs.overlays[i] = 892 list->hwLayers[pdev->bufs.overlay_map[i]]; 893 } 894 } 895 896 data = (exynos5_hwc_post_data_t *) 897 malloc(sizeof(exynos5_hwc_post_data_t)); 898 memcpy(data, &pdev->bufs, sizeof(pdev->bufs)); 899 900 data->fence = -1; 901 pthread_mutex_init(&data->completion_lock, NULL); 902 pthread_cond_init(&data->completion, NULL); 903 904 if (pdev->bufs.fb_window == NO_FB_NEEDED) { 905 exynos5_post_callback(data, NULL); 906 } else { 907 908 struct hwc_callback_entry entry; 909 entry.callback = exynos5_post_callback; 910 entry.data = data; 911 912 queue = reinterpret_cast<hwc_callback_queue_t *>( 913 pdev->gralloc_module->queue); 914 lock = const_cast<pthread_mutex_t *>( 915 &pdev->gralloc_module->queue_lock); 916 917 pthread_mutex_lock(lock); 918 queue->push_front(entry); 919 pthread_mutex_unlock(lock); 920 921 EGLBoolean success = eglSwapBuffers((EGLDisplay)dpy, 922 (EGLSurface)sur); 923 if (!success) { 924 ALOGE("HWC_EGL_ERROR"); 925 if (list) { 926 pthread_mutex_lock(lock); 927 queue->removeAt(0); 928 pthread_mutex_unlock(lock); 929 free(data); 930 } 931 return HWC_EGL_ERROR; 932 } 933 } 934 } 935 936 937 pthread_mutex_lock(&data->completion_lock); 938 while (data->fence == -1) 939 pthread_cond_wait(&data->completion, &data->completion_lock); 940 pthread_mutex_unlock(&data->completion_lock); 941 942 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { 943 if (pdev->bufs.overlay_map[i] != -1) { 944 int dup_fd = dup(data->fence); 945 if (dup_fd < 0) 946 ALOGW("release fence dup failed: %s", strerror(errno)); 947 list->hwLayers[pdev->bufs.overlay_map[i]].releaseFenceFd = dup_fd; 948 } 949 } 950 close(data->fence); 951 free(data); 952 return 0; 953} 954 955static void exynos5_registerProcs(struct hwc_composer_device_1* dev, 956 hwc_procs_t const* procs) 957{ 958 struct exynos5_hwc_composer_device_1_t* pdev = 959 (struct exynos5_hwc_composer_device_1_t*)dev; 960 pdev->procs = const_cast<hwc_procs_t *>(procs); 961} 962 963static int exynos5_query(struct hwc_composer_device_1* dev, int what, int *value) 964{ 965 struct exynos5_hwc_composer_device_1_t *pdev = 966 (struct exynos5_hwc_composer_device_1_t *)dev; 967 968 switch (what) { 969 case HWC_BACKGROUND_LAYER_SUPPORTED: 970 // we support the background layer 971 value[0] = 1; 972 break; 973 case HWC_VSYNC_PERIOD: 974 // vsync period in nanosecond 975 value[0] = 1000000000.0 / pdev->gralloc_module->fps; 976 break; 977 default: 978 // unsupported query 979 return -EINVAL; 980 } 981 return 0; 982} 983 984static int exynos5_eventControl(struct hwc_composer_device_1 *dev, int event, 985 int enabled) 986{ 987 struct exynos5_hwc_composer_device_1_t *pdev = 988 (struct exynos5_hwc_composer_device_1_t *)dev; 989 990 switch (event) { 991 case HWC_EVENT_VSYNC: 992 __u32 val = !!enabled; 993 int err = ioctl(pdev->fd, S3CFB_SET_VSYNC_INT, &val); 994 if (err < 0) { 995 ALOGE("vsync ioctl failed"); 996 return -errno; 997 } 998 999 return 0; 1000 } 1001 1002 return -EINVAL; 1003} 1004 1005static void handle_hdmi_uevent(struct exynos5_hwc_composer_device_1_t *pdev, 1006 const char *buff, int len) 1007{ 1008 const char *s = buff; 1009 s += strlen(s) + 1; 1010 1011 while (*s) { 1012 if (!strncmp(s, "SWITCH_STATE=", strlen("SWITCH_STATE="))) 1013 pdev->hdmi_hpd = atoi(s + strlen("SWITCH_STATE=")) == 1; 1014 1015 s += strlen(s) + 1; 1016 if (s - buff >= len) 1017 break; 1018 } 1019 1020 ALOGV("HDMI HPD changed to %s", pdev->hdmi_hpd ? "enabled" : "disabled"); 1021 1022 if (pdev->procs && pdev->procs->invalidate) 1023 pdev->procs->invalidate(pdev->procs); 1024} 1025 1026static void handle_vsync_event(struct exynos5_hwc_composer_device_1_t *pdev) 1027{ 1028 if (!pdev->procs || !pdev->procs->vsync) 1029 return; 1030 1031 int err = lseek(pdev->vsync_fd, 0, SEEK_SET); 1032 if (err < 0) { 1033 ALOGE("error seeking to vsync timestamp: %s", strerror(errno)); 1034 return; 1035 } 1036 1037 char buf[4096]; 1038 err = read(pdev->vsync_fd, buf, sizeof(buf)); 1039 if (err < 0) { 1040 ALOGE("error reading vsync timestamp: %s", strerror(errno)); 1041 return; 1042 } 1043 buf[sizeof(buf) - 1] = '\0'; 1044 1045 errno = 0; 1046 uint64_t timestamp = strtoull(buf, NULL, 0); 1047 if (!errno) 1048 pdev->procs->vsync(pdev->procs, 0, timestamp); 1049} 1050 1051static void *hwc_vsync_thread(void *data) 1052{ 1053 struct exynos5_hwc_composer_device_1_t *pdev = 1054 (struct exynos5_hwc_composer_device_1_t *)data; 1055 char uevent_desc[4096]; 1056 memset(uevent_desc, 0, sizeof(uevent_desc)); 1057 1058 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 1059 1060 uevent_init(); 1061 1062 char temp[4096]; 1063 int err = read(pdev->vsync_fd, temp, sizeof(temp)); 1064 if (err < 0) { 1065 ALOGE("error reading vsync timestamp: %s", strerror(errno)); 1066 return NULL; 1067 } 1068 1069 struct pollfd fds[2]; 1070 fds[0].fd = pdev->vsync_fd; 1071 fds[0].events = POLLPRI; 1072 fds[1].fd = uevent_get_fd(); 1073 fds[1].events = POLLIN; 1074 1075 while (true) { 1076 int err = poll(fds, 2, -1); 1077 1078 if (err > 0) { 1079 if (fds[0].revents & POLLPRI) { 1080 handle_vsync_event(pdev); 1081 } 1082 else if (fds[1].revents & POLLIN) { 1083 int len = uevent_next_event(uevent_desc, 1084 sizeof(uevent_desc) - 2); 1085 1086 bool hdmi = !strcmp(uevent_desc, 1087 "change@/devices/virtual/switch/hdmi"); 1088 if (hdmi) 1089 handle_hdmi_uevent(pdev, uevent_desc, len); 1090 } 1091 } 1092 else if (err == -1) { 1093 if (errno == EINTR) 1094 break; 1095 ALOGE("error in vsync thread: %s", strerror(errno)); 1096 } 1097 } 1098 1099 return NULL; 1100} 1101 1102static int exynos5_blank(struct hwc_composer_device_1 *dev, int blank) 1103{ 1104 struct exynos5_hwc_composer_device_1_t *pdev = 1105 (struct exynos5_hwc_composer_device_1_t *)dev; 1106 1107 int fb_blank = blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK; 1108 int err = ioctl(pdev->fd, FBIOBLANK, fb_blank); 1109 if (err < 0) { 1110 ALOGE("%sblank ioctl failed", blank ? "" : "un"); 1111 return -errno; 1112 } 1113 1114 return 0; 1115} 1116 1117struct hwc_methods_1 exynos5_methods = { 1118 eventControl: exynos5_eventControl, 1119 blank: exynos5_blank, 1120}; 1121 1122static int exynos5_close(hw_device_t* device); 1123 1124static int exynos5_open(const struct hw_module_t *module, const char *name, 1125 struct hw_device_t **device) 1126{ 1127 int ret; 1128 int sw_fd; 1129 1130 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 1131 return -EINVAL; 1132 } 1133 1134 struct exynos5_hwc_composer_device_1_t *dev; 1135 dev = (struct exynos5_hwc_composer_device_1_t *)malloc(sizeof(*dev)); 1136 memset(dev, 0, sizeof(*dev)); 1137 1138 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 1139 (const struct hw_module_t **)&dev->gralloc_module)) { 1140 ALOGE("failed to get gralloc hw module"); 1141 ret = -EINVAL; 1142 goto err_get_module; 1143 } 1144 1145 if (gralloc_open((const hw_module_t *)dev->gralloc_module, 1146 &dev->alloc_device)) { 1147 ALOGE("failed to open gralloc"); 1148 ret = -EINVAL; 1149 goto err_get_module; 1150 } 1151 1152 dev->fd = open("/dev/graphics/fb0", O_RDWR); 1153 if (dev->fd < 0) { 1154 ALOGE("failed to open framebuffer"); 1155 ret = dev->fd; 1156 goto err_open_fb; 1157 } 1158 1159 dev->vsync_fd = open("/sys/devices/platform/exynos5-fb.1/vsync", O_RDONLY); 1160 if (dev->vsync_fd < 0) { 1161 ALOGE("failed to open vsync attribute"); 1162 ret = dev->vsync_fd; 1163 goto err_ioctl; 1164 } 1165 1166 sw_fd = open("/sys/class/switch/hdmi/state", O_RDONLY); 1167 if (sw_fd) { 1168 char val; 1169 if (read(sw_fd, &val, 1) == 1 && val == '1') 1170 dev->hdmi_hpd = true; 1171 } 1172 1173 dev->base.common.tag = HARDWARE_DEVICE_TAG; 1174 dev->base.common.version = HWC_DEVICE_API_VERSION_1_0; 1175 dev->base.common.module = const_cast<hw_module_t *>(module); 1176 dev->base.common.close = exynos5_close; 1177 1178 dev->base.prepare = exynos5_prepare; 1179 dev->base.set = exynos5_set; 1180 dev->base.registerProcs = exynos5_registerProcs; 1181 dev->base.query = exynos5_query; 1182 dev->base.methods = &exynos5_methods; 1183 1184 dev->bufs.pdev = dev; 1185 1186 *device = &dev->base.common; 1187 1188 ret = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev); 1189 if (ret) { 1190 ALOGE("failed to start vsync thread: %s", strerror(ret)); 1191 ret = -ret; 1192 goto err_vsync; 1193 } 1194 1195 return 0; 1196 1197err_vsync: 1198 close(dev->vsync_fd); 1199err_ioctl: 1200 close(dev->fd); 1201err_open_fb: 1202 gralloc_close(dev->alloc_device); 1203err_get_module: 1204 free(dev); 1205 return ret; 1206} 1207 1208static int exynos5_close(hw_device_t *device) 1209{ 1210 struct exynos5_hwc_composer_device_1_t *dev = 1211 (struct exynos5_hwc_composer_device_1_t *)device; 1212 pthread_kill(dev->vsync_thread, SIGTERM); 1213 pthread_join(dev->vsync_thread, NULL); 1214 for (size_t i = 0; i < NUM_GSC_UNITS; i++) { 1215 if (dev->gsc[i].gsc) 1216 exynos_gsc_destroy(dev->gsc[i].gsc); 1217 for (size_t j = 0; i < NUM_GSC_DST_BUFS; j++) 1218 if (dev->gsc[i].dst_buf[j]) 1219 dev->alloc_device->free(dev->alloc_device, dev->gsc[i].dst_buf[j]); 1220 } 1221 gralloc_close(dev->alloc_device); 1222 close(dev->vsync_fd); 1223 close(dev->fd); 1224 return 0; 1225} 1226 1227static struct hw_module_methods_t exynos5_hwc_module_methods = { 1228 open: exynos5_open, 1229}; 1230 1231hwc_module_t HAL_MODULE_INFO_SYM = { 1232 common: { 1233 tag: HARDWARE_MODULE_TAG, 1234 module_api_version: HWC_MODULE_API_VERSION_0_1, 1235 hal_api_version: HARDWARE_HAL_API_VERSION, 1236 id: HWC_HARDWARE_MODULE_ID, 1237 name: "Samsung exynos5 hwcomposer module", 1238 author: "Google", 1239 methods: &exynos5_hwc_module_methods, 1240 } 1241}; 1242