Gtk/gtkmm glarea 队列渲染不适用于专用图形
Posted
技术标签:
【中文标题】Gtk/gtkmm glarea 队列渲染不适用于专用图形【英文标题】:Gtk/gtkmm glarea queue render doesnt work with dedicated graphics 【发布时间】:2020-08-21 06:18:54 【问题描述】:我开始使用 gtkmm 和环氧树脂处理一个 github 项目(一个逻辑门模拟器)。我有一台安装了 debian buster 和 nvidia-bumblebee 驱动程序的 optimus 笔记本电脑,一切正常,除了如果我使用 optirun 或 primusrun 启动程序,glArea->queue_render
和 glArea->queue_draw
函数似乎都不起作用。我必须调整窗口大小才能重新呈现 glArea 小部件。有时当我重新启动系统并编译程序时,它根本不会以 bumblebee 启动并输出以下错误:
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】:OpenGL 与 GTK+3 的集成很差,例如在 OS X 上,您会看到此错误,因为 OpenGL 根本没有实现。也许这对你来说是同样的情况
此外,在 gtkmm-3.18 中,当 GLArea 类派生时,一个错误(自此版本以来已修复)显示此错误。但这不是你的情况。
如果这可能对您有所帮助,我在 Lecrapouille/SimTaDyn 中有一个混合 OpenGL/GTKmm 的类似应用程序,我想这会给您同样的错误。
【讨论】:
感谢您的回答,是的,我看到 gtkmm 和 opengl 不能很好地协同工作。我在使用专用图形时也遇到了鼠标事件的问题,我认为这些事件函数有一些执行时间限制 bcs 如果我写一个更长的程序开始以意想不到的方式工作。可能会迁移到 IamGUI 或 QT。以上是关于Gtk/gtkmm glarea 队列渲染不适用于专用图形的主要内容,如果未能解决你的问题,请参考以下文章