Got OpenGL kind of working again. Lots of other work recreating functionality as well, but none of its done yet.

This commit is contained in:
Peter Slattery 2019-07-21 23:30:53 -07:00
parent 134a0a1e20
commit 0f220c608d
16 changed files with 1508 additions and 931 deletions

39
build.bat Normal file
View File

@ -0,0 +1,39 @@
@echo off
set ProjectDevRoot=C:\projects
set ProjectName=foldhaus
set ProjectDevPath=%ProjectDevRoot%\%ProjectName%
pushd %ProjectDevPath%
IF NOT EXIST .\build\ mkdir .\build
C:\programs\ctime\ctime.exe -begin %ProjectDevPath%\build\win32_foldhaus_build_time.ctm
set CommonCompilerFlags=-nologo -DDEBUG=1 -DPLATFORM_WINDOWS -FC -WX -W4 -Z7 -Oi -GR- -EHsc -EHa- -MTd -fp:fast -fp:except-
set CommonCompilerFlags=-wd4127 -wd4702 -wd4101 -wd4505 -wd4100 -wd4189 -wd4244 -wd4201 -wd4996 -I%CommonLibs% -O2 %CommonCompilerFlags%
set CommonLinkerFlags= -opt:ref
pushd build
del *.pdb > NUL 2> NUL
REM Compile and Run the Preprocessor
REM cl %CommonCompilerFlags% ..\meta\foldhaus_meta.cpp /link %CommonLinkerFlags%
pushd ..\src\
REM ..\build\foldhaus_meta.exe C:\projects\foldhaus\src\
popd
REM cl %CommonCompilerFlags% F:\src\foldhaus_util_radialumia_file_converter.cpp /link %CommonLinkerFlags%
REM foldhaus_util_radialumia_file_converter.exe
echo WAITING FOR PDB TO WRITE > lock.tmp
cl %CommonCompilerFlags% ..\src\foldhaus_app.cpp /Fefoldhaus.dll /LD /link %CommonLinkerFlags% /EXPORT:InitializeApplication /EXPORT:UpdateAndRender /EXPORT:CleanupApplication /EXPORT:ReloadStaticData
set LastError=%ERRORLEVEL%
del lock.tmp
cl %CommonCompilerFlags% ..\src\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib -incremental:no
C:\programs\ctime\ctime.exe -end C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm %LastError%
C:\programs\ctime\ctime.exe -stats C:\projects\foldhaus\build\win32_foldhaus_build_time.ctm
popd

View File

@ -249,8 +249,8 @@ DrawLEDsInBufferRangeJob (s32 ThreadID, void* JobData)
v4 P2 = ModelMatrix * P2_In; v4 P2 = ModelMatrix * P2_In;
v4 P3 = ModelMatrix * P3_In; v4 P3 = ModelMatrix * P3_In;
PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color); PushTri3DOnBatch(Data->Batch, P0, P1, P2, UV0, UV1, UV2, Color, Color, Color);
PushTri3DOnBatch(Data->Batch, P0, P2, P3, UV0, UV2, UV3, Color); PushTri3DOnBatch(Data->Batch, P0, P2, P3, UV0, UV2, UV3, Color, Color, Color);
LED++; LED++;
} }
@ -418,11 +418,49 @@ INITIALIZE_APPLICATION(InitializeApplication)
if (stbtt_InitFont(&StbFont, FontFile.Base, stbtt_GetFontOffsetForIndex(FontFile.Base, 0))) if (stbtt_InitFont(&StbFont, FontFile.Base, stbtt_GetFontOffsetForIndex(FontFile.Base, 0)))
{ {
bitmap_font* Font = PushStruct(State->Permanent, bitmap_font); bitmap_font* Font = PushStruct(State->Permanent, bitmap_font);
Font->Atlas = PushTexture(State);
RenderStbttToBitmapFont(Font, StbFont, FontSize, 512, State->Permanent, State->Transient );
Font->BitmapWidth = 512;
Font->BitmapHeight = 512;
Font->BitmapBytesPerPixel = 4;
Font->BitmapMemory = PushArray(State->Permanent, u8, Font->BitmapWidth * Font->BitmapHeight * Font->BitmapBytesPerPixel);;
Font->BitmapStride = Font->BitmapWidth * Font->BitmapBytesPerPixel;
platform_font_info FontInfo = Context.PlatformGetFontInfo("Anonymous Pro", 14);
Font->PixelHeight = FontInfo.PixelHeight;
Font->Ascent = FontInfo.Ascent;
Font->Descent = FontInfo.Descent;
Font->Leading = FontInfo.Leading;
Font->MaxCharWidth = FontInfo.MaxCharWidth;
Font->CodepointDictionarySize = (FontInfo.CodepointOnePastLast - FontInfo.CodepointStart);
Font->CodepointDictionaryCount = 0;
Font->CodepointKeys = PushArray(State->Permanent, char, Font->CodepointDictionarySize);
Font->CodepointValues = PushArray(State->Permanent, codepoint_bitmap, Font->CodepointDictionarySize);
for (s32 Codepoint = FontInfo.CodepointStart;
Codepoint < FontInfo.CodepointOnePastLast;
Codepoint++)
{
u32 CodepointX, CodepointY;
GetNextCodepointOffset(Font, &CodepointX, &CodepointY);
u32 CodepointW, CodepointH;
Context.PlatformDrawFontCodepoint(
Font->BitmapMemory,
Font->BitmapWidth,
Font->BitmapHeight,
CodepointX, CodepointY,
(char)Codepoint, FontInfo,
&CodepointW, &CodepointH);
AddCodepointToFont(Font, Codepoint, 0, 0, CodepointW, CodepointH, CodepointX, CodepointY);
}
State->Interface.Font = Font; State->Interface.Font = Font;
State->Font = Font; State->Font = Font;
Font->Atlas->Handle = Context.PlatformGetGPUTextureHandle(Font->Atlas->Memory, Font->Atlas->Width, Font->Atlas->Height); Font->BitmapTextureHandle = Context.PlatformGetGPUTextureHandle(Font->BitmapMemory,
Font->BitmapWidth, Font->BitmapHeight);
} }
} else {} } else {}
} }
@ -570,12 +608,9 @@ UPDATE_AND_RENDER(UpdateAndRender)
m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera); m44 ModelViewMatrix = GetCameraModelViewMatrix(State->Camera);
m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera); m44 ProjectionMatrix = GetCameraPerspectiveProjectionMatrix(State->Camera);
RenderBuffer->ViewWidth = Context.WindowWidth;
RenderBuffer->ViewHeight = Context.WindowHeight;
r32 LEDHalfWidth = .5f; r32 LEDHalfWidth = .5f;
PushRenderPerspective(RenderBuffer, Context.WindowWidth, Context.WindowHeight, State->Camera); PushRenderPerspective(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight, State->Camera);
PushRenderClearScreen(RenderBuffer); PushRenderClearScreen(RenderBuffer);
DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle DEBUG_IF(GlobalDebugServices->Interface.RenderSculpture) // DebugServices RenderSculpture Toggle
@ -634,7 +669,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
DEBUG_TRACK_SCOPE(DrawInterface); DEBUG_TRACK_SCOPE(DrawInterface);
PushRenderOrthographic(RenderBuffer, Context.WindowWidth, Context.WindowHeight); PushRenderOrthographic(RenderBuffer, 0, 0, Context.WindowWidth, Context.WindowHeight);
// Universe Data View // Universe Data View
if (State->DrawUniverseOutputDisplay) if (State->DrawUniverseOutputDisplay)
@ -698,7 +733,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
v2{Context.WindowWidth, Context.WindowHeight}, v2{Context.WindowWidth, Context.WindowHeight},
0, State->Interface, Input); 0, State->Interface, Input);
v2 ButtonDim = v2{200, State->Interface.Font->NewLineYOffset + 10}; v2 ButtonDim = v2{200, (r32)NewLineYOffset(*State->Interface.Font) + 10};
v2 ButtonPos = v2{State->Interface.Margin.x, Context.WindowHeight - (ButtonDim.y + 10)}; v2 ButtonPos = v2{State->Interface.Margin.x, Context.WindowHeight - (ButtonDim.y + 10)};
button_result LoadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, button_result LoadAssemblyBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim,
MakeStringLiteral("Load Assembly"), MakeStringLiteral("Load Assembly"),

View File

@ -3,7 +3,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
{ {
DEBUG_TRACK_SCOPE(DrawDebugInterface); DEBUG_TRACK_SCOPE(DrawDebugInterface);
v2 TopOfDebugView = v2{StartX, WindowHeight - (Interface.Font->NewLineYOffset + 5)}; v2 TopOfDebugView = v2{StartX, WindowHeight - (NewLineYOffset(*Interface.Font) + 5)};
v2 TopOfScreenLinePos = TopOfDebugView; v2 TopOfScreenLinePos = TopOfDebugView;
arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient); arena_snapshot StartTempMemory = TakeSnapshotOfArena(*Transient);
@ -24,7 +24,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
(u32)FramesPerSecond); (u32)FramesPerSecond);
DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, WhiteV4); DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, WhiteV4);
v2 ButtonDim = v2{200, Interface.Font->NewLineYOffset + 10}; v2 ButtonDim = v2{200, (r32)NewLineYOffset(*Interface.Font) + 10};
TopOfScreenLinePos.y -= ButtonDim.y + 10; TopOfScreenLinePos.y -= ButtonDim.y + 10;
v2 ButtonPos = TopOfScreenLinePos; v2 ButtonPos = TopOfScreenLinePos;
button_result CameraBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, button_result CameraBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim,
@ -52,7 +52,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
button_result SendSACNDataBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim, button_result SendSACNDataBtn = EvaluateButton(RenderBuffer, ButtonPos, ButtonPos + ButtonDim,
SACNButtonString, Interface, Input); SACNButtonString, Interface, Input);
TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset + 10; TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font) + 10;
if (CameraBtn.Pressed) if (CameraBtn.Pressed)
{ {
@ -85,7 +85,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
3, Camera.LookAt.y, 3, Camera.LookAt.y,
3, Camera.LookAt.z); 3, Camera.LookAt.z);
DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f}); DrawString(RenderBuffer, DebugString, Interface.Font, Interface.FontSize, TopOfScreenLinePos, v4{1.0f, 1.0f, 1.0f, 1.0f});
TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset; TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
} }
if (GlobalDebugServices->Interface.ShowTrackedScopes) if (GlobalDebugServices->Interface.ShowTrackedScopes)
@ -127,7 +127,7 @@ DrawDebugInterface (render_command_buffer* RenderBuffer, r32 StartX, interface_c
Register, WhiteV4).x; Register, WhiteV4).x;
Register.x += GSMax(ColumnFourX - Register.x, 200.f); Register.x += GSMax(ColumnFourX - Register.x, 200.f);
TopOfScreenLinePos.y -= Interface.Font->NewLineYOffset; TopOfScreenLinePos.y -= NewLineYOffset(*Interface.Font);
} }

View File

@ -30,6 +30,14 @@ typedef CLEANUP_APPLICATION(cleanup_application);
// Platform Functions // Platform Functions
typedef struct platform_font_info platform_font_info;
#define GET_FONT_INFO(name) platform_font_info name(char* FontName, s32 PixelHeight)
typedef GET_FONT_INFO(platform_get_font_info);
#define DRAW_FONT_CODEPOINT(name) void name(u8* DestBuffer, s32 DestBufferWidth, s32 DestBufferHeight, u32 XOffset, u32 YOffset, char Codepoint, platform_font_info FontInfo, u32* OutWidth, u32* OutHeight)
typedef DRAW_FONT_CODEPOINT(platform_draw_font_codepoint);
// Worker Threads // Worker Threads
#define THREADED_WORK_PROC(name) void name(s32 ThreadID, void* Data) #define THREADED_WORK_PROC(name) void name(s32 ThreadID, void* Data)
@ -106,7 +114,8 @@ struct context
platform_write_entire_file* PlatformWriteEntireFile; platform_write_entire_file* PlatformWriteEntireFile;
platform_get_file_path* PlatformGetFilePath; platform_get_file_path* PlatformGetFilePath;
platform_get_gpu_texture_handle* PlatformGetGPUTextureHandle; platform_get_gpu_texture_handle* PlatformGetGPUTextureHandle;
platform_get_font_info* PlatformGetFontInfo;
platform_draw_font_codepoint* PlatformDrawFontCodepoint;
platform_get_socket_handle* PlatformGetSocketHandle; platform_get_socket_handle* PlatformGetSocketHandle;
platform_get_send_address* PlatformGetSendAddress; platform_get_send_address* PlatformGetSendAddress;
platform_set_socket_option* PlatformSetSocketOption; platform_set_socket_option* PlatformSetSocketOption;

View File

