Karan Joisher
10 posts
StretchDIBits isn't working when it has an opengl context and is in fullscreen mode
Edited by Karan Joisher on Reason: Initial post
I have been writing a platform layer and initially I started with software rendering using StretchDIBits. I also added the toggle fullscreen function that was used in this series.

Software Blit:
  1 2 3 4 5 6 7 8 9 10 11 void PfBlitToScreen(PfWindow *window) { // Using CS_OWNDC, hence cached the deviceContext handle. HDC deviceContextHandle = window->deviceContext; int32 scanLines = StretchDIBits(deviceContextHandle, 0, 0,window->offscreenBuffer.width, window->offscreenBuffer.height, 0,0,window->offscreenBuffer.width, window->offscreenBuffer.height, window->offscreenBuffer.data, &(window->offscreenBuffer.info),DIB_RGB_COLORS,SRCCOPY); ASSERT(scanLines); } 

ToggleFullscreen:
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void PfToggleFullscreen(PfWindow *window) { DWORD windowStyle = GetWindowLong(window->windowHandle, GWL_STYLE); if(windowStyle & WS_OVERLAPPEDWINDOW) { MONITORINFO monitorInfo = {sizeof(monitorInfo)}; if(GetWindowPlacement(window->windowHandle, &(window->prevWindowPlacement)) && GetMonitorInfo(MonitorFromWindow(window->windowHandle, MONITOR_DEFAULTTOPRIMARY), &monitorInfo)) { SetWindowLong(window->windowHandle, GWL_STYLE, windowStyle & ~WS_OVERLAPPEDWINDOW); SetWindowPos(window->windowHandle, HWND_TOP, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top, SWP_NOOWNERZORDER | SWP_FRAMECHANGED); window->fullscreen = true; } } else { SetWindowLong(window->windowHandle, GWL_STYLE, windowStyle | WS_OVERLAPPEDWINDOW); SetWindowPlacement(window->windowHandle, &(window->prevWindowPlacement)); SetWindowPos(window->windowHandle, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); window->fullscreen = false; } } 

This worked as expected.
Later I added OpenGL context and still kept the option to use the PfBlitToScreen()
However when the window toggled to fullscreen mode, it would just clear the screen black.
I tried to find out the cause by stepping through the debugger but it turns out that when I stepped through the function it would output the image properly.

I later changed the PfBlitToScreen() functions such that when the window is in fullscreen mode and when the window has an OpenGL context, I would use "hardware blit" rather than "software blit" i.e. I would send the offscreen buffer as a texture to OpenGL. Having made this change, the image was properly outputted in fullscreen mode.

Modified PfBlitToScreen():
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void PfBlitToScreen(PfWindow *window) { /* HACK(KARAN): stretchdibits doesn't work in fullscreen mode when the window has an opengl context. So when in fullscreen mode and if we have a glContext, use opengl texture rendering path. */ if(window->fullscreen && (window->glContext != 0)) { PfglMakeCurrent(window); PfglRenderWindow(window); PfglSwapBuffers(window); } else { HDC deviceContextHandle = window->deviceContext;//GetDC(window->windowHandle); int32 scanLines = StretchDIBits(deviceContextHandle, 0, 0,window->offscreenBuffer.width, window->offscreenBuffer.height, 0,0,window->offscreenBuffer.width, window->offscreenBuffer.height, window->offscreenBuffer.data, &(window->offscreenBuffer.info),DIB_RGB_COLORS,SRCCOPY); ASSERT(scanLines); } } 

So my question is why does this happen and is there a way to fix this so that I can use StretchDIBits even in fullscreen OpenGL context mode.
Mārtiņš Možeiko
2198 posts / 1 project
StretchDIBits isn't working when it has an opengl context and is in fullscreen mode
Modern windows does a lot of optimizations when window is fully covering monitor. It bypasses compositor to have less lag when flipping buffers. Probably this also bypasses GDI rendered output.

I would avoid calling GDI functions on DC that has GL context created (HGLRC).