Discussion:
[Gtk-sharp-list] Drawing pixbufs to screen FAST..
Eto
2004-12-30 16:40:32 UTC
Permalink
Hi all!

I'm really liking this GTK# thing. Combines my favorite language with linux
development. Can't get much better.

I am running into a performance problem though, but I'm unsure of the best way
to do this.

I am creating a console-like application that updates small parts of the
display on the fly. I generate the character in a pixbuf, then draw that to
the screen. (I need to do this because the character definitions are
completely customizable). This is done in a background thread.

The slow part is not generating the pixbuf, but rather, drawing it to screen.
In windows, this is extreemly fast and works like a charm.

I am not scaling the image or anything, just using the Drawable.DrawPixbuf
method to output to screen (though, I would still like to be able to scale
the output).

My question is this: what is the best way in GTK# to draw a lot of small
images to the screen real, real FAST?

Any help would be muchly appreciated!

Thanks,
Curtis.
Gabriel Ebner
2004-12-31 07:40:34 UTC
Permalink
Post by Eto
My question is this: what is the best way in GTK# to draw a lot of small
images to the screen real, real FAST?
The fastest way I've found is to create server-side pixmaps:

Pixbuf pb = ...;
Pixmap mask, pm;
pb.RenderPixmapAndMask(out pm, out mask, 128);
pb.Dispose();
mask.Dispose();

Gabriel.
Dan Winship
2005-01-05 19:11:48 UTC
Permalink
Post by Eto
The slow part is not generating the pixbuf, but rather, drawing it to screen.
In windows, this is extreemly fast and works like a charm.
I am not scaling the image or anything, just using the Drawable.DrawPixbuf
method to output to screen (though, I would still like to be able to scale
the output).
Are you sure you're actually drawing it to the screen? Have you read the
bits of the gdk documentation about drawing and expose events and the
like? The problem might be that you're not invalidating the window, so
the drawing you do doesn't show up until some arbitrary time later.

-- Dan
Eto
2005-01-05 21:14:08 UTC
Permalink
Post by Dan Winship
Are you sure you're actually drawing it to the screen? Have you read the
bits of the gdk documentation about drawing and expose events and the
like? The problem might be that you're not invalidating the window, so
the drawing you do doesn't show up until some arbitrary time later.
-- Dan
Hey Dan,

When doing the animation, I draw directly to the screen by doing something
like this:

Gdk.Drawable drawable = drawingArea.GdkWindow;

// create pixbuf and generate it's content

drawable.DrawPixbuf(...);

I don't do this in the expose event (when animating). I do not have a problem
with it actually drawing to screen, as it all updates properly. It's just
slow(er). I wouldn't call it unbearable for some applications, but for doing
an animation like I am, I can't get it go as fast as I need it..

It's even slower when doing any sort of scaling, like doing 50%, etc.. but
this is mainly due to having to create a secondary pixbuf and doing
Pixbuf.Scale() on it, then drawing the scaled pixbuf. Ideally I'd be able to
get all this to go fast.

I thought of using Cairo to do the drawing so that it'd use some video
acceleration, but havn't had much success yet on that front.

I tried Gabriel's suggestion, but unfortunately, the images aren't static so i
would need to create the pixbuf anyway and converting from pixbuf to pixmap
is just the same as just drawing the pixbuf. *shrug*

Thanks for any help!
Curtis.
Eto
2005-01-06 19:19:24 UTC
Permalink
Post by Dan Winship
Are you sure you're actually drawing it to the screen? Have you read the
bits of the gdk documentation about drawing and expose events and the
like? The problem might be that you're not invalidating the window, so
the drawing you do doesn't show up until some arbitrary time later.
-- Dan
I'm fairly sure... hehe.. I am not measuring the speed visually though. I
have code that syncs to the desired speed, but this speed cannot be achieved
(the actual code does not execute fast enough). It does a thread sleep if
it is going too fast, but does nothing if it's going too slow. It never gets
around to waiting, unless I choose a very slow animation speed.

I also measure the total time it takes to run the animation, which is longer
than it should be.

It can be achieved fine in windows using SWF with the same back-end code..

I'm not sure exactly what documentation you refer to with regards to drawing
and expose events. As I mentioned, I'm not using expose/invalidate to update
the screen while animating. I have a background thread that does this. I
have tried making the thread invalidate the region to update then letting the
expose event draw it, but it is equally as slow.. plus it also combines the
regions to update, which is an undesired effect for the animation. ):

