win32 - StretchBlt() vs StretchDIBits()?

Started by
13 comments, last by Extrarius 18 years, 7 months ago
Quote:Original post by mark-w
it seems when I first used StretchBlt() a month ago I must have been using it inefficiently (without the clipping values etc) so I was under the impression it was really slow. Now that I took the time to manually figure out where those clipping planes should be when I 'zoom in' on my bitmap, StretchBlt() works extremely fast.

StretchBlt can be fast and it can be slow. On nvidia cards, StretchBlt is hardware accelerated and is very fast. On ATi cards (at least the ones I've tried), it is not accelerated and is dog slow, managing only 5fps or so when stretching a simple bitmap from 640x480 to 1024x768.

Quote:Original post by JakeM
uhmmm, no, no, and no. If GDI functions were hardware accelerated, then that means the device context (hDC) is also hardware accelerated, which also would mean you could create a hardware accelerated offscreen memory hDC that could be used with OpenGL, etc... But this is completely bogus. Have you ever tried to copy memory from OpenGL to GDI or vice versa? Can't do it in hardware. Show me proof if you can.

Actually, GDI is often hardware accelerated. That is done only for operation that actually draw to device DC's of course (after all, it's Graphics Device Interface). Having hardware acceleration is not mutually exclusive with having unaccelerated offscreen memory DCs. (or printer DCs). I remember the 3dfx Voodoo Banshee being touted as the first graphics card having implemented the entire GDI in hardware.
Kippesoep
Advertisement
Lets end the "does GDI support hardware accelleration" debate by going straight to the docs: MSDN docs for driver entry points to do GDI hardware accelleration.

It's up to the driver to tell GDI that it wants to handle these sorts of things. If the driver does not support it then GDI will do it in software. Even if the driver *does* ask to get called by GDI it can change it's mind again and call back to GDI to handle things anyway - this is actually the common case for things like text output (see EngTextOut which is the GDI callback that drivers make when they don't want to fully support text. In this case the driver will do things like accumulate dirty regions, have GDI do all the heavy lifting, and then do a simple blt to get the final bits on the screen.
-Mike
Quote:Original post by Anon Mike
StretchDIBits works fine. At least I haven't had any problems using it. You need to know a little more GDI magic to fully understand what all the parameters are supposed to be though.[...]
Could you explain what you mean by the last statement quoted? It seems pretty obvious from the documentation that all the parameters are the same except that for the source you need to provide info about a DIB (the pointer to it's 'bits' meaning the out parameter of CreateDIBSection and the bitmap info used to create it).
I got StretchDIBits to work fine as long as I didn't actually stretch, but as soon as I did weird random things started happening. I even tried negating various parameters and creating an upside down DIB (instead of using a negative height) but nothing made it stretch properly on any of the machines I tested it on (some of which had onboard, others had nvidia cards, and the OSes varied between 2K and XP).
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk
Quote:Extrarius
Could you explain what you mean by the last statement quoted?

Just that the docs can be a bit confusing if you don't really understand the lingo, although now that I look again I think I was thinking of SetDIBitsToDevice more than StretchDIBits.

Quote:I got StretchDIBits to work fine as long as I didn't actually stretch

Here's some that captures the upper-left 200x200 corner of the desktop into a 200x200x24bpp DIB section, then uses StretchDIBits to resize it to 50x50 and copy it to the client area of the app:

    // create the DIB section and put it in a memory DC    BITMAPINFO bitmapinfo;    ZeroMemory(&bitmapinfo, sizeof(bitmapinfo));    bitmapinfo.bmiHeader.biSize = sizeof(bitmapinfo.bmiHeader);    bitmapinfo.bmiHeader.biWidth = 200;    bitmapinfo.bmiHeader.biHeight = 200;    bitmapinfo.bmiHeader.biPlanes = 1;    bitmapinfo.bmiHeader.biBitCount = 24;    bitmapinfo.bmiHeader.biCompression = BI_RGB;    void * bits;    HDC desktop = GetDC(NULL);    HDC memory = CreateCompatibleDC(desktop);    HBITMAP dibsection = CreateDIBSection(memory, &bitmapinfo, DIB_RGB_COLORS, &bits, NULL, 0);    HBITMAP oldbitmap = SelectBitmap(memory, dibsection);    // Capture 200x200 image from the desktop    BitBlt(memory, 0, 0, 200, 200, desktop, 0, 0, SRCCOPY);    // Stretch captured image to a 50x50 region of the app client area    StretchDIBits(m_dc, 0, 0, 50, 50, 0, 0, 200, 200, bits, &bitmapinfo, DIB_RGB_COLORS, SRCCOPY);    // Cleanup    DeleteObject(SelectBitmap(memory, oldbitmap));    DeleteDC(memory);    ReleaseDC(NULL, desktop);
-Mike
I made a test application using your code and found it to mostly work, but the system still treats the coordinate system somewhat strange - it's measuring the source Y and Height from the bottom of the image even for a 'rightside up' DIB (aka negative height). I can't remeber the exact problems, but I was having some serious problems relating to source and destination coordinates not making any sense, such as working the way described above for some coordinates and in other ways at seemingly random times.
"Walk not the trodden path, for it has borne it's burden." -John, Flying Monk

This topic is closed to new replies.

Advertisement