diff --git a/.bam/functions.lua b/.bam/functions.lua index 1312770..5a796da 100644 --- a/.bam/functions.lua +++ b/.bam/functions.lua @@ -1,7 +1,7 @@ local _systems = { "Win32", - -- "Linux" + "Unix" } @@ -14,12 +14,19 @@ end -- Detect what system we currently are on. function system() - local win = os.getenv('OS') - - if win:lower():match('windows') then - return _systems[1] + if family ~= nil then + if family == "windows" then + return _systems[1] + end + if family == "unix" then + return _systems[2] + end end + local win = os.getenv('OS') + if win ~= nil and win:lower():match('windows') then + return _systems[1] + end return nil end diff --git a/.gitignore b/.gitignore index bcd7a8c..6977329 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ +# Build system related files build/ .bam/* !.bam/*.lua diff --git a/assets/fonts/Anonymous Pro.ttf b/assets/fonts/Anonymous-Pro.ttf similarity index 100% rename from assets/fonts/Anonymous Pro.ttf rename to assets/fonts/Anonymous-Pro.ttf diff --git a/engine.build.lua b/engine.build.lua index a7920b3..1d2978d 100644 --- a/engine.build.lua +++ b/engine.build.lua @@ -17,8 +17,22 @@ if global_settings.debug then settings.cc.flags:Add("-DSPECTRE_DEBUG") end +-- Platform +if TARGET_OS == "Win32" then + settings.cc.defines:Add("SPECTRE_PLATFORM_WIN=1") +elseif TARGET_OS == "Unix" then + settings.cc.defines:Add("SPECTRE_PLATFORM_UNIX=1") +end + -- FreeType2 -settings.cc.includes:Add("vendor/FreeType2/include") +if TARGET_OS == "Win32" then + settings.cc.includes:Add("vendor/FreeType2/include") + + -- Staticly link freetype on windows. + settings.link.libpath:Add("vendor/FreeType2/lib/x86") +else + settings.cc.includes:Add("/usr/include/freetype2") +end -- STB settings.cc.includes:Add("vendor/stb/include") @@ -39,25 +53,40 @@ local system_module = Module("source/System", { }) local platform_common_module = Module("source/Platform", { + "PlatformApplication.cpp", "PlatformDisplay.cpp" }) - --- if TARGET_OS == "Win32" then -- Needed later for unix. -local platform_spec_module = Module("source/Platform/Win32", { - "Win32Application.cpp", - "Win32Display.cpp", - "Win32GLContext.cpp", - "Win32Input.cpp", - "Win32Internal.cpp", - "Win32Keyboard.cpp", - "Win32Misc.cpp", - "Win32Mouse.cpp", - "Win32EventQueue.cpp", - "Win32System.cpp", - "glad_wgl.c" -}) ---end +if TARGET_OS == "Win32" then + platform_spec_module = Module("source/Platform/Win32", { + "Win32Application.cpp", + "Win32Display.cpp", + "Win32GLContext.cpp", + "Win32Input.cpp", + "Win32Internal.cpp", + "Win32Keyboard.cpp", + "Win32Misc.cpp", + "Win32Mouse.cpp", + "Win32EventQueue.cpp", + "Win32System.cpp", + "glad_wgl.c" + }) +elseif TARGET_OS == "Unix" then + platform_spec_module = Module("source/Platform/Unix", { + "Xlib.cpp", + "UnixApplication.cpp", + "X11Display.cpp", + "GLXContext.cpp", + "X11Input.cpp", + "X11Keyboard.cpp", + "X11Mouse.cpp", + "X11EventQueue.cpp", + "X11WindowEventHandler.cpp", + "UnixMisc.cpp", + "UnixSystem.cpp", + "glad_glx.c" + }) +end local input_module = Module("source/Input", { "InputDevice.cpp", @@ -134,7 +163,9 @@ local scene_module = Module("source/Scene", { ----------------------------------------------------------- -- Dependancies -Import("vendor/FreeType2/build.lua") +if TARGET_OS == "Win32" then + Import("vendor/FreeType2/build.lua") +end -- engine local obj = Compile(settings, { diff --git a/examples/build.lua b/examples/build.lua index 552dea1..381f5e3 100644 --- a/examples/build.lua +++ b/examples/build.lua @@ -16,6 +16,10 @@ if TARGET_OS == "Win32" then -- Windows needs to link against these. example_settings.link.libs:Add("opengl32", "gdi32", "user32") +elseif TARGET_OS == "Unix" then + + -- Unix nees dl and X11 libs. + example_settings.link.libs:Add("dl", 'X11', 'Xrandr', 'freetype') end -- For now, to get examples working diff --git a/include/Spectre/Display/DisplayDescription.h b/include/Spectre/Display/DisplayDescription.h index 0d6539b..06067e0 100644 --- a/include/Spectre/Display/DisplayDescription.h +++ b/include/Spectre/Display/DisplayDescription.h @@ -9,7 +9,7 @@ namespace sp { namespace DisplayDecorate { enum Type { - None = 0, + Empty = 0, Menu = 1 << 0, Resize = 1 << 1, Close = 1 << 2, diff --git a/source/Display/Display.cpp b/source/Display/Display.cpp index 24ced50..bd13bd6 100644 --- a/source/Display/Display.cpp +++ b/source/Display/Display.cpp @@ -114,7 +114,7 @@ void Display::setVideoMode(Mode mode) m_cacheDesc = m_description; } - desc.decoration = DisplayDecorate::None; + desc.decoration = DisplayDecorate::Empty; } else { desc = m_cacheDesc; } diff --git a/source/Display/GLContext.cpp b/source/Display/GLContext.cpp index cd26ca8..2c812dc 100644 --- a/source/Display/GLContext.cpp +++ b/source/Display/GLContext.cpp @@ -1,9 +1,12 @@ #include -#ifdef _WIN32 +#ifdef SPECTRE_PLATFORM_WIN #include typedef sp::Win32GLContext ContextType; +#elif SPECTRE_PLATFORM_UNIX +#include +typedef sp::GLXContext ContextType; #else #error "No GLContext implementation exists" #endif diff --git a/source/Game.cpp b/source/Game.cpp index 5213c50..573b5af 100644 --- a/source/Game.cpp +++ b/source/Game.cpp @@ -4,17 +4,18 @@ #include #include #include - -#include -#include +#include #include +#include +#include + namespace sp { Game::Game() : m_running(false) { - m_platform = new Win32Application(); + m_platform = PlatformApplication::create(); m_graphics = new Graphics(m_platform); m_input = new InputModule(&m_platform->getInput()); m_messageHandler = new MessageHandler(); @@ -24,12 +25,17 @@ Game::~Game() { delete m_input; delete m_graphics; - delete m_platform; delete m_messageHandler; + + // TODO: This is abit ugly tbh. + m_platform->shutdown(); + delete m_platform; } void Game::run() { + m_platform->init(); + if (!m_graphics->init()) { return; } diff --git a/source/Platform/PlatformApplication.cpp b/source/Platform/PlatformApplication.cpp new file mode 100644 index 0000000..f50e54b --- /dev/null +++ b/source/Platform/PlatformApplication.cpp @@ -0,0 +1,21 @@ + +#include "PlatformApplication.h" + +#ifdef SPECTRE_PLATFORM_WIN +#include +typedef sp::Win32Application ApplicationImpl; +#elif SPECTRE_PLATFORM_UNIX +#include +typedef sp::UnixApplication ApplicationImpl; +#else +#error "No Application implementation exists" +#endif + +namespace sp { + +PlatformApplication* PlatformApplication::create() +{ + return new ApplicationImpl; +} + +} // namespace sp diff --git a/source/Platform/PlatformApplication.h b/source/Platform/PlatformApplication.h index 800bf31..d094ca3 100644 --- a/source/Platform/PlatformApplication.h +++ b/source/Platform/PlatformApplication.h @@ -11,6 +11,8 @@ class MessageQueue; class PlatformApplication { public : + static PlatformApplication* create(); + virtual void init() = 0; virtual void shutdown() = 0; diff --git a/source/Platform/PlatformDisplay.cpp b/source/Platform/PlatformDisplay.cpp index 154930e..4cfb3c7 100644 --- a/source/Platform/PlatformDisplay.cpp +++ b/source/Platform/PlatformDisplay.cpp @@ -2,9 +2,12 @@ #include #include "PlatformDisplay.h" -#ifdef _WIN32 +#ifdef SPECTRE_PLATFORM_WIN #include typedef sp::Win32Display DisplayType; +#elif SPECTRE_PLATFORM_UNIX +#include +typedef sp::X11Display DisplayType; #else #error "No Display implementation exists" #endif diff --git a/source/Platform/Unix/GLXContext.cpp b/source/Platform/Unix/GLXContext.cpp new file mode 100644 index 0000000..ea93438 --- /dev/null +++ b/source/Platform/Unix/GLXContext.cpp @@ -0,0 +1,210 @@ + +#include +#include +#include + +#include "glad_glx.h" +#include "Xlib.h" +#include "GLXContext.h" + +namespace sp { + +static bool loadGL() { + + static bool init = false; + if (!init) { + int ver; + init = true; + + ver = gladLoaderLoadGL(); + if (!ver) { + return false; + } + + Log::info("GLX: Opengl Version %d.%d loaded.", + GLAD_VERSION_MAJOR(ver), GLAD_VERSION_MINOR(ver)); + } + + return true; +} + +// Ensure that OpenGL extensions are loaded. +static bool ensureExtensionsLoaded(::Display* disp, int screen) +{ + char msg[1024]; + static bool init = false; + + if (!init) { + int ver; + init = true; + + ver = gladLoaderLoadGLX(disp, screen); + if (!ver) { + Log::warn("GLX: Could not load GLX extensions"); + return false; + } + + snprintf(msg, 1024, "GLX: GLX Version %d.%d loaded", + GLAD_VERSION_MAJOR(ver), GLAD_VERSION_MINOR(ver)); + + // Check for atleast version 1.4 + if (ver < 10004) { + Log::error("%s but atleast version 1.4 is needed.", msg); + return false; + } + + Log::info("%s.", msg); + } + + return true; +} + +GLXContext::GLXContext() : +m_win (0), +m_ctx (NULL) +{ +} + +GLXContext::~GLXContext() +{ + destroy(); +} + +bool GLXContext::create(const PlatformDisplay* display) +{ + // Destroy any previous context first. + destroy(); + + m_win = (::Window) display->getHandle(); + + if (!createGLContext()) { + destroy(); + return false; + } + + return true; +} + +bool GLXContext::createGLContext() +{ + ::Display* disp = Xlib::getDisplay(); + ::GLXFBConfig *fbc; + ::XVisualInfo *info; + int fbcount; + + GLint vi_attr[] = { + GLX_RGBA, + GLX_DEPTH_SIZE, 24, + GLX_DOUBLEBUFFER, 1, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None + }; + + GLint ctx_attr[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 2, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + + // Ensure glx extensions are loaded. + if (!ensureExtensionsLoaded(disp, DefaultScreen(disp))) { + return false; + } + + info = ::glXChooseVisual(disp, DefaultScreen(disp), vi_attr); + if (info == NULL) { + Log::warn("GLX: Could not find a valid VisualInfo."); + return false; + } + + // Setup GL settings. + fbc = glXChooseFBConfig(disp, DefaultScreen(disp), (const int*) info->visual, &fbcount); + if (fbc == NULL) { + Log::warn("GLX: Could not find FB Config."); + return false; + } + + // Create context. + m_ctx = glXCreateContextAttribsARB(disp, fbc[0], NULL, GL_TRUE, ctx_attr); + if (m_ctx == NULL) { + Log::warn("GLX: Failed to create context."); + return false; + } + + glXMakeCurrent(disp, m_win, m_ctx); + + // Load OpenGL + if (!loadGL()) { + Log::warn("GLX: Could not load OpenGL"); + return false; + } + + return true; +} + +void GLXContext::destroy() +{ + if (m_ctx) { + ::glXDestroyContext(Xlib::getDisplay(), m_ctx); + m_ctx = NULL; + } + + m_win = None; +} + +bool GLXContext::activate() +{ + if (m_win && m_ctx) { + return ::glXMakeCurrent(Xlib::getDisplay(), m_win, m_ctx); + } + return false; +} + +bool GLXContext::deactivate() +{ + return ::glXMakeCurrent(Xlib::getDisplay(), None, NULL); +} + +bool GLXContext::isActive() const +{ + return ::glXGetCurrentContext() == m_ctx; +} + +bool GLXContext::setSwapInterval(int interval) +{ + ::Display *disp = Xlib::getDisplay(); + ensureExtensionsLoaded(disp, DefaultScreen(disp)); + + if (GLAD_GLX_MESA_swap_control) { + return glXSwapIntervalMESA(interval); + } + + if (GLAD_GLX_SGI_swap_control) { + return glXSwapIntervalSGI(interval); + } + + return false; +} + +void GLXContext::setSize(unsigned int width, unsigned int height) +{ + // TODO: Not GLX specific! move to generic GLContext class. + if (activate()) { + glViewport(0, 0, width, height); + } +} + +void GLXContext::setSize(const Vector2u size) +{ + setSize(size.x, size.y); +} + +void GLXContext::swapBuffers() +{ + glXSwapBuffers(Xlib::getDisplay(), m_win); +} + +} // namespace sp diff --git a/source/Platform/Unix/GLXContext.h b/source/Platform/Unix/GLXContext.h new file mode 100644 index 0000000..878a6f7 --- /dev/null +++ b/source/Platform/Unix/GLXContext.h @@ -0,0 +1,49 @@ + +#ifndef PLATFORM_UNIX_GLXCONTEXT_H +#define PLATFORM_UNIX_GLXCONTEXT_H + +// X11 OpenGL Context (glx) + +#include "glad_glx.h" +#include + +namespace sp { + +class GLXContext : public GLContext +{ +public : + GLXContext(); + ~GLXContext(); + + // Create a context associated with a display. + bool create(const PlatformDisplay* display); + + void destroy(); + + bool activate(); + + bool deactivate(); + + bool isActive() const; + + bool setSwapInterval(int interval); + + void setSize(unsigned int width, unsigned int height); + + void setSize(const Vector2u size); + + void swapBuffers(); + +private : + bool createGLContext(); + +private : + + ::Window m_win; + + ::GLXContext m_ctx; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_GLXCONTEXT_H */ diff --git a/source/Platform/Unix/UnixApplication.cpp b/source/Platform/Unix/UnixApplication.cpp new file mode 100644 index 0000000..f2c175f --- /dev/null +++ b/source/Platform/Unix/UnixApplication.cpp @@ -0,0 +1,27 @@ + +#include "UnixApplication.h" +#include "Xlib.h" + +namespace sp { + +void UnixApplication::init() +{ + Xlib::init(); +} + +void UnixApplication::shutdown() +{ + Xlib::shutdown(); +} + +PlatformInput& UnixApplication::getInput() +{ + return m_input; +} + +MessageQueue& UnixApplication::getMessageQueue() +{ + return m_messageQueue; +} + +} // namespace sp diff --git a/source/Platform/Unix/UnixApplication.h b/source/Platform/Unix/UnixApplication.h new file mode 100644 index 0000000..1f5c2dc --- /dev/null +++ b/source/Platform/Unix/UnixApplication.h @@ -0,0 +1,30 @@ + +#ifndef PLATFORM_UNIX_APPLICATION_H +#define PLATFORM_UNIX_APPLICATION_H + +#include +#include +#include "X11Input.h" + +namespace sp { + +class UnixApplication : public PlatformApplication +{ +public : + virtual void init(); + + virtual void shutdown(); + + virtual PlatformInput& getInput(); + + virtual MessageQueue& getMessageQueue(); + +protected : + + X11Input m_input; + MessageQueue m_messageQueue; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_APPLICATION_H */ diff --git a/source/Platform/Unix/UnixMisc.cpp b/source/Platform/Unix/UnixMisc.cpp new file mode 100644 index 0000000..fd557f2 --- /dev/null +++ b/source/Platform/Unix/UnixMisc.cpp @@ -0,0 +1,110 @@ + +#include +#include +#include "Xlib.h" +#include +#include + +namespace sp { + +// Code "borrowed" from SFML :) +// see: https://github.com/SFML/SFML/blob/master/src/SFML/Window/Unix/VideoModeImpl.cpp + +void PlatformMisc::GetDisplayModes(std::vector& modes) +{ + ::Display *disp = Xlib::getDisplay(); + + if (disp) { + int scr = DefaultScreen(disp); + + // Check for XRandR. + int ver; + if (XQueryExtension(disp, "RANDR", &ver, &ver, &ver)) { + + XRRScreenConfiguration* config = ::XRRGetScreenInfo(disp, RootWindow(disp, scr)); + if (config) { + int nbSizes; + XRRScreenSize* sizes = ::XRRConfigSizes(config, &nbSizes); + if (sizes && nbSizes > 0) { + int nbDepths = 0; + int* depths = ::XListDepths(disp, scr, &nbDepths); + if (depths && nbDepths > 0) { + + for(int i = 0; i < nbDepths; i++) { + for(int j = 0; j < nbSizes; j++) { + DisplayMode mode(sizes[j].width, sizes[j].height, depths[i]); + + ::Rotation rot; + XRRConfigRotations(config, &rot); + + if (rot == RR_Rotate_90 || rot == RR_Rotate_270) { + std::swap(mode.width, mode.height); + } + + if (std::find(modes.begin(), modes.end(), mode) == modes.end()) { + modes.push_back(mode); + } + } + } + + XFree(depths); + } + } + } else { + Log::error("Failed to get screen configuration while trying to get display modes."); + } + + XRRFreeScreenConfigInfo(config); + } else { + Log::error("Failed to use XRandR extension while trying to get display modes."); + } + } else { + Log::error("Failed to connect to the X server while trying to get display modes."); + } +} + +DisplayMode PlatformMisc::GetDesktopMode() +{ + DisplayMode mode; + + ::Display *disp = Xlib::getDisplay(); + + if (disp) { + int scr = DefaultScreen(disp); + + // Check for XRandR. + int ver; + if (XQueryExtension(disp, "RANDR", &ver, &ver, &ver)) { + + XRRScreenConfiguration* config = ::XRRGetScreenInfo(disp, RootWindow(disp, scr)); + if (config) { + int nbSizes; + ::Rotation rot; + int current = XRRConfigCurrentConfiguration(config, &rot); + + XRRScreenSize* sizes = ::XRRConfigSizes(config, &nbSizes); + if (sizes && nbSizes > 0) { + + mode = DisplayMode(sizes[current].width, sizes[current].height, DefaultDepth(disp, scr)); + + XRRConfigRotations(config, &rot); + if (rot == RR_Rotate_90 || rot == RR_Rotate_270) { + std::swap(mode.width, mode.height); + } + } + } else { + Log::error("Failed to get screen configuration while trying to get desktop display mode."); + } + + XRRFreeScreenConfigInfo(config); + } else { + Log::error("Failed to use XRandR extension while trying to get desktop display mode."); + } + } else { + Log::error("Failed to connect to the X server while trying to get desktop display mode."); + } + + return mode; +} + +} // namespace sp diff --git a/source/Platform/Unix/UnixSystem.cpp b/source/Platform/Unix/UnixSystem.cpp new file mode 100644 index 0000000..68d5384 --- /dev/null +++ b/source/Platform/Unix/UnixSystem.cpp @@ -0,0 +1,31 @@ + +#include +#include +#include + +namespace sp { + +unsigned long system::getMilliseconds() +{ + struct timespec tv; + clock_gettime(CLOCK_REALTIME, &tv); + return (tv.tv_sec * 1000ul) + (tv.tv_nsec / 1000000ul); + +} + +void system::sleep(int milliseconds) +{ + struct timespec req, rem; + req.tv_sec = milliseconds / 1000ul; + req.tv_nsec = (milliseconds - (req.tv_sec * 1000ul)) * 1000000ul; + +_start: + // Try again if we get interrupted. + if (clock_nanosleep(CLOCK_REALTIME, 0, &req, &rem) == EINTR) { + // Update req with remaining time. + req = rem; + goto _start; + } +} + +} // namespace sp diff --git a/source/Platform/Unix/X11Display.cpp b/source/Platform/Unix/X11Display.cpp new file mode 100644 index 0000000..d960670 --- /dev/null +++ b/source/Platform/Unix/X11Display.cpp @@ -0,0 +1,278 @@ + +#include +#include +#include "X11WindowEventHandler.h" +#include "Xlib.h" +#include "GLXContext.h" +#include "X11Display.h" + +// Sometimes not defined in headers. +#ifndef _NET_WM_STATE_TOGGLE +#define _NET_WM_STATE_TOGGLE 2 +#endif + +namespace sp { + +namespace _priv { + + // Pointer to the display that has focus (or NULL if none have). + X11Display* focused_display = NULL; +} + +X11Display* X11Display::getFocused() +{ + return _priv::focused_display; +} + +X11Display:: +X11Display() : +m_screen (0), +m_size (200,200), +m_cur_last (0), +m_cur_hidden (0) +{ +} + +bool X11Display::create(DisplayDescription description) +{ + XSetWindowAttributes attr; + XVisualInfo* vi; + Atom protocols; + Visual* visual; + Window root_win; + ::Display* disp = Xlib::getDisplay(); + + m_screen = DefaultScreen(disp); + root_win = XRootWindow(disp, m_screen); + visual = DefaultVisual(disp, m_screen); + + attr.border_pixel = BlackPixel(disp, m_screen); + attr.background_pixel = WhitePixel(disp, m_screen); + //attr.override_redirect = True; + attr.colormap = ::XCreateColormap(disp, root_win, visual, AllocNone); + // We want InputFocus,Keyboard,Mouse,Resize,Exposure (repaint) events. + attr.event_mask = FocusChangeMask + | KeyPressMask | KeyReleaseMask + | ButtonPressMask | ButtonReleaseMask | PointerMotionMask + | StructureNotifyMask | ExposureMask; + + m_win = ::XCreateWindow(disp, root_win, + 0, 0, /* Position */ + m_size.x, m_size.y, 0 /* Border width */, DefaultDepth(disp, m_screen), + InputOutput, visual, + CWBackPixel | CWColormap | CWBorderPixel | CWEventMask, &attr); + + // Register event handler + X11WindowEventHandler::registerHandler(disp, m_win, this); + + // X11 does not handle pressing the X button on a window. + // that is the job of the window manager. + // Here we can request the WM to send us a delete event so we can handle it ourself. + protocols = Xlib::getAtom("WM_DELETE_WINDOW"); + XSetWMProtocols(disp, m_win, &protocols, 1); + + setVisible(true); + + setSize(description.mode.width, description.mode.height); + + // Clear and take focus + XClearWindow(disp, m_win); + XMapRaised(disp, m_win); + + Log::info("X11: Created display"); + + createHiddenCursor(); + + return true; +} + +void X11Display::destroy() +{ + if (m_win) { + ::Display* disp = Xlib::getDisplay(); + X11WindowEventHandler::unregisterHandler(disp, m_win); + ::XDestroyWindow(disp, m_win); + } +} + +bool X11Display::isValid() +{ + return m_win; +} + +void* X11Display::getHandle() const +{ + return (void*) m_win; +} + +void X11Display::setSize(unsigned int width, unsigned int height) +{ + // X11 does not like if width or height is zero. + if (width == 0) { + width = 1; + } + + if (height == 0) { + height = 1; + } + + m_size = Vector2u(width, height); + ::XResizeWindow(Xlib::getDisplay(), m_win, m_size.x, m_size.y); +} + +Vector2u X11Display::getSize() const +{ + return m_size; +} + +void X11Display::setPosition(unsigned int x, unsigned int y) +{ + ::XMoveWindow(Xlib::getDisplay(), m_win, x, y); +} + +Vector2u X11Display::getPosition() const +{ + Vector2u pos(0, 0); + XWindowAttributes attr; + + if (XGetWindowAttributes(Xlib::getDisplay(), m_win, &attr)) { + pos.x = attr.x; + pos.y = attr.y; + } + return pos; +} + +void X11Display::setVisible(bool visible) +{ + if (visible) { + ::XMapWindow(Xlib::getDisplay(), m_win); + } else { + ::XUnmapWindow(Xlib::getDisplay(), m_win); + } +} + +void X11Display::minimize() +{ + ::XIconifyWindow(Xlib::getDisplay(), m_win, m_screen); +} + +void X11Display::maximize() +{ + ::XClientMessageEvent ev = {}; + ::Display* disp = Xlib::getDisplay(); + + ev.type = ClientMessage; + ev.window = m_win; + ev.message_type = Xlib::getAtom("_NET_WM_STATE"); + ev.format = 32; + ev.data.l[0] = _NET_WM_STATE_TOGGLE; + ev.data.l[1] = Xlib::getAtom("_NET_WM_STATE_MAXIMIZED_HORZ"); + ev.data.l[2] = Xlib::getAtom("_NET_WM_STATE_MAXIMIZED_VERT"); + ev.data.l[3] = 1; + + ::XSendEvent(disp, DefaultRootWindow(disp), False, + SubstructureNotifyMask, (XEvent*) &ev); +} + +void X11Display::setCaption(const std::string& caption) +{ + ::XStoreName(Xlib::getDisplay(), m_win, caption.c_str()); +} + +// TODO: Move this up to the non-platform layer. +void X11Display::setIcon(const std::string& icon) +{ + Image img; + + if (img.loadFromFile(icon)) { + setIcon(img.getWidth(), img.getHeight(), img.getPixels()); + } +} + +void X11Display::setIcon(unsigned int width, unsigned int height, const uint8_t *pixels) +{ + ::Display* disp = Xlib::getDisplay(); + ::Atom net_wm_icon = Xlib::getAtom("_NET_WM_ICON", False); + ::Atom cardinal = Xlib::getAtom("CARDINAL", False); + std::vector buffer(2 + width * height); + uint64_t *ptr = &buffer[0]; + + *ptr++ = width; + *ptr++ = height; + + // TODO: Conversion between differnet formats should be defined as functions in Graphics/PixelFormat.h + for (std::size_t i = 0; i < width * height; i++) { + *ptr++ = (pixels[i * 4 + 2] << 0) + | (pixels[i * 4 + 1] << 8) + | (pixels[i * 4 + 0] << 16) + | (pixels[i * 4 + 3] << 24); + } + + ::XChangeProperty(disp, m_win, + net_wm_icon, cardinal, 32, + PropModeReplace, + reinterpret_cast(&buffer[0]), + 2 + width * height); + + XFlush(disp); +} + +void X11Display::createHiddenCursor() +{ + ::Display* disp = Xlib::getDisplay(); + XColor c; + Pixmap pix = ::XCreatePixmap(disp, m_win, 1, 1, 1); + GC gc = ::XCreateGC(disp, pix, 0, NULL); + + // Draw transparent pixel. + ::XDrawPoint(disp, pix, gc, 0, 0); + + c.red = c.green = c.blue = 0; + c.flags = DoRed | DoGreen | DoBlue; + m_cur_hidden = XCreatePixmapCursor(disp, pix, pix, &c, &c, 0, 0); + + // Free GC and pixmap. + ::XFreePixmap(disp, pix); + ::XFreeGC(disp, gc); +} + +void X11Display::showCursor(bool value) +{ + XDefineCursor(Xlib::getDisplay(), m_win, value ? m_cur_last : m_cur_hidden); +} + +void X11Display::grabCursor(bool value) +{ + // TODO (this is abit harder on X11 than windows.) +} + +void X11Display::processEvent(const ::XEvent& event) +{ + Vector2u size; + + switch(event.xany.type) { + case ConfigureNotify: + size.x = event.xconfigure.width; + size.y = event.xconfigure.height; + + if (m_size != size) { + m_size = size; + Log::info("X11: Resize event"); + onReshape(size.x, size.y); + } + break; + case MotionNotify : + // Generates to much events to log :) + break; + case FocusIn: + Log::debug("X11: FocusIn"); + _priv::focused_display = this; + break; + case FocusOut: + Log::debug("X11: FocusOut"); + _priv::focused_display = NULL; + break; + } +} + +} // namespace sp diff --git a/source/Platform/Unix/X11Display.h b/source/Platform/Unix/X11Display.h new file mode 100644 index 0000000..403aaaf --- /dev/null +++ b/source/Platform/Unix/X11Display.h @@ -0,0 +1,75 @@ + +#ifndef PLATFORM_UNIX_X11DISPLAY_H +#define PLATFORM_UNIX_X11DISPLAY_H + +#include +#include +#include +#include +#include + +namespace sp { + +// NOTE: This class wraps a X11 Window and Screen handle +// and is NOT a Class wrapper around X11's `Display` type. +class X11Display : public PlatformDisplay +{ +public : + + static X11Display* getFocused(); + + X11Display(); + + virtual bool create(DisplayDescription description); + + virtual void destroy(); + + virtual bool isValid(); + + virtual void* getHandle() const; + + virtual void setSize(unsigned int width, unsigned int height); + + virtual Vector2u getSize() const; + + virtual void setPosition(unsigned int x, unsigned int y); + + virtual Vector2u getPosition() const; + + virtual void setVisible(bool visible); + + virtual void minimize(); + + virtual void maximize(); + + virtual void setCaption(const std::string& caption); + + virtual void setIcon(const std::string& icon); + + virtual void setIcon(unsigned int width, unsigned int height, const uint8_t *pixels); + + virtual void showCursor(bool value); + + virtual void grabCursor(bool value); + + void processEvent(const ::XEvent& event); + +protected : + + void createHiddenCursor(); + +protected : + + ::Window m_win; + + int m_screen; + + ::Cursor m_cur_hidden; + ::Cursor m_cur_last; + + Vector2u m_size; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_X11DISPLAY_H */ diff --git a/source/Platform/Unix/X11EventQueue.cpp b/source/Platform/Unix/X11EventQueue.cpp new file mode 100644 index 0000000..86931f8 --- /dev/null +++ b/source/Platform/Unix/X11EventQueue.cpp @@ -0,0 +1,60 @@ + +#include + +#include "X11EventQueue.h" +#include "Xlib.h" +#include "X11Keyboard.h" +#include "X11Mouse.h" +#include "X11WindowEventHandler.h" + +namespace sp { + +bool X11EventQueue::poll(Event& event) +{ + ::Display* disp = Xlib::getDisplay(); + Atom del_win = Xlib::getAtom("WM_DELETE_WINDOW"); + Atom wm_proto = Xlib::getAtom("WM_PROTOCOLS"); + + if (XPending(disp)) { + XEvent xevent; + + XNextEvent(disp, &xevent); + + switch(xevent.type) { + case ClientMessage: + Log::info("X11: ClientMessage"); + + if (xevent.xclient.message_type == wm_proto + && xevent.xclient.data.l[0] == del_win) { + + event.type = Event::Quit; + return true; + } + break; + case ResizeRequest: + Log::info("X11: Resize event"); + break; + case KeyPress: + case KeyRelease: + if (X11Keyboard::handleMessage(&xevent.xkey, event)) { + return true; + } + break; + case ButtonPress: + case ButtonRelease: + case MotionNotify: + if (X11Mouse::handleMessage(&xevent, event)) { + return true; + } + break; + default: + // Pass to window. + Log::info("X11: Window Event"); + X11WindowEventHandler::process(disp, xevent); + } + } + + return false; +} + +} //namespace sp diff --git a/source/Platform/Unix/X11EventQueue.h b/source/Platform/Unix/X11EventQueue.h new file mode 100644 index 0000000..b34c3dc --- /dev/null +++ b/source/Platform/Unix/X11EventQueue.h @@ -0,0 +1,20 @@ + +#ifndef PLATFORM_UNIX_X11_EVENT_QUEUE_H +#define PLATFORM_UNIX_X11_EVENT_QUEUE_H + +#include +#include +#include + +namespace sp { + +class X11EventQueue : public PlatformEventQueue +{ +public : + + virtual bool poll(Event& event); +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_X11_EVENT_QUEUE_H */ diff --git a/source/Platform/Unix/X11Input.cpp b/source/Platform/Unix/X11Input.cpp new file mode 100644 index 0000000..2af3f10 --- /dev/null +++ b/source/Platform/Unix/X11Input.cpp @@ -0,0 +1,22 @@ + +#include "X11Keyboard.h" +#include "X11Mouse.h" +#include "X11Input.h" + +namespace sp { + +Keyboard* X11Input::createKeyboard() +{ + return new X11Keyboard(); +} + +Mouse* X11Input::createMouse() +{ + return new X11Mouse(); +} + +void X11Input::update() +{ +} + +} // namespace sp diff --git a/source/Platform/Unix/X11Input.h b/source/Platform/Unix/X11Input.h new file mode 100644 index 0000000..6bb7439 --- /dev/null +++ b/source/Platform/Unix/X11Input.h @@ -0,0 +1,21 @@ + +#ifndef PLATFORM_UNIX_X11INPUT_H +#define PLATFORM_UNIX_X11INPUT_H + +#include + +namespace sp { + +class X11Input : public PlatformInput +{ +public : + virtual Keyboard* createKeyboard(); + + virtual Mouse* createMouse(); + + virtual void update(); +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_X11INPUT_H */ diff --git a/source/Platform/Unix/X11Keyboard.cpp b/source/Platform/Unix/X11Keyboard.cpp new file mode 100644 index 0000000..b345ecb --- /dev/null +++ b/source/Platform/Unix/X11Keyboard.cpp @@ -0,0 +1,368 @@ + +#include +#include "X11Keyboard.h" +#include "X11Display.h" +#include "Xlib.h" +#include +#include +#include + +namespace sp { + +static Keyboard::Key KeySymToKeyboardKey(KeySym key) { + + switch(key) { + // Letters + case XK_A: case XK_a: + return Keyboard::Key::A; + case XK_B: case XK_b: + return Keyboard::Key::B; + case XK_C: case XK_c: + return Keyboard::Key::C; + case XK_D: case XK_d: + return Keyboard::Key::D; + case XK_E: case XK_e: + return Keyboard::Key::E; + case XK_F: case XK_f: + return Keyboard::Key::F; + case XK_G: case XK_g: + return Keyboard::Key::G; + case XK_H: case XK_h: + return Keyboard::Key::H; + case XK_I: case XK_i: + return Keyboard::Key::I; + case XK_J: case XK_j: + return Keyboard::Key::J; + case XK_K: case XK_k: + return Keyboard::Key::K; + case XK_L: case XK_l: + return Keyboard::Key::L; + case XK_M: case XK_m: + return Keyboard::Key::M; + case XK_N: case XK_n: + return Keyboard::Key::N; + case XK_O: case XK_o: + return Keyboard::Key::O; + case XK_P: case XK_p: + return Keyboard::Key::P; + case XK_Q: case XK_q: + return Keyboard::Key::Q; + case XK_R: case XK_r: + return Keyboard::Key::R; + case XK_S: case XK_s: + return Keyboard::Key::S; + case XK_T: case XK_t: + return Keyboard::Key::T; + case XK_U: case XK_u: + return Keyboard::Key::U; + case XK_V: case XK_v: + return Keyboard::Key::V; + case XK_W: case XK_w: + return Keyboard::Key::W; + case XK_X: case XK_x: + return Keyboard::Key::X; + case XK_Y: case XK_y: + return Keyboard::Key::Y; + case XK_Z: case XK_z: + return Keyboard::Key::Z; + + // Numbers + case XK_1: + return Keyboard::Key::One; + case XK_2: + return Keyboard::Key::Two; + case XK_3: + return Keyboard::Key::Three; + case XK_4: + return Keyboard::Key::Four; + case XK_5: + return Keyboard::Key::Five; + case XK_6: + return Keyboard::Key::Six; + case XK_7: + return Keyboard::Key::Seven; + case XK_8: + return Keyboard::Key::Eight; + case XK_9: + return Keyboard::Key::Nine; + case XK_0: + return Keyboard::Key::Zero; + + case XK_period : + return Keyboard::Key::Period; + case XK_comma : + return Keyboard::Key::Comma; + case XK_Return : + return Keyboard::Key::Enter; + case XK_BackSpace : + return Keyboard::Key::Backspace; + case XK_Escape : + return Keyboard::Key::Escape; + case XK_space : + return Keyboard::Key::Space; + case XK_Caps_Lock : + return Keyboard::Key::Capslock; + + // Arrows + case XK_Up : + return Keyboard::Key::Up; + case XK_Down : + return Keyboard::Key::Down; + case XK_Left : + return Keyboard::Key::Left; + case XK_Right : + return Keyboard::Key::Right; + + // Numpad + + case XK_KP_1 : case XK_KP_End : + return Keyboard::Key::Numpad1; + case XK_KP_2 : case XK_KP_Down : + return Keyboard::Key::Numpad2; + case XK_KP_3 : case XK_KP_Page_Down : + return Keyboard::Key::Numpad3; + case XK_KP_4 : case XK_KP_Left : + return Keyboard::Key::Numpad4; + case XK_KP_5 : case XK_KP_Begin : + return Keyboard::Key::Numpad5; + case XK_KP_6 : case XK_KP_Right : + return Keyboard::Key::Numpad6; + case XK_KP_7 : case XK_KP_Home : + return Keyboard::Key::Numpad7; + case XK_KP_8 : case XK_KP_Up : + return Keyboard::Key::Numpad8; + case XK_KP_9 : case XK_KP_Page_Up : + return Keyboard::Key::Numpad9; + case XK_KP_0 : case XK_KP_Insert : + return Keyboard::Key::Numpad0; + + case XK_Home : + return Keyboard::Key::Home; + case XK_End : + return Keyboard::Key::End; + case XK_Insert : + return Keyboard::Key::Insert; + case XK_Delete : + return Keyboard::Key::Delete; + case XK_Page_Up : + return Keyboard::Key::PageUp; + case XK_Page_Down : + return Keyboard::Key::PageDown; + case XK_Pause : + return Keyboard::Key::Pause; + + + // Function keys + case XK_F1 : + return Keyboard::Key::F1; + case XK_F2 : + return Keyboard::Key::F2; + case XK_F3 : + return Keyboard::Key::F3; + case XK_F4 : + return Keyboard::Key::F4; + case XK_F5 : + return Keyboard::Key::F5; + case XK_F6 : + return Keyboard::Key::F6; + case XK_F7 : + return Keyboard::Key::F7; + case XK_F8 : + return Keyboard::Key::F8; + case XK_F9 : + return Keyboard::Key::F9; + case XK_F10 : + return Keyboard::Key::F10; + case XK_F11 : + return Keyboard::Key::F11; + case XK_F12 : + return Keyboard::Key::F12; + + case XK_Tab : + return Keyboard::Key::Tab; + case XK_Shift_L : + return Keyboard::Key::LShift; + case XK_Shift_R : + return Keyboard::Key::RShift; + case XK_Control_L : + return Keyboard::Key::LCtrl; + case XK_Control_R : + return Keyboard::Key::RCtrl; + case XK_Alt_L : + return Keyboard::Key::LAlt; + case XK_Alt_R : +#ifdef XK_XKB_KEYS + case XK_ISO_Level3_Shift : +#endif /* XK_XKB_KEYS */ + return Keyboard::Key::RAlt; + + default: + sp::Log::debug("X11Keyboard - Unknown keycode: 0x%X", key); + return Keyboard::Key::Unknown; + }; +} + +X11Keyboard::X11Keyboard() : +m_disp(NULL), +m_win(0) +{ + memset(m_key_state, 0, sizeof(m_key_state) / sizeof(m_key_state[0])); +} + +X11Keyboard::~X11Keyboard() +{ +} + +void X11Keyboard::init() +{ +} + +bool X11Keyboard::isKeyDown(Keyboard::Key key) +{ + KeySym sym; + + // Only signal that a button is down + // if we have focus on a window. + if (!m_win) { + return false; + } + + switch(key) { + // Letters + case Keyboard::Key::A : sym = XK_a; break; + case Keyboard::Key::B : sym = XK_b; break; + case Keyboard::Key::C : sym = XK_c; break; + case Keyboard::Key::D : sym = XK_d; break; + case Keyboard::Key::E : sym = XK_e; break; + case Keyboard::Key::F : sym = XK_f; break; + case Keyboard::Key::G : sym = XK_g; break; + case Keyboard::Key::H : sym = XK_h; break; + case Keyboard::Key::I : sym = XK_i; break; + case Keyboard::Key::J : sym = XK_j; break; + case Keyboard::Key::K : sym = XK_k; break; + case Keyboard::Key::L : sym = XK_l; break; + case Keyboard::Key::M : sym = XK_m; break; + case Keyboard::Key::N : sym = XK_n; break; + case Keyboard::Key::O : sym = XK_o; break; + case Keyboard::Key::P : sym = XK_p; break; + case Keyboard::Key::Q : sym = XK_q; break; + case Keyboard::Key::R : sym = XK_r; break; + case Keyboard::Key::S : sym = XK_s; break; + case Keyboard::Key::T : sym = XK_t; break; + case Keyboard::Key::U : sym = XK_u; break; + case Keyboard::Key::V : sym = XK_v; break; + case Keyboard::Key::W : sym = XK_w; break; + case Keyboard::Key::X : sym = XK_x; break; + case Keyboard::Key::Y : sym = XK_y; break; + case Keyboard::Key::Z : sym = XK_z; break; + + // Numbers + case Keyboard::Key::One : sym = XK_1; break; + case Keyboard::Key::Two : sym = XK_2; break; + case Keyboard::Key::Three : sym = XK_3; break; + case Keyboard::Key::Four : sym = XK_4; break; + case Keyboard::Key::Five : sym = XK_5; break; + case Keyboard::Key::Six : sym = XK_6; break; + case Keyboard::Key::Seven : sym = XK_7; break; + case Keyboard::Key::Eight : sym = XK_8; break; + case Keyboard::Key::Nine : sym = XK_9; break; + case Keyboard::Key::Zero : sym = XK_0; break; + + case Keyboard::Key::Period : sym = XK_period; break; + case Keyboard::Key::Comma : sym = XK_comma; break; + case Keyboard::Key::Enter : sym = XK_Return; break; + case Keyboard::Key::Backspace : sym = XK_BackSpace; break; + case Keyboard::Key::Escape : sym = XK_Escape; break; + case Keyboard::Key::Space : sym = XK_space; break; + case Keyboard::Key::Capslock : sym = XK_Caps_Lock; break; + + // Arrows + case Keyboard::Key::Up : sym = XK_Up; break; + case Keyboard::Key::Down : sym = XK_Down; break; + case Keyboard::Key::Left : sym = XK_Left; break; + case Keyboard::Key::Right : sym = XK_Right; break; + + // Numpad + case Keyboard::Key::Numpad1 : sym = XK_KP_1; break; + case Keyboard::Key::Numpad2 : sym = XK_KP_2; break; + case Keyboard::Key::Numpad3 : sym = XK_KP_3; break; + case Keyboard::Key::Numpad4 : sym = XK_KP_4; break; + case Keyboard::Key::Numpad5 : sym = XK_KP_5; break; + case Keyboard::Key::Numpad6 : sym = XK_KP_6; break; + case Keyboard::Key::Numpad7 : sym = XK_KP_7; break; + case Keyboard::Key::Numpad8 : sym = XK_KP_8; break; + case Keyboard::Key::Numpad9 : sym = XK_KP_9; break; + case Keyboard::Key::Numpad0 : sym = XK_KP_0; break; + + case Keyboard::Key::Home : sym = XK_Home; break; + case Keyboard::Key::End : sym = XK_End; break; + case Keyboard::Key::Insert : sym = XK_Insert; break; + case Keyboard::Key::Delete : sym = XK_Delete; break; + case Keyboard::Key::PageUp : sym = XK_Page_Up; break; + case Keyboard::Key::PageDown : sym = XK_Page_Down; break; + case Keyboard::Key::Pause : sym = XK_Pause; break; + + // Function keys + case Keyboard::Key::F1 : sym = XK_F1; break; + case Keyboard::Key::F2 : sym = XK_F2; break; + case Keyboard::Key::F3 : sym = XK_F3; break; + case Keyboard::Key::F4 : sym = XK_F4; break; + case Keyboard::Key::F5 : sym = XK_F5; break; + case Keyboard::Key::F6 : sym = XK_F6; break; + case Keyboard::Key::F7 : sym = XK_F7; break; + case Keyboard::Key::F8 : sym = XK_F8; break; + case Keyboard::Key::F9 : sym = XK_F9; break; + case Keyboard::Key::F10 : sym = XK_F10; break; + case Keyboard::Key::F11 : sym = XK_F11; break; + case Keyboard::Key::F12 : sym = XK_F12; break; + + case Keyboard::Key::Tab : sym = XK_Tab; break; + case Keyboard::Key::LShift : sym = XK_Shift_L; break; + case Keyboard::Key::RShift : sym = XK_Shift_R; break; + case Keyboard::Key::LCtrl : sym = XK_Control_L; break; + case Keyboard::Key::RCtrl : sym = XK_Control_R; break; + case Keyboard::Key::LAlt : sym = XK_Alt_L; break; +#ifdef XK_XKB_KEYS + case Keyboard::Key::RAlt : sym = XK_ISO_Level3_Shift; break; +#else + case Keyboard::Key::RAlt : sym = XK_Alt_R; break; +#endif /* XK_XKB_KEYS */ + default : sym = 0; break; + } + + KeyCode keycode = ::XKeysymToKeycode(Xlib::getDisplay(), sym); + + if (keycode) { + return m_key_state[keycode / 8] & (1 << (keycode % 8)); + } + return false; +} + +bool X11Keyboard::handleMessage(XKeyEvent* xkeyevent, Event& event) +{ + KeySym sym = ::XLookupKeysym(xkeyevent, 0); + Keyboard::Key code = KeySymToKeyboardKey(sym); + + if (code != Keyboard::Key::Unknown) { + event.type = Event::Key; + event.key.code = code; + event.key.pressed = xkeyevent->type == KeyPress; + return true; + } + return false; +} + +void X11Keyboard::update(InputModule *input) +{ + X11Display *focus = X11Display::getFocused(); + m_win = focus ? (::Window) focus->getHandle() : 0; + + // If we have focus. + if (m_win) { + + // Query keyboard state. + ::XQueryKeymap(Xlib::getDisplay(), m_key_state); + } +} + +} // namespace sp diff --git a/source/Platform/Unix/X11Keyboard.h b/source/Platform/Unix/X11Keyboard.h new file mode 100644 index 0000000..3140160 --- /dev/null +++ b/source/Platform/Unix/X11Keyboard.h @@ -0,0 +1,38 @@ + +#ifndef PLATFORM_UNIX_X11KEYBOARD_H +#define PLATFORM_UNIX_X11KEYBOARD_H + +#include +#include +#include + +namespace sp { + +class X11Keyboard : public Keyboard +{ +public : + X11Keyboard(); + ~X11Keyboard(); + + void init(); + + bool isKeyDown(Keyboard::Key key); + + // Translate a XKeyEvent to sp::Event, Called from X11EventQueue + static bool handleMessage(XKeyEvent* xkeyevent, Event& event); + +protected : + + virtual void update(InputModule *input); + +private : + ::Display* m_disp; + ::Window m_win; // Focused window + + // Cached keyboard state. + char m_key_state[32]; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_X11KEYBOARD_H */ diff --git a/source/Platform/Unix/X11Mouse.cpp b/source/Platform/Unix/X11Mouse.cpp new file mode 100644 index 0000000..f4bd651 --- /dev/null +++ b/source/Platform/Unix/X11Mouse.cpp @@ -0,0 +1,135 @@ + +#include +#include +#include "Xlib.h" +#include "X11Display.h" +#include "X11Mouse.h" + +#define XBUTTON1BIT (1<<0) +#define XBUTTON2BIT (1<<1) + +namespace sp { + +namespace _priv { + + // Variable to handle extra button state (not queryable in xlib) + unsigned int xstate = 0; +} + +X11Mouse::X11Mouse() : +m_btn_state(0) +{ +} + +void X11Mouse::init() +{ + updateFocusedWindow(); +} + +Vector2f X11Mouse::getPosition() const +{ + return m_position; +} + +Vector2f X11Mouse::getAbsPosition() const +{ + return m_abs_position; +} + +bool X11Mouse::isButtonDown(Mouse::Button button) const +{ + // Only signal that a button is down + // if we have focus on a window. + if (!m_win) { + return false; + } + + switch(button) { + case Mouse::Button::Left : + return m_btn_state & Button1Mask; + case Mouse::Button::Right : + return m_btn_state & Button3Mask; + case Mouse::Button::Middle : + return m_btn_state & Button2Mask; + case Mouse::Button::XButton1 : + return _priv::xstate & XBUTTON1BIT; + case Mouse::Button::XButton2 : + return _priv::xstate & XBUTTON2BIT; + default : + return false; + } + return false; +} + +void X11Mouse::update(InputModule *input) +{ + ::Display* disp = Xlib::getDisplay(); + ::Window root, child; + int rx, ry, x = 0, y = 0; + + updateFocusedWindow(); + + // Query position and button state. + XQueryPointer(disp, + m_win ? m_win : ::XDefaultRootWindow(disp), + &root, &child, + &rx, &ry, + &x, &y, &m_btn_state); + + // Update abs position (relative to root). + m_abs_position.x = rx; + m_abs_position.y = ry; + + // Update window position. + if (m_win) { + m_position.x = x; + m_position.y = y; + } +} + +void X11Mouse::updateFocusedWindow() +{ + X11Display *focus = X11Display::getFocused(); + m_win = focus ? (::Window) focus->getHandle() : 0; +} + +#define SETXSTATE(bit) \ + _priv::xstate = (xevent->type == ButtonPress) \ + ? _priv::xstate | (bit) \ + : _priv::xstate & ~(bit) + +bool X11Mouse::handleMessage(XEvent* xevent, Event& event) +{ + if (xevent->type == MotionNotify) { + event.type = Event::MouseMove; + event.mouseMove.x = xevent->xmotion.x; + event.mouseMove.y = xevent->xmotion.y; + return true; + } + + if (xevent->type == ButtonPress || xevent->type == ButtonRelease) { + + Mouse::Button trans = Mouse::Button::Unknown; + + switch(xevent->xbutton.button) { + case Button1 : trans = Mouse::Button::Left; break; + case Button2 : trans = Mouse::Button::Middle; break; + case Button3 : trans = Mouse::Button::Right; break; + // Xlib do not support querying of button 8 and 9. + // so we have to fake it. + case 8 : trans = Mouse::Button::XButton1; SETXSTATE(XBUTTON1BIT); break; + case 9 : trans = Mouse::Button::XButton2; SETXSTATE(XBUTTON2BIT); break; + } + + if (trans != Mouse::Button::Unknown) { + event.type = Event::MouseButton; + event.mouseButton.pressed = xevent->type == ButtonPress; + event.mouseButton.button = trans; + return true; + } + } + + return false; +} + +} // namespace sp diff --git a/source/Platform/Unix/X11Mouse.h b/source/Platform/Unix/X11Mouse.h new file mode 100644 index 0000000..9cb0872 --- /dev/null +++ b/source/Platform/Unix/X11Mouse.h @@ -0,0 +1,45 @@ + +#ifndef PLATFORM_UNIX_X11MOUSE_H +#define PLATFORM_UNIX_X11MOUSE_H + +#include +#include + +namespace sp { + +class X11Mouse : public Mouse +{ +public : + X11Mouse(); + + virtual void init(); + + // Get mouse position + virtual Vector2f getPosition() const; + + virtual Vector2f getAbsPosition() const; + + virtual bool isButtonDown(Mouse::Button button) const; + + // Translate a XEvent to sp::Event, Called from X11EventQueue + static bool handleMessage(XEvent* xevent, Event& event); + +protected : + + virtual void update(InputModule *input); + + void updateFocusedWindow(); + +protected : + ::Window m_win; // Focused window. + + Vector2f m_position; + + Vector2f m_abs_position; + + unsigned int m_btn_state; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_X11MOUSE_H */ diff --git a/source/Platform/Unix/X11WindowEventHandler.cpp b/source/Platform/Unix/X11WindowEventHandler.cpp new file mode 100644 index 0000000..fa6eb45 --- /dev/null +++ b/source/Platform/Unix/X11WindowEventHandler.cpp @@ -0,0 +1,51 @@ + +#include +#include "X11Display.h" +#include "X11WindowEventHandler.h" +#include + +namespace sp { + +// Context used to store X11Display pointer. +::XContext X11WindowEventHandler::win_context = None; + +void X11WindowEventHandler::registerHandler(::Display* disp, ::Window window, X11Display *ptr) +{ + // Initialize context before use. + if (win_context == None) { + win_context = XUniqueContext(); + } + + // Save pointer to window. + XSaveContext(disp, window, win_context, (XPointer) ptr); +} + +void X11WindowEventHandler::unregisterHandler(::Display* disp, ::Window window) +{ + // No context. nothing to do. + if (win_context == None) { + return; + } + + XDeleteContext(disp, window, win_context); +} + +void X11WindowEventHandler::process(::Display* disp, const ::XEvent& event) +{ + XPointer ptr; + + // No context. nothing to do. + if (win_context == None) { + return; + } + + // Get the pointer for window ID. + if (XFindContext(disp, event.xany.window, win_context, &ptr) == 0) { + X11Display* disp_ptr = (X11Display*) ptr; + + // Delegate + disp_ptr->processEvent(event); + } +} + +} // namespace sp diff --git a/source/Platform/Unix/X11WindowEventHandler.h b/source/Platform/Unix/X11WindowEventHandler.h new file mode 100644 index 0000000..79f6ed2 --- /dev/null +++ b/source/Platform/Unix/X11WindowEventHandler.h @@ -0,0 +1,29 @@ + +#ifndef PLATFORM_UNIX_X11_WINDOW_EVENT_HANDLER_H +#define PLATFORM_UNIX_X11_WINDOW_EVENT_HANDLER_H + +#include +#include + +namespace sp { + +class X11Display; + +class X11WindowEventHandler +{ +public: + + static void registerHandler(::Display* disp, ::Window window, X11Display *ptr); + + static void unregisterHandler(::Display* disp, ::Window window); + + static void process(::Display* disp, const ::XEvent& event); + +protected : + + static ::XContext win_context; +}; + +} // namespace sp + +#endif /* PLATFORM_UNIX_WINDOW_EVENT_HANDLER_H */ diff --git a/source/Platform/Unix/Xlib.cpp b/source/Platform/Unix/Xlib.cpp new file mode 100644 index 0000000..32e36fb --- /dev/null +++ b/source/Platform/Unix/Xlib.cpp @@ -0,0 +1,34 @@ + +#include +#include "Xlib.h" + +namespace sp { namespace Xlib { + +namespace _priv { + // Define a global display (for simplicity, we always connect to local one.) + ::Display* display = NULL; +}; + +void init() +{ + _priv::display = XOpenDisplay(NULL); +} + +void shutdown() +{ + XCloseDisplay(_priv::display); + _priv::display = NULL; +} + +::Display* getDisplay() +{ + assert(_priv::display != NULL); + return _priv::display; +} + +::Atom getAtom(const std::string& name, bool onlyIfExists) +{ + return XInternAtom(getDisplay(), name.c_str(), onlyIfExists); +} + +} } // namespace sp::Xlib diff --git a/source/Platform/Unix/Xlib.h b/source/Platform/Unix/Xlib.h new file mode 100644 index 0000000..cc5cb2d --- /dev/null +++ b/source/Platform/Unix/Xlib.h @@ -0,0 +1,22 @@ + +#ifndef SPECTRE_PLATFORM_UNIX_XLIB_H +#define SPECTRE_PLATFORM_UNIX_XLIB_H + +#include +#include + +// Wrapper for some Xlib functions. + +namespace sp { namespace Xlib { + +void init(); + +void shutdown(); + +::Display* getDisplay(); + +::Atom getAtom(const std::string& name, bool onlyIfExists = false); + +} } // namespace sp::xlib + +#endif /* SPECTRE_PLATFORM_UNIX_XLIB_H */ diff --git a/source/Platform/Unix/glad_glx.c b/source/Platform/Unix/glad_glx.c new file mode 100644 index 0000000..c9af335 --- /dev/null +++ b/source/Platform/Unix/glad_glx.c @@ -0,0 +1,382 @@ +#include +#include +#include +#include "glad_glx.h" + +#ifndef GLAD_IMPL_UTIL_C_ +#define GLAD_IMPL_UTIL_C_ + +#ifdef _MSC_VER +#define GLAD_IMPL_UTIL_SSCANF sscanf_s +#else +#define GLAD_IMPL_UTIL_SSCANF sscanf +#endif + +#endif /* GLAD_IMPL_UTIL_C_ */ + + +int GLAD_GLX_VERSION_1_0 = 0; +int GLAD_GLX_VERSION_1_1 = 0; +int GLAD_GLX_VERSION_1_2 = 0; +int GLAD_GLX_VERSION_1_3 = 0; +int GLAD_GLX_VERSION_1_4 = 0; +int GLAD_GLX_ARB_create_context = 0; +int GLAD_GLX_ARB_create_context_profile = 0; +int GLAD_GLX_ARB_get_proc_address = 0; +int GLAD_GLX_EXT_swap_control = 0; +int GLAD_GLX_MESA_swap_control = 0; +int GLAD_GLX_SGI_swap_control = 0; + + + +PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig = NULL; +PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual = NULL; +PFNGLXCOPYCONTEXTPROC glad_glXCopyContext = NULL; +PFNGLXCREATECONTEXTPROC glad_glXCreateContext = NULL; +PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB = NULL; +PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap = NULL; +PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext = NULL; +PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer = NULL; +PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap = NULL; +PFNGLXCREATEWINDOWPROC glad_glXCreateWindow = NULL; +PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext = NULL; +PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap = NULL; +PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer = NULL; +PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap = NULL; +PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow = NULL; +PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString = NULL; +PFNGLXGETCONFIGPROC glad_glXGetConfig = NULL; +PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext = NULL; +PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay = NULL; +PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable = NULL; +PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable = NULL; +PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib = NULL; +PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs = NULL; +PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress = NULL; +PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB = NULL; +PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent = NULL; +PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA = NULL; +PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig = NULL; +PFNGLXISDIRECTPROC glad_glXIsDirect = NULL; +PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent = NULL; +PFNGLXMAKECURRENTPROC glad_glXMakeCurrent = NULL; +PFNGLXQUERYCONTEXTPROC glad_glXQueryContext = NULL; +PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable = NULL; +PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension = NULL; +PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString = NULL; +PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString = NULL; +PFNGLXQUERYVERSIONPROC glad_glXQueryVersion = NULL; +PFNGLXSELECTEVENTPROC glad_glXSelectEvent = NULL; +PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers = NULL; +PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT = NULL; +PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA = NULL; +PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI = NULL; +PFNGLXUSEXFONTPROC glad_glXUseXFont = NULL; +PFNGLXWAITGLPROC glad_glXWaitGL = NULL; +PFNGLXWAITXPROC glad_glXWaitX = NULL; + + +static void glad_glx_load_GLX_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_VERSION_1_0) return; + glad_glXChooseVisual = (PFNGLXCHOOSEVISUALPROC) load(userptr, "glXChooseVisual"); + glad_glXCopyContext = (PFNGLXCOPYCONTEXTPROC) load(userptr, "glXCopyContext"); + glad_glXCreateContext = (PFNGLXCREATECONTEXTPROC) load(userptr, "glXCreateContext"); + glad_glXCreateGLXPixmap = (PFNGLXCREATEGLXPIXMAPPROC) load(userptr, "glXCreateGLXPixmap"); + glad_glXDestroyContext = (PFNGLXDESTROYCONTEXTPROC) load(userptr, "glXDestroyContext"); + glad_glXDestroyGLXPixmap = (PFNGLXDESTROYGLXPIXMAPPROC) load(userptr, "glXDestroyGLXPixmap"); + glad_glXGetConfig = (PFNGLXGETCONFIGPROC) load(userptr, "glXGetConfig"); + glad_glXGetCurrentContext = (PFNGLXGETCURRENTCONTEXTPROC) load(userptr, "glXGetCurrentContext"); + glad_glXGetCurrentDrawable = (PFNGLXGETCURRENTDRAWABLEPROC) load(userptr, "glXGetCurrentDrawable"); + glad_glXIsDirect = (PFNGLXISDIRECTPROC) load(userptr, "glXIsDirect"); + glad_glXMakeCurrent = (PFNGLXMAKECURRENTPROC) load(userptr, "glXMakeCurrent"); + glad_glXQueryExtension = (PFNGLXQUERYEXTENSIONPROC) load(userptr, "glXQueryExtension"); + glad_glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion"); + glad_glXSwapBuffers = (PFNGLXSWAPBUFFERSPROC) load(userptr, "glXSwapBuffers"); + glad_glXUseXFont = (PFNGLXUSEXFONTPROC) load(userptr, "glXUseXFont"); + glad_glXWaitGL = (PFNGLXWAITGLPROC) load(userptr, "glXWaitGL"); + glad_glXWaitX = (PFNGLXWAITXPROC) load(userptr, "glXWaitX"); +} +static void glad_glx_load_GLX_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_VERSION_1_1) return; + glad_glXGetClientString = (PFNGLXGETCLIENTSTRINGPROC) load(userptr, "glXGetClientString"); + glad_glXQueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC) load(userptr, "glXQueryExtensionsString"); + glad_glXQueryServerString = (PFNGLXQUERYSERVERSTRINGPROC) load(userptr, "glXQueryServerString"); +} +static void glad_glx_load_GLX_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_VERSION_1_2) return; + glad_glXGetCurrentDisplay = (PFNGLXGETCURRENTDISPLAYPROC) load(userptr, "glXGetCurrentDisplay"); +} +static void glad_glx_load_GLX_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_VERSION_1_3) return; + glad_glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) load(userptr, "glXChooseFBConfig"); + glad_glXCreateNewContext = (PFNGLXCREATENEWCONTEXTPROC) load(userptr, "glXCreateNewContext"); + glad_glXCreatePbuffer = (PFNGLXCREATEPBUFFERPROC) load(userptr, "glXCreatePbuffer"); + glad_glXCreatePixmap = (PFNGLXCREATEPIXMAPPROC) load(userptr, "glXCreatePixmap"); + glad_glXCreateWindow = (PFNGLXCREATEWINDOWPROC) load(userptr, "glXCreateWindow"); + glad_glXDestroyPbuffer = (PFNGLXDESTROYPBUFFERPROC) load(userptr, "glXDestroyPbuffer"); + glad_glXDestroyPixmap = (PFNGLXDESTROYPIXMAPPROC) load(userptr, "glXDestroyPixmap"); + glad_glXDestroyWindow = (PFNGLXDESTROYWINDOWPROC) load(userptr, "glXDestroyWindow"); + glad_glXGetCurrentReadDrawable = (PFNGLXGETCURRENTREADDRAWABLEPROC) load(userptr, "glXGetCurrentReadDrawable"); + glad_glXGetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC) load(userptr, "glXGetFBConfigAttrib"); + glad_glXGetFBConfigs = (PFNGLXGETFBCONFIGSPROC) load(userptr, "glXGetFBConfigs"); + glad_glXGetSelectedEvent = (PFNGLXGETSELECTEDEVENTPROC) load(userptr, "glXGetSelectedEvent"); + glad_glXGetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) load(userptr, "glXGetVisualFromFBConfig"); + glad_glXMakeContextCurrent = (PFNGLXMAKECONTEXTCURRENTPROC) load(userptr, "glXMakeContextCurrent"); + glad_glXQueryContext = (PFNGLXQUERYCONTEXTPROC) load(userptr, "glXQueryContext"); + glad_glXQueryDrawable = (PFNGLXQUERYDRAWABLEPROC) load(userptr, "glXQueryDrawable"); + glad_glXSelectEvent = (PFNGLXSELECTEVENTPROC) load(userptr, "glXSelectEvent"); +} +static void glad_glx_load_GLX_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_VERSION_1_4) return; + glad_glXGetProcAddress = (PFNGLXGETPROCADDRESSPROC) load(userptr, "glXGetProcAddress"); +} +static void glad_glx_load_GLX_ARB_create_context( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_ARB_create_context) return; + glad_glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) load(userptr, "glXCreateContextAttribsARB"); +} +static void glad_glx_load_GLX_ARB_get_proc_address( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_ARB_get_proc_address) return; + glad_glXGetProcAddressARB = (PFNGLXGETPROCADDRESSARBPROC) load(userptr, "glXGetProcAddressARB"); +} +static void glad_glx_load_GLX_EXT_swap_control( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_EXT_swap_control) return; + glad_glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) load(userptr, "glXSwapIntervalEXT"); +} +static void glad_glx_load_GLX_MESA_swap_control( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_MESA_swap_control) return; + glad_glXGetSwapIntervalMESA = (PFNGLXGETSWAPINTERVALMESAPROC) load(userptr, "glXGetSwapIntervalMESA"); + glad_glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC) load(userptr, "glXSwapIntervalMESA"); +} +static void glad_glx_load_GLX_SGI_swap_control( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GLX_SGI_swap_control) return; + glad_glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) load(userptr, "glXSwapIntervalSGI"); +} + + + +static int glad_glx_has_extension(Display *display, int screen, const char *ext) { +#ifndef GLX_VERSION_1_1 + (void) display; + (void) screen; + (void) ext; +#else + const char *terminator; + const char *loc; + const char *extensions; + + if (glXQueryExtensionsString == NULL) { + return 0; + } + + extensions = glXQueryExtensionsString(display, screen); + + if(extensions == NULL || ext == NULL) { + return 0; + } + + while(1) { + loc = strstr(extensions, ext); + if(loc == NULL) + break; + + terminator = loc + strlen(ext); + if((loc == extensions || *(loc - 1) == ' ') && + (*terminator == ' ' || *terminator == '\0')) { + return 1; + } + extensions = terminator; + } +#endif + + return 0; +} + +static GLADapiproc glad_glx_get_proc_from_userptr(void *userptr, const char* name) { + return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); +} + +static int glad_glx_find_extensions(Display *display, int screen) { + GLAD_GLX_ARB_create_context = glad_glx_has_extension(display, screen, "GLX_ARB_create_context"); + GLAD_GLX_ARB_create_context_profile = glad_glx_has_extension(display, screen, "GLX_ARB_create_context_profile"); + GLAD_GLX_ARB_get_proc_address = glad_glx_has_extension(display, screen, "GLX_ARB_get_proc_address"); + GLAD_GLX_EXT_swap_control = glad_glx_has_extension(display, screen, "GLX_EXT_swap_control"); + GLAD_GLX_MESA_swap_control = glad_glx_has_extension(display, screen, "GLX_MESA_swap_control"); + GLAD_GLX_SGI_swap_control = glad_glx_has_extension(display, screen, "GLX_SGI_swap_control"); + return 1; +} + +static int glad_glx_find_core_glx(Display **display, int *screen) { + int major = 0, minor = 0; + if(*display == NULL) { +#ifdef GLAD_GLX_NO_X11 + (void) screen; + return 0; +#else + *display = XOpenDisplay(0); + if (*display == NULL) { + return 0; + } + *screen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(*display)); +#endif + } + glXQueryVersion(*display, &major, &minor); + GLAD_GLX_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; + GLAD_GLX_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; + GLAD_GLX_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; + GLAD_GLX_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; + GLAD_GLX_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1; + return GLAD_MAKE_VERSION(major, minor); +} + +int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr) { + int version; + glXQueryVersion = (PFNGLXQUERYVERSIONPROC) load(userptr, "glXQueryVersion"); + if(glXQueryVersion == NULL) return 0; + version = glad_glx_find_core_glx(&display, &screen); + + glad_glx_load_GLX_VERSION_1_0(load, userptr); + glad_glx_load_GLX_VERSION_1_1(load, userptr); + glad_glx_load_GLX_VERSION_1_2(load, userptr); + glad_glx_load_GLX_VERSION_1_3(load, userptr); + glad_glx_load_GLX_VERSION_1_4(load, userptr); + + if (!glad_glx_find_extensions(display, screen)) return 0; + glad_glx_load_GLX_ARB_create_context(load, userptr); + glad_glx_load_GLX_ARB_get_proc_address(load, userptr); + glad_glx_load_GLX_EXT_swap_control(load, userptr); + glad_glx_load_GLX_MESA_swap_control(load, userptr); + glad_glx_load_GLX_SGI_swap_control(load, userptr); + + return version; +} + +int gladLoadGLX(Display *display, int screen, GLADloadfunc load) { + return gladLoadGLXUserPtr(display, screen, glad_glx_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + +#ifdef GLAD_GLX + +#ifndef GLAD_LOADER_LIBRARY_C_ +#define GLAD_LOADER_LIBRARY_C_ + +#include +#include + +#if GLAD_PLATFORM_WIN32 +#include +#else +#include +#endif + + +static void* glad_get_dlopen_handle(const char *lib_names[], int length) { + void *handle = NULL; + int i; + + for (i = 0; i < length; ++i) { +#if GLAD_PLATFORM_WIN32 + #if GLAD_PLATFORM_UWP + size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR); + LPWSTR buffer = (LPWSTR) malloc(buffer_size); + if (buffer != NULL) { + int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size); + if (ret != 0) { + handle = (void*) LoadPackagedLibrary(buffer, 0); + } + free((void*) buffer); + } + #else + handle = (void*) LoadLibraryA(lib_names[i]); + #endif +#else + handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL); +#endif + if (handle != NULL) { + return handle; + } + } + + return NULL; +} + +static void glad_close_dlopen_handle(void* handle) { + if (handle != NULL) { +#if GLAD_PLATFORM_WIN32 + FreeLibrary((HMODULE) handle); +#else + dlclose(handle); +#endif + } +} + +static GLADapiproc glad_dlsym_handle(void* handle, const char *name) { + if (handle == NULL) { + return NULL; + } + +#if GLAD_PLATFORM_WIN32 + return (GLADapiproc) GetProcAddress((HMODULE) handle, name); +#else + return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name); +#endif +} + +#endif /* GLAD_LOADER_LIBRARY_C_ */ + +typedef void* (GLAD_API_PTR *GLADglxprocaddrfunc)(const char*); + +static GLADapiproc glad_glx_get_proc(void *userptr, const char *name) { + return GLAD_GNUC_EXTENSION ((GLADapiproc (*)(const char *name)) userptr)(name); +} + +static void* _glx_handle; + +static void* glad_glx_dlopen_handle(void) { + static const char *NAMES[] = { +#if defined __CYGWIN__ + "libGL-1.so", +#endif + "libGL.so.1", + "libGL.so" + }; + + if (_glx_handle == NULL) { + _glx_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0])); + } + + return _glx_handle; +} + +int gladLoaderLoadGLX(Display *display, int screen) { + int version = 0; + void *handle = NULL; + int did_load = 0; + GLADglxprocaddrfunc loader; + + did_load = _glx_handle == NULL; + handle = glad_glx_dlopen_handle(); + if (handle != NULL) { + loader = (GLADglxprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB"); + if (loader != NULL) { + version = gladLoadGLXUserPtr(display, screen, glad_glx_get_proc, GLAD_GNUC_EXTENSION (void*) loader); + } + + if (!version && did_load) { + gladLoaderUnloadGLX(); + } + } + + return version; +} + + +void gladLoaderUnloadGLX() { + if (_glx_handle != NULL) { + glad_close_dlopen_handle(_glx_handle); + _glx_handle = NULL; + } +} + +#endif /* GLAD_GLX */ diff --git a/source/Platform/Unix/glad_glx.h b/source/Platform/Unix/glad_glx.h new file mode 100644 index 0000000..d6ffe96 --- /dev/null +++ b/source/Platform/Unix/glad_glx.h @@ -0,0 +1,602 @@ +/** + * Loader generated by glad 2.0.0-beta on Sat Dec 21 20:36:57 2019 + * + * Generator: C/C++ + * Specification: glx + * Extensions: 6 + * + * APIs: + * - glx=1.4 + * + * Options: + * - MX_GLOBAL = False + * - ON_DEMAND = False + * - LOADER = True + * - ALIAS = False + * - HEADER_ONLY = False + * - DEBUG = False + * - MX = False + * + * Commandline: + * --api='glx=1.4' --extensions='GLX_ARB_create_context,GLX_ARB_create_context_profile,GLX_ARB_get_proc_address,GLX_EXT_swap_control,GLX_MESA_swap_control,GLX_SGI_swap_control' c --loader + * + * Online: + * http://glad.sh/#api=glx%3D1.4&extensions=GLX_ARB_create_context%2CGLX_ARB_create_context_profile%2CGLX_ARB_get_proc_address%2CGLX_EXT_swap_control%2CGLX_MESA_swap_control%2CGLX_SGI_swap_control&generator=c&options=LOADER + * + */ + +#ifndef GLAD_GLX_H_ +#define GLAD_GLX_H_ + +#ifdef GLX_H + #error GLX header already included (API: glx), remove previous include! +#endif +#define GLX_H 1 + + +#include +#include +#include + +#include + +#define GLAD_GLX +#define GLAD_OPTION_GLX_LOADER + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GLAD_PLATFORM_H_ +#define GLAD_PLATFORM_H_ + +#ifndef GLAD_PLATFORM_WIN32 + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__) + #define GLAD_PLATFORM_WIN32 1 + #else + #define GLAD_PLATFORM_WIN32 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_APPLE + #ifdef __APPLE__ + #define GLAD_PLATFORM_APPLE 1 + #else + #define GLAD_PLATFORM_APPLE 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_EMSCRIPTEN + #ifdef __EMSCRIPTEN__ + #define GLAD_PLATFORM_EMSCRIPTEN 1 + #else + #define GLAD_PLATFORM_EMSCRIPTEN 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_UWP + #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY) + #ifdef __has_include + #if __has_include() + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #endif + + #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY + #include + #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define GLAD_PLATFORM_UWP 1 + #endif + #endif + + #ifndef GLAD_PLATFORM_UWP + #define GLAD_PLATFORM_UWP 0 + #endif +#endif + +#ifdef __GNUC__ + #define GLAD_GNUC_EXTENSION __extension__ +#else + #define GLAD_GNUC_EXTENSION +#endif + +#ifndef GLAD_API_CALL + #if defined(GLAD_API_CALL_EXPORT) + #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__) + #if defined(GLAD_API_CALL_EXPORT_BUILD) + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllexport)) extern + #else + #define GLAD_API_CALL __declspec(dllexport) extern + #endif + #else + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllimport)) extern + #else + #define GLAD_API_CALL __declspec(dllimport) extern + #endif + #endif + #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD) + #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern + #else + #define GLAD_API_CALL extern + #endif + #else + #define GLAD_API_CALL extern + #endif +#endif + +#ifdef APIENTRY + #define GLAD_API_PTR APIENTRY +#elif GLAD_PLATFORM_WIN32 + #define GLAD_API_PTR __stdcall +#else + #define GLAD_API_PTR +#endif + +#ifndef GLAPI +#define GLAPI GLAD_API_CALL +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY GLAD_API_PTR +#endif + +#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor) +#define GLAD_VERSION_MAJOR(version) (version / 10000) +#define GLAD_VERSION_MINOR(version) (version % 10000) + +#define GLAD_GENERATOR_VERSION "2.0.0-beta" + +typedef void (*GLADapiproc)(void); + +typedef GLADapiproc (*GLADloadfunc)(const char *name); +typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name); + +typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...); +typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...); + +#endif /* GLAD_PLATFORM_H_ */ + +#define GLX_ACCUM_ALPHA_SIZE 17 +#define GLX_ACCUM_BLUE_SIZE 16 +#define GLX_ACCUM_BUFFER_BIT 0x00000080 +#define GLX_ACCUM_GREEN_SIZE 15 +#define GLX_ACCUM_RED_SIZE 14 +#define GLX_ALPHA_SIZE 11 +#define GLX_AUX_BUFFERS 7 +#define GLX_AUX_BUFFERS_BIT 0x00000010 +#define GLX_BACK_LEFT_BUFFER_BIT 0x00000004 +#define GLX_BACK_RIGHT_BUFFER_BIT 0x00000008 +#define GLX_BAD_ATTRIBUTE 2 +#define GLX_BAD_CONTEXT 5 +#define GLX_BAD_ENUM 7 +#define GLX_BAD_SCREEN 1 +#define GLX_BAD_VALUE 6 +#define GLX_BAD_VISUAL 4 +#define GLX_BLUE_SIZE 10 +#define GLX_BUFFER_SIZE 2 +#define GLX_BufferSwapComplete 1 +#define GLX_COLOR_INDEX_BIT 0x00000002 +#define GLX_COLOR_INDEX_TYPE 0x8015 +#define GLX_CONFIG_CAVEAT 0x20 +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001 +#define GLX_CONTEXT_FLAGS_ARB 0x2094 +#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002 +#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 +#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#define GLX_DAMAGED 0x8020 +#define GLX_DEPTH_BUFFER_BIT 0x00000020 +#define GLX_DEPTH_SIZE 12 +#define GLX_DIRECT_COLOR 0x8003 +#define GLX_DONT_CARE 0xFFFFFFFF +#define GLX_DOUBLEBUFFER 5 +#define GLX_DRAWABLE_TYPE 0x8010 +#define GLX_EVENT_MASK 0x801F +#define GLX_EXTENSIONS 0x3 +#define GLX_EXTENSION_NAME "GLX" +#define GLX_FBCONFIG_ID 0x8013 +#define GLX_FRONT_LEFT_BUFFER_BIT 0x00000001 +#define GLX_FRONT_RIGHT_BUFFER_BIT 0x00000002 +#define GLX_GRAY_SCALE 0x8006 +#define GLX_GREEN_SIZE 9 +#define GLX_HEIGHT 0x801E +#define GLX_LARGEST_PBUFFER 0x801C +#define GLX_LEVEL 3 +#define GLX_MAX_PBUFFER_HEIGHT 0x8017 +#define GLX_MAX_PBUFFER_PIXELS 0x8018 +#define GLX_MAX_PBUFFER_WIDTH 0x8016 +#define GLX_MAX_SWAP_INTERVAL_EXT 0x20F2 +#define GLX_NONE 0x8000 +#define GLX_NON_CONFORMANT_CONFIG 0x800D +#define GLX_NO_EXTENSION 3 +#define GLX_PBUFFER 0x8023 +#define GLX_PBUFFER_BIT 0x00000004 +#define GLX_PBUFFER_CLOBBER_MASK 0x08000000 +#define GLX_PBUFFER_HEIGHT 0x8040 +#define GLX_PBUFFER_WIDTH 0x8041 +#define GLX_PIXMAP_BIT 0x00000002 +#define GLX_PRESERVED_CONTENTS 0x801B +#define GLX_PSEUDO_COLOR 0x8004 +#define GLX_PbufferClobber 0 +#define GLX_RED_SIZE 8 +#define GLX_RENDER_TYPE 0x8011 +#define GLX_RGBA 4 +#define GLX_RGBA_BIT 0x00000001 +#define GLX_RGBA_TYPE 0x8014 +#define GLX_SAMPLES 100001 +#define GLX_SAMPLE_BUFFERS 100000 +#define GLX_SAVED 0x8021 +#define GLX_SCREEN 0x800C +#define GLX_SLOW_CONFIG 0x8001 +#define GLX_STATIC_COLOR 0x8005 +#define GLX_STATIC_GRAY 0x8007 +#define GLX_STENCIL_BUFFER_BIT 0x00000040 +#define GLX_STENCIL_SIZE 13 +#define GLX_STEREO 6 +#define GLX_SWAP_INTERVAL_EXT 0x20F1 +#define GLX_TRANSPARENT_ALPHA_VALUE 0x28 +#define GLX_TRANSPARENT_BLUE_VALUE 0x27 +#define GLX_TRANSPARENT_GREEN_VALUE 0x26 +#define GLX_TRANSPARENT_INDEX 0x8009 +#define GLX_TRANSPARENT_INDEX_VALUE 0x24 +#define GLX_TRANSPARENT_RED_VALUE 0x25 +#define GLX_TRANSPARENT_RGB 0x8008 +#define GLX_TRANSPARENT_TYPE 0x23 +#define GLX_TRUE_COLOR 0x8002 +#define GLX_USE_GL 1 +#define GLX_VENDOR 0x1 +#define GLX_VERSION 0x2 +#define GLX_VISUAL_ID 0x800B +#define GLX_WIDTH 0x801D +#define GLX_WINDOW 0x8022 +#define GLX_WINDOW_BIT 0x00000001 +#define GLX_X_RENDERABLE 0x8012 +#define GLX_X_VISUAL_TYPE 0x22 +#define __GLX_NUMBER_EVENTS 17 + + +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GLX_OML_sync_control extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif + + + + + + + + + + + + + + + + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) + +#else + +#endif + +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) + +#else + +#endif + + + + + + + +typedef XID GLXFBConfigID; +typedef struct __GLXFBConfigRec *GLXFBConfig; +typedef XID GLXContextID; +typedef struct __GLXcontextRec *GLXContext; +typedef XID GLXPixmap; +typedef XID GLXDrawable; +typedef XID GLXWindow; +typedef XID GLXPbuffer; +typedef void (GLAD_API_PTR *__GLXextFuncPtr)(void); +typedef XID GLXVideoCaptureDeviceNV; +typedef unsigned int GLXVideoDeviceNV; +typedef XID GLXVideoSourceSGIX; +typedef XID GLXFBConfigIDSGIX; +typedef struct __GLXFBConfigRec *GLXFBConfigSGIX; +typedef XID GLXPbufferSGIX; +typedef struct { + int event_type; /* GLX_DAMAGED or GLX_SAVED */ + int draw_type; /* GLX_WINDOW or GLX_PBUFFER */ + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* XID of Drawable */ + unsigned int buffer_mask; /* mask indicating which buffers are affected */ + unsigned int aux_buffer; /* which aux buffer was affected */ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXPbufferClobberEvent; +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came from a SendEvent request */ + Display *display; /* Display the event was read from */ + GLXDrawable drawable; /* drawable on which event was requested in event mask */ + int event_type; + int64_t ust; + int64_t msc; + int64_t sbc; +} GLXBufferSwapComplete; +typedef union __GLXEvent { + GLXPbufferClobberEvent glxpbufferclobber; + GLXBufferSwapComplete glxbufferswapcomplete; + long pad[24]; +} GLXEvent; +typedef struct { + int type; + unsigned long serial; + Bool send_event; + Display *display; + int extension; + int evtype; + GLXDrawable window; + Bool stereo_tree; +} GLXStereoNotifyEventEXT; +typedef struct { + int type; + unsigned long serial; /* # of last request processed by server */ + Bool send_event; /* true if this came for SendEvent request */ + Display *display; /* display the event was read from */ + GLXDrawable drawable; /* i.d. of Drawable */ + int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */ + int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */ + unsigned int mask; /* mask indicating which buffers are affected*/ + int x, y; + int width, height; + int count; /* if nonzero, at least this many more */ +} GLXBufferClobberEventSGIX; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int networkId; +} GLXHyperpipeNetworkSGIX; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int channel; + unsigned int participationType; + int timeSlice; +} GLXHyperpipeConfigSGIX; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int srcXOrigin, srcYOrigin, srcWidth, srcHeight; + int destXOrigin, destYOrigin, destWidth, destHeight; +} GLXPipeRect; +typedef struct { + char pipeName[80]; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */ + int XOrigin, YOrigin, maxHeight, maxWidth; +} GLXPipeRectLimits; + + +#define GLX_VERSION_1_0 1 +GLAD_API_CALL int GLAD_GLX_VERSION_1_0; +#define GLX_VERSION_1_1 1 +GLAD_API_CALL int GLAD_GLX_VERSION_1_1; +#define GLX_VERSION_1_2 1 +GLAD_API_CALL int GLAD_GLX_VERSION_1_2; +#define GLX_VERSION_1_3 1 +GLAD_API_CALL int GLAD_GLX_VERSION_1_3; +#define GLX_VERSION_1_4 1 +GLAD_API_CALL int GLAD_GLX_VERSION_1_4; +#define GLX_ARB_create_context 1 +GLAD_API_CALL int GLAD_GLX_ARB_create_context; +#define GLX_ARB_create_context_profile 1 +GLAD_API_CALL int GLAD_GLX_ARB_create_context_profile; +#define GLX_ARB_get_proc_address 1 +GLAD_API_CALL int GLAD_GLX_ARB_get_proc_address; +#define GLX_EXT_swap_control 1 +GLAD_API_CALL int GLAD_GLX_EXT_swap_control; +#define GLX_MESA_swap_control 1 +GLAD_API_CALL int GLAD_GLX_MESA_swap_control; +#define GLX_SGI_swap_control 1 +GLAD_API_CALL int GLAD_GLX_SGI_swap_control; + + +typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXCHOOSEFBCONFIGPROC)(Display * dpy, int screen, const int * attrib_list, int * nelements); +typedef XVisualInfo * (GLAD_API_PTR *PFNGLXCHOOSEVISUALPROC)(Display * dpy, int screen, int * attribList); +typedef void (GLAD_API_PTR *PFNGLXCOPYCONTEXTPROC)(Display * dpy, GLXContext src, GLXContext dst, unsigned long mask); +typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTPROC)(Display * dpy, XVisualInfo * vis, GLXContext shareList, Bool direct); +typedef GLXContext (GLAD_API_PTR *PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display * dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int * attrib_list); +typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEGLXPIXMAPPROC)(Display * dpy, XVisualInfo * visual, Pixmap pixmap); +typedef GLXContext (GLAD_API_PTR *PFNGLXCREATENEWCONTEXTPROC)(Display * dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct); +typedef GLXPbuffer (GLAD_API_PTR *PFNGLXCREATEPBUFFERPROC)(Display * dpy, GLXFBConfig config, const int * attrib_list); +typedef GLXPixmap (GLAD_API_PTR *PFNGLXCREATEPIXMAPPROC)(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int * attrib_list); +typedef GLXWindow (GLAD_API_PTR *PFNGLXCREATEWINDOWPROC)(Display * dpy, GLXFBConfig config, Window win, const int * attrib_list); +typedef void (GLAD_API_PTR *PFNGLXDESTROYCONTEXTPROC)(Display * dpy, GLXContext ctx); +typedef void (GLAD_API_PTR *PFNGLXDESTROYGLXPIXMAPPROC)(Display * dpy, GLXPixmap pixmap); +typedef void (GLAD_API_PTR *PFNGLXDESTROYPBUFFERPROC)(Display * dpy, GLXPbuffer pbuf); +typedef void (GLAD_API_PTR *PFNGLXDESTROYPIXMAPPROC)(Display * dpy, GLXPixmap pixmap); +typedef void (GLAD_API_PTR *PFNGLXDESTROYWINDOWPROC)(Display * dpy, GLXWindow win); +typedef const char * (GLAD_API_PTR *PFNGLXGETCLIENTSTRINGPROC)(Display * dpy, int name); +typedef int (GLAD_API_PTR *PFNGLXGETCONFIGPROC)(Display * dpy, XVisualInfo * visual, int attrib, int * value); +typedef GLXContext (GLAD_API_PTR *PFNGLXGETCURRENTCONTEXTPROC)(void); +typedef Display * (GLAD_API_PTR *PFNGLXGETCURRENTDISPLAYPROC)(void); +typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTDRAWABLEPROC)(void); +typedef GLXDrawable (GLAD_API_PTR *PFNGLXGETCURRENTREADDRAWABLEPROC)(void); +typedef int (GLAD_API_PTR *PFNGLXGETFBCONFIGATTRIBPROC)(Display * dpy, GLXFBConfig config, int attribute, int * value); +typedef GLXFBConfig * (GLAD_API_PTR *PFNGLXGETFBCONFIGSPROC)(Display * dpy, int screen, int * nelements); +typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSPROC)(const GLubyte * procName); +typedef __GLXextFuncPtr (GLAD_API_PTR *PFNGLXGETPROCADDRESSARBPROC)(const GLubyte * procName); +typedef void (GLAD_API_PTR *PFNGLXGETSELECTEDEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long * event_mask); +typedef int (GLAD_API_PTR *PFNGLXGETSWAPINTERVALMESAPROC)(void); +typedef XVisualInfo * (GLAD_API_PTR *PFNGLXGETVISUALFROMFBCONFIGPROC)(Display * dpy, GLXFBConfig config); +typedef Bool (GLAD_API_PTR *PFNGLXISDIRECTPROC)(Display * dpy, GLXContext ctx); +typedef Bool (GLAD_API_PTR *PFNGLXMAKECONTEXTCURRENTPROC)(Display * dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); +typedef Bool (GLAD_API_PTR *PFNGLXMAKECURRENTPROC)(Display * dpy, GLXDrawable drawable, GLXContext ctx); +typedef int (GLAD_API_PTR *PFNGLXQUERYCONTEXTPROC)(Display * dpy, GLXContext ctx, int attribute, int * value); +typedef void (GLAD_API_PTR *PFNGLXQUERYDRAWABLEPROC)(Display * dpy, GLXDrawable draw, int attribute, unsigned int * value); +typedef Bool (GLAD_API_PTR *PFNGLXQUERYEXTENSIONPROC)(Display * dpy, int * errorb, int * event); +typedef const char * (GLAD_API_PTR *PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display * dpy, int screen); +typedef const char * (GLAD_API_PTR *PFNGLXQUERYSERVERSTRINGPROC)(Display * dpy, int screen, int name); +typedef Bool (GLAD_API_PTR *PFNGLXQUERYVERSIONPROC)(Display * dpy, int * maj, int * min); +typedef void (GLAD_API_PTR *PFNGLXSELECTEVENTPROC)(Display * dpy, GLXDrawable draw, unsigned long event_mask); +typedef void (GLAD_API_PTR *PFNGLXSWAPBUFFERSPROC)(Display * dpy, GLXDrawable drawable); +typedef void (GLAD_API_PTR *PFNGLXSWAPINTERVALEXTPROC)(Display * dpy, GLXDrawable drawable, int interval); +typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALMESAPROC)(unsigned int interval); +typedef int (GLAD_API_PTR *PFNGLXSWAPINTERVALSGIPROC)(int interval); +typedef void (GLAD_API_PTR *PFNGLXUSEXFONTPROC)(Font font, int first, int count, int list); +typedef void (GLAD_API_PTR *PFNGLXWAITGLPROC)(void); +typedef void (GLAD_API_PTR *PFNGLXWAITXPROC)(void); + +GLAD_API_CALL PFNGLXCHOOSEFBCONFIGPROC glad_glXChooseFBConfig; +#define glXChooseFBConfig glad_glXChooseFBConfig +GLAD_API_CALL PFNGLXCHOOSEVISUALPROC glad_glXChooseVisual; +#define glXChooseVisual glad_glXChooseVisual +GLAD_API_CALL PFNGLXCOPYCONTEXTPROC glad_glXCopyContext; +#define glXCopyContext glad_glXCopyContext +GLAD_API_CALL PFNGLXCREATECONTEXTPROC glad_glXCreateContext; +#define glXCreateContext glad_glXCreateContext +GLAD_API_CALL PFNGLXCREATECONTEXTATTRIBSARBPROC glad_glXCreateContextAttribsARB; +#define glXCreateContextAttribsARB glad_glXCreateContextAttribsARB +GLAD_API_CALL PFNGLXCREATEGLXPIXMAPPROC glad_glXCreateGLXPixmap; +#define glXCreateGLXPixmap glad_glXCreateGLXPixmap +GLAD_API_CALL PFNGLXCREATENEWCONTEXTPROC glad_glXCreateNewContext; +#define glXCreateNewContext glad_glXCreateNewContext +GLAD_API_CALL PFNGLXCREATEPBUFFERPROC glad_glXCreatePbuffer; +#define glXCreatePbuffer glad_glXCreatePbuffer +GLAD_API_CALL PFNGLXCREATEPIXMAPPROC glad_glXCreatePixmap; +#define glXCreatePixmap glad_glXCreatePixmap +GLAD_API_CALL PFNGLXCREATEWINDOWPROC glad_glXCreateWindow; +#define glXCreateWindow glad_glXCreateWindow +GLAD_API_CALL PFNGLXDESTROYCONTEXTPROC glad_glXDestroyContext; +#define glXDestroyContext glad_glXDestroyContext +GLAD_API_CALL PFNGLXDESTROYGLXPIXMAPPROC glad_glXDestroyGLXPixmap; +#define glXDestroyGLXPixmap glad_glXDestroyGLXPixmap +GLAD_API_CALL PFNGLXDESTROYPBUFFERPROC glad_glXDestroyPbuffer; +#define glXDestroyPbuffer glad_glXDestroyPbuffer +GLAD_API_CALL PFNGLXDESTROYPIXMAPPROC glad_glXDestroyPixmap; +#define glXDestroyPixmap glad_glXDestroyPixmap +GLAD_API_CALL PFNGLXDESTROYWINDOWPROC glad_glXDestroyWindow; +#define glXDestroyWindow glad_glXDestroyWindow +GLAD_API_CALL PFNGLXGETCLIENTSTRINGPROC glad_glXGetClientString; +#define glXGetClientString glad_glXGetClientString +GLAD_API_CALL PFNGLXGETCONFIGPROC glad_glXGetConfig; +#define glXGetConfig glad_glXGetConfig +GLAD_API_CALL PFNGLXGETCURRENTCONTEXTPROC glad_glXGetCurrentContext; +#define glXGetCurrentContext glad_glXGetCurrentContext +GLAD_API_CALL PFNGLXGETCURRENTDISPLAYPROC glad_glXGetCurrentDisplay; +#define glXGetCurrentDisplay glad_glXGetCurrentDisplay +GLAD_API_CALL PFNGLXGETCURRENTDRAWABLEPROC glad_glXGetCurrentDrawable; +#define glXGetCurrentDrawable glad_glXGetCurrentDrawable +GLAD_API_CALL PFNGLXGETCURRENTREADDRAWABLEPROC glad_glXGetCurrentReadDrawable; +#define glXGetCurrentReadDrawable glad_glXGetCurrentReadDrawable +GLAD_API_CALL PFNGLXGETFBCONFIGATTRIBPROC glad_glXGetFBConfigAttrib; +#define glXGetFBConfigAttrib glad_glXGetFBConfigAttrib +GLAD_API_CALL PFNGLXGETFBCONFIGSPROC glad_glXGetFBConfigs; +#define glXGetFBConfigs glad_glXGetFBConfigs +GLAD_API_CALL PFNGLXGETPROCADDRESSPROC glad_glXGetProcAddress; +#define glXGetProcAddress glad_glXGetProcAddress +GLAD_API_CALL PFNGLXGETPROCADDRESSARBPROC glad_glXGetProcAddressARB; +#define glXGetProcAddressARB glad_glXGetProcAddressARB +GLAD_API_CALL PFNGLXGETSELECTEDEVENTPROC glad_glXGetSelectedEvent; +#define glXGetSelectedEvent glad_glXGetSelectedEvent +GLAD_API_CALL PFNGLXGETSWAPINTERVALMESAPROC glad_glXGetSwapIntervalMESA; +#define glXGetSwapIntervalMESA glad_glXGetSwapIntervalMESA +GLAD_API_CALL PFNGLXGETVISUALFROMFBCONFIGPROC glad_glXGetVisualFromFBConfig; +#define glXGetVisualFromFBConfig glad_glXGetVisualFromFBConfig +GLAD_API_CALL PFNGLXISDIRECTPROC glad_glXIsDirect; +#define glXIsDirect glad_glXIsDirect +GLAD_API_CALL PFNGLXMAKECONTEXTCURRENTPROC glad_glXMakeContextCurrent; +#define glXMakeContextCurrent glad_glXMakeContextCurrent +GLAD_API_CALL PFNGLXMAKECURRENTPROC glad_glXMakeCurrent; +#define glXMakeCurrent glad_glXMakeCurrent +GLAD_API_CALL PFNGLXQUERYCONTEXTPROC glad_glXQueryContext; +#define glXQueryContext glad_glXQueryContext +GLAD_API_CALL PFNGLXQUERYDRAWABLEPROC glad_glXQueryDrawable; +#define glXQueryDrawable glad_glXQueryDrawable +GLAD_API_CALL PFNGLXQUERYEXTENSIONPROC glad_glXQueryExtension; +#define glXQueryExtension glad_glXQueryExtension +GLAD_API_CALL PFNGLXQUERYEXTENSIONSSTRINGPROC glad_glXQueryExtensionsString; +#define glXQueryExtensionsString glad_glXQueryExtensionsString +GLAD_API_CALL PFNGLXQUERYSERVERSTRINGPROC glad_glXQueryServerString; +#define glXQueryServerString glad_glXQueryServerString +GLAD_API_CALL PFNGLXQUERYVERSIONPROC glad_glXQueryVersion; +#define glXQueryVersion glad_glXQueryVersion +GLAD_API_CALL PFNGLXSELECTEVENTPROC glad_glXSelectEvent; +#define glXSelectEvent glad_glXSelectEvent +GLAD_API_CALL PFNGLXSWAPBUFFERSPROC glad_glXSwapBuffers; +#define glXSwapBuffers glad_glXSwapBuffers +GLAD_API_CALL PFNGLXSWAPINTERVALEXTPROC glad_glXSwapIntervalEXT; +#define glXSwapIntervalEXT glad_glXSwapIntervalEXT +GLAD_API_CALL PFNGLXSWAPINTERVALMESAPROC glad_glXSwapIntervalMESA; +#define glXSwapIntervalMESA glad_glXSwapIntervalMESA +GLAD_API_CALL PFNGLXSWAPINTERVALSGIPROC glad_glXSwapIntervalSGI; +#define glXSwapIntervalSGI glad_glXSwapIntervalSGI +GLAD_API_CALL PFNGLXUSEXFONTPROC glad_glXUseXFont; +#define glXUseXFont glad_glXUseXFont +GLAD_API_CALL PFNGLXWAITGLPROC glad_glXWaitGL; +#define glXWaitGL glad_glXWaitGL +GLAD_API_CALL PFNGLXWAITXPROC glad_glXWaitX; +#define glXWaitX glad_glXWaitX + + + + + +GLAD_API_CALL int gladLoadGLXUserPtr(Display *display, int screen, GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGLX(Display *display, int screen, GLADloadfunc load); + +#ifdef GLAD_GLX + +GLAD_API_CALL int gladLoaderLoadGLX(Display *display, int screen); + +GLAD_API_CALL void gladLoaderUnloadGLX(void); + +#endif +#ifdef __cplusplus +} +#endif +#endif diff --git a/source/Platform/Win32/Win32Display.cpp b/source/Platform/Win32/Win32Display.cpp index de68f77..89bedd0 100644 --- a/source/Platform/Win32/Win32Display.cpp +++ b/source/Platform/Win32/Win32Display.cpp @@ -246,7 +246,7 @@ DWORD Win32Display::getWin32Flags(unsigned int flags) { DWORD win32_flags = WS_VISIBLE; - if (flags == DisplayDecorate::None) { + if (flags == DisplayDecorate::Empty) { win32_flags |= WS_POPUP; } else { if (flags & DisplayDecorate::Menu) { diff --git a/source/System/MessageQueue.cpp b/source/System/MessageQueue.cpp index 8ff7a3b..57f4fa4 100644 --- a/source/System/MessageQueue.cpp +++ b/source/System/MessageQueue.cpp @@ -1,9 +1,12 @@ #include -#ifdef _WIN32 +#ifdef SPECTRE_PLATFORM_WIN #include typedef sp::Win32EventQueue ImplType; +#elif SPECTRE_PLATFORM_UNIX +#include +typedef sp::X11EventQueue ImplType; #else #error "No MessageQueue implementation exists" #endif