From 4ad7ee307b81ed249cff9c34a1dfa3c5be52515b Mon Sep 17 00:00:00 2001 From: Aaro Saila Date: Sun, 2 Aug 2026 01:59:44 +0300 Subject: [PATCH] Random fixes and additions. Progress with xlib --- meson.build | 9 +- src/DynArray.c | 2 + src/DynArray.h | 28 ++--- src/DynString.c | 63 +++++++++++- src/DynString.h | 13 ++- src/main.c | 209 +++++++++++++++++++++++++++++++++++++- src/pltf/win32/internal.h | 5 +- src/pltf/win32/pltf.c | 3 +- src/pltf/win32/win_proc.h | 4 + tests/main.c | 32 +++++- 10 files changed, 341 insertions(+), 27 deletions(-) diff --git a/meson.build b/meson.build index f1beaac..b4cffb7 100644 --- a/meson.build +++ b/meson.build @@ -8,10 +8,8 @@ pltf_src = [] cargs = [ '-std=c99', - '-Og', - '-g', - '-DBOUNDS_CHECK', '-DSHADERS_PATH="../src/shaders/"', + # '-DDEBUG=1' ] dependencies = [ @@ -21,7 +19,6 @@ link_args = [] test_link_args = [ '-static' ] include_dirs = [ - # 'vendor/', 'src/' ] test_include_dirs = [ @@ -35,7 +32,9 @@ if host_machine.system() == 'linux' ] dependencies += [ - dependency('libglvnd') + dependency('x11'), + dependency('glx'), + dependency('libglvnd'), ] libcmocka = cc.find_library( diff --git a/src/DynArray.c b/src/DynArray.c index ab6e798..23e7e04 100644 --- a/src/DynArray.c +++ b/src/DynArray.c @@ -1,3 +1,5 @@ #include "DynArray.h" +#include "DynString.h" DYN_ARRAY_IMPL(DynString, DynString); +DYN_ARRAY_IMPL(char*, charp); diff --git a/src/DynArray.h b/src/DynArray.h index bac260d..8973781 100644 --- a/src/DynArray.h +++ b/src/DynArray.h @@ -7,11 +7,11 @@ #include "DynString.h" -#ifdef BOUNDS_CHECK +#ifdef DEBUG #include "log.h" -#endif // BOUNDS_CHECK +#endif // DEBUG #define DYN_ARRAY_EXPANDER(macro, type, type_name, func_name) macro(type, DynArray_##type_name, DynArray_##type_name##_##func_name); @@ -43,17 +43,17 @@ // DYN_ARRAY_STRUCT(int); -#define DYN_ARRAY_ALLOC_SIG(type, type_name, func_name) int func_name(type_name* darr) +#define DYN_ARRAY_ALLOC_SIG(type, type_name, func_name) bool func_name(type_name* darr) #define DYN_ARRAY_ALLOC(type, type_name, func_name) \ DYN_ARRAY_ALLOC_SIG(type, type_name, func_name) { \ darr->data = (type*) calloc(1, sizeof(type)); \ if (darr->data == NULL) { \ - return -1; \ + return false; \ } \ darr->len = 0; \ darr->capacity = 1; \ - return 1; \ + return true; \ } #define DYN_ARRAY_IS_NULL_SIG(type, type_name, func_name) bool func_name(const type_name* darr) @@ -83,25 +83,25 @@ #define DYN_ARRAY_AT_SIG(type, type_name, func_name) type* func_name(type_name* darr, const size_t i) -#ifdef BOUNDS_CHECK +#ifdef DEBUG -#define DYN_ARRAY_AT(type, type_name, func_name) \ - DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ - if (i < 0 || i > darr->len) { \ +#define DYN_ARRAY_AT(type, type_name, func_name) \ + DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ + if (i < 0 || i > darr->len) { \ LOG_FATALF(#func_name " out-of-bounds. i: %zu, len: %zu", i, darr->len); \ - } \ - \ - return &darr->data[i]; \ + } \ + \ + return darr->data + i; \ } #else #define DYN_ARRAY_AT(type, type_name, func_name) \ DYN_ARRAY_AT_SIG(type, type_name, func_name) { \ - return darr->data[i]; \ + return darr->data + i; \ } -#endif // BOUNDS_CHECK +#endif // DEBUG // DYN_ARRAY_PUSH_BACK(int, DynArray_int, DynArray_int_push_back); diff --git a/src/DynString.c b/src/DynString.c index 76ad6c3..5fc8c30 100644 --- a/src/DynString.c +++ b/src/DynString.c @@ -8,9 +8,9 @@ DynString DynString_alloc(const char* str, const size_t len) { DynString dstr = { - .data = (char*) malloc(sizeof(char) * len + 1), + .data = (char*) malloc(sizeof(char) * (len + 1)), .len = len, - .capacity = len + .capacity = len + 1 }; if (dstr.data == NULL) { LOG_FATAL("Ran out of memory"); @@ -74,13 +74,33 @@ bool DynString_equal_c_str(const DynString* s1, const char* s2) { return true; } +bool DynString_equal_next_chars_c_str( + const DynString* dstr, + const char* str, + const size_t str_len, + size_t s +) { + if (dstr->len < s || dstr->len < s + str_len) { + return false; + } + + const size_t e = s + str_len; + for (size_t i = 0; s < e; s++, i++) { + if (dstr->data[s] != str[i]) { + return false; + } + } + + return true; +} + void DynString_reserve(DynString* dstr, const size_t new_capacity) { if (dstr->capacity >= new_capacity) { return; } errno = 0; - dstr->data = realloc(dstr->data, new_capacity); + dstr->data = (char*) realloc(dstr->data, sizeof(char) * new_capacity); if (errno != 0) { LOG_FATAL("Ran out of memory"); } @@ -112,3 +132,40 @@ DynString DynString_alloc_concat_c_strs( DynString_concat_c_str(&dstr, s2, s2_len); return dstr; } + +DynString* DynString_split( + const DynString* dstr, + const char* delim, + size_t* ret_len +) { + DynString* arr = (DynString*) malloc(0); + if (arr == NULL) { + LOG_FATAL("malloc failed"); + } + *ret_len = 0; + DynString elem = DynString_alloc("", 0); + size_t delim_len = strlen(delim); + for (size_t i = 0; i < dstr->len; i++) { + if (DynString_equal_next_chars_c_str(dstr, delim, delim_len, i)) { + arr = realloc(arr, sizeof(DynString) * (*ret_len + 1)); + if (arr == NULL) { + LOG_FATAL("realloc failed"); + } + arr[*ret_len] = elem; + *ret_len += 1; + elem = DynString_alloc("", 0); + i += delim_len - 1; + } else { + DynString_concat_c_str(&elem, dstr->data + i, 1); + } + } + + arr = realloc(arr, sizeof(DynString) * (*ret_len + 1)); + if (arr == NULL) { + LOG_FATAL("realloc failed"); + } + arr[*ret_len] = elem; + *ret_len += 1; + + return arr; +} diff --git a/src/DynString.h b/src/DynString.h index 4d54d78..2c47e64 100644 --- a/src/DynString.h +++ b/src/DynString.h @@ -1,8 +1,8 @@ #ifndef DYN_STRING_H_ #define DYN_STRING_H_ -#include #include +#include #define DYN_STRING_FMT(dstr) (int) (dstr).len, (dstr).data @@ -18,6 +18,12 @@ bool DynString_is_null(const DynString* dstr); const char* DynString_c_str(const DynString* dstr); bool DynString_equal(const DynString* s1, const DynString* s2); bool DynString_equal_c_str(const DynString* s1, const char* s2); +bool DynString_equal_next_chars_c_str( + const DynString* dstr, + const char* str, + const size_t str_len, + const size_t s +); void DynString_concat_c_str( DynString* dstr, const char* str, @@ -29,5 +35,10 @@ DynString DynString_alloc_concat_c_strs( const char* s2, const size_t s2_len ); +DynString* DynString_split( + const DynString* dstr, + const char* delim, + size_t* arr_len +); #endif // DYN_STRING_H_ diff --git a/src/main.c b/src/main.c index 9b074b0..9cc9407 100644 --- a/src/main.c +++ b/src/main.c @@ -114,10 +114,217 @@ int main() { #ifdef __linux__ +#include +#include +#include +#include #include +#include +#include +#include + +#include "log.h" +#include "DynString.h" + +void print_pixmap_format_values(const XPixmapFormatValues* px) { + puts("{"); + printf(" depth : %d\n", px->depth); + printf(" bits_per_pixel: %d\n", px->bits_per_pixel); + printf(" scanline_pad : %d\n", px->scanline_pad); + puts("}"); +} + +void print_visual_info(const XVisualInfo* vi) { + puts("{"); + printf(" visual : %p\n", vi->visual); + printf(" visualid : %lu\n", vi->visualid); + printf(" screen : %d\n", vi->screen); + printf(" depth : %u\n", vi->depth); + printf(" class : %d\n", vi->class); + printf(" red_mask : %lu\n", vi->red_mask); + printf(" green_mask : %lu\n", vi->green_mask); + printf(" blue_mask : %lu\n", vi->blue_mask); + printf(" colormap_size: %d\n", vi->colormap_size); + printf(" bits_per_rgb : %d\n", vi->bits_per_rgb); + puts("}"); +} + +void print_info(Display* display) { + const int screen_num = DefaultScreen(display); + Colormap color_map = DefaultColormap(display, screen_num); + int default_depth = DefaultDepth(display, screen_num); + int depths_count = 0; + int* depths = XListDepths(display, screen_num, &depths_count); + if (depths == NULL) { + LOG_FATAL("XListDepths failed"); + } + int cells = DisplayCells(display, screen_num); + int color_depth = DisplayPlanes(display, screen_num); + char* display_string = DisplayString(display); + int queue_length = QLength(display); + int screen_count = ScreenCount(display); + char* server_vendor = ServerVendor(display); + int vendor_release = VendorRelease(display); + + printf("DefaultScreen : %d\n", screen_num); + printf("DefaultColormap: %lu\n", color_map); + printf("DefaultDepth : %d\n", default_depth); + printf("XListDepths : "); + for (int i = 0; i < depths_count; i++) { + printf("%d ", depths[i]); + } + puts(""); + printf("DisplayCells : %d\n", cells); + printf("DisplayPlanes : %d\n", color_depth); + printf("DisplayString : %s\n", display_string); + printf("QLength : %d\n", queue_length); + printf("ScreenCount : %d\n", screen_count); + printf("ServerVendor : %s\n", server_vendor); + printf("VendorRelease : %d\n", vendor_release); + + XFree(depths); + + int d_supported_pixmap_formats_n = 0; + XPixmapFormatValues* d_supported_pixmap_formats = XListPixmapFormats(display, &d_supported_pixmap_formats_n); + if (d_supported_pixmap_formats == NULL) { + LOG_FATAL("XListPixmapFormats failed"); + } + int img_byte_order = ImageByteOrder(display); + int bitmap_unit = XBitmapUnit(display); + int bitmap_bit_order = BitmapBitOrder(display); + int bitmap_pad = BitmapPad(display); + int s_height_px = DisplayHeight(display, screen_num); + int s_height_mm = DisplayHeightMM(display, screen_num); + int s_width_px = DisplayWidth(display, screen_num); + int s_width_mm = DisplayWidthMM(display, screen_num); + + puts(""); + printf("XListPixmapFormats (%d):\n", d_supported_pixmap_formats_n); + for (int i = 0; i < d_supported_pixmap_formats_n; i++) { + print_pixmap_format_values(d_supported_pixmap_formats + i); + } + printf("ImageByteOrder : %s\n", img_byte_order == LSBFirst ? "LSBFirst" : "MSBFirst"); + printf("XBitmapUnit : %d\n", bitmap_unit); + printf("BitmapBitOrder : %s\n", bitmap_bit_order == LSBFirst ? "LSBFirst" : "MSBFirst"); + printf("BitmapPad : %d\n", bitmap_pad); + printf("DisplayHeight (DefaultScreen): %d\n", s_height_px); + printf("DisplayHeightMM (DefaultScreen): %d\n", s_height_mm); + printf("DisplayWidth (DefaultScreen): %d\n", s_width_px); + printf("DisplayWidthMM (DefaultScreen): %d\n", s_width_mm); + + XFree(d_supported_pixmap_formats); + + Screen* screen = ScreenOfDisplay(display, screen_num); + unsigned long s_black_pixel = BlackPixelOfScreen(screen); + unsigned long s_white_pixel = WhitePixelOfScreen(screen); + int s_cells = CellsOfScreen(screen); + int s_default_depth = DefaultDepthOfScreen(screen); + int does_backing_store = DoesBackingStore(screen); + bool does_save_unders = DoesSaveUnders(screen); + int s_max_colormaps = MaxCmapsOfScreen(screen); + int s_min_colormaps = MinCmapsOfScreen(screen); + int s_planes_n = PlanesOfScreen(screen); + + puts("\n(Default Screen)"); + printf("BlackPixelOfScreen : %lu\n", s_black_pixel); + printf("WhitePixelOfScreen : %lu\n", s_white_pixel); + printf("CellsOfScreen : %d\n", s_cells); + printf("DefaultDepthOfScreen: %d\n", s_default_depth); + printf("DoesBackingStore : %s\n", does_backing_store == WhenMapped ? "WhenMapped" : (does_backing_store == NotUseful ? "NotUseful" : "Always")); + printf("DoesSaveUnders : %s\n", does_save_unders ? "true" : "false"); + printf("MaxCmapsOfScreen : %d\n", s_max_colormaps); + printf("MinCmapsOfScreen : %d\n", s_min_colormaps); + printf("PlanesOfScreen : %d\n", s_planes_n); + puts(""); +} int main() { - printf("Hello linux\n"); + Display* display = XOpenDisplay(NULL); + if (display == NULL) { + LOG_FATAL("XOpenDisplay failed."); + } + + int err_base = 0; + int event_base = 0; + if (!glXQueryExtension(display, &err_base, &event_base)) { + LOG_FATALF( + "GLX extension not supported. err_base: %d, event_base: %d", + err_base, + event_base + ); + } + + int glx_major = 0; + int glx_minor = 0; + if (glXQueryVersion(display, &glx_major, &glx_minor)) { + printf("GLX Version %d.%d\n", glx_major, glx_minor); + if (glx_minor < 1) { + LOG_FATAL("GLX Version must be at least 1.1"); + } + } else { + LOG_ERROR("glXQueryVersion failed"); + } + + const char* glx_extensions_c_str = glXQueryExtensionsString(display, DefaultScreen(display)); + printf("glx_extensions_c_str: %s\n", glx_extensions_c_str); + DynString glx_extensions_str = DynString_alloc(glx_extensions_c_str, strlen(glx_extensions_c_str)); + size_t glx_ext_n = 0; + DynString* glx_extensions = DynString_split(&glx_extensions_str, " ", &glx_ext_n); + + printf("GLX extensions:\n"); + for (size_t i = 0; i < glx_ext_n; i++) { + printf(" %s\n", DynString_c_str(glx_extensions + i)); + } + + + // XVisualInfo visual_info = { 0 }; + // Status xstatus = XMatchVisualInfo(display, DefaultScreen(display), 32, TrueColor, &visual_info); + // if (xstatus == 0) { + // LOG_FATAL("XMatchVisualInfo failed"); + // } + // printf("Matched visual:\n"); + // print_visual_info(&visual_info); + // + // Cursor cursor = XCreateFontCursor(display, XC_iron_cross); + // XSetWindowAttributes win_attr = { + // .background_pixel = 0x00000000, + // .border_pixel = 0xFF000000, + // .colormap = XCreateColormap(display, DefaultRootWindow(display), visual_info.visual, AllocNone), + // .event_mask = Expose, + // .backing_store = WhenMapped, + // .cursor = cursor, + // }; + // + // Window window = XCreateWindow( + // display, + // DefaultRootWindow(display), + // 0, + // 0, + // PLTF_DEFAULT_WINDOW_WIDTH, + // PLTF_DEFAULT_WINDOW_HEIGHT, + // 0, + // visual_info.depth, + // InputOutput, + // visual_info.visual, + // CWBackPixel | + // CWBorderPixel | + // CWColormap | + // CWEventMask | + // CWBackingStore | + // CWCursor, + // &win_attr + // ); + // + // XMapWindow(display, window); + // + // XFlush(display); + // + // pause(); + // + // XDestroyWindow(display, window); + + XCloseDisplay(display); + return 0; } diff --git a/src/pltf/win32/internal.h b/src/pltf/win32/internal.h index c6259c5..78c26bf 100644 --- a/src/pltf/win32/internal.h +++ b/src/pltf/win32/internal.h @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #ifndef PLTF_WIN32_INTERNAL_H_ #define PLTF_WIN32_INTERNAL_H_ @@ -31,7 +33,8 @@ extern PltfWin32State pltf_state; extern HMODULE opengl_module; bool pltf_has_wgl_extension(const char* name); -// bool pltf_has_wgl_extension_c_str(const char* name); unsigned int vk_to_pltf_key(WPARAM key); #endif // PLTF_WIN32_INTERNAL_H_ + +#endif // _WIN32 diff --git a/src/pltf/win32/pltf.c b/src/pltf/win32/pltf.c index 486a08e..cdcedc6 100644 --- a/src/pltf/win32/pltf.c +++ b/src/pltf/win32/pltf.c @@ -1,6 +1,7 @@ -#include "pltf/pltf.h" #ifdef _WIN32 +#include "pltf/pltf.h" + #include #include #include diff --git a/src/pltf/win32/win_proc.h b/src/pltf/win32/win_proc.h index e2ba409..e81f845 100644 --- a/src/pltf/win32/win_proc.h +++ b/src/pltf/win32/win_proc.h @@ -1,3 +1,5 @@ +#ifdef _WIN32 + #ifndef WIN_PROC_H_ #define WIN_PROC_H_ @@ -6,3 +8,5 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); #endif // WIN_PROC_H_ + +#endif // _WIN32 diff --git a/tests/main.c b/tests/main.c index 8c5c094..8e75836 100644 --- a/tests/main.c +++ b/tests/main.c @@ -63,6 +63,24 @@ void test_DynString_equal_c_str(void** state) { DynString_free(&s1); } +void test_DynString_equal_next_chars_c_str(void** state) { + DynString dstr = DynString_alloc("Hello", strlen("Hello")); + char* str = "ll"; + size_t str_len = strlen(str); + assert_true(DynString_equal_next_chars_c_str(&dstr, str, str_len, 2)); + assert_false(DynString_equal_next_chars_c_str(&dstr, str, str_len, 1)); + DynString_free(&dstr); +} + +void test_DynString_reserve(void** state) { + char* str = "aa"; + size_t str_len = strlen(str); + DynString dstr = DynString_alloc(str, str_len); + assert_true(dstr.len == str_len); + assert_true(dstr.capacity == str_len + 1); + assert_memory_equal(dstr.data, (void*) str, str_len + 1); +} + void test_DynString_concat_c_str(void** state) { const char* dstr_c_str = "Hello"; const char* c_str = " World"; @@ -71,7 +89,7 @@ void test_DynString_concat_c_str(void** state) { DynString dstr = DynString_alloc(dstr_c_str, strlen("Hello")); DynString_concat_c_str(&dstr, c_str, strlen(c_str)); - assert_memory_equal(dstr.data, "Hello World", strlen("Hello World")); + assert_memory_equal(dstr.data, (void*) "Hello World\0", strlen("Hello World") + 1); assert_true(dstr.len == combined_length); assert_true(dstr.capacity == combined_length + 1); @@ -89,14 +107,26 @@ void test_DynString_c_str(void** state) { assert_string_equal("Hello World", DynString_c_str(&dstr)); } +void test_DynString_split(void** state) { + DynString dstr = DynString_alloc("Hello World", strlen("Hello World")); + size_t arr_len = 0; + DynString* arr = DynString_split(&dstr, " ", &arr_len); + assert_true(arr_len == 2); + assert_string_equal(DynString_c_str(arr), "Hello"); + assert_string_equal(DynString_c_str(arr + 1), "World"); +} + int main() { const struct CMUnitTest tests[] = { cmocka_unit_test(test_DynString_alloc), cmocka_unit_test(test_DynString_free), cmocka_unit_test(test_DynString_equal), cmocka_unit_test(test_DynString_equal_c_str), + cmocka_unit_test(test_DynString_equal_next_chars_c_str), + cmocka_unit_test(test_DynString_reserve), cmocka_unit_test(test_DynString_concat_c_str), cmocka_unit_test(test_DynString_c_str), + cmocka_unit_test(test_DynString_split), }; return cmocka_run_group_tests(tests, NULL, NULL);