   Help optimizing image BitBlt
  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]
Quote:Original post by scottrick49Currently 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.   ;Quote:Original post by Evil SteveYou 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%.;Quote:Original post by scottrick49Good 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...   ;Quote:Original post by scottrick49Good 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...;  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?   ;Quote:Original post by scottrick49The 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.   ;  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...   ;  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(&rect, (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(&rect);dstDC.SelectPen(oldPen);dstDC.SelectBrush(oldBrush);// Restore bitmapdstDC.SelectBitmap(oldDst);IBITMAP_Release(theBitmap);;  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.   