@ -18,7 +18,7 @@ Render3DQuadBatch (u8* CommandData, s32 TriCount)
v4* Colors = (v4*)(CommandData + BATCH_3D_COLORS_OFFSET(TriCount)); v4* Colors = (v4*)(CommandData + BATCH_3D_COLORS_OFFSET(TriCount));
#if IMMEDIATE_MODE_RENDERING #if IMMEDIATE_MODE_RENDERING
glBegin(GL_TRIANGLES);
for (s32 Tri = 0; Tri < TriCount; Tri++) for (s32 Tri = 0; Tri < TriCount; Tri++)
{ {
v4 P0 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)]; v4 P0 = Vertecies[BATCH_3D_VERTEX_INDEX(Tri, 0)];
@ -33,9 +33,8 @@ Render3DQuadBatch (u8* CommandData, s32 TriCount)
OpenGLDraw3DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2); OpenGLDraw3DTri(P0, P1, P2, UV0, UV1, UV2, C0, C1, C2);
} }
glEnd();
#else #else
OpenGLRenderTriBuffer((u8*)Vertecies, 4, UVs, 2, Colors, 4, TriCount * 3); OpenGLRenderTriBuffer((u8*)Vertecies, 4, (u8*)UVs, 2, (u8*)Colors, 4, TriCount * 3);
#endif #endif
} }
@ -67,7 +66,7 @@ Render2DQuadBatch (u8* CommandData, s32 QuadCount)
} }
} }
#else #else
OpenGLRenderTriBuffer((u8*)Vertecies, 2, UVs, 2, Colors, 4, QuadCount * 2 * 3); OpenGLRenderTriBuffer((u8*)Vertecies, 2, (u8*)UVs, 2, (u8*)Colors, 4, QuadCount * 2 * 3);
#endif #endif
} }
@ -76,8 +75,6 @@ RenderCommandBuffer (render_command_buffer CommandBuffer)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
glViewport(0, 0, CommandBuffer.ViewWidth, CommandBuffer.ViewHeight);
glMatrixMode(GL_TEXTURE_2D); glMatrixMode(GL_TEXTURE_2D);
glLoadIdentity(); glLoadIdentity();
@ -100,6 +97,9 @@ RenderCommandBuffer (render_command_buffer CommandBuffer)
{ {
render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1); render_command_set_render_mode* Command = (render_command_set_render_mode*)(CommandHeader + 1);
glViewport(Command->ViewOffsetX, Command->ViewOffsetY,
Command->ViewWidth, Command->ViewHeight);
LoadModelView(Command->ModelView.E); LoadModelView(Command->ModelView.E);
LoadProjection(Command->Projection.E); LoadProjection(Command->Projection.E);

View File

@ -181,6 +181,7 @@ struct render_command_set_render_mode
{ {
m44 ModelView; m44 ModelView;
m44 Projection; m44 Projection;
r32 ViewOffsetX, ViewOffsetY;
r32 ViewWidth, ViewHeight; r32 ViewWidth, ViewHeight;
b32 UseDepthBuffer; b32 UseDepthBuffer;
}; };
@ -280,7 +281,10 @@ ThreadSafeIncrementQuadConstructorCount (render_quad_batch_constructor* Construc
} }
inline void inline void
PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v2 UV0, v2 UV1, v2 UV2, v4 Color) PushTri3DOnBatch (render_quad_batch_constructor* Constructor,
v4 P0, v4 P1, v4 P2,
v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2)
{ {
s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor); s32 Tri = ThreadSafeIncrementQuadConstructorCount(Constructor);
// Vertecies // Vertecies
@ -292,17 +296,28 @@ PushTri3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4
Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 1)] = UV1; Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 1)] = UV1;
Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 2)] = UV1; Constructor->UVs[BATCH_3D_UV_INDEX(Tri, 2)] = UV1;
// Color V0 // Color V0
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 0)] = Color; Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 0)] = C0;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 1)] = Color; Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 1)] = C1;
Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 2)] = Color; Constructor->ColorsV[BATCH_3D_COLOR_INDEX(Tri, 2)] = C2;
}; };
internal void internal void
PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color) PushQuad3DOnBatch (render_quad_batch_constructor* Constructor, v4 P0, v4 P1, v4 P2, v4 P3, v2 UVMin, v2 UVMax, v4 Color)
{ {
Assert(Constructor->Count < Constructor->Max); Assert(Constructor->Count < Constructor->Max);
PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color); PushTri3DOnBatch(Constructor, P0, P1, P2, UVMin, v2{UVMax.x, UVMin.y}, UVMax, Color, Color, Color);
PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color); PushTri3DOnBatch(Constructor, P0, P2, P3, UVMin, UVMax, v2{UVMin.x, UVMax.y}, Color, Color, Color);
}
internal void
PushQuad3DOnBatch (render_quad_batch_constructor* Constructor,
v4 P0, v4 P1, v4 P2, v4 P3,
v2 UV0, v2 UV1, v2 UV2, v2 UV3,
v4 C0, v4 C1, v4 C2, v4 C3)
{
Assert(Constructor->Count < Constructor->Max);
PushTri3DOnBatch(Constructor, P0, P1, P2, UV0, UV1, UV2, C0, C1, C2);
PushTri3DOnBatch(Constructor, P0, P2, P3, UV0, UV2, UV3, C0, C2, C3);
} }
internal void internal void
@ -418,19 +433,26 @@ PushRenderCommand_ (render_command_buffer* CommandBuffer, render_command_type Co
return Result; return Result;
} }
internal void internal render_command_set_render_mode*
PushRenderPerspective (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHeight, camera Camera) PushRenderPerspective (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight, camera Camera)
{ {
render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode);
Command->ModelView = GetCameraModelViewMatrix(Camera); Command->ModelView = GetCameraModelViewMatrix(Camera);
Command->Projection = GetCameraPerspectiveProjectionMatrix(Camera); Command->Projection = GetCameraPerspectiveProjectionMatrix(Camera);
Command->ViewWidth;
Command->ViewHeight; Command->ViewOffsetX = (r32)OffsetX;
Command->ViewOffsetY = (r32)OffsetY;
Command->ViewWidth = (r32)ViewWidth;
Command->ViewHeight = (r32)ViewHeight;
Command->UseDepthBuffer = true; Command->UseDepthBuffer = true;
return Command;
} }
internal void internal void
PushRenderOrthographic (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHeight) PushRenderOrthographic (render_command_buffer* Buffer, s32 OffsetX, s32 OffsetY, s32 ViewWidth, s32 ViewHeight)
{ {
render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode); render_command_set_render_mode* Command = PushRenderCommand(Buffer, render_command_set_render_mode);
Command->ModelView = m44{ Command->ModelView = m44{
@ -448,8 +470,12 @@ PushRenderOrthographic (render_command_buffer* Buffer, s32 ViewWidth, s32 ViewHe
0, 0, 1, 0, 0, 0, 1, 0,
-1, -1, 0, 1 -1, -1, 0, 1
}; };
Command->ViewWidth;
Command->ViewHeight; Command->ViewOffsetX = (r32)OffsetX;
Command->ViewOffsetY = (r32)OffsetY;
Command->ViewWidth = ViewWidth;
Command->ViewHeight = ViewHeight;
Command->UseDepthBuffer = false;; Command->UseDepthBuffer = false;;
} }
@ -531,6 +557,21 @@ PushRenderTexture2DBatch(render_command_buffer* Buffer, s32 QuadCount,
return Result; return Result;
} }
internal render_quad_batch_constructor
PushRenderTexture2DBatch (render_command_buffer* Buffer, s32 QuadCount,
u8* TextureMemory, s32 TextureHandle, s32 TextureWidth, s32 TextureHeight,
s32 TextureBytesPerPixel, s32 TextureStride)
{
render_texture Texture = render_texture{
TextureMemory,
TextureHandle,
TextureWidth,
TextureHeight,
TextureBytesPerPixel,
TextureStride};
return PushRenderTexture2DBatch(Buffer, QuadCount, Texture);
}
internal void internal void
PushRenderTexture2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color, PushRenderTexture2D (render_command_buffer* Buffer, v2 Min, v2 Max, v4 Color,
v2 UVMin, v2 UVMax, v2 UVMin, v2 UVMax,

101
gs_font.h
View File

@ -1,6 +1,107 @@
#ifndef GS_FONT_H #ifndef GS_FONT_H
struct codepoint_bitmap
{
s32 XOffset, YOffset;
s32 Width, Height;
s32 BitmapX, BitmapY;
};
struct bitmap_font
{
char* Name;
s32 PixelHeight;
s32 Ascent;
s32 Descent;
s32 Leading;
s32 MaxCharWidth;
u32 CodepointDictionarySize;
u32 CodepointDictionaryCount;
char* CodepointKeys;
codepoint_bitmap* CodepointValues;
u8* BitmapMemory;
u32 BitmapWidth;
u32 BitmapHeight;
u32 BitmapBytesPerPixel;
u32 BitmapStride;
s32 BitmapTextureHandle;
};
internal bitmap_font
InitializeTextFont (s32 CodepointCount, u8* CodepointMemory, s32 CodepointMemorySize)
{
bitmap_font Result = {};
Result.CodepointDictionarySize = CodepointCount;
Result.CodepointDictionaryCount = 0;
Assert(CodepointMemorySize >= (sizeof(char) + sizeof(codepoint_bitmap)) * CodepointCount);
Result.CodepointKeys = (char*)CodepointMemory;
Result.CodepointValues = (codepoint_bitmap*)(CodepointMemory + (sizeof(char) * CodepointCount));
}
#define GLYPH_SKIRT 1
internal void
GetNextCodepointOffset (bitmap_font* Font, u32* X, u32* Y)
{
s32 LastCodepointIndex = Font->CodepointDictionaryCount - 1;
if (LastCodepointIndex >= 0)
{
codepoint_bitmap BitmapInfo = Font->CodepointValues[LastCodepointIndex];
u32 TempX = BitmapInfo.XOffset + BitmapInfo.Width + GLYPH_SKIRT;
u32 TempY = BitmapInfo.YOffset;
if (TempX + Font->MaxCharWidth > Font->BitmapWidth)
{
TempX = 0;
TempY -= BitmapInfo.Height + GLYPH_SKIRT;
}
*X = TempX;
*Y = TempY;
}
else
{
*X = 0;
*Y = 0;
}
}
internal void
AddCodepointToFont (bitmap_font* Font, char Codepoint,
s32 XOffset, s32 YOffset, s32 Width, s32 Height,
s32 BitmapX, s32 BitmapY)
{
Assert(Font->CodepointDictionaryCount < Font->CodepointDictionarySize);
char* Key = Font->CodepointKeys + Font->CodepointDictionaryCount;
codepoint_bitmap* Value = Font->CodepointValues + Font->CodepointDictionaryCount;
Font->CodepointDictionaryCount++;
*Key = Codepoint;
*Value = {XOffset, YOffset, Width, Height, BitmapX, BitmapY};
}
internal s32
GetIndexForCodepoint (bitmap_font Font, char Codepoint)
{
s32 Result = -1;
for (u32 i = 0; i < Font.CodepointDictionaryCount; i++)
{
if (Font.CodepointKeys[i] == Codepoint)
{
Result = i;
break;
}
}
return Result;
}
inline s32
NewLineYOffset (bitmap_font Font)
{
s32 Result = Font.Ascent - Font.Descent;
return Result;
}
#define GS_FONT_H #define GS_FONT_H
#endif #endif

View File

@ -1,4 +0,0 @@
#ifndef GS_INPUT_H
#define GS_INPUT_H
#endif

View File

@ -1,5 +1,51 @@
#ifndef GS_PLATFORM_H #ifndef GS_PLATFORM_H
#ifndef GS_LANGUAGE_H
// Types
typedef signed char b8;
typedef short int b16;
typedef int b32;
typedef long long int b64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef unsigned long long int u64;
typedef signed char s8;
typedef short int s16;
typedef int s32;
typedef long long int s64;
typedef float r32;
typedef double r64;
#define internal static
#define local_persist static
#define global_variable static
#ifdef DEBUG
#define Assert(condition) if(!(condition)) { *((int *)0) = 5; }
#define InvalidCodePath Assert(0)
#define InvalidDefaultCase default: { InvalidCodePath; }
#endif
#endif
#ifdef PLATFORM_WINDOWS
#include "gs_win32.h"
#endif
struct window_info
{
char* Name;
s32 Width;
s32 Height;
};
typedef struct window window;
#define PLATFORM_MEMORY_NO_ERROR 0
struct platform_memory_result struct platform_memory_result
{ {
u8* Base; u8* Base;
@ -7,7 +53,21 @@ struct platform_memory_result
s32 Error; s32 Error;
}; };
#define PLATFORM_MEMORY_NO_ERROR 0 struct texture_buffer
{
u8* Memory;
s32 Width;
s32 Height;
s32 Pitch;
s32 BytesPerPixel;
};
struct system_path
{
char* Path;
s32 PathLength;
s32 IndexOfLastSlash;
};
#define PLATFORM_ALLOC(name) platform_memory_result name(s32 Size) #define PLATFORM_ALLOC(name) platform_memory_result name(s32 Size)
typedef PLATFORM_ALLOC(platform_alloc); typedef PLATFORM_ALLOC(platform_alloc);
@ -21,28 +81,32 @@ typedef PLATFORM_READ_ENTIRE_FILE(platform_read_entire_file);
#define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size) #define PLATFORM_WRITE_ENTIRE_FILE(name) b32 name(char* Path, u8* Contents, s32 Size)
typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file); typedef PLATFORM_WRITE_ENTIRE_FILE(platform_write_entire_file);
#define PLATFORM_GET_FILE_PATH(name) #define PLATFORM_GET_FILE_PATH(name) b32 name(char* PathBuffer, s32 BufferLength)
typedef PLATFORM_GET_FILE_PATH(platform_get_file_path); typedef PLATFORM_GET_FILE_PATH(platform_get_file_path);
#define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) #define PLATFORM_GET_GPU_TEXTURE_HANDLE(name) s32 name(u8* Memory, s32 Width, s32 Height)
typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle); typedef PLATFORM_GET_GPU_TEXTURE_HANDLE(platform_get_gpu_texture_handle);
#define PLATFORM_GET_SOCKET_HANDLE(name) typedef s32 platform_socket_handle;
typedef s32 platform_network_address_handle;
#define PLATFORM_GET_SOCKET_HANDLE(name) platform_socket_handle name(s32 AddressFamily, s32 Type, s32 Protocol)
typedef PLATFORM_GET_SOCKET_HANDLE(platform_get_socket_handle); typedef PLATFORM_GET_SOCKET_HANDLE(platform_get_socket_handle);
#define PLATFORM_GET_SEND_ADDRESS(name) #define PLATFORM_GET_SEND_ADDRESS_HANDLE(name) platform_network_address_handle name(s32 AddressFamily, u16 Port, u32 Address)
typedef PLATFORM_GET_SEND_ADDRESS(platform_get_send_address); typedef PLATFORM_GET_SEND_ADDRESS_HANDLE(platform_get_send_address);
#define PLATFORM_SET_SOCKET_OPTION(name) #define PLATFORM_SET_SOCKET_OPTION(name) s32 name(platform_socket_handle SocketHandle, s32 Level, s32 Option, const char* OptionValue, s32 OptionLength)
typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option); typedef PLATFORM_SET_SOCKET_OPTION(platform_set_socket_option);
#define PLATFORM_SEND_TO(name) #define PLATFORM_SEND_TO(name) s32 name(platform_socket_handle SocketHandle, platform_network_address_handle AddressHandle, const char* Buffer, s32 BufferLength, s32 Flags)
typedef PLATFORM_SEND_TO(platform_send_to); typedef PLATFORM_SEND_TO(platform_send_to);
#define PLATFORM_CLOSE_SOCKET(name) #define PLATFORM_CLOSE_SOCKET(name) void name(platform_socket_handle SocketHandle)
typedef PLATFORM_CLOSE_SOCKET(platform_close_socket); typedef PLATFORM_CLOSE_SOCKET(platform_close_socket);
#ifndef GS_INPUT
#define GS_INPUT
enum key_code enum key_code
{ {
KeyCode_Invalid, KeyCode_Invalid,
@ -119,6 +183,7 @@ struct input_frame
b32 KeysDown[(int)KeyCode_Count]; b32 KeysDown[(int)KeyCode_Count];
s32 StringInputUsed; s32 StringInputUsed;
char StringInput[INPUT_FRAME_STRING_LENGTH]; char StringInput[INPUT_FRAME_STRING_LENGTH];
s32 MouseX, MouseY, MouseScroll;
}; };
struct input struct input
@ -126,6 +191,7 @@ struct input
input_frame Frames[2]; input_frame Frames[2];
input_frame* New; input_frame* New;
input_frame* Old; input_frame* Old;
s32 MouseDownX, MouseDownY;
}; };
internal void InitializeInput (input* Input); internal void InitializeInput (input* Input);
@ -167,5 +233,19 @@ KeyTransitionedUp (input Input, key_code Key)
{ {
return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key]; return !Input.New->KeysDown[Key] && Input.Old->KeysDown[Key];
} }
#endif // GS_INPUT
internal window PlatformCreateWindow (char* Name, s32 Width, s32 Height);
// Time
internal r32
GetSecondsElapsed (s64 Start, s64 End, s64 PerformanceCountFrequency)
{
r32 Result = ((r32)(End - Start) / (r32) PerformanceCountFrequency);
return Result;
}
#define GS_PLATFORM_H #define GS_PLATFORM_H
#endif // GS_PLATFORM_H #endif // GS_PLATFORM_H

