diff options
author | David 'Digit' Turner <digit@android.com> | 2011-02-02 12:12:53 -0800 |
---|---|---|
committer | Android Code Review <code-review@android.com> | 2011-02-02 12:12:53 -0800 |
commit | d6eda1d7b357746ad8d9a4c80dc0235ef56c40e0 (patch) | |
tree | b669e7b99c01bd8aafd2079321c8cb80302454e0 | |
parent | ce747472342237e882369e486254684ab7708362 (diff) | |
parent | 07db34976ba1dd045a51c4ab2c7f52479cddcc57 (diff) | |
download | external_qemu-d6eda1d7b357746ad8d9a4c80dc0235ef56c40e0.zip external_qemu-d6eda1d7b357746ad8d9a4c80dc0235ef56c40e0.tar.gz external_qemu-d6eda1d7b357746ad8d9a4c80dc0235ef56c40e0.tar.bz2 |
Merge changes Icd076267,I6d5ad6ec
* changes:
Simplify UI-only sources.
Simplify core framebuffer management.
-rw-r--r-- | Makefile.android | 5 | ||||
-rw-r--r-- | android/console.c | 46 | ||||
-rw-r--r-- | android/display-core.c | 124 | ||||
-rw-r--r-- | android/display-core.h | 34 | ||||
-rw-r--r-- | android/framebuffer.c | 9 | ||||
-rw-r--r-- | android/framebuffer.h | 9 | ||||
-rw-r--r-- | android/looper-generic.c | 2 | ||||
-rw-r--r-- | android/main-common.c | 2 | ||||
-rw-r--r-- | android/main-ui.c | 11 | ||||
-rw-r--r-- | android/protocol/fb-updates-proxy.c | 70 | ||||
-rw-r--r-- | android/protocol/fb-updates-proxy.h | 13 | ||||
-rw-r--r-- | android/protocol/ui-commands-impl.c | 4 | ||||
-rw-r--r-- | android/qemulator.c | 6 | ||||
-rw-r--r-- | console-ui.c | 715 | ||||
-rw-r--r-- | console.c | 17 | ||||
-rw-r--r-- | console.h | 35 | ||||
-rw-r--r-- | qemu-timer-ui.c | 2 | ||||
-rw-r--r-- | vl-android-ui.c | 495 |
18 files changed, 241 insertions, 1358 deletions
diff --git a/Makefile.android b/Makefile.android index 1e103fd..7ddff81 100644 --- a/Makefile.android +++ b/Makefile.android @@ -690,7 +690,6 @@ CORE_MISC_SOURCES = vl-android.c \ module.c \ qemu-timer.c \ android/boot-properties.c \ - android/display.c \ android/hw-kmsg.c \ android/hw-lcd.c \ android/gps.c \ @@ -876,6 +875,7 @@ endif VL_SOURCES := android/framebuffer.c \ user-events-qemu.c \ android/cmdline-option.c \ + android/display.c \ android/looper-qemu.c \ android/protocol/ui-commands-qemu.c \ android/protocol/core-commands-qemu.c \ @@ -1209,14 +1209,11 @@ endif VL_SOURCES := android/framebuffer.c \ android/cmdline-option.c \ android/config.c \ - android/display.c \ android/looper-generic.c \ android/snapshot.c \ android/main-common.c \ android/main-ui.c \ - qemu-timer-ui.c \ vl-android-ui.c \ - console-ui.c \ iolooper-select.c \ android/protocol/core-connection.c \ android/protocol/attach-ui-impl.c \ diff --git a/android/console.c b/android/console.c index d776a5c..d883002 100644 --- a/android/console.c +++ b/android/console.c @@ -121,9 +121,6 @@ typedef struct ControlGlobalRec_ /* UI client currently attached to the core. */ ControlClient attached_ui_client = NULL; -/* Core framebuffer service client. */ -ControlClient framebuffer_client = NULL; - /* User events service client. */ ControlClient user_events_client = NULL; @@ -245,15 +242,6 @@ control_client_destroy( ControlClient client ) attached_ui_client = NULL; } - if (client == framebuffer_client) { - ProxyFramebuffer* core_fb = coredisplay_detach_fb_service(); - if (core_fb != NULL) { - proxyFb_destroy(core_fb); - AFREE(core_fb); - } - framebuffer_client = NULL; - } - if (client == user_events_client) { userEventsImpl_destroy(); user_events_client = NULL; @@ -2525,14 +2513,12 @@ destroy_attach_ui_client(void) } } -/* Core display instance. */ -extern CoreDisplay core_display; - static int do_create_framebuffer_service( ControlClient client, char* args ) { ProxyFramebuffer* core_fb; const char* protocol = "-raw"; // Default framebuffer exchange protocol. + char reply_buf[64]; // Protocol type is defined by the arguments passed with the stream switch // command. @@ -2555,38 +2541,20 @@ do_create_framebuffer_service( ControlClient client, char* args ) } } - // Make sure that there are no framebuffer client already existing. - if (framebuffer_client != NULL) { - control_write( client, "KO: Another framebuffer service is already existing!\r\n" ); - control_client_destroy(client); - return -1; - } - - core_fb = proxyFb_create(client->sock, protocol, coredisplay_get_framebuffer()); - if (!coredisplay_attach_fb_service(core_fb)) { - char reply_buf[4096]; - framebuffer_client = client; - // Reply "OK" with the framebuffer's bits per pixel - snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n", - proxyFb_get_bits_per_pixel(core_fb)); - control_write( client, reply_buf); - } else { + core_fb = proxyFb_create(client->sock, protocol); + if (core_fb == NULL) { control_write( client, "KO\r\n" ); control_client_destroy(client); return -1; } + // Reply "OK" with the framebuffer's bits per pixel + snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n", + proxyFb_get_bits_per_pixel(core_fb)); + control_write( client, reply_buf); return 0; } -void -destroy_control_fb_client(void) -{ - if (framebuffer_client != NULL) { - control_client_destroy(framebuffer_client); - } -} - static int do_create_user_events_service( ControlClient client, char* args ) { diff --git a/android/display-core.c b/android/display-core.c index 6834cd6..80b7665 100644 --- a/android/display-core.c +++ b/android/display-core.c @@ -15,120 +15,54 @@ * by the core to communicate display changes to the attached UI */ -#include "android/utils/system.h" #include "android/display-core.h" +#include "qemu-common.h" -/* Core display descriptor. */ -struct CoreDisplay { - /* Display state for this core display. */ - DisplayState* ds; - - /* Framebuffer for this core display. */ - QFrameBuffer* fb; - - /* Framebuffer service associated with this core display. */ - ProxyFramebuffer* core_fb; -}; - -/* One and only one core display instance. */ -CoreDisplay core_display; - -/* - * Framebuffer calls this routine when it detects changes. This routine will - * initiate a "push" of the framebuffer changes to the UI. - * See QFrameBufferUpdateFunc in framebuffer.h for more info on this callback. - */ -static void -coredisplay_fb_update(void* opaque, int x, int y, int w, int h) -{ - CoreDisplay* cd = (CoreDisplay*)opaque; - if (cd->core_fb) { - proxyFb_update(cd->core_fb, cd->fb, x, y, w, h); - } -} - -/* - * Framebuffer callback. See QFrameBufferRotateFunc in framebuffer.h for more - * info on this callback. +/* This callback is call periodically by the GUI timer. + * Its purpose is to ensure that hw framebuffer updates are properly + * detected. Call the normal QEMU function for this here. */ static void -coredisplay_fb_rotate(void* opaque, int rotation) +coredisplay_refresh(DisplayState* ds) { + (void)ds; + vga_hw_update(); } -/* - * Framebuffer callback. See QFrameBufferPollFunc in framebuffer.h for more - * info on this callback. +/* Don't do anything here because this callback can't differentiate + * between several listeners. This will be handled by a DisplayUpdateListener + * instead. See Android-specific changes in console.h + * + * In the core, the DisplayUpdateListener is registered by the ProxyFramebuffer + * object. See android/protocol/fb-updates-proxy.c. */ static void -coredisplay_fb_poll(void* opaque) +coredisplay_update(DisplayState* ds, int x, int y, int w, int h) { - // This will eventually call core_display_fb_update. - qframebuffer_check_updates(); + (void)ds; + (void)x; + (void)y; + (void)w; + (void)h; } -/* - * Framebuffer callback. See QFrameBufferDoneFunc in framebuffer.h for more - * info on this callback. +/* This callback is normally used to indicate that the display resolution + * was changed by the guest (e.g. when a Windows PC changes the display from + * 1024x768 to 800x600. Since this doesn't happen in Android, ignore it. */ static void -coredisplay_fb_done(void* opaque) +coredisplay_resize(DisplayState* ds) { + (void)ds; } void coredisplay_init(DisplayState* ds) { - int format; - - core_display.ds = ds; - /* Create and initialize framebuffer instance that will be used for core - * display. - */ - ANEW0(core_display.fb); - core_display.core_fb = NULL; - - /* In the core, there is no skin to parse and the format of ds->surface - * is determined by the -android-gui option. - */ - format = QFRAME_BUFFER_RGB565; - if (ds->surface->pf.bytes_per_pixel == 4) - format = QFRAME_BUFFER_RGBX_8888; - - qframebuffer_init(core_display.fb, ds->surface->width, ds->surface->height, - 0, format); - qframebuffer_fifo_add(core_display.fb); - /* Register core display as the client for the framebuffer, so we can start - * receiving framebuffer notifications. Note that until UI connects to the - * core all framebuffer callbacks are essentially no-ops. - */ - qframebuffer_add_client(core_display.fb, &core_display, - coredisplay_fb_update, coredisplay_fb_rotate, - coredisplay_fb_poll, coredisplay_fb_done); - android_display_init(ds, core_display.fb); -} - -int -coredisplay_attach_fb_service(ProxyFramebuffer* core_fb) -{ - if (core_display.core_fb == NULL) { - core_display.core_fb = core_fb; - return 0; - } else { - return -1; - } -} - -ProxyFramebuffer* -coredisplay_detach_fb_service(void) -{ - ProxyFramebuffer* ret = core_display.core_fb; - core_display.core_fb = NULL; - return ret; -} + static DisplayChangeListener dcl[1]; -QFrameBuffer* -coredisplay_get_framebuffer(void) -{ - return core_display.fb; + dcl->dpy_update = coredisplay_update; + dcl->dpy_refresh = coredisplay_refresh; + dcl->dpy_resize = coredisplay_resize; + register_displaychangelistener(ds, dcl); } diff --git a/android/display-core.h b/android/display-core.h index edeccac..e6a1b7d 100644 --- a/android/display-core.h +++ b/android/display-core.h @@ -18,42 +18,14 @@ #ifndef _ANDROID_DISPLAY_CORE_H #define _ANDROID_DISPLAY_CORE_H -#include "android/framebuffer.h" -#include "android/display.h" -#include "android/protocol/fb-updates-proxy.h" - -/* Descriptor for a core display instance */ -typedef struct CoreDisplay CoreDisplay; +#include "console.h" /* * Initializes one and only one instance of a core display. - * Param: + * Only used to register a dummy display change listener that + * will trigger a timer. * ds - Display state to use for the core display. */ extern void coredisplay_init(DisplayState* ds); -/* - * Attaches framebuffer service to the core display. - * Param: - * core_fb - Framebuffer service descriptor to attach. - * Return: - * 0 on success, or -1 on failure. - */ -extern int coredisplay_attach_fb_service(ProxyFramebuffer* core_fb); - -/* - * Detaches framebuffer service previously attached to the core display. - * Return: - * Framebuffer service descriptor attached to the core display, or NULL if - * the core display didn't have framebuffer service attached to it. - */ -extern ProxyFramebuffer* coredisplay_detach_fb_service(void); - -/* - * Get framebuffer descriptor for core display. - * Return: - * Framebuffer descriptor for core display. - */ -extern QFrameBuffer* coredisplay_get_framebuffer(void); - #endif /* _ANDROID_DISPLAY_CORE_H */ diff --git a/android/framebuffer.c b/android/framebuffer.c index 53c6a48..b9b968e 100644 --- a/android/framebuffer.c +++ b/android/framebuffer.c @@ -281,6 +281,15 @@ qframebuffer_check_updates( void ) } void +qframebuffer_pulse( void ) +{ + int nn; + for (nn = 0; nn < framebuffer_fifo_count; nn++) { + qframebuffer_poll(framebuffer_fifo[nn]); + } +} + +void qframebuffer_invalidate_all( void ) { int nn; diff --git a/android/framebuffer.h b/android/framebuffer.h index 9d1f626..faf2f41 100644 --- a/android/framebuffer.h +++ b/android/framebuffer.h @@ -172,6 +172,10 @@ qframebuffer_update( QFrameBuffer* qfbuff, int x, int y, int w, int h ); extern void qframebuffer_rotate( QFrameBuffer* qfbuff, int rotation ); +/* this function is used to poll a framebuffer's client for input + * events. Should be called either explicitely, or through qframebuffer_pulse() + * periodically. + */ extern void qframebuffer_poll( QFrameBuffer* qfbuff ); @@ -188,6 +192,11 @@ qframebuffer_done( QFrameBuffer* qfbuff ); extern void qframebuffer_check_updates( void ); +/* call this function periodically to force a poll on all franebuffers + */ +extern void +qframebuffer_pulse( void ); + /* this is called by the emulator. for each registered framebuffer, call * its producer's Invalidate method, if any */ diff --git a/android/looper-generic.c b/android/looper-generic.c index 6ec0db4..d75fbff 100644 --- a/android/looper-generic.c +++ b/android/looper-generic.c @@ -289,7 +289,7 @@ glooper_addActiveTimer(GLooper* looper, GLoopTimer* tt) pnode = &node->activeNext; } tt->activeNext = *pnode; - *pnode = tt->activeNext; + *pnode = tt; } static void diff --git a/android/main-common.c b/android/main-common.c index 23ba5b9..bcae501 100644 --- a/android/main-common.c +++ b/android/main-common.c @@ -315,7 +315,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) } snprintf(buf, sizeof buf, "width=%d,height=%d", width, height); +#if !defined(CONFIG_STANDALONE_UI) && !defined(CONFIG_STANDALONE_CORE) android_display_init(ds, qframebuffer_fifo_get()); +#endif } /* list of skin aliases */ diff --git a/android/main-ui.c b/android/main-ui.c index 9981b76..daf71cb 100644 --- a/android/main-ui.c +++ b/android/main-ui.c @@ -1507,16 +1507,5 @@ int main(int argc, char **argv) } } - // Connect to the core's framebuffer service - if (implFb_create(attachUiImpl_get_console_socket(), "-raw", - qemulator_get_first_framebuffer(qemulator_get()))) { - return -1; - } - - // Attach the recepient of UI commands. - if (uiCmdImpl_create(attachUiImpl_get_console_socket())) { - return -1; - } - return qemu_main(n, args); } diff --git a/android/protocol/fb-updates-proxy.c b/android/protocol/fb-updates-proxy.c index 359c942..ec7414d 100644 --- a/android/protocol/fb-updates-proxy.c +++ b/android/protocol/fb-updates-proxy.c @@ -16,7 +16,6 @@ */ #include "console.h" -#include "android/framebuffer.h" #include "android/looper.h" #include "android/display-core.h" #include "android/async-utils.h" @@ -37,8 +36,9 @@ struct ProxyFramebuffer { /* I/O associated with this descriptor. */ LoopIo io; - /* Framebuffer used for this service. */ - QFrameBuffer* fb; + /* Display state used for this service */ + DisplayState* ds; + DisplayUpdateListener* ds_listener; /* Looper used to communicate framebuffer updates. */ Looper* looper; @@ -80,9 +80,9 @@ typedef struct FBUpdateNotify { * Pointer in framebuffer's pixels for the given pixel. */ static const uint8_t* -_pixel_offset(const QFrameBuffer* fb, int x, int y) +_pixel_offset(const DisplaySurface* dsu, int x, int y) { - return (const uint8_t*)fb->pixels + y * fb->pitch + x * fb->bytes_per_pixel; + return (const uint8_t*)dsu->data + y * dsu->linesize + x * dsu->pf.bytes_per_pixel; } /* @@ -93,13 +93,13 @@ _pixel_offset(const QFrameBuffer* fb, int x, int y) * x, y, w, and h - dimensions of the rectangle to copy. */ static void -_copy_fb_rect(uint8_t* rect, const QFrameBuffer* fb, int x, int y, int w, int h) +_copy_fb_rect(uint8_t* rect, const DisplaySurface* dsu, int x, int y, int w, int h) { - const uint8_t* start = _pixel_offset(fb, x, y); + const uint8_t* start = _pixel_offset(dsu, x, y); for (; h > 0; h--) { - memcpy(rect, start, w * fb->bytes_per_pixel); - start += fb->pitch; - rect += w * fb->bytes_per_pixel; + memcpy(rect, start, w * dsu->pf.bytes_per_pixel); + start += dsu->linesize; + rect += w * dsu->pf.bytes_per_pixel; } } @@ -113,10 +113,10 @@ _copy_fb_rect(uint8_t* rect, const QFrameBuffer* fb, int x, int y, int w, int h) * Initialized framebuffer update notification descriptor. */ static FBUpdateNotify* -fbupdatenotify_create(ProxyFramebuffer* proxy_fb, const QFrameBuffer* fb, +fbupdatenotify_create(ProxyFramebuffer* proxy_fb, int x, int y, int w, int h) { - const size_t rect_size = w * h * fb->bytes_per_pixel; + const size_t rect_size = w * h * proxy_fb->ds->surface->pf.bytes_per_pixel; FBUpdateNotify* ret = malloc(sizeof(FBUpdateNotify) + rect_size); ret->next_fb_update = NULL; @@ -126,7 +126,7 @@ fbupdatenotify_create(ProxyFramebuffer* proxy_fb, const QFrameBuffer* fb, ret->message.y = y; ret->message.w = w; ret->message.h = h; - _copy_fb_rect(ret->message.rect, fb, x, y, w, h); + _copy_fb_rect(ret->message.rect, proxy_fb->ds->surface, x, y, w, h); return ret; } @@ -143,9 +143,6 @@ fbupdatenotify_delete(FBUpdateNotify* desc) } } -/* Implemented in android/console.c */ -extern void destroy_control_fb_client(void); - /* * Asynchronous write I/O callback launched when writing framebuffer * notifications to the socket. @@ -191,6 +188,8 @@ _proxyFb_io_write(ProxyFramebuffer* proxy_fb) } } +static void proxyFb_update(void* opaque, int x, int y, int w, int h); + /* * Asynchronous read I/O callback launched when reading framebuffer requests * from the socket. @@ -201,6 +200,7 @@ static void _proxyFb_io_read(ProxyFramebuffer* proxy_fb) { // Read the request header. + DisplaySurface* dsu; const AsyncStatus status = asyncReader_read(&proxy_fb->fb_req_reader, &proxy_fb->io); switch (status) { @@ -209,9 +209,9 @@ _proxyFb_io_read(ProxyFramebuffer* proxy_fb) switch (proxy_fb->fb_req_header.request_type) { case AFB_REQUEST_REFRESH: // Force full screen update to be sent - proxyFb_update(proxy_fb, proxy_fb->fb, - 0, 0, proxy_fb->fb->width, - proxy_fb->fb->height); + dsu = proxy_fb->ds->surface; + proxyFb_update(proxy_fb, + 0, 0, dsu->width, dsu->height); break; default: derror("Unknown framebuffer request %d\n", @@ -226,7 +226,7 @@ _proxyFb_io_read(ProxyFramebuffer* proxy_fb) loopIo_dontWantRead(&proxy_fb->io); if (errno == ECONNRESET) { // UI has exited. We need to destroy framebuffer service. - destroy_control_fb_client(); + proxyFb_destroy(proxy_fb); } break; @@ -253,14 +253,24 @@ _proxyFb_io_fun(void* opaque, int fd, unsigned events) } ProxyFramebuffer* -proxyFb_create(int sock, const char* protocol, QFrameBuffer* fb) +proxyFb_create(int sock, const char* protocol) { // At this point we're implementing the -raw protocol only. ProxyFramebuffer* ret; + DisplayState* ds = get_displaystate(); + DisplayUpdateListener* dul; + ANEW0(ret); ret->sock = sock; ret->looper = looper_newCore(); - ret->fb = fb; + ret->ds = ds; + + ANEW0(dul); + dul->opaque = ret; + dul->dpy_update = proxyFb_update; + register_displayupdatelistener(ds, dul); + ret->ds_listener = dul; + ret->fb_update_head = NULL; ret->fb_update_tail = NULL; loopIo_init(&ret->io, ret->looper, sock, _proxyFb_io_fun, ret); @@ -273,6 +283,7 @@ void proxyFb_destroy(ProxyFramebuffer* proxy_fb) { if (proxy_fb != NULL) { + unregister_displayupdatelistener(proxy_fb->ds, proxy_fb->ds_listener); if (proxy_fb->looper != NULL) { // Stop all I/O that may still be going on. loopIo_done(&proxy_fb->io); @@ -286,15 +297,16 @@ proxyFb_destroy(ProxyFramebuffer* proxy_fb) looper_free(proxy_fb->looper); proxy_fb->looper = NULL; } + AFREE(proxy_fb); } } -void -proxyFb_update(ProxyFramebuffer* proxy_fb, - struct QFrameBuffer* fb, int x, int y, int w, int h) +static void +proxyFb_update(void* opaque, int x, int y, int w, int h) { + ProxyFramebuffer* proxy_fb = opaque; AsyncStatus status; - FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, fb, x, y, w, h); + FBUpdateNotify* descr = fbupdatenotify_create(proxy_fb, x, y, w, h); // Lets see if we should list it behind other pending updates. if (proxy_fb->fb_update_tail != NULL) { @@ -327,6 +339,8 @@ proxyFb_update(ProxyFramebuffer* proxy_fb, int proxyFb_get_bits_per_pixel(ProxyFramebuffer* proxy_fb) { - return (proxy_fb != NULL && proxy_fb->fb != NULL) ? - proxy_fb->fb->bits_per_pixel : -1; + if (proxy_fb == NULL || proxy_fb->ds == NULL) + return -1; + + return proxy_fb->ds->surface->pf.bits_per_pixel; } diff --git a/android/protocol/fb-updates-proxy.h b/android/protocol/fb-updates-proxy.h index e750f1a..15b1d5b 100644 --- a/android/protocol/fb-updates-proxy.h +++ b/android/protocol/fb-updates-proxy.h @@ -29,11 +29,10 @@ typedef struct ProxyFramebuffer ProxyFramebuffer; * supported values ar: * -raw Transfers the updating rectangle buffer over the socket. * -shared Used a shared memory to transfer the updating rectangle buffer. - * fb - Framebuffer descriptor for this service. * Return: * Framebuffer service descriptor. */ -ProxyFramebuffer* proxyFb_create(int sock, const char* protocol, struct QFrameBuffer* fb); +ProxyFramebuffer* proxyFb_create(int sock, const char* protocol); /* * Destroys framebuffer service created with proxyFb_create. @@ -43,16 +42,6 @@ ProxyFramebuffer* proxyFb_create(int sock, const char* protocol, struct QFrameBu void proxyFb_destroy(ProxyFramebuffer* core_fb); /* - * Notifies framebuffer client about changes in framebuffer. - * Param: - * core_fb - Framebuffer service descriptor created with proxyFb_create - * fb Framebuffer containing pixels. - * x, y, w, and h identify the rectangle that has benn changed. - */ -void proxyFb_update(ProxyFramebuffer* core_fb, struct QFrameBuffer* fb, - int x, int y, int w, int h); - -/* * Gets number of bits used to encode a single pixel. * Param: * core_fb - Framebuffer service descriptor created with proxyFb_create diff --git a/android/protocol/ui-commands-impl.c b/android/protocol/ui-commands-impl.c index f265514..2ca4194 100644 --- a/android/protocol/ui-commands-impl.c +++ b/android/protocol/ui-commands-impl.c @@ -124,7 +124,7 @@ _uiCmdImpl_io_read(void* opaque) status = read(uicmd->sock, uicmd->reader_buffer + uicmd->reader_offset, uicmd->reader_bytes - uicmd->reader_offset); if (status == 0) { - /* Disconnection, meaning that the core process got termonated. */ + /* Disconnection, meaning that the core process got terminated. */ fprintf(stderr, "core-ui-control service got disconnected\n"); uiCmdImpl_destroy(); return; @@ -201,7 +201,7 @@ uiCmdImpl_create(SockAddress* console_socket) return -1; } - // Initialze UI command reader. + // Initialize UI command reader. _uiCmdImpl.sock = core_connection_get_socket(_uiCmdImpl.core_connection); if (qemu_set_fd_handler(_uiCmdImpl.sock, _uiCmdImpl_io_read, NULL, &_uiCmdImpl)) { diff --git a/android/qemulator.c b/android/qemulator.c index 36a9ec8..c90a674 100644 --- a/android/qemulator.c +++ b/android/qemulator.c @@ -97,8 +97,10 @@ qemulator_fb_update( void* _emulator, int x, int y, int w, int h ) { QEmulator* emulator = _emulator; - if (emulator->window) - skin_window_update_display( emulator->window, x, y, w, h ); + if (!emulator->window) { + qemulator_setup( emulator ); + } + skin_window_update_display( emulator->window, x, y, w, h ); } static void diff --git a/console-ui.c b/console-ui.c deleted file mode 100644 index 42a5cb3..0000000 --- a/console-ui.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * QEMU graphical console - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "qemu-common.h" -#include "console.h" -#include "qemu-timer.h" -#include "android/utils/system.h" - -//#define DEBUG_CONSOLE -#define DEFAULT_BACKSCROLL 512 -#define MAX_CONSOLES 12 - -#define QEMU_RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) -#define QEMU_RGB(r, g, b) QEMU_RGBA(r, g, b, 0xff) - -typedef struct TextAttributes { - uint8_t fgcol:4; - uint8_t bgcol:4; - uint8_t bold:1; - uint8_t uline:1; - uint8_t blink:1; - uint8_t invers:1; - uint8_t unvisible:1; -} TextAttributes; - -typedef struct TextCell { - uint8_t ch; - TextAttributes t_attrib; -} TextCell; - -#define MAX_ESC_PARAMS 3 - -enum TTYState { - TTY_STATE_NORM, - TTY_STATE_ESC, - TTY_STATE_CSI, -}; - -typedef struct QEMUFIFO { - uint8_t *buf; - int buf_size; - int count, wptr, rptr; -} QEMUFIFO; - -typedef enum { - GRAPHIC_CONSOLE, - TEXT_CONSOLE, - TEXT_CONSOLE_FIXED_SIZE -} console_type_t; - -/* ??? This is mis-named. - It is used for both text and graphical consoles. */ -struct TextConsole { - console_type_t console_type; - DisplayState *ds; - /* Graphic console state. */ - vga_hw_update_ptr hw_update; - vga_hw_invalidate_ptr hw_invalidate; - vga_hw_screen_dump_ptr hw_screen_dump; - vga_hw_text_update_ptr hw_text_update; - void *hw; - - int g_width, g_height; - int width; - int height; - int total_height; - int backscroll_height; - int x, y; - int x_saved, y_saved; - int y_displayed; - int y_base; - TextAttributes t_attrib_default; /* default text attributes */ - TextAttributes t_attrib; /* currently active text attributes */ - TextCell *cells; - int text_x[2], text_y[2], cursor_invalidate; - - int update_x0; - int update_y0; - int update_x1; - int update_y1; - - enum TTYState state; - int esc_params[MAX_ESC_PARAMS]; - int nb_esc_params; - - /* fifo for key pressed */ - QEMUFIFO out_fifo; - uint8_t out_fifo_buf[16]; - QEMUTimer *kbd_timer; -}; - -static DisplayState *display_state; -static TextConsole *active_console; -static TextConsole *consoles[MAX_CONSOLES]; -static int nb_consoles = 0; - -#ifdef CONFIG_ANDROID -/* Graphic console width, height and bits per pixel. - * These default values can be changed with the "-android-gui" option. - */ -int android_display_width = 640; -int android_display_height = 480; -int android_display_bpp = 32; -#endif - -void vga_hw_update(void) -{ - if (active_console && active_console->hw_update) - active_console->hw_update(active_console->hw); -} - -void vga_hw_invalidate(void) -{ - if (active_console && active_console->hw_invalidate) - active_console->hw_invalidate(active_console->hw); -} - -void vga_hw_screen_dump(const char *filename) -{ - TextConsole *previous_active_console; - - previous_active_console = active_console; - active_console = consoles[0]; - /* There is currently no way of specifying which screen we want to dump, - so always dump the first one. */ - if (consoles[0]->hw_screen_dump) - consoles[0]->hw_screen_dump(consoles[0]->hw, filename); - active_console = previous_active_console; -} - -void vga_hw_text_update(console_ch_t *chardata) -{ - if (active_console && active_console->hw_text_update) - active_console->hw_text_update(active_console->hw, chardata); -} - -/* convert a RGBA color to a color index usable in graphic primitives */ -static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) -{ - unsigned int r, g, b, color; - - switch(ds_get_bits_per_pixel(ds)) { -#if 0 - case 8: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = (rgb_to_index[r] * 6 * 6) + - (rgb_to_index[g] * 6) + - (rgb_to_index[b]); - break; -#endif - case 15: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); - break; - case 16: - r = (rgba >> 16) & 0xff; - g = (rgba >> 8) & 0xff; - b = (rgba) & 0xff; - color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); - break; - case 32: - default: - color = rgba; - break; - } - return color; -} - -/***********************************************************/ -/* basic char display */ - -#define FONT_HEIGHT 16 -#define FONT_WIDTH 8 - -#include "vgafont.h" - -#define cbswap_32(__x) \ -((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) - -#ifdef HOST_WORDS_BIGENDIAN -#define PAT(x) x -#else -#define PAT(x) cbswap_32(x) -#endif - -static const uint32_t dmask16[16] = { - PAT(0x00000000), - PAT(0x000000ff), - PAT(0x0000ff00), - PAT(0x0000ffff), - PAT(0x00ff0000), - PAT(0x00ff00ff), - PAT(0x00ffff00), - PAT(0x00ffffff), - PAT(0xff000000), - PAT(0xff0000ff), - PAT(0xff00ff00), - PAT(0xff00ffff), - PAT(0xffff0000), - PAT(0xffff00ff), - PAT(0xffffff00), - PAT(0xffffffff), -}; - -static const uint32_t dmask4[4] = { - PAT(0x00000000), - PAT(0x0000ffff), - PAT(0xffff0000), - PAT(0xffffffff), -}; - -static uint32_t color_table[2][8]; - -enum color_names { - COLOR_BLACK = 0, - COLOR_RED = 1, - COLOR_GREEN = 2, - COLOR_YELLOW = 3, - COLOR_BLUE = 4, - COLOR_MAGENTA = 5, - COLOR_CYAN = 6, - COLOR_WHITE = 7 -}; - -static const uint32_t color_table_rgb[2][8] = { - { /* dark */ - QEMU_RGB(0x00, 0x00, 0x00), /* black */ - QEMU_RGB(0xaa, 0x00, 0x00), /* red */ - QEMU_RGB(0x00, 0xaa, 0x00), /* green */ - QEMU_RGB(0xaa, 0xaa, 0x00), /* yellow */ - QEMU_RGB(0x00, 0x00, 0xaa), /* blue */ - QEMU_RGB(0xaa, 0x00, 0xaa), /* magenta */ - QEMU_RGB(0x00, 0xaa, 0xaa), /* cyan */ - QEMU_RGB(0xaa, 0xaa, 0xaa), /* white */ - }, - { /* bright */ - QEMU_RGB(0x00, 0x00, 0x00), /* black */ - QEMU_RGB(0xff, 0x00, 0x00), /* red */ - QEMU_RGB(0x00, 0xff, 0x00), /* green */ - QEMU_RGB(0xff, 0xff, 0x00), /* yellow */ - QEMU_RGB(0x00, 0x00, 0xff), /* blue */ - QEMU_RGB(0xff, 0x00, 0xff), /* magenta */ - QEMU_RGB(0x00, 0xff, 0xff), /* cyan */ - QEMU_RGB(0xff, 0xff, 0xff), /* white */ - } -}; - -static inline unsigned int col_expand(DisplayState *ds, unsigned int col) -{ - switch(ds_get_bits_per_pixel(ds)) { - case 8: - col |= col << 8; - col |= col << 16; - break; - case 15: - case 16: - col |= col << 16; - break; - default: - break; - } - - return col; -} -#ifdef DEBUG_CONSOLE -static void console_print_text_attributes(TextAttributes *t_attrib, char ch) -{ - if (t_attrib->bold) { - printf("b"); - } else { - printf(" "); - } - if (t_attrib->uline) { - printf("u"); - } else { - printf(" "); - } - if (t_attrib->blink) { - printf("l"); - } else { - printf(" "); - } - if (t_attrib->invers) { - printf("i"); - } else { - printf(" "); - } - if (t_attrib->unvisible) { - printf("n"); - } else { - printf(" "); - } - - printf(" fg: %d bg: %d ch:'%2X' '%c'\n", t_attrib->fgcol, t_attrib->bgcol, ch, ch); -} -#endif - -void console_select(unsigned int index) -{ - TextConsole *s; - - if (index >= MAX_CONSOLES) - return; - active_console->g_width = ds_get_width(active_console->ds); - active_console->g_height = ds_get_height(active_console->ds); - s = consoles[index]; - if (s) { - DisplayState *ds = s->ds; - active_console = s; - if (ds_get_bits_per_pixel(s->ds)) { - ds->surface = qemu_resize_displaysurface(ds, s->g_width, s->g_height); - } else { - s->ds->surface->width = s->width; - s->ds->surface->height = s->height; - } - dpy_resize(s->ds); - vga_hw_invalidate(); - } -} - -static TextConsole *get_graphic_console(DisplayState *ds) -{ - int i; - TextConsole *s; - for (i = 0; i < nb_consoles; i++) { - s = consoles[i]; - if (s->console_type == GRAPHIC_CONSOLE && s->ds == ds) - return s; - } - return NULL; -} - -static TextConsole *new_console(DisplayState *ds, console_type_t console_type) -{ - TextConsole *s; - int i; - - if (nb_consoles >= MAX_CONSOLES) - return NULL; - ANEW0(s); - if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) && - (console_type == GRAPHIC_CONSOLE))) { - active_console = s; - } - s->ds = ds; - s->console_type = console_type; - if (console_type != GRAPHIC_CONSOLE) { - consoles[nb_consoles++] = s; - } else { - /* HACK: Put graphical consoles before text consoles. */ - for (i = nb_consoles; i > 0; i--) { - if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE) - break; - consoles[i] = consoles[i - 1]; - } - consoles[i] = s; - nb_consoles++; - } - return s; -} - -static DisplaySurface* defaultallocator_create_displaysurface(int width, int height) -{ - DisplaySurface *surface; - - ANEW0(surface); - surface->width = width; - surface->height = height; - surface->linesize = width * 4; - surface->pf = qemu_default_pixelformat(32); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - surface->data = (uint8_t*) android_alloc0(surface->linesize * surface->height); - - return surface; -} - -static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface, - int width, int height) -{ - surface->width = width; - surface->height = height; - surface->linesize = width * 4; - surface->pf = qemu_default_pixelformat(32); - if (surface->flags & QEMU_ALLOCATED_FLAG) - surface->data = (uint8_t*) android_realloc(surface->data, surface->linesize * surface->height); - else - surface->data = (uint8_t*) android_alloc(surface->linesize * surface->height); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG; -#else - surface->flags = QEMU_ALLOCATED_FLAG; -#endif - - return surface; -} - -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data) -{ - DisplaySurface *surface; - - ANEW0(surface); - surface->width = width; - surface->height = height; - surface->linesize = linesize; - surface->pf = qemu_default_pixelformat(bpp); -#ifdef HOST_WORDS_BIGENDIAN - surface->flags = QEMU_BIG_ENDIAN_FLAG; -#endif - surface->data = data; - - return surface; -} - -static void defaultallocator_free_displaysurface(DisplaySurface *surface) -{ - if (surface == NULL) - return; - if (surface->flags & QEMU_ALLOCATED_FLAG) - AFREE(surface->data); - AFREE(surface); -} - -static struct DisplayAllocator default_allocator = { - defaultallocator_create_displaysurface, - defaultallocator_resize_displaysurface, - defaultallocator_free_displaysurface -}; - -static void dumb_display_init(void) -{ - DisplayState *ds; - ANEW0(ds); - ds->allocator = &default_allocator; - ds->surface = qemu_create_displaysurface(ds, 640, 480); - register_displaystate(ds); -} - -/***********************************************************/ -/* register display */ - -void register_displaystate(DisplayState *ds) -{ - DisplayState **s; - s = &display_state; - while (*s != NULL) - s = &(*s)->next; - ds->next = NULL; - *s = ds; -} - -DisplayState *get_displaystate(void) -{ - if (!display_state) { - dumb_display_init (); - } - return display_state; -} - -DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da) -{ - if(ds->allocator == &default_allocator) { - DisplaySurface *surf; - surf = da->create_displaysurface(ds_get_width(ds), ds_get_height(ds)); - defaultallocator_free_displaysurface(ds->surface); - ds->surface = surf; - ds->allocator = da; - } - return ds->allocator; -} - -DisplayState *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, - void *opaque) -{ - TextConsole *s; - DisplayState *ds; - - ANEW0(ds); - ds->allocator = &default_allocator; -#ifdef CONFIG_ANDROID - ds->surface = qemu_create_displaysurface(ds, android_display_width, android_display_height); -#else - ds->surface = qemu_create_displaysurface(ds, 640, 480); -#endif - - s = new_console(ds, GRAPHIC_CONSOLE); - if (s == NULL) { - qemu_free_displaysurface(ds); - AFREE(ds); - return NULL; - } - s->hw_update = update; - s->hw_invalidate = invalidate; - s->hw_screen_dump = screen_dump; - s->hw_text_update = text_update; - s->hw = opaque; - - register_displaystate(ds); - return ds; -} - -int is_graphic_console(void) -{ - return active_console && active_console->console_type == GRAPHIC_CONSOLE; -} - -int is_fixedsize_console(void) -{ - return active_console && active_console->console_type != TEXT_CONSOLE; -} - -void console_color_init(DisplayState *ds) -{ - int i, j; - for (j = 0; j < 2; j++) { - for (i = 0; i < 8; i++) { - color_table[j][i] = col_expand(ds, - vga_get_color(ds, color_table_rgb[j][i])); - } - } -} - -void qemu_console_resize(DisplayState *ds, int width, int height) -{ - TextConsole *s = get_graphic_console(ds); - if (!s) return; - - s->g_width = width; - s->g_height = height; - if (is_graphic_console()) { - ds->surface = qemu_resize_displaysurface(ds, width, height); - dpy_resize(ds); - } -} - -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) -{ - if (is_graphic_console()) { - dpy_copy(ds, src_x, src_y, dst_x, dst_y, w, h); - } -} - -PixelFormat qemu_different_endianness_pixelformat(int bpp) -{ - PixelFormat pf; - - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 24: - pf.rmask = 0x000000FF; - pf.gmask = 0x0000FF00; - pf.bmask = 0x00FF0000; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 0; - pf.gshift = 8; - pf.bshift = 16; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - break; - case 32: - pf.rmask = 0x0000FF00; - pf.gmask = 0x00FF0000; - pf.bmask = 0xFF000000; - pf.amask = 0x00000000; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 0; - pf.rshift = 8; - pf.gshift = 16; - pf.bshift = 24; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; - } - return pf; -} - -PixelFormat qemu_default_pixelformat(int bpp) -{ - PixelFormat pf; - - memset(&pf, 0x00, sizeof(PixelFormat)); - - pf.bits_per_pixel = bpp; - pf.bytes_per_pixel = bpp / 8; - pf.depth = bpp == 32 ? 24 : bpp; - - switch (bpp) { - case 15: - pf.bits_per_pixel = 16; - pf.bytes_per_pixel = 2; - pf.rmask = 0x00007c00; - pf.gmask = 0x000003E0; - pf.bmask = 0x0000001F; - pf.rmax = 31; - pf.gmax = 31; - pf.bmax = 31; - pf.rshift = 10; - pf.gshift = 5; - pf.bshift = 0; - pf.rbits = 5; - pf.gbits = 5; - pf.bbits = 5; - break; - case 16: - pf.rmask = 0x0000F800; - pf.gmask = 0x000007E0; - pf.bmask = 0x0000001F; - pf.rmax = 31; - pf.gmax = 63; - pf.bmax = 31; - pf.rshift = 11; - pf.gshift = 5; - pf.bshift = 0; - pf.rbits = 5; - pf.gbits = 6; - pf.bbits = 5; - break; - case 24: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - case 32: - pf.rmask = 0x00FF0000; - pf.gmask = 0x0000FF00; - pf.bmask = 0x000000FF; - pf.amax = 255; - pf.rmax = 255; - pf.gmax = 255; - pf.bmax = 255; - pf.ashift = 24; - pf.rshift = 16; - pf.gshift = 8; - pf.bshift = 0; - pf.rbits = 8; - pf.gbits = 8; - pf.bbits = 8; - pf.abits = 8; - break; - default: - break; - } - return pf; -} - -#ifdef CONFIG_ANDROID -void -android_display_init_from(int width, int height, int rotation, int bpp) -{ - DisplayState *ds; - ANEW0(ds); - ds->allocator = &default_allocator; - ds->surface = qemu_create_displaysurface(ds, width, height); - register_displaystate(ds); -} -#endif @@ -1733,6 +1733,23 @@ PixelFormat qemu_default_pixelformat(int bpp) } #ifdef CONFIG_ANDROID + +void +unregister_displayupdatelistener(DisplayState *ds, DisplayUpdateListener *dul) +{ + DisplayUpdateListener **pnode = &ds->update_listeners; + for (;;) { + if (*pnode == NULL) + break; + if (*pnode == dul) { + *pnode = dul->next; + break; + } + pnode = &(*pnode)->next; + } + dul->next = NULL; +} + void android_display_reset(DisplayState* ds, int width, int height, int bitspp) { @@ -169,6 +169,19 @@ struct DisplayChangeListener { struct DisplayChangeListener *next; }; +#ifdef CONFIG_ANDROID +/* The problem with DisplayChangeListener is that the callbacks can't + * differentiate between different DisplayChangeListeners. Instead of + * modifying the type above, which is going to generate conflicts with + * upstream changes, we define our own listener type here. + */ +typedef struct DisplayUpdateListener { + void* opaque; + void (*dpy_update)(void* opaque, int x, int y, int w, int h); + struct DisplayUpdateListener *next; +} DisplayUpdateListener; +#endif + struct DisplayAllocator { DisplaySurface* (*create_displaysurface)(int width, int height); DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height); @@ -182,7 +195,9 @@ struct DisplayState { struct DisplayAllocator* allocator; struct DisplayChangeListener* listeners; - +#ifdef CONFIG_ANDROID + struct DisplayUpdateListener* update_listeners; +#endif void (*mouse_set)(int x, int y, int on); void (*cursor_define)(QEMUCursor *cursor); @@ -233,6 +248,17 @@ static inline void register_displaychangelistener(DisplayState *ds, DisplayChang ds->listeners = dcl; } +#ifdef CONFIG_ANDROID +static inline void register_displayupdatelistener(DisplayState *ds, DisplayUpdateListener *dul) +{ + dul->next = ds->update_listeners; + ds->update_listeners = dul; +} + +void unregister_displayupdatelistener(DisplayState *ds, DisplayUpdateListener *dul); + +#endif + static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) { struct DisplayChangeListener *dcl = s->listeners; @@ -240,6 +266,13 @@ static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) dcl->dpy_update(s, x, y, w, h); dcl = dcl->next; } +#ifdef CONFIG_ANDROID + DisplayUpdateListener* dul = s->update_listeners; + while (dul != NULL) { + dul->dpy_update(dul->opaque, x, y, w, h); + dul = dul->next; + } +#endif } static inline void dpy_resize(DisplayState *s) diff --git a/qemu-timer-ui.c b/qemu-timer-ui.c index ae85509..095036d 100644 --- a/qemu-timer-ui.c +++ b/qemu-timer-ui.c @@ -49,6 +49,8 @@ extern QEMUClock* rtc_clock; #include "qemu-timer.h" +QEMUClock *rtc_clock; + /***********************************************************/ /* real time host monotonic timer */ diff --git a/vl-android-ui.c b/vl-android-ui.c index c4a396c..91a7764 100644 --- a/vl-android-ui.c +++ b/vl-android-ui.c @@ -27,6 +27,8 @@ #define _GNU_SOURCE 1 #endif +#include <sys/wait.h> + #include "qemu-common.h" #include "net.h" #include "console.h" @@ -47,217 +49,46 @@ #include "android/protocol/user-events-proxy.h" #include "android/protocol/core-commands-proxy.h" #include "android/protocol/ui-commands-impl.h" +#include "android/qemulator.h" -#ifdef CONFIG_MEMCHECK -#include "memcheck/memcheck.h" -#endif // CONFIG_MEMCHECK - -#include <unistd.h> -#include <fcntl.h> -#include <signal.h> -#include <time.h> -#include <errno.h> -#include <sys/time.h> -#include <zlib.h> - -/* Needed early for CONFIG_BSD etc. */ -#include "config-host.h" - -#ifndef _WIN32 -#include <libgen.h> -#include <pwd.h> -#include <sys/times.h> -#include <sys/wait.h> -#include <termios.h> -#include <sys/mman.h> -#include <sys/ioctl.h> -#include <sys/resource.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <net/if.h> -#if defined(__NetBSD__) -#include <net/if_tap.h> -#endif -#ifdef __linux__ -#include <linux/if_tun.h> -#endif -#include <arpa/inet.h> -#include <dirent.h> -#include <netdb.h> -#include <sys/select.h> -#ifdef CONFIG_BSD -#include <sys/stat.h> -#if defined(__FreeBSD__) || defined(__DragonFly__) -#include <libutil.h> -#else -#include <util.h> -#endif -#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) -#include <freebsd/stdlib.h> -#else -#ifdef __linux__ -#include <pty.h> -#include <malloc.h> -#include <linux/rtc.h> - -/* For the benefit of older linux systems which don't supply it, - we use a local copy of hpet.h. */ -/* #include <linux/hpet.h> */ -#include "hpet.h" - -#include <linux/ppdev.h> -#include <linux/parport.h> -#endif -#ifdef __sun__ -#include <sys/stat.h> -#include <sys/ethernet.h> -#include <sys/sockio.h> -#include <netinet/arp.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/ip_icmp.h> // must come after ip.h -#include <netinet/udp.h> -#include <netinet/tcp.h> -#include <net/if.h> -#include <syslog.h> -#include <stropts.h> -#endif -#endif -#endif - -#if defined(__OpenBSD__) -#include <util.h> -#endif - -#if defined(CONFIG_VDE) -#include <libvdeplug.h> -#endif - -#ifdef _WIN32 -#include <windows.h> -#include <malloc.h> -#include <sys/timeb.h> -#include <mmsystem.h> -#define getopt_long_only getopt_long -#define memalign(align, size) malloc(size) -#endif - - -#ifdef CONFIG_COCOA -#undef main -#define main qemu_main -#endif /* CONFIG_COCOA */ - -#include "qemu-timer.h" -#include "qemu-char.h" - -#if defined(CONFIG_SKINS) && !defined(CONFIG_STANDALONE_CORE) -#undef main -#define main qemu_main -#endif - -#include "qemu_socket.h" - -static const char *data_dir; - -static DisplayState *display_state; -DisplayType display_type = DT_DEFAULT; -const char* keyboard_layout = NULL; -int64_t ticks_per_sec; -int vm_running; -static int autostart; -QEMUClock *rtc_clock; -#ifdef TARGET_SPARC -int graphic_width = 1024; -int graphic_height = 768; -int graphic_depth = 8; -#else -int graphic_width = 800; -int graphic_height = 600; -int graphic_depth = 15; -#endif -static int full_screen = 0; -#ifdef CONFIG_SDL -static int no_frame = 0; -#endif -int no_quit = 0; -int smp_cpus = 1; -const char *vnc_display; -int acpi_enabled = 1; -int no_reboot = 0; -int no_shutdown = 0; -int cursor_hide = 1; -int graphic_rotate = 0; -#ifndef _WIN32 -int daemonize = 0; -#endif -#ifdef TARGET_ARM -int old_param = 0; -#endif -const char *qemu_name; -int alt_grab = 0; - -static QEMUTimer *nographic_timer; - -uint8_t qemu_uuid[16]; - -extern int android_display_width; -extern int android_display_height; -extern int android_display_bpp; - -extern void dprint( const char* format, ... ); - -#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) - -/* compute with 96 bit intermediate result: (a*b)/c */ -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) -{ - union { - uint64_t ll; - struct { -#ifdef HOST_WORDS_BIGENDIAN - uint32_t high, low; -#else - uint32_t low, high; -#endif - } l; - } u, res; - uint64_t rl, rh; - - u.ll = a; - rl = (uint64_t)u.l.low * (uint64_t)b; - rh = (uint64_t)u.l.high * (uint64_t)b; - rh += (rl >> 32); - res.l.high = rh / c; - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; - return res.ll; -} +static Looper* mainLooper; /***********************************************************/ /* I/O handling */ typedef struct IOHandlerRecord { - int fd; - IOCanReadHandler *fd_read_poll; - IOHandler *fd_read; - IOHandler *fd_write; - int deleted; - void *opaque; - /* temporary data */ - struct pollfd *ufd; + LoopIo io[1]; + IOHandler* fd_read; + IOHandler* fd_write; + int running; + int deleted; + void* opaque; struct IOHandlerRecord *next; } IOHandlerRecord; static IOHandlerRecord *first_io_handler; -/* XXX: fd_read_poll should be suppressed, but an API change is - necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) +static void ioh_callback(void* opaque, int fd, unsigned events) +{ + IOHandlerRecord* ioh = opaque; + ioh->running = 1; + if ((events & LOOP_IO_READ) != 0) { + ioh->fd_read(ioh->opaque); + } + if (!ioh->deleted && (events & LOOP_IO_WRITE) != 0) { + ioh->fd_write(ioh->opaque); + } + ioh->running = 0; + if (ioh->deleted) { + loopIo_done(ioh->io); + free(ioh); + } +} + +int qemu_set_fd_handler(int fd, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) { IOHandlerRecord **pioh, *ioh; @@ -266,175 +97,76 @@ int qemu_set_fd_handler2(int fd, for(;;) { ioh = *pioh; if (ioh == NULL) - break; - if (ioh->fd == fd) { - ioh->deleted = 1; + return 0; + if (ioh->io->fd == fd) { break; } pioh = &ioh->next; } + if (ioh->running) { + ioh->deleted = 1; + } else { + *pioh = ioh->next; + loopIo_done(ioh->io); + free(ioh); + } } else { for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (ioh->fd == fd) + if (ioh->io->fd == fd) goto found; } ANEW0(ioh); ioh->next = first_io_handler; first_io_handler = ioh; + loopIo_init(ioh->io, mainLooper, fd, ioh_callback, ioh); found: - ioh->fd = fd; - ioh->fd_read_poll = fd_read_poll; - ioh->fd_read = fd_read; + ioh->fd_read = fd_read; ioh->fd_write = fd_write; - ioh->opaque = opaque; - ioh->deleted = 0; + ioh->opaque = opaque; + + if (fd_read != NULL) + loopIo_wantRead(ioh->io); + else + loopIo_dontWantRead(ioh->io); + + if (fd_write != NULL) + loopIo_wantWrite(ioh->io); + else + loopIo_dontWantWrite(ioh->io); } return 0; } -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) -{ - return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); -} - /***********************************************************/ /* main execution loop */ +static LoopTimer gui_timer[1]; + static void gui_update(void *opaque) { - uint64_t interval = GUI_REFRESH_INTERVAL; - DisplayState *ds = opaque; - DisplayChangeListener *dcl = ds->listeners; - - dpy_refresh(ds); - - while (dcl != NULL) { - if (dcl->gui_timer_interval && - dcl->gui_timer_interval < interval) - interval = dcl->gui_timer_interval; - dcl = dcl->next; - } - qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock(rt_clock)); + LoopTimer* timer = opaque; + qframebuffer_pulse(); + loopTimer_startRelative(timer, GUI_REFRESH_INTERVAL); } -static void nographic_update(void *opaque) +static void init_gui_timer(Looper* looper) { - uint64_t interval = GUI_REFRESH_INTERVAL; - - qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock)); + loopTimer_init(gui_timer, looper, gui_update, gui_timer); + loopTimer_startRelative(gui_timer, 0); + qframebuffer_invalidate_all(); } -static int shutdown_requested = 0; - +/* Called from qemulator.c */ void qemu_system_shutdown_request(void) { - shutdown_requested = 1; -} - - - -static int qemu_event_init(void) -{ - return 0; -} - -static int qemu_init_main_loop(void) -{ - return qemu_event_init(); -} - -#define qemu_mutex_lock_iothread() do { } while (0) -#define qemu_mutex_unlock_iothread() do { } while (0) - - -#ifdef _WIN32 -static void host_main_loop_wait(int *timeout) -{ -} -#else -static void host_main_loop_wait(int *timeout) -{ -} -#endif - -void main_loop_wait(int timeout) -{ - IOHandlerRecord *ioh; - fd_set rfds, wfds, xfds; - int ret, nfds; - struct timeval tv; - - host_main_loop_wait(&timeout); - - /* poll any events */ - /* XXX: separate device handlers from system ones */ - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (ioh->deleted) - continue; - if (ioh->fd_read && - (!ioh->fd_read_poll || - ioh->fd_read_poll(ioh->opaque) != 0)) { - FD_SET(ioh->fd, &rfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - if (ioh->fd_write) { - FD_SET(ioh->fd, &wfds); - if (ioh->fd > nfds) - nfds = ioh->fd; - } - } - - tv.tv_sec = timeout / 1000; - tv.tv_usec = (timeout % 1000) * 1000; - - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); - if (ret > 0) { - IOHandlerRecord **pioh; - - for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { - ioh->fd_read(ioh->opaque); - } - if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { - ioh->fd_write(ioh->opaque); - } - } - - /* remove deleted IO handlers */ - pioh = &first_io_handler; - while (*pioh) { - ioh = *pioh; - if (ioh->deleted) { - *pioh = ioh->next; - AFREE(ioh); - } else - pioh = &ioh->next; - } - } - - qemu_run_all_timers(); -} - -static void main_loop(void) -{ - while (!shutdown_requested) { - main_loop_wait(qemu_calculate_timeout()); - } + looper_forceQuit(mainLooper); } #ifndef _WIN32 static void termsig_handler(int signal) { - /* qemu_system_shutdown_request(); */ + qemu_system_shutdown_request(); } static void sigchld_handler(int signal) @@ -459,40 +191,6 @@ static void sighandler_setup(void) #endif -#define QEMU_FILE_TYPE_BIOS 0 -#define QEMU_FILE_TYPE_KEYMAP 1 - -char *qemu_find_file(int type, const char *name) -{ - int len; - const char *subdir; - char *buf; - - /* If name contains path separators then try it as a straight path. */ - if ((strchr(name, '/') || strchr(name, '\\')) - && access(name, R_OK) == 0) { - return strdup(name); - } - switch (type) { - case QEMU_FILE_TYPE_BIOS: - subdir = ""; - break; - case QEMU_FILE_TYPE_KEYMAP: - subdir = "keymaps/"; - break; - default: - abort(); - } - len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2; - buf = android_alloc0(len); - snprintf(buf, len, "%s/%s%s", data_dir, subdir, name); - if (access(buf, R_OK)) { - AFREE(buf); - return NULL; - } - return buf; -} - #ifdef _WIN32 static BOOL WINAPI qemu_ctrl_handler(DWORD type) { @@ -501,13 +199,8 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type) } #endif -int main(int argc, char **argv, char **envp) +int qemu_main(int argc, char **argv, char **envp) { - DisplayState *ds; - DisplayChangeListener *dcl; - - init_clocks(); - #ifndef _WIN32 { struct sigaction act; @@ -538,18 +231,6 @@ int main(int argc, char **argv, char **envp) } #endif - autostart= 1; - - if (qemu_init_main_loop()) { - fprintf(stderr, "qemu_init_main_loop failed\n"); - exit(1); - } - - if (init_timer_alarm() < 0) { - fprintf(stderr, "could not initialize alarm timer\n"); - exit(1); - } - #ifdef _WIN32 socket_init(); #endif @@ -559,42 +240,23 @@ int main(int argc, char **argv, char **envp) sighandler_setup(); #endif - /* just use the first displaystate for the moment */ - ds = display_state = get_displaystate(); - - if (display_type == DT_DEFAULT) { - display_type = DT_SDL; - } - + mainLooper = looper_newGeneric(); - switch (display_type) { - case DT_NOGRAPHIC: - break; - case DT_SDL: - sdl_display_init(ds, full_screen, no_frame); - break; - default: - break; - } - dpy_resize(ds); + /* Register a timer to call qframebuffer_pulse periodically */ + init_gui_timer(mainLooper); - dcl = ds->listeners; - while (dcl != NULL) { - if (dcl->dpy_refresh != NULL) { - ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds); - qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock)); - } - dcl = dcl->next; + // Connect to the core's framebuffer service + if (implFb_create(attachUiImpl_get_console_socket(), "-raw", + qemulator_get_first_framebuffer(qemulator_get()))) { + return -1; } - if (display_type == DT_NOGRAPHIC || display_type == DT_VNC) { - nographic_timer = qemu_new_timer(rt_clock, nographic_update, NULL); - qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock)); + // Attach the recepient of UI commands. + if (uiCmdImpl_create(attachUiImpl_get_console_socket())) { + return -1; } - //qemu_chr_initial_reset(); - - main_loop(); + looper_run(mainLooper); implFb_destroy(); userEventsProxy_destroy(); @@ -602,6 +264,5 @@ int main(int argc, char **argv, char **envp) uiCmdImpl_destroy(); attachUiImpl_destroy(); - quit_timers(); return 0; } |