Explorar o código

Random fixes and additions. Progress with xlib

Aaro Saila hai 3 meses
pai
achega
4ad7ee307b
Modificáronse 10 ficheiros con 341 adicións e 27 borrados
  1. 4 5
      meson.build
  2. 2 0
      src/DynArray.c
  3. 14 14
      src/DynArray.h
  4. 60 3
      src/DynString.c
  5. 12 1
      src/DynString.h
  6. 208 1
      src/main.c
  7. 4 1
      src/pltf/win32/internal.h
  8. 2 1
      src/pltf/win32/pltf.c
  9. 4 0
      src/pltf/win32/win_proc.h
  10. 31 1
      tests/main.c

+ 4 - 5
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(

+ 2 - 0
src/DynArray.c

@@ -1,3 +1,5 @@
 #include "DynArray.h"
+#include "DynString.h"
 
 DYN_ARRAY_IMPL(DynString, DynString);
+DYN_ARRAY_IMPL(char*, charp);

+ 14 - 14
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);
 

+ 60 - 3
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;
+}

+ 12 - 1
src/DynString.h

@@ -1,8 +1,8 @@
 #ifndef DYN_STRING_H_
 #define DYN_STRING_H_
 
-#include <stddef.h>
 #include <stdbool.h>
+#include <stddef.h>
 
 #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_

+ 208 - 1
src/main.c

@@ -114,10 +114,217 @@ int main() {
 
 #ifdef __linux__
 
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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;
 }
 

+ 4 - 1
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

+ 2 - 1
src/pltf/win32/pltf.c

@@ -1,6 +1,7 @@
-#include "pltf/pltf.h"
 #ifdef _WIN32
 
+#include "pltf/pltf.h"
+
 #include <GL/glcorearb.h>
 #include <GL/wglext.h>
 #include <assert.h>

+ 4 - 0
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

+ 31 - 1
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);