Cleaning window managers for consistency.

This commit is contained in:
James Grogan 2022-11-12 15:34:54 +00:00
parent 5d984aa61d
commit 392a2b7889
28 changed files with 452 additions and 325 deletions

View file

@ -45,13 +45,8 @@ void GuiApplication::run()
MLOG_INFO("Creating Window Interface"); MLOG_INFO("Creating Window Interface");
mUiInterface = UiInterfaceFactory::create(mDesktopManager.get(), mUiInterfaceBackend); mUiInterface = UiInterfaceFactory::create(mDesktopManager.get(), mUiInterfaceBackend);
mUiInterface->initialize();
mUiInterface->addWindow(mainWindow);
mUiInterface->showWindow(mainWindow);
mUiInterface->loop(); mUiInterface->loop();
mUiInterface->shutDown();
MLOG_INFO("Window Interface Shut Down"); MLOG_INFO("Window Interface Shut Down");
mMainApplication->ShutDown(); mMainApplication->ShutDown();

View file

@ -26,11 +26,11 @@ public:
virtual ~IPlatformWindow() = default; 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: protected:
mt::Window* mWindow{nullptr}; mt::Window* mWindow{nullptr};
}; };

View file

@ -35,6 +35,12 @@ std::vector<VisualLayer*> Window::GetLayers()
return mWidget->getLayers(); return mWidget->getLayers();
} }
void Window::clearPlatformWindow()
{
mPlatformWindow.reset();
}
void Window::OnMouseEvent(const MouseEvent* event) void Window::OnMouseEvent(const MouseEvent* event)
{ {
mWidget->onMouseEvent(event); mWidget->onMouseEvent(event);

View file

@ -62,6 +62,8 @@ public:
void clear(); void clear();
void clearPlatformWindow();
private: private:
int mHandle {-1}; int mHandle {-1};
WidgetUPtr mWidget {nullptr}; WidgetUPtr mWidget {nullptr};

View file

@ -15,7 +15,8 @@ if(UNIX)
ui_interfaces/x11/XcbLayerInterface.cpp ui_interfaces/x11/XcbLayerInterface.cpp
ui_interfaces/x11/XcbTextInterface.cpp ui_interfaces/x11/XcbTextInterface.cpp
ui_interfaces/x11/XcbKeyboard.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 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}) list(APPEND X11_INCLUDE_DIRS ${X11_xkbcommon_INCLUDE_PATH})

View file

@ -36,6 +36,14 @@ void WindowManager::AddWindow(WindowUPtr window)
mWindows.push_back(std::move(window)); mWindows.push_back(std::move(window));
} }
void WindowManager::clearPlatformWindows()
{
for (auto& window : mWindows)
{
window->clearPlatformWindow();
}
}
mt::Window* WindowManager::GetMainWindow() const mt::Window* WindowManager::GetMainWindow() const
{ {
if(mWindows.size()>0) if(mWindows.size()>0)

View file

@ -27,6 +27,18 @@ public:
void OnKeyboardEvent(const KeyboardEvent* event); 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: private:
std::vector<WindowUPtr> mWindows; std::vector<WindowUPtr> mWindows;
}; };

View file

@ -19,22 +19,18 @@ public:
virtual ~AbstractUIInterface() = default; virtual ~AbstractUIInterface() = default;
virtual void initialize() = 0;
virtual void loop() = 0; virtual void loop() = 0;
virtual void shutDown() = 0;
virtual void showWindow(mt::Window* window) = 0; virtual void showWindow(mt::Window* window) = 0;
virtual void addWindow(mt::Window* window) = 0; virtual void addWindow(mt::Window* window) = 0;
void setUseHardwareRendering(bool useHardware)
{
mUseHardwareRendering = useHardware;
}
protected: protected:
virtual void initialize() = 0;
virtual void shutDown() = 0;
virtual void initializeHardwareRendering() {};
DesktopManager* mDesktopManager{nullptr}; DesktopManager* mDesktopManager{nullptr};
bool mUseHardwareRendering{false}; bool mUseHardwareRendering{false};
}; };

