Scroll Buffering in Windows Applications - c#

How is scrolling typically handled in a Windows application that has computationally expensive graphics to render? For example, if I am rendering a waveform graph of a sound, after processing the wave form from a peakfile, should I:
Render the entire graphical representation to an in-memory GDI surface, and then simply have a scrollable control change the start/end of the render area?
Render the visible portion of the wave only. In a separate thread, process any new chunks of the graphc that come into view.
Render the visible portion of the wave, plus a buffer. This way, there's less of a chance of the user seeing "blank" or "currently rendering" portions of the waveform. Still, if a user quickly scrolls to a distant area, the whole section will be blank until rendering is complete.
The problem is, many applications handle this in different ways.
For example:
Adobe Acrobat - renders blank pages during scroll unless page is in cache. Any pages that would be visible within the document render area are rendered in a separate thread and are presented opon completion.
Microsoft Word - Essentially, the same as above. Documents are separated into distinct pages, so each page is processed/rendered on an as-needed basis and added to a cache.
Internet Explorer - Unknown. It appears that an entire "webpage" is rendered in graphic memory, no matter how many "screens" worth of graphic data it consumes. Theoretically, with a web page that scrolls for 10 or 15 screen lengths, this could mean 50-60MB worth of graphic memory consumption. Could anyone with experience with WebKit or FireFox explain whether or not the rendering engine favors consuming a ton of memory, or tries to render peices of the page "on the fly" to conserve memory?
If it helps, my application is based on C#, .NET 3.5, and WinForms.

This is a complexity vs. user experience trade-off. Your third option will give you the best user experience (they can start to see things right away and start to work). It is also the most complex to code (will take the longest to develop, with the most amount of bugs to kill).
The "correct" solution depends on how "expensive" expensive is, and on the demands of your user base. I would select the option with the least complexity that will provide a user experience that will satisfy the bulk of the customers:
Make it as complex as it needs to be, but no more complex than that.

I think this is actually a memory-usage versus a processor-usage tradeoff. Your first option (rendering the entire wave on an appropriately-sized canvas, and then moving that canvas around with only a visible window portion showing) might be the best approach, assuming you have enough memory for it. After an initial rendering delay, the user experience will be smooth and seamless.
If you don't have enough memory for this, then you have to render the visible portion on the fly. I've written this application (WAV data viewer) many times, and usually GDI+ is more than fast enough to render portions (even large portions) of WAV data in realtime (with a high framerate above 30 fps, which produces perfectly smooth animation). The key to this, however, is not to render each sample value as a separate point - this would be dog slow. What you want to do is for each pixel on your X axis, scan the corresponding chunk of WAV samples to get the minimimum and maximum sample value, and then render a single line between these values.

Related

Should I use Image or WebBrowser for displaying image?

