diff options
author | Erik Gilling <konkers@android.com> | 2011-10-12 16:52:34 -0500 |
---|---|---|
committer | Erik Gilling <konkers@android.com> | 2011-10-12 16:21:59 -0700 |
commit | 13644ed3bd1e45d1b1f1c27e678db622f595c768 (patch) | |
tree | 983e8cca64e9995ddb22acd46e7bc241e64b904b /hwc/hwc.c | |
parent | b9af092e499f1c2a65d38f21acc77b4f81a18d8d (diff) | |
download | hardware_ti_omap4-13644ed3bd1e45d1b1f1c27e678db622f595c768.zip hardware_ti_omap4-13644ed3bd1e45d1b1f1c27e678db622f595c768.tar.gz hardware_ti_omap4-13644ed3bd1e45d1b1f1c27e678db622f595c768.tar.bz2 |
hwc: fallback on GL after idle for power savings
If no frame has been posted for 250ms, rerender using GL to take load off
the overlay engine.
Change-Id: I1790f7b7b43fd0d60b7392b9aec01339234aa915
Signed-off-by: Erik Gilling <konkers@android.com>
Diffstat (limited to 'hwc/hwc.c')
-rw-r--r-- | hwc/hwc.c | 75 |
1 files changed, 70 insertions, 5 deletions
@@ -19,6 +19,7 @@ #include <stdlib.h> #include <stdarg.h> #include <fcntl.h> +#include <poll.h> #include <sys/ioctl.h> #include <linux/fb.h> @@ -111,6 +112,7 @@ struct omap4_hwc_device { int dsscomp_fd; int fb_fd; int hdmi_fb_fd; + int pipe_fds[2]; IMG_framebuffer_device_public_t *fb_dev; struct dsscomp_setup_dispc_data dsscomp_data; @@ -129,6 +131,9 @@ struct omap4_hwc_device { int flags_rgb_order; int flags_nv12_only; + int idle; + + int force_sgx; }; typedef struct omap4_hwc_device omap4_hwc_device_t; @@ -934,7 +939,7 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* } /* phase 3 logic */ - if (can_dss_render_all(hwc_dev, &num)) { + if (!hwc_dev->force_sgx && can_dss_render_all(hwc_dev, &num)) { /* All layers can be handled by the DSS -- don't use SGX for composition */ hwc_dev->use_sgx = 0; hwc_dev->swap_rb = num.BGR != 0; @@ -970,7 +975,8 @@ static int omap4_hwc_prepare(struct hwc_composer_device *dev, hwc_layer_list_t* hwc_layer_t *layer = &list->hwLayers[i]; IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - if (dsscomp->num_ovls < num.max_hw_overlays && + if (!hwc_dev->force_sgx && + dsscomp->num_ovls < num.max_hw_overlays && can_dss_render_layer(hwc_dev, layer) && mem_used + mem1d(handle) < MAX_TILER_SLOT && /* can't have a transparent overlay in the middle of the framebuffer stack */ @@ -1266,6 +1272,11 @@ static int omap4_hwc_set(struct hwc_composer_device *dev, hwc_display_t dpy, //dump_dsscomp(dsscomp); + // signal the event thread that a post has happened + write(hwc_dev->pipe_fds[1], "s", 1); + if (hwc_dev->force_sgx > 0) + hwc_dev->force_sgx--; + err = hwc_dev->fb_dev->Post2((framebuffer_device_t *)hwc_dev->fb_dev, hwc_dev->buffers, hwc_dev->post2_layers, @@ -1317,6 +1328,7 @@ static void omap4_hwc_dump(struct hwc_composer_device *dev, char *buff, int buff int i; len = dump_printf(buff, buff_len, len, "omap4_hwc %d:\n", dsscomp->num_ovls); + len = dump_printf(buff, buff_len, len, " idle timeout: %dms\n", hwc_dev->idle); for (i = 0; i < dsscomp->num_ovls; i++) { struct dss2_ovl_cfg *cfg = &dsscomp->ovls[i].cfg; @@ -1455,14 +1467,59 @@ static void *omap4_hwc_hdmi_thread(void *data) { omap4_hwc_device_t *hwc_dev = data; static char uevent_desc[4096]; + struct pollfd fds[2]; + int prev_force_sgx = 0; + int timeout; + int err; + uevent_init(); + fds[0].fd = uevent_get_fd(); + fds[0].events = POLLIN; + fds[1].fd = hwc_dev->pipe_fds[0]; + fds[1].events = POLLIN; + + timeout = hwc_dev->idle ? hwc_dev->idle : -1; + memset(uevent_desc, 0, sizeof(uevent_desc)); do { - /* keep last 2 zeroes to ensure double 0 termination */ - uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); - handle_uevents(hwc_dev, uevent_desc); + err = poll(fds, hwc_dev->idle ? 2 : 1, timeout); + + if (err == 0) { + if (hwc_dev->idle) { + pthread_mutex_lock(&hwc_dev->lock); + prev_force_sgx = hwc_dev->force_sgx; + hwc_dev->force_sgx = 2; + pthread_mutex_unlock(&hwc_dev->lock); + + if (!prev_force_sgx && hwc_dev->procs && hwc_dev->procs->invalidate) { + hwc_dev->procs->invalidate(hwc_dev->procs); + timeout = -1; + } + + continue; + } + } + + if (err == -1) { + if (errno != EINTR) + LOGE("event error: %m"); + continue; + } + + if (hwc_dev->idle && fds[1].revents & POLLIN) { + char c; + read(hwc_dev->pipe_fds[0], &c, 1); + if (!hwc_dev->force_sgx) + timeout = hwc_dev->idle ? hwc_dev->idle : -1; + } + + if (fds[0].revents & POLLIN) { + /* keep last 2 zeroes to ensure double 0 termination */ + uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2); + handle_uevents(hwc_dev, uevent_desc); + } } while (1); return NULL; @@ -1550,6 +1607,12 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, goto done; } + if (pipe(hwc_dev->pipe_fds) == -1) { + LOGE("failed to event pipe (%d): %m", errno); + err = -errno; + goto done; + } + if (pthread_mutex_init(&hwc_dev->lock, NULL)) { LOGE("failed to create mutex (%d): %m", errno); err = -errno; @@ -1570,6 +1633,8 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, hwc_dev->flags_rgb_order = atoi(value); property_get("debug.hwc.nv12_only", value, "0"); hwc_dev->flags_nv12_only = atoi(value); + property_get("debug.hwc.idle", value, "250"); + hwc_dev->idle = atoi(value); /* get the board specific clone properties */ /* 0:0:1280:720 */ |