add readme

main
Allen Webster 2023-09-29 18:09:40 -07:00
commit d70845d23c
50 changed files with 42983 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
build/*
*.exe
*.pdb
*.exp
*.lib
*.obj
*.dll

15
build.bat Normal file
View File

@ -0,0 +1,15 @@
@echo off
set core_name=app
set exe_name=appWin32
set build_options= -DBUILD_WIN32=1
set compile_flags= -nologo /Zi /FC /I ../source/
set common_link_flags= opengl32.lib -opt:ref -incremental:no
set platform_link_flags= gdi32.lib user32.lib winmm.lib comdlg32.lib %common_link_flags%
if not exist build mkdir build
pushd build
start /b /wait "" "cl.exe" %build_options% %compile_flags% ../source/win32/win32_main.c /link %platform_link_flags% /out:%exe_name%.exe
start /b /wait "" "cl.exe" %build_options% %compile_flags% ../source/app.c /LD /link %common_link_flags% /out:%core_name%.dll
copy ..\data\* . >NUL
popd

BIN
data/liberation-mono.ttf Normal file

Binary file not shown.

57
project.4coder Normal file
View File

@ -0,0 +1,57 @@
version(1);
project_name = "Application Template";
patterns =
{
"*.c",
"*.cpp",
"*.ds",
"*.h",
"*.bat",
"*.sh",
"*.4coder",
};
blacklist_patterns =
{
".*",
};
load_paths =
{
{
{ {"."}, .recursive = true, .relative = true }, .os = "win"
},
};
command_list =
{
{
.name = "build",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "build.bat", .os = "win" },
},
},
{
.name = "run",
.out = "*compilation*",
.footer_panel = true,
.save_dirty_files = true,
.cursor_at_end = false,
.cmd =
{
{ "run.bat", .os = "win" },
},
},
};
fkey_command[1] = "build";
fkey_command[3] = "run";

10
readme.md Normal file
View File

@ -0,0 +1,10 @@
# Splink
An entry for the Handmade Network Lisp Jam of 2020.
What if a programming environment had built in error containment structures and code organizational properties like slices? For the jam I decided to explore that with a lisp editor and interpreter environment.
# Credits
The base layer for this application was forked from Ryan Fleury's app template.

4
run.bat Normal file
View File

@ -0,0 +1,4 @@
@echo off
pushd build
appWin32.exe
popd

1254
source/app.c Normal file

File diff suppressed because it is too large Load Diff

125
source/app.h Normal file
View File

@ -0,0 +1,125 @@
/* date = July 2nd 2020 11:52 pm */
#ifndef APP_H
#define APP_H
////////////////////////////////
// NOTE(allen): Floating Window
typedef struct APP_FloatingWindowResult APP_FloatingWindowResult;
struct APP_FloatingWindowResult{
Rect rect;
};
typedef void APP_FloatingWindowCallbackType(void *ptr, APP_FloatingWindowResult *result);
////////////////////////////////
// NOTE(allen): Variables
typedef enum{
APP_MouseLayer_Null,
APP_MouseLayer_Main,
APP_MouseLayer_FloatingWindow,
} APP_MouseLayer;
typedef enum{
APP_BtnCtx_Null,
APP_BtnCtx_ToolBox,
APP_BtnCtx_ListerOptions,
APP_BtnCtx_Lister,
APP_BtnCtx_ViewButtons,
APP_BtnCtx_Tabs,
} APP_MouseLayer;
typedef u32 APP_ListerFlags;
enum{
APP_ListerFlag_Spaces = (1 << 0),
APP_ListerFlag_Pages = (1 << 1),
APP_ListerFlag_Tests = (1 << 2),
APP_ListerFlag_Invalids = (1 << 3),
APP_ListerFlag_Definitions = (1 << 4),
};
typedef struct APP_Variables APP_Variables;
struct APP_Variables{
M_Arena arena_;
M_Arena *arena;
R_Font font;
v2 mouse_p;
v2 window_dim;
f32 frame_time;
////////////////////////////////
// NOTE(allen): Engine State
u64 frame_indx;
M_Arena frame_arena[2];
STR_Hash string_hash;
STR_Index keyword_table[C_BuiltInIndex_COUNT];
C_CellMemory cells;
C_CellBucket static_bucket;
C_Statics statics;
C_CellBucket global_defines_bucket;
C_CellBucket eval_bucket;
C_Cell *spaces_env;
E_Definition *free_definition;
E_Space *free_space;
E_Space *first_space_ordered;
E_Space *last_space_ordered;
E_Space *first_space;
E_Space *last_space;
E_Space *first_invalid_space;
E_Space *last_invalid_space;
u64 identifier_available_count;
STR_Index identifier_available[8];
E_Tile *free_tile;
E_View *free_view;
E_View *first_view;
E_View *last_view;
E_View *active_view;
E_EditorState *active_editor;
E_Tile *active_tile;
E_View *change_view;
E_Tile *snap_to_tile;
////////////////////////////////
// NOTE(allen): UI
UI_Id active_mouse_layer;
UI_Id current_mouse_layer;
UI_Id owner_of_floating_window;
void *floating_window_ptr;
APP_FloatingWindowCallbackType *floating_window_callback;
Rect floating_window_last_frame_rect;
UI_Id last_frame_owner_of_floating_window;
void *last_frame_floating_window_ptr;
String8 tool_tip_string;
APP_ListerFlags lister_flags;
C_Token panel_filter_memory;
E_TokenBuffer panel_filter_buffer;
E_EditorState panel_filter;
f32 panel_scroll_y;
////////////////////////////////
// NOTE(allen): Frame Data
E_EditorState *neighbor_editors[2];
};
#endif //APP_H

185
source/app_core.c Normal file
View File

@ -0,0 +1,185 @@
////////////////////////////////
// NOTE(allen): App core
global APP_Variables *vars = 0;
internal M_Arena*
APP_GetFrameArena(void){
return(&vars->frame_arena[vars->frame_indx&1]);
}
internal STR_Hash*
APP_GetStringHash(void){
return(&vars->string_hash);
}
internal C_CellMemory*
APP_GetCellMemory(void){
return(&vars->cells);
}
internal E_EditorState*
APP_GetActiveEditor(void){
return(vars->active_editor);
}
internal E_Tile*
APP_GetActiveTile(void){
return(vars->active_tile);
}
internal void
APP_SetActiveView(E_View *view){
if (vars->active_view != view){
vars->active_tile = 0;
vars->active_editor = 0;
}
vars->active_view = view;
Assert(vars->active_view != 0);
}
internal void
APP_SetActiveEditor(E_EditorState *editor){
if (vars->active_editor != editor){
vars->active_tile = 0;
}
vars->active_editor = editor;
}
internal void
APP_SetActiveTile(E_Tile *tile){
if (vars->active_tile != tile){
b32 editor_in_tile = 0;
if (tile != 0){
for (u64 i = 0; i < ArrayCount(tile->editors); i += 1){
if (vars->active_editor == &tile->editors[i]){
editor_in_tile = 1;
break;
}
}
}
if (!editor_in_tile){
vars->active_editor = 0;
}
}
vars->active_tile = tile;
}
internal C_Statics*
APP_GetStatics(void){
return(&vars->statics);
}
internal C_CellBucket*
APP_GetEvalBucket(void){
return(&vars->eval_bucket);
}
internal void
APP_SignalSnapToTile(E_Tile *tile){
vars->snap_to_tile = tile;
}
internal void
APP_SignalViewChange(E_View *view){
if (view != 0){
vars->change_view = view;
}
}
internal E_View*
APP_GetGlobalView(E_Space *space){
E_View *result = 0;
for (E_View *view = vars->first_view;
view != 0;
view = view->next){
if (view->kind == E_ViewKind_Global && view->space == space){
result = view;
break;
}
}
return(result);
}
internal E_View*
APP_GetPageView(E_Definition *definition){
E_View *result = 0;
for (E_View *view = vars->first_view;
view != 0;
view = view->next){
if (view->kind == E_ViewKind_Page && view->definition == definition){
result = view;
break;
}
}
return(result);
}
internal E_Space*
APP_GetActiveSpace(void){
E_Space *result = 0;
E_View *view = vars->active_view;
if (view != 0){
result = view->space;
Assert(result != 0);
}
return(result);
}
internal void
APP_SignalSpaceNameAvailable(STR_Index name){
if (vars->identifier_available_count < ArrayCount(vars->identifier_available)){
vars->identifier_available[vars->identifier_available_count] = name;
}
vars->identifier_available_count += 1;
}
internal UI_Id
APP_OwnerOfFloatingWindow(void){
return(vars->owner_of_floating_window);
}
internal void
APP_TakeOwnershipOfFloatingWindow(UI_Id id){
vars->owner_of_floating_window = id;
}
internal void
APP_ZeroOwnershipOfFloatingWindow(void){
MemoryZeroStruct(&vars->owner_of_floating_window);
}
internal void*
APP_GetFloatingWindowPtr(void){
return(vars->floating_window_ptr);
}
internal void*
APP_GetLastFrameFloatingWindowPtr(void){
void *result = 0;
if (UI_IdEq(vars->last_frame_owner_of_floating_window, vars->owner_of_floating_window)){
result = vars->last_frame_floating_window_ptr;
}
return(result);
}
internal void
APP_SetFloatingWindowPtrAndCallback(void *ptr, APP_FloatingWindowCallbackType *callback){
vars->floating_window_ptr = ptr;
vars->floating_window_callback = callback;
}
internal b32
APP_MouseIsActive(void){
return(UI_IdEq(vars->active_mouse_layer, vars->current_mouse_layer));
}
internal void
APP_SetMouseLayer(UI_Id id){
vars->current_mouse_layer = id;
}
internal void
APP_SetToolTip(String8 string){
vars->tool_tip_string = string;
}

101
source/app_memory.c Normal file
View File

@ -0,0 +1,101 @@
// NOTE(allen): memory
#define M_ARENA_MAX Gigabytes(4)
#define M_ARENA_COMMIT_SIZE Kilobytes(4)
internal M_Arena
M_ArenaInitializeWithAlign(u64 auto_align)
{
M_Arena arena = {0};
arena.max = M_ARENA_MAX;
arena.base = os->Reserve(arena.max);
arena.alloc_position = 0;
arena.commit_position = 0;
arena.auto_align = auto_align;
return arena;
}
internal M_Arena
M_ArenaInitialize(void)
{
return(M_ArenaInitializeWithAlign(8));
}
internal void *
M_ArenaPush(M_Arena *arena, u64 size)
{
void *memory = 0;
if(arena->alloc_position + size > arena->commit_position)
{
u64 commit_size = size;
commit_size += M_ARENA_COMMIT_SIZE-1;
commit_size -= commit_size % M_ARENA_COMMIT_SIZE;
os->Commit((u8 *)arena->base + arena->commit_position, commit_size);
arena->commit_position += commit_size;
}
memory = (u8 *)arena->base + arena->alloc_position;
u64 p = arena->alloc_position + size;
arena->alloc_position = (p + arena->auto_align - 1)&(~(arena->auto_align - 1));
return memory;
}
internal void *
M_ArenaPushZero(M_Arena *arena, u64 size)
{
void *memory = M_ArenaPush(arena, size);
MemorySet(memory, 0, size);
return memory;
}
internal void
M_ArenaSetPosBack(M_Arena *arena, u64 pos)
{
if (pos <= arena->alloc_position)
{
arena->alloc_position = pos;
}
}
internal void
M_ArenaSetPosBackByPtr(M_Arena *arena, void *ptr)
{
u8 *uptr = (u8*)ptr;
u64 pos = (uptr - (u8*)arena->base);
if ((u8*)arena->base <= uptr)
{
M_ArenaSetPosBack(arena, pos);
}
}
internal void
M_ArenaPop(M_Arena *arena, u64 size)
{
size = ClampTop(size, arena->alloc_position);
arena->alloc_position -= size;
}
internal void
M_ArenaClear(M_Arena *arena)
{
M_ArenaPop(arena, arena->alloc_position);
}
internal void
M_ArenaRelease(M_Arena *arena)
{
os->Release(arena->base);
}
internal M_Temp
M_BeginTemp(M_Arena *arena)
{
M_Temp temp = {arena, arena->alloc_position};
return(temp);
}
internal void
M_EndTemp(M_Temp temp)
{
M_ArenaSetPosBack(temp.arena, temp.pos);
}

38
source/app_memory.h Normal file
View File

@ -0,0 +1,38 @@
// NOTE(allen): memory
typedef struct M_Arena M_Arena;
struct M_Arena
{
void *base;
u64 max;
u64 alloc_position;
u64 commit_position;
u64 auto_align;
};
typedef struct M_Temp M_Temp;
struct M_Temp
{
M_Arena *arena;
u64 pos;
};
////////////////////////////////
#define PushArray(arena,T,c) ( (T*)(M_ArenaPush((arena),sizeof(T)*(c))) )
#define PushArrayZero(arena,T,c) ( (T*)(M_ArenaPushZero((arena),sizeof(T)*(c))) )
internal M_Arena M_ArenaInitializeWithAlign(u64 auto_align);
internal M_Arena M_ArenaInitialize(void);
internal void M_ArenaRelease(M_Arena *arena);
internal void* M_ArenaPush(M_Arena *arena, u64 size);
internal void* M_ArenaPushZero(M_Arena *arena, u64 size);
internal void M_ArenaSetPosBack(M_Arena *arena, u64 pos);
internal void M_ArenaSetPosBackByPtr(M_Arena *arena, void *ptr);
internal void M_ArenaPop(M_Arena *arena, u64 size);
internal void M_ArenaClear(M_Arena *arena);
internal M_Temp M_BeginTemp(M_Arena *arena);
internal void M_EndTemp(M_Temp temp);

1898
source/compute.c Normal file

File diff suppressed because it is too large Load Diff

229
source/compute.h Normal file
View File

@ -0,0 +1,229 @@
/* date = July 8th 2020 7:11 am */
#ifndef COMPUTE_H
#define COMPUTE_H
typedef enum{
C_TokenKind_NULL,
C_TokenKind_Space,
C_TokenKind_Newline,
C_TokenKind_Comment,
#define C_TokenKind_FIRST_HARD C_TokenKind_OpenParen
C_TokenKind_OpenParen,
C_TokenKind_CloseParen,
C_TokenKind_Quote,
C_TokenKind_Label,
#define C_TokenKind_LAST_HARD C_TokenKind_Label
C_TokenKind_COUNT,
} C_TokenKind;
typedef struct C_Token C_Token;
struct C_Token{
C_TokenKind kind;
STR_Index string;
};
typedef struct C_TokenArray C_TokenArray;
struct C_TokenArray{
C_Token *vals;
u64 count;
};
////////////////////////////////
typedef u64 C_Id;
typedef struct C_Deferred C_Deferred;
struct C_Deferred{
void *user_ptr;
struct C_Cell *env;
struct C_Cell *cell;
b32 doing_eval;
b32 finished_eval;
};
#define C_BUILT_IN_SIG(name) struct C_Cell* name(struct C_EvalCtx *ctx, struct C_Cell *cell, struct C_Cell **env)
typedef C_BUILT_IN_SIG(C_BuiltInFunctionType);
typedef enum{
C_CellKind_Nil,
C_CellKind_Constructed,
C_CellKind_F64,
C_CellKind_Id,
C_CellKind_Identifier,
// NOTE(allen): Used in eval but not emitted by parser
C_CellKind_BuiltIn,
C_CellKind_Environment,
C_CellKind_Function,
C_CellKind_Macro,
C_CellKind_FunctionV,
C_CellKind_MacroV,
C_CellKind_Register,
C_CellKind_Deferred,
C_CellKind_Space,
// NOTE(allen): Used in memory allocation strategy,
// a correctly functioning lisp eval should not encounter this.
// If it does it will be treated as Nil.
C_CellKind_BlockHeader,
} C_CellKind;
// NOTE(allen): Forming verbs (functions, macros, variadics):
// first_child -> constructed list of parameters
// -> identifier for variadics
// next -> expression forming body of function
// env -> environment inherited from enclosing scope
typedef struct C_Cell C_Cell;
struct C_Cell{
C_CellKind kind;
C_Cell *next;
union{
C_Cell *first_child;
C_BuiltInFunctionType *built_in;
};
union{
u64 x;
struct C_CellBucket *bucket;
void *space;
f64 f;
STR_Index identifier;
C_Cell *env;
C_Deferred *deferred;
C_Id id;
u64 depth_counter;
};
};
// NOTE(allen): We want fast divides on whatever size we pick here.
#define C_BLOCK_CAP 256
typedef struct C_CellMemory C_CellMemory;
struct C_CellMemory{
M_Arena arena;
C_Cell *cells;
C_Cell *free_block;
};
typedef struct C_CellBucket C_CellBucket;
struct C_CellBucket{
C_CellMemory *memory;
C_Cell *first_block;
C_Cell *last_block;
u64 cursor;
};
typedef struct C_ListBuilder C_ListBuilder;
struct C_ListBuilder{
C_Cell *f;
C_Cell **u;
u64 c;
};
////////////////////////////////
typedef struct C_ParseError C_ParseError;
struct C_ParseError{
String8 message;
C_Token *token;
};
typedef struct C_ParseCtx C_ParseCtx;
struct C_ParseCtx{
struct C_Statics *statics;
C_CellBucket *bucket;
C_Token *token;
C_Token *opl;
u64 error_count;
u64 error_max;
C_ParseError *errors;
};
////////////////////////////////
#define C_BuiltInXList(X) \
X("define", Define) \
X("function", Function) \
X("function...", FunctionV) \
X("macro", Macro) \
X("macro...", MacroV) \
X("write-reg", WriteRegister) \
X("read-reg", ReadRegister) \
X("get-thread-local-reg", GetUniqueRegister) \
X("block", Block) \
X("first", First) \
X("next", Next) \
X("push", Push) \
X("list", List) \
X("list-count", ListCount) \
X("id", Id) \
X("all-ids", AllIds) \
X("quote", Quote) \
X("eval", Eval) \
X("apply", Apply) \
X("far-eval", FarEval) \
X("kind", Kind) \
X("if", If) \
X("switch", Switch) \
X("loop", Loop) \
X("+1", Increment) \
X("-1", Decrement) \
X("+", Add) \
X("-", Sub) \
X("*", Mul) \
X("/", Div) \
X("%", Mod) \
X("^", Pow) \
X("<", Ls) \
X(">", Gr) \
X("<=", LsEq) \
X(">=", GrEq) \
X("==", Eq) \
X("!=", NotEq) \
X("not", Not) \
X("and", And) \
X("or", Or) \
X("ceil", Ceil) \
X("floor", Floor) \
X("round", Round)
typedef enum{
C_BuiltInIndex_Nil,
#define EnumMember(N,F) C_BuiltInIndex_##F,
C_BuiltInXList(EnumMember)
#undef EnumMember
C_BuiltInIndex_COUNT,
} C_BuiltInIndex;
typedef struct C_Statics C_Statics;
struct C_Statics{
union{
struct{
C_Cell *Nil;
#define StaticMember(N,F) C_Cell *F;
C_BuiltInXList(StaticMember)
#undef StaticMember
};
C_Cell *built_in[C_BuiltInIndex_COUNT];
};
C_Cell *env;
};
////////////////////////////////
typedef struct C_EvalCtx C_EvalCtx;
struct C_EvalCtx{
C_Statics *statics;
C_CellBucket *bucket;
C_Cell *id_env;
C_Cell *regs;
u64 max_depth;
u64 depth;
u64 loop_lim;
C_Id reg_id_counter;
};
#endif //COMPUTE_H

1169
source/definition.c Normal file

File diff suppressed because it is too large Load Diff

186
source/definition.h Normal file
View File

@ -0,0 +1,186 @@
/* date = July 7th 2020 7:47 am */
#ifndef DEFINITION_H
#define DEFINITION_H
typedef u32 E_DefinitionFlags;
enum{
E_DefinitionFlag_Invalid = (1 << 0),
E_DefinitionFlag_Page = (1 << 1),
E_DefinitionFlag_Test = (1 << 2),
};
typedef struct E_Definition E_Definition;
struct E_Definition{
// NOTE(allen): State
E_Definition *ordered_next;
E_Definition *ordered_prev;
E_Definition *next;
E_Definition *prev;
struct E_Space *space;
E_DefinitionFlags flags;
STR_Index last_name;
C_Id id;
b32 delete_me;
// NOTE(allen): Contents
C_Token name_token_buffer;
union{
struct{
E_TokenBuffer name;
E_TokenBuffer body;
};
E_TokenBuffer buffers[2];
};
// NOTE(allen): Compute
b32 invalid_name_field;
C_CellBucket bucket;
u64 error_count;
C_ParseError errors[20];
union{
struct{
C_Cell *name_cell;
C_Cell *body_cell;
};
C_Cell *cells[2];
};
C_Deferred deferred;
};
typedef struct E_Space E_Space;
struct E_Space{
E_Space *ordered_next;
E_Space *ordered_prev;
E_Space *next;
E_Space *prev;
b32 invalid;
STR_Index last_name;
C_Cell *defines_env;
C_Cell *id_env;
C_Cell *id_list;
u64 id_counter;
E_Definition *first_definition;
E_Definition *last_definition;
E_Definition *first_invalid_definition;
E_Definition *last_invalid_definition;
E_Definition *first_definition_ordered;
E_Definition *last_definition_ordered;
b32 delete_signal;
b32 init_error;
b32 dirty;
f32 last_save_time;
STR_Index save_path;
u64 identifier_available_count;
STR_Index identifier_available[8];
};
////////////////////////////////
typedef struct E_Tile E_Tile;
struct E_Tile{
E_Tile *next;
E_Tile *prev;
struct E_TileCache *tile_cache;
b32 free_me;
E_Definition *definition;
union{
struct{
E_EditorState name;
E_EditorState body;
};
E_EditorState editors[2];
};
R_Font *font;
};
typedef struct E_ViewCallbackIn E_ViewCallbackIn;
struct E_ViewCallbackIn{
E_Definition *definition;
};
typedef union E_ViewCallbackOut E_ViewCallbackOut;
union E_ViewCallbackOut{
E_Definition *definition;
String8 name;
};
#define VIEW_CALLBACK_SIG(name) void name(struct E_View *view, E_ViewCallbackIn *in, E_ViewCallbackOut *out)
typedef VIEW_CALLBACK_SIG(E_ViewCallback);
/* NOTE(allen): View v-table
** derive_from_source (void) (void)
** create_new_definition (void) (out->definition)
** look_at_definition (in->definition) (void)
** cleanup (void) (void)
** shutdown (void) (void)
** get_name (void) (out->name)
*/
typedef enum{
E_ViewKind_Null,
E_ViewKind_Global,
E_ViewKind_Page,
} E_ViewKind;
typedef struct E_View E_View;
struct E_View{
E_ViewKind kind;
E_View *prev;
E_View *next;
// NOTE(allen): v-table
E_ViewCallback *derive_from_source;
E_ViewCallback *create_new_definition;
E_ViewCallback *look_at_definition;
E_ViewCallback *cleanup;
E_ViewCallback *shutdown;
E_ViewCallback *get_name;
// NOTE(allen): Tiles
R_Font *font;
E_Tile *first_tile;
E_Tile *last_tile;
b32 free_children;
f32 scroll_y;
// NOTE(allen): Variables
E_Space *space;
String8 name;
E_Definition *definition;
b32 state_ahead_of_source;
};
////////////////////////////////
internal E_View* E_NewView(void);
internal void E_DeleteView(E_View *view);
internal void E_ViewDeriveFromSource(E_View *view);
internal E_Definition* E_ViewCreateNewDefinition(E_View *view);
internal void E_ViewLookAtDefinition(E_View *view, E_Definition *definition);
internal b32 E_ViewWillLookAtDefinition(E_View *view);
internal void E_ViewCleanup(E_View *view);
internal b32 E_ViewWillCloseDefinition(E_View *view);
internal void E_ViewShutdown(E_View *view);
internal String8 E_ViewGetName(E_View *view);
internal void E_InitGlobalView(E_View *view, R_Font *font, E_Space *space);
internal void E_InitPageView(E_View *view, R_Font *font, E_Definition *definition);
#endif //DEFINITION_H

12570
source/ext/glext.h Normal file

File diff suppressed because it is too large Load Diff

7471
source/ext/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

3235
source/ext/stb_truetype.h Normal file

File diff suppressed because it is too large Load Diff

5453
source/ext/stb_vorbis.c Normal file

File diff suppressed because it is too large Load Diff

851
source/ext/wglext.h Normal file
View File

