Gtk / gtkmm glarea queue render не работает с выделенной графикой - PullRequest
1 голос
/ 06 мая 2020

Я начал работать над проектом на github (симулятор логических c ворот) с gtkmm и эпоксидной смолой. У меня есть ноутбук optimus с установленными драйверами debian buster и nvidia-bumblebee, и все работает нормально, за исключением того, что если я запускаю программу с помощью optirun или primusrun, ни функция glArea->queue_render, ни glArea->queue_draw, похоже, не работает. Мне нужно изменить размер окна, чтобы повторно отрендерить виджет glArea. Также иногда, когда я перезагружаю систему и компилирую программу, она вообще не запускается с помощью шмеля и выдает следующую ошибку:

311-0 - нет реализации gl

Это может быть что-то с моей системой, но optirun и primusrun обычно работают нормально.

Есть идеи, что может быть причиной этой проблемы?

класс средства визуализации:

#ifndef RENDERER_DATA_H
#define RENDERER_DATA_H
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec2.hpp>
struct scene{               //viewport data
    glm::mat4 proj;
    glm::mat4 view;
    glm::mat4 model;
    glm::mat4 mvp;
    float zoom = 1.0f;
    glm::vec2 dim;
    glm::vec3 pos = {0, 0, 1.0f};
};

struct pointer{             //mouse data
    int button;
    int x, y;
};

struct keyboard{            //keyboard data

};

#endif

#ifndef RENDERER_H
#define RENDERER_H
/*
 This is the renderer of the viewport
*/
#include "viewport/shader.hpp"
#include "viewport/vertexbuffer.hpp"
#include "viewport/indexbuffer.hpp"
#include "viewport/vertexarray.hpp"
#include "viewport/objects/grid.hpp"
#include <gtkmm-3.0/gtkmm.h>
#include <gtkmm-3.0/gtkmm/glarea.h>
#include <glm/glm.hpp>
//#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>
//#include <gdkmm-3.0/gdkmm/glcontext.h>
//#include <glibmm-2.4/glibmm/refptr.h>
//#include <epoxy/gl.h>
//#include <epoxy/glx.h>
#include <iostream>

class Renderer{
    public:
        Renderer(Gtk::GLArea*);                             //constructor connects the following callbacks:
        void realize();                                     //called when widget glArea is created
        void unrealize();                                   //called when widget glArea is destroyed
        void resize(int width, int height);                 //called when the glArea is resized
        bool render(const Glib::RefPtr<Gdk::GLContext>&);   //called when the viewport should render itself
        bool mouse_move(GdkEventMotion* event);             //called when both mouse button pressed and mouse moved
        bool mouse_scroll(GdkEventScroll* event);           //called when the mouse is wheel is rotated
        bool button_press(GdkEventButton* button);          //called when a button is pressed
        bool button_release(GdkEventButton* button);        //called when a button is released
    private:
        Gtk::GLArea* glArea;                                //pointer to the glArea widget, created in ui object
        GLuint vao;
        IndexBuffer* ibptr;
        VertexBuffer* vbptr;
        VertexArray* vaptr;
        VertexBufferLayout* vblptr;
        Shader* shader_program;
        Grid* grid;

        pointer mouse;                                      //mouse variable obj
        scene viewport;                                     //viewport variable obj

        void update_view();                                 //This function is resposible for paning and zooming the viewport
        glm::vec3 mouse_translate(glm::vec3);               //translates screen coords to world coords

};

#endif //

реализация:

    //#include <ui.hpp>
#include "./renderer.hpp"

