Re: [Mono-winforms-list] Scrolling performance isues

2008-08-11 Thread Carlos Alberto Cortez

El dom, 10-08-2008 a las 18:55 -0700, Chris Toshok escribió:
 Nice. That look pretty good, with the only issue being performance  
 over an X connection with high latency - it'll block all UI until the  
 redraws complete.


I thought that was exactly we wanted to do ;-)

 
 That said, it's definitely better than what we have now :)

Ok to commit for now? Specially for 2.0 :-)

Carlos.

___
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list


Re: [Mono-winforms-list] Scrolling performance isues

2008-08-10 Thread Chris Toshok
Nice. That look pretty good, with the only issue being performance  
over an X connection with high latency - it'll block all UI until the  
redraws complete.

That said, it's definitely better than what we have now :)

toshok

On Aug 7, 2008, at 12:17 PM, Carlos Alberto Cortez [EMAIL PROTECTED] 
  wrote:


 Hey Chris

 Comments below.


 I'm also not sure flushing the paint queue before doing the XCopyArea
 (suggestion 1 above) will be enough either.  It's very easy to  
 imagine
 a scenario where you're scrolling and we do another ScrollWindow
 before all the GraphicsExpose events have been received.  We really  
 do
 need to block things somehow.  And it'll be more than just blocking
 the message queue - we'll need to actually stop the thread if there's
 a call to ScrollWindow (or anything else that ends up copying) until
 the GraphicsExposes have been handled.

 I went and began to review our code and wondering how to do it the
 proper way - then went to Gtk+ scrolling code once more, and then  
 could
 see that the gtk textbox was handling the scroll itself (it seems the
 algorithm is what's called 'smooth scrolling', not sure).

 The idea is that after each request to scroll, they call XIfEvent to
 wait for GraphicsExpose/NoExpose events on the scrolled window,  
 blocking
 the thread until they get one of them (so you can invalidate or exit  
 the
 loop), and adding a expose operation on the window.

 I implemented this today for our implementation and it seems to work
 just fine, and it seems it follows your idea ;-)

 Take a look and tell what you think.
 Carlos.

 PD - The patch is a test, so needs to be beautified still ;-) But  
 should
 work.
 xplatx11-changes.patch
___
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list


Re: [Mono-winforms-list] Scrolling performance isues

2008-08-07 Thread Carlos Alberto Cortez

Hey Chris

Comments below.

 
 I'm also not sure flushing the paint queue before doing the XCopyArea
 (suggestion 1 above) will be enough either.  It's very easy to imagine
 a scenario where you're scrolling and we do another ScrollWindow
 before all the GraphicsExpose events have been received.  We really do
 need to block things somehow.  And it'll be more than just blocking
 the message queue - we'll need to actually stop the thread if there's
 a call to ScrollWindow (or anything else that ends up copying) until
 the GraphicsExposes have been handled.

I went and began to review our code and wondering how to do it the
proper way - then went to Gtk+ scrolling code once more, and then could
see that the gtk textbox was handling the scroll itself (it seems the
algorithm is what's called 'smooth scrolling', not sure). 

The idea is that after each request to scroll, they call XIfEvent to
wait for GraphicsExpose/NoExpose events on the scrolled window, blocking
the thread until they get one of them (so you can invalidate or exit the
loop), and adding a expose operation on the window.

I implemented this today for our implementation and it seems to work
just fine, and it seems it follows your idea ;-)

Take a look and tell what you think.
Carlos.

PD - The patch is a test, so needs to be beautified still ;-) But should
work.
Index: XplatUIX11.cs
===
--- XplatUIX11.cs	(revisión: 109846)
+++ XplatUIX11.cs	(copia de trabajo)
@@ -4860,6 +4860,33 @@
 			y = dest_y_return;
 		}
 
+		bool GraphicsExposePredicate (IntPtr display, ref XEvent xevent, IntPtr arg)
+		{
+			return (xevent.type == XEventName.GraphicsExpose || xevent.type == XEventName.NoExpose) 
+arg == xevent.GraphicsExposeEvent.drawable;
+		}
+
+		delegate bool EventPredicate (IntPtr display, ref XEvent xevent, IntPtr arg);
+
+		void ProcessGraphicsExpose (Hwnd hwnd)
+		{
+			XEvent xevent = new XEvent ();
+			IntPtr handle = Hwnd.HandleFromObject (hwnd);
+			EventPredicate predicate = GraphicsExposePredicate;
+
+			for (;;) {
+XIfEvent (Display, ref xevent, predicate, handle);
+if (xevent.type != XEventName.GraphicsExpose)
+	break;
+
+AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.GraphicsExposeEvent.x, xevent.GraphicsExposeEvent.y,
+		xevent.GraphicsExposeEvent.width, xevent.GraphicsExposeEvent.height);
+
+if (xevent.GraphicsExposeEvent.count == 0)
+	break;
+			}
+		}
+
 		internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
 			Hwnd		hwnd;
 			IntPtr		gc;