View File

@ -243,9 +243,8 @@ static s32 IntToString (s32 Int, char* String, s32 Length, s32 Offset);
static float ParseFloat (char* String, s32 Length); static float ParseFloat (char* String, s32 Length);
static s32 FloatToString(float Float, char *String, s32 Length, s32 AfterPoint); static s32 FloatToString(float Float, char *String, s32 Length, s32 AfterPoint);
// Print F // PrintF
static s32 PrintF(string* String, char* Format, ...);
#define PrintString(str, format, ...) snprintf(str.Memory, str.Max, format, __VA_ARGS__); str.Length = CharArrayLength(str.Memory);
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// String Memory Function Declarations // String Memory Function Declarations
@ -1278,11 +1277,12 @@ FloatToString(float Float, char *String, s32 Length, s32 AfterPoint)
internal s32 internal s32
PrintStringF(char* Format, char* Destination, s32 DestLength, ...) PrintF (string* String, char* Format, ...)
{ {
va_list Args; va_list Args;
va_start(Args, DestLength); va_start(Args, Format);
#if 0
s32 LengthPrinted = 0; s32 LengthPrinted = 0;
char* DestChar = Destination; char* DestChar = Destination;
@ -1334,9 +1334,10 @@ PrintStringF(char* Format, char* Destination, s32 DestLength, ...)
} }
*(Destination + LengthPrinted) = 0; *(Destination + LengthPrinted) = 0;
va_end(Args); #endif
return LengthPrinted; va_end(Args);
return 0;
} }

View File

