GDI+ and DirectX9 drawing

GDI+ and DirectX9 drawing

Post by Anders For » Wed, 31 Dec 2003 17:09:17


I'm doing windowed drawnig of GDI+ graphics for a drawing
application. After some tweaking I've achieved decent
performance on the GDI+ drawing itself, but I feel the
actual rendering of buffers to screen (manually) is a bit
slow. I use a 3-buffer scheme with a permanent
backbuffer, a temporary overlay, and the visible screen.
At each redraw I paint the overlay to the permanent
backbuffer (for things that were handled with xor drawing
ing GDI), then this whole image is splashed onto the
screen.

This means at least 2 DrawImageUnscaled()-calls at each
frame, which seems to scale by the size of the window
(about 50-60 ms. for a large window).

I want to try using directdraw 9 surfaces for the
drawing, but I cant get it working without recreating the
surfaces (one for each of my gdi+ buffer bitmaps) at each
frame, which takes about the same time to allocate as the
DrawImageUnscaled. Thus no real speedup. I'm hoping to
spend at most 10ms. painting once the buffers are done,
they take long enough to draw anyway...

Is there a way of using GDI+ for drawing and then using
DirectDraw only for the drawing of painted bitmaps to
screen? Or can I somehow use GDI+ but use some method
that is 5 times faster than DrawImageUnscaled?

Regards
/Anders
 
 
 

GDI+ and DirectX9 drawing

Post by xinhuan » Thu, 01 Jan 2004 17:11:44

It is not necessary to create a DDraw Surface for every frame. Just create
the Surface on load, and then you can lock and update the Surface in every
frame. A fast AGP card can easily handle this in less than 10 ms, even for
full screen sized surfaces.

Regards,
Xin

This posting is provided "AS IS" with no warranties, and confers no rights.

Are you secure? Visit http://www.yqcomputer.com/ to get the latest
critical updates and service packs available for your computer's Windows
operating system.

 
 
 

GDI+ and DirectX9 drawing

Post by Anders For » Sat, 03 Jan 2004 18:13:52


frame. Just create
the Surface in every
than 10 ms, even for

I'm not sure how to go about this, I can't seem to find
any good examples of GDI+ interaction with Managed
DirectX.

How do I set up my buffers/surfaces? Right now I create a
bitmap, and then a surface for the bitmap:
offscreenBitmap = new Bitmap(ctrl.ClientRectangle.Width,
ctrl.ClientRectangle.Height);
tempsurface = new Surface(offscreenBitmap,
offscreenSurfaceDescription, displayDevice);

Now when I want to do GDI+ drawing on the offsecreen
surface, I would get the graphics from the bitmap using
Graphics.FromImage(), and draw on that graphics. Is this
when I need to lock the memory of the surface? Or do I
lock when I blit the tempsurface to the display surface?
When do I lock, and what surfaces need locking?

Any pointers to relevant articles/tutorials are
appreciated.

regards,
Anders
 
 
 

GDI+ and DirectX9 drawing

Post by xinhuan » Wed, 07 Jan 2004 18:08:59

I was about to point you to the document of Lock & Unlock in the Managed
DirectX SDK, but I immediately realized that the document is so preliminary
that it gives you virtually no information
( http://www.yqcomputer.com/
.directx.directdraw/c/surface/m/lock0.asp).

So I sat down with the C# SpriteAnimate sample and modified its
ProcessNextFrame method a bit to show how to lock and modify the surface
memory. My modification starts after the DisplayFrame call. All it does is
to modify the surfaceAnimation sufrace into random horizontal lines.

Note that it seems the Lock method returns the array in wrong ranks. So I
used an unsafe pointer to workaround it (and boost up the performance). I
will go ahead and check if it is a real bug.

If you are not familiar with unsafe code, you can check Eric Gunnerson's
article at
< http://www.yqcomputer.com/
ml/csharp11152001.asp>

unsafe private void ProcessNextFrame()
{
// Figure how much time has passed since the last time.
int tickCurrent = Environment.TickCount;
int tickDifference = tickCurrent - tickLast;

// Don't update if no time has passed.
if (0 == tickDifference)
return;

tickLast = tickCurrent;

// Move the sprites according to how much time has passed.
for (int i = 0; i < numSprites; i++)
UpdateSprite(ref sprite[i], tickDifference / 1000.0f);

//Draw the sprites and text to the screen.
DisplayFrame();

short[,] buf1 = (short[,]) surfaceAnimation.Lock(LockFlags.Wait |
LockFlags.WriteOnly);

fixed(short* buf = &buf1[0,0])
{
int width = surfaceAnimation.SurfaceDescription.Width;
for(int y = 0; y < surfaceAnimation.SurfaceDescription.Height; y++)
{
short color = (short)(GetNextRand() & 65535);
for(int x = 0; x < width; x++)
*(buf + y * width + x) = color;
}
}

surfaceAnimation.Unlock(buf1);
}


Hope this helps.

Regards,
Xin

This posting is provided "AS IS" with no warranties, and confers no rights.

Are you secure? Visit http://www.yqcomputer.com/ to get the latest
critical updates and service packs available for your computer's Windows
operating system.