some app flow redesign

This commit is contained in:
Jack Andersen 2015-08-27 14:10:46 -10:00
parent d69e76d911
commit 12e5948d31
9 changed files with 227 additions and 237 deletions

View File

@ -27,7 +27,6 @@ else()
lib/x11/ApplicationWayland.hpp
lib/x11/WindowXCB.cpp
lib/x11/WindowWayland.cpp
lib/x11/GraphicsContextXCB.cpp
lib/x11/GraphicsContextWayland.cpp
lib/inputdev/HIDListenerUdev.cpp
lib/inputdev/HIDDeviceUdev.cpp)
@ -73,7 +72,7 @@ else()
endif()
include_directories(${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR})
list(APPEND _BOO_SYS_LIBS xcb xcb-glx xcb-xinput xcb-xkb xcb-keysyms xkbcommon xkbcommon-x11 ${DBUS_LIBRARY} udev pthread)
list(APPEND _BOO_SYS_LIBS xcb xcb-glx xcb-xinput xcb-xkb xcb-keysyms xkbcommon xkbcommon-x11 GL ${DBUS_LIBRARY} udev pthread)
endif()

View File

@ -14,9 +14,8 @@ class IApplication;
struct IApplicationCallback
{
virtual void appLaunched(IApplication* app) {(void)app;}
virtual void appQuitting(IApplication* app) {(void)app;}
virtual void appFilesOpen(IApplication* app, const std::vector<std::string>& paths) {(void)app;(void)paths;}
virtual void appQuitting(IApplication*) {}
virtual void appFilesOpen(IApplication*, const std::vector<std::string>&) {}
};
class IApplication
@ -44,8 +43,7 @@ public:
};
virtual EPlatformType getPlatformType() const=0;
virtual void run()=0;
virtual void quit()=0;
virtual void pump()=0;
virtual const std::string& getUniqueName() const=0;
virtual const std::string& getFriendlyName() const=0;
virtual const std::string& getProcessName() const=0;

View File

@ -127,6 +127,8 @@ public:
virtual bool isFullscreen() const=0;
virtual void setFullscreen(bool fs)=0;
virtual void waitForRetrace()=0;
virtual uintptr_t getPlatformHandle() const=0;
virtual void _incomingEvent(void* event) {(void)event;}

View File

