Skip to main content
GameDev.net gamedev.net
🔒 Locked

Help optimizing image BitBlt

Started by scottrick49 May 11, 2009 at 2:55 PM 8 replies 2.6k views
Original Post
scottrick49
scottrick49
Currently I'm trying to optimize some bitmap drawing. Here is the "meat" of the drawing code. My profiler tells me that this stuff right here is taking about 50% of the total drawing time.

// Dest DC.
CDCHandle dstDC((HDC)IDisplay::Get()->GetDC());
HBITMAP oldDst = dstDC.SelectBitmap((HBITMAP)_itsBitmapHandle);

// Source DC.
CDC srcDC;
srcDC.CreateCompatibleDC();
HBITMAP oldSrc = 0;

// Move the bits.
oldSrc = srcDC.SelectBitmap((HBITMAP)pSrc->_itsBitmapHandle);
dstDC.BitBlt(xDst, yDst, dx, dy, srcDC, xSrc, ySrc, dwRop);

// Put everything back.
dstDC.SelectBitmap(oldDst);
if (oldSrc != 0)
	srcDC.SelectBitmap(oldSrc);
Do any red flags go off in your head when you are reading this code? I didn't write it and I don't know much about using GDI, so I have been struggling to find optimizations. Any help is appreciated. [Edited by - scottrick49 on May 12, 2009 1:32:09 PM]
scottrick49
Evil Steve
Evil Steve
Quote:
Original post by scottrick49
Currently I'm trying to optimize some bitmap drawing.

Here is the "meat" of the drawing code. My profiler tells me that this stuff right here is taking about 50% of the total drawing time.
// Dest DC.CDCHandle dstDC((HDC)IDisplay::Get()->GetDC());HBITMAP oldDst = dstDC.SelectBitmap((HBITMAP)_itsBitmapHandle);// Source DC.CDC srcDC;srcDC.CreateCompatibleDC();HBITMAP oldSrc = 0;// Move the bits.oldSrc = srcDC.SelectBitmap((HBITMAP)pSrc->_itsBitmapHandle);dstDC.BitBlt(xDst, yDst, dx, dy, srcDC, xSrc, ySrc, dwRop);// Put everything back.dstDC.SelectBitmap(oldDst);if (oldSrc != 0)	srcDC.SelectBitmap(oldSrc);


Do any red flags go off in your head when you are reading this code? I didn't write it and I don't know much about using GDI, so I have been struggling to find optimizations. Any help is appreciated.
You shouldn't be calling CreateCompatibleDC() all the time - make the device context once, then re-use it every tick.
Personally, I create an Image class which contains the HDC and HBITMAP (With the HBITMAP selected into the HDC), and then every tick it's just a call to BitBlt().

EDIT: And unless you're putting another HBITMAP into the dest DC, don't bother calling SelectObject on it all the time - just do that once at startup too.
scottrick49
scottrick49
Quote:
Original post by Evil Steve
You shouldn't be calling CreateCompatibleDC() all the time - make the device context once, then re-use it every tick.


Good to know, but according to the profiler, the unnecessary calls to CreateCompatibleDC are only taking up 3% of the draw time, so it doesn't seem like the main issue. dstDC.BitBlt is the main culprit at 40%.

scottrick49
Evil Steve
Evil Steve
Quote:
Original post by scottrick49
Good to know, but according to the profiler, the unnecessary calls to CreateCompatibleDC are only taking up 3% of the draw time, so it doesn't seem like the main issue. dstDC.BitBlt is the main culprit at 40%.
Are both bitmaps the same format? If not, there'll be some conversion taking place, which could be slow.
And how large are the bitmaps? BitBlt() is about as fast as you're going to get really...
Rattenhirn
Rattenhirn
Quote:
Original post by scottrick49
Good to know, but according to the profiler, the unnecessary calls to CreateCompatibleDC are only taking up 3% of the draw time, so it doesn't seem like the main issue. dstDC.BitBlt is the main culprit at 40%.


Optimise BitBlt or blit less bits. The good old "dirty rect" algorithm comes to mind...

scottrick49
scottrick49
The bitmaps are small; probably ten 64x64 images and then maybe a handful of smaller ones. I'm working on a windows mobile device, which is already pretty slow.

I am not sure about the bitmap formats. How do i tell?
scottrick49
Evil Steve
Evil Steve
Quote:
Original post by scottrick49
The bitmaps are small; probably ten 64x64 images and then maybe a handful of smaller ones. I'm working on a windows mobile device, which is already pretty slow.

I am not sure about the bitmap formats. How do i tell?
When you create the bitmaps, you have to specify the bit depth. Or, if you load the bitmap, the bit depth will be the bit depth of the source bitmap. For output to the screen, I imagine you want to have all of the bitmaps in the same bit depth as the output screen.

You can also call GetObject() on the HBITMAP to fill in a BITMAP struct, which has the bit depth in there.
scottrick49
scottrick49
Did some digging and both the images and the screen are 16 bits per pixel, so I don't think that is the issue.

Gonna keep digging...
scottrick49
scottrick49
scottrick49
Also, I've noticed that our DrawRect routine is also very slow. The problem is probably related.
IDisplay* theDisplay = IDisplay::Get();IBitmap*  theBitmap = theDisplay->GetDestination();// Dest DC.CDCHandle dstDC((HDC)_itsDC);HBITMAP oldDst = dstDC.SelectBitmap((HBITMAP)theBitmap->_itsBitmapHandle);// Offset for viewport.pRect->x += _itsViewport.x;pRect->y += _itsViewport.y;RECT rect;AEERectToRECT(*pRect, rect);// Fill if needed.if (_itsFillMode)	dstDC.FillRect(▭, (HBRUSH)_itsFillBrush);// Null brush.CBrush cBrush;HBRUSH oldBrush = dstDC.SelectBrush(AtlGetStockBrush(NULL_BRUSH));// 1 pixel thick pen.HPEN oldPen = dstDC.SelectPen((HPEN)_itsHPen);// Draw the frame.dstDC.Rectangle(▭);dstDC.SelectPen(oldPen);dstDC.SelectBrush(oldBrush);// Restore bitmapdstDC.SelectBitmap(oldDst);IBITMAP_Release(theBitmap);
scottrick49
Adam_42
Adam_42
To get an idea of the best speed you could possibly get you could time a memcpy of 64x64x2 bytes = 8KB. BitBlt() probably won't go any quicker than that, unless it gets hardware accelerated.

If memcpy is significantly faster than BitBlt you could try writing your own drawing routines using an off screen buffer, and just copy your buffer to the screen at the end.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.