gdk double buffering



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I have some questions/ideas regarding the "speed" of GDK/gtk. 


Double buffering Usage
- ----------------------

Like Owen Taylor said in:
http://www.gtk.org/~otaylor/gtk/2.0/gdk-drawing.html
part of the gtk speed problem is the fact not all widgets are draw at once. 
GDK has functions for double buffering ( begin_paint() / end_paint() ) but 
this will not solve the problem. This because this will buffer a x11 window. 
On most expose events however, it's not enough to redraw one x11 window. But 
several expose events will come in back to back. These individual expose 
events can be double buffered. But if the time between the events is to large 
that will also be seen as "flicker". An example of what happens now:

- -- Gtk Application --
  expose event1 
	1 buffer is created 
	2 widget drawn to buffer 
	3 buffer blitted

  expose event2 
	1 buffer is created 
	2 widget drawn to buffer 
	3 buffer blitted

   ...

This can be improved by:

- -- GTK Application --
  expose event1:
    1 buffer is created
    2 widget drawn to buffer
    3 buffer pushed on blit stack

  expose event2:
    1 buffer is created
    2 widget drawn to buffer
    3 buffer pushed on blit stack
  
  ...			

  ; all	widgets drawn
  blit all buffers on stack to screen

This will not solve all problems. This is because X can't guarantee that all 
operations happen in one frame. This is large problem. Because how hard the 
widget set library tries, it can't ever guarantee that a operation is flicker 
free. 

For example, when the user shades a window. 2 apps might become visible. These 
apps have to redraw all windows. But even if both apps stack all drawing 
operations. It might happen that app1 is several msecs earlier than app2. 
That way, when one app redraws it's window, the other app might still be busy 
filling it's draw stack. That way, one window is redraw, while the other is 
not. Leaving the user with a screen that is half updated and half not. 

What we want is that operations are atomic. We know atomic operations from 
databases. Atomic operations in databases are handled with transactions. So 
handling events in X should be done in a way of transactions. Here is how i 
see it:

 
- -- XFree --
	struct TBACKBUFFER {
		list 		/* list containing all draw operations */
		locked 		/* is the buffer still in a transaction */
		draw		/* is the buffer drawn yet */
	} back_buffer;

	begin_transaction()	
	{
		back_buffer->locked = true
		back_buffer->drawn = FAlSE
	}
		

	vsync()
	{
		/* vsync should be called on a vsync */

		/* we still need to draw the back buffer */
		if(back_buffer->drawn == false) {

			/* transaction is finished so it's safe to draw */
			if(back_buffer->locked == true) {
				do all operations in back_buffer->list

				back_buffer->draw = TRUE;
				clear(back_buffer->list);			
			}
				

		}
	}


	transaction_end()
	{
		/* we are done here */
		back_buffer->locked = false;
	}

	User clicks button

	begin_transaction();		

		for window<-window_list[] do
			expose_event(window); /* All draw operations will be appended to list */

	/* Ok done, on next vsync all operations will be drawn */
	end_transaction(); 	

Problem with this approach is that if a program does not respond to a expose 
event the whole transaction will stale. I am sure there are ways to solve 
this. And the above example is just an idea not a concept. 

Double buffering implementation
- ------------------------------- 		
	
There are several ways to implement buffering:


- - Create pixmap and draw to pixmap. This is how gtk does it at the moment. It 
would be more efficient to create a pixmap the size of the expose event. And 
only draw the part of the widget that needs te be redrawn. 

- - Save the operations. It is also possible to save the operations that need to 
be drawn. e.g. save the fact that a line needs to be drawn from 
(0,0)-(100,100). And do the draw operation later. 

I don't know which one is faster or smaller in memory usage. But at first 
sight it seems to me the second method uses less memory. 

Transactions using a deamon
- ---------------------------

It would be possible to create the transactions described above using a deamon 
that sends all X operations from gtk apps to X. You would need a special 
version of gdk that communicates with the daemon. It would be cleaner to 
implement it in X, but it's just a thought. 


Ok, that's about it. I hope i'm not talking (too much) out of my arse. I don't 
really like the way widget sets communicate with X these days. I always think 
that the applications "fall apart" when doing a redraw. It doesn't feel 
"solid". 

Wouter van Kleunen


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE+byLdw4uuzvY55gsRAkELAJ9YIflbJ1mgR9sN/20WqoN1BcH11QCeKN3u
JnJj66gxAWhoAZ8MHIewN4k=
=3zuS
-----END PGP SIGNATURE-----




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