@ -46,16 +46,11 @@ public:
return PLAT_WAYLAND;
}
void run()
void pump()
{
}
void quit()
{
}
const std::string& getUniqueName() const
{
return m_uniqueName;

View File

@ -10,8 +10,13 @@
#include <xkbcommon/xkbcommon-x11.h>
#include <xcb/xkb.h>
#include <xcb/xinput.h>
#include <xcb/glx.h>
#undef explicit
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <dbus/dbus.h>
DBusConnection* registerDBus(const char* appName, bool& isFirst);
@ -20,6 +25,10 @@ DBusConnection* registerDBus(const char* appName, bool& isFirst);
namespace boo
{
PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI = nullptr;
PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI = nullptr;
int XCB_GLX_EVENT_BASE = 0;
int XINPUT_OPCODE = 0;
static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent)
@ -131,7 +140,7 @@ class ApplicationXCB final : public IApplication
std::unordered_map<xcb_window_t, IWindow*> m_windows;
xcb_connection_t* m_xcbConn = NULL;
bool m_running;
int m_xcbFd, m_dbusFd, m_maxFd;
void _deletedWindow(IWindow* window)
{
@ -198,6 +207,13 @@ public:
/* Open X connection */
m_xcbConn = xcb_connect(NULL, NULL);
/* GLX extension data */
const xcb_query_extension_reply_t* glxExtData =
xcb_get_extension_data(m_xcbConn, &xcb_glx_id);
XCB_GLX_EVENT_BASE = glxExtData->first_event;
FglXGetVideoSyncSGI = PFNGLXGETVIDEOSYNCSGIPROC(glXGetProcAddress((GLubyte*)"glXGetVideoSyncSGI"));
FglXWaitVideoSyncSGI = PFNGLXWAITVIDEOSYNCSGIPROC(glXGetProcAddress((GLubyte*)"glXWaitVideoSyncSGI"));
/* The xkb extension requests that the X server does not
* send repeated keydown events when a key is held */
xkb_x11_setup_xkb_extension(m_xcbConn,
@ -212,9 +228,14 @@ public:
/* Xinput major opcode */
const xcb_query_extension_reply_t* xiReply =
xcb_get_extension_data(m_xcbConn, &xcb_input_id);
if (xiReply)
XINPUT_OPCODE = xiReply->major_opcode;
XINPUT_OPCODE = xiReply->major_opcode;
/* Get file descriptors of xcb and dbus interfaces */
m_xcbFd = xcb_get_file_descriptor(m_xcbConn);
dbus_connection_get_unix_fd(m_dbus, &m_dbusFd);
m_maxFd = MAX(m_xcbFd, m_dbusFd);
xcb_flush(m_xcbConn);
}
~ApplicationXCB()
@ -227,35 +248,23 @@ public:
return PLAT_XCB;
}
void run()
void pump()
{
if (!m_xcbConn)
return;
xcb_generic_event_t* event;
m_running = true;
m_callback.appLaunched(this);
xcb_flush(m_xcbConn);
fd_set fds;
FD_ZERO(&fds);
FD_SET(m_xcbFd, &fds);
FD_SET(m_dbusFd, &fds);
select(m_maxFd+1, &fds, NULL, NULL, NULL);
int xcbFd = xcb_get_file_descriptor(m_xcbConn);
int dbusFd;
dbus_connection_get_unix_fd(m_dbus, &dbusFd);
int maxFd = MAX(xcbFd, dbusFd);
while (m_running)
if (FD_ISSET(m_xcbFd, &fds))
{
fd_set fds;
FD_ZERO(&fds);
FD_SET(xcbFd, &fds);
FD_SET(dbusFd, &fds);
select(maxFd+1, &fds, NULL, NULL, NULL);
if (FD_ISSET(xcbFd, &fds))
event = xcb_poll_for_event(m_xcbConn);
if (event)
{
event = xcb_poll_for_event(m_xcbConn);
if (!event)
break;
bool windowEvent;
xcb_window_t evWindow = getWindowOfEvent(event, windowEvent);
//fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event));
@ -267,40 +276,33 @@ public:
}
free(event);
}
if (FD_ISSET(dbusFd, &fds))
{
DBusMessage* msg;
dbus_connection_read_write(m_dbus, 0);
while ((msg = dbus_connection_pop_message(m_dbus)))
{
/* check if the message is a signal from the correct interface and with the correct name */
if (dbus_message_is_signal(msg, "boo.signal.FileHandling", "Open"))
{
/* read the parameters */
std::vector<std::string> paths;
DBusMessageIter iter;
dbus_message_iter_init(msg, &iter);
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID)
{
const char* argVal;
dbus_message_iter_get_basic(&iter, &argVal);
paths.push_back(argVal);
dbus_message_iter_next(&iter);
}
m_callback.appFilesOpen(this, paths);
}
dbus_message_unref(msg);
}
}
}
m_callback.appQuitting(this);
}
void quit()
{
m_running = false;
if (FD_ISSET(m_dbusFd, &fds))
{
DBusMessage* msg;
dbus_connection_read_write(m_dbus, 0);
while ((msg = dbus_connection_pop_message(m_dbus)))
{
/* check if the message is a signal from the correct interface and with the correct name */
if (dbus_message_is_signal(msg, "boo.signal.FileHandling", "Open"))
{
/* read the parameters */
std::vector<std::string> paths;
DBusMessageIter iter;
dbus_message_iter_init(msg, &iter);
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID)
{
const char* argVal;
dbus_message_iter_get_basic(&iter, &argVal);
paths.push_back(argVal);
dbus_message_iter_next(&iter);
}
m_callback.appFilesOpen(this, paths);
}
dbus_message_unref(msg);
}
}
}
const std::string& getUniqueName() const

