Re: gtk_widget_queue_draw_area much slower in gtk3 than gtk3



 Emmanuele Bassi twisted the bytes to say:

Hi Emmanuele,


 Emmanuele> On 30 March 2015 at 18:56, dmg <dmg uvic ca> wrote:

On Mon, Mar 30, 2015 at 5:22 AM, Emmanuele Bassi <ebassi gmail com> wrote:

Motion events are compressed in GTK+; they get collected and pushed to
the application code once per frame, because you cannot obviously
paint any faster than what your display can show, and because the vast
majority of applications do not draw content in response to fine event
delivery.

Please see this: https://github.com/xournalpp/xournalpp/issues/109
it exemplifies the problem we have from gtk2 to gtk3.

I did a small test. I tried to draw a curve during 1 second. And the
results seem to support this as the reason.

in the motion notify event our logic is the following:

1- We gather the coordinates of the new point
2- Using cairo we draw the new line segment directly onto the canvas

 Emmanuele> What does drawing "directly onto the canvas" mean, in this context?


I have modified the example program to draw on the screen using
cairo. It mimics what we do in Xournal regarding drawing (except that we
don't use a callback).

https://github.com/dmgerman/testDrawing/blob/master/drawing.c

I have made it such that it uses both gtk_widget_queue_draw and it does
not.

Compile and run. If you press the middle button it will switch from
not using gtk_widget_queue_draw to using gtk_widget_queue_draw. I use
different colors for different segments. See 

http://turingmachine.org/~dmg/temp/test_Drawing.png 

I am using two methods to refresh the screen:

1. gtk_widget_queue_draw (see line 132)
2. a timer callback. See line 69. 


There are things i don't quite understand.

1. Why can the timer handler refresh the screen without a call to
   gtk_widget_queue_draw

2. How can I achieve the same result inside draw_line to avoid the timer
   callback without using gtk_widget_queue_draw?

3. What is the proper way to use gdk_window_set_event_compression:

  gdk_window_set_event_compression (gtk_widget_get_parent_window (window), FALSE);

I get: 

(drawing:22296): Gdk-CRITICAL **: gdk_window_set_event_compression: assertion 'GDK_IS_WINDOW (window)' failed

I have tried different widgets and I get the same error.


Let me answer the rest of your questions:

3- We then compute the area that the new segment occupies
4- We call gtk_widget_queue_draw_area synchronously

 Emmanuele> What does "call gtk_widget_queue_draw_area" synchronously mean, in this context?

We call it inside the even handler for motion notify. Every time we draw
a line segment, we call it to refresh the screen (the person writing
needs to have the screen refreshed every 50ms or so to not feel a lag).


When 4 is removed, sampling increases significantly and we no longer
have the problem but now the screen is not refreshed immediately. It
is random when the refresh is.

 Emmanuele> That sounds… impressively wrong.

:) See my test.

 Emmanuele> Are you getting a cairo_t* from the GdkWindow used by the widget and
 Emmanuele> just drawing on it?

Yes.

 Emmanuele> Are you drawing on an image surface and then using the image surface
 Emmanuele> as the source for the cairo_t* in the GtkWidget::draw signal handler?

No. This will sound like a hack, but this is what we need to do:

1. We keep a data structure for the polygons drawn by the user. In the
   draw  callback we redraw the surface from the data structures.

2. When the user is drawing a line we directly draw in the surface as
   the user is adding segments, one segment at a time. These segments
   are then overwritten by the draw callback. 
   
   When the user lifts the pen we invalidate the region of the polygon
   being drawn, and issue a gtk_widget_queue_draw_area. This is ok,
   because the user does not need as immediate feedback as when drawing
   from the line.

   The way I test this is by drawing the segments in grey. And then when
   responding to "draw" I draw them in black. This way I can see that
   the segments are drawn as expected, and then replaced with the proper
   polygon once the stroke finishes.


 Emmanuele> Are you using a thread to avoid blocking the UI from the event handler
 Emmanuele> while you draw on an offscreen surface?

no.

It seems to me that the problem is the that we call
gtk_widget_queue_draw_area every time we have a segment.

 Emmanuele> No, that's definitely not the problem.

Please run the test. I am very grateful you are helping us.

--
Daniel M. German                  "If all mankind minus one,
                                   were of one opinion, and only
                                   one person were of the contrary opinion,
                                   mankind would be no more justified
                                   in silencing that one person,
                                   than he, if he had the power,
    John Stuart Mill ->            would be justified in silencing mankind."
http://turingmachine.org/
http://silvernegative.com/
dmg (at) uvic (dot) ca
replace (at) with @ and (dot) with .

 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]