From 392a2b7889a49aaa42985488a32c7d4139098b1f Mon Sep 17 00:00:00 2001 From: James Grogan Date: Sat, 12 Nov 2022 15:34:54 +0000 Subject: [PATCH] Cleaning window managers for consistency. --- src/client/GuiApplication.cpp | 5 - .../desktop_elements/IPlatformWindow.h | 6 +- src/ui_elements/desktop_elements/Window.cpp | 6 + src/ui_elements/desktop_elements/Window.h | 2 + src/windows/CMakeLists.txt | 3 +- src/windows/managers/WindowManager.cpp | 8 ++ src/windows/managers/WindowManager.h | 12 ++ .../ui_interfaces/AbstractUiInterface.h | 14 +-- .../ui_interfaces/UiInterfaceFactory.cppcd | 0 .../wayland/WaylandEglInterface.cpp | 5 + .../wayland/WaylandEglInterface.h | 5 +- .../wayland/WaylandEglWindowInterface.h | 2 +- .../wayland/WaylandInterface.cpp | 36 +++--- .../ui_interfaces/wayland/WaylandInterface.h | 6 +- .../ui_interfaces/wayland/WaylandSurface.cpp | 69 +++++++++--- .../ui_interfaces/wayland/WaylandSurface.h | 51 +++++---- .../ui_interfaces/x11/GlxInterface.cpp | 106 ------------------ src/windows/ui_interfaces/x11/GlxInterface.h | 33 ------ .../ui_interfaces/x11/XcbGlInterface.cpp | 71 ++++++++++++ .../ui_interfaces/x11/XcbGlInterface.h | 39 +++++++ .../x11/XcbGlWindowInterface.cpp | 67 +++++++++++ .../ui_interfaces/x11/XcbGlWindowInterface.h | 28 +++++ .../ui_interfaces/x11/XcbInterface.cpp | 94 +++++----------- src/windows/ui_interfaces/x11/XcbInterface.h | 26 ++--- src/windows/ui_interfaces/x11/XcbWindow.cpp | 50 +++++++-- src/windows/ui_interfaces/x11/XcbWindow.h | 19 +++- test/graphics/TestOpenGlRendering.cpp | 4 +- test/image/TestPngWriter.cpp | 10 +- 28 files changed, 452 insertions(+), 325 deletions(-) delete mode 100644 src/windows/ui_interfaces/UiInterfaceFactory.cppcd delete mode 100644 src/windows/ui_interfaces/x11/GlxInterface.cpp delete mode 100644 src/windows/ui_interfaces/x11/GlxInterface.h create mode 100644 src/windows/ui_interfaces/x11/XcbGlInterface.cpp create mode 100644 src/windows/ui_interfaces/x11/XcbGlInterface.h create mode 100644 src/windows/ui_interfaces/x11/XcbGlWindowInterface.cpp create mode 100644 src/windows/ui_interfaces/x11/XcbGlWindowInterface.h diff --git a/src/client/GuiApplication.cpp b/src/client/GuiApplication.cpp index 52d3f47..772ec4d 100644 --- a/src/client/GuiApplication.cpp +++ b/src/client/GuiApplication.cpp @@ -45,13 +45,8 @@ void GuiApplication::run() MLOG_INFO("Creating Window Interface"); mUiInterface = UiInterfaceFactory::create(mDesktopManager.get(), mUiInterfaceBackend); - mUiInterface->initialize(); - mUiInterface->addWindow(mainWindow); - mUiInterface->showWindow(mainWindow); mUiInterface->loop(); - mUiInterface->shutDown(); - MLOG_INFO("Window Interface Shut Down"); mMainApplication->ShutDown(); diff --git a/src/ui_elements/desktop_elements/IPlatformWindow.h b/src/ui_elements/desktop_elements/IPlatformWindow.h index ca5d672..2b54d94 100644 --- a/src/ui_elements/desktop_elements/IPlatformWindow.h +++ b/src/ui_elements/desktop_elements/IPlatformWindow.h @@ -26,11 +26,11 @@ public: virtual ~IPlatformWindow() = default; - virtual void show() const = 0; + virtual void show() = 0; - virtual void map() const = 0; + virtual void map() = 0; - virtual void clear() const = 0; + virtual void clear() = 0; protected: mt::Window* mWindow{nullptr}; }; diff --git a/src/ui_elements/desktop_elements/Window.cpp b/src/ui_elements/desktop_elements/Window.cpp index 7036b22..2748c8f 100644 --- a/src/ui_elements/desktop_elements/Window.cpp +++ b/src/ui_elements/desktop_elements/Window.cpp @@ -35,6 +35,12 @@ std::vector Window::GetLayers() return mWidget->getLayers(); } +void Window::clearPlatformWindow() +{ + mPlatformWindow.reset(); +} + + void Window::OnMouseEvent(const MouseEvent* event) { mWidget->onMouseEvent(event); diff --git a/src/ui_elements/desktop_elements/Window.h b/src/ui_elements/desktop_elements/Window.h index 19ec0c9..3fc121e 100644 --- a/src/ui_elements/desktop_elements/Window.h +++ b/src/ui_elements/desktop_elements/Window.h @@ -62,6 +62,8 @@ public: void clear(); + void clearPlatformWindow(); + private: int mHandle {-1}; WidgetUPtr mWidget {nullptr}; diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index 18fd72d..1507bb7 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -15,7 +15,8 @@ if(UNIX) ui_interfaces/x11/XcbLayerInterface.cpp ui_interfaces/x11/XcbTextInterface.cpp ui_interfaces/x11/XcbKeyboard.cpp - ui_interfaces/x11/GlxInterface.cpp + ui_interfaces/x11/XcbGlInterface.cpp + ui_interfaces/x11/XcbGlWindowInterface.cpp ) list(APPEND platform_LIBS ${X11_LIBRARIES} ${X11_xcb_LIB} ${X11_X11_xcb_LIB} ${X11_xkbcommon_LIB} libxcb-image.so) list(APPEND X11_INCLUDE_DIRS ${X11_xkbcommon_INCLUDE_PATH}) diff --git a/src/windows/managers/WindowManager.cpp b/src/windows/managers/WindowManager.cpp index 894241c..7b2da19 100644 --- a/src/windows/managers/WindowManager.cpp +++ b/src/windows/managers/WindowManager.cpp @@ -36,6 +36,14 @@ void WindowManager::AddWindow(WindowUPtr window) mWindows.push_back(std::move(window)); } +void WindowManager::clearPlatformWindows() +{ + for (auto& window : mWindows) + { + window->clearPlatformWindow(); + } +} + mt::Window* WindowManager::GetMainWindow() const { if(mWindows.size()>0) diff --git a/src/windows/managers/WindowManager.h b/src/windows/managers/WindowManager.h index 0ba191b..0817816 100644 --- a/src/windows/managers/WindowManager.h +++ b/src/windows/managers/WindowManager.h @@ -27,6 +27,18 @@ public: void OnKeyboardEvent(const KeyboardEvent* event); + void clearPlatformWindows(); + + std::size_t getNumWindows() const + { + return mWindows.size(); + } + + mt::Window* getWindow(std::size_t idx) const + { + return mWindows[idx].get(); + } + private: std::vector mWindows; }; diff --git a/src/windows/ui_interfaces/AbstractUiInterface.h b/src/windows/ui_interfaces/AbstractUiInterface.h index 8b27e5b..8d8fdcd 100644 --- a/src/windows/ui_interfaces/AbstractUiInterface.h +++ b/src/windows/ui_interfaces/AbstractUiInterface.h @@ -19,22 +19,18 @@ public: virtual ~AbstractUIInterface() = default; - virtual void initialize() = 0; - virtual void loop() = 0; - virtual void shutDown() = 0; - virtual void showWindow(mt::Window* window) = 0; virtual void addWindow(mt::Window* window) = 0; - void setUseHardwareRendering(bool useHardware) - { - mUseHardwareRendering = useHardware; - } - protected: + virtual void initialize() = 0; + virtual void shutDown() = 0; + + virtual void initializeHardwareRendering() {}; + DesktopManager* mDesktopManager{nullptr}; bool mUseHardwareRendering{false}; }; diff --git a/src/windows/ui_interfaces/UiInterfaceFactory.cppcd b/src/windows/ui_interfaces/UiInterfaceFactory.cppcd deleted file mode 100644 index e69de29..0000000 diff --git a/src/windows/ui_interfaces/wayland/WaylandEglInterface.cpp b/src/windows/ui_interfaces/wayland/WaylandEglInterface.cpp index 34f2695..418d97a 100644 --- a/src/windows/ui_interfaces/wayland/WaylandEglInterface.cpp +++ b/src/windows/ui_interfaces/wayland/WaylandEglInterface.cpp @@ -4,6 +4,11 @@ #include +WaylandEglInterface::WaylandEglInterface(wl_display* display) +{ + initialize(display); +} + void WaylandEglInterface::initialize(wl_display* display) { mEglDisplay = eglGetDisplay((EGLNativeDisplayType) display); diff --git a/src/windows/ui_interfaces/wayland/WaylandEglInterface.h b/src/windows/ui_interfaces/wayland/WaylandEglInterface.h index cfc1e86..27988f9 100644 --- a/src/windows/ui_interfaces/wayland/WaylandEglInterface.h +++ b/src/windows/ui_interfaces/wayland/WaylandEglInterface.h @@ -7,8 +7,7 @@ struct wl_display; class WaylandEglInterface { public: - - void initialize(wl_display* display); + WaylandEglInterface(wl_display* display); EGLDisplay getDisplay() const; @@ -17,6 +16,8 @@ public: EGLContext getContext() const; private: + void initialize(wl_display* display); + EGLDisplay mEglDisplay; EGLConfig mEglConfig; EGLContext mEglContext; diff --git a/src/windows/ui_interfaces/wayland/WaylandEglWindowInterface.h b/src/windows/ui_interfaces/wayland/WaylandEglWindowInterface.h index 31c7236..314334f 100644 --- a/src/windows/ui_interfaces/wayland/WaylandEglWindowInterface.h +++ b/src/windows/ui_interfaces/wayland/WaylandEglWindowInterface.h @@ -19,6 +19,6 @@ public: private: wl_egl_window* mEglWindow{nullptr}; - EGLSurface mEglSurface; + EGLSurface mEglSurface{nullptr}; WaylandEglInterface* mEglInterface; }; diff --git a/src/windows/ui_interfaces/wayland/WaylandInterface.cpp b/src/windows/ui_interfaces/wayland/WaylandInterface.cpp index 30e97cf..c7fccbf 100644 --- a/src/windows/ui_interfaces/wayland/WaylandInterface.cpp +++ b/src/windows/ui_interfaces/wayland/WaylandInterface.cpp @@ -1,6 +1,9 @@ #include "WaylandInterface.h" #include "FileLogger.h" +#include "DesktopManager.h" +#include "WindowManager.h" + #include "WaylandSurface.h" #include "WaylandBuffer.h" #include "WaylandSeatInterface.h" @@ -13,10 +16,9 @@ void WaylandInterface::registryHandleGlobalEvent(void *data, struct wl_registry uint32_t name, const char *interface, uint32_t version) { auto thisClass = static_cast(data); - std::stringstream sstrm; sstrm << "interface: " << interface << " version " << version << " name " << name; - MLOG_INFO(sstrm.str()); + //MLOG_INFO(sstrm.str()); if (strcmp(interface, wl_compositor_interface.name) == 0) { @@ -51,7 +53,7 @@ WaylandInterface::WaylandInterface(DesktopManager* desktopManager, bool useHardw WaylandInterface::~WaylandInterface() { - + shutDown(); } void WaylandInterface::initialize() @@ -76,9 +78,21 @@ void WaylandInterface::initialize() if (mUseHardwareRendering) { - mEglInterface = std::make_unique(); - mEglInterface->initialize(mDisplay); + initializeHardwareRendering(); } + + const auto num_windows = mDesktopManager->GetWindowManager()->getNumWindows(); + for(std::size_t idx=0; idx< num_windows; idx++) + { + addWindow(mDesktopManager->GetWindowManager()->getWindow(idx)); + } + + mDesktopManager->GetWindowManager()->GetMainWindow()->show(); +} + +void WaylandInterface::initializeHardwareRendering() +{ + mEglInterface = std::make_unique(mDisplay); } void WaylandInterface::setSeat(wl_seat* seat) @@ -115,18 +129,12 @@ void WaylandInterface::doXdgPong(uint32_t serial) void WaylandInterface::addWindow(mt::Window* window) { - auto surface = std::make_unique(window); - mSurfaces.push_back(std::move(surface)); + WaylandSurface::add(window, mCompositor, mXdgBase, mBuffer, mEglInterface.get()); } void WaylandInterface::showWindow(mt::Window* window) { - if (mSurfaces.empty()) - { - return; - } - - mSurfaces[0]->initialize(mCompositor, mXdgBase, mBuffer, mEglInterface.get()); + window->show(); } void WaylandInterface::shutDown() @@ -139,6 +147,8 @@ void WaylandInterface::shutDown() void WaylandInterface::loop() { + initialize(); + while (wl_display_dispatch(mDisplay) != -1) { /* This space deliberately left blank */ diff --git a/src/windows/ui_interfaces/wayland/WaylandInterface.h b/src/windows/ui_interfaces/wayland/WaylandInterface.h index aba7668..1fdc82a 100644 --- a/src/windows/ui_interfaces/wayland/WaylandInterface.h +++ b/src/windows/ui_interfaces/wayland/WaylandInterface.h @@ -10,7 +10,6 @@ #include #include -class WaylandSurface; class WaylandBuffer; class WaylandSeatInterface; class WaylandEglInterface; @@ -29,11 +28,13 @@ public: void showWindow(mt::Window* window) override; +private: void initialize() override; + void initializeHardwareRendering() override; + void shutDown() override; -private: static void registryHandleGlobalEvent(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version); static void registryHandleGlobalRemoveEvent(void *data, struct wl_registry *registry, uint32_t name); @@ -54,7 +55,6 @@ private: xdg_wm_base* mXdgBase{nullptr}; xdg_wm_base_listener mXdgBaseListener; - std::vector > mSurfaces; std::shared_ptr mBuffer; std::unique_ptr mSeatInterface; std::unique_ptr mEglInterface; diff --git a/src/windows/ui_interfaces/wayland/WaylandSurface.cpp b/src/windows/ui_interfaces/wayland/WaylandSurface.cpp index 0eebde6..cb90a27 100644 --- a/src/windows/ui_interfaces/wayland/WaylandSurface.cpp +++ b/src/windows/ui_interfaces/wayland/WaylandSurface.cpp @@ -3,10 +3,22 @@ #include "WaylandEglWindowInterface.h" #include "ImagePrimitives.h" -WaylandSurface::WaylandSurface(mt::Window* window) - : IPlatformWindow(window) +void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface) { + auto wayland_window = std::make_unique(window, compositor, xdg_wm_base, buffer, eglInterface); + window->SetPlatformWindow(std::move(wayland_window)); +} +WaylandSurface::WaylandSurface(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface) + : IPlatformWindow(window), + mCompositor(compositor), + mXdgWmBase(xdg_wm_base), + mBuffer(buffer) +{ + if (eglInterface) + { + mEglWindowInterface = std::make_unique(eglInterface); + } } WaylandSurface::~WaylandSurface() @@ -14,16 +26,28 @@ WaylandSurface::~WaylandSurface() } -void WaylandSurface::initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface) +void WaylandSurface::show() { - mBuffer = buffer; - if (eglInterface) - { - mEglWindowInterface = std::make_unique(eglInterface); - } + map(); +} - mSurface = wl_compositor_create_surface(compositor); - mXdgSurface = xdg_wm_base_get_xdg_surface(xdg_wm_base, mSurface); +void WaylandSurface::clear() +{ + +} + +void WaylandSurface::map() +{ + if (!mSurface) + { + initialize(); + } +} + +void WaylandSurface::initialize() +{ + mSurface = wl_compositor_create_surface(mCompositor); + mXdgSurface = xdg_wm_base_get_xdg_surface(mXdgWmBase, mSurface); auto xdg_surface_configure = [](void *data, struct xdg_surface *xdg_surface, uint32_t serial) { @@ -37,7 +61,7 @@ void WaylandSurface::initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_b mXdgTopLevel = xdg_surface_get_toplevel(mXdgSurface); xdg_toplevel_set_title(mXdgTopLevel, "Example client"); - auto region = wl_compositor_create_region(compositor); + auto region = wl_compositor_create_region(mCompositor); wl_region_add(region, 0, 0, mWindow->GetWidth(), mWindow->GetHeight()); wl_surface_set_opaque_region(mSurface, region); @@ -47,7 +71,6 @@ void WaylandSurface::initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_b void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial) { xdg_surface_ack_configure(xdg_surface, serial); - paint(nullptr); } @@ -55,18 +78,28 @@ void WaylandSurface::paint(mt::Screen* screen) { if (mEglWindowInterface) { - mEglWindowInterface->initialize(mSurface, mWindow->GetWidth(), mWindow->GetHeight()); - mEglWindowInterface->draw(); + paintHardware(); } else { - auto buffer = drawFrame(); - wl_surface_attach(mSurface, buffer, 0, 0); - //wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX); - wl_surface_commit(mSurface); + paintSoftware(); } } +void WaylandSurface::paintHardware() +{ + mEglWindowInterface->initialize(mSurface, mWindow->GetWidth(), mWindow->GetHeight()); + mEglWindowInterface->draw(); +} + +void WaylandSurface::paintSoftware() +{ + auto buffer = drawFrame(); + wl_surface_attach(mSurface, buffer, 0, 0); + //wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX); + wl_surface_commit(mSurface); +} + wl_buffer* WaylandSurface::drawFrame() { const auto width = mWindow->GetWidth(); diff --git a/src/windows/ui_interfaces/wayland/WaylandSurface.h b/src/windows/ui_interfaces/wayland/WaylandSurface.h index 670adcf..94093ec 100644 --- a/src/windows/ui_interfaces/wayland/WaylandSurface.h +++ b/src/windows/ui_interfaces/wayland/WaylandSurface.h @@ -18,46 +18,45 @@ class WaylandEglWindowInterface; class WaylandSurface : public IPlatformWindow { - public: - WaylandSurface(mt::Window* window); + + static void add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface); + + WaylandSurface(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface); ~WaylandSurface(); - void initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr buffer, WaylandEglInterface* eglInterface); - void onConfigure(xdg_surface *xdg_surface, uint32_t serial); + void show(); + + void map(); + + void clear(); + +private: + void initialize(); + + void paint(mt::Screen* screen) override; + + void paintHardware(); + void paintSoftware(); + + wl_buffer* drawFrame(); - void show() const - { - map(); - } - - void map() const - { - - } - - void clear() const - { - - } - -private: - void paint(mt::Screen* screen) override; - mt::Window* mWindow{nullptr}; + wl_compositor* mCompositor{nullptr}; + xdg_wm_base* mXdgWmBase{nullptr}; + std::shared_ptr mBuffer; + std::unique_ptr mEglWindowInterface; + wl_surface* mSurface{nullptr}; xdg_surface* mXdgSurface{nullptr}; - xdg_surface_listener mXdgSurfaceListener{nullptr}; + xdg_surface_listener mXdgSurfaceListener; xdg_toplevel* mXdgTopLevel{nullptr}; - - std::shared_ptr mBuffer; - std::unique_ptr mEglWindowInterface{nullptr}; }; using WaylandSurfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/GlxInterface.cpp b/src/windows/ui_interfaces/x11/GlxInterface.cpp deleted file mode 100644 index 70aaf09..0000000 --- a/src/windows/ui_interfaces/x11/GlxInterface.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "GlxInterface.h" - -#include "OpenGlInterface.h" -#include "FileLogger.h" - -#include - -GlxInterface::GlxInterface() - : mContext(), - mDrawable(), - mWindow(), - mConfig() -{ - -} - -static int visual_attribs[] = -{ - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - //GLX_SAMPLE_BUFFERS , 1, - //GLX_SAMPLES , 4, - None -}; - -std::unique_ptr GlxInterface::Create() -{ - return std::make_unique(); -} - -void GlxInterface::SetupContext(Display* display, int default_screen) -{ - /* Query framebuffer configurations that match visual_attribs */ - int num_fb_configs = 0; - GLXFBConfig* fb_configs = glXChooseFBConfig(display, default_screen, visual_attribs, &num_fb_configs); - if (!fb_configs || num_fb_configs == 0) - { - MLOG_ERROR("glXGetFBConfigs failed"); - return; - } - - /* Select first framebuffer config and query visualID */ - int visualID = 0; - mConfig = fb_configs[0]; - glXGetFBConfigAttrib(display, mConfig, GLX_VISUAL_ID, &visualID); - - /* Create OpenGL context */ - mContext = glXCreateNewContext(display, mConfig, GLX_RGBA_TYPE, 0, True); - if (!mContext) - { - MLOG_ERROR("glXCreateNewContext failed"); - return; - } -} - -void GlxInterface::SwapBuffers(Display* display) -{ - glXSwapBuffers(display, mDrawable); -} - -void GlxInterface::Draw() -{ - OpenGlInterface::draw(); -} - -bool GlxInterface::SetupWindow(Display* display, xcb_window_t window) -{ - /* Create GLX Window */ - mWindow = glXCreateWindow(display, mConfig, window, 0); - if (!mWindow) - { - glXDestroyContext(display, mContext); - MLOG_ERROR("glXCreateWindow failed"); - return false; - } - - mDrawable = mWindow; - - /* make OpenGL context current */ - if (!glXMakeContextCurrent(display, mDrawable, mDrawable, mContext)) - { - glXDestroyContext(display, mContext); - MLOG_ERROR("glXMakeContextCurrent failed"); - return false; - } - return true; -} - -void GlxInterface::DestroyWindow(Display* display) -{ - glXDestroyWindow(display, mWindow); -} - -void GlxInterface::DestroyContext(Display* display) -{ - glXDestroyContext(display, mContext); -} diff --git a/src/windows/ui_interfaces/x11/GlxInterface.h b/src/windows/ui_interfaces/x11/GlxInterface.h deleted file mode 100644 index 29b7406..0000000 --- a/src/windows/ui_interfaces/x11/GlxInterface.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include -#include -#include - -class GlxInterface -{ -public: - - GlxInterface(); - - static std::unique_ptr Create(); - - void SetupContext(Display* display, int default_screen); - - bool SetupWindow(Display* display, xcb_window_t window); - - void DestroyWindow(Display* display); - - void DestroyContext(Display* display); - - void SwapBuffers(Display* display); - - void Draw(); - -private: - GLXContext mContext; - GLXDrawable mDrawable; - GLXWindow mWindow; - GLXFBConfig mConfig; -}; - -using GlxInterfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbGlInterface.cpp b/src/windows/ui_interfaces/x11/XcbGlInterface.cpp new file mode 100644 index 0000000..02cbc09 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbGlInterface.cpp @@ -0,0 +1,71 @@ +#include "XcbGlInterface.h" + +#include "FileLogger.h" + +#include + +XcbGlInterface::XcbGlInterface(Display* display, int default_screen) + : mDisplay(display), + mContext(), + mConfig() +{ + setupContext(default_screen); +} + +XcbGlInterface::~XcbGlInterface() +{ + destroyContext(); +} + +static int visual_attribs[] = +{ + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GLX_ALPHA_SIZE, 8, + GLX_DEPTH_SIZE, 24, + GLX_STENCIL_SIZE, 8, + GLX_DOUBLEBUFFER, True, + //GLX_SAMPLE_BUFFERS , 1, + //GLX_SAMPLES , 4, + None +}; + +std::unique_ptr XcbGlInterface::Create(Display* display, int default_screen) +{ + return std::make_unique(display, default_screen); +} + +void XcbGlInterface::setupContext(int default_screen) +{ + /* Query framebuffer configurations that match visual_attribs */ + int num_fb_configs = 0; + GLXFBConfig* fb_configs = glXChooseFBConfig(mDisplay, default_screen, visual_attribs, &num_fb_configs); + if (!fb_configs || num_fb_configs == 0) + { + MLOG_ERROR("glXGetFBConfigs failed"); + return; + } + + /* Select first framebuffer config and query visualID */ + int visualID = 0; + mConfig = fb_configs[0]; + glXGetFBConfigAttrib(mDisplay, mConfig, GLX_VISUAL_ID, &visualID); + + /* Create OpenGL context */ + mContext = glXCreateNewContext(mDisplay, mConfig, GLX_RGBA_TYPE, 0, True); + if (!mContext) + { + MLOG_ERROR("glXCreateNewContext failed"); + return; + } +} + +void XcbGlInterface::destroyContext() +{ + glXDestroyContext(mDisplay, mContext); +} diff --git a/src/windows/ui_interfaces/x11/XcbGlInterface.h b/src/windows/ui_interfaces/x11/XcbGlInterface.h new file mode 100644 index 0000000..702ef77 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbGlInterface.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +class XcbGlInterface +{ +public: + XcbGlInterface(Display* display, int default_screen); + + ~XcbGlInterface(); + + static std::unique_ptr Create(Display* display, int default_screen); + + Display* getDisplay() const + { + return mDisplay; + } + + GLXContext getContext() const + { + return mContext; + } + + GLXFBConfig getConfig() const + { + return mConfig; + } + +private: + void setupContext(int default_screen); + void destroyContext(); + + Display* mDisplay{nullptr}; + GLXContext mContext; + GLXFBConfig mConfig; +}; + +using XcbGlInterfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbGlWindowInterface.cpp b/src/windows/ui_interfaces/x11/XcbGlWindowInterface.cpp new file mode 100644 index 0000000..9c8a61b --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbGlWindowInterface.cpp @@ -0,0 +1,67 @@ +#include "XcbGlWindowInterface.h" + +#include "OpenGlInterface.h" +#include "XcbGlInterface.h" +#include "FileLogger.h" + +#include + +XcbGlWindowInterface::XcbGlWindowInterface(XcbGlInterface* glInterface) + : mGlInterface(glInterface), + mDrawable(), + mWindow() +{ + +} + +XcbGlWindowInterface::~XcbGlWindowInterface() +{ + if (mWindow) + { + destroyWindow(); + } +} + +void XcbGlWindowInterface::draw() +{ + OpenGlInterface::draw(); + swapBuffers(); +} + +void XcbGlWindowInterface::swapBuffers() +{ + glXSwapBuffers(mGlInterface->getDisplay(), mDrawable); +} + +bool XcbGlWindowInterface::initialize(xcb_window_t window) +{ + if (mWindow) + { + return true; + } + + /* Create GLX Window */ + mWindow = glXCreateWindow(mGlInterface->getDisplay(), mGlInterface->getConfig(), window, 0); + if (!mWindow) + { + glXDestroyContext(mGlInterface->getDisplay(), mGlInterface->getContext()); + MLOG_ERROR("glXCreateWindow failed"); + return false; + } + + mDrawable = mWindow; + + /* make OpenGL context current */ + if (!glXMakeContextCurrent(mGlInterface->getDisplay(), mDrawable, mDrawable, mGlInterface->getContext())) + { + glXDestroyContext(mGlInterface->getDisplay(), mGlInterface->getContext()); + MLOG_ERROR("glXMakeContextCurrent failed"); + return false; + } + return true; +} + +void XcbGlWindowInterface::destroyWindow() +{ + glXDestroyWindow(mGlInterface->getDisplay(), mWindow); +} diff --git a/src/windows/ui_interfaces/x11/XcbGlWindowInterface.h b/src/windows/ui_interfaces/x11/XcbGlWindowInterface.h new file mode 100644 index 0000000..aa9f934 --- /dev/null +++ b/src/windows/ui_interfaces/x11/XcbGlWindowInterface.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include +#include + +class XcbGlInterface; + +class XcbGlWindowInterface +{ +public: + XcbGlWindowInterface(XcbGlInterface* glInterface); + + ~XcbGlWindowInterface(); + + bool initialize(xcb_window_t window); + + void draw(); + +private: + void destroyWindow(); + void swapBuffers(); + + XcbGlInterface* mGlInterface{nullptr}; + GLXDrawable mDrawable; + GLXWindow mWindow; +}; + +using XcbGlWindowInterfacePtr = std::unique_ptr; diff --git a/src/windows/ui_interfaces/x11/XcbInterface.cpp b/src/windows/ui_interfaces/x11/XcbInterface.cpp index a787225..dad4ee6 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.cpp +++ b/src/windows/ui_interfaces/x11/XcbInterface.cpp @@ -15,23 +15,20 @@ #include "XcbWindow.h" #include "XcbLayerInterface.h" #include "XcbEventInterface.h" -#include "GlxInterface.h" +#include "XcbGlInterface.h" #include "FileLogger.h" XcbInterface::XcbInterface(DesktopManager* desktopManager, bool useHardware) : AbstractUIInterface(desktopManager, useHardware), - mConnection(nullptr), - mX11Display(), - mGlxInterface(), - mXcbEventInterface(XcbEventInterface::Create()) + mEventInterface(XcbEventInterface::Create()) { } XcbInterface::~XcbInterface() { - + shutDown(); } void XcbInterface::initialize() @@ -41,9 +38,17 @@ void XcbInterface::initialize() createGraphicsContext(); if (mUseHardwareRendering) { - initializeOpenGl(); + initializeHardwareRendering(); } mDesktopManager->SetKeyboard(XcbKeyboard::Create()); + + const auto num_windows = mDesktopManager->GetWindowManager()->getNumWindows(); + for(std::size_t idx=0; idx< num_windows; idx++) + { + addWindow(mDesktopManager->GetWindowManager()->getWindow(idx)); + } + + mDesktopManager->GetWindowManager()->GetMainWindow()->show(); } void XcbInterface::connect() @@ -94,31 +99,10 @@ void XcbInterface::updateScreen() mDesktopManager->AddScreen(std::move(screen)); } -void XcbInterface::initializeOpenGl() +void XcbInterface::initializeHardwareRendering() { - mGlxInterface = GlxInterface::Create(); const auto default_screen = DefaultScreen(mX11Display); - mGlxInterface->SetupContext(mX11Display, default_screen); -} - -void XcbInterface::createOpenGlDrawable(mt::Window* window) -{ - if (!mUseHardwareRendering or !window or !window->GetPlatformWindow()) - { - return; - } - - auto xcb_window = dynamic_cast(window->GetPlatformWindow()); - if (!xcb_window) - { - return; - } - - if (!mGlxInterface->SetupWindow(mX11Display, xcb_window->getHandle())) - { - MLOG_ERROR("Failed to set up OpenGL Drawable"); - xcb_destroy_window(mConnection, xcb_window->getHandle()); - } + mGlInterface = XcbGlInterface::Create(mX11Display, default_screen); } void XcbInterface::createGraphicsContext() @@ -149,11 +133,6 @@ void XcbInterface::mapWindow(mt::Window* window) void XcbInterface::showWindow(mt::Window* window) { window->show(); - - if (mUseHardwareRendering) - { - createOpenGlDrawable(window); - } } uint32_t XcbInterface::getEventMask() @@ -167,7 +146,7 @@ uint32_t XcbInterface::getEventMask() void XcbInterface::addWindow(mt::Window* window) { auto screen = mDesktopManager->GetDefaultScreen(); - XcbWindow::add(window, mConnection, screen, getEventMask()); + XcbWindow::add(window, mConnection, screen, getEventMask(), mGlInterface.get()); } void XcbInterface::onPaint() @@ -182,27 +161,16 @@ void XcbInterface::onPaint() void XcbInterface::onExposeEvent(xcb_expose_event_t* event) { - // Update the window - if (mUseHardwareRendering) - { - mGlxInterface->Draw(); - mGlxInterface->SwapBuffers(mX11Display); - } - else - { - //auto window = mWindows[event->window]; - //window->SetSize(event->width, event->height); - onPaint(); - xcb_flush(mConnection); - } + //auto window = mWindows[event->window]; + //window->SetSize(event->width, event->height); + + onPaint(); } void XcbInterface::loop() { - if (!mConnection) - { - return; - } + initialize(); + xcb_generic_event_t *event; while ((event = xcb_wait_for_event(mConnection))) { @@ -215,25 +183,25 @@ void XcbInterface::loop() } case XCB_KEY_PRESS: { auto kp = reinterpret_cast(event); - auto ui_event = mXcbEventInterface->ConvertKeyPress(kp, mDesktopManager->GetKeyboard()); + auto ui_event = mEventInterface->ConvertKeyPress(kp, mDesktopManager->GetKeyboard()); mDesktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_KEY_RELEASE: { auto kr = reinterpret_cast(event); - auto ui_event = mXcbEventInterface->ConvertKeyRelease(kr, mDesktopManager->GetKeyboard()); + auto ui_event = mEventInterface->ConvertKeyRelease(kr, mDesktopManager->GetKeyboard()); mDesktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_BUTTON_PRESS: { auto press = reinterpret_cast(event); - auto ui_event = mXcbEventInterface->ConvertButtonPress(press); + auto ui_event = mEventInterface->ConvertButtonPress(press); mDesktopManager->OnUiEvent(std::move(ui_event)); break; } case XCB_BUTTON_RELEASE: { auto release = reinterpret_cast(event); - auto ui_event = mXcbEventInterface->ConvertButtonRelease(release); + auto ui_event = mEventInterface->ConvertButtonRelease(release); mDesktopManager->OnUiEvent(std::move(ui_event)); break; } @@ -244,16 +212,6 @@ void XcbInterface::loop() onEventsDispatched(); free(event); } - onLoopCompleted(); -} - -void XcbInterface::onLoopCompleted() -{ - if (mUseHardwareRendering) - { - mGlxInterface->DestroyWindow(mX11Display); - mGlxInterface->DestroyContext(mX11Display); - } } void XcbInterface::onEventsDispatched() @@ -268,6 +226,8 @@ void XcbInterface::onEventsDispatched() void XcbInterface::shutDown() { + mDesktopManager->GetWindowManager()->clearPlatformWindows(); + if (!mConnection) { return; diff --git a/src/windows/ui_interfaces/x11/XcbInterface.h b/src/windows/ui_interfaces/x11/XcbInterface.h index d4ec561..1d66f29 100644 --- a/src/windows/ui_interfaces/x11/XcbInterface.h +++ b/src/windows/ui_interfaces/x11/XcbInterface.h @@ -4,8 +4,8 @@ #include -class GlxInterface; -using GlxInterfacePtr = std::unique_ptr; +class XcbGlInterface; +using XcbGlInterfacePtr = std::unique_ptr; class XcbEventInterface; using XcbEventInterfacePtr = std::unique_ptr; @@ -29,35 +29,31 @@ public: ~XcbInterface(); - void initialize() override; - void loop() override; - void shutDown() override; - - void showWindow(mt::Window* window) override; - void addWindow(mt::Window* window) override; + void showWindow(mt::Window* window) override; + private: + void initialize() override; void onPaint(); void onEventsDispatched(); - void onLoopCompleted(); void onExposeEvent(xcb_expose_event_t* event); - void initializeOpenGl(); + void initializeHardwareRendering() override; void createGraphicsContext(); - void createOpenGlDrawable(mt::Window* window); void connect(); void updateScreen(); void mapWindow(mt::Window* window); + void shutDown() override; uint32_t getEventMask(); private: - xcb_connection_t* mConnection; - _XDisplay* mX11Display; - GlxInterfacePtr mGlxInterface; - XcbEventInterfacePtr mXcbEventInterface {nullptr}; + xcb_connection_t* mConnection{nullptr}; + _XDisplay* mX11Display{nullptr}; + XcbGlInterfacePtr mGlInterface; + XcbEventInterfacePtr mEventInterface; }; diff --git a/src/windows/ui_interfaces/x11/XcbWindow.cpp b/src/windows/ui_interfaces/x11/XcbWindow.cpp index b40a810..a1b6d2e 100644 --- a/src/windows/ui_interfaces/x11/XcbWindow.cpp +++ b/src/windows/ui_interfaces/x11/XcbWindow.cpp @@ -6,18 +6,27 @@ #include "XcbImage.h" #include "Screen.h" #include "ImagePrimitives.h" +#include "XcbGlWindowInterface.h" #include -XcbWindow::XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection) +XcbWindow::XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection, XcbGlInterface* xcbGlInterface) : IPlatformWindow(window), mHandle(hwnd), mConnection(connection) { - + if (xcbGlInterface) + { + mGlInterface = std::make_unique(xcbGlInterface); + } } -void XcbWindow::add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask) +XcbWindow::~XcbWindow() +{ + xcb_destroy_window(mConnection, mHandle); +} + +void XcbWindow::add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask, XcbGlInterface* xcbGlInterface) { if (!screen) { @@ -39,7 +48,7 @@ void XcbWindow::add(mt::Window* window, xcb_connection_t* connection, mt::Screen xcb_screen->GetNativeScreen()->root_visual, /* visual */ mask, values ); /* masks */ - auto xcb_window = std::make_unique(window, hwnd, connection); + auto xcb_window = std::make_unique(window, hwnd, connection, xcbGlInterface); window->SetPlatformWindow(std::move(xcb_window)); } @@ -53,7 +62,7 @@ unsigned XcbWindow::getGraphicsContext() const return mGraphicsContext; } -void XcbWindow::show() const +void XcbWindow::show() { map(); } @@ -62,18 +71,39 @@ void XcbWindow::paint(mt::Screen* screen) { auto xcb_screen = dynamic_cast(screen->GetPlatformScreen()); + if (mGlInterface) + { + paintHardware(xcb_screen); + } + else + { + paintSoftware(xcb_screen); + } +} + +void XcbWindow::paintHardware(XcbScreen* screen) +{ + if (mGlInterface) + { + mGlInterface->initialize(mHandle); + mGlInterface->draw(); + } +} + +void XcbWindow::paintSoftware(XcbScreen* screen) +{ if (!mBackingImage) { - mBackingImage = std::make_unique(mConnection, mWindow, xcb_screen->GetNativeScreen()); + mBackingImage = std::make_unique(mConnection, mWindow, screen->GetNativeScreen()); } auto backing_image = mWindow->getBackingImage(); backing_image->initialize(); //ImagePrimitives::drawCheckerboard(const_cast(backing_image->getDataPtr()), backing_image->getWidth(), backing_image->getHeight(), 0); - mBackingImage->update(mWindow, xcb_screen->GetNativeScreen(), mConnection, xcb_screen->GetGraphicsContext()); + mBackingImage->update(mWindow, screen->GetNativeScreen(), mConnection, screen->GetGraphicsContext()); - xcb_copy_area(mConnection, mBackingImage->getPixMap(), mHandle, xcb_screen->GetGraphicsContext(), 0, 0 ,0 , 0, backing_image->getWidth(), backing_image->getHeight()); + xcb_copy_area(mConnection, mBackingImage->getPixMap(), mHandle, screen->GetGraphicsContext(), 0, 0 ,0 , 0, backing_image->getWidth(), backing_image->getHeight()); /* for(const auto& layer : mWindow->GetLayers()) { @@ -82,13 +112,13 @@ void XcbWindow::paint(mt::Screen* screen) */ } -void XcbWindow::clear() const +void XcbWindow::clear() { xcb_clear_area(mConnection, 1, mHandle, 0, 0, mWindow->GetWidth(), mWindow->GetHeight()); xcb_flush(mConnection); } -void XcbWindow::map() const +void XcbWindow::map() { xcb_map_window(mConnection, mHandle); xcb_flush(mConnection); diff --git a/src/windows/ui_interfaces/x11/XcbWindow.h b/src/windows/ui_interfaces/x11/XcbWindow.h index 9be33b2..35c0c00 100644 --- a/src/windows/ui_interfaces/x11/XcbWindow.h +++ b/src/windows/ui_interfaces/x11/XcbWindow.h @@ -3,6 +3,9 @@ #include "IPlatformWindow.h" class XcbImage; +class XcbScreen; +class XcbGlWindowInterface; +class XcbGlInterface; struct xcb_connection_t; namespace mt @@ -13,27 +16,31 @@ namespace mt class XcbWindow : public IPlatformWindow { public: - XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection); - virtual ~XcbWindow() = default; + XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection, XcbGlInterface* xcbGlInterface); + virtual ~XcbWindow(); - static void add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask); + static void add(mt::Window* window, xcb_connection_t* connection, mt::Screen* screen, uint32_t eventMask, XcbGlInterface* xcbGlInterface); int getHandle() const; unsigned getGraphicsContext() const; - void show() const override; + void show() override; void paint(mt::Screen* screen) override; - void clear() const override; + void clear() override; - void map() const override; + void map() override; private: + void paintHardware(XcbScreen* screen); + void paintSoftware(XcbScreen* screen); + int mHandle{-1}; unsigned mGraphicsContext {0}; xcb_connection_t* mConnection{nullptr}; std::unique_ptr mBackingImage; + std::unique_ptr mGlInterface; }; using XcbWindowPtr = std::unique_ptr; diff --git a/test/graphics/TestOpenGlRendering.cpp b/test/graphics/TestOpenGlRendering.cpp index f6f8cab..aa0e19a 100644 --- a/test/graphics/TestOpenGlRendering.cpp +++ b/test/graphics/TestOpenGlRendering.cpp @@ -14,8 +14,8 @@ public: { auto app = std::make_unique(); - //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11); - app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); + app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11); + //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); app->run(); return true; diff --git a/test/image/TestPngWriter.cpp b/test/image/TestPngWriter.cpp index b877858..c01cf9d 100644 --- a/test/image/TestPngWriter.cpp +++ b/test/image/TestPngWriter.cpp @@ -9,13 +9,13 @@ int main() unsigned width = 200; unsigned height = 200; unsigned numChannels = 3; - auto image = Image::Create(width, height); - image->SetNumChannels(numChannels); + auto image = Image::Create(width, height); + image->setNumChannels(numChannels); - std::vector data(image->GetBytesPerRow()*height, 0); + std::vector data(image->getBytesPerRow()*height, 0); for(unsigned jdx=0;jdxGetBytesPerRow(); + const auto heightOffset = jdx*image->getBytesPerRow(); for(unsigned idx=0;idxSetData(data); + image->setData(data); PngWriter writer; writer.SetPath("test.png");