Thanks!
Curtis.
Federico Mena Quintero
2005-01-18 14:50:54 UTC
Permalink
Post by Eto
I am creating a console-like application that updates small parts of the
display on the fly. I generate the character in a pixbuf, then draw that to
the screen. (I need to do this because the character definitions are
completely customizable). This is done in a background thread.
The slow part is not generating the pixbuf, but rather, drawing it to screen.
In windows, this is extreemly fast and works like a charm.
I am not scaling the image or anything, just using the Drawable.DrawPixbuf
method to output to screen (though, I would still like to be able to scale
the output).
Some things to keep in mind:

- Do your pixbufs have an alpha channel? Due to the current
implementation in the X server of the RENDER extension, they may not go
through accelerated paths.

- If you'll be drawings many little pixbufs, it may be faster to
composite them onto a larger pixbuf without an alpha channel, and send
that to your window with DrawPixbuf(). Download the gtk-sharp sources
and see gtk-sharp/sample/GtkDemo/DemoPixbuf.cs, which makes a nice
animation.

- You may want to turn off double-buffering for your widget and handle
exposures yourself. EOG has a good example of a non-double-buffered
image widget that is quite fast.

- Can you pre-generate server-side pixmaps out of your pixbufs and keep
them around? That way they are likely to live in video memory, and
blitting will be very fast.

If you have a web page or something that shows what you are trying to do
in your program, we may be able to come up with more concrete
suggestions.

Federico
Eto
2005-01-19 01:17:51 UTC
Permalink
Post by Federico Mena Quintero
- Do your pixbufs have an alpha channel? Due to the current
implementation in the X server of the RENDER extension, they may not go
through accelerated paths.
Actually yes, even though I don't use it. This is because I'm generating the
pixbuf on the fly, and generating a 32 bit image is MUCH easier (and faster)
than 24. In system.drawing, I have the option of a 32-bit bitmap without
using alpha.. anything like this for gtk?

I tried 24 bit before, but it didn't make much difference at the time.
Post by Federico Mena Quintero
- If you'll be drawings many little pixbufs, it may be faster to
composite them onto a larger pixbuf without an alpha channel, and send
that to your window with DrawPixbuf(). Download the gtk-sharp sources
and see gtk-sharp/sample/GtkDemo/DemoPixbuf.cs, which makes a nice
animation.
I think sending the entire thing to screen would be a lot slower.. or are you
thinking to just send portions of the larger pixbuf to screen?
Post by Federico Mena Quintero
- You may want to turn off double-buffering for your widget and handle
exposures yourself. EOG has a good example of a non-double-buffered
image widget that is quite fast.
Hm, lemmie check.. yup.. It's already turned off for the DrawingArea widget.
Post by Federico Mena Quintero
- Can you pre-generate server-side pixmaps out of your pixbufs and keep
them around? That way they are likely to live in video memory, and
blitting will be very fast.
Unfortunately, no.. unless there's an easy and fast way to change the colour
of pixels in a pixbuf before drawing them. I could do it this way if I used
8-bit indexed images.. but then it won't be in video memory anyway so there's
no point.. hehe
Post by Federico Mena Quintero
If you have a web page or something that shows what you are trying to do
in your program, we may be able to come up with more concrete
suggestions.
Hm, good idea! (: This is for an image viewing/editing application, which
views (and edits) obsolete (to the world) formats, such as ANSI, Avatar,
Ascii, RIP.. as well as new formats such as bmp/jpeg/etc. It's for a very
niche market, but I've been part of it for many, MANY years. (:

I've got windows-specific apps for viewing (.net) and editing (win32). I want
to make one that does both, but with support for GTK.

The windows only versions are here:
http://pablo.etoxn.ca

You can download the current GTK (and SWF) version that I'm working on here:
http://pablo.etoxn.ca/PabloDraw-3.0.3.zip

If you run it in windows, pass 'gtk' as the command line to run the gtk
version ('swf' for windows forms). It uses a custom GUI toolkit that runs on
GTK or SWF depending on the platform.

There are a few files included in the above ZIP file to test it out. The main
ones i'm interested in making faster are the .ANS files. For the .RIP files
i'm drawing directly to the screen, but if drawing the images to screen goes
fast enough, then I can switch it over (as to provide proper dos aspect while
animating). Make sure to set the zoom to 100% when viewing rips, as there's
a bug in the gtk version with that..

Thanks for your VERY valuable input!

Curtis.

Loading...