aboutsummaryrefslogtreecommitdiffstats
path: root/android
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-02-02 12:12:53 -0800
committerAndroid Code Review <code-review@android.com>2011-02-02 12:12:53 -0800
commitd6eda1d7b357746ad8d9a4c80dc0235ef56c40e0 (patch)
treeb669e7b99c01bd8aafd2079321c8cb80302454e0 /android
parentce747472342237e882369e486254684ab7708362 (diff)
parent07db34976ba1dd045a51c4ab2c7f52479cddcc57 (diff)
downloadexternal_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.
Diffstat (limited to 'android')
-rw-r--r--android/console.c46
-rw-r--r--android/display-core.c124
-rw-r--r--android/display-core.h34
-rw-r--r--android/framebuffer.c9
-rw-r--r--android/framebuffer.h9
-rw-r--r--android/looper-generic.c2
-rw-r--r--android/main-common.c2
-rw-r--r--android/main-ui.c11
-rw-r--r--android/protocol/fb-updates-proxy.c70
-rw-r--r--android/protocol/fb-updates-proxy.h13
-rw-r--r--android/protocol/ui-commands-impl.c4
-rw-r--r--android/qemulator.c6
12 files changed, 109 insertions, 221 deletions
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