diff options
author | Michael Brehm <djp952@gmail.com> | 2012-09-15 02:03:39 -0500 |
---|---|---|
committer | Chirayu Desai <chirayudesai1@gmail.com> | 2012-09-16 11:36:05 +0530 |
commit | 3c938a7e18ab2e06b3d925fdc99e157ad125f6bb (patch) | |
tree | ac9d4a10ed930d51ce515b99e95625a8769d8a6d /exynos3 | |
parent | 317dcfa0f0ed518a7bb5577ea36559713c3f6698 (diff) | |
download | hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.zip hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.tar.gz hardware_samsung-3c938a7e18ab2e06b3d925fdc99e157ad125f6bb.tar.bz2 |
exynos3: Implement custom VSYNC IOCTL
* Replace crespo-based VSYNC uevent mechanism in hwcomposer
with a custom IOCTL mechanism instead (required kernel
modifications.
* The VSYNC uevents were spamming the Android UEventObserver
and causing about 7% of constant CPU load
c86856efabfa0b2981ceb47898dc5873a4998707
Improve custom VSYNC handler in hwcomposer
* only poll when necessary
* solves suspend/resume instability?
45bf1dae7fa9057a3415151f7559e7bd2a162ead
Change-Id: Icdb5c60059e71688479d390b7b3a1f09a0315a5f
Diffstat (limited to 'exynos3')
-rwxr-xr-x | exynos3/s5pc110/include/sec_lcd.h | 1 | ||||
-rw-r--r-- | exynos3/s5pc110/libhwcomposer/Android.mk | 4 | ||||
-rw-r--r-- | exynos3/s5pc110/libhwcomposer/SecHWC.cpp | 52 |
3 files changed, 57 insertions, 0 deletions
diff --git a/exynos3/s5pc110/include/sec_lcd.h b/exynos3/s5pc110/include/sec_lcd.h index 6a3a34a..82ef42f 100755 --- a/exynos3/s5pc110/include/sec_lcd.h +++ b/exynos3/s5pc110/include/sec_lcd.h @@ -34,6 +34,7 @@ struct secfb_user_window { #define FBIO_WAITFORVSYNC _IO ('F', 32) #define SECFB_WIN_POSITION _IOW ('F', 203, struct secfb_user_window) #define S3CFB_SET_VSYNC_INT _IOW ('F', 206, uint32_t) +#define S3CFB_WAIT_FOR_VSYNC _IOR ('F', 311, uint64_t) #define DEFAULT_LCD_WIDTH (480) #define DEFAULT_LCD_HEIGHT (800) diff --git a/exynos3/s5pc110/libhwcomposer/Android.mk b/exynos3/s5pc110/libhwcomposer/Android.mk index defda3e..a058145 100644 --- a/exynos3/s5pc110/libhwcomposer/Android.mk +++ b/exynos3/s5pc110/libhwcomposer/Android.mk @@ -27,6 +27,10 @@ LOCAL_C_INCLUDES := \ LOCAL_SRC_FILES := SecHWCUtils.cpp SecHWC.cpp +ifeq ($(BOARD_CUSTOM_VSYNC_IOCTL),true) + LOCAL_CFLAGS += -DVSYNC_IOCTL +endif + LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM) LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY) diff --git a/exynos3/s5pc110/libhwcomposer/SecHWC.cpp b/exynos3/s5pc110/libhwcomposer/SecHWC.cpp index dda1108..31d25f4 100644 --- a/exynos3/s5pc110/libhwcomposer/SecHWC.cpp +++ b/exynos3/s5pc110/libhwcomposer/SecHWC.cpp @@ -453,6 +453,17 @@ static int hwc_query(struct hwc_composer_device* dev, return 0; } +#ifdef VSYNC_IOCTL +// Linux version of a manual reset event to control when +// and when not to ask the video card for a VSYNC. This +// stops the worker thread from asking for a VSYNC when +// there is nothing useful to do with it and more closely +// mimicks the original uevent mechanism +int vsync_enable = 0; +pthread_mutex_t vsync_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t vsync_condition = PTHREAD_COND_INITIALIZER; +#endif + static int hwc_eventControl(struct hwc_composer_device* dev, int event, int enabled) { @@ -465,6 +476,18 @@ static int hwc_eventControl(struct hwc_composer_device* dev, if (err < 0) return -errno; +#if VSYNC_IOCTL + // Enable or disable the ability for the worker thread + // to ask for VSYNC events from the video driver + pthread_mutex_lock(&vsync_mutex); + if(enabled) { + vsync_enable = 1; + pthread_cond_broadcast(&vsync_condition); + } + else vsync_enable = 0; + pthread_mutex_unlock(&vsync_mutex); +#endif + return 0; } @@ -496,18 +519,47 @@ void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len) static void *hwc_vsync_thread(void *data) { hwc_context_t *ctx = (hwc_context_t *)(data); +#ifdef VSYNC_IOCTL + uint64_t timestamp = 0; +#else char uevent_desc[4096]; memset(uevent_desc, 0, sizeof(uevent_desc)); +#endif setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); +#ifndef VSYNC_IOCTL uevent_init(); +#endif while(true) { +#ifdef VSYNC_IOCTL + // Only continue if hwc_eventControl is enabled, otherwise + // just sit here and wait until it is. This stops the code + // from constantly looking for the VSYNC event with the screen + // turned off. + pthread_mutex_lock(&vsync_mutex); + if(!vsync_enable) pthread_cond_wait(&vsync_condition, &vsync_mutex); + pthread_mutex_unlock(&vsync_mutex); + + timestamp = 0; // Reset the timestamp value + + // S3CFB_WAIT_FOR_VSYNC is a custom IOCTL I added to wait for + // the VSYNC interrupt, and then return the timestamp that was + // originally being communicated via a uevent. The uevent was + // spamming the UEventObserver and events/0 process with more + // information than this device could really deal with every 18ms + int res = ioctl(ctx->global_lcd_win.fd, S3CFB_WAIT_FOR_VSYNC, ×tamp); + if(res > 0) { + if(!ctx->procs || !ctx->procs->vsync) continue; + ctx->procs->vsync(ctx->procs, 0, timestamp); + } +#else int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); bool vsync = !strcmp(uevent_desc, "change@/devices/platform/s3cfb"); if(vsync) handle_vsync_uevent(ctx, uevent_desc, len); +#endif } return NULL; |