View File

@ -1,153 +0,0 @@
#include "boo/IGraphicsContext.hpp"
#include "boo/IWindow.hpp"
#include <xcb/xcb.h>
#include <xcb/glx.h>
#include <GL/glx.h>
#include <GL/glcorearb.h>
#include <stdio.h>
#include <stdlib.h>
#include <thread>
namespace boo
{
struct GraphicsContextXCB : IGraphicsContext
{
EGraphicsAPI m_api;
EPixelFormat m_pf;
IWindow* m_parentWindow;
xcb_connection_t* m_xcbConn;
xcb_glx_fbconfig_t m_fbconfig = 0;
xcb_visualid_t m_visualid = 0;
xcb_glx_window_t m_glxWindow = 0;
xcb_glx_context_t m_glxCtx = 0;
xcb_glx_context_tag_t m_glxCtxTag = 0;
std::thread* m_commandThread = NULL;
public:
IWindowCallback* m_callback;
GraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow, xcb_connection_t* conn, uint32_t& visualIdOut)
: m_api(api),
m_pf(PF_RGBA8),
m_parentWindow(parentWindow),
m_xcbConn(conn)
{
/* WTF freedesktop?? Fix this awful API and your nonexistant docs */
xcb_glx_get_fb_configs_reply_t* fbconfigs =
xcb_glx_get_fb_configs_reply(m_xcbConn, xcb_glx_get_fb_configs(m_xcbConn, 0), NULL);
struct conf_prop
{
uint32_t key;
uint32_t val;
}* props = (struct conf_prop*)xcb_glx_get_fb_configs_property_list(fbconfigs);
for (uint32_t i=0 ; i<fbconfigs->num_FB_configs ; ++i)
{
struct conf_prop* configProps = &props[fbconfigs->num_properties * i];
uint32_t fbconfId, visualId, depthSize, colorSize, doubleBuffer;
for (uint32_t j=0 ; j<fbconfigs->num_properties ; ++j)
{
struct conf_prop* prop = &configProps[j];
if (prop->key == GLX_FBCONFIG_ID)
fbconfId = prop->val;
if (prop->key == GLX_VISUAL_ID)
visualId = prop->val;
else if (prop->key == GLX_DEPTH_SIZE)
depthSize = prop->val;
else if (prop->key == GLX_BUFFER_SIZE)
colorSize = prop->val;
else if (prop->key == GLX_DOUBLEBUFFER)
doubleBuffer = prop->val;
}
/* Double-buffer only */
if (!doubleBuffer)
continue;
if (m_pf == PF_RGBA8 && colorSize >= 32)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBA8_Z24 && colorSize >= 32 && depthSize >= 24)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBAF32 && colorSize >= 128)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBAF32_Z24 && colorSize >= 128 && depthSize >= 24)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
}
free(fbconfigs);
if (!m_fbconfig)
{
fprintf(stderr, "unable to find suitable pixel format");
return;
}
visualIdOut = m_visualid;
}
~GraphicsContextXCB()
{
}
void _setCallback(IWindowCallback* cb)
{
m_callback = cb;
}
EGraphicsAPI getAPI() const
{
return m_api;
}
EPixelFormat getPixelFormat() const
{
return m_pf;
}
void setPixelFormat(EPixelFormat pf)
{
if (pf > PF_RGBAF32_Z24)
return;
m_pf = pf;
}
void initializeContext()
{
m_glxWindow = xcb_generate_id(m_xcbConn);
xcb_glx_create_window(m_xcbConn, 0, m_fbconfig,
m_parentWindow->getPlatformHandle(),
m_glxWindow, 0, NULL);
}
};
IGraphicsContext* _GraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, xcb_connection_t* conn,
uint32_t& visualIdOut)
{
return new GraphicsContextXCB(api, parentWindow, conn, visualIdOut);
}
}

