From 304f32fa988815c2780c709235724e94651d02ba Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Fri, 7 Nov 2014 10:14:05 -0600 Subject: Fix up old libminui to compile Implement some needed updates to libminui to make it compile for healthd. Note that res_create_multi_display_surface is not fully implemented so healthd may still have issues with displaying some graphics. Will update later when we are able to test these changes. Change-Id: Ic1095a998f5dfe7e36a08384c86da28e0524a03f --- minui/Android.mk | 6 ++- minui/events.c | 86 ++++++++++++++++++++--------- minui/graphics.c | 8 +++ minui/minui.h | 18 ++++++- minui/resources.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 29 deletions(-) (limited to 'minui') diff --git a/minui/Android.mk b/minui/Android.mk index 54eb06166..061bee67e 100644 --- a/minui/Android.mk +++ b/minui/Android.mk @@ -9,8 +9,9 @@ else endif LOCAL_C_INCLUDES +=\ - external/libpng\ - external/zlib + external/libpng \ + external/zlib \ + system/core/include/pixelflinger ifeq ($(TW_TARGET_USES_QCOM_BSP), true) LOCAL_CFLAGS += -DMSM_BSP @@ -25,6 +26,7 @@ else endif LOCAL_STATIC_LIBRARY := libpng +LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_static LOCAL_MODULE := libminui # This used to compare against values in double-quotes (which are just diff --git a/minui/events.c b/minui/events.c index 2918afaa8..df7dad448 100644 --- a/minui/events.c +++ b/minui/events.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include @@ -34,11 +34,15 @@ ((array)[(bit)/BITS_PER_LONG] & (1 << ((bit) % BITS_PER_LONG))) struct fd_info { + int fd; ev_callback cb; void *data; }; -static struct pollfd ev_fds[MAX_DEVICES + MAX_MISC_FDS]; +static int epollfd; +static struct epoll_event polledevents[MAX_DEVICES + MAX_MISC_FDS]; +static int npolledevents; + static struct fd_info ev_fdinfo[MAX_DEVICES + MAX_MISC_FDS]; static unsigned ev_count = 0; @@ -50,6 +54,12 @@ int ev_init(ev_callback input_cb, void *data) DIR *dir; struct dirent *de; int fd; + struct epoll_event ev; + bool epollctlfail = false; + + epollfd = epoll_create(MAX_DEVICES + MAX_MISC_FDS); + if (epollfd == -1) + return -1; dir = opendir("/dev/input"); if(dir != 0) { @@ -74,8 +84,15 @@ int ev_init(ev_callback input_cb, void *data) continue; } - ev_fds[ev_count].fd = fd; - ev_fds[ev_count].events = POLLIN; + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr = (void *)&ev_fdinfo[ev_count]; + if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev)) { + close(fd); + epollctlfail = true; + continue; + } + + ev_fdinfo[ev_count].fd = fd; ev_fdinfo[ev_count].cb = input_cb; ev_fdinfo[ev_count].data = data; ev_count++; @@ -84,59 +101,78 @@ int ev_init(ev_callback input_cb, void *data) } } + if (epollctlfail && !ev_count) { + close(epollfd); + epollfd = -1; + return -1; + } + return 0; } int ev_add_fd(int fd, ev_callback cb, void *data) { + struct epoll_event ev; + int ret; + if (ev_misc_count == MAX_MISC_FDS || cb == NULL) return -1; - ev_fds[ev_count].fd = fd; - ev_fds[ev_count].events = POLLIN; - ev_fdinfo[ev_count].cb = cb; - ev_fdinfo[ev_count].data = data; - ev_count++; - ev_misc_count++; - return 0; + ev.events = EPOLLIN | EPOLLWAKEUP; + ev.data.ptr = (void *)&ev_fdinfo[ev_count]; + ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev); + if (!ret) { + ev_fdinfo[ev_count].fd = fd; + ev_fdinfo[ev_count].cb = cb; + ev_fdinfo[ev_count].data = data; + ev_count++; + ev_misc_count++; + } + + return ret; +} + +int ev_get_epollfd(void) +{ + return epollfd; } void ev_exit(void) { while (ev_count > 0) { - close(ev_fds[--ev_count].fd); + close(ev_fdinfo[--ev_count].fd); } ev_misc_count = 0; ev_dev_count = 0; + close(epollfd); } int ev_wait(int timeout) { - int r; - - r = poll(ev_fds, ev_count, timeout); - if (r <= 0) + npolledevents = epoll_wait(epollfd, polledevents, ev_count, timeout); + if (npolledevents <= 0) return -1; return 0; } void ev_dispatch(void) { - unsigned n; + int n; int ret; - for (n = 0; n < ev_count; n++) { - ev_callback cb = ev_fdinfo[n].cb; - if (cb && (ev_fds[n].revents & ev_fds[n].events)) - cb(ev_fds[n].fd, ev_fds[n].revents, ev_fdinfo[n].data); + for (n = 0; n < npolledevents; n++) { + struct fd_info *fdi = polledevents[n].data.ptr; + ev_callback cb = fdi->cb; + if (cb) + cb(fdi->fd, polledevents[n].events, fdi->data); } } -int ev_get_input(int fd, short revents, struct input_event *ev) +int ev_get_input(int fd, uint32_t epevents, struct input_event *ev) { int r; - if (revents & POLLIN) { + if (epevents & EPOLLIN) { r = read(fd, ev, sizeof(*ev)); if (r == sizeof(*ev)) return 0; @@ -157,11 +193,11 @@ int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data) memset(key_bits, 0, sizeof(key_bits)); memset(ev_bits, 0, sizeof(ev_bits)); - ret = ioctl(ev_fds[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); + ret = ioctl(ev_fdinfo[i].fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); if (ret < 0 || !test_bit(EV_KEY, ev_bits)) continue; - ret = ioctl(ev_fds[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits); + ret = ioctl(ev_fdinfo[i].fd, EVIOCGKEY(sizeof(key_bits)), key_bits); if (ret < 0) continue; diff --git a/minui/graphics.c b/minui/graphics.c index 8f951756d..948a07c0f 100644 --- a/minui/graphics.c +++ b/minui/graphics.c @@ -495,3 +495,11 @@ void gr_get_memory_surface(gr_surface surface) { get_memory_surface( (GGLSurface*) surface); } + +// These are new graphics functions from 5.0 that were not available in +// 4.4 that are required by charger and healthd +void gr_clear() +{ + return; +} + diff --git a/minui/minui.h b/minui/minui.h index 103318aa7..4c629c1b5 100644 --- a/minui/minui.h +++ b/minui/minui.h @@ -56,7 +56,7 @@ unsigned int gr_get_height(gr_surface surface); // see http://www.mjmwired.net/kernel/Documentation/input/ for info. struct input_event; -typedef int (*ev_callback)(int fd, short revents, void *data); +typedef int (*ev_callback)(int fd, uint32_t epevents, void *data); typedef int (*ev_set_key_callback)(int code, int value, void *data); int ev_init(ev_callback input_cb, void *data); @@ -71,19 +71,33 @@ int ev_sync_key_state(ev_set_key_callback set_key_cb, void *data); */ int ev_wait(int timeout); -int ev_get_input(int fd, short revents, struct input_event *ev); +int ev_get_input(int fd, uint32_t epevents, struct input_event *ev); void ev_dispatch(void); +int ev_get_epollfd(void); // Resources // Returns 0 if no error, else negative. int res_create_surface(const char* name, gr_surface* pSurface); + +// Load an array of display surfaces from a single PNG image. The PNG +// should have a 'Frames' text chunk whose value is the number of +// frames this image represents. The pixel data itself is interlaced +// by row. +int res_create_multi_display_surface(const char* name, + int* frames, gr_surface** pSurface); + int res_create_localized_surface(const char* name, gr_surface* pSurface); void res_free_surface(gr_surface surface); static inline int res_create_display_surface(const char* name, gr_surface* pSurface) { return res_create_surface(name, pSurface); } +// These are new graphics functions from 5.0 that were not available in +// 4.4 that are required by charger and healthd +void gr_clear(); + + #ifdef __cplusplus } #endif diff --git a/minui/resources.c b/minui/resources.c index 064325edf..605edbca7 100644 --- a/minui/resources.c +++ b/minui/resources.c @@ -186,6 +186,164 @@ exit: return result; } +static int open_png(const char* name, png_structp* png_ptr, png_infop* info_ptr, + png_uint_32* width, png_uint_32* height, png_byte* channels) { + char resPath[256]; + unsigned char header[8]; + int result = 0; + + snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name); + resPath[sizeof(resPath)-1] = '\0'; + FILE* fp = fopen(resPath, "rb"); + if (fp == NULL) { + result = -1; + goto exit; + } + + size_t bytesRead = fread(header, 1, sizeof(header), fp); + if (bytesRead != sizeof(header)) { + result = -2; + goto exit; + } + + if (png_sig_cmp(header, 0, sizeof(header))) { + result = -3; + goto exit; + } + + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!*png_ptr) { + result = -4; + goto exit; + } + + *info_ptr = png_create_info_struct(*png_ptr); + if (!*info_ptr) { + result = -5; + goto exit; + } + + if (setjmp(png_jmpbuf(*png_ptr))) { + result = -6; + goto exit; + } + + png_init_io(*png_ptr, fp); + png_set_sig_bytes(*png_ptr, sizeof(header)); + png_read_info(*png_ptr, *info_ptr); + + int color_type, bit_depth; + png_get_IHDR(*png_ptr, *info_ptr, width, height, &bit_depth, + &color_type, NULL, NULL, NULL); + + *channels = png_get_channels(*png_ptr, *info_ptr); + + if (bit_depth == 8 && *channels == 3 && color_type == PNG_COLOR_TYPE_RGB) { + // 8-bit RGB images: great, nothing to do. + } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_GRAY) { + // 1-, 2-, 4-, or 8-bit gray images: expand to 8-bit gray. + png_set_expand_gray_1_2_4_to_8(*png_ptr); + } else if (bit_depth <= 8 && *channels == 1 && color_type == PNG_COLOR_TYPE_PALETTE) { + // paletted images: expand to 8-bit RGB. Note that we DON'T + // currently expand the tRNS chunk (if any) to an alpha + // channel, because minui doesn't support alpha channels in + // general. + png_set_palette_to_rgb(*png_ptr); + *channels = 3; + } else { + fprintf(stderr, "minui doesn't support PNG depth %d channels %d color_type %d\n", + bit_depth, *channels, color_type); + result = -7; + goto exit; + } + + return result; + + exit: + if (result < 0) { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + } + if (fp != NULL) { + fclose(fp); + } + + return result; +} + +int res_create_multi_display_surface(const char* name, int* frames, gr_surface** pSurface) { + gr_surface* surface = NULL; + int result = 0; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + png_uint_32 width, height; + png_byte channels; + int i; + + *pSurface = NULL; + *frames = -1; + + result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels); + if (result < 0) return result; + + *frames = 1; + png_textp text; + int num_text; + if (png_get_text(png_ptr, info_ptr, &text, &num_text)) { + for (i = 0; i < num_text; ++i) { + if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) { + *frames = atoi(text[i].text); + break; + } + } + printf(" found frames = %d\n", *frames); + } + + if (height % *frames != 0) { + printf("bad height (%d) for frame count (%d)\n", height, *frames); + result = -9; + goto exit; + } + + surface = malloc(*frames * sizeof(gr_surface)); + if (surface == NULL) { + result = -8; + goto exit; + } + for (i = 0; i < *frames; ++i) { + surface[i] = NULL;//init_display_surface(width, height / *frames); + if (surface[i] == NULL) { + result = -8; + goto exit; + } + } + + /*unsigned char* p_row = malloc(width * 4); + unsigned int y; + for (y = 0; y < height; ++y) { + png_read_row(png_ptr, p_row, NULL); + int frame = y % *frames; + unsigned char* out_row = surface[frame]->data + + (y / *frames) * surface[frame]->row_bytes; + transform_rgb_to_draw(p_row, out_row, channels, width); + } + free(p_row); this will need to be brought in line with the older resources and graphics code */ + + *pSurface = (gr_surface*) surface; + +exit: + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + if (result < 0) { + if (surface) { + for (i = 0; i < *frames; ++i) { + if (surface[i]) free(surface[i]); + } + free(surface); + } + } + return result; +} + static int matches_locale(const char* loc) { if (locale == NULL) return 0; -- cgit v1.2.3