2012-07-26 38 views
1

我試圖從一個線程繪製成開羅像面和我得到斷言錯誤:多線程,gtk3和開羅:在開羅表面拉絲

gtk_mt: /build/buildd/cairo-1.10.2/src/cairo-surface.c:385: _cairo_surface_begin_modification: Assertion `! surface->finished' failed. Aborted (core dumped)

這是我的計劃:

#include <stdlib.h> 
#include <gtk/gtk.h> 
#include <gdk/gdk.h> 
#include <cairo.h> 

#define IMAGE_WIDTH 320 
#define IMAGE_HEIGHT 200 

gpointer thread_func(gpointer data) 
{ 
    int x, y; 
    unsigned char rgb_r, rgb_g, rgb_b; 
    GtkWidget *widget = (GtkWidget*)data; 
    GdkWindow *window; 
    cairo_t *cr; 
    cairo_format_t format = CAIRO_FORMAT_ARGB32; 
    cairo_surface_t *surface; 
    unsigned char *image_data, *rgbptr; 
    int width = IMAGE_WIDTH; 
    int height = IMAGE_HEIGHT; 
    int stride; 

    gdk_threads_enter(); 
    stride = cairo_format_stride_for_width(format, width); 
    image_data = malloc(stride * height); 
    surface = cairo_image_surface_create_for_data(image_data, format, width, height, stride); 
    window = gtk_widget_get_window(widget); 
    cr = gdk_cairo_create(window); 
    gdk_threads_leave(); 

    while(1) 
    { 
     rgb_r = random() & 0xff; 
     rgb_g = random() & 0xff; 
     rgb_b = random() & 0xff; 

     for(y = 0; y < height; ++y) 
     { 
      rgbptr = &image_data[y * stride]; 
      if(!(random() & 0x3f)) 
      { 
       rgb_r = random() & 0xff; 
       rgb_g = random() & 0xff; 
       rgb_b = random() & 0xff; 
      }   

      for(x = 0; x < width; ++x) 
      { 
       *rgbptr++ = rgb_r; *rgbptr++ = rgb_g; *rgbptr++ = rgb_b; 
       *rgbptr = 0xff; 
      } 
     } 

     gdk_threads_enter(); 
     cairo_set_source_surface(cr, surface, 0, 0); 
     cairo_paint(cr); 
     gdk_threads_leave(); 
     sleep(2); 
    } 

    return(NULL); 
} 

int main(int argc, char **argv) 
{ 
    GtkWidget *window; 
    GtkWidget *darea; 
    GThread *thread; 
    GError *error = NULL; 

    if(! g_thread_supported()) 
     g_thread_init(NULL); 
    gdk_threads_init(); 

    gdk_threads_enter(); 
    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    darea = gtk_drawing_area_new(); 
    gtk_widget_set_size_request(darea, IMAGE_WIDTH, IMAGE_HEIGHT); 
    gtk_container_add(GTK_CONTAINER (window), darea); 
    gtk_widget_show_all (window); 

    thread = g_thread_create(thread_func, (gpointer)darea, FALSE, &error); 
    if(!thread) 
    { 
     g_print("Error: %s\n", error->message); 
     return(-1); 
    } 

    gtk_main(); 
    gdk_threads_leave(); 

    return(0); 
} 

任何幫助表示讚賞!

+0

嗯,看起來像是stackoverflow不能正確縮進......只是假裝「thread =」這一行以及「return」行之間的所有內容都被縮進了兩個空格。 – 2012-07-26 11:56:14

回答

1

好吧,似乎不可能重用surface和cr。我將這些調用移到了循環的gdk_threads_enter() - 部分中,然後工作。 (另外,有一個錯誤,我通過執行* rgbptr = 0xff寫入A通道,我忘記了指針之後的內容。)

+1

問題是,其他線程仍然需要使用它,而您的窗口(cairo_surface_finish())則完成cairo表面(cairo_surface_finish())。只要調用cairo_surface_finish(),表面就不能再使用了。 – 2012-07-27 16:07:10