Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootstrap/window #3

Merged
merged 3 commits into from
Jun 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion code/config.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
#define RT_LOG_FILE "log.txt"

#define TEMP_MEM_SIZE RT_MEGABYTES(8)
#define TEMP_MEM_SIZE RT_MEGABYTES(8)

namespace rt {
char const static *WIN_NAME = "Raytracing Engine";
char const static *WIN_CLASS = "rt_engine";
s64 constexpr static WIN_WIDTH = 1366;
s64 constexpr static WIN_HEIGHT = 768;
bool constexpr static VSYNC = true;
} // namespace rt
8 changes: 8 additions & 0 deletions code/first.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
#include "base/base.hpp"
#include "math/math.hpp"
#include "os/os.hpp"
#include "window/window.hpp"

#include "base/base.cpp"
#include "math/math.cpp"
#include "os/os.cpp"
#include "window/window.cpp"


using namespace rt;
Expand Down Expand Up @@ -52,6 +54,7 @@ main(void) {

os_start_app_timer();
os_init_filesystem();
window_create_or_panic();

String_Builder sb;

Expand All @@ -66,8 +69,13 @@ main(void) {

dbg_check_(false);

while(!window_is_closed()) {
win32_message_loop();
}

logf("Goodbye :)\n");
fflush(gLog_File);


return 0;
}
4 changes: 4 additions & 0 deletions code/math/vec.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ union Vec2 {
f32 x, y;
};

struct {
f32 width, height;
};

f32 v[2] = {};
};

Expand Down
3 changes: 2 additions & 1 deletion code/os/winapi_headers.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#define OEMRESOURCE // OEM Resource values
// #define NOATOM // Atom Manager routines
// #define NOCLIPBOARD // Clipboard routines
#define NOCOLOR // Screen colors
// #define NOCOLOR // Screen colors
// #define NOCTLMGR // Control and Dialog routines
#define NODRAWTEXT // DrawText() and DT_*
// #define NOGDI // All GDI defines and routines
Expand Down Expand Up @@ -44,6 +44,7 @@
#define NOMINMAX

#include <Windows.h>
#include <WinUser.h>

#include <debugapi.h> // __debugbreak, OutputDebugString
// MiniDump {
Expand Down
96 changes: 96 additions & 0 deletions code/window/window.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "wnd_proc.hxx"

namespace rt {
enum Window_Mode {
WindowMode_Closed = 0,
WindowMode_Open,
WindowMode_Minimized
};

struct Win32_Window {
::HWND hWnd;
// @Note: Updated by the window proc in order to avoid calls to WinApi
Window_Mode mode;
} static gWin32_Window;

void
window_create_or_panic() {
WNDCLASSEXA window_class = {
.cbSize = sizeof(WNDCLASSEX),
.style = CS_HREDRAW | CS_VREDRAW,
.lpfnWndProc = win32_main_window_proc,
.hInstance = ::GetModuleHandleA(NULL),
.hCursor = ::LoadCursorA(NULL, IDC_ARROW),
.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1),
.lpszMenuName = NULL,
.lpszClassName = WIN_CLASS
};

if (!::RegisterClassExA(&window_class)) {
errf("Failed to register window class");
}

UINT constexpr window_style = WS_OVERLAPPEDWINDOW;
RECT window_rect = {0, 0, WIN_WIDTH, WIN_HEIGHT};
::AdjustWindowRect(&window_rect, window_style, FALSE);

gWin32_Window.hWnd = ::CreateWindowA(WIN_CLASS,
WIN_NAME,
window_style,
CW_USEDEFAULT,
CW_USEDEFAULT,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
NULL,
NULL,
GetModuleHandleA(NULL),
NULL
);

if (!gWin32_Window.hWnd) {
errf("Failed to create window");
}

::ShowWindow(gWin32_Window.hWnd, 1);
::UpdateWindow(gWin32_Window.hWnd);

gWin32_Window.mode = WindowMode_Open;
}

[[nodiscard]] Vec2
window_get_size() {
::RECT rect = {};

check_(::GetClientRect(gWin32_Window.hWnd, &rect));

Vec2 const size = {
.width = (f32)rect.right - rect.left,
.height = (f32)rect.bottom - rect.top
};

return size;
}

