[Mono-winforms-list] Master's Thesis

2005-08-17 Thread ahappone
Hi!

I'm a student in University Of Kuopio in Finland. I'm about to do master's 
thesis concerning Mono and Windows.Forms. My plan was to make a simple game 
and compare performance of .NET and Mono with it. To achieve this goal I have 
to make a game loop that runs on maximum speed and then count the frames per 
second.

This is easy to do with .NET by overriding main forms "OnPaint"-method and 
calling "this.Invalidate()" at the end of it. This is very simple and 
effective but only seems to work with .NET. Mono doesn't start looping this 
way. It seems that Mono always needs somekind of event (from Timer for 
example) to call "OnPaint"-method.

I know this is not the only way to make it work, but I have tried many other 
ways too without results. I can make the loop work with Timer but its maximum 
frequency is too small for performance comparisons. So I need your help to 
make a game loop that runs as fast as it can on Mono!

I hope that someone understood what I'm trying to say here and propably could 
give me some hints.
___
Mono-winforms-list maillist  -  Mono-winforms-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-winforms-list


Re: [Mono-winforms-list] Master's Thesis

2005-08-26 Thread Jonathan Gilbert
At 02:34 PM 26/08/2005 +0300, you wrote:
>Hi!
>
>I composed a reply message to you earlier but I guess our mail system
blocked it
>because it contained .exe files as attachment (two versions of the game I am
>making). I just wanted to thank you for your good advice!!! I wrote one
version
>of the game just the way you described. And it works really good! Only
problem
>is that it is slow compared to "real" double buffer.

It shouldn't be slow. The only reason I can think is that it must still be
doing some sort of translation of the buffer. I assume you went with the
second approach, with the Bitmap that you LockBits, draw to, UnlockBits,
and then Graphics.DrawImageUnscaled to the screen. You can find the code
for Bitmap.LockBits inside libgdiplus's src/bitmap.c file (the source code
is in Mono's SVN). I actually wrote parts of it myself, but I was forced to
work with the existing infrastructure which, for simplicity, only has one
"real" non-indexed pixel format, that being CAIRO_FORMAT_ARGB32. This
corresponds, I believe, to PixelFormat.Format32bppArgb.

I'm not sure exactly how mono implements its double-buffer, but at least
when I wrote my library (mode13 -- http://www.deltaq.org/mode13/), it was
crucial that repainting the form not hold up the message queue, and also
that it not be delayed by WM_* messages. I actually came up with a rather
elaborate scheme involving two Bitmaps that get swapped back and forth,
making an "active" plane that isn't visible, and a "visible" plane that
isn't being drawn to. However, I never leave the game's thread, and I never
use Window Messages, in order to paint the surface of the form.

One other minor point of note for performance is that Mono is in the
process of switching from Cairo 0.3 to Cairo 1.0. The current SVN head does
not reflect this, afaik; it's still sitting on a branch. However, it will
be switched over "soon", after which many drawing operations should see a
notable improvement in speed. Depending on exactly what you're doing when
drawing, this may affect you more or less. :-)

>I wrote a second version of the game that uses overridden OnPaint()-method
for
>drawing AND thread for game loop. This way I could use the doublebuffer
setting
>and get about two times faster framerate compared to what you suggested. Only
>problem is that it doesn't work with Mono :( I call Refresh()-method in
>thread's while loop to get form redrawn. This works just fine with .NET
but not
>with Mono. Could it be that Mono's Refresh()-method is not implemented at
all?
>It should force invalidate and update of the form immediately after calling,
>and that way it may not append any messages to message queue?

Check out the following MSDN page:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemwindowsformscontrolclassinvokerequiredtopic.asp

(try http://lnks.us/WCTG09 if that wraps too badly; it should go to the
same place)

In particular, it says, quote:

   There are four methods on a control that are safe to call from any
thread: Invoke, BeginInvoke, EndInvoke and CreateGraphics.

The Refresh method isn't one of these, I'm afraid, and that could be the
source of your problems. Even if it were (or if you used Control.Invoke),
it would still require marshalling the repaint operation to a different
thread, which is something you really want to avoid! It should be possible
to get directly drawing to the form from a background thread to perform
*better* than drawing from the UI thread, since you can do essentially
exactly what the framework does on the UI thread without all the extra
baggage of passing messages around, waiting for other messages to be
handled, etc.

If you really want the standard double-buffering behaviour, you might be
able to replicate it within your own code; just search
System.Windows.Forms/Control.cs and any other applicable files for places
where it checks whether the DoubleBuffer style is set.

>Would you like to see the sourcecode of my game too? I can try to attach it
>again without any binaries (so our mail-blocker shouldn't block it). It's
very
>nice to have someone that can understand my point of view there :)
>
>BTW. You were the only one on your post list who replyed something useful
to me!

Sure, and thanks :-) Many people see programming as a job -- something
tedious which must be done but at least they get paid for it -- but I have
a true passion for it :-)

Jonathan Gilbert

>> At 11:10 AM 10/08/2005 +0300, Alvi Happonen wrote:
>> [snip]
>> >This is easy to do with .NET by overriding main forms "OnPaint"-method and
>> >calling "this.Invalidate()" at the end of it. This is very simple and
>> >effective but only seems to work with .NET. Mono doesn't start looping
this
>> >way. It seems that Mono always needs somekind of event (from Timer for
>> >example) to call "OnPaint"-method.
>>
>> While the GUI widgets and such all require marshalling calls to a specific
>> UI thread, System.Drawing is completely threadsafe an