From 8822b946f6bdca93cb765c6d805ed32421dd8933 Mon Sep 17 00:00:00 2001 From: rodin Date: Fri, 29 Jan 2010 21:13:34 +0000 Subject: [PATCH] Getting cryptic error message: lt-chimara: Fatal IO error 11 (Resource temporarily unavailable) on X server :0.0 why?? --- libchimara/graphics.c | 133 +++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 47 deletions(-) diff --git a/libchimara/graphics.c b/libchimara/graphics.c index f94b90c..fda5ad6 100644 --- a/libchimara/graphics.c +++ b/libchimara/graphics.c @@ -6,8 +6,10 @@ extern GPrivate *glk_data_key; void on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info); +void on_pixbuf_closed(GdkPixbufLoader *loader, gpointer data); static gboolean size_determined; +static gboolean image_loaded; glui32 glk_image_get_info(glui32 image, glui32 *width, glui32 *height) @@ -61,11 +63,12 @@ glk_image_get_info(glui32 image, glui32 *width, glui32 *height) g_free(buffer); /* Determine the image dimensions */ - if(!size_determined) { - WARNING("Cannot read image size"); - g_free(info); - return FALSE; + g_mutex_lock(glk_data->resource_lock); + while(!size_determined) { + /* Wait for the PixbufLoader to finish reading the image size */ + g_cond_wait(glk_data->resource_info_available, glk_data->resource_lock); } + g_mutex_unlock(glk_data->resource_lock); if(width != NULL) *width = info->width; @@ -79,52 +82,21 @@ glk_image_get_info(glui32 image, glui32 *width, glui32 *height) void on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info) { + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + + g_mutex_lock(glk_data->resource_lock); info->width = width; info->height = height; size_determined = TRUE; -} - -/*** Called when the graphics window is resized. Resize the backing pixmap if necessary ***/ -void -on_graphics_size_allocate(GtkWidget *widget, GtkAllocation *allocation, winid_t win) -{ - printf("allocate to: %dx%d\n", allocation->width, allocation->height); - GdkPixmap *oldmap; - gtk_image_get_pixmap( GTK_IMAGE(widget), &oldmap, NULL ); - gint oldwidth = 0; - gint oldheight = 0; - - /* Determine whether a pixmap exists with the correct size */ - gboolean needs_resize = FALSE; - if(oldmap == NULL) - needs_resize = TRUE; - else { - gdk_drawable_get_size( GDK_DRAWABLE(oldmap), &oldwidth, &oldheight ); - if(oldwidth != allocation->width || oldheight != allocation->height) - needs_resize = TRUE; - } - - if(needs_resize) { - printf("needs resize\n"); - /* Create a new pixmap */ - GdkPixmap *newmap = gdk_pixmap_new(widget->window, allocation->width, allocation->height, -1); - gdk_draw_rectangle( GDK_DRAWABLE(newmap), widget->style->white_gc, TRUE, 0, 0, allocation->width, allocation->height); - - /* Copy the contents of the old pixmap */ - if(oldmap != NULL) - gdk_draw_drawable( GDK_DRAWABLE(newmap), widget->style->white_gc, GDK_DRAWABLE(oldmap), 0, 0, 0, 0, oldwidth, oldheight); - - /* Use the new pixmap */ - gtk_image_set_from_pixmap( GTK_IMAGE(widget), newmap, NULL ); - g_object_unref(newmap); - } + g_cond_broadcast(glk_data->resource_info_available); + g_mutex_unlock(glk_data->resource_lock); } glui32 -glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) { +glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) +{ VALID_WINDOW(win, return FALSE); g_return_val_if_fail(win->type == wintype_Graphics, FALSE); - printf("Drawing image %d\n", (int)image); ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); giblorb_result_t res; @@ -144,10 +116,12 @@ glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) { /* Load the resource */ GdkPixbufLoader *loader = gdk_pixbuf_loader_new(); + g_signal_connect( loader, "closed", G_CALLBACK(on_pixbuf_closed), NULL ); glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start); buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) ); guint32 total_read = 0; + image_loaded = FALSE; while(total_read < res.length) { guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE); @@ -161,27 +135,42 @@ glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) { total_read += num_read; } - printf("Loading done\n"); + + if( !gdk_pixbuf_loader_close(loader, &pixbuf_error) ) { + WARNING_S("Cannot read image", pixbuf_error->message); + giblorb_unload_chunk(glk_data->resource_map, image); + g_free(buffer); + return FALSE; + } + + if(!image_loaded) { + /* Wait for the PixbufLoader to finish loading the image */ + g_mutex_lock(glk_data->resource_lock); + while(!image_loaded) { + g_cond_wait(glk_data->resource_loaded, glk_data->resource_lock); + } + g_mutex_unlock(glk_data->resource_lock); + } + giblorb_unload_chunk(glk_data->resource_map, image); g_free(buffer); gtk_image_get_pixmap( GTK_IMAGE(win->widget), &canvas, NULL ); if(canvas == NULL) { WARNING("Could not get pixmap"); - gdk_pixbuf_loader_close(loader, &pixbuf_error); return FALSE; } GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); if(pixbuf == NULL) { WARNING("Could not read image"); - gdk_pixbuf_loader_close(loader, &pixbuf_error); return FALSE; } - // TODO: FIX hang? + printf("Drawing image %d\n", (int)image); + + // TODO: fix hang gdk_draw_pixbuf( GDK_DRAWABLE(canvas), NULL, pixbuf, 0, 0, val1, val2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0 ); - gdk_pixbuf_loader_close(loader, &pixbuf_error); /* Update the screen */ gtk_widget_queue_draw(win->widget); @@ -189,6 +178,19 @@ glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) { return TRUE; } +void +on_pixbuf_closed(GdkPixbufLoader *loader, gpointer data) +{ + printf("closed\n"); + ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key); + + g_mutex_lock(glk_data->resource_lock); + image_loaded = TRUE; + g_cond_broadcast(glk_data->resource_loaded); + g_mutex_unlock(glk_data->resource_lock); +} + + glui32 glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2, glui32 width, glui32 height) { @@ -222,3 +224,40 @@ glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 void glk_window_flow_break(winid_t win) { } + +/*** Called when the graphics window is resized. Resize the backing pixmap if necessary ***/ +void +on_graphics_size_allocate(GtkWidget *widget, GtkAllocation *allocation, winid_t win) +{ + printf("allocate to: %dx%d\n", allocation->width, allocation->height); + GdkPixmap *oldmap; + gtk_image_get_pixmap( GTK_IMAGE(widget), &oldmap, NULL ); + gint oldwidth = 0; + gint oldheight = 0; + + /* Determine whether a pixmap exists with the correct size */ + gboolean needs_resize = FALSE; + if(oldmap == NULL) + needs_resize = TRUE; + else { + gdk_drawable_get_size( GDK_DRAWABLE(oldmap), &oldwidth, &oldheight ); + if(oldwidth != allocation->width || oldheight != allocation->height) + needs_resize = TRUE; + } + + if(needs_resize) { + printf("needs resize\n"); + /* Create a new pixmap */ + GdkPixmap *newmap = gdk_pixmap_new(widget->window, allocation->width, allocation->height, -1); + gdk_draw_rectangle( GDK_DRAWABLE(newmap), widget->style->white_gc, TRUE, 0, 0, allocation->width, allocation->height); + + /* Copy the contents of the old pixmap */ + if(oldmap != NULL) + gdk_draw_drawable( GDK_DRAWABLE(newmap), widget->style->white_gc, GDK_DRAWABLE(oldmap), 0, 0, 0, 0, oldwidth, oldheight); + + /* Use the new pixmap */ + gtk_image_set_from_pixmap( GTK_IMAGE(widget), newmap, NULL ); + g_object_unref(newmap); + } +} + -- 2.30.2