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:
| 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.