@ -66,6 +66,15 @@ union v4
r32 E[4]; r32 E[4];
}; };
#define WhiteV4 v4{1, 1, 1, 1}
#define BlackV4 v4{0, 0, 0, 1}
#define RedV4 v4{1, 0, 0, 1}
#define GreenV4 v4{0, 1, 0, 1}
#define BlueV4 v4{0, 0, 1, 1}
#define YellowV4 v4{1, 1, 0, 1}
#define TealV4 v4{0, 1, 1, 1}
#define PinkV4 v4{1, 0, 1, 1}
////////////////////////////////////// //////////////////////////////////////
// MATRIX // MATRIX
///////////////////////////////////// /////////////////////////////////////
@ -99,8 +108,8 @@ union m44
struct rect struct rect
{ {
v2 LowerLeft; v2 Min;
v2 UpperRight; v2 Max;
}; };
@ -187,6 +196,19 @@ V4OpV4Def(*)
#undef V3OpV3Def #undef V3OpV3Def
#undef V4OpV4Def #undef V4OpV4Def
#define V2RefOpV2Def(op) v2 operator##op (v2& A, v2 B) { return v2{ A.x op B.x, A.y op B.y };}
#define V3RefOpV3Def(op) v3 operator##op (v3& A, v3 B) { return v3{ A.x op B.x, A.y op B.y, A.z op B.z };}
#define V4RefOpScalarDef(op) v4 operator##op (v4& A, v4 B) { return v4{ A.x op B.x, A.y op B.y, A.z op B.z, A.w op B.w };}
V2RefOpV2Def(+=)
V2RefOpV2Def(-=)
V3RefOpV3Def(+=)
V3RefOpV3Def(-=)
V4RefOpScalarDef(+=)
V4RefOpScalarDef(-=)
#undef V2RefOpV2Def
#undef V3RefOpV3Def
#undef V4RefOpV4Def
#define V2OpScalarDef(op) v2 operator##op (v2 A, r32 B) { return v2{ A.x op B, A.y op B };} #define V2OpScalarDef(op) v2 operator##op (v2 A, r32 B) { return v2{ A.x op B, A.y op B };}
#define V3OpScalarDef(op) v3 operator##op (v3 A, r32 B) { return v3{ A.x op B, A.y op B, A.z op B };} #define V3OpScalarDef(op) v3 operator##op (v3 A, r32 B) { return v3{ A.x op B, A.y op B, A.z op B };}
#define V4OpScalarDef(op) v4 operator##op (v4 A, r32 B) { return v4{ A.x op B, A.y op B, A.z op B, A.w op B };} #define V4OpScalarDef(op) v4 operator##op (v4 A, r32 B) { return v4{ A.x op B, A.y op B, A.z op B, A.w op B };}
@ -201,9 +223,9 @@ V4OpScalarDef(/)
#undef V4POpScalarDef #undef V4POpScalarDef
#define V2POpScalarDef(op) v2 operator##op (v2* A, r32 B) { return v2{ A->x op B, A->y op B };} #define V2POpScalarDef(op) v2 operator##op (v2& A, r32 B) { return v2{ A->x op B, A->y op B };}
#define V3POpScalarDef(op) v3 operator##op (v3* A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };} #define V3POpScalarDef(op) v3 operator##op (v3& A, r32 B) { return v3{ A->x op B, A->y op B, A->z op B };}
#define V4POpScalarDef(op) v4 operator##op (v4* A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };} #define V4POpScalarDef(op) v4 operator##op (v4& A, r32 B) { return v4{ A->x op B, A->y op B, A->z op B, A->w op B };}
V2OpScalarDef(*=) V2OpScalarDef(*=)
V2OpScalarDef(/=) V2OpScalarDef(/=)
V3OpScalarDef(*=) V3OpScalarDef(*=)
@ -613,6 +635,39 @@ PointToPercentRange (v2 P, v2 Min, v2 Max)
return Result; return Result;
} }
//////////////////////////////////////
// RECT
//////////////////////////////////////
inline r32
Width (rect Rect)
{
s32 Result = Rect.Max.x - Rect.Min.x;
return Result;
}
inline r32
Height (rect Rect)
{
s32 Result = Rect.Max.y - Rect.Min.y;
return Result;
}
inline v2
CalculateRectCenter (rect Rect)
{
v2 Result = (Rect.Min + Rect.Max) / 2.0f;
return Result;
}
inline b32
PointIsInRect (v2 Point, rect Rect)
{
b32 Result = ((Point.x >= Rect.Min.x && Point.x <= Rect.Max.x) &&
(Point.y >= Rect.Min.y && Point.y <= Rect.Max.y));
return Result;
}
////////////////////////////////////// //////////////////////////////////////
// MATRIX // MATRIX
////////////////////////////////////// //////////////////////////////////////
@ -778,8 +833,6 @@ Transpose (m44 M)
static m44 static m44
GetPositionM44 (v4 Position) GetPositionM44 (v4 Position)
{ {
DEBUG_TRACK_SCOPE(GetPositionM44);
#if 1 #if 1
return m44{ return m44{
1, 0, 0, 0, 1, 0, 0, 0,

974
gs_win32.cpp Normal file
View File

@ -0,0 +1,974 @@
#ifndef GS_WIN32_CPP
struct win32_state
{
b32 Initialized;
b32 Running;
};
struct win32_opengl_window_info
{
s32 ColorBits;
s32 AlphaBits;
s32 DepthBits;
HGLRC RenderContext;
};
struct window
{
char* Name;
char* ClassName;
s32 Width;
s32 Height;
WNDPROC WindowEventHandler;
WNDCLASS Class;
HWND Handle;
HDC DeviceContext;
// TODO(peter): Make this a union?
win32_opengl_window_info OpenGLInfo;
};
struct handle_window_msg_result
{
b32 NeedsUpdate;
#ifdef DEBUG
char MessageType[128];
#endif
};
global_variable win32_state GlobalWin32State;
// Utility
internal s32 Win32StringLength(char* String);
internal s32 Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest);
// Windowing & Graphics
struct win32_offscreen_buffer
{
texture_buffer Buffer;
BITMAPINFO Info;
};
LRESULT CALLBACK Win32HandleWindowsEvents (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam);
internal handle_window_msg_result HandleWindowsMessage (HWND WindowHandle, MSG Message);
internal void Win32UpdateWindowDimension(window* Window);
internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height);
internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, window Window);
// Memory
internal PLATFORM_ALLOC(Win32Alloc);
internal PLATFORM_FREE(Win32Free);
// File IO
internal PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile);
internal PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile);
internal FILETIME Win32GetFileLastWriteTime;
// DLL
struct win32_dll_refresh
{
FILETIME LastWriteTime;
HMODULE DLL;
b32 IsValid;
char SourceDLLPath[MAX_PATH];
char WorkingDLLPath[MAX_PATH];
char LockFilePath[MAX_PATH];
};
internal b32 LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult);
internal void UnloadApplicationDLL(win32_dll_refresh* DLL);
internal win32_dll_refresh InitializeDLLHotReloading(char* SourceDLLName, char* WorkingDLLFileName, char* LockFileName);
internal b32 HotLoadDLL(win32_dll_refresh* DLL);
// Networking
///
// Utils
///
internal s32
Win32StringLength(char* String)
{
char* At = String;
while (*At) { At++; };
return At - String;
}
internal s32
Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest)
{
char* Dst = Dest;
char* AAt = A;
for (s32 a = 0; a < ALen; a++)
{
*Dst++ = *AAt++;
}
char* BAt = B;
for (s32 b = 0; b < BLen; b++)
{
*Dst++ = *BAt++;
}
return Dst - Dest;
}
///
// Windowing
///
internal window
Win32CreateWindow (HINSTANCE HInstance, char* WindowName, s32 Width, s32 Height,
WNDPROC WindowEventHandler)
{
window Result = {};
Result.Name = WindowName;
Result.ClassName = WindowName;
Result.Width = Width;
Result.Height = Height;
Result.WindowEventHandler = WindowEventHandler;
Result.Class = {};
Result.Class.style = CS_HREDRAW | CS_VREDRAW;
Result.Class.lpfnWndProc = WindowEventHandler;
Result.Class.hInstance = HInstance;
Result.Class.lpszClassName = WindowName;
if (RegisterClass(&Result.Class))
{
Result.Handle = CreateWindowEx(
0,
Result.Class.lpszClassName,
WindowName,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
Width,
Height,
0,
0,
HInstance,
0);
Result.DeviceContext = GetDC(Result.Handle);
}
return Result;
};
internal window
PlatformCreateWindow (char* WindowName, s32 Width, s32 Height)
{
HINSTANCE HInstance = GetModuleHandle(NULL);
return Win32CreateWindow(HInstance, WindowName, Width, Height, Win32HandleWindowsEvents);
}
internal void
CreateOpenGLWindowContext (win32_opengl_window_info Info, window* Window)
{
// Setup pixel format
{
PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 };
// TODO: Program seems to work perfectly fine without all other params except dwFlags.
// Can we skip other params for the sake of brevity?
PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
PixelFormatDesc.nVersion = 1;
PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info?
PixelFormatDesc.cColorBits = Info.ColorBits;
PixelFormatDesc.cAlphaBits = Info.AlphaBits;
PixelFormatDesc.cDepthBits = Info.DepthBits;
PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info?
//
s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc);
if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed
if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed
}
// Create rendering context
{
// TODO: Create "proper" context?
// https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation
Info.RenderContext = wglCreateContext(Window->DeviceContext);
wglMakeCurrent(Window->DeviceContext, Info.RenderContext);
// TODO(Peter): do we want this?
/*
glGetIntegerv(GL_MAJOR_VERSION, );
glGetIntegerv(GL_MINOR_VERSION, );
(char*)glGetString(GL_VENDOR);
(char*)glGetString(GL_RENDERER);
*/
}
Window->OpenGLInfo = Info;
}
struct handle_window_event_result
{
LRESULT Result;
b32 Handled;
};
internal void
Win32UpdateInputFrameMouseButtonState (input_frame* InputFrame, key_code KeyCode, int Win32VirtualKey)
{
InputFrame->KeysDown[KeyCode] = (GetKeyState(Win32VirtualKey) & (1 << 15)) != 0;
}
internal void
Win32UpdateInputFrameMouseState (input_frame* InputFrame)
{
Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseLeftButton, VK_LBUTTON);
Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseMiddleButton, VK_MBUTTON);
Win32UpdateInputFrameMouseButtonState(InputFrame, KeyCode_MouseRightButton, VK_RBUTTON);
// NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are
// VK_XBUTTON1 and VK_XBUTTON2
}
internal void
Win32UpdateInputFrameMouseWheelDelta (input_frame* InputFrame, MSG Message)
{
int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam);
InputFrame->MouseScroll = MouseWheel;
}
internal handle_window_event_result
HandleWindowEventUnlessWouldUseDefault (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam)
{
handle_window_event_result Result = {};
Result.Handled = false;
switch (Msg)
{
case WM_SIZE:
{
Result.Handled = true;
}break;
case WM_CLOSE:
{
Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam);
Result.Handled = true;
}break;
case WM_DESTROY:
{
GlobalWin32State.Running = false;
Result.Handled = true;
}break;
case WM_PAINT:
{
PAINTSTRUCT PaintStruct;
HDC DeviceContext;
b32 PaintResult;
DeviceContext = BeginPaint(WindowHandle, &PaintStruct);
PaintResult = EndPaint(WindowHandle, &PaintStruct);
Result.Handled = true;
}break;
}
return Result;
}
LRESULT CALLBACK
Win32HandleWindowsEvents (
HWND WindowHandle,
UINT Msg,
WPARAM wParam,
LPARAM lParam
)
{
handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault(
WindowHandle,
Msg,
wParam,
lParam);
if (!EventResult.Handled)
{
EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam);
}
return EventResult.Result;
}
#define WIN32_SHOULD_TRANSLATE_TO_CHAR -1
static int
Win32GetKeyIndex (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar)
{
int Result = WIN32_SHOULD_TRANSLATE_TO_CHAR;
if (Win32VirtualKey == VK_ESCAPE) { Result = (int)KeyCode_Esc; }
if (!TranslateToChar)
{
if (Win32VirtualKey == VK_SPACE) { Result = (int)KeyCode_Space; }
}
if (Win32VirtualKey == VK_CAPITAL) { Result = (int)KeyCode_CapsLock; }
else if (Win32VirtualKey == VK_TAB) { Result = (int)KeyCode_Tab; }
else if (Win32VirtualKey == VK_LSHIFT) { Result = (int)KeyCode_LeftShift; }
else if (Win32VirtualKey == VK_RSHIFT) { Result = (int)KeyCode_RightShift; }
else if (Win32VirtualKey == VK_LCONTROL) { Result = (int)KeyCode_LeftCtrl; }
else if (Win32VirtualKey == VK_RCONTROL) { Result = (int)KeyCode_RightCtrl; }
// TODO(Peter): support the function key?
//else if (Win32VirtualKey == VK_) { Result = (int)KeyCode_Fn; }
else if (Win32VirtualKey == VK_MENU) { Result = (int)KeyCode_Alt; }
else if (Win32VirtualKey == VK_PRIOR) { Result = (int)KeyCode_PageUp; }
else if (Win32VirtualKey == VK_NEXT) { Result = (int)KeyCode_PageDown; }
else if (Win32VirtualKey == VK_BACK) { Result = (int)KeyCode_Backspace; }
else if (Win32VirtualKey == VK_DELETE) { Result = (int)KeyCode_Delete; }
else if (Win32VirtualKey == VK_RETURN) { Result = (int)KeyCode_Enter; }
else if (Win32VirtualKey == VK_F1) { Result = (int)KeyCode_F1; }
else if (Win32VirtualKey == VK_F2) { Result = (int)KeyCode_F2; }
else if (Win32VirtualKey == VK_F3) { Result = (int)KeyCode_F3; }
else if (Win32VirtualKey == VK_F4) { Result = (int)KeyCode_F4; }
else if (Win32VirtualKey == VK_F5) { Result = (int)KeyCode_F5; }
else if (Win32VirtualKey == VK_F6) { Result = (int)KeyCode_F6; }
else if (Win32VirtualKey == VK_F7) { Result = (int)KeyCode_F7; }
else if (Win32VirtualKey == VK_F8) { Result = (int)KeyCode_F8; }
else if (Win32VirtualKey == VK_F9) { Result = (int)KeyCode_F9; }
else if (Win32VirtualKey == VK_F10) { Result = (int)KeyCode_F10; }
else if (Win32VirtualKey == VK_F11) { Result = (int)KeyCode_F11; }
else if (Win32VirtualKey == VK_F12) { Result = (int)KeyCode_F12; }
if (!TranslateToChar)
{
if (Win32VirtualKey == 0x30) { Result = (int)KeyCode_0; }
else if (Win32VirtualKey == 0x31) { Result = (int)KeyCode_1; }
else if (Win32VirtualKey == 0x32) { Result = (int)KeyCode_2; }
else if (Win32VirtualKey == 0x33) { Result = (int)KeyCode_3; }
else if (Win32VirtualKey == 0x34) { Result = (int)KeyCode_4; }
else if (Win32VirtualKey == 0x35) { Result = (int)KeyCode_5; }
else if (Win32VirtualKey == 0x36) { Result = (int)KeyCode_6; }
else if (Win32VirtualKey == 0x37) { Result = (int)KeyCode_7; }
else if (Win32VirtualKey == 0x38) { Result = (int)KeyCode_8; }
else if (Win32VirtualKey == 0x39) { Result = (int)KeyCode_9; }
else if (Win32VirtualKey == 0x41) { Result = (int)KeyCode_A; }
else if (Win32VirtualKey == 0x42) { Result = (int)KeyCode_B; }
else if (Win32VirtualKey == 0x43) { Result = (int)KeyCode_C; }
else if (Win32VirtualKey == 0x44) { Result = (int)KeyCode_D; }
else if (Win32VirtualKey == 0x45) { Result = (int)KeyCode_E; }
else if (Win32VirtualKey == 0x46) { Result = (int)KeyCode_F; }
else if (Win32VirtualKey == 0x47) { Result = (int)KeyCode_G; }
else if (Win32VirtualKey == 0x48) { Result = (int)KeyCode_H; }
else if (Win32VirtualKey == 0x49) { Result = (int)KeyCode_I; }
else if (Win32VirtualKey == 0x4A) { Result = (int)KeyCode_J; }
else if (Win32VirtualKey == 0x4B) { Result = (int)KeyCode_K; }
else if (Win32VirtualKey == 0x4C) { Result = (int)KeyCode_L; }
else if (Win32VirtualKey == 0x4D) { Result = (int)KeyCode_M; }
else if (Win32VirtualKey == 0x4E) { Result = (int)KeyCode_N; }
else if (Win32VirtualKey == 0x4F) { Result = (int)KeyCode_O; }
else if (Win32VirtualKey == 0x50) { Result = (int)KeyCode_P; }
else if (Win32VirtualKey == 0x51) { Result = (int)KeyCode_Q; }
else if (Win32VirtualKey == 0x52) { Result = (int)KeyCode_R; }
else if (Win32VirtualKey == 0x53) { Result = (int)KeyCode_S; }
else if (Win32VirtualKey == 0x54) { Result = (int)KeyCode_T; }
else if (Win32VirtualKey == 0x55) { Result = (int)KeyCode_U; }
else if (Win32VirtualKey == 0x56) { Result = (int)KeyCode_V; }
else if (Win32VirtualKey == 0x57) { Result = (int)KeyCode_W; }
else if (Win32VirtualKey == 0x58) { Result = (int)KeyCode_X; }
else if (Win32VirtualKey == 0x59) { Result = (int)KeyCode_Y; }
else if (Win32VirtualKey == 0x5A) { Result = (int)KeyCode_Z; }
}
if (NumpadValid)
{
if (Win32VirtualKey == VK_NUMPAD0) { Result = (int)KeyCode_Num0; }
else if (Win32VirtualKey == VK_NUMPAD1) { Result = (int)KeyCode_Num1; }
else if (Win32VirtualKey == VK_NUMPAD2) { Result = (int)KeyCode_Num2; }
else if (Win32VirtualKey == VK_NUMPAD3) { Result = (int)KeyCode_Num3; }
else if (Win32VirtualKey == VK_NUMPAD4) { Result = (int)KeyCode_Num4; }
else if (Win32VirtualKey == VK_NUMPAD5) { Result = (int)KeyCode_Num5; }
else if (Win32VirtualKey == VK_NUMPAD6) { Result = (int)KeyCode_Num6; }
else if (Win32VirtualKey == VK_NUMPAD7) { Result = (int)KeyCode_Num7; }
else if (Win32VirtualKey == VK_NUMPAD8) { Result = (int)KeyCode_Num8; }
else if (Win32VirtualKey == VK_NUMPAD9) { Result = (int)KeyCode_Num9; }
}
if (Win32VirtualKey == VK_UP) { Result = (int)KeyCode_UpArrow; }
else if (Win32VirtualKey == VK_DOWN) { Result = (int)KeyCode_DownArrow; }
else if (Win32VirtualKey == VK_LEFT) { Result = (int)KeyCode_LeftArrow; }
else if (Win32VirtualKey == VK_RIGHT) { Result = (int)KeyCode_RightArrow; }
return Result;
}
internal handle_window_msg_result
HandleWindowsMessage (
HWND WindowHandle,
MSG Message)
{
handle_window_msg_result Result = {};
Result.NeedsUpdate = 0;
switch (Message.message)
{
case WM_HOTKEY:
{
}break;
case WM_MOUSEWHEEL:
{
int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam);
/*
Input.New->MouseScroll = MouseWheel;
Result.NeedsUpdate = true;
*/
}break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
{
/*
Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0;
Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0;
Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0;
// NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are
// VK_XBUTTON1 and VK_XBUTTON2
if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input))
{
Input.MouseDownX = Input.New->MouseX;
Input.MouseDownY = Input.New->MouseY;
}
Result.NeedsUpdate = true;*/
}break;
case WM_MOUSEMOVE:
{
POINT MousePos;
GetCursorPos(&MousePos);
ScreenToClient(WindowHandle, &MousePos);
/*
Input.New->MouseX = MousePos.x;
Input.New->MouseY = App.WindowHeight - MousePos.y;
Result.NeedsUpdate = true;
*/
}break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
int VirtualKey = (int)Message.wParam;
bool KeyDown = (Message.lParam & (1 << 31)) == 0;
int KeyIndex = Win32GetKeyIndex(VirtualKey, true, true);
/*
if (KeyIndex >= 0)
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent ");
Input.New->KeyStates[KeyIndex] = KeyDown;
Result.NeedsUpdate = true;
}
else
{
if (Input.TranslateInputToCharValues && KeyDown)
{
// NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages
// in the message pump, and if we do it here as well, character producing
// key messages get put on the message queue twice
TranslateMessage(&Message);
DispatchMessage(&Message);
}
else
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent ");
// NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR,
// the app still has a chance to respond to it.
Result.NeedsUpdate = true;
}
}
*/
}break;
case WM_CHAR:
{
/*
char TranslatedChar = (char)Message.wParam;
int KeyIndex = GetKeyIndexFromChar(TranslatedChar);
if (KeyIndex >= 0)
{
// NOTE(Peter): Always setting this to true becuase windows is stupid and doesn't
// pass the press/release bit through correctly. So now the KEYDOWN/KEYUP Messages above
// only translate the message to a WM_CHAR message if its a key down. Since we clear all
// keystates to false at the beginning of an input frame, this will make transitions
// get registered correctly.
Input.New->KeyStates[KeyIndex] = true;
Result.NeedsUpdate = true;
}
else
{
printf("Translated Char Not Recognized: %c\n", TranslatedChar);
//InvalidCodePath;
}
*/
}break;
default:
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}break;
}
return Result;
}
internal void
Win32UpdateWindowDimension(window* Window)
{
RECT ClientRect;
GetClientRect(Window->Handle, &ClientRect);
Window->Width = ClientRect.right - ClientRect.left;
Window->Height = ClientRect.bottom - ClientRect.top;
}
internal void
Win32ResizeDIBSection(win32_offscreen_buffer *Win32Buffer, int Width, int Height)
{
if(Win32Buffer->Buffer.Memory)
{
VirtualFree(Win32Buffer->Buffer.Memory, 0, MEM_RELEASE);
}
Win32Buffer->Buffer.Width = Width;
Win32Buffer->Buffer.Height = Height;
int BytesPerPixel = 4;
Win32Buffer->Buffer.BytesPerPixel = BytesPerPixel;
Win32Buffer->Info.bmiHeader.biSize = sizeof(Win32Buffer->Info.bmiHeader);
Win32Buffer->Info.bmiHeader.biWidth = Win32Buffer->Buffer.Width;
Win32Buffer->Info.bmiHeader.biHeight = -Win32Buffer->Buffer.Height; // Top down, not bottom up
Win32Buffer->Info.bmiHeader.biPlanes = 1;
Win32Buffer->Info.bmiHeader.biBitCount = 32;
Win32Buffer->Info.bmiHeader.biCompression = BI_RGB;
int BitmapMemorySize = (Win32Buffer->Buffer.Width * Win32Buffer->Buffer.Height)*BytesPerPixel;
Win32Buffer->Buffer.Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
Win32Buffer->Buffer.Pitch = Width*BytesPerPixel;
}
internal void
Win32DisplayBufferInWindow(win32_offscreen_buffer* Win32Buffer, window Window)
{
StretchDIBits(Window.DeviceContext,
0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height,
0, 0, Win32Buffer->Buffer.Width, Win32Buffer->Buffer.Height,
Win32Buffer->Buffer.Memory,
&Win32Buffer->Info,
DIB_RGB_COLORS, SRCCOPY);
}
///
// Memory
///
internal u8*
Win32BasicAlloc (s32 Size)
{
return (u8*)VirtualAlloc(NULL, Size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
}
PLATFORM_ALLOC(Win32Alloc)
{
platform_memory_result Result = {};
Result.Error = PLATFORM_MEMORY_NO_ERROR;
Result.Base = Win32BasicAlloc(Size);
if (Result.Base)
{
Result.Size = Size;
}
else
{
Result.Error = 1;
}
return Result;
}
PLATFORM_FREE(Win32Free)
{
b32 Result = VirtualFree(Base, Size, MEM_RELEASE);
return Result;
}
// File IO
PLATFORM_READ_ENTIRE_FILE(Win32ReadEntireFile)
{
platform_memory_result Result = {};
Result.Error = PLATFORM_MEMORY_NO_ERROR;
HANDLE FileHandle = CreateFileA (
Path,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
DWORD FileSize = GetFileSize(FileHandle, NULL);
Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (Result.Base)
{
Result.Size = FileSize;
s32 BytesRead = 0;
if (ReadFile(FileHandle, (LPVOID)Result.Base, FileSize, (LPDWORD)(&BytesRead), NULL))
{
}
else
{
Result.Size = 0;
Result.Error = 1;
}
}
CloseHandle(FileHandle);
}
else
{
// TODO(Peter): failure
}
return Result;
}
PLATFORM_WRITE_ENTIRE_FILE(Win32WriteEntireFile)
{
b32 Result = false;
HANDLE FileHandle = CreateFileA (
Path,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
DWORD BytesWritten = 0;
b32 WriteSuccess = WriteFile(FileHandle,
Contents, Size,
&BytesWritten,
NULL);
if (WriteSuccess && BytesWritten == (u32)Size)
{
CloseHandle(FileHandle);
Result = true;
}
else
{
Result = false;
}
}
else
{
Result = false;
}
return Result;
}
internal FILETIME
GetFileLastWriteTime(char* Path)
{
FILETIME Result = {};
WIN32_FIND_DATA FindData = {};
HANDLE FileHandle = FindFirstFileA(Path, &FindData);
if (FileHandle != INVALID_HANDLE_VALUE)
{
Result = FindData.ftLastWriteTime;
FindClose(FileHandle);
}
else
{
// TODO(Peter): Error handling
}
return Result;
}
PLATFORM_GET_FILE_PATH(Win32SystemDialogueOpenFile)
{
b32 Result = false;
return Result;
}
///
// DLL
///
internal void
GetApplicationPath(system_path* Result)
{
Assert(Result->Path);
Result->PathLength = GetModuleFileNameA(0, Result->Path, Result->PathLength);
u32 CharactersScanned = 0;
u32 IndexOfLastSlash = 0;
char *Scan = Result->Path;
while(*Scan)
{
if (*Scan == '\\')
{
Result->IndexOfLastSlash = CharactersScanned + 1;
}
Scan++;
CharactersScanned++;
}
}
internal b32
LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult)
{
b32 Success = false;
Assert(DLLResult->DLL == 0);
DLLResult->DLL = LoadLibraryA(DLLName); // TODO(Peter): Error checking
if (DLLResult->DLL)
{
Success = true;
DLLResult->IsValid = true;
}
return Success;
}
internal void
UnloadApplicationDLL(win32_dll_refresh* DLL)
{
if (DLL->DLL)
{
FreeLibrary(DLL->DLL);
}
DLL->DLL = 0;
DLL->IsValid = false;
}
internal win32_dll_refresh
InitializeDLLHotReloading(char* SourceDLLName,
char* WorkingDLLFileName,
char* LockFileName)
{
win32_dll_refresh Result = {};
Result.IsValid = false;
system_path ExePath = {};
ExePath.PathLength = MAX_PATH;
ExePath.Path = (char*)Win32BasicAlloc(ExePath.PathLength);
GetApplicationPath(&ExePath);
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(SourceDLLName), SourceDLLName,
MAX_PATH, Result.SourceDLLPath);
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(WorkingDLLFileName), WorkingDLLFileName,
MAX_PATH, Result.WorkingDLLPath);
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(LockFileName), LockFileName,
MAX_PATH, Result.LockFilePath);
Win32Free((u8*)ExePath.Path, ExePath.PathLength);
return Result;
}
internal b32
HotLoadDLL(win32_dll_refresh* DLL)
{
b32 DidReload = false;
FILETIME UpdatedLastWriteTime = GetFileLastWriteTime(DLL->SourceDLLPath);
if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime))
{
WIN32_FILE_ATTRIBUTE_DATA Ignored;
if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored))
{
UnloadApplicationDLL(DLL);
CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE);
LoadApplicationDLL(DLL->WorkingDLLPath, DLL);
DLL->LastWriteTime = UpdatedLastWriteTime;
DidReload = true;
}
}
return DidReload;
}
/////////////////////////////////////////
//
// Timing
//
/////////////////////////////////////////
internal s64
GetPerformanceFrequency ()
{
LARGE_INTEGER Frequency;
if (!QueryPerformanceFrequency(&Frequency))
{
s32 Error = GetLastError();
InvalidCodePath;
}
return (s64)Frequency.QuadPart;
}
internal s64
GetWallClock ()
{
LARGE_INTEGER Time;
if (!QueryPerformanceCounter(&Time))
{
s32 Error = GetLastError();
InvalidCodePath;
}
return (s64)Time.QuadPart;
}
/////////////////////////////////////////
//
// Open GL
//
/////////////////////////////////////////
internal void
OpenGLRenderTriBuffer (u8* Vertecies, s32 VertexElements,
u8* UVs, s32 UVElements,
u8* Colors, s32 ColorsElements,
s32 TriCount)
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(VertexElements, GL_FLOAT, VertexElements * sizeof(r32), Vertecies);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(UVElements, GL_FLOAT, UVElements * sizeof(r32), UVs);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(ColorsElements, GL_FLOAT, ColorsElements * sizeof(r32), Colors);
glDrawArrays(GL_TRIANGLES, 0, TriCount);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
}
internal void
OpenGLDraw3DTri (v4 P0, v4 P1, v4 P2,
v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2)
{
glBegin(GL_TRIANGLES);
glTexCoord2f(UV0.x, UV0.y);
glColor4f(C0.r, C0.g, C0.b, C0.a);
glVertex4f(P0.x, P0.y, P0.z, P0.w);
glTexCoord2f(UV1.x, UV1.y);
glColor4f(C1.r, C1.g, C1.b, C1.a);
glVertex4f(P1.x, P1.y, P1.z, P1.w);
glTexCoord2f(UV2.x, UV2.y);
glColor4f(C2.r, C2.g, C2.b, C2.a);
glVertex4f(P2.x, P2.y, P2.z, P2.w);
glEnd();
}
internal void
OpenGLDraw2DTri (v2 P0, v2 P1, v2 P2,
v2 UV0, v2 UV1, v2 UV2,
v4 C0, v4 C1, v4 C2)
{
glBegin(GL_TRIANGLES);
glTexCoord2f(UV0.x, UV0.y);
glColor4f(C0.r, C0.g, C0.b, C0.a);
glVertex2f(P0.x, P0.y);
glTexCoord2f(UV1.x, UV1.y);
glColor4f(C1.r, C1.g, C1.b, C1.a);
glVertex2f(P1.x, P1.y);
glTexCoord2f(UV2.x, UV2.y);
glColor4f(C2.r, C2.g, C2.b, C2.a);
glVertex2f(P2.x, P2.y);
glEnd();
}
internal void
LoadModelView (r32 Matrix[16])
{
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(Matrix);
}
internal void
LoadProjection (r32 Matrix[16])
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(Matrix);
}
internal void
ClearRenderBuffer ()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
s32 NextTextureHandle = 1;
internal s32
SubmitTexture (u8* Memory, s32 Width, s32 Height)
{
s32 TextureHandle = NextTextureHandle++;
glBindTexture(GL_TEXTURE_2D, TextureHandle);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, Memory);
return TextureHandle;
}
internal void
BindTexture (s32 TextureHandle)
{
glBindTexture(GL_TEXTURE_2D, TextureHandle);
}
#define GS_WIN32_CPP
#endif // GS_WIN32_CPP

