Advertisement
Guest User

Untitled

a guest
Mar 14th, 2018
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 34.99 KB | None | 0 0
  1. //#define COMPILE_ON_WIN
  2.  
  3. #define fpl_internal static
  4. #define fpl_constant constexpr
  5. #define fpl_inline inline
  6.  
  7. #define FPL_ARRAYCOUNT(arr) (sizeof(arr) / sizeof((arr)[0]))
  8.  
  9. #include <assert.h>
  10. #define FPL_ASSERT(exp) assert(exp)
  11.  
  12. #include <stdint.h> // uint32_t, int64_t etc.
  13. #include <stdio.h> // fprintf
  14. #include <stdlib.h> // getenv
  15. #include <string.h> // strcpy
  16. #include <malloc.h> // malloc, free
  17.  
  18. #define FPL_LOG_FORMAT(what, format) "[" what "] " format "\n"
  19. #define FPL_LOG(what, format, ...) do { \
  20.     ::fprintf(stdout, FPL_LOG_FORMAT(what, format), ## __VA_ARGS__); \
  21. } while (0)
  22.  
  23. // Subplatform POSIX
  24. #if !defined(COMPILE_ON_WIN)
  25. #include <sys/mman.h> // mmap, munmap
  26. #include <sys/types.h> // data types
  27. #include <sys/stat.h> // mkdir
  28. #include <sys/errno.h> // errno
  29. #include <signal.h> // pthread_kill
  30. #include <time.h> // clock_gettime, nanosleep
  31. #include <dlfcn.h> // dlopen, dlclose
  32. #include <fcntl.h> // open
  33. #include <unistd.h> // read, write, close, access, rmdir
  34.  
  35. // Subplatform X11
  36. #include <X11/X.h> // Window
  37. #include <X11/Xlib.h> // Display
  38. #undef None
  39. #undef Success
  40.  
  41. // GLX
  42. #include <GL/glx.h> // XVisualInfo, GLXContext, GLXDrawable
  43. #else
  44.  
  45. // Fake types to get it compile on windows
  46. #define RTLD_NOW 1337
  47. #define AllocNone 0
  48. #define CopyFromParent 0
  49.  
  50.     // @TODO(final): Event loop!
  51.  
  52.     goto success;
  53.    
  54. failed:
  55.     retCode = -1;
  56.     goto release;
  57.  
  58. success:
  59.     retCode = 0;
  60.     goto release;
  61.  
  62. release:
  63.  
  64.  
  65.     return retCode;
  66.  
  67. #define InputOutput 0x4
  68.  
  69. #define CWEventMask 0x10
  70. #define CWBorderPixel 0x11
  71. #define CWColormap 0x12
  72.  
  73. #define StructureNotifyMask 0x20
  74.  
  75. typedef int XID;
  76. typedef XID Colormap;
  77. typedef XID Visual;
  78. struct Display {
  79.     int dummy;
  80. };
  81. struct XVisualInfo {
  82.     int depth;
  83.     Visual *visual;
  84. };
  85. typedef XID Window;
  86. struct XSetWindowAttributes {
  87.     Colormap colormap;
  88.     int event_mask;
  89. };
  90. struct XErrorEvent {
  91.     int type;
  92.     Display *display;           /* Display the event was read from */
  93.     unsigned long serial;       /* serial number of failed request */
  94.     unsigned char error_code;   /* error code of failed request */
  95.     unsigned char request_code; /* Major op-code of failed request */
  96.     unsigned char minor_code;   /* Minor op-code of failed request */
  97.     XID resourceid;             /* resource id */
  98. };
  99. #define XERRORHANDLER(name) int name(Display *display, XErrorEvent *ev)
  100. typedef XERRORHANDLER(__XErrorHandler);
  101. typedef __XErrorHandler *XErrorHandler;
  102.  
  103. typedef unsigned char GLubyte;
  104. typedef int GLint;
  105. #define GL_TRUE 1
  106. #define GL_FALSE 0
  107.  
  108. #ifndef True
  109. #   define True 1
  110. #   define False 0
  111. #endif
  112. #ifndef Bool
  113. #   define Bool int
  114. #endif
  115.  
  116. #define GLX_VENDOR 1
  117. #define GLX_RGBA_BIT 0x00000001
  118. #define GLX_WINDOW_BIT 0x00000001
  119. #define GLX_DRAWABLE_TYPE 0x8010
  120. #define GLX_RENDER_TYPE 0x8011
  121. #define GLX_RGBA_TYPE 0x8014
  122. #define GLX_DOUBLEBUFFER 5
  123. #define GLX_STEREO 6
  124. #define GLX_AUX_BUFFERS 7
  125. #define GLX_RED_SIZE 8
  126. #define GLX_GREEN_SIZE 9
  127. #define GLX_BLUE_SIZE 10
  128. #define GLX_ALPHA_SIZE 11
  129. #define GLX_DEPTH_SIZE 12
  130. #define GLX_STENCIL_SIZE 13
  131. #define GLX_ACCUM_RED_SIZE 14
  132. #define GLX_ACCUM_GREEN_SIZE 15
  133. #define GLX_ACCUM_BLUE_SIZE 16
  134. #define GLX_ACCUM_ALPHA_SIZE 17
  135. #define GLX_SAMPLES 0x186a1
  136. #define GLX_VISUAL_ID 0x800b
  137.  
  138. #define GLX_X_VISUAL_TYPE 0x22
  139. #define GLX_TRUE_COLOR 0x8002
  140.  
  141. typedef XID GLXWindow;
  142. typedef XID GLXDrawable;
  143. struct __GLXFBConfig {
  144.     int dummy;
  145. };
  146. struct __GLXcontext {
  147.     int dummy;
  148. };
  149. typedef __GLXFBConfig* GLXFBConfig;
  150. typedef __GLXcontext* GLXContext;
  151.  
  152. static void *dlopen(const char *filepath, int loadtype) {
  153.     return nullptr;
  154. }
  155. static void dlclose(void *handle) {
  156. }
  157. static void *dlsym(void *handle, const char *name) {
  158.     return nullptr;
  159. }
  160. static const char *getenv(const char *name) {
  161.     return nullptr;
  162. }
  163. #endif
  164.  
  165. #define FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, target, type, name) \
  166.     target = (type *)::dlsym(libHandle, name); \
  167.     if (target == nullptr) { \
  168.         break; \
  169.     }
  170.  
  171. namespace fpl {
  172.     namespace subplatform_posix {
  173.         fpl_constant int DL_LOADTYPE = RTLD_NOW;
  174.     }
  175.  
  176.     namespace subplatform_x11 {
  177.         //
  178.         // X11 Api
  179.         //
  180. #       define FPL_FUNC_X11_X_FREE(name) int name(void *data)
  181.         typedef FPL_FUNC_X11_X_FREE(fpl_func_x11_XFree);
  182. #       define FPL_FUNC_X11_X_FLUSH(name) void name(Display *display)
  183.         typedef FPL_FUNC_X11_X_FLUSH(fpl_func_x11_XFlush);
  184. #       define FPL_FUNC_X11_X_OPEN_DISPLAY(name) Display *name(char *display_name)
  185.         typedef FPL_FUNC_X11_X_OPEN_DISPLAY(fpl_func_x11_XOpenDisplay);
  186. #       define FPL_FUNC_X11_X_CLOSE_DISPLAY(name) int name(Display *display)
  187.         typedef FPL_FUNC_X11_X_CLOSE_DISPLAY(fpl_func_x11_XCloseDisplay);
  188. #       define FPL_FUNC_X11_X_DEFAULT_SCREEN(name) int name(Display *display)
  189.         typedef FPL_FUNC_X11_X_DEFAULT_SCREEN(fpl_func_x11_XDefaultScreen);
  190. #       define FPL_FUNC_X11_X_ROOT_WINDOW(name) Window name(Display *display, int screen_number)
  191.         typedef FPL_FUNC_X11_X_ROOT_WINDOW(fpl_func_x11_XRootWindow);
  192. #       define FPL_FUNC_X11_X_CREATE_WINDOW(name) Window name(Display *display, Window parent, int x, int y, unsigned int width, unsigned int height, unsigned int border_width, int depth, unsigned int clazz, Visual *visual, unsigned long valuemask, XSetWindowAttributes *attributes)
  193.         typedef FPL_FUNC_X11_X_CREATE_WINDOW(fpl_func_x11_XCreateWindow);
  194. #       define FPL_FUNC_X11_X_DESTROY_WINDOW(name) int name(Display *display, Window w)
  195.         typedef FPL_FUNC_X11_X_DESTROY_WINDOW(fpl_func_x11_XDestroyWindow);
  196. #       define FPL_FUNC_X11_X_CREATE_COLORMAP(name) Colormap name(Display *display, Window w, Visual *visual, int alloc)
  197.         typedef FPL_FUNC_X11_X_CREATE_COLORMAP(fpl_func_x11_XCreateColormap);
  198. #       define FPL_FUNC_X11_X_DEFAULT_COLORMAP(name) Colormap name(Display *display, int screen_number)
  199.         typedef FPL_FUNC_X11_X_DEFAULT_COLORMAP(fpl_func_x11_XDefaultColormap);
  200. #       define FPL_FUNC_X11_X_FREE_COLORMAP(name) void name(Display *display, Colormap colormap)
  201.         typedef FPL_FUNC_X11_X_FREE_COLORMAP(fpl_func_x11_XFreeColormap);
  202. #       define FPL_FUNC_X11_X_MAP_WINDOW(name) void name(Display *display, Window w)
  203.         typedef FPL_FUNC_X11_X_MAP_WINDOW(fpl_func_x11_XMapWindow);
  204. #       define FPL_FUNC_X11_X_UNMAP_WINDOW(name) void name(Display *display, Window w)
  205.         typedef FPL_FUNC_X11_X_UNMAP_WINDOW(fpl_func_x11_XUnmapWindow);
  206. #       define FPL_FUNC_X11_X_STORE_NAME(name) void name(Display *display, Window w, char *windowName)
  207.         typedef FPL_FUNC_X11_X_STORE_NAME(fpl_func_x11_XStoreName);
  208. //#       define FPL_FUNC_X11_X_RENDER_FIND_VISUAL_FORMAT(name) XRenderPictFormat* name(Display* display, Visual const* visual)
  209. //        typedef FPL_FUNC_X11_X_RENDER_FIND_VISUAL_FORMAT(fpl_func_x11_XRenderFindVisualFormat);
  210. #       define FPL_FUNC_X11_X_DEFAULT_VISUAL(name) Visual *name(Display *display, int screen_number)
  211.         typedef FPL_FUNC_X11_X_DEFAULT_VISUAL(fpl_func_x11_XDefaultVisual);
  212. #       define FPL_FUNC_X11_X_SET_ERROR_HANDLER(name) XErrorHandler name(XErrorHandler handler)
  213.         typedef FPL_FUNC_X11_X_SET_ERROR_HANDLER(fpl_func_x11_XSetErrorHandler);
  214.  
  215.         struct X11Api {
  216.             void *libHandle;
  217.             fpl_func_x11_XFlush *XFlush;
  218.             fpl_func_x11_XFree *XFree;
  219.             fpl_func_x11_XOpenDisplay *XOpenDisplay;
  220.             fpl_func_x11_XCloseDisplay *XCloseDisplay;
  221.             fpl_func_x11_XDefaultScreen *XDefaultScreen;
  222.             fpl_func_x11_XRootWindow *XRootWindow;
  223.             fpl_func_x11_XCreateWindow *XCreateWindow;
  224.             fpl_func_x11_XDestroyWindow *XDestroyWindow;
  225.             fpl_func_x11_XCreateColormap *XCreateColormap;
  226.             fpl_func_x11_XFreeColormap *XFreeColormap;
  227.             fpl_func_x11_XDefaultColormap *XDefaultColormap;
  228.             fpl_func_x11_XMapWindow *XMapWindow;
  229.             fpl_func_x11_XUnmapWindow *XUnmapWindow;
  230.             fpl_func_x11_XStoreName *XStoreName;
  231.             //fpl_func_x11_XRenderFindVisualFormat *XRenderFindVisualFormat;
  232.             fpl_func_x11_XDefaultVisual *XDefaultVisual;
  233.             fpl_func_x11_XSetErrorHandler *XSetErrorHandler;
  234.         };
  235.  
  236.         fpl_internal void UnloadX11Api(X11Api &x11Api) {
  237.             if (x11Api.libHandle != nullptr) {
  238.                 ::dlclose(x11Api.libHandle);
  239.             }
  240.             x11Api = {};
  241.         }
  242.  
  243.         fpl_internal bool LoadX11Api(X11Api &x11Api) {
  244.             const char* libFileNames[] = {
  245.                 "libX11.so",
  246.                 "libX11.so.7",
  247.                 "libX11.so.6",
  248.                 "libX11.so.5",
  249.             };
  250.             bool result = false;
  251.             for (uint32_t index = 0; index < FPL_ARRAYCOUNT(libFileNames); ++index) {
  252.                 const char *libName = libFileNames[index];
  253.                 void *libHandle = x11Api.libHandle = ::dlopen(libName, subplatform_posix::DL_LOADTYPE);
  254.                 if (libHandle != nullptr) {
  255.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XFlush, fpl_func_x11_XFlush, "XFlush");
  256.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XFree, fpl_func_x11_XFree, "XFree");
  257.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XOpenDisplay, fpl_func_x11_XOpenDisplay, "XOpenDisplay");
  258.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XCloseDisplay, fpl_func_x11_XCloseDisplay, "XCloseDisplay");
  259.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XDefaultScreen, fpl_func_x11_XDefaultScreen, "XDefaultScreen");
  260.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XRootWindow, fpl_func_x11_XRootWindow, "XRootWindow");
  261.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XCreateWindow, fpl_func_x11_XCreateWindow, "XCreateWindow");
  262.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XDestroyWindow, fpl_func_x11_XDestroyWindow, "XDestroyWindow");
  263.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XCreateColormap, fpl_func_x11_XCreateColormap, "XCreateColormap");
  264.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XFreeColormap, fpl_func_x11_XFreeColormap, "XFreeColormap");
  265.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XDefaultColormap, fpl_func_x11_XDefaultColormap, "XDefaultColormap");
  266.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XMapWindow, fpl_func_x11_XMapWindow, "XMapWindow");
  267.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XUnmapWindow, fpl_func_x11_XUnmapWindow, "XUnmapWindow");
  268.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XStoreName, fpl_func_x11_XStoreName, "XStoreName");
  269.                     //FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XRenderFindVisualFormat, fpl_func_x11_XRenderFindVisualFormat, "XRenderFindVisualFormat");
  270.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XDefaultVisual, fpl_func_x11_XDefaultVisual, "XDefaultVisual");
  271.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, x11Api.XSetErrorHandler, fpl_func_x11_XSetErrorHandler, "XSetErrorHandler");
  272.                     result = true;
  273.                     break;
  274.                 }
  275.                 UnloadX11Api(x11Api);
  276.             }
  277.             return(result);
  278.         }
  279.  
  280.         struct X11AppState {
  281.             X11Api api;
  282.         };
  283.  
  284.         struct X11WindowState {
  285.             Window root;
  286.             Window window;
  287.             Colormap colorMap;
  288.             XErrorHandler originalErrorHandler;
  289.             Display *display;
  290.             int32_t screen;
  291.         };
  292.  
  293.         struct X11WindowAttributesInput {
  294.             X11AppState *appState;
  295.             X11WindowState *windowState;
  296.         };
  297.  
  298.         struct X11WindowAttributesOutput {
  299.             Colormap colorMap;
  300.             Visual *visual;
  301.             int colorDepth;
  302.         };
  303.  
  304.     } // subplatform_x11
  305. } // fpl
  306.  
  307. namespace fpl {
  308.     namespace platform {
  309.         struct PlatformWindowState {
  310.             subplatform_x11::X11WindowState x11;
  311.         };
  312.  
  313.         struct PlatformVideoState {
  314.             void *mem;
  315.             size_t size;
  316.         };
  317.  
  318.         struct PlatformAppState {
  319.             subplatform_x11::X11AppState x11;
  320.             PlatformWindowState window;
  321.             PlatformVideoState video;
  322.         };
  323.  
  324.         struct WindowAttributesInput {
  325.             subplatform_x11::X11WindowAttributesInput x11;
  326.             PlatformVideoState *video;
  327.         };
  328.  
  329.         struct WindowAttributesOutput {
  330.             subplatform_x11::X11WindowAttributesOutput x11;
  331.         };
  332.  
  333. #       define FPL_FUNC_GET_WINDOW_ATTRIBUTES(name) bool name(const platform::WindowAttributesInput &input, platform::WindowAttributesOutput &output)
  334.         typedef FPL_FUNC_GET_WINDOW_ATTRIBUTES(GetWindowAttributes_callback);
  335.     }
  336. }
  337.  
  338. namespace fpl {
  339.     namespace strings {
  340.         char *CopyAnsiString(const char *sourceStr, char *destStr, size_t destLength) {
  341.             char *result = strncpy(destStr, sourceStr, destLength);
  342.             return(result);
  343.         }
  344.     }
  345.  
  346.     namespace subplatform_x11 {
  347.  
  348.         fpl_internal void X11ReleaseSubplatform(X11AppState &appState) {
  349.             UnloadX11Api(appState.api);
  350.         }
  351.  
  352.         fpl_internal bool X11InitSubplatform(X11AppState &appState) {
  353.             if (!LoadX11Api(appState.api)) {
  354.                 return false;
  355.             }
  356.             return true;
  357.         }
  358.  
  359.         fpl_internal void X11ReleaseWindow(const X11AppState &x11AppState, X11WindowState &windowState) {
  360.             const X11Api &x11Api = x11AppState.api;
  361.             if (windowState.window) {
  362.                 FPL_LOG("X11", "Unmap Window '%d' on Display '%p'", (int)windowState.window, windowState.display);
  363.                 x11Api.XUnmapWindow(windowState.display, windowState.window);
  364.                 FPL_LOG("X11", "Destroy Window '%d' on Display '%p'", (int)windowState.window, windowState.display);
  365.                 x11Api.XDestroyWindow(windowState.display, windowState.window);
  366.                 windowState.window = (Window)0;
  367.             }
  368.             if (windowState.colorMap) {
  369.                 FPL_LOG("X11", "Free Colormap '%d' on Display '%p'", (int)windowState.colorMap, windowState.display);
  370.                 x11Api.XFreeColormap(windowState.display, windowState.colorMap);
  371.                 windowState.colorMap = (Colormap)0;
  372.             }
  373.             if (windowState.display != nullptr) {
  374.                 FPL_LOG("X11", "Flush Display '%p'", windowState.display);
  375.                 x11Api.XFlush(windowState.display);
  376.                 FPL_LOG("X11", "Close Display '%p'", windowState.display);
  377.                 x11Api.XCloseDisplay(windowState.display);
  378.                 windowState.display = nullptr;
  379.             }
  380.             FPL_LOG("X11", "Clear Window State");
  381.             windowState = {};
  382.         }
  383.  
  384.         fpl_internal int X11ErrorHandler(Display *display, XErrorEvent *ev) {
  385.             return 0;
  386.         }
  387.  
  388.         fpl_internal bool X11InitWindow(platform::GetWindowAttributes_callback *getWindowAttributesCallback, const platform::WindowAttributesInput &winAttribInput, X11AppState &x11AppState, X11WindowState &windowState) {
  389.             const X11Api &x11Api = x11AppState.api;
  390.  
  391.             // @TODO(final): Implement this!
  392.             // See: https://www.khronos.org/opengl/wiki/Programming_OpenGL_in_Linux:_GLX_and_Xlib
  393.  
  394.             // Get display with fallback from environment variable
  395.             const char *displayStrings[] = {
  396.                 nullptr,
  397.                 getenv("DISPLAY")
  398.             };
  399.             char displayStringBuffer[256];
  400.             for (uint32_t displayStringIndex = 0; displayStringIndex < FPL_ARRAYCOUNT(displayStrings); ++displayStringIndex) {
  401.                 // @NOTE(final): Nonsense we have to copy the constant display string to a variable buffer to satisfy the compiler
  402.                 const char *displayString = displayStrings[displayStringIndex];
  403.                 const char *notNullDisplayString = (displayString == nullptr ? "nullptr" : displayString);
  404.                 if (displayString != nullptr) {
  405.                     strings::CopyAnsiString(displayString, displayStringBuffer, FPL_ARRAYCOUNT(displayStringBuffer));
  406.                     windowState.display = x11Api.XOpenDisplay(displayStringBuffer);
  407.                 } else {
  408.                     windowState.display = x11Api.XOpenDisplay(nullptr);
  409.                 }
  410.                 FPL_LOG("X11", "Open Display from String '%s'", notNullDisplayString);
  411.                 if (windowState.display != nullptr) {
  412.                     FPL_LOG("X11", "Successfully opened Display: '%p' from String '%s'", windowState.display, notNullDisplayString);
  413.                     break;
  414.                 }
  415.                 FPL_LOG("X11", "Failed opening Display from String '%s'!", notNullDisplayString);
  416.             }
  417.             if (windowState.display == nullptr) {
  418.                 return false;
  419.             }
  420.  
  421.             // Set error handler
  422.             windowState.originalErrorHandler = x11Api.XSetErrorHandler(X11ErrorHandler);
  423.  
  424.             // Get screen
  425.             FPL_LOG("X11", "Get Screen from Display '%p'", windowState.display);
  426.             windowState.screen = x11Api.XDefaultScreen(windowState.display);
  427.             FPL_LOG("X11", "Successfully got Screen: '%d' from Display '%p'", windowState.screen, windowState.display);
  428.  
  429.             // Get root window
  430.             FPL_LOG("X11", "Get Root Window From Display '%p' and Screen '%d'", windowState.display, windowState.screen);
  431.             windowState.root = x11Api.XRootWindow(windowState.display, windowState.screen);
  432.             FPL_LOG("X11", "Successfully got Root Window '%d' from Display '%p' and Screen '%d'", (int)windowState.root, windowState.display, windowState.screen);
  433.  
  434.             // @TODO(final): This entire thing about getting the visual info is just bullshit and need to replaced by a much more sane implementation!
  435.             FPL_LOG("X11", "Get Window Attributes from Callback '%p':", getWindowAttributesCallback);
  436.             platform::WindowAttributesOutput winAttribOutput = {};
  437.             bool gotWindowAttributes = getWindowAttributesCallback(winAttribInput, winAttribOutput);
  438.             if (!gotWindowAttributes) {
  439.                 FPL_LOG("X11", "Failed getting Window Attributes from Callback '%p'!", getWindowAttributesCallback);
  440.             } else {
  441.                 FPL_LOG("X11", "Successfully got Window Attributes");
  442.             }
  443.  
  444.             // Set window attributes
  445.             XSetWindowAttributes swa = {};
  446.             unsigned long valueMask;
  447.             if (gotWindowAttributes) {
  448.                 FPL_LOG("X11", "Using Colormap from Window Attributes");
  449.                 swa.colormap = winAttribOutput.x11.colorMap;
  450.                 valueMask = CWEventMask | CWBorderPixel | CWColormap;
  451.             } else {
  452.                 FPL_LOG("X11", "Not using a Colormap");
  453.                 winAttribOutput.x11.colorMap = x11Api.XDefaultColormap(windowState.display, windowState.screen);
  454.                 winAttribOutput.x11.visual = x11Api.XDefaultVisual(windowState.display, windowState.root);
  455.                 winAttribOutput.x11.colorDepth = CopyFromParent;
  456.                 valueMask = CWEventMask | CWBorderPixel;
  457.             }
  458.             swa.event_mask = StructureNotifyMask;
  459.  
  460.             // @TODO(final): Get window width from settings (Either window or fullscreen)
  461.             uint32_t windowWidth = 800;
  462.             uint32_t windowHeight = 600;
  463.  
  464.             // Create window
  465.             FPL_LOG("X11", "Create Window with Display('%p'), Root('%d'), Dimension(%d x %d), ColorDepth(%d)", windowState.display, (int)windowState.root, windowWidth, windowHeight, winAttribOutput.x11.colorDepth);
  466.             windowState.colorMap = winAttribOutput.x11.colorMap;
  467.             windowState.window = x11Api.XCreateWindow(windowState.display, windowState.root, 0, 0, windowWidth, windowHeight, 0, winAttribOutput.x11.colorDepth, InputOutput, winAttribOutput.x11.visual, valueMask, &swa);
  468.             if (!windowState.window) {
  469.                 FPL_LOG("X11", "Failed creating Window from Display '%p' and Root '%d'", windowState.display, (int)windowState.root);
  470.                 X11ReleaseWindow(x11AppState, windowState);
  471.                 return false;
  472.             }
  473.             FPL_LOG("X11", "Successfully created Window '%d'", (int)windowState.window);
  474.  
  475.             // Show window
  476.             FPL_LOG("X11", "Map Window '%d' on Display '%p'", (int)windowState.window, windowState.display);
  477.             x11Api.XMapWindow(windowState.display, windowState.window);
  478.  
  479.             // Set title
  480.             char windowTitleBuffer[256];
  481.             strings::CopyAnsiString("Unnamed FPL X Window", windowTitleBuffer, FPL_ARRAYCOUNT(windowTitleBuffer));
  482.             FPL_LOG("X11", "Set window title to '%s'", windowTitleBuffer);
  483.             x11Api.XStoreName(windowState.display, windowState.window, windowTitleBuffer);
  484.  
  485.             return true;
  486.         }
  487.  
  488.     } // subplatform_x11
  489.  
  490.     namespace drivers {
  491.         // GLX function prototypes
  492. #       define FPL_FUNC_GL_X_CHOOSE_VISUAL(name) XVisualInfo* name(Display *dpy, int screen, int *attribList)
  493.         typedef FPL_FUNC_GL_X_CHOOSE_VISUAL(fpl_func_glx_glXChooseVisual);
  494. #       define FPL_FUNC_GL_X_CREATE_CONTEXT(name) GLXContext name(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
  495.         typedef FPL_FUNC_GL_X_CREATE_CONTEXT(fpl_func_glx_glXCreateContext);
  496. #       define FPL_FUNC_GL_X_CREATE_NEW_CONTEXT(name) GLXContext name(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
  497.         typedef FPL_FUNC_GL_X_CREATE_NEW_CONTEXT(fpl_func_glx_glXCreateNewContext);
  498. #       define FPL_FUNC_GL_X_DESTROY_CONTEXT(name) void name(Display *dpy, GLXContext ctx)
  499.         typedef FPL_FUNC_GL_X_DESTROY_CONTEXT(fpl_func_glx_glXDestroyContext);
  500. #       define FPL_FUNC_GL_X_MAKE_CURRENT(name) Bool name(Display *dpy, GLXDrawable drawable, GLXContext ctx)
  501.         typedef FPL_FUNC_GL_X_MAKE_CURRENT(fpl_func_glx_glXMakeCurrent);
  502. #       define FPL_FUNC_GL_X_SWAP_BUFFERS(name) void name(Display *dpy, GLXDrawable drawable)
  503.         typedef FPL_FUNC_GL_X_SWAP_BUFFERS(fpl_func_glx_glXSwapBuffers);
  504. #       define FPL_FUNC_GL_X_GET_PROC_ADDRESS(name) void *name(const GLubyte *procname)
  505.         typedef FPL_FUNC_GL_X_GET_PROC_ADDRESS(fpl_func_glx_glXGetProcAddress);
  506. #       define FPL_FUNC_GL_X_CHOOSE_FB_CONFIG(name) GLXFBConfig *name(Display *dpy, int screen, const int *attrib_list,  int *nelements)
  507.         typedef FPL_FUNC_GL_X_CHOOSE_FB_CONFIG(fpl_func_glx_glXChooseFBConfig);
  508. #       define FPL_FUNC_GL_X_GET_FB_CONFIGS(name) GLXFBConfig *name(Display *dpy, int screen, int *nelements)
  509.         typedef FPL_FUNC_GL_X_GET_FB_CONFIGS(fpl_func_glx_glXGetFBConfigs);
  510. #       define FPL_FUNC_GL_X_GET_VISUAL_FROM_FB_CONFIG(name) XVisualInfo *name(Display *dpy, GLXFBConfig config)
  511.         typedef FPL_FUNC_GL_X_GET_VISUAL_FROM_FB_CONFIG(fpl_func_glx_glXGetVisualFromFBConfig);
  512. #       define FPL_FUNC_GL_X_GET_FB_CONFIG_ATTRIB(name) int name(Display *dpy, GLXFBConfig config, int attribute, int *value)
  513.         typedef FPL_FUNC_GL_X_GET_FB_CONFIG_ATTRIB(fpl_func_glx_glXGetFBConfigAttrib);
  514. #       define FPL_FUNC_GL_X_CREATE_WINDOW(name) GLXWindow name(Display *dpy, GLXFBConfig config, Window win, const int *attrib_list)
  515.         typedef FPL_FUNC_GL_X_CREATE_WINDOW(fpl_func_glx_glXCreateWindow);
  516. #       define FPL_FUNC_GL_X_QUERY_EXTENSION(name) Bool name(Display *dpy,  int *errorBase,  int *eventBase)
  517.         typedef FPL_FUNC_GL_X_QUERY_EXTENSION(fpl_func_glx_glXQueryExtension);
  518.  
  519.         struct GLXApi {
  520.             void *libHandle;
  521.             fpl_func_glx_glXChooseVisual *glXChooseVisual;
  522.             fpl_func_glx_glXCreateContext *glXCreateContext;
  523.             fpl_func_glx_glXDestroyContext *glXDestroyContext;
  524.             fpl_func_glx_glXCreateNewContext *glXCreateNewContext;
  525.             fpl_func_glx_glXMakeCurrent *glXMakeCurrent;
  526.             fpl_func_glx_glXSwapBuffers *glXSwapBuffers;
  527.             fpl_func_glx_glXGetProcAddress *glXGetProcAddress;
  528.             fpl_func_glx_glXChooseFBConfig *glXChooseFBConfig;
  529.             fpl_func_glx_glXGetFBConfigs *glXGetFBConfigs;
  530.             fpl_func_glx_glXGetVisualFromFBConfig *glXGetVisualFromFBConfig;
  531.             fpl_func_glx_glXGetFBConfigAttrib *glXGetFBConfigAttrib;
  532.             fpl_func_glx_glXCreateWindow *glXCreateWindow;
  533.             fpl_func_glx_glXQueryExtension *glXQueryExtension;
  534.         };
  535.  
  536.         fpl_internal void UnloadGLXApi(GLXApi &glxApi) {
  537.             if (glxApi.libHandle != nullptr) {
  538.                 FPL_LOG("GLX", "Unload Api (Library '%p')", glxApi.libHandle);
  539.                 ::dlclose(glxApi.libHandle);
  540.             }
  541.             glxApi = {};
  542.         }
  543.  
  544.         fpl_internal bool LoadGLXApi(GLXApi &glxApi) {
  545.             const char* libFileNames[] = {
  546.                 "libGLX.so",
  547.                 "libGLX.so.0",
  548.             };
  549.             bool result = false;
  550.             for (uint32_t index = 0; index < FPL_ARRAYCOUNT(libFileNames); ++index) {
  551.                 const char *libName = libFileNames[index];
  552.                 FPL_LOG("GLX", "Load GLX Api from Library: %s", libName);
  553.                 void *libHandle = glxApi.libHandle = ::dlopen(libName, subplatform_posix::DL_LOADTYPE);
  554.                 if (libHandle != nullptr) {
  555.                     FPL_LOG("GLX", "Library Found: '%s', Resolving Procedures", libName);
  556.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXChooseVisual, fpl_func_glx_glXChooseVisual, "glXChooseVisual");
  557.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXCreateContext, fpl_func_glx_glXCreateContext, "glXCreateContext");
  558.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXDestroyContext, fpl_func_glx_glXDestroyContext, "glXDestroyContext");
  559.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXCreateNewContext, fpl_func_glx_glXCreateNewContext, "glXCreateNewContext");
  560.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXMakeCurrent, fpl_func_glx_glXMakeCurrent, "glXMakeCurrent");
  561.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXSwapBuffers, fpl_func_glx_glXSwapBuffers, "glXSwapBuffers");
  562.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXGetProcAddress, fpl_func_glx_glXGetProcAddress, "glXGetProcAddress");
  563.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXChooseFBConfig, fpl_func_glx_glXChooseFBConfig, "glXChooseFBConfig");
  564.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXGetFBConfigs, fpl_func_glx_glXGetFBConfigs, "glXGetFBConfigs");
  565.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXGetVisualFromFBConfig, fpl_func_glx_glXGetVisualFromFBConfig, "glXGetVisualFromFBConfig");
  566.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXGetFBConfigAttrib, fpl_func_glx_glXGetFBConfigAttrib, "glXGetFBConfigAttrib");
  567.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXCreateWindow, fpl_func_glx_glXCreateWindow, "glXCreateWindow");
  568.                     FPL_POSIX_GET_FUNCTION_ADDRESS_BREAK(libHandle, libName, glxApi.glXQueryExtension, fpl_func_glx_glXQueryExtension, "glXQueryExtension");
  569.                     FPL_LOG("GLX", "Successfully loaded GLX Api from Library '%s'", libName);
  570.                     result = true;
  571.                     break;
  572.                 }
  573.                 UnloadGLXApi(glxApi);
  574.             }
  575.             return (result);
  576.         }
  577.  
  578.         struct X11VideoOpenGLState {
  579.             GLXApi glxApi;
  580.             XVisualInfo *visualInfo;
  581.             GLXContext glxContext;
  582.             bool isActivated;
  583.         };
  584.  
  585.         fpl_inline int GLXGetFrameBufferConfigAttrib(const GLXApi &glxApi, Display *display, GLXFBConfig fbConfig, int attrib) {
  586.             int result;
  587.             glxApi.glXGetFBConfigAttrib(display, fbConfig, attrib, &result);
  588.             return(result);
  589.         }
  590.  
  591.         fpl_internal XVisualInfo *GLXGetVisualInfo(const subplatform_x11::X11AppState &x11AppState, const X11VideoOpenGLState &glState, Display *display, int screen) {
  592.             XVisualInfo *result = nullptr;
  593.  
  594.             const GLXApi &glxApi = glState.glxApi;
  595.             const subplatform_x11::X11Api &x11Api = x11AppState.api;
  596.  
  597.             GLint attributes[] = {
  598.                 GLX_RENDER_TYPE, GLX_RGBA_BIT,
  599.                 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
  600.                 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
  601.                 GLX_RED_SIZE, 8,
  602.                 GLX_GREEN_SIZE, 8,
  603.                 GLX_BLUE_SIZE, 8,
  604.                 GLX_ALPHA_SIZE, 8,
  605.                 GLX_STENCIL_SIZE, 8,
  606.                 GLX_DEPTH_SIZE, 24,
  607.                 GLX_DOUBLEBUFFER, True,
  608.                 0
  609.             };
  610.  
  611.             // Find all frame buffer configs
  612.             FPL_LOG("GLX", "Get FrameBuffer Configs for Display '%p' and Screen '%d':", display, screen);
  613.             int fbAllConfigCount = 0;
  614.             GLXFBConfig *fbAllConfigs = glxApi.glXChooseFBConfig(display, screen, attributes, &fbAllConfigCount);
  615.  
  616.             if (!fbAllConfigs || !fbAllConfigCount) {
  617.                 FPL_LOG("GLX", "Failed getting FrameBuffer Configs from Display '%p' and Screen '%d'!", display, screen);
  618.                 return nullptr;
  619.             }
  620.             FPL_LOG("GLX", "Successfully got '%d' FrameBuffer Configs from Display '%p' and Screen '%d'", fbAllConfigCount, display, screen);
  621.  
  622.             XVisualInfo *foundVisualInfo = nullptr;
  623.             GLXFBConfig foundFBConfig = nullptr;
  624.             for (int fbConfigIndex = 0; fbConfigIndex < fbAllConfigCount; ++fbConfigIndex) {
  625.                 GLXFBConfig testFBConfig = fbAllConfigs[fbConfigIndex];
  626.  
  627.                 // Get visual info from frame buffer config
  628.                 XVisualInfo *visualInfo = (XVisualInfo*)glxApi.glXGetVisualFromFBConfig(display, testFBConfig);
  629.                 if (!visualInfo) {
  630.                     continue;
  631.                 }
  632.  
  633.                 // Get alpha bits
  634.                 int testAlphaBits = GLXGetFrameBufferConfigAttrib(glxApi, display, testFBConfig, GLX_ALPHA_SIZE);
  635.  
  636.                 // Found a suitable frame buffer config with visual
  637.                 if (testAlphaBits > 0) {
  638.                     foundFBConfig = testFBConfig;
  639.                     foundVisualInfo = visualInfo;
  640.                     break;
  641.                 }
  642.  
  643.                 // Release unused visual info (Important!)
  644.                 x11Api.XFree(visualInfo);
  645.             }
  646.  
  647.             if (foundFBConfig != nullptr) {
  648.                 FPL_ASSERT(foundVisualInfo != nullptr);
  649.                 int doubleBuffer = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_DOUBLEBUFFER);
  650.                 int redBits = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_RED_SIZE);
  651.                 int greenBits = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_GREEN_SIZE);
  652.                 int blueBits = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_BLUE_SIZE);
  653.                 int alphaBits = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_ALPHA_SIZE);
  654.                 int depthBits = GLXGetFrameBufferConfigAttrib(glxApi, display, foundFBConfig, GLX_DEPTH_SIZE);
  655.                 int colorDepth = redBits + greenBits + blueBits + alphaBits;
  656.                 FPL_LOG("GLX", "Successfully found a suitable Frame Buffer Config (Doublebuffer: %s, Color bits: %d, Depth bits: %d) with Visual '%p'", (doubleBuffer == True ? "Yes" : "No"), colorDepth, depthBits, foundVisualInfo);
  657.                 result = foundVisualInfo;
  658.             } else {
  659.                 FPL_LOG("GLX", "Failed finding a suitable Frame Buffer Config for Display '%p'!", display);
  660.             }
  661.  
  662.             // Release frame buffer configs (Important!)
  663.             x11Api.XFree(fbAllConfigs);
  664.  
  665.             return(result);
  666.         }
  667.  
  668.         fpl_internal bool GLXGetWindowAttributes(const subplatform_x11::X11AppState &x11AppState, const subplatform_x11::X11WindowState &windowState, X11VideoOpenGLState &glState, subplatform_x11::X11WindowAttributesOutput &outAttributes) {
  669.             const GLXApi &glxApi = glState.glxApi;
  670.             const subplatform_x11::X11Api &x11Api = x11AppState.api;
  671.  
  672.             Display *display = windowState.display;
  673.             Window root = windowState.root;
  674.             int screen = windowState.screen;
  675.  
  676.             FPL_LOG("GLX", "Get Visual Info for Display '%p' and Screen '%d':", windowState.display, windowState.screen);
  677.             XVisualInfo *visualInfo = GLXGetVisualInfo(x11AppState, glState, display, screen);
  678.             if (visualInfo == nullptr) {
  679.                 FPL_LOG("GLX", "Failed getting Visual Info for Display '%p' and Screen '%d'!", windowState.display, windowState.screen);
  680.                 return false;
  681.             }
  682.             FPL_LOG("GLX", "Successfully got Visual Info '%p' for Display '%p' and Screen '%d'", windowState.display, windowState.screen, visualInfo);
  683.  
  684.             FPL_LOG("GLX", "Create Colormap on Display '%p' and Screen '%d'", display, screen);
  685.             Colormap colorMap = x11Api.XCreateColormap(display, root, visualInfo->visual, AllocNone);
  686.  
  687.             outAttributes.visual = visualInfo->visual;
  688.             outAttributes.colorMap = colorMap;
  689.             outAttributes.colorDepth = visualInfo->depth;
  690.  
  691.             // @BAD(final): Really bad design here, a get function should not change anything at all
  692.             glState.visualInfo = visualInfo;
  693.  
  694.             return(true);
  695.         }
  696.  
  697.         fpl_internal bool X11InitVideoOpenGL(const subplatform_x11::X11AppState &x11AppState, const subplatform_x11::X11WindowState &windowState, X11VideoOpenGLState &glState) {
  698.             const GLXApi &glxApi = glState.glxApi;
  699.  
  700.             glState.isActivated = false;
  701.  
  702.             if (glState.visualInfo == nullptr) {
  703.                 FPL_LOG("GLX", "VisualInfo was not set!");
  704.                 return false;
  705.             }
  706.  
  707.             FPL_LOG("GLX", "Create Context for Display '%p' and VisualInfo '%p':", windowState.display, glState.visualInfo);
  708.             glState.glxContext = glxApi.glXCreateContext(windowState.display, glState.visualInfo, nullptr, GL_TRUE);
  709.             if (glState.glxContext == nullptr) {
  710.                 FPL_LOG("GLX", "Failed creating Context for Display '%p' and VisualInfo '%p'!", windowState.display, glState.visualInfo);
  711.                 return false;
  712.             }
  713.             FPL_LOG("GLX", "Successfully created Context for Display '%p' and VisualInfo '%p': %p", windowState.display, glState.visualInfo, glState.glxContext);
  714.  
  715.             FPL_LOG("GLX", "Activate Context for Display '%p' and Context '%p':", windowState.display, glState.glxContext);
  716.             if (!glxApi.glXMakeCurrent(windowState.display, windowState.window, glState.glxContext)) {
  717.                 FPL_LOG("GLX", "Failed activating Context for Display '%p' and Context '%p'!", windowState.display, glState.glxContext);
  718.                 return false;
  719.             }
  720.             FPL_LOG("GLX", "Successfully activated Context for Display '%p' and Context '%p'", windowState.display, glState.glxContext);
  721.  
  722.             glState.isActivated = true;
  723.  
  724.             return true;
  725.         }
  726.  
  727.         fpl_internal void X11ReleaseVideoOpenGL(const subplatform_x11::X11Api &x11Api, const subplatform_x11::X11WindowState &windowState, X11VideoOpenGLState &glState) {
  728.             GLXApi &glxApi = glState.glxApi;
  729.             if (glState.isActivated) {
  730.                 FPL_LOG("GLX", "Disable Context for Display '%p'", windowState.display);
  731.                 glxApi.glXMakeCurrent(windowState.display, 0L, nullptr);
  732.                 glState.isActivated = false;
  733.             }
  734.             if (glState.glxContext != nullptr) {
  735.                 FPL_LOG("GLX", "Destroy Context '%p' for Display '%p'", glState.glxContext, windowState.display);
  736.                 glxApi.glXDestroyContext(windowState.display, glState.glxContext);
  737.                 glState.glxContext = nullptr;
  738.             }
  739.             // @TODO(final): Do we want to free it before we destroy the context???
  740.             if (glState.visualInfo != nullptr) {
  741.                 x11Api.XFree(glState.visualInfo);
  742.                 glState.visualInfo = nullptr;
  743.             }
  744.         }
  745.     } // drivers
  746.  
  747.     namespace common_video {
  748.         struct VideoState {
  749.             drivers::X11VideoOpenGLState x11_opengl;
  750.         };
  751.  
  752.         // @NOTE(final): The window has no access to the video driver directly, so we use callback to access it.
  753.         fpl_internal FPL_FUNC_GET_WINDOW_ATTRIBUTES(DefaultGetWindowAttributes) {
  754.             FPL_ASSERT(input.x11.appState != nullptr);
  755.             FPL_ASSERT(input.x11.windowState != nullptr);
  756.             VideoState *videoState = (VideoState *)input.video->mem;
  757.             bool result = drivers::GLXGetWindowAttributes(*input.x11.appState, *input.x11.windowState, videoState->x11_opengl, output.x11);
  758.             return(result);
  759.         }
  760.     } // common_video
  761. } // fpl
  762.  
  763. int ReleaseAppState(fpl::platform::PlatformAppState *appState) {
  764.     // Release rendering context
  765.     fpl::common_video::VideoState *videoState = (fpl::common_video::VideoState *)appState->video.mem;
  766.     if (videoState != nullptr) {
  767.         fpl::drivers::X11ReleaseVideoOpenGL(appState->x11.api, appState->window.x11, videoState->x11_opengl);
  768.     }
  769.  
  770.     // Release window
  771.     fpl::subplatform_x11::X11ReleaseWindow(appState->x11, appState->window.x11);
  772.  
  773.     // Unload OpenGL library
  774.     if (videoState != nullptr) {
  775.         fpl::drivers::UnloadGLXApi(videoState->x11_opengl.glxApi);
  776.     }
  777.  
  778.     // Unload X11 library
  779.     fpl::subplatform_x11::UnloadX11Api(appState->x11.api);
  780.  
  781.     // Free app state
  782.     free(appState);
  783. }
  784.  
  785. int main(int argc, char *args[]) {
  786.     // Allocate all state
  787.     fpl::platform::PlatformAppState *appState = (fpl::platform::PlatformAppState *)malloc(sizeof(fpl::platform::PlatformAppState));
  788.     memset(appState, 0, sizeof(fpl::platform::PlatformAppState));
  789.  
  790.     // Setup get window attributes callback and input
  791.     fpl::platform::GetWindowAttributes_callback *getWinAttribsCallback = fpl::common_video::DefaultGetWindowAttributes;
  792.     fpl::platform::WindowAttributesInput winAttribInput = {};
  793.     winAttribInput.video = &appState->video;
  794.     winAttribInput.x11.appState = &appState->x11;
  795.     winAttribInput.x11.windowState = &appState->window.x11;
  796.  
  797.     // Init video state
  798.     appState->video.size = sizeof(fpl::common_video::VideoState);
  799.     appState->video.mem = malloc(appState->video.size);
  800.     if (!appState->video.mem) {
  801.         ReleaseAppState(appState);
  802.         return -1;
  803.     }
  804.     memset(appState->video.mem, 0, appState->video.size);
  805.     fpl::common_video::VideoState *videoState = (fpl::common_video::VideoState *)appState->video.mem;
  806.  
  807.     // Load X11 library
  808.     fpl::subplatform_x11::X11AppState &x11AppState = appState->x11;
  809.     if (!fpl::subplatform_x11::X11InitSubplatform(x11AppState)) {
  810.         ReleaseAppState(appState);
  811.         return -1;
  812.     }
  813.  
  814.     // Load OpenGL library
  815.     if (!fpl::drivers::LoadGLXApi(videoState->x11_opengl.glxApi)) {
  816.         ReleaseAppState(appState);
  817.         return -1;
  818.     }
  819.  
  820.     // Create window
  821.     if (!fpl::subplatform_x11::X11InitWindow(getWinAttribsCallback, winAttribInput, appState->x11, appState->window.x11)) {
  822.         ReleaseAppState(appState);
  823.         return -1;
  824.     }
  825.  
  826.     // Create rendering context
  827.     if (!fpl::drivers::X11InitVideoOpenGL(appState->x11, appState->window.x11, videoState->x11_opengl)) {
  828.         ReleaseAppState(appState);
  829.         return -1;
  830.     }
  831.    
  832.     ReleaseAppState(appState);
  833.  
  834.     return 0;
  835. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement