Hi; On 24 March 2015 at 14:43, Sergei Naumov <vo...@rambler.ru> wrote:
>> The idiomatic way is to create a surface either using >> gdk_window_create_similar_surface(), or >> gdk_window_create_similar_image_surface(), which will take care of >> giving you the most appropriate surface for the platform you're using. >> >> You can usually do that from the main thread context, after realizing >> the widget in order to obtain its GdkWindow; you keep the surface >> inside your widget instance data, and draw on it from the thread you >> create for rendering. At the end of the thread, you queue a redraw on >> the widget, and then you use the surface as the source for rendering >> on the cairo_t* that the ::draw signal gives to you. > > > Do I understand this correctly that what you are saying is as follows? > > 1) create a surface in the main gtk thread You can only use the GDK and GTK+ API from the same thread that called gtk_init/gtk_main, so if you want to use gdk_window_create_similar_surface() you will have to call the function from the main thread; you can create a Cairo image surface from the thread you spawn for drawing, and then pass the surface to the main thread, but in general it's easier if only a single thread is responsible for creating and destroying resources. > 2) make this surface global across threads No. You attach this drawing surface to the instance of your widget, and you pass your widget as a pointer to the drawing thread. You will need the widget pointer in any case, because you have to schedule a widget redraw from the thread by using something like gdk_threads_add_idle() or g_main_context_invoke(). > 3) draw whatever on the surface From the thread, yes. As long as only one thread at a time accesses the Cairo surface, you should be safe. > 4) bind something to a "draw" signal that redraws That's the only way to make it work. You *cannot* use GTK API from different threads. In short: 1. create the widget instance 2. realize it 3. create a similar Cairo surface from the GdkWindow of the widget 4. store Cairo surface on the widget instance; you can use a subclass or g_object_set_data(), with a preference for the former 5. connect a callback to/override the class closure of the ::draw signal a. in the draw signal handler, you take the surface and use it a source to draw on the cairo_t given to you; you can use a boolean flag to know whether or not the contents of the surface are okay to use 6. fire off a thread, and pass the pointer to widget to the thread function 7. inside the thread function, draw on the surface 8. at the end of the thread, schedule a redraw in the main thread a. use gdk_threads_add_idle() with a callback and pass the widget pointer as the data b. from within the callback, set the boolean flag that tells the ::draw callback to use the surface as a source, and call gtk_widget_queue_draw() It's safe to draw on Cairo surfaces from different threads, assuming only a thread at a time does it; it's not safe to use GTK API from different threads, though. That's why you can create a surface from the main thread, and draw on it in a separate thread — as long as you ensure that all the operations involving GTK happen on the main thread. Ciao, Emmanuele. -- https://www.bassi.io [@] ebassi [@gmail.com] _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list