Jump to content
  • Advertisement
Sign in to follow this  

Fastest way to double buffer in Win32?

This topic is 687 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all


I am trying to make the simplest realtime raytracer possible that only renders spheres.


Before I implement the actual raytracing code, i want to make sure i have the fastest drawing and double buffering i can get out of C and win32. 


Below is a complete program that creates a 600x600 no resizable window, draws a square in the memory buffer and bitblts it to the screen. It also changes the position on a simple timer.


The tutorial that i got the code from said that it would be faster to create the Bitmap once as a global rather than create a new one each frame but every time i create the bit map either on creation or via a simple bool, the square doesnt move.


Also, are there any other tricks or techniques for faster double buffering?


Thanks for any help.

#include <windows.h>
#include <stdbool.h>

#define WNDCLASSNAME "wndclass"

//HDC hdc;
HWND hwnd;

HDC          hdcMem;
HBITMAP      hbmMem;
HANDLE       hOld;

RECT		 r;
HDC          hdc;

const int ID_TIMER = 1;

bool quit = false;

int random = 0; random2 = 0;;
int ret;
int width;
int height;
int xx = 300;
int yy = 300;
bool firstTime = true;

//  The event handler

LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
	switch (msg)
	case WM_CREATE:
		ret = SetTimer(hwnd, ID_TIMER, 5, NULL);
		if (ret == 0)
			MessageBox(hwnd, "Could not SetTimer()!", "Error", MB_OK | MB_ICONEXCLAMATION);

		GetClientRect(hwnd, &r);
		if (r.bottom == 0) {

		width = r.right;
		height = r.bottom;

	case WM_TIMER:
		switch (wparam)
		case 1:
			InvalidateRect(hwnd, NULL, FALSE);
			//ReleaseDC(hwnd, hdc);
			return 0;
		return 1;
	case WM_PAINT:

		// Get DC for window
		hdc = BeginPaint(hwnd, &ps);

		// Create an off-screen DC for double-buffering
		hdcMem = CreateCompatibleDC(hdc);

		//if (firstTime)
			hbmMem = CreateCompatibleBitmap(hdc, width, height);
			firstTime = false;

		hOld = SelectObject(hdcMem, hbmMem);

		random = rand() % 20 + (-9);
		random2 = rand() % 20 + (-9);

		xx += random;
		yy += random2;

		// Draw into hdcMem here
		for (int x = 0; x < 100; x++)
			for (int y = 0; y < 100; y++)
				SetPixel(hdcMem, x+xx, y+yy, RGB(255, 0, 0));

		// Transfer the off-screen DC to the screen
		BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);

		// Free-up the off-screen DC
		SelectObject(hdcMem, hOld);

		EndPaint(hwnd, &ps);
		ReleaseDC(hwnd, hdc);
		return 0;
	case WM_CLOSE:
		KillTimer(hwnd, ID_TIMER);
		ReleaseDC(hwnd, hdc);
	return DefWindowProc(hwnd, msg, wparam, lparam);

//  WinMain

int WINAPI WinMain(HINSTANCE hinstance,
	HINSTANCE hprevinstance,
	LPSTR lpcmdline,
	int nshowcmd)
	MSG msg;

	ex.cbSize = sizeof(WNDCLASSEX);
	ex.style = CS_OWNDC;
	ex.lpfnWndProc = WinProc;
	ex.cbClsExtra = 0;
	ex.cbWndExtra = 0;
	ex.hInstance = hinstance;
	ex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	ex.hCursor = LoadCursor(NULL, IDC_ARROW);
	ex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	ex.lpszMenuName = NULL;
	ex.lpszClassName = WNDCLASSNAME;
	ex.hIconSm = NULL;

	// Create the window 

	hwnd = CreateWindowEx(NULL,
		200, 0,
		600, 600,

	ShowWindow(hwnd, SW_SHOW);

	// The message loop
	//HDC hdc = GetDC(hwnd);

	while (!quit)
		if (PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE))
			if (msg.message == WM_QUIT)
				quit = true;


Share this post

Link to post
Share on other sites

A few things to note:

- The BitBlt should be in your main loop not in message handling under WM_PAINT.

- The bitmap should only be created once.

- Don't use SetPixel, get the address of the bitmap and write to it directly (use CreateDIBSection instead of CreateCompatibleBitmap)


If you do everything right you should only have the cost of one ram-to-vram memory copy per frame.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!