Source

pyGAP / game / src / platform / x11 / window_glx.cpp

#include "platform/x11/window_glx.h"
#include "platform/x11/display.h"

#include "common/log.h"
#include <GL/glx.h>


namespace platform {
namespace x11 {


WindowGLX::WindowGLX(Display* display):
    WindowX11(display),
    gl_context_(0)
{
    ::Display* disp = display_->get_display();

    if (disp)
    {
        int glx_major, glx_minor;
        ::glXQueryVersion(disp, &glx_major, &glx_minor);
        LOG("GLX version %d.%d\n", glx_major, glx_minor)
    }
}


WindowGLX::~WindowGLX() {
    detach_context();
    destroy_context();
    restore_cursor();
    destroy();
}


int WindowGLX::init(int width, int height, bool fullscreen) {
    // Check if fullscreen video mode is available for the given resolution
    /*if (fullscreen) {
        int mode = display_->get_video_mode(width, height);
        if (!mode) {
            printf("Failed to switch to %i x %i video mode\n", width, height);
            printf("Fall back to windowed mode\n");
            fullscreen = false;
        }
        else {
            printf("Switching to video mode %i...\n", mode);
            display_->set_video_mode(mode);
        }
    }*/

    if (create(width, height, fullscreen))
        return 1;
    remove_cursor();

    if (create_context())
        return 1;
    if (attach_context())
        return 1;
    // TODO: delete window if error

    return 0;
}


int WindowGLX::create(int width, int height, bool fullscreen) {
    ::XSetWindowAttributes attributes;
    unsigned long          value_mask;

    ::Display* display = display_->get_display();
    ::Window root_window = display_->get_root_window();

    int x(0), y(0);

    if (!display) {
        LOG("No open X display\n")
        return 1;
    }

    GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };

    visual_info_ = ::glXChooseVisual(display, 0, att);
    color_map_ = ::XCreateColormap(display, root_window, visual_info_->visual, AllocNone);

    attributes.colormap = color_map_;
    attributes.border_pixel = 0;
    attributes.event_mask = ExposureMask|KeyPressMask|KeyReleaseMask|ButtonPressMask|StructureNotifyMask|FocusChangeMask;

    if (fullscreen) {
        attributes.override_redirect = True;
        value_mask = CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect;
    }
    else {
        attributes.override_redirect = False;
        value_mask = CWBorderPixel|CWColormap|CWEventMask;
    }

    window_ = ::XCreateWindow(
        display, root_window,
        x, y, width, height, 0,
        visual_info_->depth,
        InputOutput,
        visual_info_->visual,
        value_mask,
        &attributes);

    if (window_ == 0) {
        LOG("Failed to create window\n")
        return 1;
    }

    width_ = width;
    height_ = height;

    /*
    XSizeHints size_hint;
    size_hint.flags = PMinSize|PMaxSize;
    size_hint.min_width = width;
    size_hint.min_height = height;
    size_hint.max_width = width;
    size_hint.max_height = height;

    XSetWMNormalHints(display_, window_, &size_hint);
    */

    ::XStoreName(display, window_, window_name_);
    ::XMapRaised(display, window_);

    if (fullscreen) {
        //::XMapRaised(display_, window_);
        ::XGrabKeyboard(display, window_, True, GrabModeAsync, GrabModeAsync, CurrentTime);
        ::XGrabPointer(display, window_, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window_, None, CurrentTime);
    }
    else {
        if ((wm_protocol_ = ::XInternAtom(display, "WM_PROTOCOLS", False)) == None) {
            LOG("Failed to look up WM_PROTOCOLS\n")
            return 1;
        }

        if ((wm_delete_ = ::XInternAtom(display, "WM_DELETE_WINDOW", False)) != None)
            ::XSetWMProtocols(display, window_, &wm_delete_, 1);
    }
    //::XFlush(display_);
    LOG("Window created\n")

    return 0;
}


int WindowGLX::create_context() {
    ::Display* display = display_->get_display();

    gl_context_ = ::glXCreateContext(display, visual_info_, NULL, true);
    if (!gl_context_) {
        LOG("Failed to create rendering context\n")
        return 1;
    }
    LOG("Rendering context created\n")

    if (::glXIsDirect(display, gl_context_))
       LOG("DRI enabled\n")
    else
       LOG("No DRI available\n")

    return 0;
}


int WindowGLX::attach_context() {
    ::Display* display = display_->get_display();

    if (!::glXMakeCurrent(display, window_, gl_context_)) {
        LOG("Failed to make rendering context current\n")
        return 1;
    }
    return 0;
}


void WindowGLX::display() const {
    ::Display* display = display_->get_display();

    if (window_ && gl_context_)
        ::glXSwapBuffers(display, window_);
}


void WindowGLX::detach_context() {
    ::Display* display = display_->get_display();

    ::glXMakeCurrent(display, 0, 0);
}


void WindowGLX::destroy_context()
{
    ::Display* display = display_->get_display();

    ::glXDestroyContext(display, gl_context_);
    LOG("Rendering context destroyed\n")
}


void WindowGLX::destroy() {
    ::Display* display = display_->get_display();

    if (!window_)
        return;

    ::XDestroyWindow(display, window_);
    window_ = 0;

    LOG("Window destroyed\n")
    ::XFreeColormap(display, color_map_);
}


} /* namespace x11 */ } /* namespace platform */
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.