Begin move to SDL
This commit is contained in:
@@ -27,12 +27,34 @@ struct Library {
|
|||||||
Array<S8_String> objects;
|
Array<S8_String> objects;
|
||||||
Array<S8_String> include_paths;
|
Array<S8_String> include_paths;
|
||||||
Array<S8_String> defines;
|
Array<S8_String> defines;
|
||||||
|
Array<S8_String> link;
|
||||||
};
|
};
|
||||||
|
|
||||||
Library PrepareSDL() {
|
Library PrepareSDL() {
|
||||||
|
Library l = {};
|
||||||
|
l.include_paths.add("../src/external/SDL/include");
|
||||||
|
l.objects.add("../src/external/SDL/VisualC/static_x64/Release/SDL3.lib");
|
||||||
|
l.link.add("/SUBSYSTEM:WINDOWS");
|
||||||
|
l.link.add("opengl32.lib");
|
||||||
|
l.link.add("imm32.lib");
|
||||||
|
l.link.add("gdi32.lib");
|
||||||
|
l.link.add("winmm.lib");
|
||||||
|
l.link.add("shell32.lib");
|
||||||
|
l.link.add("user32.lib");
|
||||||
|
l.link.add("advapi32.lib");
|
||||||
|
l.link.add("Setupapi.lib");
|
||||||
|
l.link.add("ole32.lib");
|
||||||
|
l.link.add("oleaut32.lib");
|
||||||
|
l.link.add("Version.lib");
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Library PrepareSDLDynamic() {
|
||||||
Library l = {};
|
Library l = {};
|
||||||
l.include_paths.add("../src/external/SDL/include");
|
l.include_paths.add("../src/external/SDL/include");
|
||||||
l.objects.add("../src/external/SDL/VisualC/x64/Release/SDL3.lib");
|
l.objects.add("../src/external/SDL/VisualC/x64/Release/SDL3.lib");
|
||||||
|
l.link.add("/SUBSYSTEM:WINDOWS");
|
||||||
|
OS_CopyFile("../src/external/SDL/VisualC/x64/Release/SDL3.dll", "./SDL3.dll", false);
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +99,7 @@ Library PrepareLua() {
|
|||||||
Library PrepareGlad() {
|
Library PrepareGlad() {
|
||||||
Library l = {};
|
Library l = {};
|
||||||
l.sources.add("../src/external/glad/glad.c");
|
l.sources.add("../src/external/glad/glad.c");
|
||||||
l.include_paths.add("../src/external/glad");
|
l.include_paths.add("../src/external/glad/");
|
||||||
l.objects.add("glad.obj");
|
l.objects.add("glad.obj");
|
||||||
if (!OS_FileExists(l.objects[0])) {
|
if (!OS_FileExists(l.objects[0])) {
|
||||||
Array<S8_String> cmd = {};
|
Array<S8_String> cmd = {};
|
||||||
@@ -101,6 +123,7 @@ int CompileTextEditor() {
|
|||||||
cmd.add("cl.exe");
|
cmd.add("cl.exe");
|
||||||
cmd.add("-Fe:te.exe");
|
cmd.add("-Fe:te.exe");
|
||||||
cmd.add("-Fd:te.pdb");
|
cmd.add("-Fd:te.pdb");
|
||||||
|
cmd.add("-I ../src");
|
||||||
AddCommonFlags(&cmd);
|
AddCommonFlags(&cmd);
|
||||||
For2(lib, libs) For(lib.defines) cmd.add(it);
|
For2(lib, libs) For(lib.defines) cmd.add(it);
|
||||||
|
|
||||||
@@ -122,10 +145,44 @@ int CompileTextEditor() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CompileNewPlatform() {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
Array<Library> libs = {};
|
||||||
|
libs.add(PrepareGlad());
|
||||||
|
libs.add(PrepareLua());
|
||||||
|
libs.add(PrepareSDLDynamic());
|
||||||
|
|
||||||
|
Array<S8_String> cmd = {};
|
||||||
|
cmd.add("cl.exe");
|
||||||
|
cmd.add("-Fe:te.exe");
|
||||||
|
cmd.add("-Fd:te.pdb");
|
||||||
|
cmd.add("-I ../src");
|
||||||
|
AddCommonFlags(&cmd);
|
||||||
|
For2(lib, libs) For(lib.defines) cmd.add(it);
|
||||||
|
|
||||||
|
cmd.add("../src/new_platform/new_platform.cpp");
|
||||||
|
cmd.add("../src/basic/win32.cpp");
|
||||||
|
|
||||||
|
For2(lib, libs) For(lib.include_paths) cmd.add(Fmt("-I %.*s", S8_Expand(it)));
|
||||||
|
|
||||||
|
cmd.add("/link");
|
||||||
|
cmd.add("/incremental:no");
|
||||||
|
For2(lib, libs) For(lib.link) cmd.add(it);
|
||||||
|
For(libs) For2(o, it.objects) cmd.add(o);
|
||||||
|
|
||||||
|
OS_DeleteFile("te.pdb");
|
||||||
|
// For(cmd) IO_Printf("%.*s\n", S8_Expand(it));
|
||||||
|
|
||||||
|
result += Run(cmd);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
MA_InitScratch();
|
MA_InitScratch();
|
||||||
SRC_InitCache(Perm, "te.cache");
|
SRC_InitCache(Perm, "te.cache");
|
||||||
int result = CompileTextEditor();
|
// int result = CompileTextEditor();
|
||||||
|
int result = CompileNewPlatform();
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
OS_DeleteFile("te.cache");
|
OS_DeleteFile("te.cache");
|
||||||
|
|||||||
149
src/new_platform/font.cpp
Normal file
149
src/new_platform/font.cpp
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
struct Glyph {
|
||||||
|
Vec2I size;
|
||||||
|
Vec2I offset;
|
||||||
|
int32_t xadvance;
|
||||||
|
int32_t left_side_bearing;
|
||||||
|
Rect2 atlas_bounding_box;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Font {
|
||||||
|
Array<Glyph> glyphs;
|
||||||
|
uint32_t first_char, last_char;
|
||||||
|
uint32_t texture_id;
|
||||||
|
|
||||||
|
int32_t size;
|
||||||
|
int32_t descent;
|
||||||
|
int32_t ascent;
|
||||||
|
int32_t line_gap;
|
||||||
|
|
||||||
|
Rect2 white_texture_bounding_box;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Atlas {
|
||||||
|
uint8_t *bitmap;
|
||||||
|
Vec2I size;
|
||||||
|
Vec2 inverse_size;
|
||||||
|
int xcursor;
|
||||||
|
int ycursor;
|
||||||
|
|
||||||
|
int32_t biggest_height;
|
||||||
|
Rect2 white_texture_bounding_box;
|
||||||
|
uint32_t texture_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
Atlas CreateAtlas(Allocator allocator, Vec2I size) {
|
||||||
|
Atlas result = {};
|
||||||
|
result.size = size;
|
||||||
|
result.inverse_size.x = 1.f / (float)result.size.x;
|
||||||
|
result.inverse_size.y = 1.f / (float)result.size.y;
|
||||||
|
result.bitmap = AllocArray(allocator, uint8_t, size.x * size.y);
|
||||||
|
|
||||||
|
// Add a whitebox first for rectangle rendering
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
uint8_t *dst = result.bitmap + x + y * result.size.x;
|
||||||
|
*dst = 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.white_texture_bounding_box = {2.f * result.inverse_size.x, 2.f / (float)result.size.y, 14.f * result.inverse_size.x, 14.f / (float)result.size.y};
|
||||||
|
result.xcursor += 16;
|
||||||
|
result.biggest_height += 16;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect2 PackBitmap(Atlas *atlas, uint8_t *bitmap, int width, int height) {
|
||||||
|
// Packing into a texture atlas
|
||||||
|
// @Inefficient The algorithm is a simplest thing I had in mind, first we advance
|
||||||
|
// through the atlas in X packing consecutive glyphs. After we get to the end of the row
|
||||||
|
// we advance to the next row by the Y size of the biggest packed glyph. If we get to the
|
||||||
|
// end of atlas and fail to pack everything the app panics.
|
||||||
|
|
||||||
|
int spacing = 4;
|
||||||
|
if (atlas->xcursor + width > atlas->size.x) {
|
||||||
|
if (atlas->ycursor + height < atlas->size.y) {
|
||||||
|
atlas->xcursor = 0;
|
||||||
|
atlas->ycursor += atlas->biggest_height + spacing;
|
||||||
|
} else {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Font loading error!", "Error while packing a font into atlas. Atlas size for this font scale is a bit too small", NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *src = bitmap;
|
||||||
|
for (int y = atlas->ycursor; y < atlas->ycursor + height; y += 1) {
|
||||||
|
for (int x = atlas->xcursor; x < atlas->xcursor + width; x += 1) {
|
||||||
|
uint8_t *dst = atlas->bitmap + x + y * atlas->size.x;
|
||||||
|
*dst = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec2 size = {(float)width * atlas->inverse_size.x, (float)height * atlas->inverse_size.y};
|
||||||
|
Vec2 pos = {(float)atlas->xcursor * atlas->inverse_size.x, (float)atlas->ycursor * atlas->inverse_size.y};
|
||||||
|
Rect2 result = {pos.x, pos.y, pos.x + size.x, pos.y + size.y};
|
||||||
|
|
||||||
|
atlas->xcursor += width + spacing;
|
||||||
|
if (height > atlas->biggest_height) {
|
||||||
|
atlas->biggest_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font CreateFont(Atlas *atlas, int32_t size, String path) {
|
||||||
|
Scratch scratch;
|
||||||
|
Font result = {};
|
||||||
|
|
||||||
|
String file = ReadFile(scratch, path);
|
||||||
|
if (file.len == 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
stbtt_fontinfo stb_font;
|
||||||
|
int success = stbtt_InitFont(&stb_font, (const unsigned char *)file.data, 0);
|
||||||
|
if (!success) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float scale = stbtt_ScaleForPixelHeight(&stb_font, (float)result.size);
|
||||||
|
float em_scale = stbtt_ScaleForMappingEmToPixels(&stb_font, (float)result.size);
|
||||||
|
|
||||||
|
int ascent, descent, line_gap;
|
||||||
|
stbtt_GetFontVMetrics(&stb_font, &ascent, &descent, &line_gap);
|
||||||
|
result.ascent = (int32_t)((float)ascent * scale);
|
||||||
|
result.descent = (int32_t)((float)descent * scale);
|
||||||
|
result.line_gap = (int32_t)((float)line_gap * scale);
|
||||||
|
result.size = size;
|
||||||
|
result.first_char = ' ';
|
||||||
|
result.last_char = '~';
|
||||||
|
result.white_texture_bounding_box = atlas->white_texture_bounding_box;
|
||||||
|
|
||||||
|
for (uint32_t ascii_symbol = result.first_char; ascii_symbol <= result.last_char; ascii_symbol++) {
|
||||||
|
int width, height, xoff, yoff;
|
||||||
|
uint8_t *bitmap = (uint8_t *)stbtt_GetCodepointBitmap(&stb_font, 0, scale, ascii_symbol, &width, &height, &xoff, &yoff);
|
||||||
|
defer { stbtt_FreeBitmap(bitmap, 0); };
|
||||||
|
|
||||||
|
int xadvance, left_side_bearing;
|
||||||
|
stbtt_GetCodepointHMetrics(&stb_font, ascii_symbol, &xadvance, &left_side_bearing);
|
||||||
|
|
||||||
|
Glyph glyph = {};
|
||||||
|
glyph.atlas_bounding_box = PackBitmap(atlas, bitmap, width, height);
|
||||||
|
glyph.size = {width, height};
|
||||||
|
glyph.offset = {xoff, yoff};
|
||||||
|
glyph.xadvance = (int32_t)((float)xadvance * scale);
|
||||||
|
glyph.left_side_bearing = (int32_t)((float)left_side_bearing * scale);
|
||||||
|
Add(&result.glyphs, glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Glyph *GetGlyph(Font *font, uint32_t codepoint) {
|
||||||
|
bool is_in_range = codepoint >= font->first_char && codepoint <= font->last_char;
|
||||||
|
if (is_in_range) {
|
||||||
|
uint32_t index = codepoint - font->first_char;
|
||||||
|
return &font->glyphs[index];
|
||||||
|
} else {
|
||||||
|
uint32_t index = '?' - font->first_char;
|
||||||
|
return &font->glyphs[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
129
src/new_platform/new_platform.cpp
Normal file
129
src/new_platform/new_platform.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#define BASIC_IMPL
|
||||||
|
#include "basic/basic.h"
|
||||||
|
#include "basic/filesystem.h"
|
||||||
|
|
||||||
|
#include "SDL3/SDL.h"
|
||||||
|
#include "external/glad/glad.h"
|
||||||
|
#include "external/stb_truetype.h"
|
||||||
|
#include "external/stb_truetype.c"
|
||||||
|
|
||||||
|
#include "basic/math_int.cpp"
|
||||||
|
#include "basic/math.cpp"
|
||||||
|
#include "font.cpp"
|
||||||
|
|
||||||
|
bool AppIsRunning = true;
|
||||||
|
|
||||||
|
void ProcessSDLEvent(SDL_Event *event) {
|
||||||
|
switch (event->type) {
|
||||||
|
case SDL_EVENT_QUIT: AppIsRunning = false; return;
|
||||||
|
case SDL_EVENT_KEY_DOWN: {
|
||||||
|
SDL_KeyboardEvent &key = event->key;
|
||||||
|
bool shift = key.mod & SDL_KMOD_SHIFT;
|
||||||
|
bool ctrl = key.mod & SDL_KMOD_CTRL;
|
||||||
|
bool alt = key.mod & SDL_KMOD_ALT;
|
||||||
|
bool super = key.mod & SDL_KMOD_GUI;
|
||||||
|
|
||||||
|
if (key.key == SDLK_F5) {
|
||||||
|
AppIsRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_KEY_UP: {
|
||||||
|
SDL_KeyboardEvent &key = event->key;
|
||||||
|
bool shift = key.mod & SDL_KMOD_SHIFT;
|
||||||
|
bool ctrl = key.mod & SDL_KMOD_CTRL;
|
||||||
|
bool alt = key.mod & SDL_KMOD_ALT;
|
||||||
|
bool super = key.mod & SDL_KMOD_GUI;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_TEXT_INPUT: {
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_MOTION: {
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
|
} break;
|
||||||
|
case SDL_EVENT_MOUSE_WHEEL: {
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *user) {
|
||||||
|
printf("%s", message);
|
||||||
|
if (severity == GL_DEBUG_SEVERITY_HIGH || severity == GL_DEBUG_SEVERITY_MEDIUM) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "OpenGL error", message, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
int WinMain(void *hInstance, void *hPrevInstance, const char *lpCmdLine, int nShowCmd)
|
||||||
|
#else
|
||||||
|
int main()
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
InitScratch();
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO) == -1) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't initialize SDL!", SDL_GetError(), NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *glsl_version = "#version 130";
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||||
|
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
||||||
|
Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
|
||||||
|
SDL_Window *window = SDL_CreateWindow("Text editor", 640, 480, window_flags);
|
||||||
|
if (window == NULL) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't create window!", SDL_GetError(), NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
||||||
|
SDL_GL_MakeCurrent(window, gl_context);
|
||||||
|
SDL_GL_SetSwapInterval(1); // Enable vsync
|
||||||
|
SDL_ShowWindow(window);
|
||||||
|
|
||||||
|
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) {
|
||||||
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Couldn't load opengl!", SDL_GetError(), NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDebugMessageCallback(&GLDebugCallback, NULL);
|
||||||
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
|
||||||
|
Arena Perm = {};
|
||||||
|
InitArena(&Perm);
|
||||||
|
Atlas atlas = CreateAtlas(Perm, {1024, 1024});
|
||||||
|
Font font = CreateFont(&atlas, 16, "c:\\Windows\\Fonts\\consola.ttf");
|
||||||
|
{
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &atlas.texture_id);
|
||||||
|
glTextureParameteri(atlas.texture_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTextureParameteri(atlas.texture_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTextureParameteri(atlas.texture_id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTextureStorage2D(atlas.texture_id, 1, GL_R8, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y);
|
||||||
|
glTextureSubImage2D(atlas.texture_id, 0, 0, 0, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y, GL_RED, GL_UNSIGNED_BYTE, atlas.bitmap);
|
||||||
|
}
|
||||||
|
font.texture_id = atlas.texture_id;
|
||||||
|
|
||||||
|
while (AppIsRunning) {
|
||||||
|
glClearColor(255, 255, 255, 255);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_WaitEvent(&event);
|
||||||
|
ProcessSDLEvent(&event);
|
||||||
|
SDL_GL_SwapWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
SDL_Quit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#define BASIC_IMPL
|
#define BASIC_IMPL
|
||||||
#include "../basic/basic.h"
|
#include "basic/basic.h"
|
||||||
#include "../basic/filesystem.h"
|
#include "basic/filesystem.h"
|
||||||
#include "../profiler/profiler.cpp"
|
#include "basic/string16.cpp"
|
||||||
|
#include "basic/math_int.cpp"
|
||||||
|
#include "basic/math.cpp"
|
||||||
|
#include "profiler/profiler.cpp"
|
||||||
#include "new_basic.cpp"
|
#include "new_basic.cpp"
|
||||||
#include "string16.cpp"
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "math_int.cpp"
|
|
||||||
#include "math.cpp"
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "colors.cpp"
|
#include "colors.cpp"
|
||||||
#include "raylib_utils.cpp"
|
#include "raylib_utils.cpp"
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ Int FontLineSpacing;
|
|||||||
Int FontCharSpacing;
|
Int FontCharSpacing;
|
||||||
|
|
||||||
Int FrameID;
|
Int FrameID;
|
||||||
|
|
||||||
String WorkingDir;
|
String WorkingDir;
|
||||||
|
|
||||||
String16 EvalString(Allocator allocator, String16 string16);
|
String16 EvalString(Allocator allocator, String16 string16);
|
||||||
|
|||||||
Reference in New Issue
Block a user