View File

@ -1,8 +1,15 @@
#include "boo/IWindow.hpp"
#include "boo/IGraphicsContext.hpp"
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glxext.h>
namespace boo
{
extern PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI;
extern PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI;
IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow);
@ -74,6 +81,12 @@ struct WindowWayland : IWindow
}
void waitForRetrace()
{
unsigned int sync;
FglXWaitVideoSyncSGI(1, 0, &sync);
}
uintptr_t getPlatformHandle() const
{

View File

@ -8,6 +8,9 @@
#include <xcb/xcb_keysyms.h>
#include <xkbcommon/xkbcommon.h>
#include <xcb/xinput.h>
#include <xcb/glx.h>
#include <GL/glx.h>
#include <GL/glcorearb.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
@ -25,6 +28,10 @@
namespace boo
{
extern PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI;
extern PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI;
extern int XCB_GLX_EVENT_BASE;
extern int XINPUT_OPCODE;
static inline double fp3232val(xcb_input_fp3232_t* val)
@ -146,16 +153,141 @@ static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOu
*hOut = height;
}
IGraphicsContext* _GraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, xcb_connection_t* conn,
uint32_t& visualIdOut);
struct GraphicsContextXCB : IGraphicsContext
{
EGraphicsAPI m_api;
EPixelFormat m_pf;
IWindow* m_parentWindow;
xcb_connection_t* m_xcbConn;
xcb_glx_fbconfig_t m_fbconfig = 0;
xcb_visualid_t m_visualid = 0;
xcb_glx_window_t m_glxWindow = 0;
xcb_glx_context_t m_glxCtx = 0;
xcb_glx_context_tag_t m_glxCtxTag = 0;
public:
IWindowCallback* m_callback;
GraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow, xcb_connection_t* conn, uint32_t& visualIdOut)
: m_api(api),
m_pf(PF_RGBA8),
m_parentWindow(parentWindow),
m_xcbConn(conn)
{
/* WTF freedesktop?? Fix this awful API and your nonexistant docs */
xcb_glx_get_fb_configs_reply_t* fbconfigs =
xcb_glx_get_fb_configs_reply(m_xcbConn, xcb_glx_get_fb_configs(m_xcbConn, 0), NULL);
struct conf_prop
{
uint32_t key;
uint32_t val;
}* props = (struct conf_prop*)xcb_glx_get_fb_configs_property_list(fbconfigs);
for (uint32_t i=0 ; i<fbconfigs->num_FB_configs ; ++i)
{
struct conf_prop* configProps = &props[fbconfigs->num_properties * i];
uint32_t fbconfId, visualId, depthSize, colorSize, doubleBuffer;
for (uint32_t j=0 ; j<fbconfigs->num_properties ; ++j)
{
struct conf_prop* prop = &configProps[j];
if (prop->key == GLX_FBCONFIG_ID)
fbconfId = prop->val;
if (prop->key == GLX_VISUAL_ID)
visualId = prop->val;
else if (prop->key == GLX_DEPTH_SIZE)
depthSize = prop->val;
else if (prop->key == GLX_BUFFER_SIZE)
colorSize = prop->val;
else if (prop->key == GLX_DOUBLEBUFFER)
doubleBuffer = prop->val;
}
/* Double-buffer only */
if (!doubleBuffer)
continue;
if (m_pf == PF_RGBA8 && colorSize >= 32)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBA8_Z24 && colorSize >= 32 && depthSize >= 24)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBAF32 && colorSize >= 128)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
else if (m_pf == PF_RGBAF32_Z24 && colorSize >= 128 && depthSize >= 24)
{
m_fbconfig = fbconfId;
m_visualid = visualId;
break;
}
}
free(fbconfigs);
if (!m_fbconfig)
{
fprintf(stderr, "unable to find suitable pixel format");
return;
}
visualIdOut = m_visualid;
}
~GraphicsContextXCB()
{
}
void _setCallback(IWindowCallback* cb)
{
m_callback = cb;
}
EGraphicsAPI getAPI() const
{
return m_api;
}
EPixelFormat getPixelFormat() const
{
return m_pf;
}
void setPixelFormat(EPixelFormat pf)
{
if (pf > PF_RGBAF32_Z24)
return;
m_pf = pf;
}
void initializeContext()
{
m_glxWindow = xcb_generate_id(m_xcbConn);
xcb_glx_create_window(m_xcbConn, 0, m_fbconfig,
m_parentWindow->getPlatformHandle(),
m_glxWindow, 0, NULL);
}
};
struct WindowXCB : IWindow
{
xcb_connection_t* m_xcbConn;
xcb_window_t m_windowId;
IGraphicsContext* m_gfxCtx;
IWindowCallback* m_callback;
xcb_window_t m_windowId;
GraphicsContextXCB m_gfxCtx;
uint32_t m_visualId;
/* Last known input device id (0xffff if not yet set) */
xcb_input_device_id_t m_lastInputID = 0xffff;
@ -174,7 +306,7 @@ struct WindowXCB : IWindow
public:
WindowXCB(const std::string& title, xcb_connection_t* conn)
: m_xcbConn(conn), m_callback(NULL)
: m_xcbConn(conn), m_callback(NULL), m_gfxCtx(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, m_visualId)
{
if (!S_ATOMS)
S_ATOMS = new XCBAtoms(conn);
@ -183,14 +315,10 @@ public:
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data;
m_pixelFactor = screen->width_in_pixels / (float)screen->width_in_millimeters / REF_DPMM;
/* Construct graphics context */
uint32_t visualId;
m_gfxCtx = _GraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this, m_xcbConn, visualId);
/* Create colormap */
xcb_colormap_t colormap = xcb_generate_id(m_xcbConn);
xcb_create_colormap(m_xcbConn, XCB_COLORMAP_ALLOC_NONE,
colormap, screen->root, visualId);
colormap, screen->root, m_visualId);
/* Create window */
int x, y, w, h;
@ -208,9 +336,10 @@ public:
m_windowId = xcb_generate_id(conn);
xcb_create_window(m_xcbConn, XCB_COPY_FROM_PARENT, m_windowId, screen->root,
x, y, w, h, 10,
XCB_WINDOW_CLASS_INPUT_OUTPUT, visualId,
XCB_WINDOW_CLASS_INPUT_OUTPUT, m_visualId,
XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
valueMasks);
/* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */
xcb_generic_error_t* xiErr = NULL;
@ -233,7 +362,7 @@ public:
};
xcb_input_xi_select_events(m_xcbConn, m_windowId, 1, &masks.mask);
}
free(xiReply);
free(xiReply);
/* Register netwm extension atom for window closing */
#if 0
@ -262,7 +391,7 @@ public:
xcb_map_window(m_xcbConn, m_windowId);
xcb_flush(m_xcbConn);
m_gfxCtx->initializeContext();
m_gfxCtx.initializeContext();
}
~WindowXCB()
@ -383,6 +512,12 @@ public:
(const char*)&fsEvent);
}
void waitForRetrace()
{
unsigned int sync;
FglXWaitVideoSyncSGI(1, 0, &sync);
}
uintptr_t getPlatformHandle() const
{
return (uintptr_t)m_windowId;

View File

@ -200,7 +200,6 @@ int main(int argc, const char** argv)
std::unique_ptr<boo::IApplication> app =
ApplicationBootstrap(boo::IApplication::PLAT_AUTO,
appCb, "rwk", "RWK", argc, argv);
app->run();
printf("IM DYING!!\n");
return 0;
}