Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无头QT4 OpenGL应用程序_C++_Qt_Opengl - Fatal编程技术网

C++ 无头QT4 OpenGL应用程序

C++ 无头QT4 OpenGL应用程序,c++,qt,opengl,C++,Qt,Opengl,我正在QT4中创建一个headless控制台应用程序,该应用程序执行一些OpenGL渲染,然后通过websocket将结果通过网络发送出去。我已经运行了所有的渲染和网络代码(假设我有一个GUI),但是我在转换到无头应用程序时遇到了一些问题。是否可以在没有窗口的情况下创建QGLContext 在网上阅读的机会不多,但根据我收集的信息,你可以创建一个QGLPixelBuffer,它是一个有效的QPaintDevice。它似乎创建了自己的专用QGLContext,用于硬件加速绘图。这个路由的问题是,我

我正在QT4中创建一个headless控制台应用程序,该应用程序执行一些OpenGL渲染,然后通过websocket将结果通过网络发送出去。我已经运行了所有的渲染和网络代码(假设我有一个GUI),但是我在转换到无头应用程序时遇到了一些问题。是否可以在没有窗口的情况下创建QGLContext

在网上阅读的机会不多,但根据我收集的信息,你可以创建一个QGLPixelBuffer,它是一个有效的QPaintDevice。它似乎创建了自己的专用QGLContext,用于硬件加速绘图。这个路由的问题是,我需要访问它的底层QGLContext,这样我就可以与另一个线程(用于从渲染场景中快速DMA纹理传输的网络线程)共享它。下面是一个小型原型。有什么想法吗

应用程序.h

/**
@file
@author     Nikolaus Karpinsky
*/

#ifndef _APPLICATION_H_
#define _APPLICATION_H_

#include <QCoreApplication>
#include <QTimer>

#include "MainController.h"

#endif  // _APPLICATION_H_
主控制器

/**
 @file
 @author        Nikolaus Karpinsky
 */

#ifndef _MAIN_CONTROLLER_H_
#define _MAIN_CONTROLLER_H_

#include <QObject>
#include <QGLWidget>
#include <QGLPixelBuffer>
#include <QGLFramebufferObject>
#include <memory>

using namespace std;

class MainController : public QObject
{
  Q_OBJECT

private:
  unqiue_ptr<QGLPixelBuffer> m_mainBuffer;
  //unique_ptr<QGLContext> m_mainContext;

public:
  MainController();
  void Init(void);

public slots:
  void Start(void);
  void Close(void);

signals:
  void Finished(void);
};

#endif  // _MAIN_CONTROLLER_H_
/**
@文件
@作家尼古拉斯·卡尔平斯基
*/
#ifndef\u主控制器\u H_
#定义主控制器_
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
类主控制器:公共QObject
{
Q_对象
私人:
unqiue_ptr m_main buffer;
//唯一的主上下文;
公众:
主控制器();
void Init(void);
公众时段:
作废开始(作废);
作废关闭(作废);
信号:
完成作废(作废);
};
#endif/\u主控制器\u H_
MainController.cpp

#include "MainController.h"

MainController::MainController() : QObject()
{ }

void MainController::Init(void)
{
  m_mainBuffer = unique_ptr<QGLPixelBuffer>(new QGLPixelBuffer(800, 600));
  bool has      = buffer->hasOpenGLPbuffers();
  bool current  = buffer->makeCurrent();
  bool valid    = buffer->isValid();

  //  Now I need to get access to the context to share it with additional threads
  // m_mainContext = unique_ptr<QGLContext>(new QGLContext(buffer.getContext()));
}

void MainController::Start(void)
{
}

void MainController::Close(void)
{
  //  This will tell the event loop that we are done and close the app
  emit( Finished() );
}
#包括“MainController.h”
MainController::MainController():QObject()
{ }
void MainController::Init(void)
{
m_mainBuffer=unique_ptr(新的QGLPixelBuffer(800600));
bool has=buffer->hasOpenGLPbuffers();
bool current=buffer->makeCurrent();
bool valid=buffer->isValid();
//现在我需要访问上下文以与其他线程共享它
//m_mainContext=unique_ptr(新的QGLContext(buffer.getContext());
}
void主控制器::开始(void)
{
}
void主控制器::关闭(void)
{
//这将告诉事件循环我们已经完成并关闭应用程序
发射(完成的());
}
是否可以在没有窗口的情况下创建QGLContext

