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/ApplicationWayland.hpp
lib/x11/WindowXCB.cpp lib/x11/WindowXCB.cpp
lib/x11/WindowWayland.cpp lib/x11/WindowWayland.cpp
lib/x11/GraphicsContextXCB.cpp
lib/x11/GraphicsContextWayland.cpp lib/x11/GraphicsContextWayland.cpp
lib/inputdev/HIDListenerUdev.cpp lib/inputdev/HIDListenerUdev.cpp
lib/inputdev/HIDDeviceUdev.cpp) lib/inputdev/HIDDeviceUdev.cpp)
@ -73,7 +72,7 @@ else()
endif() endif()
include_directories(${DBUS_INCLUDE_DIR} ${DBUS_ARCH_INCLUDE_DIR}) 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() endif()

View File

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

View File

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

View File

@ -46,12 +46,7 @@ public:
return PLAT_WAYLAND; return PLAT_WAYLAND;
} }
void run() void pump()
{
}
void quit()
{ {
} }

View File

@ -10,8 +10,13 @@
#include <xkbcommon/xkbcommon-x11.h> #include <xkbcommon/xkbcommon-x11.h>
#include <xcb/xkb.h> #include <xcb/xkb.h>
#include <xcb/xinput.h> #include <xcb/xinput.h>
#include <xcb/glx.h>
#undef explicit #undef explicit
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <dbus/dbus.h> #include <dbus/dbus.h>
DBusConnection* registerDBus(const char* appName, bool& isFirst); DBusConnection* registerDBus(const char* appName, bool& isFirst);
@ -20,6 +25,10 @@ DBusConnection* registerDBus(const char* appName, bool& isFirst);
namespace boo namespace boo
{ {
PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI = nullptr;
PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI = nullptr;
int XCB_GLX_EVENT_BASE = 0;
int XINPUT_OPCODE = 0; int XINPUT_OPCODE = 0;
static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent) 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; std::unordered_map<xcb_window_t, IWindow*> m_windows;
xcb_connection_t* m_xcbConn = NULL; xcb_connection_t* m_xcbConn = NULL;
bool m_running; int m_xcbFd, m_dbusFd, m_maxFd;
void _deletedWindow(IWindow* window) void _deletedWindow(IWindow* window)
{ {
@ -198,6 +207,13 @@ public:
/* Open X connection */ /* Open X connection */
m_xcbConn = xcb_connect(NULL, NULL); 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 /* The xkb extension requests that the X server does not
* send repeated keydown events when a key is held */ * send repeated keydown events when a key is held */
xkb_x11_setup_xkb_extension(m_xcbConn, xkb_x11_setup_xkb_extension(m_xcbConn,
@ -212,9 +228,14 @@ public:
/* Xinput major opcode */ /* Xinput major opcode */
const xcb_query_extension_reply_t* xiReply = const xcb_query_extension_reply_t* xiReply =
xcb_get_extension_data(m_xcbConn, &xcb_input_id); 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() ~ApplicationXCB()
@ -227,35 +248,23 @@ public:
return PLAT_XCB; return PLAT_XCB;
} }
void run() void pump()
{ {
if (!m_xcbConn) if (!m_xcbConn)
return; return;
xcb_generic_event_t* event; xcb_generic_event_t* event;
m_running = true;
m_callback.appLaunched(this);
xcb_flush(m_xcbConn);
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)
{
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(xcbFd, &fds); FD_SET(m_xcbFd, &fds);
FD_SET(dbusFd, &fds); FD_SET(m_dbusFd, &fds);
select(maxFd+1, &fds, NULL, NULL, NULL); select(m_maxFd+1, &fds, NULL, NULL, NULL);
if (FD_ISSET(xcbFd, &fds)) if (FD_ISSET(m_xcbFd, &fds))
{ {
event = xcb_poll_for_event(m_xcbConn); event = xcb_poll_for_event(m_xcbConn);
if (!event) if (event)
break; {
bool windowEvent; bool windowEvent;
xcb_window_t evWindow = getWindowOfEvent(event, windowEvent); xcb_window_t evWindow = getWindowOfEvent(event, windowEvent);
//fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event)); //fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event));
@ -267,8 +276,9 @@ public:
} }
free(event); free(event);
} }
}
if (FD_ISSET(dbusFd, &fds)) if (FD_ISSET(m_dbusFd, &fds))
{ {
DBusMessage* msg; DBusMessage* msg;
dbus_connection_read_write(m_dbus, 0); dbus_connection_read_write(m_dbus, 0);
@ -295,14 +305,6 @@ public:
} }
} }
m_callback.appQuitting(this);
}
void quit()
{
m_running = false;
}
const std::string& getUniqueName() const const std::string& getUniqueName() const
{ {
return m_uniqueName; return m_uniqueName;

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

View File

@ -8,6 +8,9 @@
#include <xcb/xcb_keysyms.h> #include <xcb/xcb_keysyms.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include <xcb/xinput.h> #include <xcb/xinput.h>
#include <xcb/glx.h>
#include <GL/glx.h>
#include <GL/glcorearb.h>
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -25,6 +28,10 @@
namespace boo namespace boo
{ {
extern PFNGLXGETVIDEOSYNCSGIPROC FglXGetVideoSyncSGI;
extern PFNGLXWAITVIDEOSYNCSGIPROC FglXWaitVideoSyncSGI;
extern int XCB_GLX_EVENT_BASE;
extern int XINPUT_OPCODE; extern int XINPUT_OPCODE;
static inline double fp3232val(xcb_input_fp3232_t* val) 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; *hOut = height;
} }
IGraphicsContext* _GraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api, struct GraphicsContextXCB : IGraphicsContext
IWindow* parentWindow, xcb_connection_t* conn, {
uint32_t& visualIdOut); 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 struct WindowXCB : IWindow
{ {
xcb_connection_t* m_xcbConn; xcb_connection_t* m_xcbConn;
xcb_window_t m_windowId;
IGraphicsContext* m_gfxCtx;
IWindowCallback* m_callback; 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) */ /* Last known input device id (0xffff if not yet set) */
xcb_input_device_id_t m_lastInputID = 0xffff; xcb_input_device_id_t m_lastInputID = 0xffff;
@ -174,7 +306,7 @@ struct WindowXCB : IWindow
public: public:
WindowXCB(const std::string& title, xcb_connection_t* conn) 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) if (!S_ATOMS)
S_ATOMS = new XCBAtoms(conn); S_ATOMS = new XCBAtoms(conn);
@ -183,14 +315,10 @@ public:
xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(m_xcbConn)).data; 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; 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 */ /* Create colormap */
xcb_colormap_t colormap = xcb_generate_id(m_xcbConn); xcb_colormap_t colormap = xcb_generate_id(m_xcbConn);
xcb_create_colormap(m_xcbConn, XCB_COLORMAP_ALLOC_NONE, xcb_create_colormap(m_xcbConn, XCB_COLORMAP_ALLOC_NONE,
colormap, screen->root, visualId); colormap, screen->root, m_visualId);
/* Create window */ /* Create window */
int x, y, w, h; int x, y, w, h;
@ -208,10 +336,11 @@ public:
m_windowId = xcb_generate_id(conn); m_windowId = xcb_generate_id(conn);
xcb_create_window(m_xcbConn, XCB_COPY_FROM_PARENT, m_windowId, screen->root, xcb_create_window(m_xcbConn, XCB_COPY_FROM_PARENT, m_windowId, screen->root,
x, y, w, h, 10, 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, XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
valueMasks); valueMasks);
/* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */ /* The XInput 2.1 extension enables per-pixel smooth scrolling trackpads */
xcb_generic_error_t* xiErr = NULL; xcb_generic_error_t* xiErr = NULL;
xcb_input_xi_query_version_reply_t* xiReply = xcb_input_xi_query_version_reply_t* xiReply =
@ -262,7 +391,7 @@ public:
xcb_map_window(m_xcbConn, m_windowId); xcb_map_window(m_xcbConn, m_windowId);
xcb_flush(m_xcbConn); xcb_flush(m_xcbConn);
m_gfxCtx->initializeContext(); m_gfxCtx.initializeContext();
} }
~WindowXCB() ~WindowXCB()
@ -383,6 +512,12 @@ public:
(const char*)&fsEvent); (const char*)&fsEvent);
} }
void waitForRetrace()
{
unsigned int sync;
FglXWaitVideoSyncSGI(1, 0, &sync);
}
uintptr_t getPlatformHandle() const uintptr_t getPlatformHandle() const
{ {
return (uintptr_t)m_windowId; return (uintptr_t)m_windowId;

View File

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