mirror of https://github.com/AxioDL/boo.git
154 lines
4.2 KiB
C++
154 lines
4.2 KiB
C++
#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);
|
|
}
|
|
|
|
}
|