I am attempting to author a single buffered, windowed application using the original DirectDraw interface.
This is purely for educational purposes and the just because attitude. I'm playing around with the IDirectDraw
interface (I stress this is the original version, as in DirectX 1.0).
Now, the documentation contains group of tutorials on creating a back-buffer and flipping between the primary surface and the back-buffer surface.
However, it gives no description about writing a windowed, single buffer application. In fact I can find little reference to the idea at all. There's nothing that indicates its not possible.
By setting the cooperation level with to DDSCL_NORMAL
the application behaves within a window.
hr = IDirectDraw_SetCooperativeLevel(lpDirectDraw, hWnd_, DDSCL_NORMAL);
if (hr != DD_OK)
return -1;
Followed by creating the primary surface after success.
ZeroMemory(&ddSurfaceDesc, sizeof ddSurfaceDesc);
ddSurfaceDesc.dwSize = sizeof ddSurfaceDesc;
ddSurfaceDesc.dwFlags = DDSD_CAPS;
ddSurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
hr = IDirectDraw_CreateSurface(lpDirectDraw, &ddSurfaceDesc, &lpDirectDrawPrimarySurface, (IUnknown *) NULL);
if (hr != DD_OK)
return -1;
This function also succeeds. Note that I do not create a back-buffer.
However, in my main loop:
while (fIterateLoop)
{
for (ZeroMemory(&msg, sizeof msg); PeekMessage(&msg, (HWND) NULL, 0, 0, PM_REMOVE); DispatchMessage(&msg))
fIterateLoop = msg.message == WM_QUIT ? FALSE : TRUE;
if (fDraw && lpDirectDrawPrimarySurface != (LPDIRECTDRAWSURFACE) NULL)
{
HDC hdc;
hr = IDirectDrawSurface_GetDC(lpDirectDrawPrimarySurface, &hdc);
if (hr == DD_OK)
{
SetBkColor(hdc, RGB(0, 0, 0));
SetTextColor(hdc, RGB(255, 255, 255));
TextOut(hdc, 15, 15, "hello, world!", sizeof "hello, world!" - 1);
hr = IDirectDrawSurface_ReleaseDC(lpDirectDrawPrimarySurface, hdc);
}
}
}
Nothing is drawn to the window at all. My original code (a fullscreen buffered application) correctly shows "hello, world!" in the top left-hand side of the screen and the only modifications are the tiny edits to stop the back-buffer creation, and to write directly to the primary surface.
If I call CreateSurface
with the options for a back-buffer after calling SetCooperativeLevel
with DDSCL_NORMAL
then it returns and error. This I understand because the documentation states:
If you were using IDirectDraw::SetCooperativeLevel to set the mode to DDSCL_NORMAL, you could create only surfaces that blit between the surfaces.
Have I missed something? Have I fundamentally misunderstood DirectDraw? I was under the impression that using buffers was for:
- Performance benefits, and
- To prevent screen tearing.
I care about neither of these right not. What can I do?