@@ -4913,6 +4940,8 @@
 			Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
 			AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
 
+			ProcessGraphicsExpose (hwnd);
+
 			XFreeGC(DisplayHandle, gc);
 		}
 
@@ -4966,94 +4995,10 @@
 visible_area.Intersect (r);
 			}
 
-			// If region is null, the entire area is visible.
-			// Get the area not obscured otherwise.
-			Region visible_region = GetVisibleRegion (c, visible_area);
-			if (visible_region != null) {
-RectangleF rectf = visible_region.GetBounds (Hwnd.GraphicsContext);
-visible_area = new Rectangle ((int) rectf.X, (int) rectf.Y,
-		(int) rectf.Width, (int) rectf.Height);
-
-visible_region.Dispose ();
-			}
-
 			visible_area.Location = c.PointToClient (visible_area.Location);
 			return visible_area;
 		}
 
-		// Obscured area by other toplevel windows
-		Region GetVisibleRegion (Control c, Rectangle visible_area)
-		{
-			Region visible_region = null;
-			IntPtr Root;
-			IntPtr Parent;
-			IntPtr Children;
-			int ChildCount;
-
-			Control form = c.FindForm ();
-			if (form == null || !form.IsHandleCreated)
-return null;
-
-			Hwnd hwnd = Hwnd.GetObjectFromWindow (form.Handle);
-			IntPtr form_handle = hwnd.whole_window;
-
-			lock (XlibLock) {
-XQueryTree (DisplayHandle, RootWindow, out Root, out Parent, out Children, out ChildCount);
-			}
-
-			int intptr_size = IntPtr.Size;
-			bool above = false;
-
-			for (int i = 0; i  ChildCount; i++) {
-IntPtr window = Marshal.ReadIntPtr (Children, i * intptr_size);
-
-XWindowAttributes win_attrs = new XWindowAttributes ();
-lock (XlibLock) {
-	XGetWindowAttributes (DisplayHandle, window, ref win_attrs);
-}
-
-Rectangle win_area = new Rectangle (win_attrs.x, win_attrs.y, 
-		win_attrs.width, win_attrs.height);
-
-if (win_attrs.map_state != MapState.IsViewable || !win_area.IntersectsWith (visible_area))
-	continue;
-
-IntPtr SubChildren;
-int SubChildCount;
-
-if (above) {
-	if (visible_region == null)
-		visible_region = new Region (visible_area);
-
-	visible_region.Exclude (win_area);
-	continue;
-}
-
-lock (XlibLock) {
-	XQueryTree (DisplayHandle, window, out Root, out Parent, out SubChildren, out SubChildCount);
-}
-
-if (SubChildren != 

Re: [Mono-winforms-list] Scrolling performance isues

2008-08-01 Thread Chris Toshok
On Fri, Jul 25, 2008 at 11:34 AM, Ivan N. Zlatev [EMAIL PROTECTED] wrote:

 Carlos Alberto Cortez wrote:
  Hey,
 
  The new code that detects not visibles areas of the window to scroll
  (obscured by other mwf windows or x11 top level ones), although working
  fine, is somewhat slow, as some people have noticed.
 
  After some research, I found that getting all the child windows for the
  root window (using XQueryTree on RootWindow, this is, top level windows)
  is the hot spot, and was causing the slow down.
 
  And after some more research in other graphics tool kits, found that:
 
  * Most of them make use of GraphicsExpose event, handling it by directly
  generating expose events or invalidating the area pointed by
  GraphicsExpose (Gtk+ as far as I know, and also Ivan told me other
  frameworks do that).
 

 Yes, this is because GraphicsExpose is designed exactly for that
 purpose. It is fired when a destination area can't be copied (XCopyArea)
 to because the source area is obscured. I still fail to see why we need
 special obscured-areas-checking logic when we can just handle that message.


You answer your question below - the reason why we couldn't use
GraphicsExpose is precisely because of the timing issue.  Calculating the
exact region to expose is just one possible solution (which turns out to
likely be the wrong one).


 I do understand that if we do indeed handle the GraphicsExpose message
 we stand the problem that it might get delayed (X11 message roundtrip
 time) until after we perform the next ScrollWindow/XCopyArea, so because
 the destination area (for the previous ScrollWindow call) won't be
 repainted yet we will copy that garbage from it to the next offset.

 However we currently have an explicit AddExpose just after the
 XCopyArea, so we are working around this problem by forcing a repaint on
 the queue, so that we are guaranteed to be repainted prior to the next
 ScrollWindow. And this just-works (tm) :-)

 If we want to handle it properly we can either

 1) Flush the paint queue prior to XCopyArea somehow
 ... or ...
 2) Block the message queue until we get the last GraphicsExpose for
 the window, invalidate and then unblock the message queue.
 ... or ...
 3) Something better

  And also, regarding our code:
 
  * When using composite (Xgl or similar) it's not necessary to do this
  detection, since the window manager (*it seems*) is doing something that
  somehow already knows which areas need to get an expose event (in other
  words: only mwf overlapping detection is needed, not for x top level
  windows).
  * The new code, at least in my laptop, without using composite, seems to
  work fine (no performance lost), and don't know if it's because
  XQueryTree on RootTree returns a minor number of windows (61 with no
  composite, instead of 89 with composite, using 5 terminals and a gtk+
  application, for example).
 

 This I think is very implementation/environment/window manager/toolkit
 specific. E.g some toolkits/window managers might keep menu windows as
 hidden, but still mapped toplevels. I think this was referred to as one
 of the reason for the huge number of toplevels in some email I saw on a
 mailing list long time ago. Because of the variety of setups out there
 (window managers, toolkits, etc, etc) we can't really know with how many
 toplevels we are going to deal.

 To give you an example of the problem - on my GNOME + Metacity desktop
 with a standard set of programs running (Firefox, terminal, pidgin,
 nautilus, thunderbird, etc) XQueryTree returns 228 toplevels.

  So, it seems that we should actually handle GraphicsExpose (which all it
  involves) *or maybe* try to detect if we are using composite - if we
  are, simply don't use this new code, but just do simple calculations,
  and if we are not using it, do the detection, since it won't harm the
  performance.
 

 My personal position on the matter is that short-term (as in for Mono
 2.0) we just handle GraphicsExpose instead of the new code and keep the
 AddExpose after XCopyArea to workaround the timing issue. Long-term we
 can look into adding a proper handling for the delays of GraphicsExpose
 if it's feasible.


