hwc.cpp revision 853a7f886465b773586c9ec4a8c6f07684ddf160
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 17#include <errno.h> 18#include <fcntl.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#include <cutils/log.h> 33#include <hardware/gralloc.h> 34#include <hardware/hardware.h> 35#include <hardware/hwcomposer.h> 36#include <hardware_legacy/uevent.h> 37#include <utils/Vector.h> 38 39#include <sync/sync.h> 40 41#include "ump.h" 42#include "ion.h" 43#include "gralloc_priv.h" 44 45struct hwc_callback_entry 46{ 47 void (*callback)(void *, private_handle_t *); 48 void *data; 49}; 50typedef android::Vector<struct hwc_callback_entry> hwc_callback_queue_t; 51 52const size_t NUM_HW_WINDOWS = 5; 53const size_t NO_FB_NEEDED = NUM_HW_WINDOWS + 1; 54 55struct exynos5_hwc_composer_device_t; 56 57struct exynos5_hwc_post_data_t { 58 exynos5_hwc_composer_device_t *pdev; 59 hwc_layer_t *overlays[NUM_HW_WINDOWS]; 60 size_t fb_window; 61}; 62 63struct exynos5_hwc_composer_device_t { 64 hwc_composer_device_t base; 65 66 int fd; 67 exynos5_hwc_post_data_t bufs; 68 69 const private_module_t *gralloc_module; 70 hwc_procs_t *procs; 71 pthread_t vsync_thread; 72}; 73 74static void dump_layer(hwc_layer_t const *l) 75{ 76 ALOGV("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, " 77 "{%d,%d,%d,%d}, {%d,%d,%d,%d}", 78 l->compositionType, l->flags, l->handle, l->transform, 79 l->blending, 80 l->sourceCrop.left, 81 l->sourceCrop.top, 82 l->sourceCrop.right, 83 l->sourceCrop.bottom, 84 l->displayFrame.left, 85 l->displayFrame.top, 86 l->displayFrame.right, 87 l->displayFrame.bottom); 88} 89 90static void dump_handle(private_handle_t *h) 91{ 92 ALOGV("\t\tformat = %d, width = %u, height = %u, bpp = %u, stride = %u", 93 h->format, h->width, h->height, h->bpp, h->stride); 94} 95 96static void dump_config(s3c_fb_win_config &c) 97{ 98 ALOGV("\tstate = %u", c.state); 99 if (c.state == c.S3C_FB_WIN_STATE_BUFFER) { 100 ALOGV("\t\tfd = %d, offset = %u, stride = %u, " 101 "x = %d, y = %d, w = %u, h = %u, " 102 "format = %u", 103 c.fd, c.offset, c.stride, 104 c.x, c.y, c.w, c.h, 105 c.format); 106 } 107 else if (c.state == c.S3C_FB_WIN_STATE_COLOR) { 108 ALOGV("\t\tcolor = %u", c.color); 109 } 110} 111 112inline int WIDTH(const hwc_rect &rect) { return rect.right - rect.left; } 113inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; } 114 115static bool is_scaled(const hwc_layer_t &layer) 116{ 117 return WIDTH(layer.displayFrame) != WIDTH(layer.sourceCrop) || 118 HEIGHT(layer.displayFrame) != HEIGHT(layer.sourceCrop); 119} 120 121static enum s3c_fb_pixel_format exynos5_format_to_s3c_format(int format) 122{ 123 switch (format) { 124 case HAL_PIXEL_FORMAT_RGBA_8888: 125 return S3C_FB_PIXEL_FORMAT_RGBA_8888; 126 case HAL_PIXEL_FORMAT_RGBX_8888: 127 return S3C_FB_PIXEL_FORMAT_RGBX_8888; 128 case HAL_PIXEL_FORMAT_RGBA_5551: 129 return S3C_FB_PIXEL_FORMAT_RGBA_5551; 130 case HAL_PIXEL_FORMAT_RGBA_4444: 131 return S3C_FB_PIXEL_FORMAT_RGBA_4444; 132 133 default: 134 return S3C_FB_PIXEL_FORMAT_MAX; 135 } 136} 137 138static bool exynos5_format_is_supported(int format) 139{ 140 return exynos5_format_to_s3c_format(format) < S3C_FB_PIXEL_FORMAT_MAX; 141} 142 143static bool exynos5_format_is_supported_by_gscaler(int format) 144{ 145 switch(format) { 146 case HAL_PIXEL_FORMAT_RGBA_8888: 147 case HAL_PIXEL_FORMAT_RGBX_8888: 148 case HAL_PIXEL_FORMAT_RGB_565: 149 case HAL_PIXEL_FORMAT_YV12: 150 return true; 151 152 default: 153 return false; 154 } 155} 156 157static uint8_t exynos5_format_to_bpp(int format) 158{ 159 switch (format) { 160 case HAL_PIXEL_FORMAT_RGBA_8888: 161 case HAL_PIXEL_FORMAT_RGBX_8888: 162 return 32; 163 164 case HAL_PIXEL_FORMAT_RGBA_5551: 165 case HAL_PIXEL_FORMAT_RGBA_4444: 166 return 16; 167 168 default: 169 ALOGW("unrecognized pixel format %u", format); 170 return 0; 171 } 172} 173 174bool exynos5_supports_overlay(hwc_layer_t &layer, size_t i) { 175/* private_handle_t *handle = private_handle_t::dynamicCast(layer.handle); 176 177 if (!handle) { 178 ALOGW("\tlayer %u: handle is NULL", i); 179 return false; 180 } 181 if (!exynos5_format_is_supported(handle->format)) { 182 ALOGW("\tlayer %u: pixel format %u not supported", i, 183 handle->format); 184 return false; 185 } 186 if (is_scaled(layer)) { 187 // TODO: this can be made into an overlay if a gscaler 188 // unit is available. Also some size and pixel format 189 // limitations (see 46-3 of datasheet) 190 ALOGW("\tlayer %u: scaling and transforming not supported", i); 191 return false; 192 } 193 if (layer.blending != HWC_BLENDING_NONE) { 194 // TODO: support this 195 ALOGW("\tlayer %u: blending not supported", i); 196 return false; 197 } 198 199 return true;*/ 200 201 return false; 202 // for debugging purposes, everything goes into a framebuffer 203} 204 205static int exynos5_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) 206{ 207 if (!list) 208 return 0; 209 210 ALOGV("preparing %u layers", list->numHwLayers); 211 212 exynos5_hwc_composer_device_t *pdev = 213 (exynos5_hwc_composer_device_t *)dev; 214 memset(pdev->bufs.overlays, 0, sizeof(pdev->bufs.overlays)); 215 216 bool fb_needed = false; 217 size_t first_fb = 0, last_fb; 218 219 // find unsupported overlays 220 for (size_t i = 0; i < list->numHwLayers; i++) { 221 hwc_layer_t &layer = list->hwLayers[i]; 222 223 if (layer.compositionType == HWC_BACKGROUND) { 224 ALOGV("\tlayer %u: background supported", i); 225 continue; 226 } 227 228 if (exynos5_supports_overlay(list->hwLayers[i], i)) { 229 ALOGV("\tlayer %u: overlay supported", i); 230 layer.compositionType = HWC_OVERLAY; 231 continue; 232 } 233 234 if (!fb_needed) { 235 first_fb = i; 236 fb_needed = true; 237 } 238 last_fb = i; 239 layer.compositionType = HWC_FRAMEBUFFER; 240 } 241 242 // can't composite overlays sandwiched between framebuffers 243 if (fb_needed) 244 for (size_t i = first_fb; i < last_fb; i++) 245 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; 246 247 // if we need a framebuffer but can't fit it in, reserve the last 248 // window as a framebuffer 249 if ((fb_needed && first_fb >= NUM_HW_WINDOWS) || 250 (!fb_needed && list->numHwLayers > NUM_HW_WINDOWS)) { 251 fb_needed = true; 252 first_fb = NUM_HW_WINDOWS - 1; 253 for (size_t i = first_fb; i < list->numHwLayers; i++) 254 list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; 255 } 256 257 unsigned int nextWindow = 0; 258 259 // assign as many overlays as possible to windows 260 for (size_t i = 0; i < list->numHwLayers; i++) { 261 hwc_layer_t &layer = list->hwLayers[i]; 262 263 if (nextWindow == NUM_HW_WINDOWS) { 264 ALOGV("not enough windows to assign layer %u", i); 265 layer.compositionType = HWC_FRAMEBUFFER; 266 continue; 267 } 268 269 if (fb_needed && i == first_fb) { 270 ALOGV("assigning framebuffer to window %u\n", 271 nextWindow); 272 nextWindow++; 273 continue; 274 } 275 276 if (layer.compositionType != HWC_FRAMEBUFFER) { 277 ALOGV("assigning layer %u to window %u", i, nextWindow); 278 pdev->bufs.overlays[nextWindow] = &layer; 279 nextWindow++; 280 } 281 } 282 283 if (fb_needed) 284 pdev->bufs.fb_window = first_fb; 285 else 286 pdev->bufs.fb_window = NO_FB_NEEDED; 287 288 for (size_t i = 0; i < list->numHwLayers; i++) { 289 dump_layer(&list->hwLayers[i]); 290 if(list->hwLayers[i].handle) 291 dump_handle(private_handle_t::dynamicCast( 292 list->hwLayers[i].handle)); 293 } 294 295 return 0; 296} 297 298static void exynos5_config_handle(private_handle_t *handle, 299 hwc_rect_t &sourceCrop, hwc_rect_t &displayFrame, 300 s3c_fb_win_config &cfg) { 301 cfg.state = cfg.S3C_FB_WIN_STATE_BUFFER; 302 cfg.fd = handle->fd; 303 cfg.x = displayFrame.left; 304 cfg.y = displayFrame.top; 305 cfg.w = WIDTH(displayFrame); 306 cfg.h = HEIGHT(displayFrame); 307 cfg.format = exynos5_format_to_s3c_format(handle->format); 308 uint8_t bpp = exynos5_format_to_bpp(handle->format); 309 cfg.offset = (sourceCrop.top * handle->stride + sourceCrop.left) * 310 bpp / 8; 311 cfg.stride = handle->stride * bpp / 8; 312} 313 314static void exynos5_config_overlay(hwc_layer_t *layer, s3c_fb_win_config &cfg, 315 const private_module_t *gralloc_module) 316{ 317 if (!layer) 318 return; 319 320 if (layer->compositionType == HWC_BACKGROUND) { 321 hwc_color_t color = layer->backgroundColor; 322 cfg.state = cfg.S3C_FB_WIN_STATE_COLOR; 323 cfg.color = (color.r << 16) | (color.g << 8) | color.b; 324 cfg.x = 0; 325 cfg.y = 0; 326 cfg.w = gralloc_module->xres; 327 cfg.h = gralloc_module->yres; 328 return; 329 } 330 331 private_handle_t *handle = private_handle_t::dynamicCast(layer->handle); 332 exynos5_config_handle(handle, layer->sourceCrop, layer->displayFrame, 333 cfg); 334} 335 336static void exynos5_post_callback(void *data, private_handle_t *fb) 337{ 338 exynos5_hwc_post_data_t *pdata = 339 (exynos5_hwc_post_data_t *)data; 340 341 struct s3c_fb_win_config_data win_data; 342 struct s3c_fb_win_config *config = win_data.config; 343 memset(config, 0, sizeof(win_data.config)); 344 for (size_t i = 0; i < NUM_HW_WINDOWS; i++) { 345 if (i == pdata->fb_window) { 346 hwc_rect_t rect = { 0, 0, fb->width, fb->height }; 347 exynos5_config_handle(fb, rect, rect, config[i]); 348 } else 349 exynos5_config_overlay(pdata->overlays[i], config[i], 350 pdata->pdev->gralloc_module); 351 dump_config(config[i]); 352 } 353 354 int ret = ioctl(pdata->pdev->fd, S3CFB_WIN_CONFIG, &win_data); 355 if (ret < 0) 356 ALOGE("ioctl S3CFB_WIN_CONFIG failed: %d", errno); 357 358 sync_wait(win_data.fence, 1000); 359 close(win_data.fence); 360 free(pdata); 361} 362 363static int exynos5_set(struct hwc_composer_device *dev, hwc_display_t dpy, 364 hwc_surface_t sur, hwc_layer_list_t* list) 365{ 366 exynos5_hwc_composer_device_t *pdev = 367 (exynos5_hwc_composer_device_t *)dev; 368 369 if (!dpy || !sur) 370 return 0; 371 372 hwc_callback_queue_t *queue = NULL; 373 pthread_mutex_t *lock = NULL; 374 exynos5_hwc_post_data_t *data = NULL; 375 376 if (list) { 377 data = (exynos5_hwc_post_data_t *) 378 malloc(sizeof(exynos5_hwc_post_data_t)); 379 memcpy(data, &pdev->bufs, sizeof(pdev->bufs)); 380 381 if (pdev->bufs.fb_window == NO_FB_NEEDED) { 382 exynos5_post_callback(data, NULL); 383 return 0; 384 } 385 386 struct hwc_callback_entry entry; 387 entry.callback = exynos5_post_callback; 388 entry.data = data; 389 390 queue = reinterpret_cast<hwc_callback_queue_t *>( 391 pdev->gralloc_module->queue); 392 lock = const_cast<pthread_mutex_t *>( 393 &pdev->gralloc_module->queue_lock); 394 395 pthread_mutex_lock(lock); 396 queue->push_front(entry); 397 pthread_mutex_unlock(lock); 398 } 399 400 EGLBoolean success = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); 401 if (!success) { 402 ALOGE("HWC_EGL_ERROR"); 403 if (list) { 404 pthread_mutex_lock(lock); 405 queue->removeAt(0); 406 pthread_mutex_unlock(lock); 407 free(data); 408 } 409 return HWC_EGL_ERROR; 410 } 411 412 return 0; 413} 414 415static void exynos5_registerProcs(struct hwc_composer_device* dev, 416 hwc_procs_t const* procs) 417{ 418 struct exynos5_hwc_composer_device_t* pdev = 419 (struct exynos5_hwc_composer_device_t*)dev; 420 pdev->procs = const_cast<hwc_procs_t *>(procs); 421} 422 423static int exynos5_query(struct hwc_composer_device* dev, int what, int *value) 424{ 425 struct exynos5_hwc_composer_device_t *pdev = 426 (struct exynos5_hwc_composer_device_t *)dev; 427 428 switch (what) { 429 case HWC_BACKGROUND_LAYER_SUPPORTED: 430 // we support the background layer 431 value[0] = 1; 432 break; 433 case HWC_VSYNC_PERIOD: 434 // vsync period in nanosecond 435 value[0] = 1000000000.0 / pdev->gralloc_module->fps; 436 break; 437 default: 438 // unsupported query 439 return -EINVAL; 440 } 441 return 0; 442} 443 444static int exynos5_eventControl(struct hwc_composer_device *dev, int event, 445 int enabled) 446{ 447 struct exynos5_hwc_composer_device_t *pdev = 448 (struct exynos5_hwc_composer_device_t *)dev; 449 450 switch (event) { 451 case HWC_EVENT_VSYNC: 452 __u32 val = !!enabled; 453 int err = ioctl(pdev->fd, S3CFB_SET_VSYNC_INT, &val); 454 if (err < 0) { 455 ALOGE("vsync ioctl failed"); 456 return -errno; 457 } 458 459 return 0; 460 } 461 462 return -EINVAL; 463} 464 465static void handle_vsync_uevent(struct exynos5_hwc_composer_device_t *pdev, 466 const char *buff, int len) 467{ 468 uint64_t timestamp = 0; 469 const char *s = buff; 470 471 if (!pdev->procs || !pdev->procs->vsync) 472 return; 473 474 s += strlen(s) + 1; 475 476 while (*s) { 477 if (!strncmp(s, "VSYNC=", strlen("VSYNC="))) 478 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0); 479 480 s += strlen(s) + 1; 481 if (s - buff >= len) 482 break; 483 } 484 485 pdev->procs->vsync(pdev->procs, 0, timestamp); 486} 487 488static void *hwc_vsync_thread(void *data) 489{ 490 struct exynos5_hwc_composer_device_t *pdev = 491 (struct exynos5_hwc_composer_device_t *)data; 492 char uevent_desc[4096]; 493 memset(uevent_desc, 0, sizeof(uevent_desc)); 494 495 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); 496 497 uevent_init(); 498 while (true) { 499 int len = uevent_next_event(uevent_desc, 500 sizeof(uevent_desc) - 2); 501 502 bool vsync = !strcmp(uevent_desc, 503 "change@/devices/platform/exynos5-fb.1"); 504 if (vsync) 505 handle_vsync_uevent(pdev, uevent_desc, len); 506 } 507 508 return NULL; 509} 510 511struct hwc_methods exynos5_methods = { 512 eventControl: exynos5_eventControl, 513}; 514 515static int exynos5_close(hw_device_t* device); 516 517static int exynos5_open(const struct hw_module_t *module, const char *name, 518 struct hw_device_t **device) 519{ 520 int ret; 521 522 if (strcmp(name, HWC_HARDWARE_COMPOSER)) { 523 return -EINVAL; 524 } 525 526 struct exynos5_hwc_composer_device_t *dev; 527 dev = (struct exynos5_hwc_composer_device_t *)malloc(sizeof(*dev)); 528 memset(dev, 0, sizeof(*dev)); 529 530 if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, 531 (const struct hw_module_t **)&dev->gralloc_module)) { 532 ALOGE("failed to get gralloc hw module"); 533 ret = -EINVAL; 534 goto err_get_module; 535 } 536 537 dev->fd = open("/dev/graphics/fb0", O_RDWR); 538 if (dev->fd < 0) { 539 ALOGE("failed to open framebuffer"); 540 ret = dev->fd; 541 goto err_get_module; 542 } 543 544 dev->base.common.tag = HARDWARE_DEVICE_TAG; 545 dev->base.common.version = HWC_DEVICE_API_VERSION_0_3; 546 dev->base.common.module = const_cast<hw_module_t *>(module); 547 dev->base.common.close = exynos5_close; 548 549 dev->base.prepare = exynos5_prepare; 550 dev->base.set = exynos5_set; 551 dev->base.registerProcs = exynos5_registerProcs; 552 dev->base.query = exynos5_query; 553 dev->base.methods = &exynos5_methods; 554 555 dev->bufs.pdev = dev; 556 557 *device = &dev->base.common; 558 559 ret = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev); 560 if (ret) { 561 ALOGE("failed to start vsync thread: %s", strerror(ret)); 562 ret = -ret; 563 goto err_ioctl; 564 } 565 566 return 0; 567 568err_ioctl: 569 close(dev->fd); 570err_get_module: 571 free(dev); 572 return ret; 573} 574 575static int exynos5_close(hw_device_t *device) 576{ 577 struct exynos5_hwc_composer_device_t *dev = 578 (struct exynos5_hwc_composer_device_t *)device; 579 close(dev->fd); 580 return 0; 581} 582 583static struct hw_module_methods_t exynos5_hwc_module_methods = { 584 open: exynos5_open, 585}; 586 587hwc_module_t HAL_MODULE_INFO_SYM = { 588 common: { 589 tag: HARDWARE_MODULE_TAG, 590 module_api_version: HWC_MODULE_API_VERSION_0_1, 591 hal_api_version: HARDWARE_HAL_API_VERSION, 592 id: HWC_HARDWARE_MODULE_ID, 593 name: "Samsung exynos5 hwcomposer module", 594 author: "Google", 595 methods: &exynos5_hwc_module_methods, 596 } 597}; 598