c++ - 从 SFML 提供的 X11 句柄创建 Irrlicht 设备。运行时 X11/OpenGL 错误

标签 c++ opengl x11 sfml irrlicht

我想使用 Irrlicht 渲染到由 SFML 创建的窗口中

sf::WindowHandle sf::Window::getSystemHandle() const当然要返回sf::WindowHandle ,这是一个类型定义。在 Windows 上它是 HWND__* , 在 Linux 上是 unsigned long (这可能是 X11 Windows ID),在任何其他平台上都是 void* .在 Irrlicht 文档中,他们说我应该在 Windows 上传递 HWND,但其他系统没有别的。

Irrlicht 允许创建它的主要对象 irr::IrrlichtDevice使用外部窗口的专门方法。它需要一个 struct irr::SIrrlichtCreationParameters .其中一个结构变量是 void* WindowId

所以我想做的是使用 SFML 创建一个窗口(然后使用所有 SFML 函数来轮询事件等)并使 Irrlicht 在此窗口内呈现。

核心代码:

sf::VideoMode desktop = sf::VideoMode::getDesktopMode();
sf::ContextSettings settings;
settings.antialiasingLevel = 8;
settings.depthBits = 16;
settings.stencilBits = 0;

//my own Logger class
logger.AddLog("Requesting following settings:\n");
logger.AddLog(settings);

window = std::make_shared<sf::RenderWindow>(
    sf::VideoMode(WINDOW_SIZE_X, WINDOW_SIZE_Y, desktop.bitsPerPixel),
    sf::String("Irrlicht + SFML test"),
    sf::Style::Default,
    settings);

logger.AddLog("Created SFML Window with following settings:\n");
logger.AddLog(window->getSettings());

irr::SIrrlichtCreationParameters params;
params.AntiAlias = 8;
params.Bits = 16;
params.DeviceType = irr::EIDT_BEST;
params.DriverType = irr::video::EDT_OPENGL;
params.Doublebuffer = true;
params.EventReceiver = nullptr;
params.Fullscreen = false;
params.HandleSRGB = false;
params.IgnoreInput = true;
params.Stencilbuffer = false;
params.UsePerformanceTimer = false;
params.Vsync = false;
params.WithAlphaChannel = false;
params.ZBufferBits = 24;
params.LoggingLevel = irr::ELL_DEBUG;
params.WindowId = GetWindowHandle(window->getSystemHandle()); // Described below

device.reset(irr::createDeviceEx(params)); // device is std::unique_ptr
if(device == nullptr)
    std::cout << "Can't create device!\n";

我的功能描述 SFML 的 getSystemHandle 在 Linux 上返回 unsigned long,如果我理解正确的话,它是 X11 widnow ID。 我的函数 GetWindowHandle 接受 sf::WindowHandle 并返回 void* 对于 Linux,它是:return reinterpret_cast< void* >(handle);这似乎是正确的方法,我尝试过的任何其他方法都会产生 X11 错误 BadWindowId

程序在设备创建后停止执行并且没有到达if(device == nullptr)堵塞。我的程序终止并返回 1。

我在控制台中遇到的错误:(“Irrlicht Engine”之前的所有输出都由我的记录器对象完成)

[2017.01.28 13:15:51]
Starting Application
Requesting following settings:
OpenGL context        : 1.1
flags                 : 0
antialiasing level    : 8
bits of depth   buffer: 16
bits of stencil buffer: 0
Created SFML Window with following settings:
OpenGL context        : 4.5
flags                 : 0
antialiasing level    : 8
bits of depth   buffer: 24
bits of stencil buffer: 0
Irrlicht Engine version 1.8.4
Linux 4.4.0-59-generic #80-Ubuntu SMP Fri Jan 6 17:47:47 UTC 2017 x86_64
X Error of failed request:  BadAlloc (insufficient resources for operation)
  Major opcode of failed request:  154 (GLX)
  Minor opcode of failed request:  31 (X_GLXCreateWindow)
  Serial number of failed request:  26
  Current serial number in output stream:  27

什么会导致这样的错误?

编辑 试过 sf::Window .也不行。我犯了同样的错误。根据 SFML 文档,此类还创建了自己的上下文。 我可能不得不放弃组合这 2 个库,只将 SFML 用于音频,并且只使用 Irrlicht 进行渲染。

最佳答案

简单:SFML 已经配置了窗口并在其上创建了 OpenGL 上下文。然后将该窗口传递给 Irrlicht,Irrlicht 尝试(再次)为其目的配置该窗口但失败了,因为它已经被配置过了。从技术上讲,创建额外的 OpenGL 上下文是完全可能的,但是创建一个 GLX 窗口作为另一个 GLX 窗口的子窗口(GLX 窗口是常规 X11 窗口的特化)会导致问题。

您的解决方案是修补 SFML,使其不执行“花哨的”OpenGL 窗口配置和上下文创建,这也意味着它返回普通的 X11 窗口,而没有通常在其中为 OpenGL 创建的 GLX 窗口(长故事为什么这样做,主要与直接渲染问题有关)。

也就是说,将 Irrlicht 嵌入到宿主程序提供的窗口中是为了支持 map 编辑器或类似的预览应用程序。

关于c++ - 从 SFML 提供的 X11 句柄创建 Irrlicht 设备。运行时 X11/OpenGL 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41910825/

相关文章:

c++ - Oracle OCCI 'select count(*)' 结果获取

c++ - 在处理时写入数据 block - 由于硬件限制是否存在收敛值?

c++ - 是什么导致我的光线追踪器中出现伪影?

r - CentOS 4中R渲染基础图形的问题

x11 - 令人困惑的_NET_SUPPORTING_WM_CHECK

c++ - boolean 变量按位非

c++ - 在构造之前引用变量是否定义良好

c++ - 在 Windows 上创建并行离屏 OpenGL 上下文

opengl - 逼真的贴花

linux - x11 - 在不移动指针的情况下发送鼠标点击