702 lines
23 KiB
C++
702 lines
23 KiB
C++
//
|
|
// File: win32_foldhaus.cpp
|
|
// Author: Peter Slattery
|
|
// Creation Date: 2020-01-01
|
|
//
|
|
#ifndef WIN32_FOLDHAUS_CPP
|
|
|
|
#include <Winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <intrin.h>
|
|
#include <windowsx.h>
|
|
#include <gl/gl.h>
|
|
|
|
#include "../../meta/gs_meta_include.h"
|
|
#include "../foldhaus_platform.h"
|
|
|
|
#include "../../gs_libs/gs_win32.cpp"
|
|
#include "win32_foldhaus_utils.h"
|
|
#include "win32_foldhaus_memory.h"
|
|
#include "win32_foldhaus_fileio.h"
|
|
#include "win32_foldhaus_dll.h"
|
|
#include "win32_foldhaus_timing.h"
|
|
#include "win32_foldhaus_work_queue.h"
|
|
#include "win32_foldhaus_serial.h"
|
|
#include "win32_foldhaus_socket.h"
|
|
#include "win32_foldhaus_mouse.h"
|
|
|
|
#include "../foldhaus_renderer.cpp"
|
|
|
|
#include "win32_test_code.cpp"
|
|
|
|
global b32 Running = false;
|
|
global b32 WindowIsActive = false;
|
|
|
|
char DLLName[] = "foldhaus.dll";
|
|
char WorkingDLLName[] = "foldhaus_temp.dll";
|
|
char DLLLockFileName[] = "lock.tmp";
|
|
|
|
window MainWindow;
|
|
|
|
PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle)
|
|
{
|
|
s32 Handle = SubmitTexture(Memory, Width, Height);
|
|
return Handle;
|
|
}
|
|
|
|
HDC FontDrawingDC;
|
|
HBITMAP FontBitmap;
|
|
HFONT CurrentFont;
|
|
|
|
GET_FONT_INFO(Win32GetFontInfo)
|
|
{
|
|
platform_font_info Result = {};
|
|
|
|
FontDrawingDC = CreateCompatibleDC(NULL);
|
|
SetBkColor(FontDrawingDC, RGB(0, 0, 0));
|
|
SetTextColor(FontDrawingDC, RGB(255, 255, 255));
|
|
FontBitmap = CreateCompatibleBitmap(FontDrawingDC, PixelHeight * 2, PixelHeight * 2);
|
|
HGDIOBJ SelectObjectResult = SelectObject(FontDrawingDC, FontBitmap);
|
|
|
|
CurrentFont = CreateFont(PixelHeight, 0, 0, 0,
|
|
FontWeight,
|
|
Italic,
|
|
Underline,
|
|
Strikeout,
|
|
ANSI_CHARSET,
|
|
OUT_OUTLINE_PRECIS,
|
|
CLIP_DEFAULT_PRECIS,
|
|
PROOF_QUALITY,
|
|
FIXED_PITCH,
|
|
FontName);
|
|
SelectFont(FontDrawingDC, CurrentFont);
|
|
|
|
TEXTMETRIC WindowsFontMetrics = {};
|
|
if (GetTextMetrics(FontDrawingDC, &WindowsFontMetrics))
|
|
{
|
|
Result.PixelHeight = WindowsFontMetrics.tmHeight;
|
|
Result.Ascent = WindowsFontMetrics.tmAscent;
|
|
Result.Descent = WindowsFontMetrics.tmDescent;
|
|
Result.Leading = WindowsFontMetrics.tmExternalLeading;
|
|
Result.MaxCharWidth = WindowsFontMetrics.tmMaxCharWidth;
|
|
Result.CodepointStart = WindowsFontMetrics.tmFirstChar;
|
|
Result.CodepointOnePastLast = WindowsFontMetrics.tmLastChar + 1;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
DRAW_FONT_CODEPOINT(Win32DrawFontCodepoint)
|
|
{
|
|
SIZE CodepointSize = {};
|
|
if (GetTextExtentPoint32(FontDrawingDC, &Codepoint, 1, &CodepointSize))
|
|
{
|
|
*OutWidth = CodepointSize.cx;
|
|
*OutHeight = CodepointSize.cy;
|
|
|
|
RECT TextRect = {};
|
|
TextRect.left = 0;
|
|
TextRect.right = *OutWidth;
|
|
TextRect.top = 0;
|
|
TextRect.bottom = *OutHeight;
|
|
|
|
int Error = DrawText(FontDrawingDC, &Codepoint, 1, &TextRect, DT_LEFT | DT_NOCLIP | DT_TOP);
|
|
|
|
u8* Row = DestBuffer + (YOffset * (DestBufferWidth * 4));
|
|
COLORREF PixelColor;
|
|
for (u32 Y = 0; Y < *OutHeight; Y++)
|
|
{
|
|
// NOTE(Peter): XOffset * 4 b/c its 4 bytes per pixel.
|
|
u8* Channel = (u8*)Row + (XOffset * 4);
|
|
for (u32 X = 0; X < *OutWidth; X++)
|
|
{
|
|
PixelColor = GetPixel(FontDrawingDC, X + TextRect.left, TextRect.bottom - Y);
|
|
Assert(PixelColor != CLR_INVALID);
|
|
u8 RValue = GetRValue(PixelColor);
|
|
*Channel++ = RValue;
|
|
*Channel++ = RValue;
|
|
*Channel++ = RValue;
|
|
*Channel++ = RValue;
|
|
}
|
|
Row += DestBufferWidth * 4;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
LRESULT CALLBACK
|
|
HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam)
|
|
{
|
|
LRESULT Result = 0;
|
|
|
|
switch (Msg)
|
|
{
|
|
case WM_SIZE:
|
|
{
|
|
Win32UpdateWindowDimension(&MainWindow);
|
|
//Win32ResizeDIBSection(&GlobalBackbuffer, MainWindow.Info.Width, MainWindow.Info.Height);
|
|
}break;
|
|
|
|
case WM_CLOSE:
|
|
{
|
|
Result = DefWindowProc(WindowHandle, Msg, WParam, LParam);
|
|
Running = false;
|
|
}break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
}break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT PaintStruct;
|
|
HDC DeviceContext;
|
|
b32 PaintResult;
|
|
|
|
DeviceContext = BeginPaint(WindowHandle, &PaintStruct);
|
|
PaintResult = EndPaint(WindowHandle, &PaintStruct);
|
|
}break;
|
|
|
|
case WM_ACTIVATE:
|
|
{
|
|
WindowIsActive = (LOWORD(WParam) == WA_ACTIVE || LOWORD(WParam) == WA_CLICKACTIVE);
|
|
}break;
|
|
|
|
default:
|
|
{
|
|
Result = DefWindowProc(WindowHandle, Msg, WParam, LParam);
|
|
}
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
internal void
|
|
HandleWindowMessage (MSG Message, window* Window, input_queue* InputQueue, mouse_state* Mouse)
|
|
{
|
|
switch (Message.message)
|
|
{
|
|
case WM_MOUSEWHEEL:
|
|
{
|
|
Mouse->Scroll = GET_WHEEL_DELTA_WPARAM(Message.wParam);
|
|
}break;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, false, true,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
|
|
Mouse->LeftButtonState |= KeyState_IsDown;
|
|
Mouse->DownPos = Mouse->Pos;
|
|
|
|
// :Win32MouseEventCapture
|
|
// NOTE(Peter): We capture events when the mouse goes down so that
|
|
// if the user drags outside the window, we still get the mouse up
|
|
// event and can process it. Otherwise, we can get into cases where
|
|
// an event was started, didn't end, but the user can click again and
|
|
// try to start the event again.
|
|
// We relase event capture on mouse up.
|
|
SetCapture(Window->Handle);
|
|
}break;
|
|
|
|
case WM_MBUTTONDOWN:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, false, true,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
Mouse->MiddleButtonState = KeyState_IsDown & ~KeyState_WasDown;
|
|
|
|
// :Win32MouseEventCapture
|
|
SetCapture(Window->Handle);
|
|
}break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, false, true,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
Mouse->RightButtonState = KeyState_IsDown & ~KeyState_WasDown;
|
|
Mouse->DownPos = Mouse->Pos;
|
|
|
|
// :Win32MouseEventCapture
|
|
SetCapture(Window->Handle);
|
|
}break;
|
|
|
|
case WM_LBUTTONUP:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseLeftButton, true, false,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
Mouse->LeftButtonState &= ~KeyState_IsDown;
|
|
|
|
// :Win32MouseEventCapture
|
|
ReleaseCapture();
|
|
}break;
|
|
|
|
case WM_MBUTTONUP:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseMiddleButton, true, false,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
Mouse->MiddleButtonState = ~KeyState_IsDown & KeyState_WasDown;
|
|
|
|
// :Win32MouseEventCapture
|
|
ReleaseCapture();
|
|
}break;
|
|
|
|
case WM_RBUTTONUP:
|
|
{
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
AddInputEventEntry(InputQueue, KeyCode_MouseRightButton, true, false,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
Mouse->RightButtonState = ~KeyState_IsDown & KeyState_WasDown;
|
|
|
|
// :Win32MouseEventCapture
|
|
ReleaseCapture();
|
|
}break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
case WM_SYSKEYUP:
|
|
case WM_KEYDOWN:
|
|
case WM_KEYUP:
|
|
{
|
|
#if 0
|
|
int VirtualKey = (int)Message.wParam;
|
|
key_code Key = Win32GetKeyCode(VirtualKey, true, false);
|
|
s32 KeyIndex = (int)Key;
|
|
|
|
b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0;
|
|
b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0;
|
|
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
// New Input Queue
|
|
AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
#endif
|
|
TranslateMessage(&Message);
|
|
DispatchMessage(&Message);
|
|
}break;
|
|
|
|
case WM_CHAR:
|
|
{
|
|
char VirtualKey = (char)Message.wParam;
|
|
key_code Key = CharToKeyCode(VirtualKey);
|
|
s32 KeyIndex = (int)Key;
|
|
|
|
b32 KeyWasDown = (Message.lParam & (1 << 30)) != 0;
|
|
b32 KeyIsDown = (Message.lParam & (1 << 31)) == 0;
|
|
|
|
b32 ShiftDown = GetKeyState(VK_SHIFT) & 0x8000;
|
|
b32 AltDown = GetKeyState(VK_MENU) & 0x8000;
|
|
b32 CtrlDown = GetKeyState(VK_CONTROL) & 0x8000;
|
|
|
|
// New Input Queue
|
|
AddInputEventEntry(InputQueue, Key, KeyWasDown, KeyIsDown,
|
|
ShiftDown, AltDown, CtrlDown, false);
|
|
}break;
|
|
|
|
default:
|
|
{
|
|
TranslateMessage(&Message);
|
|
DispatchMessage(&Message);
|
|
}break;
|
|
}
|
|
}
|
|
|
|
internal void
|
|
DebugPrint (char* Format, ...)
|
|
{
|
|
char Buffer[256];
|
|
gs_string StringBuffer = MakeString(Buffer, 256);
|
|
va_list Args;
|
|
va_start(Args, Format);
|
|
PrintF(&StringBuffer, Format, Args);
|
|
OutputDebugStringA(Buffer);
|
|
va_end(Args);
|
|
}
|
|
|
|
internal void
|
|
SetApplicationLinks (context* Context, win32_dll_refresh DLL, gs_work_queue* WorkQueue)
|
|
{
|
|
if (DLL.IsValid)
|
|
{
|
|
Context->InitializeApplication = (initialize_application*)GetProcAddress(DLL.DLL, "InitializeApplication");
|
|
Context->ReloadStaticData = (reload_static_data*)GetProcAddress(DLL.DLL, "ReloadStaticData");
|
|
Context->UpdateAndRender = (update_and_render*)GetProcAddress(DLL.DLL, "UpdateAndRender");
|
|
Context->CleanupApplication = (cleanup_application*)GetProcAddress(DLL.DLL, "CleanupApplication");
|
|
}
|
|
else
|
|
{
|
|
Context->InitializeApplication = 0;
|
|
Context->ReloadStaticData = 0;
|
|
Context->UpdateAndRender = 0;
|
|
Context->CleanupApplication = 0;
|
|
}
|
|
}
|
|
|
|
// TODO(Peter): :Redundant remove
|
|
internal u8*
|
|
DEBUGAlloc(s32 ElementSize, s32 ElementCount)
|
|
{
|
|
return (u8*)Win32Alloc(ElementSize * ElementCount, 0);
|
|
}
|
|
|
|
// TODO(Peter): :Redundant remove
|
|
internal u8*
|
|
Win32Realloc(u8* Buf, s32 OldSize, s32 NewSize)
|
|
{
|
|
u8* NewMemory = (u8*)Win32Alloc(NewSize, 0);
|
|
CopyMemoryTo(Buf, NewMemory, OldSize);
|
|
return NewMemory;
|
|
}
|
|
|
|
internal void
|
|
Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer* BufferAt)
|
|
{
|
|
DEBUG_TRACK_FUNCTION;
|
|
|
|
u32 BuffersSent = 0;
|
|
u32 DataSizeSent = 0;
|
|
|
|
switch(BufferAt->AddressType)
|
|
{
|
|
case AddressType_NetworkIP:
|
|
{
|
|
Win32Socket_SendTo(BufferAt->SendSocket,
|
|
BufferAt->V4SendAddress,
|
|
BufferAt->SendPort,
|
|
(const char*)BufferAt->Memory,
|
|
BufferAt->MemorySize,
|
|
0);
|
|
}break;
|
|
|
|
case AddressType_ComPort:
|
|
{
|
|
if (BufferAt->ComPort.Length > 0)
|
|
{
|
|
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
|
|
if (SerialPort != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
|
|
{
|
|
BuffersSent += 1;
|
|
DataSizeSent += BufferAt->Data.Size;
|
|
}
|
|
else
|
|
{
|
|
Win32SerialArray_Close(BufferAt->ComPort);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
OutputDebugStringA("Skipping data buffer because its COM Port isn't set");
|
|
#endif
|
|
}
|
|
}break;
|
|
|
|
InvalidDefaultCase;
|
|
}
|
|
}
|
|
|
|
internal void
|
|
Win32_SendAddressedDataBuffer_Job(gs_thread_context Context, gs_data Arg)
|
|
{
|
|
addressed_data_buffer* OutputData = (addressed_data_buffer*)Arg.Memory;
|
|
Win32_SendAddressedDataBuffer(Context, OutputData);
|
|
}
|
|
|
|
internal bool
|
|
ReloadAndLinkDLL(win32_dll_refresh* DLL, context* Context, gs_work_queue* WorkQueue, bool ShouldError)
|
|
{
|
|
bool Success = false;
|
|
if (HotLoadDLL(DLL))
|
|
{
|
|
SetApplicationLinks(Context, *DLL, WorkQueue);
|
|
Context->ReloadStaticData(*Context, GlobalDebugServices);
|
|
Success = true;
|
|
}
|
|
else if(ShouldError)
|
|
{
|
|
OutputDebugStringA("Unable to load application DLL at startup.\nAborting\n");
|
|
}
|
|
return Success;
|
|
}
|
|
|
|
internal gs_const_string
|
|
GetExePath(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
|
{
|
|
gs_const_string Result = {};
|
|
|
|
u32 Error = 0;
|
|
u32 PathSize = MAX_PATH;
|
|
char* Path = PushArray(ThreadContext.Transient, char, PathSize);
|
|
DWORD Length = GetModuleFileNameA(HInstance, Path, PathSize);
|
|
|
|
if (Length)
|
|
{
|
|
Error = GetLastError();
|
|
if (Error == ERROR_INSUFFICIENT_BUFFER) {
|
|
// PathSize wasn't long enough
|
|
// TODO(pjs): handle this case
|
|
InvalidCodePath;
|
|
}
|
|
|
|
Result.Str = Path;
|
|
Result.Length = (u64)Length;
|
|
}
|
|
else
|
|
{
|
|
Error = GetLastError();
|
|
InvalidCodePath;
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
internal bool
|
|
SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
|
|
{
|
|
bool Result = false;
|
|
|
|
gs_const_string ExePath = GetExePath(HInstance, ThreadContext);
|
|
gs_string ScratchPath = PushString(ThreadContext.Transient, ExePath.Length + 128);
|
|
gs_string WorkingDirectory = PushString(ThreadContext.Transient, ExePath.Length + 128);
|
|
|
|
while (WorkingDirectory.Length == 0)
|
|
{
|
|
s64 LastSlash = FindLastFromSet(ExePath, "\\/");
|
|
if (LastSlash < 0) break;
|
|
|
|
ExePath = Substring(ExePath, 0, LastSlash);
|
|
PrintF(&ScratchPath, "%S\\data", ExePath);
|
|
NullTerminate(&ScratchPath);
|
|
|
|
gs_file_info PathInfo = GetFileInfo(ThreadContext.FileHandler, ScratchPath.ConstString);
|
|
if (PathInfo.Path.Length > 0 &&
|
|
PathInfo.IsDirectory) {
|
|
PrintF(&WorkingDirectory, "%S", ExePath);
|
|
NullTerminate(&WorkingDirectory);
|
|
}
|
|
}
|
|
|
|
if (WorkingDirectory.Length > 0)
|
|
{
|
|
OutputDebugStringA("Setting Working Directory\n");
|
|
OutputDebugStringA(WorkingDirectory.Str);
|
|
|
|
Result = SetCurrentDirectory(WorkingDirectory.Str);
|
|
if (!Result)
|
|
{
|
|
u32 Error = GetLastError();
|
|
InvalidCodePath;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OutputDebugStringA("Error, no data folder found\n");
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
#include "../../gs_libs/gs_path.h"
|
|
|
|
int WINAPI
|
|
WinMain (
|
|
HINSTANCE HInstance,
|
|
HINSTANCE HPrevInstance,
|
|
PSTR CmdLineArgs,
|
|
INT NCmdShow
|
|
)
|
|
{
|
|
gs_thread_context ThreadContext = Win32CreateThreadContext();
|
|
|
|
gs_file_info A = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium"));
|
|
|
|
gs_file_info B = GetFileInfo(ThreadContext.FileHandler, ConstString("C:\\projects\\Lumenarium\\"));
|
|
|
|
|
|
if (!SetWorkingDirectory(HInstance, ThreadContext)) return 1;
|
|
|
|
MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
|
|
Win32UpdateWindowDimension(&MainWindow);
|
|
|
|
win32_opengl_window_info OpenGLWindowInfo = {};
|
|
OpenGLWindowInfo.ColorBits = 32;
|
|
OpenGLWindowInfo.AlphaBits = 8;
|
|
OpenGLWindowInfo.DepthBits = 0;
|
|
CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow);
|
|
|
|
context Context = {};
|
|
Context.ThreadContext = ThreadContext;
|
|
Context.MemorySize = MB(64);
|
|
Context.MemoryBase = (u8*)Win32Alloc(Context.MemorySize, 0);
|
|
|
|
gs_memory_arena PlatformPermanent = CreateMemoryArena(Context.ThreadContext.Allocator);
|
|
|
|
s64 PerformanceCountFrequency = GetPerformanceFrequency();
|
|
s64 LastFrameEnd = GetWallClock();
|
|
r32 TargetSecondsPerFrame = 1 / 60.0f;
|
|
r32 LastFrameSecondsElapsed = 0.0f;
|
|
|
|
GlobalDebugServices = PushStruct(&PlatformPermanent, debug_services);
|
|
InitDebugServices(GlobalDebugServices,
|
|
PerformanceCountFrequency,
|
|
DEBUGAlloc,
|
|
Win32Realloc,
|
|
GetWallClock,
|
|
Win32GetThreadId,
|
|
PLATFORM_THREAD_COUNT + 1);
|
|
|
|
input_queue InputQueue = InputQueue_Create(&PlatformPermanent, 32);
|
|
|
|
Win32WorkQueue_Init(&PlatformPermanent, PLATFORM_THREAD_COUNT);
|
|
|
|
// Platform functions
|
|
Context.GeneralWorkQueue = &Win32WorkQueue.WorkQueue;
|
|
Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle;
|
|
Context.PlatformGetSocketHandle = Win32GetSocketHandle;
|
|
Context.PlatformGetFontInfo = Win32GetFontInfo;
|
|
Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint;
|
|
|
|
Context.ThreadManager = PushStruct(&PlatformPermanent, platform_thread_manager);
|
|
*Context.ThreadManager = CreatePlatformThreadManager(Win32CreateThread, Win32KillThread);
|
|
|
|
Context.SocketManager = PushStruct(&PlatformPermanent, platform_socket_manager);
|
|
*Context.SocketManager = CreatePlatformSocketManager(Win32ConnectSocket, Win32CloseSocket, Win32SocketQueryStatus, Win32SocketPeek, Win32SocketReceive, Win32SocketSend);
|
|
|
|
win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName);
|
|
if (!ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, true)) { return -1; }
|
|
|
|
Mouse_Init();
|
|
|
|
Win32SocketSystem_Init(&PlatformPermanent);
|
|
|
|
Win32SerialArray_Create(ThreadContext);
|
|
|
|
render_command_buffer RenderBuffer = AllocateRenderCommandBuffer(MB(12), &PlatformPermanent, Win32Realloc);
|
|
|
|
addressed_data_buffer_list OutputData = AddressedDataBufferList_Create(ThreadContext);
|
|
|
|
Context.InitializeApplication(Context);
|
|
|
|
Running = true;
|
|
Context.WindowIsVisible = true;
|
|
while (Running)
|
|
{
|
|
if (GlobalDebugServices->RecordFrames)
|
|
{
|
|
EndDebugFrame(GlobalDebugServices);
|
|
}
|
|
DEBUG_TRACK_SCOPE(MainLoop);
|
|
|
|
ResetInputQueue(&InputQueue);
|
|
|
|
ReloadAndLinkDLL(&DLLRefresh, &Context, &Win32WorkQueue.WorkQueue, false);
|
|
|
|
AddressedDataBufferList_Clear(&OutputData);
|
|
|
|
Mouse_Update(MainWindow, &Context);
|
|
|
|
MSG Message;
|
|
while (PeekMessageA(&Message, MainWindow.Handle, 0, 0, PM_REMOVE))
|
|
{
|
|
DEBUG_TRACK_SCOPE(PeekWindowsMessages);
|
|
HandleWindowMessage(Message, &MainWindow, &InputQueue, &Context.Mouse);
|
|
}
|
|
|
|
Context.WindowBounds = rect2{v2{0, 0}, v2{(r32)MainWindow.Width, (r32)MainWindow.Height}};
|
|
RenderBuffer.ViewWidth = MainWindow.Width;
|
|
RenderBuffer.ViewHeight = MainWindow.Height;
|
|
Context.DeltaTime = LastFrameSecondsElapsed;
|
|
|
|
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
|
|
|
|
bool Multithread = true;
|
|
if (Multithread)
|
|
{
|
|
for (addressed_data_buffer* At = OutputData.Root;
|
|
At != 0;
|
|
At = At->Next)
|
|
{
|
|
gs_data ProcArg = {};
|
|
ProcArg.Memory = (u8*)At;
|
|
ProcArg.Size = sizeof(addressed_data_buffer);
|
|
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (addressed_data_buffer* At = OutputData.Root;
|
|
At != 0;
|
|
At = At->Next)
|
|
{
|
|
gs_data ProcArg = {};
|
|
ProcArg.Memory = (u8*)At;
|
|
ProcArg.Size = sizeof(addressed_data_buffer);
|
|
Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg);
|
|
}
|
|
}
|
|
|
|
RenderCommandBuffer(RenderBuffer);
|
|
ClearRenderBuffer(&RenderBuffer);
|
|
|
|
Mouse_Advance(&Context);
|
|
|
|
HDC DeviceContext = GetDC(MainWindow.Handle);
|
|
SwapBuffers(DeviceContext);
|
|
ReleaseDC(MainWindow.Handle, DeviceContext);
|
|
|
|
Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext);
|
|
|
|
s64 FinishedWorkTime = GetWallClock();
|
|
r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency);
|
|
|
|
while (SecondsElapsed < TargetSecondsPerFrame)
|
|
{
|
|
DEBUG_TRACK_SCOPE(UnusedTime);
|
|
u32 SleepTime = 1000.0f * (TargetSecondsPerFrame - SecondsElapsed);
|
|
Sleep(SleepTime);
|
|
SecondsElapsed = GetSecondsElapsed(LastFrameEnd, GetWallClock(), PerformanceCountFrequency);
|
|
}
|
|
|
|
LastFrameSecondsElapsed = SecondsElapsed;
|
|
LastFrameEnd = GetWallClock();
|
|
}
|
|
|
|
Context.CleanupApplication(Context);
|
|
|
|
Win32WorkQueue_Cleanup();
|
|
//Win32_TestCode_SocketReading_Cleanup();
|
|
|
|
Win32SocketSystem_Cleanup();
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define WIN32_FOLDHAUS_CPP
|
|
#endif // WIN32_FOLDHAUS_CPP
|