是的,但是有一个陷阱

在网上阅读的机会不多,但根据我收集的信息,你可以创建一个QGLPixelBuffer,它是一个有效的QPaintDevice

是的,但是那个PBuffer还需要和GPU通话。在Linux中,与GPU通信的通常方式是通过X服务器。因此,您实际上需要一台X服务器,使用GPU驱动程序,启动活动VT,以便PBuffer可以在GPU上工作

希望不久GPU将有一个新的ABI/API,它允许您在GPU上创建屏幕外渲染上下文,而无需X服务器

这个路由的问题是,我需要访问它的底层QGLContext,这样我就可以与另一个线程(用于从渲染场景中快速DMA纹理传输的网络线程)共享它


不幸的是,Qt开发人员对OpenGL的了解似乎很有限。有几件事在OpenGL中是完全可能的,并且在Qt中是不可能的,没有明显的原因。例如,您可以使用一个可绘制文件拥有任意数量的上下文。但是,您也可以通过重新绑定单个上下文来对任意数量的(兼容的)绘图表使用单个上下文。Qt和一个明显的设计缺陷都不支持这两种方法。我现在自己也在努力解决这个问题。

好的,所以经过一番尝试后,我找到了一个足够好的解决方案。目前,我正在以QApplication vs QCoreApplication的形式运行我的应用程序。从这里,我在GUI线程上创建了一个QGLWidget,然后立即在创建和初始化OpenGL上下文的小部件上调用updateGL()。假设我从未使应用程序可见,它运行“headless”,但仍然从X或Explorer获得所需的QT窗口句柄

再深入一点,我还需要在其他线程上共享QGLContext。要从QGLWidget复制上下文,我只需使用不推荐使用的构造函数创建一个QGLWidget,您可以在其中指定一个画师(QGLWidget),然后使用QGLWidgets上下文创建。我在下面贴了一个例子来说明。使用这个,我可以在一个线程中编写纹理,在另一个线程中处理,同时保持应用程序“无头”。谢谢datenwolf的帮助

shared_ptr<QGLContext> MainController::MakeSharedContext(void)
{
  shared_ptr<QGLContext> sharedContext(nullptr);

  if(nullptr != m_mainContext)
  {
    // m_mainContext is: shared_ptr<QGLWidget>
    sharedContext = shared_ptr<QGLContext>( new QGLContext(m_mainContext->format(), m_mainContext.get( ) ) );
    bool created = sharedContext->create( m_mainContext->context( ) );
    Utils::AssertOrThrowIfFalse(created, "Unable to create a shared OpenGL context" );
  }

  return sharedContext;
}
shared\ptr MainController::MakeSharedContext(无效)
{
共享内容(nullptr);
if(nullptr!=m_mainContext)
{
//m_main上下文为:共享\u ptr
sharedContext=shared_ptr(新的QGLContext(m_mainContext->format(),m_mainContext.get());
bool created=sharedContext->create(m_mainContext->context());
Utils::AssertOrThrowIfFalse(创建时,“无法创建共享OpenGL上下文”);
}
返回共享上下文;
}

Hmmm,糟糕透了。我希望重用我们已经拥有的许多使用QT的组件。我可以忍受必须运行X会话,但我需要在多个线程之间共享上下文。我有单线程屏幕外(控制台应用程序)渲染(假设我有一个X会话),但我不确定如何在两个应用程序之间共享纹理threads@Nik:基本上和我现在遇到的问题一样。我曾考虑将我自己的Qt-OpenGL基础设施整合起来,但看看问题有多严重,我想我会在Qt-dev论坛上对此大发雷霆。
shared_ptr<QGLContext> MainController::MakeSharedContext(void)
{
  shared_ptr<QGLContext> sharedContext(nullptr);

  if(nullptr != m_mainContext)
  {
    // m_mainContext is: shared_ptr<QGLWidget>
    sharedContext = shared_ptr<QGLContext>( new QGLContext(m_mainContext->format(), m_mainContext.get( ) ) );
    bool created = sharedContext->create( m_mainContext->context( ) );
    Utils::AssertOrThrowIfFalse(created, "Unable to create a shared OpenGL context" );
  }

  return sharedContext;
}