This has me a little confused - adding handling for GraphicsExpose isn't
going to help anything if it's not done properly.  What I mean is, adding
the handling for GraphicsExpose (essentially adding the case statement and
doing an AddExpose) won't give us anything more than what we currently have,
since we can't guarantee that any of those events will have been received.
It's a trivial change, and might lessen the problem somewhat, but it won't
fix it.

I'm also not sure flushing the paint queue before doing the XCopyArea
(suggestion 1 above) will be enough either.  It's very easy to imagine a
scenario where you're scrolling and we do another ScrollWindow before all
the GraphicsExpose events have been received.  We really do need to block
things somehow.  And it'll be more than just blocking the 

[Mono-winforms-list] Scrolling performance isues

2008-07-25 Thread Carlos Alberto Cortez
Hey,

The new code that detects not visibles areas of the window to scroll
(obscured by other mwf windows or x11 top level ones), although working
fine, is somewhat slow, as some people have noticed.

After some research, I found that getting all the child windows for the root
window (using XQueryTree on RootWindow, this is, top level windows) is the
hot spot, and was causing the slow down.

And after some more research in other graphics tool kits, found that:

* Most of them make use of GraphicsExpose event, handling it by directly
generating expose events or invalidating the area pointed by GraphicsExpose
(Gtk+ as far as I know, and also Ivan told me other frameworks do that).

And also, regarding our code:

* When using composite (Xgl or similar) it's not necessary to do this
detection, since the window manager (*it seems*) is doing something that
somehow already knows which areas need to get an expose event (in other
words: only mwf overlapping detection is needed, not for x top level
windows).
* The new code, at least in my laptop, without using composite, seems to
work fine (no performance lost), and don't know if it's because XQueryTree
on RootTree returns a minor number of windows (61 with no composite, instead
of 89 with composite, using 5 terminals and a gtk+ application, for
example).

