summaryrefslogtreecommitdiff
path: root/modules/window-opengl/gl_xcb.cpp
diff options
context:
space:
mode:
authorClaudius "keldu" Holeksa <mail@keldu.de>2023-12-04 12:18:14 +0100
committerClaudius "keldu" Holeksa <mail@keldu.de>2023-12-04 12:18:14 +0100
commita14896f9ed209dd3f9597722e5a5697bd7dbf531 (patch)
tree089ca5cbbd206d1921f8f6b53292f5bc1902ca5c /modules/window-opengl/gl_xcb.cpp
parent84ecdcbca9e55b1f57fbb832e12ff4fdbb86e7c9 (diff)
meta: Renamed folder containing source
Diffstat (limited to 'modules/window-opengl/gl_xcb.cpp')
-rw-r--r--modules/window-opengl/gl_xcb.cpp269
1 files changed, 269 insertions, 0 deletions
diff --git a/modules/window-opengl/gl_xcb.cpp b/modules/window-opengl/gl_xcb.cpp
new file mode 100644
index 0000000..5ea03f3
--- /dev/null
+++ b/modules/window-opengl/gl_xcb.cpp
@@ -0,0 +1,269 @@
+#include "gl_xcb.h"
+
+#include <cassert>
+#include <cstdint>
+#include <set>
+
+namespace saw {
+namespace gfx {
+namespace {
+glx_library_extensions load_glx_library_extensions(const char* extension_string){
+ std::string_view extensions_view{extension_string};
+
+ std::set<std::string_view> extensions;
+
+ for(;;){
+ size_t n = extensions_view.find_first_of(' ');
+ if( n != extensions_view.npos && n < extensions_view.size()){
+ std::string_view sub_glx_ext = extensions_view.substr(0,n);
+ extensions.insert(sub_glx_ext);
+ extensions_view.remove_prefix(n+1);
+ } else {
+ break;
+ }
+ }
+
+ auto find = extensions.find("GLX_ARB_create_context");
+ GLXContext (*glXCreateContextAttribsARB)(Display*, GLXFBConfig, GLXContext, Bool, const int*) = nullptr;
+ if(find != extensions.end()){
+ glXCreateContextAttribsARB = reinterpret_cast<GLXContext(*)(
+ Display*, GLXFBConfig, GLXContext, Bool, const int*)>(
+ glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB")));
+ }
+
+ return {extensions_view, glXCreateContextAttribsARB};
+}
+
+int translate_render_type_settings(gl_settings::render_type cmp){
+ switch(cmp){
+ case gl_settings::render_type::rgba:
+ return GLX_RGBA_BIT;
+ }
+ return 0;
+}
+
+int translate_drawable_type_settings(gl_settings::drawable_type cmp){
+ int i = 0;
+ if (static_cast<int32_t>(cmp) &
+ static_cast<int32_t>(gl_settings::drawable_type::window_bit)) {
+ i |= static_cast<int32_t>(GLX_WINDOW_BIT);
+ }
+ if (static_cast<int32_t>(cmp) &
+ static_cast<int32_t>(gl_settings::drawable_type::pixmap_bit)) {
+ i |= static_cast<int32_t>(GLX_PIXMAP_BIT);
+ }
+ if (static_cast<int32_t>(cmp) &
+ static_cast<int32_t>(gl_settings::drawable_type::pbuffer_bit)) {
+ i |= static_cast<int32_t>(GLX_PBUFFER_BIT);
+ }
+ return i;
+}
+}
+
+gpu_context<backend::gl_linux_xcb>::gpu_context(const glx_library_extensions& ext_lib,
+ own<device<backend::linux_xcb>> dev, int visual_id, GLXContext context, GLXFBConfig fb_config): ext_lib_{ext_lib}, device_{std::move(dev)}, visual_id_{visual_id}, context_{context}, fb_config_{fb_config}{}
+
+gpu_context<backend::gl_linux_xcb>::~gpu_context(){
+ assert(device_);
+ assert(device_->get_xcb_display());
+
+ if(context_){
+ /// @todo Check if this context is bound and only unbind if that is the case
+ // ::glXMakeContextCurrent(device_->get_xcb_display(), None, None, nullptr);
+ ::glXDestroyContext(device_->get_xcb_display(), context_);
+ }
+ device_->flush();
+}
+
+own<gpu_window<backend::gl_linux_xcb>> gpu_context<backend::gl_linux_xcb>::create_window(const video_mode& vid_mode, std::string_view title_view){
+
+ SAW_ASSERT(device_){
+ return nullptr;
+ }
+
+ own<window<backend::linux_xcb>> win = device_->create_xcb_window(vid_mode, title_view, visual_id_);
+ if(!win){
+ return nullptr;
+ }
+
+ ::GLXWindow glx_win = glXCreateWindow(device_->get_xcb_display(), fb_config_, win->get_xcb_window_handle(), nullptr);
+ return heap<gpu_window<backend::gl_linux_xcb>>(std::move(win), *this, glx_win);
+}
+
+void gpu_context<backend::gl_linux_xcb>::flush(){
+ assert(device_);
+ if(device_){
+ device_->flush();
+ }
+}
+
+own<gpu_context<backend::gl_linux_xcb> > create_gl_context(io_provider& prov, const gl_settings& settings){
+ auto eodev = create_xcb_device(prov);
+ if(eodev.is_error()){
+ return nullptr;
+ }
+ own<device<backend::linux_xcb>>& device = eodev.get_value();
+ if (!device) {
+ return nullptr;
+ }
+
+ /*
+ * Translate all attributes
+ */
+ std::vector<int> attributes;
+ attributes.reserve(33);
+
+ attributes.push_back(GLX_X_RENDERABLE);
+ attributes.push_back(settings.renderable ? True : False);
+
+ attributes.push_back(GLX_RENDER_TYPE);
+ attributes.push_back(translate_render_type_settings(settings.render_t));
+
+ attributes.push_back(GLX_RED_SIZE);
+ attributes.push_back(settings.red_bits);
+
+ attributes.push_back(GLX_GREEN_SIZE);
+ attributes.push_back(settings.green_bits);
+
+ attributes.push_back(GLX_BLUE_SIZE);
+ attributes.push_back(settings.blue_bits);
+
+ attributes.push_back(GLX_ALPHA_SIZE);
+ attributes.push_back(settings.alpha_bits);
+
+ attributes.push_back(GLX_DEPTH_SIZE);
+ attributes.push_back(settings.depth_bits);
+
+ attributes.push_back(GLX_STENCIL_SIZE);
+ attributes.push_back(settings.stencil_bits);
+
+ attributes.push_back(GLX_DOUBLEBUFFER);
+ attributes.push_back(settings.double_buffer ? True : False);
+
+ attributes.push_back(GLX_DRAWABLE_TYPE);
+ attributes.push_back(
+ translate_drawable_type_settings(settings.drawable_t));
+
+ attributes.push_back(GLX_X_VISUAL_TYPE);
+ attributes.push_back(GLX_TRUE_COLOR);
+
+ attributes.push_back(None);
+
+ int num_fb_configs = 0;
+
+ glx_library_extensions lib_ext = load_glx_library_extensions(
+ glXQueryExtensionsString(device->get_xcb_display(), device->get_xcb_screen()));
+
+ GLXFBConfig *fb_configs = glXChooseFBConfig(
+ device->get_xcb_display(), device->get_xcb_screen(), &attributes[0], &num_fb_configs);
+ if (!fb_configs || num_fb_configs == 0) {
+ /// @todo log errors
+ return nullptr;
+ }
+
+ if (lib_ext.glXCreateContextAttribsARB) {
+ ::GLXFBConfig fb_config = fb_configs[0];
+
+ ::GLXContext context;
+
+ std::vector<int> glx_attribs;
+ glx_attribs.reserve(11);
+
+ glx_attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
+ glx_attribs.push_back(settings.gl_major);
+ glx_attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
+ glx_attribs.push_back(settings.gl_minor);
+ glx_attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
+ glx_attribs.push_back(settings.core_profile
+ ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB
+ : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB);
+ glx_attribs.push_back(None);
+
+ context = lib_ext.glXCreateContextAttribsARB(
+ device->get_xcb_display(), fb_config, NULL, True, &glx_attribs[0]);
+ ::XFree(fb_configs);
+ if (!context) {
+ return nullptr;
+ }
+
+ int visual_id = 0;
+ glXGetFBConfigAttrib(device->get_xcb_display(), fb_config, GLX_VISUAL_ID,
+ &visual_id);
+ return heap<gpu_context<backend::gl_linux_xcb>>(lib_ext, std::move(device), visual_id,
+ context, fb_config);
+ }
+
+ return nullptr;
+}
+
+gpu_window<backend::gl_linux_xcb>::gpu_window(own<window<backend::linux_xcb>> win, gpu_context<backend::gl_linux_xcb> &ctx,
+ ::GLXWindow glx_win)
+ : window_{std::move(win)}, context_{&ctx}, glx_window_handle_{glx_win} {}
+
+gpu_window<backend::gl_linux_xcb>::~gpu_window() {
+ assert(context_->device_);
+ if (context_->device_) {
+ ::glXDestroyWindow(context_->device_->get_xcb_display(), glx_window_handle_);
+ }
+}
+
+void gpu_window<backend::gl_linux_xcb>::bind() {
+ assert(window_ && context_->device_ && context_->device_->get_xcb_display());
+ if (window_) {
+ if (context_->device_ && context_->device_->get_xcb_display()) {
+ ::glXMakeContextCurrent(context_->device_->get_xcb_display(), glx_window_handle_,
+ glx_window_handle_, context_->context_);
+ }
+ }
+}
+
+void gpu_window<backend::gl_linux_xcb>::show() {
+ assert(window_);
+ if (window_) {
+ window_->show();
+ }
+}
+
+void gpu_window<backend::gl_linux_xcb>::hide() {
+ assert(window_);
+ if (window_) {
+ window_->hide();
+ }
+}
+
+void gpu_window<backend::gl_linux_xcb>::swap() {
+ assert(context_->device_);
+ assert(context_->device_->get_xcb_display());
+ if (context_->device_ && context_->device_->get_xcb_display()) {
+ ::glXSwapBuffers(context_->device_->get_xcb_display(), glx_window_handle_);
+ }
+}
+
+const video_mode &gpu_window<backend::gl_linux_xcb>::get_video_mode() const {
+ assert(window_);
+ return window_->get_video_mode();
+}
+
+const std::string_view gpu_window<backend::gl_linux_xcb>::get_title() const {
+ assert(window_);
+ if (window_) {
+ return window_->get_title();
+ }
+ // Kinky
+ return "Bad window";
+}
+
+void gpu_window<backend::gl_linux_xcb>::resize(size_t height, size_t width) {
+ assert(window_);
+ if (window_) {
+ window_->resize(height, width);
+ }
+}
+
+conveyor<data<schema::WindowEvents>> gpu_window<backend::gl_linux_xcb>::on_event() {
+ assert(window_);
+ return window_->on_event();
+}
+
+}
+}