much xcb-glx work

This commit is contained in:
Jack Andersen 2015-05-09 21:02:18 -10:00
parent a70cc2c9d1
commit a66469b991
16 changed files with 173 additions and 67 deletions

View File

@ -27,8 +27,8 @@ public:
virtual void deviceError(const char* error) {fprintf(stderr, "%s\n", error);}
/* Low-Level API */
bool sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length);
bool sendUSBInterruptTransfer(const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length);
virtual void initialCycle() {}
virtual void transferCycle() {}
virtual void finalCycle() {}

View File

@ -7,7 +7,6 @@ namespace boo
class IGraphicsContext
{
friend class CWindowCocoa;
virtual void _setPlatformWindowHandle(void* handle) {(void)handle;};
virtual void _setCallback(class IWindowCallback* cb) {(void)cb;};
public:

View File

@ -3,7 +3,7 @@ CONFIG += console
#QMAKE_CXXFLAGS -= -std=c++0x
#CONFIG += c++11
unix:QMAKE_CXXFLAGS += -std=c++11 -stdlib=libc++
unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11
unix:LIBS += -std=c++11 -stdlib=libc++ -lc++abi -lxcb -lxcb-glx -lxcb-xkb -lxcb-keysyms -lxkbcommon -lxkbcommon-x11
win32:LIBS += Setupapi.lib winusb.lib User32.lib /SUBSYSTEM:Windows

View File

@ -11,7 +11,7 @@ IWindow* _CWindowWaylandNew(const std::string& title);
class CApplicationWayland final : public IApplication
{
const IApplicationCallback& m_callback;
IApplicationCallback& m_callback;
const std::string m_friendlyName;
const std::string m_pname;
const std::vector<std::string> m_args;
@ -22,7 +22,7 @@ class CApplicationWayland final : public IApplication
}
public:
CApplicationWayland(const IApplicationCallback& callback,
CApplicationWayland(IApplicationCallback& callback,
const std::string& friendlyName,
const std::string& pname,
const std::vector<std::string>& args)

View File

@ -6,6 +6,7 @@
#define explicit explicit_c
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xkbcommon/xkbcommon-x11.h>
#include <xcb/xkb.h>
#undef explicit
@ -15,7 +16,7 @@ namespace boo
static xcb_window_t getWindowOfEvent(xcb_generic_event_t* event, bool& windowEvent)
{
switch (event->response_type & ~0x80)
switch (XCB_EVENT_RESPONSE_TYPE(event))
{
case XCB_EXPOSE:
{
@ -69,7 +70,7 @@ IWindow* _CWindowXCBNew(const std::string& title, xcb_connection_t* conn);
class CApplicationXCB final : public IApplication
{
const IApplicationCallback& m_callback;
IApplicationCallback& m_callback;
const std::string m_friendlyName;
const std::string m_pname;
const std::vector<std::string> m_args;
@ -86,7 +87,7 @@ class CApplicationXCB final : public IApplication
}
public:
CApplicationXCB(const IApplicationCallback& callback,
CApplicationXCB(IApplicationCallback& callback,
const std::string& friendlyName,
const std::string& pname,
const std::vector<std::string>& args)
@ -97,7 +98,7 @@ public:
{
m_xcbConn = xcb_connect(NULL, NULL);
/* The convoluted xkb extension requests that the X server does not
/* This convoluted 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,
XKB_X11_MIN_MAJOR_XKB_VERSION,
@ -122,17 +123,22 @@ public:
void run()
{
xcb_generic_event_t* event;
m_running = true;
m_callback.appLaunched(this);
while (m_running && (event = xcb_wait_for_event(m_xcbConn)))
{
bool windowEvent;
xcb_window_t evWindow = getWindowOfEvent(event, windowEvent);
fprintf(stderr, "EVENT %d\n", XCB_EVENT_RESPONSE_TYPE(event));
if (windowEvent)
{
IWindow* window = m_windows[evWindow];
if (window)
window->_incomingEvent(event);
}
free(event);
}
m_callback.appQuitting(this);
}
void quit()

View File

@ -33,17 +33,17 @@ void CDeviceBase::closeDevice()
m_token->_deviceClose();
}
bool CDeviceBase::sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool CDeviceBase::sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_hidDev)
return m_hidDev->_sendUSBInterruptTransfer(pipe, data, length);
return m_hidDev->_sendUSBInterruptTransfer(data, length);
return false;
}
size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_hidDev)
return m_hidDev->_receiveUSBInterruptTransfer(pipe, data, length);
return m_hidDev->_receiveUSBInterruptTransfer(data, length);
return false;
}

View File

@ -59,13 +59,13 @@ parseState(SDolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
void CDolphinSmashAdapter::initialCycle()
{
uint8_t handshakePayload[] = {0x13};
sendUSBInterruptTransfer(0, handshakePayload, sizeof(handshakePayload));
sendUSBInterruptTransfer(handshakePayload, sizeof(handshakePayload));
}
void CDolphinSmashAdapter::transferCycle()
{
uint8_t payload[37];
size_t recvSz = receiveUSBInterruptTransfer(0, payload, sizeof(payload));
size_t recvSz = receiveUSBInterruptTransfer(payload, sizeof(payload));
if (recvSz != 37 || payload[0] != 0x21)
return;
//printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
@ -108,7 +108,7 @@ void CDolphinSmashAdapter::transferCycle()
else
rumbleMessage[i+1] = 0;
}
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage));
m_rumbleState = rumbleReq;
}
}
@ -116,7 +116,7 @@ void CDolphinSmashAdapter::transferCycle()
void CDolphinSmashAdapter::finalCycle()
{
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
sendUSBInterruptTransfer(rumbleMessage, sizeof(rumbleMessage));
}
void CDolphinSmashAdapter::deviceDisconnected()

View File

@ -24,7 +24,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
std::condition_variable m_initCond;
std::thread* m_thread;
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_usbIntf)
{
@ -34,7 +34,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_usbIntf)
{

View File

@ -38,7 +38,7 @@ class CHIDDeviceUdev final : public IHIDDevice
std::condition_variable m_initCond;
std::thread* m_thread;
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_devFd)
{
@ -57,7 +57,7 @@ class CHIDDeviceUdev final : public IHIDDevice
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_devFd)
{
@ -93,22 +93,22 @@ class CHIDDeviceUdev final : public IHIDDevice
udev_device_unref(udevDev);
return;
}
usb_device_descriptor devDesc = {0};
usb_device_descriptor devDesc = {};
read(device->m_devFd, &devDesc, 1);
read(device->m_devFd, &devDesc.bDescriptorType, devDesc.bLength-1);
if (devDesc.bNumConfigurations)
{
usb_config_descriptor confDesc = {0};
usb_config_descriptor confDesc = {};
read(device->m_devFd, &confDesc, 1);
read(device->m_devFd, &confDesc.bDescriptorType, confDesc.bLength-1);
if (confDesc.bNumInterfaces)
{
usb_interface_descriptor intfDesc = {0};
usb_interface_descriptor intfDesc = {};
read(device->m_devFd, &intfDesc, 1);
read(device->m_devFd, &intfDesc.bDescriptorType, intfDesc.bLength-1);
for (i=0 ; i<intfDesc.bNumEndpoints+1 ; ++i)
{
usb_endpoint_descriptor endpDesc = {0};
usb_endpoint_descriptor endpDesc = {};
read(device->m_devFd, &endpDesc, 1);
read(device->m_devFd, &endpDesc.bDescriptorType, endpDesc.bLength-1);
if ((endpDesc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
@ -193,6 +193,8 @@ class CHIDDeviceUdev final : public IHIDDevice
bool _sendHIDReport(const uint8_t* data, size_t length)
{
(void)data;
(void)length;
return false;
}

View File

@ -33,7 +33,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice
std::condition_variable m_initCond;
std::thread* m_thread;
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)
{
if (m_usbHandle)
{
@ -47,7 +47,7 @@ class CHIDDeviceWinUSB final : public IHIDDevice
return false;
}
size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)
{
if (m_usbHandle)
{

View File

@ -10,8 +10,8 @@ class IHIDDevice
{
friend class CDeviceBase;
virtual void _deviceDisconnected()=0;
virtual bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)=0;
virtual size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)=0;
virtual bool _sendUSBInterruptTransfer(const uint8_t* data, size_t length)=0;
virtual size_t _receiveUSBInterruptTransfer(uint8_t* data, size_t length)=0;
virtual bool _sendHIDReport(const uint8_t* data, size_t length)=0;
public:
inline virtual ~IHIDDevice() {}

View File

@ -47,10 +47,6 @@ public:
m_pf = pf;
}
void setPlatformWindowHandle(void* handle)
{
}
void initializeContext()
{
@ -58,7 +54,7 @@ public:
IGraphicsContext* makeShareContext() const
{
return NULL;
}
void makeCurrent()
@ -81,7 +77,7 @@ public:
IGraphicsContext* _CGraphicsContextWaylandNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow)
{
return new CGraphicsContextWayland(api, parentWindow);
}
}

View File

@ -47,10 +47,6 @@ public:
m_pf = pf;
}
void setPlatformWindowHandle(void* handle)
{
}
void initializeContext()
{

View File

@ -1,6 +1,13 @@
#include "windowsys/IGraphicsContext.hpp"
#include "windowsys/IWindow.hpp"
#include <xcb/xcb.h>
#include <xcb/glx.h>
#include <GL/glx.h>
#include <GL/glcorearb.h>
#include <stdio.h>
#include <stdlib.h>
namespace boo
{
@ -10,15 +17,90 @@ class CGraphicsContextXCB final : public 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;
CGraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow)
CGraphicsContextXCB(EGraphicsAPI api, IWindow* parentWindow, xcb_connection_t* conn, uint32_t& visualIdOut)
: m_api(api),
m_pf(PF_RGBA8),
m_parentWindow(parentWindow)
{}
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)
{
throw std::runtime_error("unable to find suitable pixel format");
return;
}
visualIdOut = m_visualid;
}
~CGraphicsContextXCB()
{
@ -47,41 +129,46 @@ public:
m_pf = pf;
}
void setPlatformWindowHandle(void* handle)
{
}
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* makeShareContext() const
{
return NULL;
}
void makeCurrent()
{
xcb_glx_make_context_current_reply_t* reply =
xcb_glx_make_context_current_reply(m_xcbConn,
xcb_glx_make_context_current(m_xcbConn, 0, m_glxWindow, m_glxWindow, m_glxCtx), NULL);
m_glxCtxTag = reply->context_tag;
free(reply);
}
void clearCurrent()
{
xcb_glx_make_context_current(m_xcbConn, m_glxCtxTag, m_glxWindow, m_glxWindow, 0);
m_glxCtxTag = 0;
}
void swapBuffer()
{
xcb_glx_swap_buffers(m_xcbConn, m_glxCtxTag, m_glxWindow);
}
};
IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow)
IWindow* parentWindow, xcb_connection_t* conn,
uint32_t& visualIdOut)
{
return new CGraphicsContextXCB(api, parentWindow, conn, visualIdOut);
}
}

View File

@ -31,7 +31,6 @@ public:
{
m_nsWindow = [[CWindowCocoaInternal alloc] initWithBooWindow:this title:title];
m_gfxCtx = _CGraphicsContextCocoaNew(IGraphicsContext::API_OPENGL_3_3, this);
m_gfxCtx->_setPlatformWindowHandle(m_nsWindow);
m_gfxCtx->initializeContext();
}

View File

@ -3,6 +3,7 @@
#include "IApplication.hpp"
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/xproto.h>
#include <xcb/xcb_keysyms.h>
#include <xkbcommon/xkbcommon.h>
@ -99,6 +100,7 @@ do {\
xcb_intern_atom_reply_t* reply = \
xcb_intern_atom_reply(conn, cookie, NULL); \
var = reply->atom; \
free(reply); \
} while(0)
struct SXCBAtoms
@ -107,6 +109,7 @@ struct SXCBAtoms
xcb_atom_t m_netwmStateFullscreen = 0;
xcb_atom_t m_netwmStateAdd = 0;
xcb_atom_t m_netwmStateRemove = 0;
xcb_atom_t m_
xcb_key_symbols_t* m_keySyms = NULL;
SXCBAtoms(xcb_connection_t* conn)
{
@ -130,7 +133,8 @@ static void genFrameDefault(xcb_screen_t* screen, int* xOut, int* yOut, int* wOu
}
IGraphicsContext* _CGraphicsContextXCBNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow);
IWindow* parentWindow, xcb_connection_t* conn,
uint32_t& visualIdOut);
class CWindowXCB final : public IWindow
{
@ -151,12 +155,21 @@ public:
{
if (!S_ATOMS)
S_ATOMS = new SXCBAtoms(conn);
m_windowId = xcb_generate_id(conn);
/* Default screen */
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 = _CGraphicsContextXCBNew(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);
/* Create window */
int x, y, w, h;
genFrameDefault(screen, &x, &y, &w, &h);
@ -166,10 +179,16 @@ public:
XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_STRUCTURE_NOTIFY
XCB_EVENT_MASK_STRUCTURE_NOTIFY | 0xFFFFFF,
colormap,
XCB_NONE
};
xcb_create_window(m_xcbConn, 0, m_windowId, 0, x, y, w, h, 10, 0, screen->root_visual,
XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK, valueMasks);
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_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP,
valueMasks);
/* Set the title of the window */
const char* c_title = title.c_str();
@ -182,8 +201,9 @@ public:
XCB_ATOM_WM_ICON_NAME, XCB_ATOM_STRING, 8,
strlen(c_title), c_title);
/* Construct graphics context */
m_gfxCtx = _CGraphicsContextXCBNew(IGraphicsContext::API_OPENGL_3_3, this);
/* Initialize context */
xcb_map_window(m_xcbConn, m_windowId);
m_gfxCtx->initializeContext();
}
@ -274,9 +294,9 @@ public:
xcb_get_property_reply(m_xcbConn, cookie, NULL);
char* props = (char*)xcb_get_property_value(reply);
char fullscreen = false;
for (int i ; i<reply->length/4 ; ++i)
for (unsigned i=0 ; i<reply->length/4 ; ++i)
{
if (props[i] == S_ATOMS->m_netwmStateFullscreen)
if ((xcb_atom_t)props[i] == S_ATOMS->m_netwmStateFullscreen)
{
fullscreen = true;
break;
@ -294,7 +314,8 @@ public:
32,
0,
m_windowId,
S_ATOMS->m_netwmState
S_ATOMS->m_netwmState,
{}
};
fsEvent.data.data32[0] = fs ? S_ATOMS->m_netwmStateAdd : S_ATOMS->m_netwmStateRemove;
fsEvent.data.data32[1] = S_ATOMS->m_netwmStateFullscreen;
@ -313,7 +334,7 @@ public:
void _incomingEvent(void* e)
{
xcb_generic_event_t* event = (xcb_generic_event_t*)e;
switch (event->response_type & ~0x80)
switch (XCB_EVENT_RESPONSE_TYPE(event))
{
case XCB_EXPOSE:
{