Renderer::Renderer(Gtk::GLArea* glarea)
/*:glArea(glarea)*/{
    glArea = glarea;

    glArea->add_events(Gdk::BUTTON_MOTION_MASK | Gdk::BUTTON1_MOTION_MASK | Gdk::BUTTON2_MOTION_MASK | Gdk::BUTTON3_MOTION_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::SCROLL_MASK);

    glArea->signal_realize().connect(sigc::mem_fun(*this, &Renderer::realize));
    glArea->signal_unrealize().connect(sigc::mem_fun(*this, &Renderer::unrealize), false);
    glArea->signal_render().connect(sigc::mem_fun(*this, &Renderer::render), false);
    glArea->signal_resize().connect(sigc::mem_fun(*this, &Renderer::resize));
    glArea->signal_motion_notify_event().connect(sigc::mem_fun(*this, &Renderer::mouse_move));
    glArea->signal_scroll_event().connect(sigc::mem_fun(*this, &Renderer::mouse_scroll));
    glArea->signal_button_press_event().connect(sigc::mem_fun(*this, &Renderer::button_press));
    glArea->signal_button_release_event().connect(sigc::mem_fun(*this, &Renderer::button_release));
}

void Renderer::realize(){
    std::clog<<"realize"<<std::endl;
    //glArea->set_required_version(4, 5);
    glArea->make_current();
    glArea->set_auto_render(true);
    std::clog<<"make current"<<std::endl;
    //std::clog<<epoxy_gl_version()<<"\n";
    //std::clog<<epoxy_glsl_version()<<"\n";


    glArea->make_current();
    std::cout<<glGetString(GL_VERSION)<<std::endl;
    std::cout<<"realize\n";
    try{
        glArea->throw_if_error();
        std::clog<<glGetString(GL_VERSION)<<"\n";
        std::clog<<glGetString(GL_VENDOR)<<"\n";
        char path[] = "./src/res/shaders";
        shader_program = new Shader(path);
        shader_program->bind();
        //shader_program = Shader::create_shader_program(nullptr);
        //glUseProgram(shader_program);

        GLfloat pos[] = {
            -0.5f, -0.5f, -1,
            0.5f, -0.5f, -1,
            0.5f, 0.5f, -1,
            -0.5f, 0.5f, -1
        };
        GLuint ind[] = {
            0, 1, 2,
            2, 3, 0
        };


        vaptr = new VertexArray();

        //glGenVertexArrays(1, &vao);
        //glBindVertexArray(vao);

        vbptr = new VertexBuffer(pos, 4 * 3 * sizeof(GLfloat));

        vblptr = new VertexBufferLayout;
        vblptr->add(3, GL_FLOAT);
        //vblptr->add(3, GL_FLOAT);
        //vblptr->add(2, GL_FLOAT);
        vaptr->addBuffer(*vbptr, *vblptr);
        //glEnableVertexAttribArray(0);
        //glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, 0);

        ibptr = new IndexBuffer(ind, 6);
        //int location = epoxy_glGetUniformLocation(shader_program->get_program(), "u_Color");
        //glUniform4f(location, 0.2f, 0.3f, 0.8f, 1.0f);
        //glm::vec4 data = {0.2f, 0.3f, 0.8f, 1.0f};
        shader_program->set_uniform4f ("u_Color", {0.2f, 0.3f, 0.8f, 1.0f});
        //viewport.proj = glm::ortho(-width/height/2, width/height/2, -height/width/2, height/width/2);
        //shader_program->set_uniform_mat4f ("mvp", viewport.proj);
        //glBindVertexArray(0);
        //glUseProgram(0);
        //glBindBuffer(GL_ARRAY_BUFFER, 0);
        //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    }catch(const Gdk::GLError& gle){
        std::cerr << "An error occured making the context current during realize:" << std::endl;
        std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
    }
    grid = new Grid(glm::vec3(-3.0, 0.0, -1.0), glm::vec3(3.0, 0.0, -1.0));
}

void Renderer::unrealize(){
    glArea->make_current();
    delete vbptr;
    delete ibptr;
    delete vaptr;
    delete vblptr;
    delete shader_program;
    try
    {
        glArea->throw_if_error();
    }
    catch(const Gdk::GLError& gle)
    {
        std::cerr << "An error occured making the context current during unrealize" << std::endl;
        std::cerr << gle.domain() << "-" << gle.code() << "-" << gle.what() << std::endl;
    }
}

void Renderer::resize(int width, int height){
    viewport.dim.x = width;
    viewport.dim.y = height;
}