I am standing between major decision in my WP7 application. It's majore purpose is to display images, always one at a time on fullscreen.
I need perfect support for pinch to zoom, moving image (while zoomed) and switching between images via flick gesture. Most of these things are already implemented in WebBrowser control, so I would just have to generate proper html source with path to image in Isolated storage.
Or should I use common Image control and implement these gestures on my own? I would like your advice before I make this decision.
Are you targeting Windows Phone 8 or 7?
Generally, I would implement my own.
Issues with using the web-browser:
1. Perf is going to be slower.
Memory footprint is going to be higher (though I doubt you really care about this - it's not going to be massive).
If you are going to favorite/download images, it will be harder (if at all possible) to navigate to them in the browser.
The background will always be white, unless you generate HTML each time that will control that bit.
The biggest issue is that the zooming in/out will be.. Janky... You won't be able to control how zoomed out the user can make it - meaning that they can zoom out enough to make the picture very small and it won't "snap back".
It's not a bad stop-gap, and the issues with it are not so big that one can say "no - don't do it", but they are enough that you should reconsider.

How to manage picture previews correctly

I'm developing a C# software that is able to show previews for files. Basically, there is a tree at the left that shows the disk filesystem entries, and a panel on the right that will show a preview of files selected in the tree, in a resizable panel that contains a docked PictureBox. Initially I only show preview for image files.
This software is designed for game developers, so I need to support all the image formats, I will use the great ImageMagick library for this purpose. The key is that some image files could be big, very big so, I have several questions, about performance and memory consumption.
Do I need to thread the load of the picture? Always, or only if the picture is very big?
Would be a correct if I load the picture directly in the Picturebox, or should I calculate a smaller size image (like a thumbnail or something similar), save it to disk, and then, show it?
Someone knows where can I download big picture files to test my preview with really very large files.
Imo always thread a work like this, there is little point in trying to decide what is big; for images that of are talking about I would of thought most would be enough that under the wrong conditions (computer is spending resources on other processes, not just yours) it could cause a perceivable pause in the UI thread.
Without knowing more, I would just test your implementation when it does the basic stuff and make a judgement call. There is also the question of required quality and desktop resolution of the user - so perhaps this should be configurable in some way.
Imo there could be no better place than PolyCount, specifically look in these forums:
http://www.polycount.com/forum/forumdisplay.php?f=42 &
http://www.polycount.com/forum/forumdisplay.php?f=60

How can I edit individual pixels in a window?

I want to create a simple video renderer to play around, and do stuff like creating what would be a mobile OS just for fun. My father told me that in the very first computers, you would edit a specific memory address and the screen would update. I would like to simulate this inside a window in Windows. Is there any way I can do this with C#?
This used to be done because you could get direct access to the video buffer. This is typically not available with today's systems, as the video memory is managed by the video driver and OS. Further, there really isn't a 1:1 mapping of video memory buffer and what is displayed anymore. With so much memory available, it became possible to have multiple buffers and switch between them. The currently displayed buffer is called the "front buffer" and other, non-displayed buffers are called "back buffers" (for more, see https://en.wikipedia.org/wiki/Multiple_buffering). We typically write to back buffers and then have the video system update the front buffer for us. This provides smooth updates, as the video driver synchronizes the update with the scan rate of the monitor.
To write to back buffers using C#, my favorite technique is to use the WPF WritableBitmap. I've also used the System.Drawing.Bitmap to update the screen by writing pixels to it via LockBits.
It's a full featured topic that's outside the scope (it won't fit, not that i won't ramble about it for hours :-) of this answer..but this should get you started with drawing in C#
http://www.geekpedia.com/tutorial50_Drawing-with-Csharp.html
Things have come a bit from the old days of direct memory manipulation..although everything is still tied to pixels.
Edit: Oh, and if you run into flickering problems and get stuck, drop me a line and i'll send you a DoubleBuffered panel to paint with.

How to draw in C#/WinForms with decent speed?

I'm trying to visualise a graph and allow people to play with it. I found the excellent Graph# library that can create an initial layout so that part is covered. Now I need to make a control that actually draws it and provides the necessary interactivity.
Graph# comes with a nice visualiser itself, however I don't like it because it is written in WPF (while my app is WinForms), and because I want to add some more interactivity options, which would require quite a remake of it anyway.
The graphs I'm drawing will routinely be pretty large, at about 100 vertices and the same amount of edges (the graphs will be trees 99% of time). That means that the resulting rendering can be up to 2000px by 2000px and even more. The users should be able to zoom in and out, scroll, highlight and drag vertices and edges, and get some popups with additional info when hovering the cursor above a vertex.
I'm worried that the standard System.Drawing might not be able to deliver a decent speed for this. I would like the dragging/zooming/scrolling operations to be smooth, and the popups should open with a little animation as well. Something like 20fps should be a necessity.
I know I can try to speed things up by pre-rendering a lot of the elements and keeping them as bitmaps in memory - but that would probably take up lots of RAM, and I'm still not sure if it would deliver the necessary performance.
What are your thoughts?
"Premature optimization is the root of all evil"
GDI+ can be great for your needs. Don't go and buy 3rd party libraries before you know you even need them.
I've done a thousand polygons on a 1000x800 pixel bitmap and redrawn it completely at over 100 frames per second, using just GDI+
That being said, if you have a lot of drawing to do, and your resolution is big.. Some of the 3rd party drawing libraries can go WAY beyond what managed GDI is capable of.
I recommend leaving Graph# alone, and just hosting it in your Windows Forms application.
The performance you will receive will be much better than trying to reimplement it in System.Drawing.
GDI+ will be plenty fast enough for what you're doing, especially if (as it sounds from your description) everything you're drawing is rectangles and vertical/horizontal lines. Polygons and non-linear shapes are a bit slower, but not much (the speed difference is partially dependent on the SmoothingMode of your Graphics object). Drawing cached Bitmaps with resizing is also quite fast, although it can slow down significantly if you use a high-quality InterpolationMode setting.
As a benchmark, I wrote a .Net Compact Framework GPS application for Windows Mobile that rendered about 10,000 lines on the screen in realtime. This only achieved a frame rate of a few frames per second, but the processing power on a Smartphone is, of course, way less than a modern PC.

.NET C# drawing slowly

I have a problem drawing something quickly in .NET. I don't think that any thing in particular should take much time, but on every machine I've tried it on, I get serious issues. This is implemented in vs2008 .NET, using C# (with some stuff in C++, but nothing relevant to the drawing).
I have three screens, and the user should be able to toggle between them with no lag. On the first screen, there are four buttons, eight user controls consisting of two buttons and 6 labels each, a text field, and a dropdown box. I don't think of it as being that much.
On the second screen, I have four labels, six buttons, and two controls that have six buttons, one opengl drawing context, and about ten labels each.
On the third screen, I have one opengl context and 10 buttons.
Flipping from any screen to any screen takes literally about a second. For instance, if I flip from the second screen to the first, the entire application blanks out, showing the background screen, and then the first screen is drawn. Many times, a screen is drawn piecemeal, as if the machine were deliberately handcrafting delicate and delicious letters in a factory in Sweden and then shipping each one individually to my screen. I exaggerate, and I want to make that clear, because I don't think Swedes are as slow as this redraw.
The first and second screen are drawn in memory, and stored there, with just a '.Hide()' and '.Show()' to make them appear and disappear. Double buffering doesn't seem to matter. The third screen is drawn anew each time, and appears to take the same amount of time to draw as the first and second.
Any thoughts? What could be going on? How can I track it down?
Thanks!
Edit: I should add that any C++ processing and the like happens in its own thread. There is the occasional MethodInvoke to draw the results of the operation to the screen, but this problem happens without calling any functions, just by pressing buttons to go from one screen to the next.
In addition to the profiler that was mentioned, you might also turn off your OpenGL contexts. If you notice a speed-up, then you'll know it's your graphics stuff, and you can focus your optimisations accordingly.
Points awarded for Swedish humour.
How can I track it down?
dotTrace - http://www.jetbrains.com/profiler/
Are you doing any other processing during the "screen flip" event? other than just letting the form be redrawn? If you are processing something between flips (maybe your c++ addition?), and you are not multi-threading, you get that white out effect. The form is probably waiting for CPU time to redraw itself.
I have never used OpenGL in such a way myself, but you might want to look at the way in that the OpenGL contexts are flipped. When switching from one page to another you might be getting a device reset (in DirectX terms), which could be causing the delay.
If at all possible have a device draw to a back System.Drawing.Bitmap, and use that bitmap on the screens. Make your OpenGL code aware of the current page the user is on, and you might get the speed up you seek.
To test this before making huge changes, try removing the OpenGL displays on your form.
This is all a whim.

Categories

Resources