@ -0,0 +1,851 @@
#ifndef __wgl_wglext_h_
#define __wgl_wglext_h_ 1
#ifdef __cplusplus
extern "C" {
#endif
/*
** Copyright (c) 2013-2017 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/*
** This header is generated from the Khronos OpenGL / OpenGL ES XML
** API Registry. The current version of the Registry, generator scripts
** used to make the header, and the header can be found at
** https://github.com/KhronosGroup/OpenGL-Registry
*/
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif
#define WGL_WGLEXT_VERSION 20180316
/* Generated C header for:
* API: wgl
* Versions considered: .*
* Versions emitted: _nomatch_^
* Default extensions included: wgl
* Additional extensions included: _nomatch_^
* Extensions removed: _nomatch_^
*/
#ifndef WGL_ARB_buffer_region
#define WGL_ARB_buffer_region 1
#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001
#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002
#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004
#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008
typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType);
typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion);
typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height);
typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
#ifdef WGL_WGLEXT_PROTOTYPES
HANDLE WINAPI wglCreateBufferRegionARB (HDC hDC, int iLayerPlane, UINT uType);
VOID WINAPI wglDeleteBufferRegionARB (HANDLE hRegion);
BOOL WINAPI wglSaveBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height);
BOOL WINAPI wglRestoreBufferRegionARB (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc);
#endif
#endif /* WGL_ARB_buffer_region */
#ifndef WGL_ARB_context_flush_control
#define WGL_ARB_context_flush_control 1
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#endif /* WGL_ARB_context_flush_control */
#ifndef WGL_ARB_create_context
#define WGL_ARB_create_context 1
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define ERROR_INVALID_VERSION_ARB 0x2095
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
#ifdef WGL_WGLEXT_PROTOTYPES
HGLRC WINAPI wglCreateContextAttribsARB (HDC hDC, HGLRC hShareContext, const int *attribList);
#endif
#endif /* WGL_ARB_create_context */
#ifndef WGL_ARB_create_context_no_error
#define WGL_ARB_create_context_no_error 1
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
#endif /* WGL_ARB_create_context_no_error */
#ifndef WGL_ARB_create_context_profile
#define WGL_ARB_create_context_profile 1
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define ERROR_INVALID_PROFILE_ARB 0x2096
#endif /* WGL_ARB_create_context_profile */
#ifndef WGL_ARB_create_context_robustness
#define WGL_ARB_create_context_robustness 1
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
#endif /* WGL_ARB_create_context_robustness */
#ifndef WGL_ARB_extensions_string
#define WGL_ARB_extensions_string 1
typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc);
#ifdef WGL_WGLEXT_PROTOTYPES
const char *WINAPI wglGetExtensionsStringARB (HDC hdc);
#endif
#endif /* WGL_ARB_extensions_string */
#ifndef WGL_ARB_framebuffer_sRGB
#define WGL_ARB_framebuffer_sRGB 1
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
#endif /* WGL_ARB_framebuffer_sRGB */
#ifndef WGL_ARB_make_current_read
#define WGL_ARB_make_current_read 1
#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglMakeContextCurrentARB (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
HDC WINAPI wglGetCurrentReadDCARB (void);
#endif
#endif /* WGL_ARB_make_current_read */
#ifndef WGL_ARB_multisample
#define WGL_ARB_multisample 1
#define WGL_SAMPLE_BUFFERS_ARB 0x2041
#define WGL_SAMPLES_ARB 0x2042
#endif /* WGL_ARB_multisample */
#ifndef WGL_ARB_pbuffer
#define WGL_ARB_pbuffer 1
DECLARE_HANDLE(HPBUFFERARB);
#define WGL_DRAW_TO_PBUFFER_ARB 0x202D
#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
#define WGL_PBUFFER_LARGEST_ARB 0x2033
#define WGL_PBUFFER_WIDTH_ARB 0x2034
#define WGL_PBUFFER_HEIGHT_ARB 0x2035
#define WGL_PBUFFER_LOST_ARB 0x2036
typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer);
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC);
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer);
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
#ifdef WGL_WGLEXT_PROTOTYPES
HPBUFFERARB WINAPI wglCreatePbufferARB (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB hPbuffer);
int WINAPI wglReleasePbufferDCARB (HPBUFFERARB hPbuffer, HDC hDC);
BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB hPbuffer);
BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB hPbuffer, int iAttribute, int *piValue);
#endif
#endif /* WGL_ARB_pbuffer */
#ifndef WGL_ARB_pixel_format
#define WGL_ARB_pixel_format 1
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_DRAW_TO_BITMAP_ARB 0x2002
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NEED_PALETTE_ARB 0x2004
#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
#define WGL_SWAP_METHOD_ARB 0x2007
#define WGL_NUMBER_OVERLAYS_ARB 0x2008
#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
#define WGL_TRANSPARENT_ARB 0x200A
#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
#define WGL_SHARE_DEPTH_ARB 0x200C
#define WGL_SHARE_STENCIL_ARB 0x200D
#define WGL_SHARE_ACCUM_ARB 0x200E
#define WGL_SUPPORT_GDI_ARB 0x200F
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_STEREO_ARB 0x2012
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_COLOR_BITS_ARB 0x2014
#define WGL_RED_BITS_ARB 0x2015
#define WGL_RED_SHIFT_ARB 0x2016
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_GREEN_SHIFT_ARB 0x2018
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_BLUE_SHIFT_ARB 0x201A
#define WGL_ALPHA_BITS_ARB 0x201B
#define WGL_ALPHA_SHIFT_ARB 0x201C
#define WGL_ACCUM_BITS_ARB 0x201D
#define WGL_ACCUM_RED_BITS_ARB 0x201E
#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_AUX_BUFFERS_ARB 0x2024
#define WGL_NO_ACCELERATION_ARB 0x2025
#define WGL_GENERIC_ACCELERATION_ARB 0x2026
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_SWAP_EXCHANGE_ARB 0x2028
#define WGL_SWAP_COPY_ARB 0x2029
#define WGL_SWAP_UNDEFINED_ARB 0x202A
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_TYPE_COLORINDEX_ARB 0x202C
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetPixelFormatAttribivARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues);
BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues);
BOOL WINAPI wglChoosePixelFormatARB (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#endif
#endif /* WGL_ARB_pixel_format */
#ifndef WGL_ARB_pixel_format_float
#define WGL_ARB_pixel_format_float 1
#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
#endif /* WGL_ARB_pixel_format_float */
#ifndef WGL_ARB_render_texture
#define WGL_ARB_render_texture 1
#define WGL_BIND_TO_TEXTURE_RGB_ARB 0x2070
#define WGL_BIND_TO_TEXTURE_RGBA_ARB 0x2071
#define WGL_TEXTURE_FORMAT_ARB 0x2072
#define WGL_TEXTURE_TARGET_ARB 0x2073
#define WGL_MIPMAP_TEXTURE_ARB 0x2074
#define WGL_TEXTURE_RGB_ARB 0x2075
#define WGL_TEXTURE_RGBA_ARB 0x2076
#define WGL_NO_TEXTURE_ARB 0x2077
#define WGL_TEXTURE_CUBE_MAP_ARB 0x2078
#define WGL_TEXTURE_1D_ARB 0x2079
#define WGL_TEXTURE_2D_ARB 0x207A
#define WGL_MIPMAP_LEVEL_ARB 0x207B
#define WGL_CUBE_MAP_FACE_ARB 0x207C
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x207D
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x207E
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x207F
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x2080
#define WGL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x2081
#define WGL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x2082
#define WGL_FRONT_LEFT_ARB 0x2083
#define WGL_FRONT_RIGHT_ARB 0x2084
#define WGL_BACK_LEFT_ARB 0x2085
#define WGL_BACK_RIGHT_ARB 0x2086
#define WGL_AUX0_ARB 0x2087
#define WGL_AUX1_ARB 0x2088
#define WGL_AUX2_ARB 0x2089
#define WGL_AUX3_ARB 0x208A
#define WGL_AUX4_ARB 0x208B
#define WGL_AUX5_ARB 0x208C
#define WGL_AUX6_ARB 0x208D
#define WGL_AUX7_ARB 0x208E
#define WGL_AUX8_ARB 0x208F
#define WGL_AUX9_ARB 0x2090
typedef BOOL (WINAPI * PFNWGLBINDTEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
typedef BOOL (WINAPI * PFNWGLRELEASETEXIMAGEARBPROC) (HPBUFFERARB hPbuffer, int iBuffer);
typedef BOOL (WINAPI * PFNWGLSETPBUFFERATTRIBARBPROC) (HPBUFFERARB hPbuffer, const int *piAttribList);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglBindTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
BOOL WINAPI wglReleaseTexImageARB (HPBUFFERARB hPbuffer, int iBuffer);
BOOL WINAPI wglSetPbufferAttribARB (HPBUFFERARB hPbuffer, const int *piAttribList);
#endif
#endif /* WGL_ARB_render_texture */
#ifndef WGL_ARB_robustness_application_isolation
#define WGL_ARB_robustness_application_isolation 1
#define WGL_CONTEXT_RESET_ISOLATION_BIT_ARB 0x00000008
#endif /* WGL_ARB_robustness_application_isolation */
#ifndef WGL_ARB_robustness_share_group_isolation
#define WGL_ARB_robustness_share_group_isolation 1
#endif /* WGL_ARB_robustness_share_group_isolation */
#ifndef WGL_3DFX_multisample
#define WGL_3DFX_multisample 1
#define WGL_SAMPLE_BUFFERS_3DFX 0x2060
#define WGL_SAMPLES_3DFX 0x2061
#endif /* WGL_3DFX_multisample */
#ifndef WGL_3DL_stereo_control
#define WGL_3DL_stereo_control 1
#define WGL_STEREO_EMITTER_ENABLE_3DL 0x2055
#define WGL_STEREO_EMITTER_DISABLE_3DL 0x2056
#define WGL_STEREO_POLARITY_NORMAL_3DL 0x2057
#define WGL_STEREO_POLARITY_INVERT_3DL 0x2058
typedef BOOL (WINAPI * PFNWGLSETSTEREOEMITTERSTATE3DLPROC) (HDC hDC, UINT uState);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglSetStereoEmitterState3DL (HDC hDC, UINT uState);
#endif
#endif /* WGL_3DL_stereo_control */
#ifndef WGL_AMD_gpu_association
#define WGL_AMD_gpu_association 1
#define WGL_GPU_VENDOR_AMD 0x1F00
#define WGL_GPU_RENDERER_STRING_AMD 0x1F01
#define WGL_GPU_OPENGL_VERSION_STRING_AMD 0x1F02
#define WGL_GPU_FASTEST_TARGET_GPUS_AMD 0x21A2
#define WGL_GPU_RAM_AMD 0x21A3
#define WGL_GPU_CLOCK_AMD 0x21A4
#define WGL_GPU_NUM_PIPES_AMD 0x21A5
#define WGL_GPU_NUM_SIMD_AMD 0x21A6
#define WGL_GPU_NUM_RB_AMD 0x21A7
#define WGL_GPU_NUM_SPI_AMD 0x21A8
typedef UINT (WINAPI * PFNWGLGETGPUIDSAMDPROC) (UINT maxCount, UINT *ids);
typedef INT (WINAPI * PFNWGLGETGPUINFOAMDPROC) (UINT id, int property, GLenum dataType, UINT size, void *data);
typedef UINT (WINAPI * PFNWGLGETCONTEXTGPUIDAMDPROC) (HGLRC hglrc);
typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTAMDPROC) (UINT id);
typedef HGLRC (WINAPI * PFNWGLCREATEASSOCIATEDCONTEXTATTRIBSAMDPROC) (UINT id, HGLRC hShareContext, const int *attribList);
typedef BOOL (WINAPI * PFNWGLDELETEASSOCIATEDCONTEXTAMDPROC) (HGLRC hglrc);
typedef BOOL (WINAPI * PFNWGLMAKEASSOCIATEDCONTEXTCURRENTAMDPROC) (HGLRC hglrc);
typedef HGLRC (WINAPI * PFNWGLGETCURRENTASSOCIATEDCONTEXTAMDPROC) (void);
typedef VOID (WINAPI * PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC) (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
#ifdef WGL_WGLEXT_PROTOTYPES
UINT WINAPI wglGetGPUIDsAMD (UINT maxCount, UINT *ids);
INT WINAPI wglGetGPUInfoAMD (UINT id, int property, GLenum dataType, UINT size, void *data);
UINT WINAPI wglGetContextGPUIDAMD (HGLRC hglrc);
HGLRC WINAPI wglCreateAssociatedContextAMD (UINT id);
HGLRC WINAPI wglCreateAssociatedContextAttribsAMD (UINT id, HGLRC hShareContext, const int *attribList);
BOOL WINAPI wglDeleteAssociatedContextAMD (HGLRC hglrc);
BOOL WINAPI wglMakeAssociatedContextCurrentAMD (HGLRC hglrc);
HGLRC WINAPI wglGetCurrentAssociatedContextAMD (void);
VOID WINAPI wglBlitContextFramebufferAMD (HGLRC dstCtx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
#endif
#endif /* WGL_AMD_gpu_association */
#ifndef WGL_ATI_pixel_format_float
#define WGL_ATI_pixel_format_float 1
#define WGL_TYPE_RGBA_FLOAT_ATI 0x21A0
#endif /* WGL_ATI_pixel_format_float */
#ifndef WGL_EXT_colorspace
#define WGL_EXT_colorspace 1
#define WGL_COLORSPACE_EXT 0x3087
#define WGL_COLORSPACE_SRGB_EXT 0x3089
#define WGL_COLORSPACE_LINEAR_EXT 0x308A
#endif /* WGL_EXT_colorspace */
#ifndef WGL_EXT_create_context_es2_profile
#define WGL_EXT_create_context_es2_profile 1
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
#endif /* WGL_EXT_create_context_es2_profile */
#ifndef WGL_EXT_create_context_es_profile
#define WGL_EXT_create_context_es_profile 1
#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
#endif /* WGL_EXT_create_context_es_profile */
#ifndef WGL_EXT_depth_float
#define WGL_EXT_depth_float 1
#define WGL_DEPTH_FLOAT_EXT 0x2040
#endif /* WGL_EXT_depth_float */
#ifndef WGL_EXT_display_color_table
#define WGL_EXT_display_color_table 1
typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id);
typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length);
typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id);
typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id);
#ifdef WGL_WGLEXT_PROTOTYPES
GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort id);
GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *table, GLuint length);
GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort id);
VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort id);
#endif
#endif /* WGL_EXT_display_color_table */
#ifndef WGL_EXT_extensions_string
#define WGL_EXT_extensions_string 1
typedef const char *(WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void);
#ifdef WGL_WGLEXT_PROTOTYPES
const char *WINAPI wglGetExtensionsStringEXT (void);
#endif
#endif /* WGL_EXT_extensions_string */
#ifndef WGL_EXT_framebuffer_sRGB
#define WGL_EXT_framebuffer_sRGB 1
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
#endif /* WGL_EXT_framebuffer_sRGB */
#ifndef WGL_EXT_make_current_read
#define WGL_EXT_make_current_read 1
#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043
typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglMakeContextCurrentEXT (HDC hDrawDC, HDC hReadDC, HGLRC hglrc);
HDC WINAPI wglGetCurrentReadDCEXT (void);
#endif
#endif /* WGL_EXT_make_current_read */
#ifndef WGL_EXT_multisample
#define WGL_EXT_multisample 1
#define WGL_SAMPLE_BUFFERS_EXT 0x2041
#define WGL_SAMPLES_EXT 0x2042
#endif /* WGL_EXT_multisample */
#ifndef WGL_EXT_pbuffer
#define WGL_EXT_pbuffer 1
DECLARE_HANDLE(HPBUFFEREXT);
#define WGL_DRAW_TO_PBUFFER_EXT 0x202D
#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E
#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F
#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030
#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031
#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032
#define WGL_PBUFFER_LARGEST_EXT 0x2033
#define WGL_PBUFFER_WIDTH_EXT 0x2034
#define WGL_PBUFFER_HEIGHT_EXT 0x2035
typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer);
typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC);
typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer);
typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
#ifdef WGL_WGLEXT_PROTOTYPES
HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList);
HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT hPbuffer);
int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT hPbuffer, HDC hDC);
BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT hPbuffer);
BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue);
#endif
#endif /* WGL_EXT_pbuffer */
#ifndef WGL_EXT_pixel_format
#define WGL_EXT_pixel_format 1
#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000
#define WGL_DRAW_TO_WINDOW_EXT 0x2001
#define WGL_DRAW_TO_BITMAP_EXT 0x2002
#define WGL_ACCELERATION_EXT 0x2003
#define WGL_NEED_PALETTE_EXT 0x2004
#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005
#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006
#define WGL_SWAP_METHOD_EXT 0x2007
#define WGL_NUMBER_OVERLAYS_EXT 0x2008
#define WGL_NUMBER_UNDERLAYS_EXT 0x2009
#define WGL_TRANSPARENT_EXT 0x200A
#define WGL_TRANSPARENT_VALUE_EXT 0x200B
#define WGL_SHARE_DEPTH_EXT 0x200C
#define WGL_SHARE_STENCIL_EXT 0x200D
#define WGL_SHARE_ACCUM_EXT 0x200E
#define WGL_SUPPORT_GDI_EXT 0x200F
#define WGL_SUPPORT_OPENGL_EXT 0x2010
#define WGL_DOUBLE_BUFFER_EXT 0x2011
#define WGL_STEREO_EXT 0x2012
#define WGL_PIXEL_TYPE_EXT 0x2013
#define WGL_COLOR_BITS_EXT 0x2014
#define WGL_RED_BITS_EXT 0x2015
#define WGL_RED_SHIFT_EXT 0x2016
#define WGL_GREEN_BITS_EXT 0x2017
#define WGL_GREEN_SHIFT_EXT 0x2018
#define WGL_BLUE_BITS_EXT 0x2019
#define WGL_BLUE_SHIFT_EXT 0x201A
#define WGL_ALPHA_BITS_EXT 0x201B
#define WGL_ALPHA_SHIFT_EXT 0x201C
#define WGL_ACCUM_BITS_EXT 0x201D
#define WGL_ACCUM_RED_BITS_EXT 0x201E
#define WGL_ACCUM_GREEN_BITS_EXT 0x201F
#define WGL_ACCUM_BLUE_BITS_EXT 0x2020
#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021
#define WGL_DEPTH_BITS_EXT 0x2022
#define WGL_STENCIL_BITS_EXT 0x2023
#define WGL_AUX_BUFFERS_EXT 0x2024
#define WGL_NO_ACCELERATION_EXT 0x2025
#define WGL_GENERIC_ACCELERATION_EXT 0x2026
#define WGL_FULL_ACCELERATION_EXT 0x2027
#define WGL_SWAP_EXCHANGE_EXT 0x2028
#define WGL_SWAP_COPY_EXT 0x2029
#define WGL_SWAP_UNDEFINED_EXT 0x202A
#define WGL_TYPE_RGBA_EXT 0x202B
#define WGL_TYPE_COLORINDEX_EXT 0x202C
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues);
BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues);
BOOL WINAPI wglChoosePixelFormatEXT (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);
#endif
#endif /* WGL_EXT_pixel_format */
#ifndef WGL_EXT_pixel_format_packed_float
#define WGL_EXT_pixel_format_packed_float 1
#define WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT 0x20A8
#endif /* WGL_EXT_pixel_format_packed_float */
#ifndef WGL_EXT_swap_control
#define WGL_EXT_swap_control 1
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglSwapIntervalEXT (int interval);
int WINAPI wglGetSwapIntervalEXT (void);
#endif
#endif /* WGL_EXT_swap_control */
#ifndef WGL_EXT_swap_control_tear
#define WGL_EXT_swap_control_tear 1
#endif /* WGL_EXT_swap_control_tear */
#ifndef WGL_I3D_digital_video_control
#define WGL_I3D_digital_video_control 1
#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050
#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051
#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052
#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053
typedef BOOL (WINAPI * PFNWGLGETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
typedef BOOL (WINAPI * PFNWGLSETDIGITALVIDEOPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetDigitalVideoParametersI3D (HDC hDC, int iAttribute, int *piValue);
BOOL WINAPI wglSetDigitalVideoParametersI3D (HDC hDC, int iAttribute, const int *piValue);
#endif
#endif /* WGL_I3D_digital_video_control */
#ifndef WGL_I3D_gamma
#define WGL_I3D_gamma 1
#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E
#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F
typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, int *piValue);
typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEPARAMETERSI3DPROC) (HDC hDC, int iAttribute, const int *piValue);
typedef BOOL (WINAPI * PFNWGLGETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
typedef BOOL (WINAPI * PFNWGLSETGAMMATABLEI3DPROC) (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetGammaTableParametersI3D (HDC hDC, int iAttribute, int *piValue);
BOOL WINAPI wglSetGammaTableParametersI3D (HDC hDC, int iAttribute, const int *piValue);
BOOL WINAPI wglGetGammaTableI3D (HDC hDC, int iEntries, USHORT *puRed, USHORT *puGreen, USHORT *puBlue);
BOOL WINAPI wglSetGammaTableI3D (HDC hDC, int iEntries, const USHORT *puRed, const USHORT *puGreen, const USHORT *puBlue);
#endif
#endif /* WGL_I3D_gamma */
#ifndef WGL_I3D_genlock
#define WGL_I3D_genlock 1
#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044
#define WGL_GENLOCK_SOURCE_EXTERNAL_SYNC_I3D 0x2045
#define WGL_GENLOCK_SOURCE_EXTERNAL_FIELD_I3D 0x2046
#define WGL_GENLOCK_SOURCE_EXTERNAL_TTL_I3D 0x2047
#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048
#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049
#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A
#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B
#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C
typedef BOOL (WINAPI * PFNWGLENABLEGENLOCKI3DPROC) (HDC hDC);
typedef BOOL (WINAPI * PFNWGLDISABLEGENLOCKI3DPROC) (HDC hDC);
typedef BOOL (WINAPI * PFNWGLISENABLEDGENLOCKI3DPROC) (HDC hDC, BOOL *pFlag);
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEI3DPROC) (HDC hDC, UINT uSource);
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEI3DPROC) (HDC hDC, UINT *uSource);
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT uEdge);
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEEDGEI3DPROC) (HDC hDC, UINT *uEdge);
typedef BOOL (WINAPI * PFNWGLGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT uRate);
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSAMPLERATEI3DPROC) (HDC hDC, UINT *uRate);
typedef BOOL (WINAPI * PFNWGLGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT uDelay);
typedef BOOL (WINAPI * PFNWGLGETGENLOCKSOURCEDELAYI3DPROC) (HDC hDC, UINT *uDelay);
typedef BOOL (WINAPI * PFNWGLQUERYGENLOCKMAXSOURCEDELAYI3DPROC) (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglEnableGenlockI3D (HDC hDC);
BOOL WINAPI wglDisableGenlockI3D (HDC hDC);
BOOL WINAPI wglIsEnabledGenlockI3D (HDC hDC, BOOL *pFlag);
BOOL WINAPI wglGenlockSourceI3D (HDC hDC, UINT uSource);
BOOL WINAPI wglGetGenlockSourceI3D (HDC hDC, UINT *uSource);
BOOL WINAPI wglGenlockSourceEdgeI3D (HDC hDC, UINT uEdge);
BOOL WINAPI wglGetGenlockSourceEdgeI3D (HDC hDC, UINT *uEdge);
BOOL WINAPI wglGenlockSampleRateI3D (HDC hDC, UINT uRate);
BOOL WINAPI wglGetGenlockSampleRateI3D (HDC hDC, UINT *uRate);
BOOL WINAPI wglGenlockSourceDelayI3D (HDC hDC, UINT uDelay);
BOOL WINAPI wglGetGenlockSourceDelayI3D (HDC hDC, UINT *uDelay);
BOOL WINAPI wglQueryGenlockMaxSourceDelayI3D (HDC hDC, UINT *uMaxLineDelay, UINT *uMaxPixelDelay);
#endif
#endif /* WGL_I3D_genlock */
#ifndef WGL_I3D_image_buffer
#define WGL_I3D_image_buffer 1
#define WGL_IMAGE_BUFFER_MIN_ACCESS_I3D 0x00000001
#define WGL_IMAGE_BUFFER_LOCK_I3D 0x00000002
typedef LPVOID (WINAPI * PFNWGLCREATEIMAGEBUFFERI3DPROC) (HDC hDC, DWORD dwSize, UINT uFlags);
typedef BOOL (WINAPI * PFNWGLDESTROYIMAGEBUFFERI3DPROC) (HDC hDC, LPVOID pAddress);
typedef BOOL (WINAPI * PFNWGLASSOCIATEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
typedef BOOL (WINAPI * PFNWGLRELEASEIMAGEBUFFEREVENTSI3DPROC) (HDC hDC, const LPVOID *pAddress, UINT count);
#ifdef WGL_WGLEXT_PROTOTYPES
LPVOID WINAPI wglCreateImageBufferI3D (HDC hDC, DWORD dwSize, UINT uFlags);
BOOL WINAPI wglDestroyImageBufferI3D (HDC hDC, LPVOID pAddress);
BOOL WINAPI wglAssociateImageBufferEventsI3D (HDC hDC, const HANDLE *pEvent, const LPVOID *pAddress, const DWORD *pSize, UINT count);
BOOL WINAPI wglReleaseImageBufferEventsI3D (HDC hDC, const LPVOID *pAddress, UINT count);
#endif
#endif /* WGL_I3D_image_buffer */
#ifndef WGL_I3D_swap_frame_lock
#define WGL_I3D_swap_frame_lock 1
typedef BOOL (WINAPI * PFNWGLENABLEFRAMELOCKI3DPROC) (void);
typedef BOOL (WINAPI * PFNWGLDISABLEFRAMELOCKI3DPROC) (void);
typedef BOOL (WINAPI * PFNWGLISENABLEDFRAMELOCKI3DPROC) (BOOL *pFlag);
typedef BOOL (WINAPI * PFNWGLQUERYFRAMELOCKMASTERI3DPROC) (BOOL *pFlag);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglEnableFrameLockI3D (void);
BOOL WINAPI wglDisableFrameLockI3D (void);
BOOL WINAPI wglIsEnabledFrameLockI3D (BOOL *pFlag);
BOOL WINAPI wglQueryFrameLockMasterI3D (BOOL *pFlag);
#endif
#endif /* WGL_I3D_swap_frame_lock */
#ifndef WGL_I3D_swap_frame_usage
#define WGL_I3D_swap_frame_usage 1
typedef BOOL (WINAPI * PFNWGLGETFRAMEUSAGEI3DPROC) (float *pUsage);
typedef BOOL (WINAPI * PFNWGLBEGINFRAMETRACKINGI3DPROC) (void);
typedef BOOL (WINAPI * PFNWGLENDFRAMETRACKINGI3DPROC) (void);
typedef BOOL (WINAPI * PFNWGLQUERYFRAMETRACKINGI3DPROC) (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetFrameUsageI3D (float *pUsage);
BOOL WINAPI wglBeginFrameTrackingI3D (void);
BOOL WINAPI wglEndFrameTrackingI3D (void);
BOOL WINAPI wglQueryFrameTrackingI3D (DWORD *pFrameCount, DWORD *pMissedFrames, float *pLastMissedUsage);
#endif
#endif /* WGL_I3D_swap_frame_usage */
#ifndef WGL_NV_DX_interop
#define WGL_NV_DX_interop 1
#define WGL_ACCESS_READ_ONLY_NV 0x00000000
#define WGL_ACCESS_READ_WRITE_NV 0x00000001
#define WGL_ACCESS_WRITE_DISCARD_NV 0x00000002
typedef BOOL (WINAPI * PFNWGLDXSETRESOURCESHAREHANDLENVPROC) (void *dxObject, HANDLE shareHandle);
typedef HANDLE (WINAPI * PFNWGLDXOPENDEVICENVPROC) (void *dxDevice);
typedef BOOL (WINAPI * PFNWGLDXCLOSEDEVICENVPROC) (HANDLE hDevice);
typedef HANDLE (WINAPI * PFNWGLDXREGISTEROBJECTNVPROC) (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
typedef BOOL (WINAPI * PFNWGLDXUNREGISTEROBJECTNVPROC) (HANDLE hDevice, HANDLE hObject);
typedef BOOL (WINAPI * PFNWGLDXOBJECTACCESSNVPROC) (HANDLE hObject, GLenum access);
typedef BOOL (WINAPI * PFNWGLDXLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
typedef BOOL (WINAPI * PFNWGLDXUNLOCKOBJECTSNVPROC) (HANDLE hDevice, GLint count, HANDLE *hObjects);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglDXSetResourceShareHandleNV (void *dxObject, HANDLE shareHandle);
HANDLE WINAPI wglDXOpenDeviceNV (void *dxDevice);
BOOL WINAPI wglDXCloseDeviceNV (HANDLE hDevice);
HANDLE WINAPI wglDXRegisterObjectNV (HANDLE hDevice, void *dxObject, GLuint name, GLenum type, GLenum access);
BOOL WINAPI wglDXUnregisterObjectNV (HANDLE hDevice, HANDLE hObject);
BOOL WINAPI wglDXObjectAccessNV (HANDLE hObject, GLenum access);
BOOL WINAPI wglDXLockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
BOOL WINAPI wglDXUnlockObjectsNV (HANDLE hDevice, GLint count, HANDLE *hObjects);
#endif
#endif /* WGL_NV_DX_interop */
#ifndef WGL_NV_DX_interop2
#define WGL_NV_DX_interop2 1
#endif /* WGL_NV_DX_interop2 */
#ifndef WGL_NV_copy_image
#define WGL_NV_copy_image 1
typedef BOOL (WINAPI * PFNWGLCOPYIMAGESUBDATANVPROC) (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglCopyImageSubDataNV (HGLRC hSrcRC, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, HGLRC hDstRC, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth);
#endif
#endif /* WGL_NV_copy_image */
#ifndef WGL_NV_delay_before_swap
#define WGL_NV_delay_before_swap 1
typedef BOOL (WINAPI * PFNWGLDELAYBEFORESWAPNVPROC) (HDC hDC, GLfloat seconds);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglDelayBeforeSwapNV (HDC hDC, GLfloat seconds);
#endif
#endif /* WGL_NV_delay_before_swap */
#ifndef WGL_NV_float_buffer
#define WGL_NV_float_buffer 1
#define WGL_FLOAT_COMPONENTS_NV 0x20B0
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_R_NV 0x20B1
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RG_NV 0x20B2
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGB_NV 0x20B3
#define WGL_BIND_TO_TEXTURE_RECTANGLE_FLOAT_RGBA_NV 0x20B4
#define WGL_TEXTURE_FLOAT_R_NV 0x20B5
#define WGL_TEXTURE_FLOAT_RG_NV 0x20B6
#define WGL_TEXTURE_FLOAT_RGB_NV 0x20B7
#define WGL_TEXTURE_FLOAT_RGBA_NV 0x20B8
#endif /* WGL_NV_float_buffer */
#ifndef WGL_NV_gpu_affinity
#define WGL_NV_gpu_affinity 1
DECLARE_HANDLE(HGPUNV);
struct _GPU_DEVICE {
DWORD cb;
CHAR DeviceName[32];
CHAR DeviceString[128];
DWORD Flags;
RECT rcVirtualScreen;
};
typedef struct _GPU_DEVICE *PGPU_DEVICE;
#define ERROR_INCOMPATIBLE_AFFINITY_MASKS_NV 0x20D0
#define ERROR_MISSING_AFFINITY_MASK_NV 0x20D1
typedef BOOL (WINAPI * PFNWGLENUMGPUSNVPROC) (UINT iGpuIndex, HGPUNV *phGpu);
typedef BOOL (WINAPI * PFNWGLENUMGPUDEVICESNVPROC) (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
typedef HDC (WINAPI * PFNWGLCREATEAFFINITYDCNVPROC) (const HGPUNV *phGpuList);
typedef BOOL (WINAPI * PFNWGLENUMGPUSFROMAFFINITYDCNVPROC) (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
typedef BOOL (WINAPI * PFNWGLDELETEDCNVPROC) (HDC hdc);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglEnumGpusNV (UINT iGpuIndex, HGPUNV *phGpu);
BOOL WINAPI wglEnumGpuDevicesNV (HGPUNV hGpu, UINT iDeviceIndex, PGPU_DEVICE lpGpuDevice);
HDC WINAPI wglCreateAffinityDCNV (const HGPUNV *phGpuList);
BOOL WINAPI wglEnumGpusFromAffinityDCNV (HDC hAffinityDC, UINT iGpuIndex, HGPUNV *hGpu);
BOOL WINAPI wglDeleteDCNV (HDC hdc);
#endif
#endif /* WGL_NV_gpu_affinity */
#ifndef WGL_NV_multisample_coverage
#define WGL_NV_multisample_coverage 1
#define WGL_COVERAGE_SAMPLES_NV 0x2042
#define WGL_COLOR_SAMPLES_NV 0x20B9
#endif /* WGL_NV_multisample_coverage */
#ifndef WGL_NV_present_video
#define WGL_NV_present_video 1
DECLARE_HANDLE(HVIDEOOUTPUTDEVICENV);
#define WGL_NUM_VIDEO_SLOTS_NV 0x20F0
typedef int (WINAPI * PFNWGLENUMERATEVIDEODEVICESNVPROC) (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
typedef BOOL (WINAPI * PFNWGLBINDVIDEODEVICENVPROC) (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
typedef BOOL (WINAPI * PFNWGLQUERYCURRENTCONTEXTNVPROC) (int iAttribute, int *piValue);
#ifdef WGL_WGLEXT_PROTOTYPES
int WINAPI wglEnumerateVideoDevicesNV (HDC hDC, HVIDEOOUTPUTDEVICENV *phDeviceList);
BOOL WINAPI wglBindVideoDeviceNV (HDC hDC, unsigned int uVideoSlot, HVIDEOOUTPUTDEVICENV hVideoDevice, const int *piAttribList);
BOOL WINAPI wglQueryCurrentContextNV (int iAttribute, int *piValue);
#endif
#endif /* WGL_NV_present_video */
#ifndef WGL_NV_render_depth_texture
#define WGL_NV_render_depth_texture 1
#define WGL_BIND_TO_TEXTURE_DEPTH_NV 0x20A3
#define WGL_BIND_TO_TEXTURE_RECTANGLE_DEPTH_NV 0x20A4
#define WGL_DEPTH_TEXTURE_FORMAT_NV 0x20A5
#define WGL_TEXTURE_DEPTH_COMPONENT_NV 0x20A6
#define WGL_DEPTH_COMPONENT_NV 0x20A7
#endif /* WGL_NV_render_depth_texture */
#ifndef WGL_NV_render_texture_rectangle
#define WGL_NV_render_texture_rectangle 1
#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGB_NV 0x20A0
#define WGL_BIND_TO_TEXTURE_RECTANGLE_RGBA_NV 0x20A1
#define WGL_TEXTURE_RECTANGLE_NV 0x20A2
#endif /* WGL_NV_render_texture_rectangle */
#ifndef WGL_NV_swap_group
#define WGL_NV_swap_group 1
typedef BOOL (WINAPI * PFNWGLJOINSWAPGROUPNVPROC) (HDC hDC, GLuint group);
typedef BOOL (WINAPI * PFNWGLBINDSWAPBARRIERNVPROC) (GLuint group, GLuint barrier);
typedef BOOL (WINAPI * PFNWGLQUERYSWAPGROUPNVPROC) (HDC hDC, GLuint *group, GLuint *barrier);
typedef BOOL (WINAPI * PFNWGLQUERYMAXSWAPGROUPSNVPROC) (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
typedef BOOL (WINAPI * PFNWGLQUERYFRAMECOUNTNVPROC) (HDC hDC, GLuint *count);
typedef BOOL (WINAPI * PFNWGLRESETFRAMECOUNTNVPROC) (HDC hDC);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglJoinSwapGroupNV (HDC hDC, GLuint group);
BOOL WINAPI wglBindSwapBarrierNV (GLuint group, GLuint barrier);
BOOL WINAPI wglQuerySwapGroupNV (HDC hDC, GLuint *group, GLuint *barrier);
BOOL WINAPI wglQueryMaxSwapGroupsNV (HDC hDC, GLuint *maxGroups, GLuint *maxBarriers);
BOOL WINAPI wglQueryFrameCountNV (HDC hDC, GLuint *count);
BOOL WINAPI wglResetFrameCountNV (HDC hDC);
#endif
#endif /* WGL_NV_swap_group */
#ifndef WGL_NV_vertex_array_range
#define WGL_NV_vertex_array_range 1
typedef void *(WINAPI * PFNWGLALLOCATEMEMORYNVPROC) (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
typedef void (WINAPI * PFNWGLFREEMEMORYNVPROC) (void *pointer);
#ifdef WGL_WGLEXT_PROTOTYPES
void *WINAPI wglAllocateMemoryNV (GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority);
void WINAPI wglFreeMemoryNV (void *pointer);
#endif
#endif /* WGL_NV_vertex_array_range */
#ifndef WGL_NV_video_capture
#define WGL_NV_video_capture 1
DECLARE_HANDLE(HVIDEOINPUTDEVICENV);
#define WGL_UNIQUE_ID_NV 0x20CE
#define WGL_NUM_VIDEO_CAPTURE_SLOTS_NV 0x20CF
typedef BOOL (WINAPI * PFNWGLBINDVIDEOCAPTUREDEVICENVPROC) (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
typedef UINT (WINAPI * PFNWGLENUMERATEVIDEOCAPTUREDEVICESNVPROC) (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
typedef BOOL (WINAPI * PFNWGLLOCKVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
typedef BOOL (WINAPI * PFNWGLQUERYVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOCAPTUREDEVICENVPROC) (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglBindVideoCaptureDeviceNV (UINT uVideoSlot, HVIDEOINPUTDEVICENV hDevice);
UINT WINAPI wglEnumerateVideoCaptureDevicesNV (HDC hDc, HVIDEOINPUTDEVICENV *phDeviceList);
BOOL WINAPI wglLockVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
BOOL WINAPI wglQueryVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice, int iAttribute, int *piValue);
BOOL WINAPI wglReleaseVideoCaptureDeviceNV (HDC hDc, HVIDEOINPUTDEVICENV hDevice);
#endif
#endif /* WGL_NV_video_capture */
#ifndef WGL_NV_video_output
#define WGL_NV_video_output 1
DECLARE_HANDLE(HPVIDEODEV);
#define WGL_BIND_TO_VIDEO_RGB_NV 0x20C0
#define WGL_BIND_TO_VIDEO_RGBA_NV 0x20C1
#define WGL_BIND_TO_VIDEO_RGB_AND_DEPTH_NV 0x20C2
#define WGL_VIDEO_OUT_COLOR_NV 0x20C3
#define WGL_VIDEO_OUT_ALPHA_NV 0x20C4
#define WGL_VIDEO_OUT_DEPTH_NV 0x20C5
#define WGL_VIDEO_OUT_COLOR_AND_ALPHA_NV 0x20C6
#define WGL_VIDEO_OUT_COLOR_AND_DEPTH_NV 0x20C7
#define WGL_VIDEO_OUT_FRAME 0x20C8
#define WGL_VIDEO_OUT_FIELD_1 0x20C9
#define WGL_VIDEO_OUT_FIELD_2 0x20CA
#define WGL_VIDEO_OUT_STACKED_FIELDS_1_2 0x20CB
#define WGL_VIDEO_OUT_STACKED_FIELDS_2_1 0x20CC
typedef BOOL (WINAPI * PFNWGLGETVIDEODEVICENVPROC) (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
typedef BOOL (WINAPI * PFNWGLRELEASEVIDEODEVICENVPROC) (HPVIDEODEV hVideoDevice);
typedef BOOL (WINAPI * PFNWGLBINDVIDEOIMAGENVPROC) (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
typedef BOOL (WINAPI * PFNWGLRELEASEVIDEOIMAGENVPROC) (HPBUFFERARB hPbuffer, int iVideoBuffer);
typedef BOOL (WINAPI * PFNWGLSENDPBUFFERTOVIDEONVPROC) (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
typedef BOOL (WINAPI * PFNWGLGETVIDEOINFONVPROC) (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetVideoDeviceNV (HDC hDC, int numDevices, HPVIDEODEV *hVideoDevice);
BOOL WINAPI wglReleaseVideoDeviceNV (HPVIDEODEV hVideoDevice);
BOOL WINAPI wglBindVideoImageNV (HPVIDEODEV hVideoDevice, HPBUFFERARB hPbuffer, int iVideoBuffer);
BOOL WINAPI wglReleaseVideoImageNV (HPBUFFERARB hPbuffer, int iVideoBuffer);
BOOL WINAPI wglSendPbufferToVideoNV (HPBUFFERARB hPbuffer, int iBufferType, unsigned long *pulCounterPbuffer, BOOL bBlock);
BOOL WINAPI wglGetVideoInfoNV (HPVIDEODEV hpVideoDevice, unsigned long *pulCounterOutputPbuffer, unsigned long *pulCounterOutputVideo);
#endif
#endif /* WGL_NV_video_output */
#ifndef WGL_OML_sync_control
#define WGL_OML_sync_control 1
typedef BOOL (WINAPI * PFNWGLGETSYNCVALUESOMLPROC) (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
typedef BOOL (WINAPI * PFNWGLGETMSCRATEOMLPROC) (HDC hdc, INT32 *numerator, INT32 *denominator);
typedef INT64 (WINAPI * PFNWGLSWAPBUFFERSMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
typedef INT64 (WINAPI * PFNWGLSWAPLAYERBUFFERSMSCOMLPROC) (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
typedef BOOL (WINAPI * PFNWGLWAITFORMSCOMLPROC) (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
typedef BOOL (WINAPI * PFNWGLWAITFORSBCOMLPROC) (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
#ifdef WGL_WGLEXT_PROTOTYPES
BOOL WINAPI wglGetSyncValuesOML (HDC hdc, INT64 *ust, INT64 *msc, INT64 *sbc);
BOOL WINAPI wglGetMscRateOML (HDC hdc, INT32 *numerator, INT32 *denominator);
INT64 WINAPI wglSwapBuffersMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder);
INT64 WINAPI wglSwapLayerBuffersMscOML (HDC hdc, int fuPlanes, INT64 target_msc, INT64 divisor, INT64 remainder);
BOOL WINAPI wglWaitForMscOML (HDC hdc, INT64 target_msc, INT64 divisor, INT64 remainder, INT64 *ust, INT64 *msc, INT64 *sbc);
BOOL WINAPI wglWaitForSbcOML (HDC hdc, INT64 target_sbc, INT64 *ust, INT64 *msc, INT64 *sbc);
#endif
#endif /* WGL_OML_sync_control */
#ifdef __cplusplus
}
#endif
#endif

1609
source/language_layer.c Normal file

File diff suppressed because it is too large Load Diff

450
source/language_layer.h Normal file
View File

@ -0,0 +1,450 @@
// NOTE(allen): Things I added durring this jam
// MemoryMatch
// Exponent32
// Sign32
// bug in Clamp
// bug in DLLRemove
// TODO(allen): Gave String8_Node/String8_List wrong naming scheme
// bug in SLLQueuePush_N
// MemoryMatchStruct
// AssertIff
////////////////////////////////
//~ NOTE(rjf): C Standard Library
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#define MemoryCopy(d,s,z) memmove(d,s,z)
#define MemoryCopyStruct(d,s) MemoryCopy(d,s,sizeof(*(d)))
#define MemorySet(s,v,z) memset(s,v,z)
#define MemoryZero(s,z) memset(s,0,z)
#define MemoryZeroStruct(s) MemoryZero(s,sizeof(*(s)))
#define MemoryZeroArray(a) memset(a,0,sizeof(a))
#define MemoryMatch(a,b,z) (memcmp((a),(b),(z)) == 0)
#define MemoryMatchStruct(a,b) MemoryMatch(a,b,sizeof(*(a)))
#define CalculateCStringLength (u32)strlen
#define CStringToI32(s) ((i32)atoi(s))
#define CStringToI16(s) ((i16)atoi(s))
#define CStringToF32(s) ((f32)atof(s))
////////////////////////////////
//~ NOTE(rjf): Base Types
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef i8 b8;
typedef i16 b16;
typedef i32 b32;
typedef i64 b64;
typedef float f32;
typedef double f64;
////////////////////////////////
//~ NOTE(rjf): Helper Macros
#define global static
#define internal static
#define local_persist static
#define ArrayCount(a) (sizeof(a) / sizeof((a)[0]))
#define Bytes(n) ((u64)(n))
#define Kilobytes(n) (((u64)(n)) << 10)
#define Megabytes(n) (((u64)(n)) << 20)
#define Gigabytes(n) (((u64)(n)) << 30)
#define Thousand(n) ((n)*1000)
#define Million(n) ((n)*1000000)
#define Billion(n) ((n)*1000000000)
#define PI (3.1415926535897f)
#define Stmnt(S) do{ S }while(0)
#define AssertBreak() (*(int*)0 = 0xABCD)
#if SHIP_MODE
#define Assert(c)
#else
#define Assert(c) Stmnt( if (!(c)){ AssertBreak(); } )
#endif
#define AssertImplies(a,b) Assert(!(a) || (b))
#define AssertIff(a,b) Assert((a) == (b))
#define InvalidPath Assert(!"Invalid Path")
#define NotImplemented Assert(!"Not Implemented")
#define Stringify_(S) #S
#define Stringify(S) Stringify_(S)
#define Glue_(A,B) A##B
#define Glue(A,B) Glue_(A,B)
#define Min(A,B) ( ((A)<(B))?(A):(B) )
#define Max(A,B) ( ((A)>(B))?(A):(B) )
#define ClampTop(A,X) Min(A,X)
#define ClampBot(X,B) Max(X,B)
#define Clamp(A,X,B) ( ((X)<(A))?(A):((X)>(B))?(B):(X) )
#define Swap(T,a,b) Stmnt( T t__ = a; a = b; b = t__; )
#define IntFromPtr(ptr) ((u64)(ptr))
#define PtrFromInt(i) (void*)((u8*)0 + (i))
#define Member(T,m) (((T*)0)->m)
#define OffsetOf(T,m) IntFromPtr(&Member(T,m))
#define CastFromMember(T,m,ptr) (T*)(((u8*)ptr) - OffsetOf(T,m))
////////////////////////////////
//~ NOTE(allen): Linked Lists
#define DLLPushBack_NP(f,l,n,next,prev) ( (f)==0?\
((f)=(l)=(n),(n)->next=(n)->prev=0):\
((l)->next=(n),(n)->prev=(l),(l)=(n),(n)->next=0) )
#define DLLPushFront_NP(f,l,n,next,prev) DLLPushBack_NP(l,f,n,prev,next)
#define DLLPushBack(f,l,n) DLLPushBack_NP(f,l,n,next,prev)
#define DLLPushFront(f,l,n) DLLPushFront_NP(f,l,n,next,prev)
#define DLLInsertAfter_NP(f,l,p,n,next,prev) ( ((l)==(p))?\
DLLPushBack_NP(f,l,n,next,prev):\
((n)->prev=(p),(n)->next=(p)->next,(p)->next->prev=(n),(p)->next=(n)) )
#define DLLInsertBefore_NP(f,l,p,n,next,prev) DLLInsertAfter_NP(l,f,p,n,prev,next)
#define DLLInsertAfter(f,l,p,n) DLLInsertAfter_NP(f,l,p,n,next,prev)
#define DLLInsertBefore(f,l,p,n) DLLInsertBefore_NP(f,l,p,n,next,prev)
#define DLLRemoveFirst_NP(f,l,next,prev) ( ((f)==(l))?\
(f)=(l)=0:\
((f)=(f)->next,(f)->prev=0) )
#define DLLRemoveLast_NP(f,l,next,prev) DLLRemoveFirst_NP(l,f,prev,next)
#define DLLRemove_NP(f,l,n,next,prev) ( ((f)==(n))?\
DLLRemoveFirst_NP(f,l,next,prev):\
((l)==(n))?\
DLLRemoveLast_NP(f,l,next,prev):\
((n)->next->prev=(n)->prev,(n)->prev->next=(n)->next) )
#define DLLRemove(f,l,n) DLLRemove_NP(f,l,n,next,prev)
#define SLLQueuePush_N(f,l,n,next) ( (f)==0?\
((f)=(l)=(n),(n)->next=0):\
((l)->next=(n),(l)=(n),(n)->next=0) )
#define SLLQueuePushFront_N(f,l,n,next) ( (f)==0?\
((f)=(l)=(n),(n)->next=0):\
((n)->next=(f),(f)=(n)) )
#define SLLQueuePop_N(f,l,next) ( (f)==(l)?\
(f)=(l)=0:\
((f)=(f)->next) )
#define SLLQueuePush(f,l,n) SLLQueuePush_N(f,l,n,next)
#define SLLQueuePushFront(f,l,n) SLLQueuePushFront_N(f,l,n,next)
#define SLLQueuePop(f,l) SLLQueuePop_N(f,l,next)
#define SLLStackPush_N(f,n,next) ( (n)->next=(f), (f)=(n) )
#define SLLStackPop_N(f,next) ( (f)=(f)->next )
#define SLLStackPush(f,n) SLLStackPush_N(f,n,next)
#define SLLStackPop(f) SLLStackPop_N(f,next)
////////////////////////////////
//~ NOTE(allen): Constants
typedef enum
{
Dimension_X,
Dimension_Y,
Dimension_Z,
Dimension_W,
} Dimension;
typedef enum
{
Side_Min,
Side_Max,
} Side;
global u32 Sign32 = 0x80000000;
global u32 Exponent32 = 0x7F800000;
global u32 Mantissa32 = 0x007FFFFF;
global f32 BigGolden32 = 1.61803398875f;
global f32 SmallGolden32 = 0.61803398875f;
////////////////////////////////
//~ NOTE(allen): Vectors
typedef union v2 v2;
union v2
{
struct
{
f32 x;
f32 y;
};
struct
{
f32 width;
f32 height;
};
float elements[2];
float v[2];
};
typedef union v3 v3;
union v3
{
struct
{
f32 x;
f32 y;
f32 z;
};
struct
{
f32 r;
f32 g;
f32 b;
};
f32 elements[3];
f32 v[3];
};
typedef union v4 v4;
union v4
{
struct
{
f32 x;
f32 y;
union
{
struct
{
f32 z;
union
{
f32 w;
f32 radius;
};
};
struct
{
f32 width;
f32 height;
};
};
};
struct
{
f32 r;
f32 g;
f32 b;
f32 a;
};
f32 elements[4];
f32 v[4];
};
typedef union iv2 iv2;
union iv2
{
struct
{
i32 x;
i32 y;
};
struct
{
i32 width;
i32 height;
};
i32 elements[2];
i32 v[2];
};
typedef union iv3 iv3;
union iv3
{
struct
{
i32 x;
i32 y;
i32 z;
};
struct
{
i32 r;
i32 g;
i32 b;
};
i32 elements[3];
i32 v[3];
};
typedef union iv4 iv4;
union iv4
{
struct
{
i32 x;
i32 y;
i32 z;
i32 w;
};
struct
{
i32 r;
i32 g;
i32 b;
i32 a;
};
i32 elements[4];
i32 v[4];
};
#define v2(...) (v2){ __VA_ARGS__ }
#define v3(...) (v3){ __VA_ARGS__ }
#define v4(...) (v4){ __VA_ARGS__ }
#define iv2(...) (iv2){ __VA_ARGS__ }
#define iv3(...) (iv3){ __VA_ARGS__ }
#define iv4(...) (iv4){ __VA_ARGS__ }
////////////////////////////////
//~ NOTE(allen): Matrix
typedef struct m4 m4;
struct m4
{
f32 elements[4][4];
};
////////////////////////////////
//~ NOTE(allen): Interval
typedef union Range Range;
union Range
{
struct
{
f32 min;
f32 max;
};
f32 v[2];
};
typedef union Rangei Rangei;
union Rangei
{
struct{
i64 min;
i64 max;
};
i64 v[2];
};
typedef union Rangeu Rangeu;
union Rangeu
{
struct{
u64 min;
u64 max;
};
u64 v[2];
};
typedef union Rect Rect;
union Rect
{
struct{
f32 x0;
f32 y0;
f32 x1;
f32 y1;
};
struct{
v2 p0;
v2 p1;
};
f32 v[4];
v2 p[2];
};
////////////////////////////////
//~ NOTE(allen): String
typedef struct String8 String8;
struct String8
{
union
{
u8 *string;
u8 *str;
void *data;
void *ptr;
};
u64 size;
};
#define S8Lit(s) S8((u8*)(s), ArrayCount(s) - 1)
#define S8LitComp(s) {(u8*)(s), ArrayCount(s) - 1}
#define StringExpand(s) (int)((s).size), ((s).str)
typedef u32 StringMatchFlags;
enum
{
StringMatchFlag_CaseInsensitive = (1<<0),
StringMatchFlag_RightSideSloppy = (1<<1),
};
typedef struct String8_Node String8_Node;
struct String8_Node
{
String8_Node *next;
String8 string;
};
typedef struct String8_List String8_List;
struct String8_List
{
String8_Node *first;
String8_Node *last;
u64 total_size;
u64 node_count;
};
typedef struct String_Join String_Join;
struct String_Join
{
String8 pre;
String8 sep;
String8 post;
};

19
source/opengl.h Normal file
View File

@ -0,0 +1,19 @@
#if BUILD_WIN32
#include <windows.h>
#include <gl/gl.h>
#include "ext/wglext.h"
#else
#error "OpenGL includes for platform not supported."
#endif
#include "ext/glext.h"
#define GLProc(name, type) PFN##type##PROC name = 0;
#include "opengl_procedure_list.h"
internal void
LoadAllOpenGLProcedures(void)
{
#define GLProc(name, type) name = os->LoadOpenGLProcedure(#name);
#include "opengl_procedure_list.h"
}

View File

@ -0,0 +1,33 @@
GLProc(glGenBuffers, GLGENBUFFERS)
GLProc(glBindBuffer, GLBINDBUFFER)
GLProc(glGenVertexArrays, GLGENVERTEXARRAYS)
GLProc(glBindVertexArray, GLBINDVERTEXARRAY)
GLProc(glCreateProgram, GLCREATEPROGRAM)
GLProc(glCreateShader, GLCREATESHADER)
GLProc(glShaderSource, GLSHADERSOURCE)
GLProc(glCompileShader, GLCOMPILESHADER)
GLProc(glGetShaderiv, GLGETSHADERIV)
GLProc(glGetShaderInfoLog, GLGETSHADERINFOLOG)
GLProc(glGetProgramiv, GLGETPROGRAMIV)
GLProc(glGetProgramInfoLog, GLGETPROGRAMINFOLOG)
GLProc(glAttachShader, GLATTACHSHADER)
GLProc(glLinkProgram, GLLINKPROGRAM)
GLProc(glValidateProgram, GLVALIDATEPROGRAM)
GLProc(glDeleteShader, GLDELETESHADER)
GLProc(glGetUniformLocation, GLGETUNIFORMLOCATION)
GLProc(glGetAttribLocation, GLGETATTRIBLOCATION)
GLProc(glEnableVertexAttribArray, GLENABLEVERTEXATTRIBARRAY)
GLProc(glVertexAttribPointer, GLVERTEXATTRIBPOINTER)
GLProc(glBufferData, GLBUFFERDATA)
GLProc(glBufferSubData, GLBUFFERSUBDATA)
GLProc(glBlendFuncSeparate, GLBLENDFUNCSEPARATE)
GLProc(glUseProgram, GLUSEPROGRAM)
GLProc(glUniform1i, GLUNIFORM1I)
GLProc(glUniform1f, GLUNIFORM1F)
GLProc(glUniform2f, GLUNIFORM2F)
GLProc(glUniform3f, GLUNIFORM3F)
GLProc(glUniform4f, GLUNIFORM4F)
GLProc(glTexSubImage3D, GLTEXSUBIMAGE3D)
GLProc(glTexImage3D, GLTEXIMAGE3D)
GLProc(glGenerateMipmap, GLGENERATEMIPMAP)
#undef GLProc

21
source/operations.c Normal file
View File

@ -0,0 +1,21 @@
////////////////////////////////
// NOTE(allen): User Operations
internal void
OP_ViewPageFromDefinition(E_Definition *definition){
E_View *switch_view = APP_GetPageView(definition);
if (switch_view == 0){
switch_view = E_NewView();
E_InitPageView(switch_view, &vars->font, definition);
}
APP_SignalViewChange(switch_view);
}
internal void
OP_LookAtDefinition(E_Definition *definition){
if (vars->active_view != 0){
E_ViewLookAtDefinition(vars->active_view, definition);
E_Tile *tile = E_GetTileForDefinition(vars->active_view->first_tile, definition);
APP_SignalSnapToTile(tile);
}
}

9
source/operations.h Normal file
View File

@ -0,0 +1,9 @@
/* date = July 12th 2020 11:19 am */
#ifndef OPERATIONS_H
#define OPERATIONS_H
internal void OP_ViewPageFromDefinition(E_Definition *definition);
internal void OP_LookAtDefinition(E_Definition *definition);
#endif //OPERATIONS_H

325
source/os.c Normal file
View File

@ -0,0 +1,325 @@
// TODO(allen): Changes durring this jam
// fix with os->event_count not resetting
////////////////////////////////
// NOTE(allen): Events
internal String8
KeyName(Key index)
{
local_persist char *strings[Key_Max] =
{
#define Key(name, str) str,
#include "os_key_list.inc"
#undef Key
};
char *string = "(Invalid Key)";
if(index >= 0 && index < ArrayCount(strings))
{
string = strings[index];
}
String8 result;
result.str = string;
result.size = CalculateCStringLength(result.str);
return result;
}
internal String8
GamepadButtonName(GamepadButton index)
{
local_persist char *strings[GamepadButton_Max] =
{
#define GamepadButton(name, str) str,
#include "os_gamepad_button_list.inc"
#undef GamepadButton
};
char *string = "(Invalid Gamepad Button)";
if(index >= 0 && index < ArrayCount(strings))
{
string = strings[index];
}
String8 result;
result.str = string;
result.size = CalculateCStringLength(result.str);
return result;
}
internal b32
OS_EventIsMouse(OS_Event *event)
{
return event->type > OS_EventType_MouseStart && event->type < OS_EventType_MouseEnd;
}
internal b32
OS_CompareEvents(OS_Event a, OS_Event b)
{
b32 result = 0;
if(a.type == b.type &&
a.key == b.key &&
a.mouse_button == b.mouse_button &&
a.gamepad_button == b.gamepad_button &&
a.character == b.character &&
a.modifiers == b.modifiers)
{
result = 1;
}
return result;
}
internal OS_Event
OS_KeyPressEvent(Key key, KeyModifiers modifiers)
{
OS_Event event =
{
.type = OS_EventType_KeyPress,
};
event.key = key;
event.modifiers = modifiers;
return event;
}
internal OS_Event
OS_KeyReleaseEvent(Key key, KeyModifiers modifiers)
{
OS_Event event =
{
.type = OS_EventType_KeyRelease,
};
event.key = key;
event.modifiers = modifiers;
return event;
}
internal OS_Event
OS_CharacterInputEvent(u64 character)
{
OS_Event event =
{
.type = OS_EventType_CharacterInput,
};
event.character = character;
return event;
}
internal OS_Event
OS_MouseMoveEvent(v2 position, v2 delta)
{
OS_Event event =
{
.type = OS_EventType_MouseMove,
};
event.position = position;
event.delta = delta;
return event;
}
internal OS_Event
OS_MousePressEvent(MouseButton button, v2 position)
{
OS_Event event =
{
.type = OS_EventType_MousePress,
};
event.mouse_button = button;
event.position = position;
return event;
}
internal OS_Event
OS_MouseReleaseEvent(MouseButton mouse_button, v2 position)
{
OS_Event event =
{
.type = OS_EventType_MouseRelease,
};
event.mouse_button = mouse_button;
event.position = position;
return event;
}
internal OS_Event
OS_MouseScrollEvent(v2 delta, KeyModifiers modifiers)
{
OS_Event event =
{
.type = OS_EventType_MouseScroll,
};
event.scroll = delta;
event.modifiers = modifiers;
return event;
}
internal b32
OS_GetNextEvent(OS_Event **event)
{
b32 result = 0;
Assert(os != 0);
u32 start_index = 0;
OS_Event *new_event = 0;
if(*event)
{
start_index = (*event - os->events) + 1;
}
for(u32 i = start_index; i < os->event_count; ++i)
{
if(os->events[i].type != OS_EventType_Null)
{
new_event = os->events+i;
break;
}
}
*event = new_event;
result = new_event != 0;
return result;
}
internal void
OS_EatEvent(OS_Event *event)
{
event->type = OS_EventType_Null;
}
// NOTE(rjf): Only called by platform layers. Do not call in app.
internal void
OS_BeginFrame(void)
{
os->pump_events = 0;
}
// NOTE(rjf): Only called by platform layers. Do not call in app.
internal void
OS_EndFrame(void)
{
os->current_time += 1.f / os->target_frames_per_second;
}
// NOTE(rjf): Only called by platform layers. Do not call in app.
internal void
OS_PushEvent(OS_Event event)
{
Assert(os != 0);
if(os->event_count < ArrayCount(os->events))
{
os->events[os->event_count++] = event;
}
}
////////////////////////////////
// NOTE(allen): Thread Context
internal OS_ArenaNode*
_OS_GetFreeScratch(OS_ThreadContext *tctx)
{
OS_ArenaNode *usable_node = tctx->free;
Assert(usable_node != 0);
SLLStackPop(tctx->free);
DLLPushBack(tctx->first_used, tctx->last_used, usable_node);
return(usable_node);
}
internal M_Arena*
_OS_MarkArenaRestore(OS_ArenaNode *node)
{
M_Arena *result = &node->arena;
OS_ArenaInlineRestore *restore = PushArray(result, OS_ArenaInlineRestore, 1);
SLLStackPush(node->restore, restore);
node->ref_count += 1;
return(result);
}
internal M_Arena*
OS_GetScratch(void)
{
OS_ThreadContext *tctx = os->GetThreadContext();
OS_ArenaNode *usable_node = tctx->first_used;
if (usable_node == 0)
{
usable_node = _OS_GetFreeScratch(tctx);
}
return(_OS_MarkArenaRestore(usable_node));
}
internal M_Arena*
OS_GetScratch1(M_Arena *a1)
{
OS_ThreadContext *tctx = os->GetThreadContext();
OS_ArenaNode *usable_node = 0;
for (OS_ArenaNode *node = tctx->first_used;
node != 0;
node = node->next)
{
if (&node->arena != a1)
{
usable_node = node;
break;
}
}
if (usable_node == 0)
{
usable_node = _OS_GetFreeScratch(tctx);
}
return(_OS_MarkArenaRestore(usable_node));
}
internal M_Arena*
OS_GetScratch2(M_Arena *a1, M_Arena *a2)
{
OS_ThreadContext *tctx = os->GetThreadContext();
OS_ArenaNode *usable_node = 0;
for (OS_ArenaNode *node = tctx->first_used;
node != 0;
node = node->next)
{
if (&node->arena != a1 && &node->arena != a2)
{
usable_node = node;
break;
}
}
if (usable_node == 0)
{
usable_node = _OS_GetFreeScratch(tctx);
}
return(_OS_MarkArenaRestore(usable_node));
}
internal void
OS_ReleaseScratch(M_Arena *arena)
{
OS_ArenaNode *node = CastFromMember(OS_ArenaNode, arena, arena);
Assert(node->ref_count > 0);
node->ref_count -= 1;
if (node->ref_count == 0)
{
OS_ThreadContext *tctx = os->GetThreadContext();
DLLRemove(tctx->first_used, tctx->last_used, node);
M_ArenaClear(arena);
SLLStackPush(tctx->free, node);
}
else
{
void *ptr = node->restore;
node->restore = node->restore->next;
M_ArenaSetPosBackByPtr(arena, ptr);
}
}
internal void
_OS_ThreadSaveFileLine(char *file_name, u64 line_number)
{
OS_ThreadContext *tctx = os->GetThreadContext();
tctx->file_name = file_name;
tctx->line_number = line_number;
}
#define OS_ThreadSaveFileLine() _OS_ThreadSaveFileLine(__FILE__, __LINE__)
internal OS_File_Line
OS_ThreadRememberFileLine(void)
{
OS_ThreadContext *tctx = os->GetThreadContext();
OS_File_Line result = {tctx->file_name, tctx->line_number};
return(result);
}

248
source/os.h Normal file
View File

@ -0,0 +1,248 @@
// TODO(allen): Changes durring this jam
// SaveToFile
//~ NOTE(rjf): Keys
typedef enum Key
{
#define Key(name, str) Key_##name,
#include "os_key_list.inc"
#undef Key
Key_Max
}
Key;
typedef u32 KeyModifiers;
enum
{
KeyModifier_Ctrl = (1<<0),
KeyModifier_Shift = (1<<1),
KeyModifier_Alt = (1<<2),
};
//~ NOTE(rjf): Mouse
typedef enum MouseButton
{
MouseButton_Left,
MouseButton_Right,
MouseButton_Middle,
}
MouseButton;
//~ NOTE(rjf): Gamepads
typedef enum GamepadButton
{
#define GamepadButton(name, str) GamepadButton_##name,
#include "os_gamepad_button_list.inc"
#undef GamepadButton
GamepadButton_Max
}
GamepadButton;
//~ NOTE(rjf): Platform Directory Listing
#define OS_DirectoryList_IncludeDirectories (1<<0)
#define OS_DirectoryList_IncludeExtensions (1<<1)
#define OS_DirectoryList_SearchRecursively (1<<2)
#define OS_DirectoryItem_IsDirectory (1<<0)
typedef struct OS_DirectoryItem OS_DirectoryItem;
struct OS_DirectoryItem
{
String8 string;
u64 flags;
};
typedef struct OS_DirectoryItemChunk OS_DirectoryItemChunk;
struct OS_DirectoryItemChunk
{
OS_DirectoryItem items[32];
OS_DirectoryItemChunk *next;
u64 item_count;
};
typedef struct OS_DirectoryList OS_DirectoryList;
struct OS_DirectoryList
{
u64 flags;
u64 item_count;
OS_DirectoryItemChunk *first_chunk;
};
//~ NOTE(rjf): Events
typedef enum OS_EventType
{
OS_EventType_Null,
// NOTE(rjf): Keyboard
OS_EventType_KeyStart,
OS_EventType_CharacterInput,
OS_EventType_KeyPress,
OS_EventType_KeyRelease,
OS_EventType_KeyEnd,
// NOTE(rjf): Mouse
OS_EventType_MouseStart,
OS_EventType_MousePress,
OS_EventType_MouseRelease,
OS_EventType_MouseMove,
OS_EventType_MouseScroll,
OS_EventType_MouseEnd,
// NOTE(rjf): Gamepads
OS_EventType_GamepadStart,
OS_EventType_GamepadConnect,
OS_EventType_GamepadDisconnect,
OS_EventType_GamepadButtonPress,
OS_EventType_GamepadButtonRelease,
OS_EventType_GamepadJoystickMove,
OS_EventType_GamepadTrigger,
OS_EventType_GamepadEnd,
OS_EventType_Max,
}
OS_EventType;
typedef struct OS_Event OS_Event;
struct OS_Event
{
OS_EventType type;
Key key;
GamepadButton gamepad_button;
MouseButton mouse_button;
KeyModifiers modifiers;
i32 gamepad_index;
u64 character;
v2 position;
v2 delta;
v2 scroll;
};
//~ NOTE(allen): Thread Context
typedef struct OS_ArenaInlineRestore OS_ArenaInlineRestore;
struct OS_ArenaInlineRestore{
OS_ArenaInlineRestore *next;
};
typedef struct OS_ArenaNode OS_ArenaNode;
struct OS_ArenaNode
{
OS_ArenaNode *next;
OS_ArenaNode *prev;
M_Arena arena;
OS_ArenaInlineRestore *restore;
u64 ref_count;
};
typedef struct OS_File_Line OS_File_Line;
struct OS_File_Line
{
char *file_name;
u64 line_number;
};
typedef struct OS_ThreadContext OS_ThreadContext;
struct OS_ThreadContext
{
OS_ArenaNode *free;
OS_ArenaNode *first_used;
OS_ArenaNode *last_used;
char *file_name;
u64 line_number;
};
//~ NOTE(rjf): Platform Data
typedef struct OS_State OS_State;
struct OS_State
{
// NOTE(rjf): Application Metadata
String8 executable_folder_absolute_path;
String8 executable_absolute_path;
String8 working_directory_path;
// NOTE(rjf): Memory
M_Arena permanent_arena;
M_Arena frame_arena;
// NOTE(rjf): Options
volatile b32 quit;
b32 vsync;
b32 fullscreen;
iv2 window_size;
f32 current_time;
f32 target_frames_per_second;
b32 wait_for_events_to_update;
b32 pump_events;
// NOTE(rjf): Event Queue and Input Data
v2 mouse_position;
u64 event_count;
OS_Event events[4096];
// NOTE(rjf): Audio Output Data
f32 *sample_out;
u32 sample_count_to_output;
u32 samples_per_second;
// NOTE(rjf): Functions
void *(*Reserve)(u64 size);
void (*Release)(void *memory);
void (*Commit)(void *memory, u64 size);
void (*Decommit)(void *memory, u64 size);
void (*OutputError)(char *error_type, char *error_format, ...);
b32 (*SaveToFile)(String8 path, void *data, u64 data_len);
void (*AppendToFile)(String8 path, void *data, u64 data_len);
void (*LoadEntireFile)(M_Arena *arena, String8 path, void **data, u64 *data_len);
char *(*LoadEntireFileAndNullTerminate)(M_Arena *arena, String8 path);
void (*DeleteFile)(String8 path);
b32 (*MakeDirectory)(String8 path);
b32 (*DoesFileExist)(String8 path);
b32 (*DoesDirectoryExist)(String8 path);
b32 (*CopyFile)(String8 dest, String8 source);
OS_DirectoryList (*ListDirectory)(M_Arena *arena, String8 path, i32 flags);
f32 (*GetTime)(void);
u64 (*GetCycles)(void);
void (*ResetCursor)(void);
void (*SetCursorToHorizontalResize)(void);
void (*SetCursorToVerticalResize)(void);
void (*SetCursorToIBar)(void);
void (*RefreshScreen)(void);
void *(*LoadOpenGLProcedure)(char *name);
OS_ThreadContext *(*GetThreadContext)(void);
String8 (*DialogueSavePath)(M_Arena *arena, String8 *fixed_extension);
String8 (*DialogueLoadPath)(M_Arena *arena, String8 *fixed_extension);
};
global OS_State *os = 0;
#ifdef _MSC_VER
#define APP_ENTRY_POINT __declspec(dllexport)
#else
#define APP_ENTRY_POINT
#endif
/* Loaded as "PermanentLoad" */
#define APP_PERMANENT_LOAD APP_ENTRY_POINT void PermanentLoad(OS_State *os_)
typedef void ApplicationPermanentLoadCallback(OS_State *);
internal void ApplicationPermanentLoadStub(OS_State *_) {}
/* Loaded as "HotLoad" */
#define APP_HOT_LOAD APP_ENTRY_POINT void HotLoad(OS_State *os_)
typedef void ApplicationHotLoadCallback(OS_State *);
internal void ApplicationHotLoadStub(OS_State *_) {}
/* Loaded as "HotUnload" */
#define APP_HOT_UNLOAD APP_ENTRY_POINT void HotUnload(void)
typedef void ApplicationHotUnloadCallback(void);
internal void ApplicationHotUnloadStub(void) {}
/* Loaded as "Update" */
#define APP_UPDATE APP_ENTRY_POINT void Update(void)
typedef void ApplicationUpdateCallback(void);
internal void ApplicationUpdateStub(void) {}

View File

@ -0,0 +1,15 @@
GamepadButton(Null, "Invalid Gamepad Button")
GamepadButton(DPadUp, "D-Pad Up")
GamepadButton(DPadDown, "D-Pad Down")
GamepadButton(DPadLeft, "D-Pad Left")
GamepadButton(DPadRight, "D-Pad Right")
GamepadButton(Start, "Start")
GamepadButton(Back, "Back")
GamepadButton(LeftThumb, "Left Thumb")
GamepadButton(RightThumb, "Right Thumb")
GamepadButton(LeftShoulder, "Left Shoulder")
GamepadButton(RightShoulder, "Right Shoulder")
GamepadButton(A, "A")
GamepadButton(B, "B")
GamepadButton(X, "X")
GamepadButton(Y, "Y")

75
source/os_key_list.inc Normal file
View File

@ -0,0 +1,75 @@
Key(Null, "Invalid Key")
Key(Esc, "Escape")
Key(F1, "F1")
Key(F2, "F2")
Key(F3, "F3")
Key(F4, "F4")
Key(F5, "F5")
Key(F6, "F6")
Key(F7, "F7")
Key(F8, "F8")
Key(F9, "F9")
Key(F10, "F10")
Key(F11, "F11")
Key(F12, "F12")
Key(GraveAccent, "Grave Accent")
Key(0, "0")
Key(1, "1")
Key(2, "2")
Key(3, "3")
Key(4, "4")
Key(5, "5")
Key(6, "6")
Key(7, "7")
Key(8, "8")
Key(9, "9")
Key(Minus, "Minus")
Key(Equal, "Equal")
Key(Backspace, "Backspace")
Key(Delete, "Delete")
Key(Tab, "Tab")
Key(A, "A")
Key(B, "B")
Key(C, "C")
Key(D, "D")
Key(E, "E")
Key(F, "F")
Key(G, "G")
Key(H, "H")
Key(I, "I")
Key(J, "J")
Key(K, "K")
Key(L, "L")
Key(M, "M")
Key(N, "N")
Key(O, "O")
Key(P, "P")
Key(Q, "Q")
Key(R, "R")
Key(S, "S")
Key(T, "T")
Key(U, "U")
Key(V, "V")
Key(W, "W")
Key(X, "X")
Key(Y, "Y")
Key(Z, "Z")
Key(Space, "Space")
Key(Enter, "Enter")
Key(Ctrl, "Ctrl")
Key(Shift, "Shift")
Key(Alt, "Alt")
Key(Up, "Up")
Key(Left, "Left")
Key(Down, "Down")
Key(Right, "Right")
Key(PageUp, "Page Up")
Key(PageDown, "Page Down")
Key(Home, "Home")
Key(End, "End")
Key(ForwardSlash, "Forward Slash")
Key(Period, "Period")
Key(Comma, "Comma")
Key(Quote, "Quote")
Key(LeftBracket, "Left Bracket")
Key(RightBracket, "Right Bracket")

4
source/program_options.h Normal file
View File

@ -0,0 +1,4 @@
#define WINDOW_TITLE "Splink!"
#define PROGRAM_FILENAME "app"
#define DEFAULT_WINDOW_WIDTH 1280
#define DEFAULT_WINDOW_HEIGHT 720

695
source/render.c Normal file
View File

@ -0,0 +1,695 @@
// NOTE(allen): Changes durring this jam
// added R_StringBaselineCapped
// added R_StringCapped
// changed R_SetClip
// changed R_Begin
// added R_GetClip
// added R_PushClip
////////////////////////////////
// NOTE(allen): Internal types
typedef struct R_GL_Vertex R_GL_Vertex;
struct R_GL_Vertex
{
v2 xy;
v3 uvw;
v4 rgba;
};
typedef struct R_GL_State R_GL_State;
struct R_GL_State
{
v2 render_resolution;
GLuint vertex_buffer;
R_GL_Vertex *vertex_memory;
u64 vertex_count;
u64 vertex_max;
R_Font *selected_font;
u32 selected_font_texture;
Rect clip;
};
typedef struct R_GL_Bind R_GL_Bind;
struct R_GL_Bind
{
char *name;
b32 is_uniform;
u32 size;
GLint v;
u32 offset;
u32 total_size;
};
////////////////////////////////
// NOTE(allen): Shader
global char shader_header[] = "#version 330\n";
global char shader_vertex_mono_texture[] =
"in vec2 vert_xy;\n"
"in vec3 vert_uvw;\n"
"in vec4 vert_c;\n"
"out vec3 frag_uvw;\n"
"out vec4 frag_c;\n"
"uniform vec2 inv_half_dim;\n"
"void main()\n"
"{\n"
" gl_Position.x = (vert_xy.x*inv_half_dim.x) - 1;\n"
" gl_Position.y = 1 - (vert_xy.y*inv_half_dim.y);\n"
" gl_Position.z = 0;\n"
" gl_Position.w = 1;\n"
" frag_uvw = vert_uvw;\n"
" frag_c = vert_c;\n"
"}\n"
;
global char shader_fragment_mono_texture[] =
"in vec3 frag_uvw;\n"
"in vec4 frag_c;\n"
"out vec4 out_c;\n"
"uniform sampler2DArray tex;\n"
"void main()\n"
"{\n"
" float v = texture(tex, frag_uvw).r;\n"
" out_c = vec4(frag_c.rgb, frag_c.a*v);\n"
"}\n"
;
#define R_GL_Bind_Members(N,u,off) R_GL_Bind N;
#define R_GL_Bind_Values(N,u,off) {#N,u,off},
#define R_GL_Mono_Texture_Binds(X)\
X(vert_xy , 0, 2)\
X(vert_uvw, 0, 3)\
X(vert_c , 0, 4)\
X(inv_half_dim, 1, 0)\
X(tex , 1, 0)
typedef struct R_GL_Mono_Texture R_GL_Mono_Texture;
struct R_GL_Mono_Texture
{
R_GL_Mono_Texture_Binds(R_GL_Bind_Members)
};
global R_GL_Mono_Texture r_gl_mono_texture = {
R_GL_Mono_Texture_Binds(R_GL_Bind_Values)
};
////////////////////////////////
// NOTE(allen): Main frame setup
global R_GL_State *global_render = 0;
internal GLuint
_R_CompilerShader(GLenum shader_kind, char *source)
{
GLuint shader = glCreateShader(shader_kind);
GLchar *sources[] = {shader_header, source};
glShaderSource(shader, 2, sources, 0);
glCompileShader(shader);
i32 log_length = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
char error[1024] = {0};
log_length = ClampTop(log_length, sizeof(error));
glGetShaderInfoLog(shader, log_length, 0, error);
Assert(log_length == 0);
return(shader);
}
internal void
R_Init(M_Arena *arena)
{
global_render = PushArrayZero(arena, R_GL_State, 1);
LoadAllOpenGLProcedures();
glEnable(GL_SCISSOR_TEST);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// NOTE(allen): vertex array
GLint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// NOTE(allen): shader
GLuint vertex_shader = _R_CompilerShader(GL_VERTEX_SHADER , shader_vertex_mono_texture );
GLuint fragment_shader = _R_CompilerShader(GL_FRAGMENT_SHADER, shader_fragment_mono_texture);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
i32 log_length = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
char error[1024] = {0};
log_length = ClampTop(log_length, sizeof(error));
glGetProgramInfoLog(program, log_length, 0, error);
Assert(log_length == 0);
{
u64 bind_count = sizeof(r_gl_mono_texture)/sizeof(R_GL_Bind);
R_GL_Bind *binds = (R_GL_Bind*)&r_gl_mono_texture;
u32 total_size = 0;
R_GL_Bind *bind = binds;
for (u64 i = 0; i < bind_count; i += 1, bind += 1)
{
if (!bind->is_uniform)
{
total_size += bind->size*sizeof(f32);
}
}
u64 offset = 0;
bind = binds;
for (u64 i = 0; i < bind_count; i += 1, bind += 1)
{
if (bind->is_uniform)
{
bind->v = glGetUniformLocation(program, bind->name);
}
else
{
bind->v = glGetAttribLocation(program, bind->name);
bind->offset = offset;
bind->total_size = total_size;
offset += bind->size*sizeof(f32);
}
}
}
glUseProgram(program);
glUniform1i(r_gl_mono_texture.tex.v, 0);
// NOTE(allen): vertex buffer
glGenBuffers(1, &global_render->vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, global_render->vertex_buffer);
// NOTE(allen): increase this number for bigger batches; keep multiple of 3
global_render->vertex_max = 4095;
global_render->vertex_memory = PushArray(arena, R_GL_Vertex, global_render->vertex_max);
glBufferData(GL_ARRAY_BUFFER, global_render->vertex_max*sizeof(R_GL_Vertex), 0, GL_DYNAMIC_DRAW);
// NOTE(allen): vertex attributes
{
u64 bind_count = sizeof(r_gl_mono_texture)/sizeof(R_GL_Bind);
R_GL_Bind *bind = (R_GL_Bind*)&r_gl_mono_texture;
for (u64 i = 0; i < bind_count; i += 1, bind += 1)
{
if (!bind->is_uniform)
{
glEnableVertexAttribArray(bind->v);
glVertexAttribPointer(bind->v, bind->size, GL_FLOAT, GL_FALSE, bind->total_size, PtrFromInt(bind->offset));
}
}
}
// NOTE(allen): setup texture download alignment
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// NOTE(allen): select null font
global_render->selected_font = 0;
global_render->selected_font_texture = 0;
}
internal void
_R_Flush(void)
{
if (global_render->vertex_count > 0)
{
glBufferSubData(GL_ARRAY_BUFFER, 0, global_render->vertex_count*sizeof(R_GL_Vertex), global_render->vertex_memory);
glDrawArrays(GL_TRIANGLES, 0, global_render->vertex_count);
global_render->vertex_count = 0;
}
}
internal R_GL_Vertex*
_R_AllocVertices(u64 count)
{
Assert(count <= global_render->vertex_max);
if (global_render->vertex_count + count > global_render->vertex_max)
{
_R_Flush();
}
R_GL_Vertex *result = global_render->vertex_memory + global_render->vertex_count;
global_render->vertex_count += count;
return(result);
}
internal void
R_Begin(v2 render_size, v3 color)
{
global_render->render_resolution = render_size;
R_SetClip(MakeRect(0.f, 0.f, V2Expand(render_size)));
glViewport(0, 0, render_size.x, render_size.y);
glClearColor(color.r, color.g, color.b, 1);
glClear(GL_COLOR_BUFFER_BIT);
glUniform2f(r_gl_mono_texture.inv_half_dim.v, 2.f/render_size.x, 2.f/render_size.y);
}
internal void
R_End(void)
{
_R_Flush();
os->RefreshScreen();
}
internal Rect
R_GetClip(void)
{
return(global_render->clip);
}
internal Rect
R_SetClip(Rect rect)
{
_R_Flush();
glScissor((GLint)rect.x0, (GLint)(global_render->render_resolution.y - rect.y1),
(GLint)(rect.x1 - rect.x0), (GLint)(rect.y1 - rect.y0));
Rect result = global_render->clip;
global_render->clip = rect;
return(result);
}
internal Rect
R_PushClip(Rect rect)
{
Rect intersected = RectIntersect(rect, global_render->clip);
Rect result = R_SetClip(intersected);
return(result);
}
////////////////////////////////
// NOTE(allen): Font
#define STB_TRUETYPE_IMPLEMENTATION
#include "ext/stb_truetype.h"
internal void
_R_TextureArraySetDataSlice(u32 index, u8 *data, u32 width, u32 height)
{
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0,
0, 0, index,
width, height, 1,
GL_RED, GL_UNSIGNED_BYTE, data);
}
internal void
_R_BaseInitFont(R_Font *font)
{
// NOTE(allen): init
font->initialized = 1;
MemoryZeroArray(font->glyph);
MemoryZeroArray(font->advance);
// NOTE(allen): font metrics
font->top_to_baseline = 0.f;
font->baseline_to_next_top = 0.f;
// NOTE(allen): setup texture
glGenTextures(1, &font->var[0]);
glBindTexture(GL_TEXTURE_2D_ARRAY, font->var[0]);
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_R8, 32, 64, 128, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 3);
// NOTE(allen): full white at slice 0
local_persist u8 temp_buffer[32*64] = {0};
if (temp_buffer[0] == 0)
{
MemorySet(temp_buffer, 0xFF, sizeof(temp_buffer));
}
_R_TextureArraySetDataSlice(0, temp_buffer, 32, 64);
}
internal void
R_InitUserFont(R_Font *font)
{
_R_BaseInitFont(font);
glBindTexture(GL_TEXTURE_2D_ARRAY, global_render->selected_font_texture);
}
internal void
R_ReleaseFont(R_Font *font)
{
font->initialized = 0;
glDeleteTextures(1, &font->var[0]);
if (global_render->selected_font == font)
{
global_render->selected_font = 0;
global_render->selected_font_texture = 0;
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
}
}
internal void
R_InitFont(R_Font *font, String8 ttf_path, i32 size)
{
font->initialized = 0;
M_Arena *scratch = OS_GetScratch();
void *data = 0;
u64 data_len = 0;
os->LoadEntireFile(scratch, ttf_path, &data, &data_len);
if (data_len > 0)
{
stbtt_fontinfo stb_font;
if (stbtt_InitFont(&stb_font, data, stbtt_GetFontOffsetForIndex(data, 0)))
{
// NOTE(allen): init
_R_BaseInitFont(font);
// NOTE(allen): font metrics
f32 scale = stbtt_ScaleForPixelHeight(&stb_font, size);
f32 em_scale = stbtt_ScaleForMappingEmToPixels(&stb_font, size);
i32 ascent;
i32 descent;
i32 gap;
stbtt_GetFontVMetrics(&stb_font, &ascent, &descent, &gap);
font->top_to_baseline = ascent*em_scale;
font->baseline_to_next_top = (gap - descent)*em_scale;
// NOTE(allen): characters between [32,126]
{
R_Glyph_Box *glyph_ptr = font->glyph + 32;
f32 *advance_ptr = font->advance + 32;
for (u32 i = 32; i <= 126; i += 1, advance_ptr += 1, glyph_ptr += 1)
{
i32 w;
i32 h;
i32 xoff;
i32 yoff;
u8 *bitmap = stbtt_GetCodepointBitmap(&stb_font, 0, scale, i, &w, &h, &xoff, &yoff);
Assert(w <= 32);
Assert(h <= 64);
_R_TextureArraySetDataSlice(i, bitmap, w, h);
stbtt_FreeBitmap(bitmap, 0);
i32 advance;
i32 lsb;
stbtt_GetCodepointHMetrics(&stb_font, i, &advance, &lsb);
glyph_ptr->offset.x = xoff;
glyph_ptr->offset.y = yoff;
glyph_ptr->dim.x = w;
glyph_ptr->dim.y = h;
*advance_ptr = advance*em_scale;
}
}
// NOTE(allen): update mipmaps
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
glBindTexture(GL_TEXTURE_2D_ARRAY, global_render->selected_font_texture);
}
}
OS_ReleaseScratch(scratch);
}
internal b32
R_FontSetSlot(R_Font *font, u32 indx, u8 *bitmap, u32 width, u32 height,
u32 xoff, u32 yoff, f32 advance)
{
b32 result = 0;
if (font->initialized)
{
if (0 < indx && indx <= 0x7F)
{
if (width <= 32 && height <= 64)
{
glBindTexture(GL_TEXTURE_2D_ARRAY, font->var[0]);
_R_TextureArraySetDataSlice(indx, bitmap, width, height);
font->glyph[indx].offset.x = xoff;
font->glyph[indx].offset.y = yoff;
font->glyph[indx].dim.x = width;
font->glyph[indx].dim.y = height;
font->advance[indx] = advance;
glBindTexture(GL_TEXTURE_2D_ARRAY, global_render->selected_font_texture);
}
}
}
return(result);
}
internal void
R_FontUpdateMipmaps(R_Font *font)
{
if (font != global_render->selected_font)
{
glBindTexture(GL_TEXTURE_2D_ARRAY, font->var[0]);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
glBindTexture(GL_TEXTURE_2D_ARRAY, global_render->selected_font_texture);
}
else
{
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
}
}
internal void
R_SelectFont(R_Font *font)
{
if (global_render->selected_font != font)
{
_R_Flush();
global_render->selected_font = font;
global_render->selected_font_texture = font->var[0];
glBindTexture(GL_TEXTURE_2D_ARRAY, global_render->selected_font_texture);
}
}
internal v2
R_StringDimWithFont(R_Font *font, f32 scale, String8 string)
{
v2 result = {0};
u8 *ptr = string.str;
u8 *end = ptr + string.size;
f32 *advances = font->advance;
for (;ptr < end; ptr += 1)
{
if (*ptr <= 0x7F)
{
result.x += f32Ceil(advances[*ptr]*scale);
}
}
result.y = f32Ceil((font->top_to_baseline + font->baseline_to_next_top)*scale);
return(result);
}
internal v2
R_StringDim(f32 scale, String8 string)
{
return(R_StringDimWithFont(global_render->selected_font, scale, string));
}
////////////////////////////////
// NOTE(allen): Draw
#define DupVert(n) vertices[n].xy = vertices[n - 2].xy
#define DupVertUVW(n) vertices[n].uvw = vertices[n - 2].uvw
#define DupVertC(n) vertices[n].c = vertices[n - 2].c
internal void
R_Rect(Rect rect, v3 color, f32 a)
{
R_GL_Vertex *vertices = _R_AllocVertices(6);
vertices[0].xy = rect.p0;
vertices[1].xy = v2(rect.x1, rect.y0);
vertices[2].xy = v2(rect.x0, rect.y1);
DupVert(3); DupVert(4);
vertices[5].xy = rect.p1;
R_GL_Vertex *v = vertices;
for (u64 i = 0; i < 6; i += 1, v += 1)
{
v->uvw = v3(0.f, 0.f, 0.f);
v->rgba = v4(color.r, color.g, color.b, a);
}
}
internal void
R_RectOutline(Rect rect, f32 thickness, v3 color, f32 a)
{
Rect outer = rect;
Rect inner = RectShrink(rect, thickness);
R_GL_Vertex *vertices = _R_AllocVertices(24);
vertices[0].xy = v2(outer.x0, outer.y0);
vertices[1].xy = v2(inner.x0, inner.y0);
vertices[2].xy = v2(outer.x1, outer.y0);
DupVert(3); DupVert(4);
vertices[5].xy = v2(inner.x1, inner.y0);
DupVert(6); DupVert(7);
vertices[8].xy = v2(outer.x1, outer.y1);
DupVert(9); DupVert(10);
vertices[11].xy = v2(inner.x1, inner.y1);
DupVert(12); DupVert(13);
vertices[14].xy = v2(outer.x0, outer.y1);
DupVert(15); DupVert(16);
vertices[17].xy = v2(inner.x0, inner.y1);
DupVert(18); DupVert(19);
vertices[20].xy = v2(outer.x0, outer.y0);
DupVert(21); DupVert(22);
vertices[23].xy = v2(inner.x0, inner.y0);
R_GL_Vertex *v = vertices;
for (u64 i = 0; i < 24; i += 1, v += 1)
{
v->uvw = v3(0.f, 0.f, 0.f);
v->rgba = v4(color.r, color.g, color.b, a);
}
}
internal v2
R_StringBaselineCapped(v2 p, f32 max_x, f32 scale, String8 string, v3 color, f32 a)
{
v2 result = {0};
R_Font *font = global_render->selected_font;
if (font != 0 && font->initialized)
{
f32 *advances = font->advance;
u8 tail[3] = {'.', '.', '.', };
f32 x_tail = f32Ceil(advances['.']*scale)*3.f;
b32 string_will_fit = 0;
f32 x = p.x;
if (x + x_tail <= max_x){
u8 *ptr = string.str;
u8 *end = ptr + string.size;
R_Glyph_Box *glyphs = font->glyph;
for (;ptr < end; ptr += 1)
{
top:
if (*ptr <= 0x7F)
{
f32 next_x = x + f32Ceil(advances[*ptr]*scale);
// NOTE(allen): If the tail isn't going to fit after this
// we look ahead to see if the string fits. If not we switch
// to the tail now.
if (next_x + x_tail > max_x && !string_will_fit){
u8 *look_ahead_ptr = ptr + 1;
f32 look_ahead_x = next_x;
for (;look_ahead_ptr < end; look_ahead_ptr += 1){
look_ahead_x += f32Ceil(advances[*ptr]*scale);
if (look_ahead_x > max_x){
break;
}
}
if (look_ahead_x > max_x){
ptr = tail;
end = ptr + 3;
goto top;
}
string_will_fit = 1;
}
R_Glyph_Box *g = &glyphs[*ptr];
Rect rect;
rect.x0 = x + g->offset.x*scale;
rect.y0 = p.y + g->offset.y*scale;
rect.x1 = rect.x0 + g->dim.x*scale;
rect.y1 = rect.y0 + g->dim.y*scale;
v2 uv;
uv.x = g->dim.x*(1.f/32.f);
uv.y = g->dim.y*(1.f/64.f);
f32 w = (*ptr);
R_GL_Vertex *vertices = _R_AllocVertices(6);
vertices[0].xy = rect.p0;
vertices[0].uvw = v3(0.f, 0.f, w);
vertices[1].xy = v2(rect.x1, rect.y0);
vertices[1].uvw = v3(uv.x, 0.f, w);
vertices[2].xy = v2(rect.x0, rect.y1);
vertices[2].uvw = v3(0.f, uv.y, w);
DupVert(3); DupVertUVW(3);
DupVert(4); DupVertUVW(4);
vertices[5].xy = rect.p1;
vertices[5].uvw = v3(uv.x, uv.y, w);
R_GL_Vertex *v = vertices;
for (u64 i = 0; i < 6; i += 1, v += 1)
{
v->rgba = v4(color.r, color.g, color.b, a);
}
x = next_x;
}
}
}
result.x = x - p.x;
result.y = f32Ceil((font->top_to_baseline + font->baseline_to_next_top)*scale);
}
return(result);
}
internal v2
R_StringCapped(v2 p, f32 max_x, f32 scale, String8 string, v3 color, f32 a)
{
v2 result = {0};
R_Font *font = global_render->selected_font;
if (font != 0 && font->initialized)
{
p.y += font->top_to_baseline*scale;
result = R_StringBaselineCapped(p, max_x, scale, string, color, a);
}
return(result);
}
internal v2
R_StringBaseline(v2 p, f32 scale, String8 string, v3 color, f32 a)
{
return(R_StringBaselineCapped(p, Inf32(), scale, string, color, a));
}
internal v2
R_String(v2 p, f32 scale, String8 string, v3 color, f32 a)
{
return(R_StringCapped(p, Inf32(), scale, string, color, a));
}

125
source/render.h Normal file
View File

@ -0,0 +1,125 @@
// NOTE(allen): Changes durring this jam
// added R_StringCapped
// added R_StringBaselineCapped
// changed R_SetClip
// added R_PushClip
// added R_GetClip
/* date = July 2nd 2020 9:58 pm */
#ifndef RENDER_H
#define RENDER_H
typedef struct R_Glyph_Box R_Glyph_Box;
struct R_Glyph_Box
{
v2 offset;
v2 dim;
};
typedef struct R_Font R_Font;
struct R_Font
{
b32 initialized;
u32 var[1];
f32 top_to_baseline;
f32 baseline_to_next_top;
R_Glyph_Box glyph[128];
f32 advance[128];
};
#define R_SP_0 "\x01"
#define R_SP_1 "\x02"
#define R_SP_2 "\x03"
#define R_SP_3 "\x04"
#define R_SP_4 "\x05"
#define R_SP_5 "\x06"
#define R_SP_6 "\x07"
#define R_SP_7 "\x08"
#define R_SP_8 "\x09"
#define R_SP_9 "\x0A"
#define R_SP_10 "\x0B"
#define R_SP_11 "\x0C"
#define R_SP_12 "\x0D"
#define R_SP_13 "\x0E"
#define R_SP_14 "\x0F"
#define R_SP_15 "\x10"
#define R_SP_16 "\x11"
#define R_SP_17 "\x12"
#define R_SP_18 "\x13"
#define R_SP_19 "\x14"
#define R_SP_20 "\x15"
#define R_SP_21 "\x16"
#define R_SP_22 "\x17"
#define R_SP_23 "\x18"
#define R_SP_24 "\x19"
#define R_SP_25 "\x1A"
#define R_SP_26 "\x1B"
#define R_SP_27 "\x1C"
#define R_SP_28 "\x1D"
#define R_SP_29 "\x1E"
#define R_SP_30 "\x1F"
#define R_SP_31 "\x7F"
#define R_SP_INDX_0 0x01
#define R_SP_INDX_1 0x02
#define R_SP_INDX_2 0x03
#define R_SP_INDX_3 0x04
#define R_SP_INDX_4 0x05
#define R_SP_INDX_5 0x06
#define R_SP_INDX_6 0x07
#define R_SP_INDX_7 0x08
#define R_SP_INDX_8 0x09
#define R_SP_INDX_9 0x0A
#define R_SP_INDX_10 0x0B
#define R_SP_INDX_11 0x0C
#define R_SP_INDX_12 0x0D
#define R_SP_INDX_13 0x0E
#define R_SP_INDX_14 0x0F
#define R_SP_INDX_15 0x10
#define R_SP_INDX_16 0x11
#define R_SP_INDX_17 0x12
#define R_SP_INDX_18 0x13
#define R_SP_INDX_19 0x14
#define R_SP_INDX_20 0x15
#define R_SP_INDX_21 0x16
#define R_SP_INDX_22 0x17
#define R_SP_INDX_23 0x18
#define R_SP_INDX_24 0x19
#define R_SP_INDX_25 0x1A
#define R_SP_INDX_26 0x1B
#define R_SP_INDX_27 0x1C
#define R_SP_INDX_28 0x1D
#define R_SP_INDX_29 0x1E
#define R_SP_INDX_30 0x1F
#define R_SP_INDX_31 0x7F
////////////////////////////////
internal void R_Init(M_Arena *arena);
internal void R_Begin(v2 render_size, v3 color);
internal void R_End(void);
internal Rect R_GetClip(void);
internal Rect R_SetClip(Rect rect);
internal Rect R_PushClip(Rect rect);
internal void R_InitFont(R_Font *font, String8 ttf_path, i32 size);
internal void R_InitUserFont(R_Font *font);
internal void R_ReleaseFont(R_Font *font);
internal b32 R_FontSetSlot(R_Font *font, u32 indx, u8 *bitmap, u32 width, u32 height,
u32 xoff, u32 yoff, f32 advance);
internal void R_FontUpdateMipmaps(R_Font *font);
internal v2 R_StringDim(f32 scale, String8 string);
internal v2 R_StringDimWithFont(R_Font *font, f32 scale, String8 string);
internal void R_Rect(Rect rect, v3 color, f32 a);
internal void R_RectOutline(Rect rect, f32 thickness, v3 color, f32 a);
internal void R_SelectFont(R_Font *font);
internal v2 R_String(v2 p, f32 scale, String8 string, v3 color, f32 a);
internal v2 R_StringBaseline(v2 p, f32 scale, String8 string, v3 color, f32 a);
internal v2 R_StringCapped(v2 p, f32 max_x, f32 scale, String8 string, v3 color, f32 a);
internal v2 R_StringBaselineCapped(v2 p, f32 max_x, f32 scale, String8 string, v3 color, f32 a);
#endif //RENDER_H

101
source/string_hash.c Normal file
View File

@ -0,0 +1,101 @@
////////////////////////////////
// NOTE(allen): Implementation
internal STR_Hash
STR_InitHash(void){
STR_Hash hash = {0};
hash.arena_ptrs = M_ArenaInitialize();
hash.arena_strs = M_ArenaInitializeWithAlign(1);
hash.str_ptrs = PushArray(&hash.arena_ptrs, String8, 1);
hash.str_count = 1;
hash.str_ptrs[0] = S8Lit("");
return(hash);
}
internal STR_Index
STR_Save(STR_Hash *hash, String8 string){
u32 count = hash->str_count;
STR_Index result = count;
String8 *str_ptr = hash->str_ptrs;
for (u32 i = 0; i < count; i += 1, str_ptr += 1){
if (StringMatch(*str_ptr, string)){
result = i;
break;
}
}
if (result == count){
String8 *new_str = PushArray(&hash->arena_ptrs, String8, 1);
new_str->str = PushArray(&hash->arena_strs, u8, string.size);
new_str->size = string.size;
MemoryCopy(new_str->str, string.str, string.size);
hash->str_count += 1;
}
return(result);
}
internal String8
STR_Read(STR_Hash *hash, STR_Index index){
String8 result = {0};
if (index < hash->str_count){
result = hash->str_ptrs[index];
}
return(result);
}
internal String8
STR_NameFromPath(String8 path){
String8 result = path;
if (path.size > 0){
u8 *first = path.str;
u8 *last = path.str + path.size - 1;
u8 *ptr = last;
for (;ptr >= first; ptr -= 1){
if (*ptr == '/' || *ptr == '\\'){
break;
}
}
if (ptr < last){
result = S8Range(ptr + 1, last + 1);
}
}
return(result);
}
internal String8
STR_NameWithoutExtension(String8 path){
String8 result = path;
if (path.size > 0){
u8 *first = path.str;
u8 *ptr = path.str + path.size - 1;
for (;ptr >= first; ptr -= 1){
if (*ptr == '.'){
break;
}
}
if (ptr > first){
result = S8Range(first, ptr);
}
}
return(result);
}
////////////////////////////////
// NOTE(allen): Test
internal void
_STR_Test(void){
STR_Hash hash = STR_InitHash();
STR_Index a = STR_Save(&hash, S8Lit("Foo"));
STR_Index b = STR_Save(&hash, S8Lit("Bar"));
STR_Index c = STR_Save(&hash, S8Lit("Jim"));
STR_Index d = STR_Save(&hash, S8Lit("Jams"));
Assert(STR_Save(&hash, S8Lit("Foo")) == a);
Assert(STR_Save(&hash, S8Lit("Bar")) == b);
Assert(STR_Save(&hash, S8Lit("Jim")) == c);
Assert(STR_Save(&hash, S8Lit("Jams")) == d);
Assert(StringMatch(STR_Read(&hash, a), S8Lit("Foo")));
Assert(StringMatch(STR_Read(&hash, b), S8Lit("Bar")));
Assert(StringMatch(STR_Read(&hash, c), S8Lit("Jim")));
Assert(StringMatch(STR_Read(&hash, d), S8Lit("Jams")));
}

22
source/string_hash.h Normal file
View File

@ -0,0 +1,22 @@
/* date = July 6th 2020 6:18 am */
#ifndef STRING_HASH_H
#define STRING_HASH_H
typedef u32 STR_Index;
typedef struct STR_Hash STR_Hash;
struct STR_Hash{
M_Arena arena_ptrs;
M_Arena arena_strs;
String8 *str_ptrs;
u32 str_count;
};
////////////////////////////////
internal STR_Hash STR_InitHash(void);
internal STR_Index STR_Save(STR_Hash *hash, String8 string);
internal String8 STR_Read(STR_Hash *hash, STR_Index index);
#endif //STRING_HASH_H

1586
source/token_buffer.c Normal file

File diff suppressed because it is too large Load Diff

114
source/token_buffer.h Normal file
View File

@ -0,0 +1,114 @@
/* date = July 6th 2020 6:35 am */
#ifndef TOKEN_BUFFER_H
#define TOKEN_BUFFER_H
typedef struct E_TokenBuffer E_TokenBuffer;
struct E_TokenBuffer{
M_Arena arena;
C_Token *tokens;
u64 count;
u64 max;
b32 dirty;
b32 text_field_mode;
};
typedef u32 E_RuneKind;
enum{
E_RuneKind_Error,
E_RuneKind_Space,
E_RuneKind_LineStart,
E_RuneKind_Symbol,
E_RuneKind_Label,
E_RuneKind_Comment,
};
typedef struct E_Rune E_Rune;
struct E_Rune{
u64 cursor_pos;
E_Rune *next;
E_Rune *prev;
String8 string;
Rect rect;
v4 color;
E_RuneKind kind;
f32 text_scale;
};
typedef struct E_RuneLayout E_RuneLayout;
struct E_RuneLayout{
E_Rune *vals;
u64 count;
E_Rune *first_line;
E_Rune *last_line;
E_Rune *first_error;
E_Rune *last_error;
v2 dim;
};
typedef struct E_LayoutIndent E_LayoutIndent;
struct E_LayoutIndent{
E_LayoutIndent *next;
f32 pre_indent;
f32 post_indent;
};
typedef struct E_LayoutCtx E_LayoutCtx;
struct E_LayoutCtx{
// NOTE(allen): state
M_Arena *arena;
M_Arena *temp_arena;
E_RuneLayout *layout;
u64 cursor_pos;
v2 p;
E_LayoutIndent *free_indent;
E_LayoutIndent *indent;
// NOTE(allen): settings
R_Font *font;
f32 text_scale;
f32 initial_padding;
v2 space_dim;
v4 cl_whitespace;
v4 cl_error;
};
typedef struct E_Cursor E_Cursor;
struct E_Cursor{
u64 pos;
u64 sub_pos;
};
typedef enum
{
E_RangeKind_SingleTokenTextRange,
E_RangeKind_MultiTokenRange,
} E_RangeKind;
typedef struct E_Range E_Range;
struct E_Range
{
E_RangeKind kind;
Rangeu range;
u64 token;
};
typedef enum{
E_EditorFieldMode_None,
E_EditorFieldMode_AnyString,
E_EditorFieldMode_CodeIdentifier,
} E_EditorFieldMode;
typedef struct E_EditorState E_EditorState;
struct E_EditorState{
E_TokenBuffer *buffer;
R_Font *font;
E_RuneLayout runes;
E_Cursor cursor;
E_Cursor mark;
f32 preferred_x;
E_EditorFieldMode text_field_mode;
};
#endif //TOKEN_BUFFER_H

872
source/ui.c Normal file
View File

@ -0,0 +1,872 @@
////////////////////////////////
// NOTE(allen): Colors
global v3 cl_black = {0.f, 0.f, 0.f};
global v3 cl_white = {1.f, 1.f, 1.f};
#define cl_gray(f) v3((f), (f), (f))
global v3 cl_red = {1.f, 0.f, 0.f};
global v3 cl_yellow = {1.f, 1.f, 0.f};
global v3 cl_green = {0.f, 1.f, 0.f};
global v3 cl_cyan = {0.f, 1.f, 1.f};
global v3 cl_blue = {0.f, 0.f, 1.f};
global v3 cl_awful = {1.f, 0.f, 1.f};
////////////////////////////////
global v3 cl_back_editor = {0.15f, 0.15f, 0.15f};
global v3 cl_back_unimportant = {0.00f, 0.00f, 0.00f};
global v3 cl_back = {0.21f, 0.21f, 0.21f};
global v3 cl_back_flash = {0.50f, 0.50f, 0.50f};
global v3 cl_outline_unimportant = {0.15f, 0.30f, 0.15f};
global v3 cl_outline_important = {0.09f, 0.50f, 0.09f};
global v3 cl_outline = {0.00f, 0.70f, 0.00f};
global v3 cl_outline_flash = {0.50f, 0.85f, 0.50f};
global v3 cl_button_text = {1.f, 1.f, 0.8f};
global v3 cl_button_text_flash = {0.f, 0.f, 0.2f};
global v3 cl_tab_outline_unimportant = {0.15f, 0.15f, 0.15f};
global v3 cl_tab_outline = {0.50f, 0.50f, 0.50f};
global v3 cl_err_back_unimportant = {0.100f, 0.00f, 0.00f};
global v3 cl_err_back = {0.299f, 0.21f, 0.21};
global v3 cl_err_back_flash = {0.550f, 0.50f, 0.50f};
global v3 cl_err_outline_unimportant = {0.30f, 0.195f, 0.15f};
global v3 cl_err_outline_important = {0.50f, 0.213f, 0.09f};
global v3 cl_err_outline = {0.70f, 0.210f, 0.00f};
global v3 cl_err_outline_flash = {0.85f, 0.605f, 0.50f};
global v3 cl_page_back_unimportant = {0.100f, 0.000f, 0.00f};
global v3 cl_page_back = {0.299f, 0.299f, 0.21f};
global v3 cl_page_back_flash = {0.550f, 0.550f, 0.50f};
global v3 cl_page_outline_unimportant = {0.30f, 0.30f, 0.15f};
global v3 cl_page_outline_important = {0.50f, 0.50f, 0.09f};
global v3 cl_page_outline = {0.70f, 0.70f, 0.00f};
global v3 cl_page_outline_flash = {0.85f, 0.85f, 0.50f};
global v3 cl_test_back_unimportant = {0.050f, 0.000f, 0.050f};
global v3 cl_test_back = {0.150f, 0.105f, 0.150f};
global v3 cl_test_back_flash = {0.275f, 0.250f, 0.275f};
global v3 cl_test_outline_unimportant = {0.200f, 0.130f, 0.200f};
global v3 cl_test_outline_important = {0.250f, 0.106f, 0.250f};
global v3 cl_test_outline = {0.350f, 0.105f, 0.350f};
global v3 cl_test_outline_flash = {0.425f, 0.303f, 0.425f};
global v3 cl_menu_bar = {0.70f, 0.70f, 0.70f};
global v3 cl_error = {1.00f, 0.00f, 0.00f};
global v3 cl_text = {1.00f, 1.00f, 1.00f};
global v3 cl_comment = {0.50f, 0.50f, 0.65f};
global v3 cl_keyword = {0.95f, 0.99f, 0.50f};
////////////////////////////////
internal UI_ColorProfile*
UI_ColorsDefault(void){
local_persist UI_ColorProfile result = {0};
local_persist b32 first = 1;
if (first){
first = 0;
result.back[0] = cl_back_unimportant;
result.back[1] = cl_back;
result.back[2] = cl_back;
result.back[3] = cl_back_flash;
result.outline[0] = cl_outline_unimportant;
result.outline[1] = cl_outline_important;
result.outline[2] = cl_outline;
result.outline[3] = cl_outline_flash;
result.front[0] = cl_button_text;
result.front[1] = cl_button_text;
result.front[2] = cl_button_text;
result.front[3] = cl_button_text_flash;
}
return(&result);
}
internal UI_ColorProfile*
UI_ColorsProblem(void){
local_persist UI_ColorProfile result = {0};
local_persist b32 first = 1;
if (first){
first = 0;
result.back[0] = cl_err_back_unimportant;
result.back[1] = cl_err_back;
result.back[2] = cl_err_back;
result.back[3] = cl_err_back_flash;
result.outline[0] = cl_err_outline_unimportant;
result.outline[1] = cl_err_outline_important;
result.outline[2] = cl_err_outline;
result.outline[3] = cl_err_outline_flash;
result.front[0] = cl_button_text;
result.front[1] = cl_button_text;
result.front[2] = cl_button_text;
result.front[3] = cl_button_text_flash;
}
return(&result);
}
internal UI_ColorProfile*
UI_ColorsTabs(void){
local_persist UI_ColorProfile result = {0};
local_persist b32 first = 1;
if (first){
first = 0;
result.back[0] = cl_back_unimportant;
result.back[1] = cl_back_editor;
result.back[2] = cl_back;
result.back[3] = cl_back;
result.outline[0] = cl_tab_outline_unimportant;
result.outline[1] = cl_back_editor;
result.outline[2] = cl_tab_outline;
result.outline[3] = cl_tab_outline;
for (u64 i = 0; i < (u64)UI_ActionLevel_COUNT; i += 1){
result.front[i] = cl_button_text;
}
}
return(&result);
}
internal UI_ColorProfile*
UI_ColorsPage(void){
local_persist UI_ColorProfile result = {0};
local_persist b32 first = 1;
if (first){
first = 0;
result.back[0] = cl_page_back_unimportant;
result.back[1] = cl_page_back;
result.back[2] = cl_page_back;
result.back[3] = cl_page_back_flash;
result.outline[0] = cl_page_outline_unimportant;
result.outline[1] = cl_page_outline_important;
result.outline[2] = cl_page_outline;
result.outline[3] = cl_page_outline_flash;
result.front[0] = cl_button_text;
result.front[1] = cl_button_text;
result.front[2] = cl_button_text;
result.front[3] = cl_button_text_flash;
}
return(&result);
}
internal UI_ColorProfile*
UI_ColorsTest(void){
local_persist UI_ColorProfile result = {0};
local_persist b32 first = 1;
if (first){
first = 0;
result.back[0] = cl_test_back_unimportant;
result.back[1] = cl_test_back;
result.back[2] = cl_test_back;
result.back[3] = cl_test_back_flash;
result.outline[0] = cl_test_outline_unimportant;
result.outline[1] = cl_test_outline_important;
result.outline[2] = cl_test_outline;
result.outline[3] = cl_test_outline_flash;
result.front[0] = cl_button_text;
result.front[1] = cl_button_text;
result.front[2] = cl_button_text;
result.front[3] = cl_button_text_flash;
}
return(&result);
}
internal void
UI_SetRedText(UI_ColorProfile *cl){
for (u64 i = 0; i < (u64)UI_ActionLevel_COUNT; i += 1){
cl->front[i] = cl_red;
}
}
internal v3
UI_Grayified(v3 color){
v3 hsv = RGBToHSV(color);
hsv.y *= 0.5f;
hsv.z *= 0.4f;
v3 result = HSVToRGB(hsv);
return(result);
}
////////////////////////////////
// NOTE(allen): Event Helpers
internal b32
UI_MouseInRect(Rect rect){
b32 result = 0;
if (APP_MouseIsActive()){
Rect clipped = RectIntersect(rect, R_GetClip());
result = RectContains(clipped, vars->mouse_p);
}
return(result);
}
internal b32
UI_TryGetLeftClick(OS_Event **event_out){
b32 result = 0;
OS_Event *event = 0;
for (;OS_GetNextEvent(&event);){
if (event->type == OS_EventType_MousePress && event->mouse_button == MouseButton_Left){
*event_out = event;
result = 1;
}
}
return(result);
}
internal b32
UI_TryEatLeftClick(void){
OS_Event *event = 0;
b32 result = UI_TryGetLeftClick(&event);
if (result){
OS_EatEvent(event);
}
return(result);
}
internal b32
UI_TryGetKeyPress(OS_Event **event_out, Key key){
b32 result = 0;
OS_Event *event = 0;
for (;OS_GetNextEvent(&event);){
if (event->type == OS_EventType_KeyPress && event->key == key){
*event_out = event;
result = 1;
}
}
return(result);
}
internal b32
UI_TryEatKeyPress(Key key){
OS_Event *event = 0;
b32 result = UI_TryGetKeyPress(&event, key);
if (result){
OS_EatEvent(event);
}
return(result);
}
internal b32
UI_TryGetKeyPressModified(OS_Event **event_out, Key key, KeyModifiers mods){
b32 result = 0;
OS_Event *event = 0;
for (;OS_GetNextEvent(&event);){
if (event->type == OS_EventType_KeyPress && event->key == key && event->modifiers == mods){
*event_out = event;
result = 1;
}
}
return(result);
}
internal b32
UI_TryEatKeyPressModified(Key key, KeyModifiers mods){
OS_Event *event = 0;
b32 result = UI_TryGetKeyPressModified(&event, key, mods);
if (result){
OS_EatEvent(event);
}
return(result);
}
internal b32
UI_TryGetScroll(OS_Event **event_out){
b32 result = 0;
OS_Event *event = 0;
for (;OS_GetNextEvent(&event);){
if (event->type == OS_EventType_MouseScroll){
*event_out = event;
result = 1;
}
}
return(result);
}
internal b32
UI_TryEatScroll(v2 *scroll_out){
OS_Event *event = 0;
b32 result = UI_TryGetScroll(&event);
if (result){
*scroll_out = event->scroll;
OS_EatEvent(event);
}
return(result);
}
internal String8
UI_StringizeKeyModified(M_Arena *arena, Key key, KeyModifiers mods){
String8_List list = {0};
if (mods & KeyModifier_Ctrl){
StringListPush(arena, &list, S8Lit("ctrl-"));
}
if (mods & KeyModifier_Shift){
StringListPush(arena, &list, S8Lit("shift-"));
}
if (mods & KeyModifier_Alt){
StringListPush(arena, &list, S8Lit("alt-"));
}
String8 key_name = KeyName(key);
StringListPush(arena, &list, key_name);
return(StringListJoin(arena, &list, 0));
}
////////////////////////////////
// NOTE(allen): UI ID
internal b32
UI_IdEq(UI_Id a, UI_Id b){
return(MemoryMatchStruct(&a, &b));
}
internal UI_Id
UI_IdZero(void){
UI_Id id = {0};
return(id);
}
internal UI_Id
UI_IdV(u64 v){
UI_Id id;
id.v1 = v;
return(id);
}
internal UI_Id
UI_IdP(void *p){
UI_Id id;
id.p1 = p;
return(id);
}
////////////////////////////////
// NOTE(allen): Button placer
internal void
UI_SetColorProfile(UI_ButtonCtx *ctx, UI_ColorProfile *profile){
MemoryCopyStruct(&ctx->cl, profile);
}
internal UI_ButtonCtx
UI_InitButtonCtx(Rect rect, v2 btn_dim, R_Font *font, UI_Id id){
UI_ButtonCtx result = {0};
v2 rect_dim = RectGetDim(rect);
if (rect_dim.x >= btn_dim.x && rect_dim.y >= btn_dim.y){
result.font = font;
result.id = id;
result.button_id.v1 = 1;
result.rect = rect;
result.p = rect.p0;
result.btn_dim = btn_dim;
result.has_room = 1;
result.condition = 1;
result.text_scale = 1;
UI_SetColorProfile(&result, UI_ColorsDefault());
}
return(result);
}
internal f32
UI_ButtonCtxGetTraversedY(UI_ButtonCtx *ctx){
return(ctx->p.y - ctx->rect.y0);
}
internal void
UI_NextCondition(UI_ButtonCtx *ctx, b32 condition){
ctx->condition = condition;
}
internal void
UI_NextHotkey(UI_ButtonCtx *ctx, Key key, KeyModifiers mods){
ctx->has_hot_key = 1;
ctx->hot_key = key;
ctx->hot_key_mods = mods;
}
internal void
UI_NextTooltip(UI_ButtonCtx *ctx, String8 string){
ctx->tool_tip = string;
}
internal void
UI_NextActive(UI_ButtonCtx *ctx, b32 active){
ctx->active = active;
}
internal void
_UI_ButtonHotkey(UI_ButtonCtx *ctx, b32 *result_out){
if (ctx->enable_hot_keys && ctx->has_hot_key && ctx->condition){
if (UI_TryEatKeyPressModified(ctx->hot_key, ctx->hot_key_mods)){
*result_out = 1;
APP_ZeroOwnershipOfFloatingWindow();
}
}
}
internal f32
_UI_ButtonGetXAdvance(UI_ButtonCtx *ctx){
f32 advance = 0;
if (ctx->enable_flexible_x_advance){
advance = ClampTop(ctx->this_button_x_advance, ctx->btn_dim.x);
}
else{
advance = ctx->btn_dim.x;
}
return(advance);
}
internal b32
_UI_ButtonGetNextP(UI_ButtonCtx *ctx, v2 p, v2 *out){
b32 result = 1;
v2 dim = ctx->btn_dim;
p.x += _UI_ButtonGetXAdvance(ctx);
if (p.x + dim.x > ctx->rect.x1){
p.x = ctx->rect.x0;
p.y += dim.y;
if (p.y + dim.y > ctx->rect.y1){
result = 0;
}
}
*out = p;
return(result);
}
internal b32
_UI_ButtonNextWillFit(UI_ButtonCtx *ctx){
b32 result = 1;
v2 p = ctx->p;
if (!_UI_ButtonGetNextP(ctx, p, &p)){
result = 0;
}
return(result);
}
internal Rect
_UI_ButtonPre(UI_ButtonCtx *ctx, UI_ActionLevel *action_level_out, b32 *result_out){
// NOTE(allen): Drop down check
ctx->do_drop_down = (ctx->enable_drop_down && !_UI_ButtonNextWillFit(ctx));
if (ctx->do_drop_down){
ctx->restore.condition = ctx->condition;
ctx->restore.active = ctx->active;
ctx->restore.has_hot_key = ctx->has_hot_key;
ctx->restore.tool_tip = ctx->tool_tip;
ctx->condition = 1;
ctx->active = 0;
ctx->has_hot_key = 0;
ctx->tool_tip = S8Lit("more");
ctx->has_room = 0;
}
// NOTE(allen): Layout
f32 right = ctx->p.x + _UI_ButtonGetXAdvance(ctx);;
Rect rect = MakeRect(V2Expand(ctx->p), right, ctx->p.y + ctx->btn_dim.y);
// NOTE(allen): Mouse
UI_ActionLevel action_level = UI_ActionLevel_None;
if (ctx->active){
action_level = UI_ActionLevel_Active;
}
ctx->did_tool_tip = 0;
if (UI_MouseInRect(rect)){
if (ctx->condition){
action_level = UI_ActionLevel_Hover;
if (UI_TryEatLeftClick()){
*result_out = 1;
action_level = UI_ActionLevel_Flash;
}
}
// NOTE(allen): Tool tip
{
M_Arena *scratch = OS_GetScratch();
String8_List tool_tip = {0};
StringListPush(scratch, &tool_tip, ctx->tool_tip);
if (ctx->has_hot_key){
StringListPush(scratch, &tool_tip, S8Lit(" ["));
String8 key_str = UI_StringizeKeyModified(scratch, ctx->hot_key, ctx->hot_key_mods);
StringListPush(scratch, &tool_tip, key_str);
StringListPush(scratch, &tool_tip, S8Lit("]"));
}
String8 tool_tip_str = StringListJoin(APP_GetFrameArena(), &tool_tip, 0);
APP_SetToolTip(tool_tip_str);
OS_ReleaseScratch(scratch);
if (tool_tip_str.size > 0){
ctx->did_tool_tip = 1;
}
}
}
*action_level_out = action_level;
// NOTE(allen): Render back
R_SelectFont(ctx->font);
v3 back = ctx->cl.back[action_level];
v3 outline = ctx->cl.outline[action_level];
if (!ctx->condition){
back = UI_Grayified(back);
outline = UI_Grayified(outline);
}
R_Rect(rect, back, 1.f);
R_RectOutline(rect, ctx->outline_t, outline, 1.f);
return(rect);
}
internal void
_UI_ButtonPost(UI_ButtonCtx *ctx){
if (!_UI_ButtonGetNextP(ctx, ctx->p, &ctx->p)){
ctx->has_room = 0;
}
if (ctx->do_drop_down){
ctx->condition = ctx->restore.condition;
ctx->active = ctx->restore.active;
ctx->has_hot_key = ctx->restore.has_hot_key;
ctx->tool_tip = ctx->restore.tool_tip;
}
}
internal void
_UI_ButtonEatExtendedParameters(UI_ButtonCtx *ctx){
ctx->condition = 1;
ctx->active = 0;
ctx->has_hot_key = 0;
ctx->tool_tip.size = 0;
}
internal void
_UI_DropDownButtonClick(UI_ButtonCtx *ctx, b32 click_result){
if (ctx->enable_hot_keys){
if (UI_TryEatKeyPressModified(Key_ForwardSlash, KeyModifier_Ctrl)){
APP_TakeOwnershipOfFloatingWindow(ctx->id);
}
}
if (click_result){
APP_TakeOwnershipOfFloatingWindow(ctx->id);
}
}
internal void
UI_ButtonDropdownCallback(void *ptr, APP_FloatingWindowResult *result);
internal UI_ButtonRecord*
_UI_DropDownButtonSaveRecord(UI_ButtonCtx *ctx, Rect rect, b32 *result_out){
M_Arena *arena = APP_GetFrameArena();
UI_ButtonDropdown *last_frame_dropdown = (UI_ButtonDropdown*)APP_GetLastFrameFloatingWindowPtr();
if (last_frame_dropdown != 0){
UI_ButtonRecord *activated = last_frame_dropdown->activated;
if (activated != 0 && UI_IdEq(activated->id, ctx->button_id)){
*result_out = 1;
APP_ZeroOwnershipOfFloatingWindow();
}
}
UI_ButtonDropdown *dropdown = (UI_ButtonDropdown*)APP_GetFloatingWindowPtr();
if (dropdown == 0){
dropdown = PushArrayZero(arena, UI_ButtonDropdown, 1);
dropdown->font = ctx->font;
dropdown->btn_dim = ctx->btn_dim;
dropdown->source_rect = rect;
APP_SetFloatingWindowPtrAndCallback(dropdown, UI_ButtonDropdownCallback);
}
UI_ButtonRecord *record = PushArray(arena, UI_ButtonRecord, 1);
record->condition = ctx->condition;
record->has_hot_key = ctx->has_hot_key;
record->hot_key = ctx->hot_key;
record->hot_key_mods = ctx->hot_key_mods;
record->outline_t = ctx->outline_t;
record->text_scale = ctx->text_scale;
MemoryCopyStruct(&record->cl, &ctx->cl);
record->tool_tip = ctx->tool_tip;
record->id = ctx->button_id;
SLLQueuePush(dropdown->first, dropdown->last, record);
dropdown->count += 1;
return(record);
}
internal b32
UI_Button(UI_ButtonCtx *ctx, u8 major, u8 minor){
b32 result = 0;
_UI_ButtonHotkey(ctx, &result);
b32 did_button = ctx->has_room;
Rect rect = {0};
if (ctx->has_room){
b32 click_result = 0;
UI_ActionLevel action_level;
rect = _UI_ButtonPre(ctx, &action_level, &click_result);
String8 on_screen_major = S8(&major, 1);
String8 on_screen_minor = S8(&minor, 1);
v3 text_color = ctx->cl.front[action_level];
if (!ctx->condition){
text_color = UI_Grayified(text_color);
}
if (ctx->do_drop_down){
_UI_DropDownButtonClick(ctx, click_result);
on_screen_major = S8Lit("/");
on_screen_minor = S8Lit(" ");
text_color = cl_button_text;
did_button = 0;
}
else{
if (click_result){
result = 1;
}
}
f32 major_scale = ctx->text_scale;
f32 minor_scale = ctx->text_scale*0.65f;
v2 major_dim = R_StringDim(major_scale, on_screen_major);
v2 minor_dim = R_StringDim(minor_scale, on_screen_minor);
if (on_screen_minor.str[0] == ' '){
minor_dim.x = 0.f;
minor_dim.y = 0.f;
}
v2 major_p = {0};
v2 minor_p = {0};
minor_p.x = major_p.x + 0.8f*major_dim.x;
// align 0.7 of the way down major with 0.5 of the way down minor
// solve for minor_y in (major_y + 0.7*major_h = minor_y + 0.5*minor_h)
minor_p.y = major_p.y + 0.7f*major_dim.y - 0.5f*minor_dim.y;
v2 combined_dim;
combined_dim.x = Max(major_p.x + major_dim.x, minor_p.x + minor_dim.x);
combined_dim.y = Max(major_p.y + major_dim.y, minor_p.y + minor_dim.y);
v2 combined_half_dim = V2Mul(combined_dim, 0.5f);
v2 center = RectGetCenter(rect);
major_p = V2Sub(center, combined_half_dim);
minor_p = V2Add(major_p, minor_p);
major_p.x = f32Floor(major_p.x);
major_p.y = f32Floor(major_p.y);
minor_p.x = f32Floor(minor_p.x);
minor_p.y = f32Floor(minor_p.y);
R_String(major_p, major_scale, on_screen_major, text_color, 1.f);
R_String(minor_p, minor_scale, on_screen_minor, text_color, 1.f);
_UI_ButtonPost(ctx);
}
if (ctx->enable_drop_down && !did_button){
if (UI_IdEq(APP_OwnerOfFloatingWindow(), ctx->id)){
b32 drop_result = 0;
UI_ButtonRecord *record = _UI_DropDownButtonSaveRecord(ctx, rect, &drop_result);
if (drop_result){
result = 1;
}
record->kind = UI_ButtonKind_Icon;
record->major = major;
record->minor = minor;
}
}
ctx->button_id.v1 += 1;
_UI_ButtonEatExtendedParameters(ctx);
return(result);
}
internal b32
UI_ButtonLabel(UI_ButtonCtx *ctx, String8 string){
b32 result = 0;
_UI_ButtonHotkey(ctx, &result);
b32 did_button = ctx->has_room;
Rect rect = {0};
if (ctx->has_room){
v2 dim = R_StringDim(ctx->text_scale, string);
if (ctx->enable_flexible_x_advance){
ctx->this_button_x_advance = dim.x + ctx->outline_t*2.f;
}
b32 click_result = 0;
UI_ActionLevel action_level;
rect = _UI_ButtonPre(ctx, &action_level, &click_result);
b32 did_tool_tip = ctx->did_tool_tip;
v3 text_color = ctx->cl.front[action_level];
if (!ctx->condition){
text_color = UI_Grayified(text_color);
}
String8 on_screen_string = string;
if (ctx->do_drop_down){
_UI_DropDownButtonClick(ctx, click_result);
on_screen_string = S8Lit("* more *");
text_color = cl_button_text;
did_button = 0;
}
else{
if (click_result){
result = 1;
}
}
Rect inner = RectShrink(rect, ctx->outline_t);
v2 p = {0};
p.x = inner.x0;
// vertically align center of text with center of box
// solve for y in: y + 0.5*h = center.y
p.y = RectGetCenter(inner).y - 0.5f*dim.y;
R_StringCapped(p, inner.x1, ctx->text_scale, on_screen_string, text_color, 1.f);
if ((action_level == UI_ActionLevel_Hover ||
action_level == UI_ActionLevel_Flash) &&
did_button && !did_tool_tip &&
dim.x > (inner.x1 - inner.x0)){
APP_SetToolTip(on_screen_string);
}
_UI_ButtonPost(ctx);
}
if (ctx->enable_drop_down && !did_button){
if (UI_IdEq(APP_OwnerOfFloatingWindow(), ctx->id)){
b32 drop_result = 0;
UI_ButtonRecord *record = _UI_DropDownButtonSaveRecord(ctx, rect, &drop_result);
if (drop_result){
result = 1;
}
record->kind = UI_ButtonKind_Label;
record->string = string;
}
}
ctx->button_id.v1 += 1;
_UI_ButtonEatExtendedParameters(ctx);
return(result);
}
internal void
UI_ButtonDropdownCallback(void *ptr, APP_FloatingWindowResult *result){
UI_ButtonDropdown *dropdown = (UI_ButtonDropdown*)ptr;
// NOTE(allen): Select drop down placement
f32 best_area = NegInf32();
v2 best_p = {0};
v2 best_dim = {0};
Side best_cast_dir[2] = {0};
Rect win = MakeRect(0, 0, V2Expand(vars->window_dim));
Rect src = dropdown->source_rect;
for (u32 x_it = 0; x_it < 2; x_it += 1){
u32 x_side = x_it^1;
for (u32 y_side = 0; y_side < 2; y_side += 1){
v2 p = v2(src.p[x_side].x, src.p[y_side].y);
Range x = MakeRange(p.x, win.p[x_side].x);
Range y = MakeRange(p.y, win.p[y_side^1].y);
v2 dim = v2(RangeSize(x), RangeSize(y));
f32 area = dim.x*dim.y;
if (area > best_area){
best_area = area;
best_p = p;
best_dim = dim;
best_cast_dir[Dimension_X] = x_side;
best_cast_dir[Dimension_Y] = y_side^1;
}
}
}
// NOTE(allen): Fit the drop down to a nice aesthetic rectangle
v2 weight = V2Hadamard(v2(1.f, SmallGolden32), dropdown->btn_dim);
v2 dim = v2(1, 1);
f32 count = (f32)dropdown->count;
for (;dim.x*dim.y < count;){
f32 scores[2];
for (u32 i = 0; i < 2; i += 1){
dim.v[i] += 1;
scores[i] = V2Dot(dim, weight)/(dim.x*dim.y);
dim.v[i] -= 1;
}
if (scores[0] <= scores[1]){
dim.v[0] += 1;
}
else{
dim.v[1] += 1;
}
}
v2 pixel_dim = V2Hadamard(dim, dropdown->btn_dim);
Range x = MakeRange(best_p.x, best_p.x + SignOfSide(best_cast_dir[Dimension_X])*pixel_dim.x);
Range y = MakeRange(best_p.y, best_p.y + SignOfSide(best_cast_dir[Dimension_Y])*pixel_dim.y);
Rect rect = MakeRectRanges(x, y);
Rect outer = RectGrow(rect, 4.f);
Rect inner = RectShrink(outer, 2.f);
// NOTE(allen): Place buttons
R_RectOutline(outer, 2.f, cl_white, 1.f);
R_Rect(inner, cl_black, 1.f);
inner.p0 = rect.p0;
UI_ButtonCtx btn_ctx = UI_InitButtonCtx(inner, dropdown->btn_dim, dropdown->font, UI_IdV(0));
for (UI_ButtonRecord *node = dropdown->first;
node != 0;
node = node->next){
MemoryCopyStruct(&btn_ctx.cl, &node->cl);
btn_ctx.outline_t = node->outline_t;
btn_ctx.text_scale = node->text_scale;
UI_NextCondition(&btn_ctx, node->condition);
if (node->has_hot_key){
UI_NextHotkey(&btn_ctx, node->hot_key, node->hot_key_mods);
}
UI_NextTooltip(&btn_ctx, node->tool_tip);
if (node->kind == UI_ButtonKind_Icon){
if (UI_Button(&btn_ctx, node->major, node->minor)){
dropdown->activated = node;
}
}
else if (node->kind == UI_ButtonKind_Label){
if (UI_ButtonLabel(&btn_ctx, node->string)){
dropdown->activated = node;
}
}
}
result->rect = outer;
}

113
source/ui.h Normal file
View File

@ -0,0 +1,113 @@
/* date = July 7th 2020 4:09 pm */
#ifndef UI_H
#define UI_H
typedef enum{
UI_ActionLevel_None,
UI_ActionLevel_Active,
UI_ActionLevel_Hover,
UI_ActionLevel_Flash,
UI_ActionLevel_COUNT,
} UI_ActionLevel;
typedef struct UI_ColorProfile UI_ColorProfile;
struct UI_ColorProfile{
v3 back[UI_ActionLevel_COUNT];
v3 outline[UI_ActionLevel_COUNT];
v3 front[UI_ActionLevel_COUNT];
};
typedef union UI_Id UI_Id;
union UI_Id{
struct{
u64 v1;
};
struct{
void *p1;
};
u64 v[1];
void *p[1];
};
typedef struct UI_ButtonCtxParamRestore UI_ButtonCtxParamRestore;
struct UI_ButtonCtxParamRestore{
b32 condition;
b32 active;
b32 has_hot_key;
String8 tool_tip;
};
typedef struct UI_ButtonCtx UI_ButtonCtx;
struct UI_ButtonCtx{
// NOTE(allen): State
R_Font *font;
UI_Id id;
UI_Id button_id;
Rect rect;
v2 p;
v2 btn_dim;
UI_ButtonCtxParamRestore restore;
b8 do_drop_down;
b8 did_tool_tip;
b8 has_room;
// NOTE(allen): Extended parameters
b8 condition;
b8 active;
b8 has_hot_key;
Key hot_key;
KeyModifiers hot_key_mods;
String8 tool_tip;
f32 this_button_x_advance;
// NOTE(allen): Settings
UI_ColorProfile cl;
f32 outline_t;
f32 text_scale;
b8 enable_drop_down;
b8 enable_hot_keys;
b8 enable_flexible_x_advance;
};
typedef enum{
UI_ButtonKind_Icon,
UI_ButtonKind_Label,
} UI_ButtonKind;
typedef struct UI_ButtonRecord UI_ButtonRecord;
struct UI_ButtonRecord{
UI_ButtonRecord *next;
String8 string;
UI_ButtonKind kind;
u8 major;
u8 minor;
b8 condition;
b8 has_hot_key;
Key hot_key;
KeyModifiers hot_key_mods;
f32 outline_t;
f32 text_scale;
UI_ColorProfile cl;
String8 tool_tip;
UI_Id id;
};
typedef struct UI_ButtonDropdown UI_ButtonDropdown;
struct UI_ButtonDropdown{
UI_ButtonRecord *first;
UI_ButtonRecord *last;
u64 count;
R_Font *font;
v2 btn_dim;
Rect source_rect;
UI_ButtonRecord *activated;
};
#endif //UI_H

View File

@ -0,0 +1,73 @@
typedef struct W32_AppCode W32_AppCode;
struct W32_AppCode
{
ApplicationPermanentLoadCallback *PermanentLoad;
ApplicationHotLoadCallback *HotLoad;
ApplicationHotUnloadCallback *HotUnload;
ApplicationUpdateCallback *Update;
HMODULE dll;
FILETIME last_dll_write_time;
};
internal b32
W32_AppCodeLoad(W32_AppCode *app_code)
{
b32 result = 1;
CopyFile(global_app_dll_path, global_temp_app_dll_path, FALSE);
app_code->dll = LoadLibraryA(global_temp_app_dll_path);
app_code->last_dll_write_time = W32_GetLastWriteTime(global_app_dll_path);
if(!app_code->dll)
{
result = 0;
goto end;
}
app_code->PermanentLoad = (void *)GetProcAddress(app_code->dll, "PermanentLoad");
app_code->HotLoad = (void *)GetProcAddress(app_code->dll, "HotLoad");
app_code->HotUnload = (void *)GetProcAddress(app_code->dll, "HotUnload");
app_code->Update = (void *)GetProcAddress(app_code->dll, "Update");
if(!app_code->PermanentLoad || !app_code->HotLoad || !app_code->HotUnload || !app_code->Update)
{
app_code->PermanentLoad = ApplicationPermanentLoadStub;
app_code->HotLoad = ApplicationHotLoadStub;
app_code->HotUnload = ApplicationHotUnloadStub;
app_code->Update = ApplicationUpdateStub;
result = 0;
goto end;
}
end:;
return result;
}
internal void
W32_AppCodeUnload(W32_AppCode *app_code)
{
if(app_code->dll)
{
FreeLibrary(app_code->dll);
}
app_code->dll = 0;
app_code->PermanentLoad = ApplicationPermanentLoadStub;
app_code->HotLoad = ApplicationHotLoadStub;
app_code->HotUnload = ApplicationHotUnloadStub;
app_code->Update = ApplicationUpdateStub;
}
internal void
W32_AppCodeUpdate(W32_AppCode *app_code)
{
FILETIME last_write_time = W32_GetLastWriteTime(global_app_dll_path);
if(CompareFileTime(&last_write_time, &app_code->last_dll_write_time))
{
app_code->HotUnload();
W32_AppCodeUnload(app_code);
W32_AppCodeLoad(app_code);
app_code->HotLoad(&global_os);
}
}

View File

@ -0,0 +1,303 @@
// TODO(allen): Changed durring this jam
// HACKED: threw in DialogueSavePath not sure it would actually want to live here.
// or even be included at all?
internal char *
W32_FrameCStringFromString(String8 string)
{
char *buffer = 0;
buffer = M_ArenaPushZero(&os->frame_arena, string.size+1);
MemoryCopy(buffer, string.str, string.size);
return buffer;
}
internal b32
W32_SaveToFile(String8 path, void *data, u64 data_len)
{
b32 result = 0;
HANDLE file = {0};
{
DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
DWORD share_mode = 0;
SECURITY_ATTRIBUTES security_attributes = {
(DWORD)sizeof(SECURITY_ATTRIBUTES),
0,
0,
};
DWORD creation_disposition = CREATE_ALWAYS;
DWORD flags_and_attributes = 0;
HANDLE template_file = 0;
if((file = CreateFile(W32_FrameCStringFromString(path),
desired_access,
share_mode,
&security_attributes,
creation_disposition,
flags_and_attributes,
template_file)) != INVALID_HANDLE_VALUE)
{
void *data_to_write = data;
DWORD data_to_write_size = (DWORD)data_len;
DWORD bytes_written = 0;
WriteFile(file, data_to_write, data_to_write_size, &bytes_written, 0);
CloseHandle(file);
result = 1;
}
else
{
W32_OutputError("File I/O Error", "Could not save to \"%s\"", path);
}
}
return(result);
}
internal void
W32_AppendToFile(String8 path, void *data, u64 data_len)
{
HANDLE file = {0};
{
DWORD desired_access = FILE_APPEND_DATA;
DWORD share_mode = 0;
SECURITY_ATTRIBUTES security_attributes = {
(DWORD)sizeof(SECURITY_ATTRIBUTES),
0,
0,
};
DWORD creation_disposition = OPEN_ALWAYS;
DWORD flags_and_attributes = 0;
HANDLE template_file = 0;
if((file = CreateFileA(W32_FrameCStringFromString(path),
desired_access,
share_mode,
&security_attributes,
creation_disposition,
flags_and_attributes,
template_file)) != INVALID_HANDLE_VALUE)
{
void *data_to_write = data;
DWORD data_to_write_size = (DWORD)data_len;
DWORD bytes_written = 0;
SetFilePointer(file, 0, 0, FILE_END);
WriteFile(file, data_to_write, data_to_write_size, &bytes_written, 0);
CloseHandle(file);
}
else
{
W32_OutputError("File I/O Error", "Could not save to \"%s\"", path);
}
}
}
internal void
W32_LoadEntireFile(M_Arena *arena, String8 path, void **data, u64 *data_len)
{
*data = 0;
*data_len = 0;
HANDLE file = {0};
{
DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
DWORD share_mode = 0;
SECURITY_ATTRIBUTES security_attributes = {
(DWORD)sizeof(SECURITY_ATTRIBUTES),
0,
0,
};
DWORD creation_disposition = OPEN_EXISTING;
DWORD flags_and_attributes = 0;
HANDLE template_file = 0;
if((file = CreateFile(W32_FrameCStringFromString(path), desired_access, share_mode, &security_attributes, creation_disposition, flags_and_attributes, template_file)) != INVALID_HANDLE_VALUE)
{
DWORD read_bytes = GetFileSize(file, 0);
if(read_bytes)
{
void *read_data = M_ArenaPush(arena, read_bytes+1);
DWORD bytes_read = 0;
OVERLAPPED overlapped = {0};
ReadFile(file, read_data, read_bytes, &bytes_read, &overlapped);
((u8 *)read_data)[read_bytes] = 0;
*data = read_data;
*data_len = (u64)bytes_read;
}
CloseHandle(file);
}
}
}
internal char *
W32_LoadEntireFileAndNullTerminate(M_Arena *arena, String8 path)
{
char *result = 0;
HANDLE file = {0};
{
DWORD desired_access = GENERIC_READ | GENERIC_WRITE;
DWORD share_mode = 0;
SECURITY_ATTRIBUTES security_attributes = {
(DWORD)sizeof(SECURITY_ATTRIBUTES),
0,
0,
};
DWORD creation_disposition = OPEN_EXISTING;
DWORD flags_and_attributes = 0;
HANDLE template_file = 0;
if((file = CreateFile(W32_FrameCStringFromString(path), desired_access, share_mode, &security_attributes, creation_disposition, flags_and_attributes, template_file)) != INVALID_HANDLE_VALUE)
{
DWORD read_bytes = GetFileSize(file, 0);
if(read_bytes)
{
result = M_ArenaPush(arena, read_bytes+1);
DWORD bytes_read = 0;
OVERLAPPED overlapped = {0};
ReadFile(file, result, read_bytes, &bytes_read, &overlapped);
result[read_bytes] = 0;
}
CloseHandle(file);
}
else
{
W32_OutputError("File I/O Error", "Could not read from \"%s\"", path);
}
}
return result;
}
internal void
W32_FreeFileMemory(void *data)
{
W32_HeapFree(data);
}
internal void
W32_DeleteFile(String8 path)
{
DeleteFileA(W32_FrameCStringFromString(path));
}
internal b32
W32_MakeDirectory(String8 path)
{
b32 result = 1;
if(!CreateDirectoryA(W32_FrameCStringFromString(path), 0))
{
result = 0;
}
return result;
}
internal b32
W32_DoesFileExist(String8 path)
{
b32 found = GetFileAttributesA(W32_FrameCStringFromString(path)) != INVALID_FILE_ATTRIBUTES;
return found;
}
internal b32
W32_DoesDirectoryExist(String8 path)
{
DWORD file_attributes = GetFileAttributesA(W32_FrameCStringFromString(path));
b32 found = (file_attributes != INVALID_FILE_ATTRIBUTES &&
!!(file_attributes & FILE_ATTRIBUTE_DIRECTORY));
return found;
}
internal b32
W32_CopyFile(String8 dest, String8 source)
{
b32 success = 0;
success = CopyFile(W32_FrameCStringFromString(source), W32_FrameCStringFromString(dest), 0);
return success;
}
internal OS_DirectoryList
W32_DirectoryListLoad(M_Arena *arena, String8 path, i32 flags)
{
OS_DirectoryList list = {0};
return list;
}
internal u8*
_W32_InitFilter(M_Arena *arena, String8 *fixed_ext){
u8 *filter = 0;
if (fixed_ext != 0){
String8_List list = {0};
StringListPush(arena, &list, fixed_ext[0]);
StringListPush(arena, &list, S8Lit("\0"));
StringListPush(arena, &list, S8Lit("*."));
StringListPush(arena, &list, fixed_ext[1]);
StringListPush(arena, &list, S8Lit("\0\0"));
String8 filter_str = StringListJoin(arena, &list, 0);
filter = filter_str.str;
}
return(filter);
}
internal String8
W32_DialogueSavePath(M_Arena *arena, String8 *fixed_ext)
{
M_Arena *scratch = OS_GetScratch1(arena);
OPENFILENAMEA openfilename = {sizeof(openfilename)};
openfilename.lpstrFilter = (LPSTR)_W32_InitFilter(scratch, fixed_ext);
openfilename.nMaxFile = Kilobytes(32);
openfilename.lpstrFile = (LPSTR)PushArray(arena, u8, openfilename.nMaxFile);
openfilename.lpstrFile[0] = 0;
openfilename.lpstrTitle = "Save";
openfilename.Flags = OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
String8 result = {0};
if (GetSaveFileNameA(&openfilename)){
result.str = openfilename.lpstrFile;
result.size = 0;
for (;openfilename.lpstrFile[result.size] != 0; result.size += 1);
}
OS_ReleaseScratch(scratch);
return(result);
}
internal String8
W32_DialogueLoadPath(M_Arena *arena, String8 *fixed_ext)
{
M_Arena *scratch = OS_GetScratch1(arena);
OPENFILENAMEA openfilename = {sizeof(openfilename)};
openfilename.lpstrFilter = (LPSTR)_W32_InitFilter(scratch, fixed_ext);
openfilename.nMaxFile = Kilobytes(32);
openfilename.lpstrFile = (LPSTR)PushArray(arena, u8, openfilename.nMaxFile);
openfilename.lpstrFile[0] = 0;
openfilename.lpstrTitle = "Open";
openfilename.Flags = OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST;
String8 result = {0};
if (GetOpenFileNameA(&openfilename)){
result.str = openfilename.lpstrFile;
result.size = 0;
for (;openfilename.lpstrFile[result.size] != 0; result.size += 1);
}
OS_ReleaseScratch(scratch);
return(result);
}

669
source/win32/win32_main.c Normal file
View File

@ -0,0 +1,669 @@
// TODO(allen): Changed durring this jam
// WM_SYSKEYDOWN bell sounds removed
#include <windows.h>
#include <windowsx.h>
#include <xinput.h>
#include <objbase.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <audiopolicy.h>
#undef DeleteFile
// NOTE(rjf): OpenGL
#include <gl/gl.h>
#include "ext/wglext.h"
#include "ext/glext.h"
// NOTE(rjf): CRT
#include <stdio.h>
// NOTE(rjf): Headers
#include "program_options.h"
#include "language_layer.h"
#include "app_memory.h"
#include "os.h"
#include "win32_timer.h"
#include "language_layer.c"
#include "app_memory.c"
#include "os.c"
// NOTE(rjf): Globals
global char global_executable_path[256];
global char global_executable_directory[256];
global char global_working_directory[256];
global char global_app_dll_path[256];
global char global_temp_app_dll_path[256];
global OS_State global_os;
global HDC global_device_context;
global HINSTANCE global_instance_handle;
global W32_Timer global_win32_timer = {0};
#define W32_MAX_GAMEPADS 16
typedef struct W32_GamepadInput W32_GamepadInput;
struct W32_GamepadInput
{
b32 connected;
v2 joystick_1;
v2 joystick_2;
f32 trigger_left;
f32 trigger_right;
i32 button_states[GamepadButton_Max];
};
W32_GamepadInput global_gamepads[W32_MAX_GAMEPADS];
// NOTE(rjf): Implementations
#include "win32_utilities.c"
#include "win32_timer.c"
#include "win32_file_io.c"
#include "win32_app_code.c"
#include "win32_xinput.c"
#include "win32_wasapi.c"
#include "win32_opengl.c"
#include "win32_thread.c"
//~
typedef enum W32_CursorStyle
{
W32_CursorStyle_Normal,
W32_CursorStyle_HorizontalResize,
W32_CursorStyle_VerticalResize,
W32_CursorStyle_IBar,
}
W32_CursorStyle;
global W32_CursorStyle global_cursor_style = 0;
internal v2
W32_GetMousePosition(HWND window)
{
v2 result = {0};
POINT mouse;
GetCursorPos(&mouse);
ScreenToClient(window, &mouse);
result.x = (f32)(mouse.x);
result.y = (f32)(mouse.y);
return result;
}
internal LRESULT
W32_WindowProc(HWND window_handle, UINT message, WPARAM w_param, LPARAM l_param)
{
LRESULT result = 0;
local_persist b32 mouse_hover_active_because_windows_makes_me_cry = 0;
KeyModifiers modifiers = 0;
if(GetKeyState(VK_CONTROL) & 0x8000)
{
modifiers |= KeyModifier_Ctrl;
}
if(GetKeyState(VK_SHIFT) & 0x8000)
{
modifiers |= KeyModifier_Shift;
}
if(GetKeyState(VK_MENU) & 0x8000)
{
modifiers |= KeyModifier_Alt;
}
if(message == WM_CLOSE || message == WM_DESTROY || message == WM_QUIT)
{
global_os.quit = 1;
result = 0;
}
else if(message == WM_LBUTTONDOWN)
{
OS_PushEvent(OS_MousePressEvent(MouseButton_Left, global_os.mouse_position));
}
else if(message == WM_LBUTTONUP)
{
OS_PushEvent(OS_MouseReleaseEvent(MouseButton_Left, global_os.mouse_position));
}
else if(message == WM_RBUTTONDOWN)
{
OS_PushEvent(OS_MousePressEvent(MouseButton_Right, global_os.mouse_position));
}
else if(message == WM_RBUTTONUP)
{
OS_PushEvent(OS_MouseReleaseEvent(MouseButton_Right, global_os.mouse_position));
}
else if(message == WM_MOUSEMOVE)
{
i16 x_position = LOWORD(l_param);
i16 y_position = HIWORD(l_param);
v2 last_mouse = global_os.mouse_position;
global_os.mouse_position = W32_GetMousePosition(window_handle);
OS_PushEvent(OS_MouseMoveEvent(global_os.mouse_position,
v2(global_os.mouse_position.x - last_mouse.x,
global_os.mouse_position.y - last_mouse.y)));
if(mouse_hover_active_because_windows_makes_me_cry == 0)
{
mouse_hover_active_because_windows_makes_me_cry = 1;
TRACKMOUSEEVENT track_mouse_event = {0};
{
track_mouse_event.cbSize = sizeof(track_mouse_event);
track_mouse_event.dwFlags = TME_LEAVE;
track_mouse_event.hwndTrack = window_handle;
track_mouse_event.dwHoverTime = HOVER_DEFAULT;
}
TrackMouseEvent(&track_mouse_event);
}
}
else if(message == WM_MOUSELEAVE)
{
mouse_hover_active_because_windows_makes_me_cry = 0;
}
else if(message == WM_MOUSEWHEEL)
{
i16 wheel_delta = HIWORD(w_param);
OS_PushEvent(OS_MouseScrollEvent(v2(0, (f32)wheel_delta), modifiers));
}
else if(message == WM_MOUSEHWHEEL)
{
i16 wheel_delta = HIWORD(w_param);
OS_PushEvent(OS_MouseScrollEvent(v2((f32)wheel_delta, 0), modifiers));
}
else if(message == WM_SETCURSOR)
{
if(global_os.mouse_position.x >= 1 && global_os.mouse_position.x <= global_os.window_size.x-1 &&
global_os.mouse_position.y >= 1 && global_os.mouse_position.y <= global_os.window_size.y-1 && mouse_hover_active_because_windows_makes_me_cry)
{
switch(global_cursor_style)
{
case W32_CursorStyle_HorizontalResize:
{
SetCursor(LoadCursorA(0, IDC_SIZEWE));
break;
}
case W32_CursorStyle_VerticalResize:
{
SetCursor(LoadCursorA(0, IDC_SIZENS));
break;
}
case W32_CursorStyle_IBar:
{
SetCursor(LoadCursorA(0, IDC_IBEAM));
break;
}
case W32_CursorStyle_Normal:
{
SetCursor(LoadCursorA(0, IDC_ARROW));
break;
}
default: break;
}
}
else
{
result = DefWindowProc(window_handle, message, w_param, l_param);
}
}
else if(message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ||
message == WM_KEYDOWN || message == WM_KEYUP)
{
u64 vkey_code = w_param;
i8 was_down = !!(l_param & (1 << 30));
i8 is_down = !(l_param & (1 << 31));
u64 key_input = 0;
if((vkey_code >= 'A' && vkey_code <= 'Z') ||
(vkey_code >= '0' && vkey_code <= '9'))
{
// NOTE(rjf): Letter/number buttons
key_input = (vkey_code >= 'A' && vkey_code <= 'Z') ? Key_A + (vkey_code-'A') : Key_0 + (vkey_code-'0');
}
else
{
if(vkey_code == VK_ESCAPE)
{
key_input = Key_Esc;
}
else if(vkey_code >= VK_F1 && vkey_code <= VK_F12)
{
key_input = Key_F1 + vkey_code - VK_F1;
}
else if(vkey_code == VK_OEM_3)
{
key_input = Key_GraveAccent;
}
else if(vkey_code == VK_OEM_MINUS)
{
key_input = Key_Minus;
}
else if(vkey_code == VK_OEM_PLUS)
{
key_input = Key_Equal;
}
else if(vkey_code == VK_BACK)
{
key_input = Key_Backspace;
}
else if(vkey_code == VK_TAB)
{
key_input = Key_Tab;
}
else if(vkey_code == VK_SPACE)
{
key_input = Key_Space;
}
else if(vkey_code == VK_RETURN)
{
key_input = Key_Enter;
}
else if(vkey_code == VK_CONTROL)
{
key_input = Key_Ctrl;
modifiers &= ~KeyModifier_Ctrl;
}
else if(vkey_code == VK_SHIFT)
{
key_input = Key_Shift;
modifiers &= ~KeyModifier_Shift;
}
else if(vkey_code == VK_MENU)
{
key_input = Key_Alt;
modifiers &= ~KeyModifier_Alt;
}
else if(vkey_code == VK_UP)
{
key_input = Key_Up;
}
else if(vkey_code == VK_LEFT)
{
key_input = Key_Left;
}
else if(vkey_code == VK_DOWN)
{
key_input = Key_Down;
}
else if(vkey_code == VK_RIGHT)
{
key_input = Key_Right;
}
else if(vkey_code == VK_DELETE)
{
key_input = Key_Delete;
}
else if(vkey_code == VK_PRIOR)
{
key_input = Key_PageUp;
}
else if(vkey_code == VK_NEXT)
{
key_input = Key_PageDown;
}
else if(vkey_code == VK_HOME)
{
key_input = Key_Home;
}
else if(vkey_code == VK_END)
{
key_input = Key_End;
}
else if(vkey_code == VK_OEM_2)
{
key_input = Key_ForwardSlash;
}
else if(vkey_code == VK_OEM_PERIOD)
{
key_input = Key_Period;
}
else if(vkey_code == VK_OEM_COMMA)
{
key_input = Key_Comma;
}
else if(vkey_code == VK_OEM_7)
{
key_input = Key_Quote;
}
else if(vkey_code == VK_OEM_4)
{
key_input = Key_LeftBracket;
}
else if(vkey_code == VK_OEM_6)
{
key_input = Key_RightBracket;
}
}
if(is_down)
{
OS_PushEvent(OS_KeyPressEvent(key_input, modifiers));
}
else
{
OS_PushEvent(OS_KeyReleaseEvent(key_input, modifiers));
}
DefWindowProc(window_handle, message, w_param, l_param);
}
else if (message == WM_SYSCHAR){
// NOTE(allen): Do nothing - just don't fall through to DefWindowProc which will
// cause bell sounds for alt modified combos.
}
else if(message == WM_CHAR)
{
u64 char_input = w_param;
if(char_input >= 32 && char_input != VK_RETURN && char_input != VK_ESCAPE &&
char_input != 127)
{
OS_PushEvent(OS_CharacterInputEvent(char_input));
}
}
else
{
result = DefWindowProc(window_handle, message, w_param, l_param);
}
return result;
}
internal f32
W32_GetTime(void)
{
W32_Timer *timer = &global_win32_timer;
LARGE_INTEGER current_time;
QueryPerformanceCounter(&current_time);
return global_os.current_time + (f32)(current_time.QuadPart - timer->begin_frame.QuadPart) / (f32)timer->counts_per_second.QuadPart;
}
internal u64
W32_GetCycles(void)
{
u64 result = __rdtsc();
return result;
}
internal void
W32_ResetCursor(void)
{
global_cursor_style = W32_CursorStyle_Normal;
}
internal void
W32_SetCursorToHorizontalResize(void)
{
global_cursor_style = W32_CursorStyle_HorizontalResize;
}
internal void
W32_SetCursorToVerticalResize(void)
{
global_cursor_style = W32_CursorStyle_VerticalResize;
}
int
WinMain(HINSTANCE instance, HINSTANCE prev_instance, LPSTR lp_cmd_line, int n_show_cmd)
{
global_instance_handle = instance;
W32_TimerInit(&global_win32_timer);
W32_AppCode win32_game_code = {0};
W32_SoundOutput win32_sound_output = {0};
// NOTE(rjf): Calculate executable name and path to DLL
{
DWORD size_of_executable_path =
GetModuleFileNameA(0, global_executable_path, sizeof(global_executable_path));
// NOTE(rjf): Calculate executable directory
{
MemoryCopy(global_executable_directory, global_executable_path, size_of_executable_path);
char *one_past_last_slash = global_executable_directory;
for(i32 i = 0; global_executable_directory[i]; ++i)
{
if(global_executable_directory[i] == '\\')
{
one_past_last_slash = global_executable_directory + i + 1;
}
}
*one_past_last_slash = 0;
}
// NOTE(rjf): Create DLL filenames
{
wsprintf(global_app_dll_path, "%s%s.dll", global_executable_directory, PROGRAM_FILENAME);
wsprintf(global_temp_app_dll_path, "%stemp_%s.dll", global_executable_directory, PROGRAM_FILENAME);
}
GetCurrentDirectory(sizeof(global_working_directory), global_working_directory);
}
WNDCLASS window_class = {0};
{
window_class.style = CS_HREDRAW | CS_VREDRAW;
window_class.lpfnWndProc = W32_WindowProc;
window_class.hInstance = instance;
window_class.lpszClassName = "ApplicationWindowClass";
window_class.hCursor = LoadCursor(0, IDC_ARROW);
}
if(!RegisterClass(&window_class))
{
// NOTE(rjf): ERROR: Window class registration failure
W32_OutputError("Fatal Error", "Window class registration failure.");
goto quit;
}
HWND window_handle = CreateWindow("ApplicationWindowClass", WINDOW_TITLE,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
DEFAULT_WINDOW_WIDTH,
DEFAULT_WINDOW_HEIGHT,
0, 0, instance, 0);
if(!window_handle)
{
// NOTE(rjf): ERROR: Window creation failure
W32_OutputError("Fatal Error", "Window creation failure.");
goto quit;
}
// NOTE(rjf): Load application code
W32_AppCode win32_app_code = {0};
{
if(!W32_AppCodeLoad(&win32_app_code))
{
// NOTE(rjf): ERROR: Application code load failure
W32_OutputError("Fatal Error", "Application code load failure.");
goto quit;
}
}
// NOTE(rjf): Sound initialization
{
win32_sound_output.channels = 2;
win32_sound_output.samples_per_second = 48000;
win32_sound_output.latency_frame_count = 48000;
W32_LoadWASAPI();
W32_InitWASAPI(&win32_sound_output);
}
// NOTE(rjf): Find refresh rate
f32 refresh_rate = 60.f;
{
DEVMODEA device_mode = {0};
if(EnumDisplaySettingsA(0, ENUM_CURRENT_SETTINGS, &device_mode))
{
refresh_rate = (float)device_mode.dmDisplayFrequency;
}
}
// NOTE(rjf): Initialize platform
{
os = &global_os;
global_os.executable_folder_absolute_path = String8FromCString(global_executable_directory);
global_os.executable_absolute_path = String8FromCString(global_executable_path);
global_os.working_directory_path = String8FromCString(global_working_directory);
global_os.quit = 0;
global_os.vsync = 1;
global_os.fullscreen = 0;
global_os.window_size.x = DEFAULT_WINDOW_WIDTH;
global_os.window_size.y = DEFAULT_WINDOW_HEIGHT;
global_os.current_time = 0.f;
global_os.target_frames_per_second = refresh_rate;
global_os.sample_out = W32_HeapAlloc(win32_sound_output.samples_per_second * sizeof(f32) * 2);
global_os.samples_per_second = win32_sound_output.samples_per_second;
global_os.Reserve = W32_Reserve;
global_os.Release = W32_Release;
global_os.Commit = W32_Commit;
global_os.Decommit = W32_Decommit;
global_os.OutputError = W32_OutputError;
global_os.SaveToFile = W32_SaveToFile;
global_os.AppendToFile = W32_AppendToFile;
global_os.LoadEntireFile = W32_LoadEntireFile;
global_os.LoadEntireFileAndNullTerminate = W32_LoadEntireFileAndNullTerminate;
global_os.DeleteFile = W32_DeleteFile;
global_os.MakeDirectory = W32_MakeDirectory;
global_os.DoesFileExist = W32_DoesFileExist;
global_os.DoesDirectoryExist = W32_DoesDirectoryExist;
global_os.CopyFile = W32_CopyFile;
global_os.ListDirectory = W32_DirectoryListLoad;
global_os.GetTime = W32_GetTime;
global_os.GetCycles = W32_GetCycles;
global_os.ResetCursor = W32_ResetCursor;
global_os.SetCursorToHorizontalResize = W32_SetCursorToHorizontalResize;
global_os.SetCursorToVerticalResize = W32_SetCursorToVerticalResize;
global_os.LoadOpenGLProcedure = W32_LoadOpenGLProcedure;
global_os.RefreshScreen = W32_OpenGLRefreshScreen;
global_os.GetThreadContext = W32_GetThreadContext;
global_os.DialogueSavePath = W32_DialogueSavePath;
global_os.DialogueLoadPath = W32_DialogueLoadPath;
global_os.permanent_arena = M_ArenaInitialize();
global_os.frame_arena = M_ArenaInitialize();
}
// NOTE(allen): Thread Context
OS_ThreadContext tctx_;
OS_ArenaNode tctx_scratch_nodes[3];
W32_ThreadInit(&tctx_, tctx_scratch_nodes, 3);
// NOTE(rjf): OpenGL initialization
{
global_device_context = GetDC(window_handle);
if(!W32_InitOpenGL(&global_device_context, global_instance_handle))
{
W32_OutputError("Fatal Error", "OpenGL initialization failure.");
goto quit;
}
}
W32_LoadXInput();
win32_app_code.PermanentLoad(&global_os);
win32_app_code.HotLoad(&global_os);
ShowWindow(window_handle, n_show_cmd);
UpdateWindow(window_handle);
while(!global_os.quit)
{
W32_TimerBeginFrame(&global_win32_timer);
M_ArenaClear(&os->frame_arena);
// NOTE(rjf): Update Windows events
{
os->event_count = 0;
MSG message;
if(global_os.wait_for_events_to_update && !global_os.pump_events)
{
WaitMessage();
}
while(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
// NOTE(rjf): Update window size
{
RECT client_rect;
GetClientRect(window_handle, &client_rect);
global_os.window_size.x = client_rect.right - client_rect.left;
global_os.window_size.y = client_rect.bottom - client_rect.top;
}
// NOTE(rjf): Update input data (post-event)
OS_BeginFrame();
{
POINT mouse;
GetCursorPos(&mouse);
ScreenToClient(window_handle, &mouse);
W32_UpdateXInput();
global_os.pump_events = 0;
}
// NOTE(rjf): Find how much sound to write and where
if(win32_sound_output.initialized)
{
global_os.sample_count_to_output = 0;
UINT32 sound_padding_size;
if(SUCCEEDED(win32_sound_output.audio_client->lpVtbl->GetCurrentPadding(win32_sound_output.audio_client, &sound_padding_size)))
{
global_os.samples_per_second = win32_sound_output.samples_per_second;
global_os.sample_count_to_output = (u32)(win32_sound_output.latency_frame_count - sound_padding_size);
if(global_os.sample_count_to_output > win32_sound_output.latency_frame_count)
{
global_os.sample_count_to_output = win32_sound_output.latency_frame_count;
}
}
for(u32 i = 0; i < win32_sound_output.buffer_frame_count; ++i)
{
global_os.sample_out[i] = 0;
}
}
// NOTE(rjf): Call into the app layer to update
{
b32 last_fullscreen = global_os.fullscreen;
win32_app_code.Update();
// NOTE(rjf): Update fullscreen if necessary
if(last_fullscreen != global_os.fullscreen)
{
W32_ToggleFullscreen(window_handle);
}
// NOTE(rjf): Fill sound buffer with game sound
if(win32_sound_output.initialized)
{
W32_FillSoundBuffer(global_os.sample_count_to_output, global_os.sample_out, &win32_sound_output);
}
}
// NOTE(rjf): Post-update platform data update
{
OS_EndFrame();
}
W32_AppCodeUpdate(&win32_app_code);
W32_TimerEndFrame(&global_win32_timer, 1000.0 * (1.0 / (f64)global_os.target_frames_per_second));
}
ShowWindow(window_handle, SW_HIDE);
W32_AppCodeUnload(&win32_app_code);
W32_CleanUpOpenGL(&global_device_context);
quit:;
return 0;
}

128
source/win32/win32_opengl.c Normal file
View File

@ -0,0 +1,128 @@
global HGLRC global_opengl_render_context;
internal void *
W32_LoadOpenGLProcedure(char *name)
{
void *p = (void *)wglGetProcAddress(name);
if(!p || p == (void *)0x1 || p == (void *)0x2 || p == (void *)0x3 || p == (void *)-1)
{
return 0;
}
else
{
return p;
}
}
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
PFNWGLMAKECONTEXTCURRENTARBPROC wglMakeContextCurrentARB;
PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
internal void
W32_LoadWGLFunctions(HINSTANCE h_instance)
{
wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC) W32_LoadOpenGLProcedure("wglChoosePixelFormatARB");
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) W32_LoadOpenGLProcedure("wglCreateContextAttribsARB");
wglMakeContextCurrentARB = (PFNWGLMAKECONTEXTCURRENTARBPROC) W32_LoadOpenGLProcedure("wglMakeContextCurrentARB");
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) W32_LoadOpenGLProcedure("wglSwapIntervalEXT");
}
internal b32
W32_InitOpenGL(HDC *device_context, HINSTANCE h_instance)
{
b32 result = 0;
// NOTE(rjf): Set up pixel format for dummy context
int pixel_format = 0;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24,
8,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
pixel_format = ChoosePixelFormat(*device_context, &pfd);
if(pixel_format)
{
SetPixelFormat(*device_context, pixel_format, &pfd);
HGLRC gl_dummy_render_context = wglCreateContext(*device_context);
wglMakeCurrent(*device_context, gl_dummy_render_context);
W32_LoadWGLFunctions(h_instance);
// NOTE(rjf): Setup real pixel format
{
int pf_attribs_i[] =
{
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
WGL_COLOR_BITS_ARB, 32,
WGL_DEPTH_BITS_ARB, 24,
WGL_STENCIL_BITS_ARB, 8,
0
};
UINT num_formats = 0;
wglChoosePixelFormatARB(*device_context,
pf_attribs_i,
0,
1,
&pixel_format,
&num_formats);
}
if(pixel_format)
{
const int context_attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 3,
0
};
global_opengl_render_context = wglCreateContextAttribsARB(*device_context,
gl_dummy_render_context,
context_attribs);
if(global_opengl_render_context)
{
wglMakeCurrent(*device_context, 0);
wglDeleteContext(gl_dummy_render_context);
wglMakeCurrent(*device_context, global_opengl_render_context);
wglSwapIntervalEXT(0);
result = 1;
}
}
}
return result;
}
internal void
W32_CleanUpOpenGL(HDC *device_context)
{
wglMakeCurrent(*device_context, 0);
wglDeleteContext(global_opengl_render_context);
}
internal void
W32_OpenGLRefreshScreen(void)
{
wglSwapLayerBuffers(global_device_context, WGL_SWAP_MAIN_PLANE);
}

View File

@ -0,0 +1,31 @@
global DWORD tls_index_thread_context = 0;
internal void
W32_ThreadSystemInit(void)
{
tls_index_thread_context = TlsAlloc();
}
internal void
W32_ThreadInit(OS_ThreadContext *tctx, OS_ArenaNode *nodes, i32 node_count)
{
MemoryZeroStruct(tctx);
MemoryZero(nodes, sizeof(*nodes)*node_count);
for (i32 i = 0; i < node_count; i += 1)
{
OS_ArenaNode *node_ptr = nodes + i;
SLLStackPush(tctx->free, node_ptr);
node_ptr->arena = M_ArenaInitialize();
}
BOOL success = TlsSetValue(tls_index_thread_context, tctx);
Assert(success);
}
internal OS_ThreadContext*
W32_GetThreadContext(void)
{
void *ptr = TlsGetValue(tls_index_thread_context);
return((OS_ThreadContext*)ptr);
}

View File

@ -0,0 +1,54 @@
internal b32
W32_TimerInit(W32_Timer *timer)
{
b32 result = 0;
if(QueryPerformanceFrequency(&timer->counts_per_second))
{
result = 1;
}
timer->sleep_is_granular = (timeBeginPeriod(1) == TIMERR_NOERROR);
return result;
}
internal void
W32_TimerBeginFrame(W32_Timer *timer)
{
QueryPerformanceCounter(&timer->begin_frame);
}
internal void
W32_TimerEndFrame(W32_Timer *timer, f64 milliseconds_per_frame)
{
LARGE_INTEGER end_frame;
QueryPerformanceCounter(&end_frame);
f64 desired_seconds_per_frame = (milliseconds_per_frame / 1000.0);
i64 elapsed_counts = end_frame.QuadPart - timer->begin_frame.QuadPart;
i64 desired_counts = (i64)(desired_seconds_per_frame * timer->counts_per_second.QuadPart);
i64 counts_to_wait = desired_counts - elapsed_counts;
LARGE_INTEGER start_wait;
LARGE_INTEGER end_wait;
QueryPerformanceCounter(&start_wait);
while(counts_to_wait > 0)
{
if(timer->sleep_is_granular)
{
DWORD milliseconds_to_sleep = (DWORD)(1000.0 * ((f64)(counts_to_wait) / timer->counts_per_second.QuadPart));
if(milliseconds_to_sleep > 0)
{
Sleep(milliseconds_to_sleep);
}
}
QueryPerformanceCounter(&end_wait);
counts_to_wait -= end_wait.QuadPart - start_wait.QuadPart;
start_wait = end_wait;
}
}

View File

@ -0,0 +1,12 @@
typedef struct W32_Timer
{
LARGE_INTEGER counts_per_second;
LARGE_INTEGER begin_frame;
b32 sleep_is_granular;
}
W32_Timer;
internal b32 W32_TimerInit(W32_Timer *timer);
internal void W32_TimerBeginFrame(W32_Timer *timer);
internal void W32_TimerEndFrame(W32_Timer *timer, f64 milliseconds_per_frame);

View File

@ -0,0 +1,121 @@
internal FILETIME
W32_GetLastWriteTime(char *filename)
{
FILETIME last_write_time = {0};
WIN32_FIND_DATA find_data;
HANDLE find_handle = FindFirstFileA(filename, &find_data);
if(find_handle != INVALID_HANDLE_VALUE)
{
FindClose(find_handle);
last_write_time = find_data.ftLastWriteTime;
}
return last_write_time;
}
internal void *
W32_HeapAlloc(u32 size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
internal void
W32_HeapFree(void *data)
{
HeapFree(GetProcessHeap(), 0, data);
}
internal void *
W32_Reserve(u64 size)
{
void *memory = VirtualAlloc(0, size, MEM_RESERVE, PAGE_NOACCESS);
return memory;
}
internal void
W32_Release(void *memory)
{
VirtualFree(memory, 0, MEM_RELEASE);
}
internal void
W32_Commit(void *memory, u64 size)
{
VirtualAlloc(memory, size, MEM_COMMIT, PAGE_READWRITE);
}
internal void
W32_Decommit(void *memory, u64 size)
{
VirtualFree(memory, size, MEM_DECOMMIT);
}
internal void
W32_OutputError(char *title, char *format, ...)
{
local_persist volatile LONG locked = 0;
while(locked);
InterlockedExchange(&locked, 1);
{
va_list args;
va_start(args, format);
u32 required_characters = vsnprintf(0, 0, format, args)+1;
va_end(args);
local_persist char text[4096] = {0};
if(required_characters > 4096)
{
required_characters = 4096;
}
va_start(args, format);
vsnprintf(text, required_characters, format, args);
va_end(args);
text[required_characters-1] = 0;
MessageBoxA(0, text, title, MB_OK);
}
InterlockedExchange(&locked, 0);
}
internal void
W32_ToggleFullscreen(HWND hwnd)
{
local_persist WINDOWPLACEMENT last_window_placement = {
sizeof(last_window_placement)
};
DWORD window_style = GetWindowLong(hwnd, GWL_STYLE);
if(window_style & WS_OVERLAPPEDWINDOW)
{
MONITORINFO monitor_info = { sizeof(monitor_info) };
if(GetWindowPlacement(hwnd, &last_window_placement) &&
GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY),
&monitor_info))
{
SetWindowLong(hwnd, GWL_STYLE,
window_style & ~WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, HWND_TOP,
monitor_info.rcMonitor.left,
monitor_info.rcMonitor.top,
monitor_info.rcMonitor.right -
monitor_info.rcMonitor.left,
monitor_info.rcMonitor.bottom -
monitor_info.rcMonitor.top,
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
}
else
{
SetWindowLong(hwnd, GWL_STYLE,
window_style | WS_OVERLAPPEDWINDOW);
SetWindowPlacement(hwnd, &last_window_placement);
SetWindowPos(hwnd, 0, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
}
}

212
source/win32/win32_wasapi.c Normal file
View File

@ -0,0 +1,212 @@
static const GUID IID_IAudioClient = {0x1CB9AD4C, 0xDBFA, 0x4c32, 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2};
static const GUID IID_IAudioRenderClient = {0xF294ACFC, 0x3146, 0x4483, 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2};
static const GUID CLSID_MMDeviceEnumerator = {0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E};
static const GUID IID_IMMDeviceEnumerator = {0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6};
static const GUID PcmSubformatGuid = {STATIC_KSDATAFORMAT_SUBTYPE_PCM};
#ifndef AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
#define AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 0x80000000
#endif
#ifndef AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
#define AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY 0x08000000
#endif
#define SOUND_LATENCY_FPS 10
#define REFTIMES_PER_SEC 10000000
#define CO_CREATE_INSTANCE(name) HRESULT name(REFCLSID rclsid, LPUNKNOWN *pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID *ppv)
typedef CO_CREATE_INSTANCE(CoCreateInstance_);
CO_CREATE_INSTANCE(CoCreateInstanceStub)
{
return 1;
}
global CoCreateInstance_ *CoCreateInstanceProc = CoCreateInstanceStub;
#define CO_INITIALIZE_EX(name) HRESULT name(LPVOID pvReserved, DWORD dwCoInit)
typedef CO_INITIALIZE_EX(CoInitializeEx_);
CO_INITIALIZE_EX(CoInitializeExStub)
{
return 1;
}
global CoInitializeEx_ *CoInitializeExProc = CoInitializeExStub;
typedef struct W32_SoundOutput W32_SoundOutput;
struct W32_SoundOutput
{
b32 initialized;
IMMDeviceEnumerator *device_enum;
IMMDevice *device;
IAudioClient *audio_client;
IAudioRenderClient *audio_render_client;
REFERENCE_TIME sound_buffer_duration;
u32 buffer_frame_count;
u32 channels;
u32 samples_per_second;
u32 latency_frame_count;
};
internal void
W32_LoadWASAPI(void)
{
HMODULE wasapi_lib = LoadLibraryA("ole32.dll");
if(wasapi_lib)
{
CoCreateInstanceProc = (CoCreateInstance_ *)GetProcAddress(wasapi_lib, "CoCreateInstance");
CoInitializeExProc = (CoInitializeEx_ *)GetProcAddress(wasapi_lib, "CoInitializeEx");
}
else
{
CoCreateInstanceProc = CoCreateInstanceStub;
CoInitializeExProc = CoInitializeExStub;
}
}
internal void
W32_InitWASAPI(W32_SoundOutput *output)
{
CoInitializeExProc(0, COINIT_SPEED_OVER_MEMORY);
REFERENCE_TIME requested_sound_duration = REFTIMES_PER_SEC * 2;
HRESULT result;
result = CoCreateInstanceProc(&CLSID_MMDeviceEnumerator,
0,
CLSCTX_ALL,
&IID_IMMDeviceEnumerator,
(LPVOID *)(&output->device_enum));
if(result == S_OK)
{
output->device_enum->lpVtbl->GetDefaultAudioEndpoint(output->device_enum,
eRender,
eConsole,
&output->device);
if(result == S_OK)
{
result = output->device->lpVtbl->Activate(output->device,
&IID_IAudioClient,
CLSCTX_ALL,
0,
(void **)&output->audio_client);
if(result == S_OK)
{
WAVEFORMATEX *wave_format = 0;
output->audio_client->lpVtbl->GetMixFormat(output->audio_client, &wave_format);
output->samples_per_second = 44100;//wave_format->nSamplesPerSec;
WORD bits_per_sample = sizeof(i16)*8;
WORD block_align = (output->channels * bits_per_sample) / 8;
DWORD average_bytes_per_second = block_align * output->samples_per_second;
WORD cb_size = 0;
WAVEFORMATEX new_wave_format = {
WAVE_FORMAT_PCM,
(WORD)output->channels,
output->samples_per_second,
average_bytes_per_second,
block_align,
bits_per_sample,
cb_size,
};
result = output->audio_client->lpVtbl->Initialize(output->audio_client,
AUDCLNT_SHAREMODE_SHARED,
AUDCLNT_STREAMFLAGS_RATEADJUST | AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM | AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY,
requested_sound_duration,
0,
&new_wave_format,
0);
output->latency_frame_count = output->samples_per_second / SOUND_LATENCY_FPS;
if(result == S_OK)
{
result = output->audio_client->lpVtbl->GetService(output->audio_client,
&IID_IAudioRenderClient,
(void **)&output->audio_render_client);
if(result == S_OK)
{
// NOTE(Ryan): Audio initialization was successful
output->audio_client->lpVtbl->GetBufferSize(output->audio_client, &output->buffer_frame_count);
output->sound_buffer_duration = (REFERENCE_TIME)((f64)REFTIMES_PER_SEC *
output->buffer_frame_count / output->samples_per_second);
output->audio_client->lpVtbl->Start(output->audio_client);
output->initialized = 1;
}
else
{
W32_OutputError("WASAPI Error", "Request for audio render service failed.");
}
}
else
{
W32_OutputError("WASAPI Error",
"Audio client initialization failed.");
}
}
else
{
W32_OutputError("WASAPI Error", "Could not activate audio device.");
}
}
else
{
W32_OutputError("WASAPI Error", "Default audio endpoint was not found.");
}
}
else
{
W32_OutputError("WASAPI Error", "Device enumerator retrieval failed.");
}
}
internal void
W32_CleanUpWASAPI(W32_SoundOutput *output)
{
if(output->initialized)
{
output->audio_client->lpVtbl->Stop(output->audio_client);
output->device_enum->lpVtbl->Release(output->device_enum);
output->device->lpVtbl->Release(output->device);
output->audio_client->lpVtbl->Release(output->audio_client);
output->audio_render_client->lpVtbl->Release(output->audio_render_client);
}
}
internal void
W32_FillSoundBuffer(u32 samples_to_write, f32 *samples, W32_SoundOutput *output)
{
if(samples_to_write)
{
BYTE *data = 0;
DWORD flags = 0;
output->audio_render_client->lpVtbl->GetBuffer(output->audio_render_client, samples_to_write, &data);
if(data)
{
i16 *destination = (i16 *)data;
f32 *source = samples;
for(UINT32 i = 0; i < samples_to_write; ++i)
{
i16 left = (i16)(*source++ * 3000);
i16 right = (i16)(*source++ * 3000);
*destination++ = left;
*destination++ = right;
}
}
output->audio_render_client->lpVtbl->ReleaseBuffer(output->audio_render_client, samples_to_write, flags);
}
}

View File

@ -0,0 +1,86 @@
#define XINPUT_GET_STATE(name) DWORD WINAPI name(DWORD dw_user_index, XINPUT_STATE *p_state)
typedef XINPUT_GET_STATE(XInputGetStateProc);
XINPUT_GET_STATE(XInputGetStateStub)
{
return ERROR_DEVICE_NOT_CONNECTED;
}
global XInputGetStateProc *XInputGetStateProcPtr = XInputGetStateStub;
#define XINPUT_SET_STATE(name) DWORD WINAPI name(DWORD dw_user_index, XINPUT_VIBRATION *p_vibration)
typedef XINPUT_SET_STATE(XInputSetStateProc);
XINPUT_SET_STATE(XInputSetStateStub)
{
return ERROR_DEVICE_NOT_CONNECTED;
}
global XInputSetStateProc *XInputSetStateProcPtr = XInputSetStateStub;
internal void
W32_LoadXInput(void)
{
XInputSetStateProcPtr = XInputSetStateStub;
XInputGetStateProcPtr = XInputGetStateStub;
HMODULE x_input_lib = LoadLibraryA("xinput1_4.dll");
if(!x_input_lib)
{
x_input_lib = LoadLibraryA("xinput9_1_0.dll");
}
if(!x_input_lib)
{
x_input_lib = LoadLibraryA("xinput1_3.dll");
}
if(x_input_lib)
{
XInputGetStateProcPtr = (XInputGetStateProc *)GetProcAddress(x_input_lib, "XInputGetState");
XInputSetStateProcPtr = (XInputSetStateProc *)GetProcAddress(x_input_lib, "XInputSetState");
}
}
internal void
W32_UpdateXInput(void)
{
for(u32 i = 0; i < W32_MAX_GAMEPADS; ++i)
{
if(i < XUSER_MAX_COUNT)
{
XINPUT_STATE controller_state = {0};
if(XInputGetStateProcPtr(0, &controller_state) == ERROR_SUCCESS)
{
// NOTE(rjf): Controller connected.
global_gamepads[i].connected = 1;
XINPUT_GAMEPAD *pad = &controller_state.Gamepad;
for(u32 j = 0; j < W32_MAX_GAMEPADS; ++j)
{
global_gamepads[i].button_states[j] = 0;
}
global_gamepads[i].button_states[GamepadButton_DPadUp] |= !!(pad->wButtons & XINPUT_GAMEPAD_DPAD_UP);
global_gamepads[i].button_states[GamepadButton_DPadDown] |= !!(pad->wButtons & XINPUT_GAMEPAD_DPAD_DOWN);
global_gamepads[i].button_states[GamepadButton_DPadLeft] |= !!(pad->wButtons & XINPUT_GAMEPAD_DPAD_LEFT);
global_gamepads[i].button_states[GamepadButton_DPadRight] |= !!(pad->wButtons & XINPUT_GAMEPAD_DPAD_RIGHT);
global_gamepads[i].button_states[GamepadButton_Start] |= !!(pad->wButtons & XINPUT_GAMEPAD_START);
global_gamepads[i].button_states[GamepadButton_Back] |= !!(pad->wButtons & XINPUT_GAMEPAD_BACK);
global_gamepads[i].button_states[GamepadButton_LeftThumb] |= !!(pad->wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
global_gamepads[i].button_states[GamepadButton_RightThumb] |= !!(pad->wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
global_gamepads[i].button_states[GamepadButton_LeftShoulder] |= !!(pad->wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER);
global_gamepads[i].button_states[GamepadButton_RightShoulder] |= !!(pad->wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER);
global_gamepads[i].button_states[GamepadButton_A] |= !!(pad->wButtons & XINPUT_GAMEPAD_A);
global_gamepads[i].button_states[GamepadButton_B] |= !!(pad->wButtons & XINPUT_GAMEPAD_B);
global_gamepads[i].button_states[GamepadButton_X] |= !!(pad->wButtons & XINPUT_GAMEPAD_X);
global_gamepads[i].button_states[GamepadButton_Y] |= !!(pad->wButtons & XINPUT_GAMEPAD_Y);
global_gamepads[i].joystick_1.x = pad->sThumbLX / 32768.f;
global_gamepads[i].joystick_1.y = pad->sThumbLY / 32768.f;
global_gamepads[i].joystick_2.x = pad->sThumbRX / 32768.f;
global_gamepads[i].joystick_2.y = pad->sThumbRY / 32768.f;
}
else
{
// NOTE(rjf): Controller is not connected
global_gamepads[i].connected = 0;
}
}
}
}

BIN
splink/common.splink Normal file

Binary file not shown.