#include #ifdef _WIN32 #include #include #include #include #include "pltf/gl_funcs.h" #include "pltf/pltf.h" #include "shader.h" typedef struct { const char* up_msg; const char* down_msg; int up_count; int down_count; } MsgState; void msg_cb(const PltfKeyAction action, void* user_data) { MsgState* state = (MsgState*) user_data; switch (action) { case PLTF_KEY_DOWN: printf("Key: %s Count: %d\n", state->down_msg, state->down_count); state->down_count++; break; case PLTF_KEY_UP: printf("Key: %s Count: %d\n", state->up_msg, state->up_count); state->up_count++; break; default: printf("INVALID PltfKeyAction. Was %d\n", action); } } int main() { pltf_init(); pltf_window_create(); pltf_gl_ctx_create(); pltf_gl_funcs_load(); pltf_gl_ctx_info_print(); pltf_key_callback_set(PLTF_KEY_ESC, pltf_window_close, NULL); MsgState msg_state = { .up_msg = "UP", .down_msg = "DOWN", .up_count = 0, .down_count = 0 }; pltf_key_callback_set(PLTF_KEY_Q, msg_cb, &msg_state); // clang-format off const float triangle_verts[] = { // pos 0.0f, 0.5f, 0.0f, // top -0.25f, -0.25f, 0.0f, // bottom-left 0.25f, -0.25f, 0.0f // bottom-right }; // clang-format on const size_t triangle_vert_count = sizeof(triangle_verts) / sizeof(triangle_verts[0]) / 3; unsigned int triangle_vao = 0; glGenVertexArrays(1, &triangle_vao); glBindVertexArray(triangle_vao); unsigned int triangle_vbo = 0; glGenBuffers(1, &triangle_vbo); glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo); glBufferData( GL_ARRAY_BUFFER, sizeof(triangle_verts), triangle_verts, GL_STATIC_DRAW ); glEnableVertexAttribArray(0); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void*) 0 ); glBindVertexArray(0); const unsigned int shader = shader_create( "shader.vert", "shader.frag" ); glClearColor(0.0f, 0.0f, 0.8f, 1.0f); while (true) { glClear(GL_COLOR_BUFFER_BIT); glUseProgram(shader); glBindVertexArray(triangle_vao); glDrawArrays(GL_TRIANGLES, 0, triangle_vert_count); pltf_swap_buffers(); const int pltf_we = pltf_window_event_handle(); if (pltf_we == PLTF_WE_DESTROY) { break; } } pltf_gl_ctx_destroy(); pltf_window_destroy(); pltf_deinit(); return 0; } #endif // _WIN32 #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(""); } void glx_print_client_info(Display* display) { const char* glx_client_vendor_str = glXGetClientString(display, GLX_VENDOR); printf("Client GLX_VENDOR: %s\n", glx_client_vendor_str); const char* glx_client_version_str = glXGetClientString(display, GLX_VERSION); printf("Client GLX_VERSION: %s\n", glx_client_version_str); const char* glx_client_extensions_str = glXGetClientString(display, GLX_EXTENSIONS); printf("Client GLX_EXTENSIONS: %s\n", glx_client_extensions_str); } void glx_print_server_info(Display* display) { const char* glx_server_vendor_str = glXQueryServerString(display, DefaultScreen(display), GLX_VENDOR); printf("Server GLX_VENDOR: %s\n", glx_server_vendor_str); const char* glx_server_version_str = glXQueryServerString(display, DefaultScreen(display), GLX_VERSION); printf("Server GLX_VERSION: %s\n", glx_server_version_str); const char* glx_server_extensions_str = glXQueryServerString(display, DefaultScreen(display), GLX_EXTENSIONS); printf("Server GLX_EXTENSIONS: %s\n", glx_server_extensions_str); } void print_glxfbconfig(Display* display, const GLXFBConfig* cfg) { int value = 0; #define PRINT_GLXFBCONFIG_VALUE(attrib) \ value = 0; \ if (glXGetFBConfigAttrib(display, *cfg, attrib, &value) != Success) { \ LOG_FATALF("Invalid attrib %s", #attrib); \ } \ printf(" %s: %d\n", #attrib, value) puts("{"); PRINT_GLXFBCONFIG_VALUE(GLX_FBCONFIG_ID); PRINT_GLXFBCONFIG_VALUE(GLX_BUFFER_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_LEVEL); PRINT_GLXFBCONFIG_VALUE(GLX_DOUBLEBUFFER); PRINT_GLXFBCONFIG_VALUE(GLX_STEREO); PRINT_GLXFBCONFIG_VALUE(GLX_AUX_BUFFERS); PRINT_GLXFBCONFIG_VALUE(GLX_RED_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_GREEN_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_BLUE_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_ALPHA_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_DEPTH_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_STENCIL_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_RED_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_GREEN_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_BLUE_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_ACCUM_ALPHA_SIZE); PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLE_BUFFERS); PRINT_GLXFBCONFIG_VALUE(GLX_SAMPLES); PRINT_GLXFBCONFIG_VALUE(GLX_RENDER_TYPE); PRINT_GLXFBCONFIG_VALUE(GLX_DRAWABLE_TYPE); PRINT_GLXFBCONFIG_VALUE(GLX_X_RENDERABLE); PRINT_GLXFBCONFIG_VALUE(GLX_X_VISUAL_TYPE); PRINT_GLXFBCONFIG_VALUE(GLX_CONFIG_CAVEAT); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_TYPE); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_INDEX_VALUE); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_RED_VALUE); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_GREEN_VALUE); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_BLUE_VALUE); PRINT_GLXFBCONFIG_VALUE(GLX_TRANSPARENT_ALPHA_VALUE); PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_WIDTH); PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_HEIGHT); PRINT_GLXFBCONFIG_VALUE(GLX_MAX_PBUFFER_PIXELS); PRINT_GLXFBCONFIG_VALUE(GLX_VISUAL_ID); puts("}"); #undef PRINT_GLXFBCONFIG_VALUE } int main() { 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; } #endif // __linux__