So, it seems that we should actually handle GraphicsExpose (which all it
involves) *or maybe* try to detect if we are using composite - if we are,
simply don't use this new code, but just do simple calculations, and if we
are not using it, do the detection, since it won't harm the performance.

But I woould like people to tell me how this code (2.0 branch or trunk)
behaves for them, in both cases (since I remember that Ivan was having
performance problems with the new code even without using composite).

Hope it's clear ;-)
Carlos.
___
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list


Re: [Mono-winforms-list] Scrolling performance isues

2008-07-25 Thread Ivan N. Zlatev
Carlos Alberto Cortez wrote:
 Hey,
 
 The new code that detects not visibles areas of the window to scroll 
 (obscured by other mwf windows or x11 top level ones), although working 
 fine, is somewhat slow, as some people have noticed.
 
 After some research, I found that getting all the child windows for the 
 root window (using XQueryTree on RootWindow, this is, top level windows) 
 is the hot spot, and was causing the slow down.
 
 And after some more research in other graphics tool kits, found that:
 
 * Most of them make use of GraphicsExpose event, handling it by directly 
 generating expose events or invalidating the area pointed by 
 GraphicsExpose (Gtk+ as far as I know, and also Ivan told me other 
 frameworks do that).
 

Yes, this is because GraphicsExpose is designed exactly for that 
purpose. It is fired when a destination area can't be copied (XCopyArea) 
to because the source area is obscured. I still fail to see why we need 
special obscured-areas-checking logic when we can just handle that message.

I do understand that if we do indeed handle the GraphicsExpose message 
we stand the problem that it might get delayed (X11 message roundtrip 
time) until after we perform the next ScrollWindow/XCopyArea, so because 
the destination area (for the previous ScrollWindow call) won't be 
repainted yet we will copy that garbage from it to the next offset.

However we currently have an explicit AddExpose just after the 
XCopyArea, so we are working around this problem by forcing a repaint on 
the queue, so that we are guaranteed to be repainted prior to the next 
ScrollWindow. And this just-works (tm) :-)

If we want to handle it properly we can either

1) Flush the paint queue prior to XCopyArea somehow
... or ...
2) Block the message queue until we get the last GraphicsExpose for 
the window, invalidate and then unblock the message queue.
... or ...
3) Something better

 And also, regarding our code:
 
 * When using composite (Xgl or similar) it's not necessary to do this 
 detection, since the window manager (*it seems*) is doing something that 
 somehow already knows which areas need to get an expose event (in other 
 words: only mwf overlapping detection is needed, not for x top level 
 windows).
 * The new code, at least in my laptop, without using composite, seems to 
 work fine (no performance lost), and don't know if it's because 
 XQueryTree on RootTree returns a minor number of windows (61 with no 
 composite, instead of 89 with composite, using 5 terminals and a gtk+ 
 application, for example).
 

This I think is very implementation/environment/window manager/toolkit 
specific. E.g some toolkits/window managers might keep menu windows as 
hidden, but still mapped toplevels. I think this was referred to as one 
of the reason for the huge number of toplevels in some email I saw on a 
mailing list long time ago. Because of the variety of setups out there 
(window managers, toolkits, etc, etc) we can't really know with how many 
toplevels we are going to deal.

To give you an example of the problem - on my GNOME + Metacity desktop 
with a standard set of programs running (Firefox, terminal, pidgin, 
nautilus, thunderbird, etc) XQueryTree returns 228 toplevels.

 So, it seems that we should actually handle GraphicsExpose (which all it 
 involves) *or maybe* try to detect if we are using composite - if we 
 are, simply don't use this new code, but just do simple calculations, 
 and if we are not using it, do the detection, since it won't harm the 
 performance.
 

My personal position on the matter is that short-term (as in for Mono 
2.0) we just handle GraphicsExpose instead of the new code and keep the 
AddExpose after XCopyArea to workaround the timing issue. Long-term we 
can look into adding a proper handling for the delays of GraphicsExpose 
if it's feasible.

 But I woould like people to tell me how this code (2.0 branch or trunk) 
 behaves for them, in both cases (since I remember that Ivan was having 
 performance problems with the new code even without using composite).
 

As I mentioned above with my setup I have 228 toplevels and I get 
garbage everywhere when scrolling on a Core Duo 2 machine.


Tell me what do you think,

Cheers,
-- 
Ivan N. Zlatev

Web: http://www.i-nZ.net
It's all some kind of whacked out conspiracy.
___
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list