View file

@ -4,6 +4,11 @@
#include <wayland-egl.h> #include <wayland-egl.h>
WaylandEglInterface::WaylandEglInterface(wl_display* display)
{
initialize(display);
}
void WaylandEglInterface::initialize(wl_display* display) void WaylandEglInterface::initialize(wl_display* display)
{ {
mEglDisplay = eglGetDisplay((EGLNativeDisplayType) display); mEglDisplay = eglGetDisplay((EGLNativeDisplayType) display);

View file

@ -7,8 +7,7 @@ struct wl_display;
class WaylandEglInterface class WaylandEglInterface
{ {
public: public:
WaylandEglInterface(wl_display* display);
void initialize(wl_display* display);
EGLDisplay getDisplay() const; EGLDisplay getDisplay() const;
@ -17,6 +16,8 @@ public:
EGLContext getContext() const; EGLContext getContext() const;
private: private:
void initialize(wl_display* display);
EGLDisplay mEglDisplay; EGLDisplay mEglDisplay;
EGLConfig mEglConfig; EGLConfig mEglConfig;
EGLContext mEglContext; EGLContext mEglContext;

View file

@ -19,6 +19,6 @@ public:
private: private:
wl_egl_window* mEglWindow{nullptr}; wl_egl_window* mEglWindow{nullptr};
EGLSurface mEglSurface; EGLSurface mEglSurface{nullptr};
WaylandEglInterface* mEglInterface; WaylandEglInterface* mEglInterface;
}; };

View file

@ -1,6 +1,9 @@
#include "WaylandInterface.h" #include "WaylandInterface.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "DesktopManager.h"
#include "WindowManager.h"
#include "WaylandSurface.h" #include "WaylandSurface.h"
#include "WaylandBuffer.h" #include "WaylandBuffer.h"
#include "WaylandSeatInterface.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) uint32_t name, const char *interface, uint32_t version)
{ {
auto thisClass = static_cast<WaylandInterface*>(data); auto thisClass = static_cast<WaylandInterface*>(data);
std::stringstream sstrm; std::stringstream sstrm;
sstrm << "interface: " << interface << " version " << version << " name " << name; sstrm << "interface: " << interface << " version " << version << " name " << name;
MLOG_INFO(sstrm.str()); //MLOG_INFO(sstrm.str());
if (strcmp(interface, wl_compositor_interface.name) == 0) if (strcmp(interface, wl_compositor_interface.name) == 0)
{ {
@ -51,7 +53,7 @@ WaylandInterface::WaylandInterface(DesktopManager* desktopManager, bool useHardw
WaylandInterface::~WaylandInterface() WaylandInterface::~WaylandInterface()
{ {
shutDown();
} }
void WaylandInterface::initialize() void WaylandInterface::initialize()
@ -76,9 +78,21 @@ void WaylandInterface::initialize()
if (mUseHardwareRendering) if (mUseHardwareRendering)
{ {
mEglInterface = std::make_unique<WaylandEglInterface>(); initializeHardwareRendering();
mEglInterface->initialize(mDisplay);
} }
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<WaylandEglInterface>(mDisplay);
} }
void WaylandInterface::setSeat(wl_seat* seat) void WaylandInterface::setSeat(wl_seat* seat)
@ -115,18 +129,12 @@ void WaylandInterface::doXdgPong(uint32_t serial)
void WaylandInterface::addWindow(mt::Window* window) void WaylandInterface::addWindow(mt::Window* window)
{ {
auto surface = std::make_unique<WaylandSurface>(window); WaylandSurface::add(window, mCompositor, mXdgBase, mBuffer, mEglInterface.get());
mSurfaces.push_back(std::move(surface));
} }
void WaylandInterface::showWindow(mt::Window* window) void WaylandInterface::showWindow(mt::Window* window)
{ {
if (mSurfaces.empty()) window->show();
{
return;
}
mSurfaces[0]->initialize(mCompositor, mXdgBase, mBuffer, mEglInterface.get());
} }
void WaylandInterface::shutDown() void WaylandInterface::shutDown()
@ -139,6 +147,8 @@ void WaylandInterface::shutDown()
void WaylandInterface::loop() void WaylandInterface::loop()
{ {
initialize();
while (wl_display_dispatch(mDisplay) != -1) while (wl_display_dispatch(mDisplay) != -1)
{ {
/* This space deliberately left blank */ /* This space deliberately left blank */

View file

@ -10,7 +10,6 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
class WaylandSurface;
class WaylandBuffer; class WaylandBuffer;
class WaylandSeatInterface; class WaylandSeatInterface;
class WaylandEglInterface; class WaylandEglInterface;
@ -29,11 +28,13 @@ public:
void showWindow(mt::Window* window) override; void showWindow(mt::Window* window) override;
private:
void initialize() override; void initialize() override;
void initializeHardwareRendering() override;
void shutDown() 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 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); 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* mXdgBase{nullptr};
xdg_wm_base_listener mXdgBaseListener; xdg_wm_base_listener mXdgBaseListener;
std::vector<std::unique_ptr<WaylandSurface> > mSurfaces;
std::shared_ptr<WaylandBuffer> mBuffer; std::shared_ptr<WaylandBuffer> mBuffer;
std::unique_ptr<WaylandSeatInterface> mSeatInterface; std::unique_ptr<WaylandSeatInterface> mSeatInterface;
std::unique_ptr<WaylandEglInterface> mEglInterface; std::unique_ptr<WaylandEglInterface> mEglInterface;

View file

@ -3,10 +3,22 @@
#include "WaylandEglWindowInterface.h" #include "WaylandEglWindowInterface.h"
#include "ImagePrimitives.h" #include "ImagePrimitives.h"
WaylandSurface::WaylandSurface(mt::Window* window) void WaylandSurface::add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, WaylandEglInterface* eglInterface)
: IPlatformWindow(window)
{ {
auto wayland_window = std::make_unique<WaylandSurface>(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<WaylandBuffer> buffer, WaylandEglInterface* eglInterface)
: IPlatformWindow(window),
mCompositor(compositor),
mXdgWmBase(xdg_wm_base),
mBuffer(buffer)
{
if (eglInterface)
{
mEglWindowInterface = std::make_unique<WaylandEglWindowInterface>(eglInterface);
}
} }
WaylandSurface::~WaylandSurface() WaylandSurface::~WaylandSurface()
@ -14,16 +26,28 @@ WaylandSurface::~WaylandSurface()
} }
void WaylandSurface::initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, WaylandEglInterface* eglInterface) void WaylandSurface::show()
{ {
mBuffer = buffer; map();
if (eglInterface)
{
mEglWindowInterface = std::make_unique<WaylandEglWindowInterface>(eglInterface);
} }
mSurface = wl_compositor_create_surface(compositor); void WaylandSurface::clear()
mXdgSurface = xdg_wm_base_get_xdg_surface(xdg_wm_base, mSurface); {
}
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) 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); mXdgTopLevel = xdg_surface_get_toplevel(mXdgSurface);
xdg_toplevel_set_title(mXdgTopLevel, "Example client"); 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_region_add(region, 0, 0, mWindow->GetWidth(), mWindow->GetHeight());
wl_surface_set_opaque_region(mSurface, region); wl_surface_set_opaque_region(mSurface, region);
@ -47,25 +71,34 @@ void WaylandSurface::initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_b
void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial) void WaylandSurface::onConfigure(xdg_surface *xdg_surface, uint32_t serial)
{ {
xdg_surface_ack_configure(xdg_surface, serial); xdg_surface_ack_configure(xdg_surface, serial);
paint(nullptr); paint(nullptr);
} }
void WaylandSurface::paint(mt::Screen* screen) void WaylandSurface::paint(mt::Screen* screen)
{ {
if (mEglWindowInterface) if (mEglWindowInterface)
{
paintHardware();
}
else
{
paintSoftware();
}
}
void WaylandSurface::paintHardware()
{ {
mEglWindowInterface->initialize(mSurface, mWindow->GetWidth(), mWindow->GetHeight()); mEglWindowInterface->initialize(mSurface, mWindow->GetWidth(), mWindow->GetHeight());
mEglWindowInterface->draw(); mEglWindowInterface->draw();
} }
else
void WaylandSurface::paintSoftware()
{ {
auto buffer = drawFrame(); auto buffer = drawFrame();
wl_surface_attach(mSurface, buffer, 0, 0); wl_surface_attach(mSurface, buffer, 0, 0);
//wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX); //wl_surface_damage(mSurface, 0, 0, UINT32_MAX, UINT32_MAX);
wl_surface_commit(mSurface); wl_surface_commit(mSurface);
} }
}
wl_buffer* WaylandSurface::drawFrame() wl_buffer* WaylandSurface::drawFrame()
{ {

View file

@ -18,46 +18,45 @@ class WaylandEglWindowInterface;
class WaylandSurface : public IPlatformWindow class WaylandSurface : public IPlatformWindow
{ {
public: public:
WaylandSurface(mt::Window* window);
static void add(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, WaylandEglInterface* eglInterface);
WaylandSurface(mt::Window* window, wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, WaylandEglInterface* eglInterface);
~WaylandSurface(); ~WaylandSurface();
void initialize(wl_compositor* compositor, xdg_wm_base* xdg_wm_base, std::shared_ptr<WaylandBuffer> buffer, WaylandEglInterface* eglInterface);
void onConfigure(xdg_surface *xdg_surface, uint32_t serial); 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(); wl_buffer* drawFrame();
void show() const
{
map();
}
void map() const
{
}
void clear() const
{
}
private:
void paint(mt::Screen* screen) override;
mt::Window* mWindow{nullptr}; mt::Window* mWindow{nullptr};
wl_compositor* mCompositor{nullptr};
xdg_wm_base* mXdgWmBase{nullptr};
std::shared_ptr<WaylandBuffer> mBuffer;
std::unique_ptr<WaylandEglWindowInterface> mEglWindowInterface;
wl_surface* mSurface{nullptr}; wl_surface* mSurface{nullptr};
xdg_surface* mXdgSurface{nullptr}; xdg_surface* mXdgSurface{nullptr};
xdg_surface_listener mXdgSurfaceListener{nullptr}; xdg_surface_listener mXdgSurfaceListener;
xdg_toplevel* mXdgTopLevel{nullptr}; xdg_toplevel* mXdgTopLevel{nullptr};
std::shared_ptr<WaylandBuffer> mBuffer;
std::unique_ptr<WaylandEglWindowInterface> mEglWindowInterface{nullptr};
}; };
using WaylandSurfacePtr = std::unique_ptr<WaylandSurface>; using WaylandSurfacePtr = std::unique_ptr<WaylandSurface>;

View file

@ -1,106 +0,0 @@
#include "GlxInterface.h"
#include "OpenGlInterface.h"
#include "FileLogger.h"
#include <GL/gl.h>
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> GlxInterface::Create()
{
return std::make_unique<GlxInterface>();
}
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);
}

View file

@ -1,33 +0,0 @@
#pragma once
#include <GL/glx.h>
#include <xcb/xcb.h>
#include <memory>
class GlxInterface
{
public:
GlxInterface();
static std::unique_ptr<GlxInterface> 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<GlxInterface>;

View file

@ -0,0 +1,71 @@
#include "XcbGlInterface.h"
#include "FileLogger.h"
#include <GL/gl.h>
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> XcbGlInterface::Create(Display* display, int default_screen)
{
return std::make_unique<XcbGlInterface>(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);
}

View file

@ -0,0 +1,39 @@
#pragma once
#include <GL/glx.h>
#include <memory>
class XcbGlInterface
{
public:
XcbGlInterface(Display* display, int default_screen);
~XcbGlInterface();
static std::unique_ptr<XcbGlInterface> 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<XcbGlInterface>;

View file

@ -0,0 +1,67 @@
#include "XcbGlWindowInterface.h"
#include "OpenGlInterface.h"
#include "XcbGlInterface.h"
#include "FileLogger.h"
#include <GL/gl.h>
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);
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <GL/glx.h>
#include <xcb/xcb.h>
#include <memory>
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<XcbGlWindowInterface>;

View file

@ -15,23 +15,20 @@
#include "XcbWindow.h" #include "XcbWindow.h"
#include "XcbLayerInterface.h" #include "XcbLayerInterface.h"
#include "XcbEventInterface.h" #include "XcbEventInterface.h"
#include "GlxInterface.h" #include "XcbGlInterface.h"
#include "FileLogger.h" #include "FileLogger.h"
XcbInterface::XcbInterface(DesktopManager* desktopManager, bool useHardware) XcbInterface::XcbInterface(DesktopManager* desktopManager, bool useHardware)
: AbstractUIInterface(desktopManager, useHardware), : AbstractUIInterface(desktopManager, useHardware),
mConnection(nullptr), mEventInterface(XcbEventInterface::Create())
mX11Display(),
mGlxInterface(),
mXcbEventInterface(XcbEventInterface::Create())
{ {
} }
XcbInterface::~XcbInterface() XcbInterface::~XcbInterface()
{ {
shutDown();
} }
void XcbInterface::initialize() void XcbInterface::initialize()
@ -41,9 +38,17 @@ void XcbInterface::initialize()
createGraphicsContext(); createGraphicsContext();
if (mUseHardwareRendering) if (mUseHardwareRendering)
{ {
initializeOpenGl(); initializeHardwareRendering();
} }
mDesktopManager->SetKeyboard(XcbKeyboard::Create()); 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() void XcbInterface::connect()
@ -94,31 +99,10 @@ void XcbInterface::updateScreen()
mDesktopManager->AddScreen(std::move(screen)); mDesktopManager->AddScreen(std::move(screen));
} }
void XcbInterface::initializeOpenGl() void XcbInterface::initializeHardwareRendering()
{ {
mGlxInterface = GlxInterface::Create();
const auto default_screen = DefaultScreen(mX11Display); const auto default_screen = DefaultScreen(mX11Display);
mGlxInterface->SetupContext(mX11Display, default_screen); mGlInterface = XcbGlInterface::Create(mX11Display, default_screen);
}
void XcbInterface::createOpenGlDrawable(mt::Window* window)
{
if (!mUseHardwareRendering or !window or !window->GetPlatformWindow())
{
return;
}
auto xcb_window = dynamic_cast<XcbWindow*>(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());
}
} }
void XcbInterface::createGraphicsContext() void XcbInterface::createGraphicsContext()
@ -149,11 +133,6 @@ void XcbInterface::mapWindow(mt::Window* window)
void XcbInterface::showWindow(mt::Window* window) void XcbInterface::showWindow(mt::Window* window)
{ {
window->show(); window->show();
if (mUseHardwareRendering)
{
createOpenGlDrawable(window);
}
} }
uint32_t XcbInterface::getEventMask() uint32_t XcbInterface::getEventMask()
@ -167,7 +146,7 @@ uint32_t XcbInterface::getEventMask()
void XcbInterface::addWindow(mt::Window* window) void XcbInterface::addWindow(mt::Window* window)
{ {
auto screen = mDesktopManager->GetDefaultScreen(); auto screen = mDesktopManager->GetDefaultScreen();
XcbWindow::add(window, mConnection, screen, getEventMask()); XcbWindow::add(window, mConnection, screen, getEventMask(), mGlInterface.get());
} }
void XcbInterface::onPaint() void XcbInterface::onPaint()
@ -181,28 +160,17 @@ void XcbInterface::onPaint()
} }
void XcbInterface::onExposeEvent(xcb_expose_event_t* event) void XcbInterface::onExposeEvent(xcb_expose_event_t* event)
{
// Update the window
if (mUseHardwareRendering)
{
mGlxInterface->Draw();
mGlxInterface->SwapBuffers(mX11Display);
}
else
{ {
//auto window = mWindows[event->window]; //auto window = mWindows[event->window];
//window->SetSize(event->width, event->height); //window->SetSize(event->width, event->height);
onPaint(); onPaint();
xcb_flush(mConnection);
}
} }
void XcbInterface::loop() void XcbInterface::loop()
{ {
if (!mConnection) initialize();
{
return;
}
xcb_generic_event_t *event; xcb_generic_event_t *event;
while ((event = xcb_wait_for_event(mConnection))) while ((event = xcb_wait_for_event(mConnection)))
{ {
@ -215,25 +183,25 @@ void XcbInterface::loop()
} }
case XCB_KEY_PRESS: { case XCB_KEY_PRESS: {
auto kp = reinterpret_cast<xcb_key_press_event_t*>(event); auto kp = reinterpret_cast<xcb_key_press_event_t*>(event);
auto ui_event = mXcbEventInterface->ConvertKeyPress(kp, mDesktopManager->GetKeyboard()); auto ui_event = mEventInterface->ConvertKeyPress(kp, mDesktopManager->GetKeyboard());
mDesktopManager->OnUiEvent(std::move(ui_event)); mDesktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_KEY_RELEASE: { case XCB_KEY_RELEASE: {
auto kr = reinterpret_cast<xcb_key_release_event_t*>(event); auto kr = reinterpret_cast<xcb_key_release_event_t*>(event);
auto ui_event = mXcbEventInterface->ConvertKeyRelease(kr, mDesktopManager->GetKeyboard()); auto ui_event = mEventInterface->ConvertKeyRelease(kr, mDesktopManager->GetKeyboard());
mDesktopManager->OnUiEvent(std::move(ui_event)); mDesktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_BUTTON_PRESS: { case XCB_BUTTON_PRESS: {
auto press = reinterpret_cast<xcb_button_press_event_t*>(event); auto press = reinterpret_cast<xcb_button_press_event_t*>(event);
auto ui_event = mXcbEventInterface->ConvertButtonPress(press); auto ui_event = mEventInterface->ConvertButtonPress(press);
mDesktopManager->OnUiEvent(std::move(ui_event)); mDesktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
case XCB_BUTTON_RELEASE: { case XCB_BUTTON_RELEASE: {
auto release = reinterpret_cast<xcb_button_release_event_t*>(event); auto release = reinterpret_cast<xcb_button_release_event_t*>(event);
auto ui_event = mXcbEventInterface->ConvertButtonRelease(release); auto ui_event = mEventInterface->ConvertButtonRelease(release);
mDesktopManager->OnUiEvent(std::move(ui_event)); mDesktopManager->OnUiEvent(std::move(ui_event));
break; break;
} }
@ -244,16 +212,6 @@ void XcbInterface::loop()
onEventsDispatched(); onEventsDispatched();
free(event); free(event);
} }
onLoopCompleted();
}
void XcbInterface::onLoopCompleted()
{
if (mUseHardwareRendering)
{
mGlxInterface->DestroyWindow(mX11Display);
mGlxInterface->DestroyContext(mX11Display);
}
} }
void XcbInterface::onEventsDispatched() void XcbInterface::onEventsDispatched()
@ -268,6 +226,8 @@ void XcbInterface::onEventsDispatched()
void XcbInterface::shutDown() void XcbInterface::shutDown()
{ {
mDesktopManager->GetWindowManager()->clearPlatformWindows();
if (!mConnection) if (!mConnection)
{ {
return; return;

View file

@ -4,8 +4,8 @@
#include <memory> #include <memory>
class GlxInterface; class XcbGlInterface;
using GlxInterfacePtr = std::unique_ptr<GlxInterface>; using XcbGlInterfacePtr = std::unique_ptr<XcbGlInterface>;
class XcbEventInterface; class XcbEventInterface;
using XcbEventInterfacePtr = std::unique_ptr<XcbEventInterface>; using XcbEventInterfacePtr = std::unique_ptr<XcbEventInterface>;
@ -29,35 +29,31 @@ public:
~XcbInterface(); ~XcbInterface();
void initialize() override;
void loop() override; void loop() override;
void shutDown() override;
void showWindow(mt::Window* window) override;
void addWindow(mt::Window* window) override; void addWindow(mt::Window* window) override;
void showWindow(mt::Window* window) override;
private: private:
void initialize() override;
void onPaint(); void onPaint();
void onEventsDispatched(); void onEventsDispatched();
void onLoopCompleted();
void onExposeEvent(xcb_expose_event_t* event); void onExposeEvent(xcb_expose_event_t* event);
void initializeOpenGl(); void initializeHardwareRendering() override;
void createGraphicsContext(); void createGraphicsContext();
void createOpenGlDrawable(mt::Window* window);
void connect(); void connect();
void updateScreen(); void updateScreen();
void mapWindow(mt::Window* window); void mapWindow(mt::Window* window);
void shutDown() override;
uint32_t getEventMask(); uint32_t getEventMask();
private: private:
xcb_connection_t* mConnection; xcb_connection_t* mConnection{nullptr};
_XDisplay* mX11Display; _XDisplay* mX11Display{nullptr};
GlxInterfacePtr mGlxInterface; XcbGlInterfacePtr mGlInterface;
XcbEventInterfacePtr mXcbEventInterface {nullptr}; XcbEventInterfacePtr mEventInterface;
}; };

View file

@ -6,18 +6,27 @@
#include "XcbImage.h" #include "XcbImage.h"
#include "Screen.h" #include "Screen.h"
#include "ImagePrimitives.h" #include "ImagePrimitives.h"
#include "XcbGlWindowInterface.h"
#include <xcb/xcb.h> #include <xcb/xcb.h>
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), : IPlatformWindow(window),
mHandle(hwnd), mHandle(hwnd),
mConnection(connection) mConnection(connection)
{ {
if (xcbGlInterface)
{
mGlInterface = std::make_unique<XcbGlWindowInterface>(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) if (!screen)
{ {
@ -39,7 +48,7 @@ void XcbWindow::add(mt::Window* window, xcb_connection_t* connection, mt::Screen
xcb_screen->GetNativeScreen()->root_visual, /* visual */ xcb_screen->GetNativeScreen()->root_visual, /* visual */
mask, values ); /* masks */ mask, values ); /* masks */
auto xcb_window = std::make_unique<XcbWindow>(window, hwnd, connection); auto xcb_window = std::make_unique<XcbWindow>(window, hwnd, connection, xcbGlInterface);
window->SetPlatformWindow(std::move(xcb_window)); window->SetPlatformWindow(std::move(xcb_window));
} }
@ -53,7 +62,7 @@ unsigned XcbWindow::getGraphicsContext() const
return mGraphicsContext; return mGraphicsContext;
} }
void XcbWindow::show() const void XcbWindow::show()
{ {
map(); map();
} }
@ -62,18 +71,39 @@ void XcbWindow::paint(mt::Screen* screen)
{ {
auto xcb_screen = dynamic_cast<XcbScreen*>(screen->GetPlatformScreen()); auto xcb_screen = dynamic_cast<XcbScreen*>(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) if (!mBackingImage)
{ {
mBackingImage = std::make_unique<XcbImage>(mConnection, mWindow, xcb_screen->GetNativeScreen()); mBackingImage = std::make_unique<XcbImage>(mConnection, mWindow, screen->GetNativeScreen());
} }
auto backing_image = mWindow->getBackingImage(); auto backing_image = mWindow->getBackingImage();
backing_image->initialize(); backing_image->initialize();
//ImagePrimitives::drawCheckerboard(const_cast<unsigned char*>(backing_image->getDataPtr()), backing_image->getWidth(), backing_image->getHeight(), 0); //ImagePrimitives::drawCheckerboard(const_cast<unsigned char*>(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()) 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_clear_area(mConnection, 1, mHandle, 0, 0, mWindow->GetWidth(), mWindow->GetHeight());
xcb_flush(mConnection); xcb_flush(mConnection);
} }
void XcbWindow::map() const void XcbWindow::map()
{ {
xcb_map_window(mConnection, mHandle); xcb_map_window(mConnection, mHandle);
xcb_flush(mConnection); xcb_flush(mConnection);

View file

@ -3,6 +3,9 @@
#include "IPlatformWindow.h" #include "IPlatformWindow.h"
class XcbImage; class XcbImage;
class XcbScreen;
class XcbGlWindowInterface;
class XcbGlInterface;
struct xcb_connection_t; struct xcb_connection_t;
namespace mt namespace mt
@ -13,27 +16,31 @@ namespace mt
class XcbWindow : public IPlatformWindow class XcbWindow : public IPlatformWindow
{ {
public: public:
XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection); XcbWindow(mt::Window* window, int hwnd, xcb_connection_t* connection, XcbGlInterface* xcbGlInterface);
virtual ~XcbWindow() = default; 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; int getHandle() const;
unsigned getGraphicsContext() const; unsigned getGraphicsContext() const;
void show() const override; void show() override;
void paint(mt::Screen* screen) override; void paint(mt::Screen* screen) override;
void clear() const override; void clear() override;
void map() const override; void map() override;
private: private:
void paintHardware(XcbScreen* screen);
void paintSoftware(XcbScreen* screen);
int mHandle{-1}; int mHandle{-1};
unsigned mGraphicsContext {0}; unsigned mGraphicsContext {0};
xcb_connection_t* mConnection{nullptr}; xcb_connection_t* mConnection{nullptr};
std::unique_ptr<XcbImage> mBackingImage; std::unique_ptr<XcbImage> mBackingImage;
std::unique_ptr<XcbGlWindowInterface> mGlInterface;
}; };
using XcbWindowPtr = std::unique_ptr<XcbWindow>; using XcbWindowPtr = std::unique_ptr<XcbWindow>;

View file

@ -14,8 +14,8 @@ public:
{ {
auto app = std::make_unique<GuiApplication>(); auto app = std::make_unique<GuiApplication>();
//app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11); app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11);
app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER); //app->setUiInterfaceBackend(UiInterfaceFactory::Backend::X11_RASTER);
app->run(); app->run();
return true; return true;

View file

@ -9,13 +9,13 @@ int main()
unsigned width = 200; unsigned width = 200;
unsigned height = 200; unsigned height = 200;
unsigned numChannels = 3; unsigned numChannels = 3;
auto image = Image::Create(width, height); auto image = Image<unsigned char>::Create(width, height);
image->SetNumChannels(numChannels); image->setNumChannels(numChannels);
std::vector<unsigned char> data(image->GetBytesPerRow()*height, 0); std::vector<unsigned char> data(image->getBytesPerRow()*height, 0);
for(unsigned jdx=0;jdx<height;jdx++) for(unsigned jdx=0;jdx<height;jdx++)
{ {
const auto heightOffset = jdx*image->GetBytesPerRow(); const auto heightOffset = jdx*image->getBytesPerRow();
for(unsigned idx=0;idx<width*numChannels;idx+=numChannels) for(unsigned idx=0;idx<width*numChannels;idx+=numChannels)
{ {
const auto index = heightOffset + idx; const auto index = heightOffset + idx;
@ -24,7 +24,7 @@ int main()
data[index+2] = 0; data[index+2] = 0;
} }
} }
image->SetData(data); image->setData(data);
PngWriter writer; PngWriter writer;
writer.SetPath("test.png"); writer.SetPath("test.png");