View File

@ -1,831 +1,17 @@
#ifndef GS_WIN32_H #ifndef GS_WIN32_H
#ifdef DEBUG struct platform_font_info
#define DEBUG_GET_MESSAGE_NAME(string, message) sprintf(string, message);
#else
#define DEBUG_GET_MESSAGE_NAME(string, message)
#endif
struct win32_state
{ {
b32 Initialized; s32 PixelHeight;
b32 Running; s32 Ascent, Descent, Leading;
s32 MaxCharWidth;
s32 CodepointStart;
s32 CodepointOnePastLast;
HDC DrawingDC;
HBITMAP Bitmap;
HFONT Font;
}; };
struct win32_window_info
{
char* Name;
char* ClassName;
s32 Width;
s32 Height;
WNDPROC WindowEventsHandler; // If this is left null, Win32HandleWindowsEvents will be used
};
struct win32_opengl_window_info
{
s32 ColorBits;
s32 AlphaBits;
s32 DepthBits;
HGLRC RenderContext;
};
struct win32_window
{
win32_window_info Info;
WNDCLASS Class;
HWND Handle;
HDC DeviceContext;
// TODO(peter): Make this a union?
win32_opengl_window_info OpenGLInfo;
};
struct handle_window_msg_result
{
b32 NeedsUpdate;
#ifdef DEBUG
char MessageType[128];
#endif
};
global_variable win32_state GlobalWin32State;
// Utility
internal s32 Win32StringLength(char* String);
internal s32 Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest);
// Windowing & Graphics
struct win32_offscreen_buffer
{
u8* Memory;
s32 Width;
s32 Height;
s32 Pitch;
s32 BytesPerPixel;
BITMAPINFO Info;
};
internal void InitializeWin32();
internal win32_window CreateWin32Window (char* WindowName, char* WindowClassName, s32 Width, s32 Height);
LRESULT CALLBACK Win32HandleWindowsEvents (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam);
internal handle_window_msg_result HandleWindowsMessage (HWND WindowHandle, MSG Message);
internal void Win32UpdateWindowDimension(win32_window* Window);
internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height);
internal void Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, win32_window Window);
// Memory
internal platform_memory_result Win32Alloc(s32 Size);
internal b32 Win32Free(u8* Base, s32 Size);
// File IO
internal platform_memory_result ReadEntireFile(char* Path);
internal b32 WriteEntireFile(char* Path, u8* Contents, s32 Size);
internal FILETIME GetFileLastWriteTime(char* Path);
// DLL
struct win32_dll_refresh
{
FILETIME LastWriteTime;
HMODULE DLL;
b32 IsValid;
char SourceDLLPath[MAX_PATH];
char WorkingDLLPath[MAX_PATH];
char LockFilePath[MAX_PATH];
};
struct executable_path
{
char Path[MAX_PATH];
s32 PathLength;
s32 IndexOfLastSlash;
};
internal executable_path GetApplicationPath();
internal b32 LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult);
internal void UnloadApplicationDLL(win32_dll_refresh* DLL);
internal win32_dll_refresh InitializeDLLHotReloading(char* SourceDLLName, char* WorkingDLLFileName, char* LockFileName);
internal b32 HotLoadDLL(win32_dll_refresh* DLL);
///
// Utils
///
internal s32
Win32StringLength(char* String)
{
char* At = String;
while (*At) { At++; };
return At - String;
}
internal s32
Win32ConcatStrings(s32 ALen, char* A, s32 BLen, char* B, s32 DestLen, char* Dest)
{
char* Dst = Dest;
char* AAt = A;
for (s32 a = 0; a < ALen; a++)
{
*Dst++ = *AAt++;
}
char* BAt = B;
for (s32 b = 0; b < BLen; b++)
{
*Dst++ = *BAt++;
}
return Dst - Dest;
}
///
// Windowing
///
internal void
InitializeWin32 ()
{
GlobalWin32State = {};
GlobalWin32State.Running = false;
GlobalWin32State.Initialized = true;
}
internal win32_window
CreateWin32Window (HINSTANCE HInstance, win32_window_info Info)
{
win32_window Result = {};
Result.Info = Info;
Result.Class = {};
Result.Class.style = CS_HREDRAW | CS_VREDRAW;
if (Info.WindowEventsHandler)
{
Result.Class.lpfnWndProc = Info.WindowEventsHandler;
}
else
{
Result.Class.lpfnWndProc = Win32HandleWindowsEvents;
}
Result.Class.hInstance = HInstance;
Result.Class.lpszClassName = Info.ClassName;
if (RegisterClass(&Result.Class))
{
Result.Handle = CreateWindowEx(
0,
Result.Class.lpszClassName,
Info.Name,
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
Info.Width,
Info.Height,
0,
0,
HInstance,
0);
Result.DeviceContext = GetDC(Result.Handle);
}
return Result;
};
internal void
CreateOpenGLWindowContext (win32_opengl_window_info Info, win32_window* Window)
{
// Setup pixel format
{
PIXELFORMATDESCRIPTOR PixelFormatDesc = { 0 };
// TODO: Program seems to work perfectly fine without all other params except dwFlags.
// Can we skip other params for the sake of brevity?
PixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
PixelFormatDesc.nVersion = 1;
PixelFormatDesc.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
PixelFormatDesc.iPixelType = PFD_TYPE_RGBA;// TODO(Peter): include this in win32_opengl_window_info?
PixelFormatDesc.cColorBits = Info.ColorBits;
PixelFormatDesc.cAlphaBits = Info.AlphaBits;
PixelFormatDesc.cDepthBits = Info.DepthBits;
PixelFormatDesc.dwLayerMask = PFD_MAIN_PLANE; // TODO(Peter): include this in win32_opengl_window_info?
//
s32 PixelFormat = ChoosePixelFormat(Window->DeviceContext, &PixelFormatDesc);
if (!PixelFormat) { InvalidCodePath; } // TODO: Log: Choose pixel format failed
if (!SetPixelFormat(Window->DeviceContext, PixelFormat, &PixelFormatDesc)) { InvalidCodePath; } // TODO: Log: Set pixel format failed
}
// Create rendering context
{
// TODO: Create "proper" context?
// https://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation
Info.RenderContext = wglCreateContext(Window->DeviceContext);
wglMakeCurrent(Window->DeviceContext, Info.RenderContext);
// TODO(Peter): do we want this?
/*
glGetIntegerv(GL_MAJOR_VERSION, );
glGetIntegerv(GL_MINOR_VERSION, );
(char*)glGetString(GL_VENDOR);
(char*)glGetString(GL_RENDERER);
*/
}
Window->OpenGLInfo = Info;
}
struct handle_window_event_result
{
LRESULT Result;
b32 Handled;
};
internal handle_window_event_result
HandleWindowEventUnlessWouldUseDefault (HWND WindowHandle, UINT Msg, WPARAM wParam, LPARAM lParam)
{
handle_window_event_result Result = {};
Result.Handled = false;
switch (Msg)
{
case WM_SIZE:
{
//ResizeDIBSection();
Result.Handled = true;
}break;
case WM_CLOSE:
{
Result.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam);
Result.Handled = true;
}break;
case WM_DESTROY:
{
GlobalWin32State.Running = false;
Result.Handled = true;
}break;
case WM_PAINT:
{
PAINTSTRUCT PaintStruct;
HDC DeviceContext;
b32 PaintResult;
DeviceContext = BeginPaint(WindowHandle, &PaintStruct);
PaintResult = EndPaint(WindowHandle, &PaintStruct);
Result.Handled = true;
}break;
}
return Result;
}
LRESULT CALLBACK
Win32HandleWindowsEvents (
HWND WindowHandle,
UINT Msg,
WPARAM wParam,
LPARAM lParam
)
{
handle_window_event_result EventResult = HandleWindowEventUnlessWouldUseDefault(
WindowHandle,
Msg,
wParam,
lParam);
if (!EventResult.Handled)
{
EventResult.Result = DefWindowProc(WindowHandle, Msg, wParam, lParam);
}
return EventResult.Result;
}
#define WIN32_SHOULD_TRANSLATE_TO_CHAR -1
static int
Win32GetKeyIndex (int Win32VirtualKey, bool NumpadValid, bool TranslateToChar)
{
int Result = WIN32_SHOULD_TRANSLATE_TO_CHAR;
if (Win32VirtualKey == VK_ESCAPE) { Result = (int)KeyCode_Esc; }
if (!TranslateToChar)
{
if (Win32VirtualKey == VK_SPACE) { Result = (int)KeyCode_Space; }
}
if (Win32VirtualKey == VK_CAPITAL) { Result = (int)KeyCode_CapsLock; }
else if (Win32VirtualKey == VK_TAB) { Result = (int)KeyCode_Tab; }
else if (Win32VirtualKey == VK_LSHIFT) { Result = (int)KeyCode_LeftShift; }
else if (Win32VirtualKey == VK_RSHIFT) { Result = (int)KeyCode_RightShift; }
else if (Win32VirtualKey == VK_LCONTROL) { Result = (int)KeyCode_LeftCtrl; }
else if (Win32VirtualKey == VK_RCONTROL) { Result = (int)KeyCode_RightCtrl; }
// TODO(Peter): support the function key?
//else if (Win32VirtualKey == VK_) { Result = (int)KeyCode_Fn; }
else if (Win32VirtualKey == VK_MENU) { Result = (int)KeyCode_Alt; }
else if (Win32VirtualKey == VK_PRIOR) { Result = (int)KeyCode_PageUp; }
else if (Win32VirtualKey == VK_NEXT) { Result = (int)KeyCode_PageDown; }
else if (Win32VirtualKey == VK_BACK) { Result = (int)KeyCode_Backspace; }
else if (Win32VirtualKey == VK_DELETE) { Result = (int)KeyCode_Delete; }
else if (Win32VirtualKey == VK_RETURN) { Result = (int)KeyCode_Enter; }
else if (Win32VirtualKey == VK_F1) { Result = (int)KeyCode_F1; }
else if (Win32VirtualKey == VK_F2) { Result = (int)KeyCode_F2; }
else if (Win32VirtualKey == VK_F3) { Result = (int)KeyCode_F3; }
else if (Win32VirtualKey == VK_F4) { Result = (int)KeyCode_F4; }
else if (Win32VirtualKey == VK_F5) { Result = (int)KeyCode_F5; }
else if (Win32VirtualKey == VK_F6) { Result = (int)KeyCode_F6; }
else if (Win32VirtualKey == VK_F7) { Result = (int)KeyCode_F7; }
else if (Win32VirtualKey == VK_F8) { Result = (int)KeyCode_F8; }
else if (Win32VirtualKey == VK_F9) { Result = (int)KeyCode_F9; }
else if (Win32VirtualKey == VK_F10) { Result = (int)KeyCode_F10; }
else if (Win32VirtualKey == VK_F11) { Result = (int)KeyCode_F11; }
else if (Win32VirtualKey == VK_F12) { Result = (int)KeyCode_F12; }
if (!TranslateToChar)
{
if (Win32VirtualKey == 0x30) { Result = (int)KeyCode_0; }
else if (Win32VirtualKey == 0x31) { Result = (int)KeyCode_1; }
else if (Win32VirtualKey == 0x32) { Result = (int)KeyCode_2; }
else if (Win32VirtualKey == 0x33) { Result = (int)KeyCode_3; }
else if (Win32VirtualKey == 0x34) { Result = (int)KeyCode_4; }
else if (Win32VirtualKey == 0x35) { Result = (int)KeyCode_5; }
else if (Win32VirtualKey == 0x36) { Result = (int)KeyCode_6; }
else if (Win32VirtualKey == 0x37) { Result = (int)KeyCode_7; }
else if (Win32VirtualKey == 0x38) { Result = (int)KeyCode_8; }
else if (Win32VirtualKey == 0x39) { Result = (int)KeyCode_9; }
else if (Win32VirtualKey == 0x41) { Result = (int)KeyCode_A; }
else if (Win32VirtualKey == 0x42) { Result = (int)KeyCode_B; }
else if (Win32VirtualKey == 0x43) { Result = (int)KeyCode_C; }
else if (Win32VirtualKey == 0x44) { Result = (int)KeyCode_D; }
else if (Win32VirtualKey == 0x45) { Result = (int)KeyCode_E; }
else if (Win32VirtualKey == 0x46) { Result = (int)KeyCode_F; }
else if (Win32VirtualKey == 0x47) { Result = (int)KeyCode_G; }
else if (Win32VirtualKey == 0x48) { Result = (int)KeyCode_H; }
else if (Win32VirtualKey == 0x49) { Result = (int)KeyCode_I; }
else if (Win32VirtualKey == 0x4A) { Result = (int)KeyCode_J; }
else if (Win32VirtualKey == 0x4B) { Result = (int)KeyCode_K; }
else if (Win32VirtualKey == 0x4C) { Result = (int)KeyCode_L; }
else if (Win32VirtualKey == 0x4D) { Result = (int)KeyCode_M; }
else if (Win32VirtualKey == 0x4E) { Result = (int)KeyCode_N; }
else if (Win32VirtualKey == 0x4F) { Result = (int)KeyCode_O; }
else if (Win32VirtualKey == 0x50) { Result = (int)KeyCode_P; }
else if (Win32VirtualKey == 0x51) { Result = (int)KeyCode_Q; }
else if (Win32VirtualKey == 0x52) { Result = (int)KeyCode_R; }
else if (Win32VirtualKey == 0x53) { Result = (int)KeyCode_S; }
else if (Win32VirtualKey == 0x54) { Result = (int)KeyCode_T; }
else if (Win32VirtualKey == 0x55) { Result = (int)KeyCode_U; }
else if (Win32VirtualKey == 0x56) { Result = (int)KeyCode_V; }
else if (Win32VirtualKey == 0x57) { Result = (int)KeyCode_W; }
else if (Win32VirtualKey == 0x58) { Result = (int)KeyCode_X; }
else if (Win32VirtualKey == 0x59) { Result = (int)KeyCode_Y; }
else if (Win32VirtualKey == 0x5A) { Result = (int)KeyCode_Z; }
}
if (NumpadValid)
{
if (Win32VirtualKey == VK_NUMPAD0) { Result = (int)KeyCode_Num0; }
else if (Win32VirtualKey == VK_NUMPAD1) { Result = (int)KeyCode_Num1; }
else if (Win32VirtualKey == VK_NUMPAD2) { Result = (int)KeyCode_Num2; }
else if (Win32VirtualKey == VK_NUMPAD3) { Result = (int)KeyCode_Num3; }
else if (Win32VirtualKey == VK_NUMPAD4) { Result = (int)KeyCode_Num4; }
else if (Win32VirtualKey == VK_NUMPAD5) { Result = (int)KeyCode_Num5; }
else if (Win32VirtualKey == VK_NUMPAD6) { Result = (int)KeyCode_Num6; }
else if (Win32VirtualKey == VK_NUMPAD7) { Result = (int)KeyCode_Num7; }
else if (Win32VirtualKey == VK_NUMPAD8) { Result = (int)KeyCode_Num8; }
else if (Win32VirtualKey == VK_NUMPAD9) { Result = (int)KeyCode_Num9; }
}
if (Win32VirtualKey == VK_UP) { Result = (int)KeyCode_UpArrow; }
else if (Win32VirtualKey == VK_DOWN) { Result = (int)KeyCode_DownArrow; }
else if (Win32VirtualKey == VK_LEFT) { Result = (int)KeyCode_LeftArrow; }
else if (Win32VirtualKey == VK_RIGHT) { Result = (int)KeyCode_RightArrow; }
return Result;
}
internal handle_window_msg_result
HandleWindowsMessage (
HWND WindowHandle,
MSG Message)
{
handle_window_msg_result Result = {};
Result.NeedsUpdate = 0;
switch (Message.message)
{
case WM_HOTKEY:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_HOTKEY ");
}break;
case WM_MOUSEWHEEL:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEWHEEL ");
int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam);
/*
Input.New->MouseScroll = MouseWheel;
Result.NeedsUpdate = true;
*/
}break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEBUTTON ");
/*
Input.New->KeyStates[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0;
Input.New->KeyStates[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0;
Input.New->KeyStates[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0;
// NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are
// VK_XBUTTON1 and VK_XBUTTON2
if (KeyTransitionedDown(KeyCode_MouseLeftButton, Input))
{
Input.MouseDownX = Input.New->MouseX;
Input.MouseDownY = Input.New->MouseY;
}
Result.NeedsUpdate = true;*/
}break;
case WM_MOUSEMOVE:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_MOUSEMOVE ");
POINT MousePos;
GetCursorPos(&MousePos);
ScreenToClient(WindowHandle, &MousePos);
/*
Input.New->MouseX = MousePos.x;
Input.New->MouseY = App.WindowHeight - MousePos.y;
Result.NeedsUpdate = true;
*/
}break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
{
int VirtualKey = (int)Message.wParam;
bool KeyDown = (Message.lParam & (1 << 31)) == 0;
int KeyIndex = Win32GetKeyIndex(VirtualKey, true, true);
/*
if (KeyIndex >= 0)
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent ");
Input.New->KeyStates[KeyIndex] = KeyDown;
Result.NeedsUpdate = true;
}
else
{
if (Input.TranslateInputToCharValues && KeyDown)
{
// NOTE(Peter): Took this out b/c we're translating the WM_CHAR messages
// in the message pump, and if we do it here as well, character producing
// key messages get put on the message queue twice
TranslateMessage(&Message);
DispatchMessage(&Message);
}
else
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_KEYEvent ");
// NOTE(Peter): This is so that when you lift up a key that was generating a WM_CHAR,
// the app still has a chance to respond to it.
Result.NeedsUpdate = true;
}
}
*/
}break;
case WM_CHAR:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "WM_CHAR ");
/*
char TranslatedChar = (char)Message.wParam;
int KeyIndex = GetKeyIndexFromChar(TranslatedChar);
if (KeyIndex >= 0)
{
// NOTE(Peter): Always setting this to true becuase windows is stupid and doesn't
// pass the press/release bit through correctly. So now the KEYDOWN/KEYUP Messages above
// only translate the message to a WM_CHAR message if its a key down. Since we clear all
// keystates to false at the beginning of an input frame, this will make transitions
// get registered correctly.
Input.New->KeyStates[KeyIndex] = true;
Result.NeedsUpdate = true;
}
else
{
printf("Translated Char Not Recognized: %c\n", TranslatedChar);
//InvalidCodePath;
}
*/
}break;
default:
{
DEBUG_GET_MESSAGE_NAME(Result.MessageType, "Unhandled WM Event ");
TranslateMessage(&Message);
DispatchMessage(&Message);
}break;
}
return Result;
}
internal void
Win32UpdateWindowDimension(win32_window* Window)
{
RECT ClientRect;
GetClientRect(Window->Handle, &ClientRect);
Window->Info.Width = ClientRect.right - ClientRect.left;
Window->Info.Height = ClientRect.bottom - ClientRect.top;
}
internal void
Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height)
{
if(Buffer->Memory)
{
VirtualFree(Buffer->Memory, 0, MEM_RELEASE);
}
Buffer->Width = Width;
Buffer->Height = Height;
int BytesPerPixel = 4;
Buffer->BytesPerPixel = BytesPerPixel;
Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
Buffer->Info.bmiHeader.biWidth = Buffer->Width;
Buffer->Info.bmiHeader.biHeight = -Buffer->Height; // Top down, not bottom up
Buffer->Info.bmiHeader.biPlanes = 1;
Buffer->Info.bmiHeader.biBitCount = 32;
Buffer->Info.bmiHeader.biCompression = BI_RGB;
int BitmapMemorySize = (Buffer->Width*Buffer->Height)*BytesPerPixel;
Buffer->Memory = (u8*)VirtualAlloc(0, BitmapMemorySize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
Buffer->Pitch = Width*BytesPerPixel;
}
internal void
Win32DisplayBufferInWindow(win32_offscreen_buffer* Buffer, win32_window Window)
{
StretchDIBits(Window.DeviceContext,
0, 0, Buffer->Width, Buffer->Height,
0, 0, Buffer->Width, Buffer->Height,
Buffer->Memory,
&Buffer->Info,
DIB_RGB_COLORS, SRCCOPY);
}
///
// Memory
///
internal win32_memory_op_result
Win32Alloc(s32 Size)
{
win32_memory_op_result Result = {};
Result.Success = false;
Result.Base = (u8*)VirtualAlloc(NULL, Size,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (Result.Base)
{
Result.Size = Size;
Result.Success = true;
}
return Result;
}
internal b32
Win32Free(u8* Base, s32 Size)
{
b32 Result = VirtualFree(Base, Size, MEM_RELEASE);
return Result;
}
// File IO
internal win32_memory_op_result
ReadEntireFile(char* Path)
{
win32_memory_op_result Result = {};
Result.Success = false;
HANDLE FileHandle = CreateFileA (
Path,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
DWORD FileSize = GetFileSize(FileHandle, NULL);
Result.Base = (u8*)VirtualAlloc(NULL, FileSize, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if (Result.Base)
{
Result.Size = FileSize;
s32 BytesRead = 0;
if (ReadFile(FileHandle, (LPVOID)Result.Base, FileSize, (LPDWORD)(&BytesRead), NULL))
{
Result.Success = true;
}
else
{
Result.Size = 0;
}
}
CloseHandle(FileHandle);
}
else
{
// TODO(Peter): failure
}
return Result;
}
internal b32
WriteEntireFile (char* Path, u8* Contents, s32 Size)
{
b32 Result = false;
HANDLE FileHandle = CreateFileA (
Path,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (FileHandle != INVALID_HANDLE_VALUE)
{
DWORD BytesWritten = 0;
b32 WriteSuccess = WriteFile(FileHandle,
Contents, Size,
&BytesWritten,
NULL);
if (WriteSuccess && BytesWritten == (u32)Size)
{
CloseHandle(FileHandle);
Result = true;
}
else
{
Result = false;
}
}
else
{
Result = false;
}
return Result;
}
internal FILETIME
GetFileLastWriteTime(char* Path)
{
FILETIME Result = {};
WIN32_FIND_DATA FindData = {};
HANDLE FileHandle = FindFirstFileA(Path, &FindData);
if (FileHandle != INVALID_HANDLE_VALUE)
{
Result = FindData.ftLastWriteTime;
FindClose(FileHandle);
}
else
{
// TODO(Peter): Error handling
}
return Result;
}
///
// DLL
///
internal executable_path
GetApplicationPath()
{
executable_path ExePath = {};
ExePath.PathLength = GetModuleFileNameA(0, ExePath.Path, MAX_PATH);
u32 CharactersScanned = 0;
u32 IndexOfLastSlash = 0;
char *Scan = ExePath.Path;
while(*Scan)
{
if (*Scan == '\\')
{
ExePath.IndexOfLastSlash = CharactersScanned + 1;
}
Scan++;
CharactersScanned++;
}
return ExePath;
}
internal b32
LoadApplicationDLL(char* DLLName, win32_dll_refresh* DLLResult)
{
b32 Success = false;
Assert(DLLResult->DLL == 0);
DLLResult->DLL = LoadLibraryA(DLLName); // TODO(Peter): Error checking
if (DLLResult->DLL)
{
Success = true;
DLLResult->IsValid = true;
}
return Success;
}
internal void
UnloadApplicationDLL(win32_dll_refresh* DLL)
{
if (DLL->DLL)
{
FreeLibrary(DLL->DLL);
}
DLL->DLL = 0;
DLL->IsValid = false;
}
internal win32_dll_refresh
InitializeDLLHotReloading(char* SourceDLLName,
char* WorkingDLLFileName,
char* LockFileName)
{
win32_dll_refresh Result = {};
Result.IsValid = false;
executable_path ExePath = GetApplicationPath();
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(SourceDLLName), SourceDLLName,
MAX_PATH, Result.SourceDLLPath);
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(WorkingDLLFileName), WorkingDLLFileName,
MAX_PATH, Result.WorkingDLLPath);
Win32ConcatStrings(ExePath.IndexOfLastSlash, ExePath.Path,
Win32StringLength(LockFileName), LockFileName,
MAX_PATH, Result.LockFilePath);
return Result;
}
internal b32
HotLoadDLL(win32_dll_refresh* DLL)
{
b32 DidReload = false;
FILETIME UpdatedLastWriteTime = GetFileLastWriteTime(DLL->SourceDLLPath);
if (CompareFileTime(&UpdatedLastWriteTime, &DLL->LastWriteTime))
{
WIN32_FILE_ATTRIBUTE_DATA Ignored;
if (!GetFileAttributesEx(DLL->LockFilePath, GetFileExInfoStandard, &Ignored))
{
UnloadApplicationDLL(DLL);
CopyFileA(DLL->SourceDLLPath, DLL->WorkingDLLPath, FALSE);
LoadApplicationDLL(DLL->WorkingDLLPath, DLL);
DLL->LastWriteTime = UpdatedLastWriteTime;
DidReload = true;
}
}
return DidReload;
}
#define GS_WIN32_H #define GS_WIN32_H
#endif // GS_WIN32_H #endif // GS_WIN32_H

View File

@ -110,24 +110,31 @@ DrawString (render_command_buffer* RenderBuffer, string String, bitmap_font* Fon
v2 LowerRight = Position; v2 LowerRight = Position;
render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length, render_quad_batch_constructor BatchConstructor = PushRenderTexture2DBatch(RenderBuffer, String.Length,
*Font->Atlas); Font->BitmapMemory,
Font->BitmapTextureHandle,
Font->BitmapWidth,
Font->BitmapHeight,
Font->BitmapBytesPerPixel,
Font->BitmapStride);
r32 FontScale = (r32)PointSize / Font->PixelHeight; r32 FontScale = (r32)PointSize / Font->PixelHeight;
v2 RegisterPosition = Position; v2 RegisterPosition = Position;
char* C = String.Memory; char* C = String.Memory;
for (s32 i = 0; i < String.Length; i++) for (s32 i = 0; i < String.Length; i++)
{ {
s32 GlyphDataIndex = GetCharacterIndexInFont(*C, Font); s32 GlyphDataIndex = GetIndexForCodepoint(*Font, *C);
character_data Data = Font->CharacterLUT_Values[GlyphDataIndex]; codepoint_bitmap CodepointInfo = Font->CodepointValues[GlyphDataIndex];
r32 MinX = RegisterPosition.x + Data.RegisterXOffset * FontScale; r32 MinX = RegisterPosition.x + CodepointInfo.XOffset * FontScale;
r32 MinY = RegisterPosition.y + Data.BaselineYOffset * FontScale; r32 MinY = RegisterPosition.y + CodepointInfo.YOffset * FontScale;
r32 MaxX = MinX + (Data.X1 - Data.X0) * FontScale; r32 MaxX = MinX + (CodepointInfo.Width) * FontScale;
r32 MaxY = MinY + (Data.Y1 - Data.Y0) * FontScale; r32 MaxY = MinY + (CodepointInfo.Height) * FontScale;
PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, Data.AtlasMinUV, Data.AtlasMaxUV, Color); v2 MinUV = v2{(r32)CodepointInfo.BitmapX, (r32)CodepointInfo.BitmapY};
v2 MaxUV = MinUV + v2{(r32)CodepointInfo.Width, (r32)CodepointInfo.Height};
PushQuad2DOnBatch(&BatchConstructor, v2{MinX, MinY}, v2{MaxX, MinY}, v2{MaxX, MaxY}, v2{MinX, MaxY}, MinUV, MaxUV, Color);
RegisterPosition.x += Data.Advance * Font->FontScale * FontScale; RegisterPosition.x += CodepointInfo.Width * FontScale;
C++; C++;
} }
@ -352,7 +359,7 @@ EvaluatePanel (render_command_buffer* RenderBuffer, v2 Min, v2 Max, string Label
v2 TextPos = v2{ v2 TextPos = v2{
Min.x + Config.Margin.x, Min.x + Config.Margin.x,
Max.y - (Config.Font->NewLineYOffset + Config.Margin.y) Max.y - ((r32)NewLineYOffset(*Config.Font) + Config.Margin.y)
}; };
DrawString(RenderBuffer, Label, Config.Font, 14, TextPos, Config.TextColor); DrawString(RenderBuffer, Label, Config.Font, 14, TextPos, Config.TextColor);
Result.ChildMax = v2{Max.x, TextPos.y} - Config.Margin; Result.ChildMax = v2{Max.x, TextPos.y} - Config.Margin;
@ -396,7 +403,7 @@ DrawOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max,
Result.StartIndex = Start; Result.StartIndex = Start;
Result.Selection = Selection_None; Result.Selection = Selection_None;
r32 OptionHeight = Config.Font->NewLineYOffset + (2 * Config.Margin.y); r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y);
r32 OptionOffset = OptionHeight + Config.Margin.y; r32 OptionOffset = OptionHeight + Config.Margin.y;
s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2; s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2;
@ -453,7 +460,7 @@ DrawSelectableOptionsList(render_command_buffer* RenderBuffer, v2 Min, v2 Max,
Result.StartIndex = Start; Result.StartIndex = Start;
Result.Selection = Selection_None; Result.Selection = Selection_None;
r32 OptionHeight = Config.Font->NewLineYOffset + (2 * Config.Margin.y); r32 OptionHeight = NewLineYOffset(*Config.Font) + (2 * Config.Margin.y);
r32 OptionOffset = OptionHeight + Config.Margin.y; r32 OptionOffset = OptionHeight + Config.Margin.y;
s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2; s32 OptionsToDisplay = ((Max.y - Min.y) / OptionHeight) - 2;

16
testmain.cpp Normal file
View File

@ -0,0 +1,16 @@
#include <windows.h>
#include "gs_platform.h"
#include "gs_win32.h"
int main (int ArgCount, char** Args)
{
window MainWindow = PlatformCreateWindow("Test Window", 1024, 768);
win32_opengl_window_info OpenGLInfo = {};
OpenGLInfo.ColorBits = 32;
OpenGLInfo.AlphaBits = 8;
Win32CreateOpenGLContext(OpenGLInfo, MainWindow);
return 0;
}

View File

@ -1,12 +1,12 @@
#include <Winsock2.h> #include <Winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <intrin.h> #include <intrin.h>
#include <windowsx.h>
#include <gl/gl.h>
#include "foldhaus_platform.h" #include "foldhaus_platform.h"
#include "gs_win32.h" #include "gs_win32.cpp"
#include "gs_opengl.h"
#include "foldhaus_renderer.cpp" #include "foldhaus_renderer.cpp"
global_variable b32 Running = false; global_variable b32 Running = false;
@ -16,7 +16,7 @@ char DLLName[] = "foldhaus.dll";
char WorkingDLLName[] = "foldhaus_temp.dll"; char WorkingDLLName[] = "foldhaus_temp.dll";
char DLLLockFileName[] = "lock.tmp"; char DLLLockFileName[] = "lock.tmp";
win32_window MainWindow; window MainWindow;
struct worker_thread_entry struct worker_thread_entry
{ {
@ -116,7 +116,7 @@ WorkerThreadProc (LPVOID InputThreadInfo)
PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle) PLATFORM_GET_GPU_TEXTURE_HANDLE(Win32GetGPUTextureHandle)
{ {
s32 Handle = SubmitTexture(Width, Height, Memory); s32 Handle = SubmitTexture(Memory, Width, Height);
return Handle; return Handle;
} }
@ -186,7 +186,7 @@ PLATFORM_GET_SEND_ADDRESS_HANDLE(Win32GetSendAddress)
Assert(Win32NetworkAddressHandleCount < Win32NetworkAddressHandleMax); Assert(Win32NetworkAddressHandleCount < Win32NetworkAddressHandleMax);
s32 NewAddressIndex = Win32NetworkAddressHandleCount++; s32 NewAddressIndex = Win32NetworkAddressHandleCount++;
NetworkAddressValues[NewAddressIndex].sin_family = Family; NetworkAddressValues[NewAddressIndex].sin_family = AddressFamily;
NetworkAddressValues[NewAddressIndex].sin_port = HostToNetU16(Port); NetworkAddressValues[NewAddressIndex].sin_port = HostToNetU16(Port);
NetworkAddressValues[NewAddressIndex].sin_addr.s_addr = HostToNetU32(Address); NetworkAddressValues[NewAddressIndex].sin_addr.s_addr = HostToNetU32(Address);
@ -233,6 +233,50 @@ PLATFORM_CLOSE_SOCKET(Win32CloseSocket)
closesocket(SocketValues[SocketIndex].Socket); closesocket(SocketValues[SocketIndex].Socket);
} }
GET_FONT_INFO(Win32GetFontInfo)
{
platform_font_info Result = {};
Result.DrawingDC = CreateCompatibleDC(NULL);
SetBkColor(Result.DrawingDC, RGB(0, 0, 0));
SetTextColor(Result.DrawingDC, RGB(255, 255, 255));
Result.Bitmap = CreateCompatibleBitmap(NULL, PixelHeight * 2, PixelHeight * 2);
SelectObject(Result.DrawingDC, Result.Bitmap);
Result.Font= CreateFont(PixelHeight, 0, 0, 0,
// TODO(Peter): Font weight, need a platform way to request others
FW_NORMAL,
FALSE, // Italic
FALSE, // Underling
FALSE, // Strikeout,
ANSI_CHARSET,
OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,
PROOF_QUALITY,
FIXED_PITCH,
FontName);
SelectFont(Result.DrawingDC, Result.Font);
TEXTMETRIC WindowsFontMetrics = {};
if (GetTextMetrics(Result.DrawingDC, &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)
{
}
LRESULT CALLBACK LRESULT CALLBACK
HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam) HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam)
{ {
@ -281,14 +325,13 @@ HandleWindowEvents (HWND WindowHandle, UINT Msg, WPARAM WParam, LPARAM LParam)
} }
internal void internal void
HandleWindowMessage (MSG Message, win32_window* Window, input_frame* InputFrame) HandleWindowMessage (MSG Message, window* Window, input_frame* InputFrame)
{ {
switch (Message.message) switch (Message.message)
{ {
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
{ {
int MouseWheel = GET_WHEEL_DELTA_WPARAM(Message.wParam); Win32UpdateInputFrameMouseWheelDelta(InputFrame, Message);
InputFrame->MouseScroll = MouseWheel;
}break; }break;
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
@ -298,11 +341,7 @@ HandleWindowMessage (MSG Message, win32_window* Window, input_frame* InputFrame)
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
case WM_RBUTTONUP: case WM_RBUTTONUP:
{ {
InputFrame->KeysDown[KeyCode_MouseLeftButton] = (GetKeyState(VK_LBUTTON) & (1 << 15)) != 0; Win32UpdateInputFrameMouseState(InputFrame);
InputFrame->KeysDown[KeyCode_MouseMiddleButton] = (GetKeyState(VK_MBUTTON) & (1 << 15)) != 0;
InputFrame->KeysDown[KeyCode_MouseRightButton] = (GetKeyState(VK_RBUTTON) & (1 << 15)) != 0;
// NOTE(Peter): If you decide to support extra mouse buttons, on windows the key codes are
// VK_XBUTTON1 and VK_XBUTTON2
}break; }break;
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
@ -342,9 +381,10 @@ internal void
DebugPrint (char* Format, ...) DebugPrint (char* Format, ...)
{ {
char Buffer[256]; char Buffer[256];
string StringBuffer = MakeString(Buffer, 256);
va_list Args; va_list Args;
va_start(Args, Format); va_start(Args, Format);
PrintFInternal(Buffer, 256, Format, Args); PrintF(&StringBuffer, Format, Args);
OutputDebugStringA(Buffer); OutputDebugStringA(Buffer);
va_end(Args); va_end(Args);
} }
@ -376,14 +416,7 @@ PSTR CmdLineArgs,
INT NCmdShow INT NCmdShow
) )
{ {
win32_window_info MainWindowInfo = {}; MainWindow = Win32CreateWindow (HInstance, "Foldhaus", 1440, 768, HandleWindowEvents);
MainWindowInfo.Name = "Foldhaus";
MainWindowInfo.ClassName = "Foldhaus Window Class";
MainWindowInfo.Width = 1440;
MainWindowInfo.Height = 768;
MainWindowInfo.WindowEventsHandler = HandleWindowEvents;
MainWindow = CreateWin32Window (HInstance, MainWindowInfo);
Win32UpdateWindowDimension(&MainWindow); Win32UpdateWindowDimension(&MainWindow);
win32_opengl_window_info OpenGLWindowInfo = {}; win32_opengl_window_info OpenGLWindowInfo = {};
@ -393,6 +426,10 @@ INT NCmdShow
CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow); CreateOpenGLWindowContext(OpenGLWindowInfo, &MainWindow);
s64 PerformanceCountFrequency = GetPerformanceFrequency(); s64 PerformanceCountFrequency = GetPerformanceFrequency();
s64 LastFrameEnd = GetWallClock();
r32 TargetSecondsPerFrame = 1 / 60.0f;
r32 LastFrameSecondsElapsed = 0.0f;
GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services)); GlobalDebugServices = (debug_services*)malloc(sizeof(debug_services));
InitDebugServices(GlobalDebugServices, (u8*)malloc(Megabytes(8)), Megabytes(8), 1000, PerformanceCountFrequency); InitDebugServices(GlobalDebugServices, (u8*)malloc(Megabytes(8)), Megabytes(8), 1000, PerformanceCountFrequency);
GlobalDebugServices->GetWallClock = GetWallClock; GlobalDebugServices->GetWallClock = GetWallClock;
@ -431,21 +468,23 @@ INT NCmdShow
context Context = {}; context Context = {};
Context.MemorySize = InitialMemory.Size; Context.MemorySize = InitialMemory.Size;
Context.MemoryBase = InitialMemory.Base; Context.MemoryBase = InitialMemory.Base;
Context.WindowWidth = MainWindow.Info.Width; Context.WindowWidth = MainWindow.Width;
Context.WindowHeight = MainWindow.Info.Height; Context.WindowHeight = MainWindow.Height;
// Platform functions // Platform functions
Context.GeneralWorkQueue = &WorkQueue; Context.GeneralWorkQueue = &WorkQueue;
Context.PlatformAlloc = Win32Alloc; Context.PlatformAlloc = Win32Alloc;
Context.PlatformFree = Win32Free; Context.PlatformFree = Win32Free;
Context.PlatformReadEntireFile = ReadEntireFile; Context.PlatformReadEntireFile = Win32ReadEntireFile;
Context.PlatformWriteEntireFile = WriteEntireFile; Context.PlatformWriteEntireFile = Win32WriteEntireFile;
Context.PlatformGetFilePath = Win32SystemDialogOpenFile; Context.PlatformGetFilePath = Win32SystemDialogueOpenFile;
Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle; Context.PlatformGetGPUTextureHandle = Win32GetGPUTextureHandle;
Context.PlatformGetSocketHandle = Win32GetSocketHandle; Context.PlatformGetSocketHandle = Win32GetSocketHandle;
Context.PlatformGetSendAddress = Win32GetSendAddress; Context.PlatformGetSendAddress = Win32GetSendAddress;
Context.PlatformSetSocketOption = Win32SetSocketOption; Context.PlatformSetSocketOption = Win32SetSocketOption;
Context.PlatformCloseSocket = Win32CloseSocket; Context.PlatformCloseSocket = Win32CloseSocket;
Context.PlatformGetFontInfo = Win32GetFontInfo;
Context.PlatformDrawFontCodepoint = Win32DrawFontCodepoint;
win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName); win32_dll_refresh DLLRefresh = InitializeDLLHotReloading(DLLName, WorkingDLLName, DLLLockFileName);
if (HotLoadDLL(&DLLRefresh)) if (HotLoadDLL(&DLLRefresh))
@ -490,7 +529,7 @@ INT NCmdShow
GetCursorPos (&MousePos); GetCursorPos (&MousePos);
ScreenToClient(MainWindow.Handle, &MousePos); ScreenToClient(MainWindow.Handle, &MousePos);
Input.New->MouseX = MousePos.x; Input.New->MouseX = MousePos.x;
Input.New->MouseY = MainWindow.Info.Height - MousePos.y; Input.New->MouseY = MainWindow.Height - MousePos.y;
if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton)) if (KeyTransitionedDown(Input, KeyCode_MouseLeftButton))
{ {
@ -501,8 +540,8 @@ INT NCmdShow
// TODO(Peter): We shouldn't need to do this translation. the platform layer knows about win32_windows. We should just make that the interface // TODO(Peter): We shouldn't need to do this translation. the platform layer knows about win32_windows. We should just make that the interface
// to all windows. // to all windows.
Context.WindowWidth = MainWindow.Info.Width; Context.WindowWidth = MainWindow.Width;
Context.WindowHeight = MainWindow.Info.Height; Context.WindowHeight = MainWindow.Height;
Context.DeltaTime = LastFrameSecondsElapsed; Context.DeltaTime = LastFrameSecondsElapsed;
Context.UpdateAndRender(Context, Input, &RenderBuffer); Context.UpdateAndRender(Context, Input, &RenderBuffer);