From 4c832f33532411bd565a0604fc341f3f14b3f0ee Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sat, 9 Sep 2023 00:01:53 -0400 Subject: [PATCH] Day 3 complete --- handmade-hero-notes | 2 +- project/gen/handmade_gen.cpp | 2 +- project/handmade_win32.cpp | 122 +++++++++++++++++++--------- project/platform/macros.h | 2 + project/platform/win32.h | 150 ++++++++++++++++++++++++++++------- 5 files changed, 209 insertions(+), 69 deletions(-) diff --git a/handmade-hero-notes b/handmade-hero-notes index 6b43c05..b67ab27 160000 --- a/handmade-hero-notes +++ b/handmade-hero-notes @@ -1 +1 @@ -Subproject commit 6b43c05d4800c498eb3c9b24e976f9a7eddf3301 +Subproject commit b67ab2734f4146a2a4bb9c3894d075cf1fe2c2cb diff --git a/project/gen/handmade_gen.cpp b/project/gen/handmade_gen.cpp index 507b486..545e059 100644 --- a/project/gen/handmade_gen.cpp +++ b/project/gen/handmade_gen.cpp @@ -12,7 +12,7 @@ int gen_main() log_fmt("Generating code for Handmade Hero\n"); log_fmt("Generaton finished for Handmade Hero\n"); - gen::deinit(); + // gen::deinit(); return 0; } #endif diff --git a/project/handmade_win32.cpp b/project/handmade_win32.cpp index a08e7db..eb7e4d4 100644 --- a/project/handmade_win32.cpp +++ b/project/handmade_win32.cpp @@ -13,11 +13,66 @@ #include "types.h" #include "win32.h" -// using namespace win32; +NS_WIN32_BEGIN -// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-wndproc -// https://learn.microsoft.com/en-us/windows/win32/winmsg/about-messages-and-message-queues#system-defined-messages -LRESULT CALLBACK MainWindowCallback( +// TODO(Ed) : This is a global for now. +global bool Running; + +global BITMAPINFO ScreenBitmapInfo; +global void* ScreenBitmapMemory; // Lets use directly mess with the "pixel's memory buffer" +global HBITMAP ScreenBitmapHandle; +global HDC ScreenDeviceContext; + +internal void +resize_dib_section( u32 width, u32 height ) +{ + // TODO(Ed) : Bulletproof memory handling here for the bitmap memory + + // TODO(Ed) : Free DIB section + + if ( ScreenBitmapHandle ) + { + DeleteObject( ScreenBitmapHandle ); + } + if ( ! ScreenDeviceContext ) + { + ScreenDeviceContext = CreateCompatibleDC( 0 ); + } + + constexpr BITMAPINFOHEADER& header = ScreenBitmapInfo.bmiHeader; + header.biSize = sizeof( header ); + header.biWidth = width; + header.biHeight = height; + header.biPlanes = 1; + header.biBitCount = 32; // Need 24, but want 32 ( alignment ) + header.biCompression = BI_RGB_Uncompressed; + header.biSizeImage = 0; + header.biXPelsPerMeter = 0; + header.biYPelsPerMeter = 0; + header.biClrUsed = 0; + header.biClrImportant = 0; + ScreenBitmapHandle = CreateDIBSection( ScreenDeviceContext, & ScreenBitmapInfo + , DIB_ColorTable_RGB, & ScreenBitmapMemory + // Ignoring these last two + , 0, 0 ); + + // ReleaseContext( 0, ScreenDeviceContext ); +} + +internal void +update_window( HDC device_context + , u32 x, u32 y + , u32 width, u32 height ) +{ + StretchDIBits( device_context + , x, y, width, height + , x, y, width, height + , ScreenBitmapMemory, & ScreenBitmapInfo + , DIB_ColorTable_RGB, RO_Source_To_Dest ); +} + +LRESULT CALLBACK +main_window_callback( HWND handle, UINT system_messages, WPARAM w_param, @@ -26,7 +81,6 @@ LRESULT CALLBACK MainWindowCallback( { LRESULT result; - // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-notifications switch ( system_messages ) { case WM_ACTIVATEAPP: @@ -37,13 +91,15 @@ LRESULT CALLBACK MainWindowCallback( case WM_CLOSE: { - OutputDebugStringA( "WM_CLOSE\n" ); + // TODO(Ed) : Handle with a message to the user + Running = false; } break; case WM_DESTROY: { - OutputDebugStringA( "WM_DESTROY\n" ); + // TODO(Ed) : Handle with as an error and recreate the window + Running = false; } break; @@ -52,21 +108,15 @@ LRESULT CALLBACK MainWindowCallback( PAINTSTRUCT info; HDC device_context = BeginPaint( handle, & info ); + u32 x = info.rcPaint.left; u32 y = info.rcPaint.top; u32 height = info.rcPaint.bottom - info.rcPaint.top; u32 width = info.rcPaint.right - info.rcPaint.left; - global DWORD operation = RO_Whiteness; - - PatBlt( device_context + update_window( handle , x, y - , width, height - , operation ); - - operation == RO_Whiteness ? - operation = RO_Blackness - : operation = RO_Whiteness; + , width, height ); EndPaint( handle, & info ); } @@ -74,6 +124,13 @@ LRESULT CALLBACK MainWindowCallback( case WM_SIZE: { + RECT client_rect; + GetClientRect( handle, & client_rect ); + + u32 width = client_rect.right - client_rect.left; + u32 height = client_rect.bottom - client_rect.top; + + resize_dib_section( width, height ); OutputDebugStringA( "WM_SIZE\n" ); } break; @@ -87,23 +144,22 @@ LRESULT CALLBACK MainWindowCallback( return result; } +NS_WIN32_END -int CALLBACK WinMain( +int CALLBACK +WinMain( HINSTANCE instance, HINSTANCE prev_instance, LPSTR commandline, int show_command ) { - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox - // MessageBox( 0, L"First message!", L"Handmade Hero", MB_Ok_Btn | MB_Icon_Information ); + using namespace win32; + MessageBox( 0, L"First message!", L"Handmade Hero", MB_Ok_Btn | MB_Icon_Information ); - // https://en.wikibooks.org/wiki/Windows_Programming/Window_Creation - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassa WNDCLASS window_class {}; - // window_class.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; window_class.style = CS_Own_Device_Context | CS_Horizontal_Redraw | CS_Vertical_Redraw; - window_class.lpfnWndProc = MainWindowCallback; + window_class.lpfnWndProc = main_window_callback; // window_class.cbClsExtra = ; // window_class.cbWndExtra = ; window_class.hInstance = instance; @@ -115,13 +171,10 @@ int CALLBACK WinMain( if ( RegisterClassW( &window_class ) ) { - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa - // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-styles HWND window_handle = CreateWindowExW( 0, window_class.lpszClassName, L"Handmade Hero", - // WS_OVERLAPPEDWINDOW | WS_VISIBLE, WS_Overlapped_Window | WS_Initially_Visible, CW_USEDEFAULT, CW_USEDEFAULT, // x, y CW_USEDEFAULT, CW_USEDEFAULT, // width, height @@ -131,36 +184,27 @@ int CALLBACK WinMain( if ( window_handle ) { - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow - // ShowWindow( window_handle, show_command ); + Running = true; - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-updatewindow - // UpdateWindow( window_handle ); - - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessage MSG message; - for (;;) + while( Running ) { BOOL msg_result = GetMessage( & message, 0, 0, 0 ); if ( msg_result > 0 ) { - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage TranslateMessage( & message ); - - // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-dispatchmessage DispatchMessage( & message ); - // break; } else { - // TODO (Ed) : Logging + // TODO(Ed) : Logging break; } } } else { - // TODO (Ed) : Logging + // TODO(Ed) : Logging } } else diff --git a/project/platform/macros.h b/project/platform/macros.h index faace17..cf19f3d 100644 --- a/project/platform/macros.h +++ b/project/platform/macros.h @@ -3,3 +3,5 @@ #define global static // Global variables #define internal static // Internal linkage #define local_persist static // Local Persisting variables + +#define api_c extern "C" diff --git a/project/platform/win32.h b/project/platform/win32.h index 064a8e5..bce6a66 100644 --- a/project/platform/win32.h +++ b/project/platform/win32.h @@ -10,19 +10,104 @@ Alternative header for windows.h // #endif #if Build_DLL -# define WIN_LIBRARY_API extern "C" __declspec(dllexport) +# define WIN_LIBRARY_API_START extern "C" __declspec(dllexport) +# define WIN_LIBRARY_API_END #else -# define WIN_LIBRARY_API extern "C" +# define WIN_LIBRARY_API_START extern "C" { +# define WIN_LIBRARY_API_END } #endif #ifndef CONST # define CONST const #endif -#define WM_ACTIVATEAPP 0x001C +#define NS_WIN32_BEGIN namespace win32 { +#define NS_WIN32_END } +NS_WIN32_BEGIN +WIN_LIBRARY_API_START -// namespace win32 { +#pragma region Gdi32 + +#define _SAL_nop_impl_ X +#define _Deref_post2_impl_(p1,p2) +#define _SAL2_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "2") _Group_(annotes _SAL_nop_impl_) +#define _Outptr_result_bytebuffer_(size) _SAL2_Source_(_Outptr_result_bytebuffer_, (size), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __bytecap_impl(size))) + +DECLARE_HANDLE(HBITMAP); + +typedef struct tagBITMAPINFOHEADER{ + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER; + +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD; + +typedef struct tagBITMAPINFO { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO, *LPBITMAPINFO, *PBITMAPINFO; + +#define GDI_DIBSIZE(bi) ((bi).biHeight < 0 ? (-1)*(GDI__DIBSIZE(bi)) : GDI__DIBSIZE(bi)) + +HDC WINAPI CreateCompatibleDC( HDC hdc); + +HBITMAP WINAPI +CreateDIBSection( + HDC hdc, + CONST BITMAPINFO *pbmi, + UINT usage, + _When_((pbmi->bmiHeader.biBitCount != 0), _Outptr_result_bytebuffer_(_Inexpressible_(GDI_DIBSIZE((pbmi->bmiHeader))))) + _When_((pbmi->bmiHeader.biBitCount == 0), _Outptr_result_bytebuffer_((pbmi->bmiHeader).biSizeImage)) + VOID **ppvBits, + HANDLE hSection, + DWORD offset +); + +typedef HANDLE HGDIOBJ; +BOOL WINAPI DeleteObject( HGDIOBJ ho); + +int WINAPI StretchDIBits( HDC hdc + , int xDest, int yDest, int DestWidth, int DestHeight + , int xSrc, int ySrc, int SrcWidth, int SrcHeight, + CONST VOID* lpBits, CONST BITMAPINFO* lpbmi + , UINT iUsage, DWORD rop ); + +typedef struct tagPAINTSTRUCT { + HDC hdc; + BOOL fErase; + RECT rcPaint; + BOOL fRestore; + BOOL fIncUpdate; + BYTE rgbReserved[32]; +} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT; + +HDC WINAPI +BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint ); + +BOOL WINAPI +EndPaint( HWND hWnd, CONST PAINTSTRUCT *lpPaint ); + +BOOL WINAPI +PatBlt( HDC hdc + , int x, int y + , int w, int h + , DWORD rop ); +#pragma endregion Gdi32 #ifdef UNICODE constexpr auto CreateWindowEx = CreateWindowExW; @@ -45,12 +130,14 @@ Alternative header for windows.h #pragma region Message Function Templates // From WinUser.h, modular headers lib doesn't have. -WIN_LIBRARY_API BOOL WINAPI GetMessageA( +BOOL WINAPI +GetMessageA( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax); -WIN_LIBRARY_API BOOL WINAPI GetMessageW( +BOOL WINAPI +GetMessageW( LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, @@ -74,29 +161,17 @@ WIN_LIBRARY_API BOOL WINAPI GetMessageW( #endif // !UNICODE #pragma endregion Message Function Templates -#pragma region Window PAINT -typedef struct tagPAINTSTRUCT { - HDC hdc; - BOOL fErase; - RECT rcPaint; - BOOL fRestore; - BOOL fIncUpdate; - BYTE rgbReserved[32]; -} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT; - -WIN_LIBRARY_API HDC WINAPI -BeginPaint( HWND hWnd, LPPAINTSTRUCT lpPaint ); - -WIN_LIBRARY_API BOOL WINAPI -EndPaint( HWND hWnd, CONST PAINTSTRUCT *lpPaint ); - -WIN_LIBRARY_API BOOL WINAPI PatBlt( HDC hdc, int x, int y, int w, int h, DWORD rop ); -#pragma endregion Window PAINT - // Class Style Constants // https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-class-styles +enum BI : DWORD +{ + BI_RGB_Uncompressed = 0L, + BI_RunLength_Encoded_8bpp = 1L, + BI_RunLength_Encoded_4bpp = 2L, +}; + enum CS : UINT { CS_Own_Device_Context = CS_OWNDC, @@ -104,12 +179,21 @@ enum CS : UINT CS_Vertical_Redraw = CS_VREDRAW, }; +enum DIB : UINT +{ + DIB_ColorTable_RGB = 0, + DIB_ColorTable_Palette = 1 + +}; + enum MB : UINT { MB_Ok_Btn = MB_OK, MB_Icon_Information = MB_ICONINFORMATION, }; +#define WM_ACTIVATEAPP 0x001C + enum WS : UINT { WS_Overlapped_Window = WS_OVERLAPPEDWINDOW, @@ -118,8 +202,18 @@ enum WS : UINT enum RasterOps : DWORD { - RO_Blackness = (DWORD)0x00000042, - RO_Whiteness = (DWORD)0x00FF0062, + RO_Source_To_Dest = (DWORD)0x00CC0020, + RO_Blackness = (DWORD)0x00000042, + RO_Whiteness = (DWORD)0x00FF0062, }; -// } +WIN_LIBRARY_API_END +NS_WIN32_END + +#undef _SAL_nop_impl_ +#undef _SAL2_Source_ +#undef _Deref_post2_impl_ +#undef _Outptr_result_bytebuffer_ +#undef _At_ +#undef _When_ +#undef GDI_DIBSIZE