Есть ли способ запустить команду opengl в потоке, отличном от потока пользовательского интерфейса gtk? - PullRequest
2 голосов
/ 11 июля 2019

Я работаю над проектом, требующим создания конвейера и выполнения вызовов gtk glarea из другого потока.

Я использую эпоксидную смолу в качестве загрузчика gl. Я также использую сборку mtw gtk + в системе Windows. Использование примера кода треугольника, создание конвейера и рендеринг с использованием сигналов realize и render glarea. Но любой вызов gl в другом потоке вызовет сбой приложения.

Вот логика рендеринга и потока. Я все еще настраиваю конвейер, используя сигнал realize, но рендеринг выполняется в другом потоке.

класс окна

#include "window.h"
#include <thread>
#include <chrono>

namespace M
{

Window::Window()
{
    set_border_width(6);
    set_default_size(640, 480);

    _box.set_spacing(6);
    add(_box);

    _box.pack_end(ngl, Gtk::PACK_EXPAND_WIDGET); // ngl : the GLArea variable

    show_all();

    thread = std::thread( [this] { render(); } );
}

void Window::render()
{
    using namespace std::chrono_literals;
    std::this_thread::sleep_for(5s);

    ngl.renderTri();
}

}

GLArea класс

#include "glarea.h"

namespace M
{

GLArea::GLArea()
    : _points(0),
      _colors(0),
      _matrix(0),
      _isButton3Pressed(false),
      _isKeyWPressed(false),
      _isKeyAPressed(false),
      _isKeySPressed(false),
      _isKeyDPressed(false)
{
    set_has_window(false);

    // It is important to explicitely allow events on the GLArea!
    _glArea.add_events(Gdk::POINTER_MOTION_MASK
            | Gdk::BUTTON_PRESS_MASK
            | Gdk::BUTTON_RELEASE_MASK
            | Gdk::KEY_PRESS_MASK
            | Gdk::KEY_RELEASE_MASK);

    pack_end(_glArea, Gtk::PACK_EXPAND_WIDGET);

    _glArea.signal_realize().connect(
            sigc::mem_fun(*this, &GLArea::realize));
    // It is important that the unrealize signal calls our handler to clean up
    // GL resources *before* the default unrealize handler is called, hence the
    // "false".
    _glArea.signal_unrealize().connect(
            sigc::mem_fun(*this, &GLArea::unrealize), false);
    /*_glArea.signal_render().connect(
            sigc::mem_fun(*this, &GLArea::render));*/

    _glArea.signal_key_press_event().connect(
            sigc::mem_fun(*this, &GLArea::on_key_press_event), false);
    _glArea.signal_key_release_event().connect(
            sigc::mem_fun(*this, &GLArea::on_key_release_event), false);

    // Grab the focus to get all key events no matter what!
    _glArea.set_can_focus(true);
    _glArea.grab_focus();

    show_all();
}

GLArea::~GLArea()
{
}

void GLArea::renderTri()
{
    while(true)
    {
        GLArea::render();
        _glArea.queue_draw();
    }
}

bool GLArea::render()
{
    try {

    _glArea.make_current();
        _glArea.throw_if_error();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        //draw();
        if(_isKeyWPressed) {
            _matrix[13] += 0.01;
        }
        if(_isKeyAPressed) {
            _matrix[12] -= 0.01;
        }
        if(_isKeySPressed) {
            _matrix[13] -= 0.01;
        }
        if(_isKeyDPressed) {
            _matrix[12] += 0.01;
        }

        glUniformMatrix4fv(_matrixLocation, 1, GL_FALSE, _matrix);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        return true;
    } catch(const Gdk::GLError &error) {
        std::cerr
            << error_string()
            << "Something went wrong in the render callback\n\t"
            << "\n\tDomain: " << error.domain()
            << "\n\tCode: " << error.code()
            << "\n\tWhat: " << error.what()
            << std::endl;
        return false;
    }
}
}

полный оригинальный образец можно найти здесь. https://github.com/mschwan/glarea-animation

Я ожидаю, что будет показан треугольник или, если будут какие-либо ошибки или предупреждения gl, он будет напечатан, но я получаю ошибку сегментации. [Информация] Реализация GL контекста Intel® HD Graphics 4400 3.2.0 - сборка 20.19.15.4963 Ошибка сегментации

...