Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CreateCompatibleBitmap and CreateDIBSection (Memory DC's)

from what I've read here it seems that most of the Windows GDI functions are accelerated. So for instance a call to BitBlt or AlphaBlend uses hardware acceleration if available. It also mentions that the contents of a window are kept only in video memory. Now this is all good and true for a window DC, but how can I use a memory DC that resides in video card memory? And once we've accomplished that how to obtain direct access to the pixels, I think that would involve 1. temporary copying the data to system memory 2. alter the pixel data 3. copy back to video memory.

I've tried two approaches, both allocate system memory as I can see in the task manager...

  1. CreateCompatibleBitmap

    HDC hDC = GetDC(NULL);
    m_hDC = CreateCompatibleDC(hDC);
    m_hBmp = CreateCompatibleBitmap(hDC, cx, cy);
    ReleaseDC(NULL, hDC);
    
    m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);
    

    and then call to obtain the bits

    GetBitmapBits(...)
    

    according to various comments this should indeed create the compatible bitmap in video memory, but why can I still see an increase in system memory (even when I don't call GetBitmapBits)?

  2. CreateDIBSection

    HDC hDC = GetDC(NULL);
    m_hDC = CreateCompatibleDC(hDC);
    
    BITMAPINFO bmi;
    memset(&bmi, 0, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = cx;
    bmi.bmiHeader.biHeight = -cy; // top-down
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32;
    bmi.bmiHeader.biCompression = BI_RGB;
    m_hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&m_pBits, NULL, NULL);
    
    ReleaseDC(NULL, hDC);
    
    m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);
    

    in this case we receive the pointer to the bits immediately (m_pBits) so it's obvious that these reside in system memory...

Or is it a copy that is kept in system memory for both methods? But if I change the bits in system memory a call to BitBlt would still have to check/copy from system memory again... not very optimized IMHO.

EDIT: I've also tried creating memory DC's by using the BeginBufferedPaint and GetBufferedPaintBits. It allocates system memory as well, so in that respect I suppose it's just a wrapper for the above methods but caches the DC's so a next call doesn't necessarily has to recreate a memory DC. See Raymond Chen's article.

EDIT #2: I guess the actual question is: Am I doing the memory DC creation correct in method 1 or 2 to get hardware accelerated GDI operations? To me it all seems fast, and both methods provide the same speed too, so there's not really a way to check it...

like image 912
demorge Avatar asked Sep 21 '11 15:09

demorge


1 Answers

Memory DCs are not created on a device. They are designed to put GDI output into memory.

From Memory Device Contexts on MSDN:

To enable applications to place output in memory rather than sending it to an actual device, use a special device context for bitmap operations called a memory device context. A memory DC enables the system to treat a portion of memory as a virtual device.

If you want hardware accelerated 2d graphics, you should consider using Direct2D.

like image 182
MSN Avatar answered Sep 26 '22 06:09

MSN