[[nodiscard]] bool
window_is_open() {
return gWin32_Window.mode == WindowMode_Open;
}

[[nodiscard]] bool
window_is_closed() {
return gWin32_Window.mode == WindowMode_Closed;
}

[[nodiscard]] bool
window_is_minimized() {
return gWin32_Window.mode == WindowMode_Minimized;
}

void
window_close() {
::PostMessageA(gWin32_Window.hWnd, WM_CLOSE, 0, 0);
}
} // namespace rt

// @Note: needs the definitions from above
#include "wnd_proc.cxx"
19 changes: 19 additions & 0 deletions code/window/window.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace rt {
void
window_create_or_panic();

[[nodiscard]] Vec2
window_get_size();

[[nodiscard]] bool
window_is_open();

[[nodiscard]] bool
window_is_closed();

[[nodiscard]] bool
window_is_minimized();

void
window_close();
} // namespace rt
76 changes: 76 additions & 0 deletions code/window/wnd_proc.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace rt {
void
win32_message_loop() {
MSG msg = {0};
if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}

::LRESULT CALLBACK
win32_main_window_proc(::HWND hwnd, ::UINT message, ::WPARAM wParam, ::LPARAM lParam) {
bool was_message_handled = false;
::LRESULT result;

was_message_handled |= win32_window_proc(result, hwnd, message, wParam, lParam);
// ... more here ...

if (!was_message_handled) {
result = ::DefWindowProc(hwnd, message, wParam, lParam);
}

return result;
}

[[nodiscard]] bool
win32_window_proc(::LRESULT &lresult,
::HWND hwnd, ::UINT message, ::WPARAM wParam, ::LPARAM lParam) {
bool handled = true;

switch (message) {
case WM_SYSCOMMAND: {
switch (wParam) {
// @Note: this should be handled by the debug renderer too -
// don't render if we're not visible. However, the RT
// should still take place, since it's taking a bit...
case SC_MINIMIZE: {
gWin32_Window.mode = WindowMode_Minimized;
logf("win32_window_proc: MINIMIZED\n");
} break;

case SC_MAXIMIZE: {
gWin32_Window.mode = WindowMode_Open;
logf("win32_window_proc: MAXIMIZED\n");
} break;

case SC_RESTORE: {
gWin32_Window.mode = WindowMode_Open;
logf("win32_window_proc: RESTORED\n");
} break;
}
// @Note: we still need to handle the resizing somehow - use default proc.
lresult = ::DefWindowProc(hwnd, message, wParam, lParam);
} break;

case WM_CLOSE: {
::DestroyWindow(hwnd);
gWin32_Window.mode = WindowMode_Closed;
logf("win32_window_proc: WM_CLOSE\n");
lresult = 0;
} break;

case WM_DESTROY: {
::PostQuitMessage(0);
lresult = 0;
logf("win32_window_proc: WM_DESTROY\n");
} break;

default: {
handled = false;
} break;
}

return handled;
}
} // namespace rt
15 changes: 15 additions & 0 deletions code/window/wnd_proc.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace rt {
void
win32_message_loop();

// General Win32 window procedure that calls other handlers
::LRESULT CALLBACK
win32_main_window_proc(::HWND hwnd, ::UINT message, ::WPARAM wParam, ::LPARAM lParam);

// Win32 window proc for handling window-related events.
// Returns false if the message was not handled by this handler. In this case, lresult
// is not modified.
[[nodiscard]] bool
win32_window_proc(::LRESULT &lresult,
::HWND hwnd, ::UINT message, ::WPARAM wParam, ::LPARAM lParam);
} // namespace rt
8 changes: 8 additions & 0 deletions notes/notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ Main ideas:
Use ChatGPT for generating UTs for math functions & other code. Maybe roll out our
own simple UT library and add the testing as a step in GitHub pipeline?

# Window procedure
Window procedure handles (mainly) 3 types of messages: window-related, input-related
and rendering-related (special case of win-related, for example window resizing).
The idea now is that we have a one, main handler, which calls subhandlers from
different modules (window module, input module and rendering module). If the sub-handlers
don't handle the message, we fallback to the default window handler and that's it.
This will prevent the window module from being too specific / tied to other modules.

# To do / priority
- window creation
- DirectX 11 immediate pipeline
Expand Down