allocating a backbuffer

This commit is contained in:
2026-01-25 14:00:33 +02:00
parent 40bb0ee554
commit 92a0d2b8aa
2 changed files with 63 additions and 17 deletions

View File

@@ -1,5 +1,5 @@
comp:
zig c++ --target=x86_64-windows -o ../build/win32_handmade.exe win32_handmade.cpp -lgdi32
zig c++ --target=x86_64-windows -o ../build/win32_handmade.exe win32_handmade.cpp -lgdi32 -g
.PHONY: clean
clean:
rm ../build/*

View File

@@ -2,17 +2,64 @@
#include <windows.h>
#include <wingdi.h>
LRESULT CALLBACK MainWindowCallback(HWND window, UINT message, WPARAM wParam,
LPARAM lParam) {
#define internal static
#define local_persist static
#define global_variable static
// NOTE: this is a global for now
global_variable bool running;
global_variable BITMAPINFO bitmapInfo;
global_variable void *bitmapMemory;
global_variable HBITMAP bitmapHandle;
global_variable HDC bitmapDeviceContext;
internal void Win32ResizeDIBSection(int width, int height) {
// TODO: bulletproof this.
// perhaps don't free first, free after, then free first if that fails
if (bitmapHandle) {
DeleteObject(bitmapHandle);
}
if (!bitmapDeviceContext) {
// TODO: should we recreate these under certain special circumstances?
bitmapDeviceContext = CreateCompatibleDC(0);
}
bitmapInfo.bmiHeader.biSize = sizeof(bitmapInfo.bmiHeader);
bitmapInfo.bmiHeader.biWidth = width;
bitmapInfo.bmiHeader.biHeight = height;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biBitCount = 24;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapHandle = CreateDIBSection(bitmapDeviceContext, &bitmapInfo,
DIB_RGB_COLORS, &bitmapMemory, 0, 0);
}
internal void Win32UpdateWindow(HDC deviceContext, int x, int y, int width,
int height) {
StretchDIBits(deviceContext, x, y, width, height, x, y, width, height,
bitmapMemory, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}
LRESULT CALLBACK Win32MainWindowCallback(HWND window, UINT message,
WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
switch (message) {
case WM_SIZE: {
RECT rect;
GetClientRect(window, &rect);
int width = rect.right - rect.left;
int height = rect.top - rect.bottom;
Win32ResizeDIBSection(width, height);
printf("WM_SIZE\n");
} break;
case WM_DESTROY: {
running = false;
// TODO: handle this as an error - recreate window?
printf("WM_DESTROY\n");
} break;
case WM_CLOSE: {
// TODO: handle this as a message to the user?
running = false;
printf("WM_CLOSE\n");
} break;
case WM_PAINT: {
@@ -22,14 +69,8 @@ LRESULT CALLBACK MainWindowCallback(HWND window, UINT message, WPARAM wParam,
int width = paint.rcPaint.right - paint.rcPaint.left;
int x = paint.rcPaint.left;
int y = paint.rcPaint.top;
Win32UpdateWindow(deviceContext, x, y, width, height);
static DWORD operation = WHITENESS;
PatBlt(deviceContext, x, y, width, height, operation);
if (operation == WHITENESS) {
operation = BLACKNESS;
} else {
operation = WHITENESS;
}
EndPaint(window, &paint);
} break;
case WM_ACTIVATEAPP: {
@@ -44,11 +85,15 @@ LRESULT CALLBACK MainWindowCallback(HWND window, UINT message, WPARAM wParam,
return res;
}
#undef RegisterClass
#undef CreateWindowEx
#undef GetMessage
#undef DispatchMessage
int CALLBACK WinMain(HINSTANCE instance, HINSTANCE prevInstance,
LPSTR commandLine, int showCode) {
WNDCLASS WindowClass = {0};
WindowClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = MainWindowCallback;
WindowClass.lpfnWndProc = Win32MainWindowCallback;
// WindowClass.cbClsExtra = ;
// WindowClass.cbWndExtra = ;
WindowClass.hInstance = instance;
@@ -57,18 +102,19 @@ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE prevInstance,
// WindowClass.lpszMenuName = ;
WindowClass.lpszClassName = "HandmadeHeroWindowClass";
if (RegisterClass(&WindowClass)) {
HWND windowHandle = CreateWindowEx(
if (RegisterClassA(&WindowClass)) {
HWND windowHandle = CreateWindowExA(
0, WindowClass.lpszClassName, "Handmade Hero",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, instance, 0);
if (windowHandle) {
running = true;
MSG message;
for (;;) {
BOOL msgResult = GetMessage(&message, 0, 0, 0);
while (running) {
BOOL msgResult = GetMessageA(&message, 0, 0, 0);
if (msgResult > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
DispatchMessageA(&message);
} else {
break;
}