bool Renderer::render(const Glib::RefPtr<Gdk::GLContext>&  context ){
    std::clog<<"render\n";
    update_view();
    //glArea->attach_buffers();
    glClear(GL_COLOR_BUFFER_BIT);
    grid->draw();
    grid->m_shader->set_uniform_mat4f("mvp", viewport.mvp);
    grid->draw();

    shader_program->bind();

    vaptr->bind();
    //ibptr->bind();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

    glBindVertexArray(0);
    glUseProgram(0);
    return true;
}

bool Renderer::mouse_move(GdkEventMotion* event){
    glm::vec3 diff = mouse_translate(glm::vec3(mouse.x, mouse.y, 0.0)) - mouse_translate(glm::vec3(event->x, event->y, 0.0));
    std::clog<<diff.x<<" "<<diff.y<<"\n";
    if(mouse.button == 1){
        viewport.pos = viewport.pos - diff;
        std::clog<<viewport.pos .x<<" "<<viewport.pos.y<<" "<<viewport.pos.z<<"\n";
        //glArea->queue_draw();
        //glArea->queue_draw();
        glArea->queue_render();
        //glArea->signal_render();
    }
    mouse.x = event->x;
    mouse.y = event->y;
    return true;
}

bool Renderer::mouse_scroll(GdkEventScroll* event){
    if(event->direction == GDK_SCROLL_DOWN && viewport.zoom>1){
        viewport.zoom = viewport.zoom - 0.1;
    }else if(event->direction == GDK_SCROLL_UP && viewport.zoom<10){
        viewport.zoom = viewport.zoom + 0.1;
    }
    glArea->queue_render();
    std::clog<<viewport.zoom<<"\n";
    return true;
}


bool Renderer::button_press(GdkEventButton* event){
    std::clog<<event->button<<"\n";
    mouse.button = event->button;
    mouse.x = event->x;
    mouse.y = event->y;
    //if(event->mouse.button == 1){ //left mouse button
    //
    //}
    return true;
}

bool Renderer::button_release(GdkEventButton* button){
    mouse.button = 0;
    return true;
}

void Renderer::update_view(){
    std::clog<<"update view\n";
    viewport.view = glm::translate(glm::mat4(1.0f), glm::vec3(viewport.pos.x, -viewport.pos.y, -viewport.pos.z));
    viewport.model = glm::translate(glm::mat4(1.0f), glm::vec3( 0, 0, 1.0));
    if(viewport.dim.x<viewport.dim.y){
        viewport.proj =  glm::ortho(-viewport.dim.x/viewport.dim.y/viewport.zoom, viewport.dim.x/viewport.dim.y/viewport.zoom, -1.0f/viewport.zoom, 1.0f/viewport.zoom);
    }else{
        viewport.proj =  glm::ortho(-1.0f/viewport.zoom, 1.0f/viewport.zoom, -viewport.dim.y/viewport.dim.x/viewport.zoom, viewport.dim.y/viewport.dim.x/viewport.zoom);
    }
    viewport.mvp = viewport.proj * viewport.view * viewport.model;

    shader_program->bind();
    shader_program->set_uniform_mat4f ("mvp", viewport.mvp);
}

glm::vec3 Renderer::mouse_translate(glm::vec3 pos){
    return glm::unProject(pos, viewport.model, viewport.proj, glm::vec4(0.0f, 0.0f, viewport.dim.x, viewport.dim.y));
}

Полный проект на github: LinuxGameGeek / logix

1 Ответ

0 голосов
/ 19 мая 2020

OpenGL плохо интегрирован с GTK + 3, например, в OS X вы увидите эту ошибку, потому что OpenGL просто не реализован. Возможно, это тот же случай для вас

Вдобавок в gtkmm-3.18 есть ошибка (исправленная с этой версии), отображающая эту ошибку, когда класс GLArea был производным. Но это не ваш случай.

Если это может вам помочь, у меня есть аналогичное приложение, смешивающее OpenGL / GTKmm в Lecrapouille / SimTaDyn, я думаю, это даст вам ту же ошибку.

...