Create raw GL context in Qt? - c++

I am using Qt for a project. It has some QGLWidgets and these work beautifully.
The problem is, I have some legacy code I want to use that uses raw OpenGL commands to do some texture and mesh processing (render meshes to images, etc). I want to call these functions from within my Qt code, but of course that requires that I set up a fresh OpenGL context before I call the OpenGL commands.
I tried to do the following:
QGLContext context(QGLFormat::defaultFormat());
std::cout << "context creation: " << context.create() << std::endl;
if(!context.isValid())
{
std::cout << "Cannot create GL context" << std::endl;
return false;
}
context.makeCurrent();
callLegacyOpenGLCode();
but it doesn't work. QGLContext::create() is returning false. This is on Windows 7 using Qt 4.8, compiled with OpenGL support.
Is this the wrong way to ask Qt to create a new OpenGL context for me? What should I do instead?

For anybody else searching about this issue, #ratchetfreak's suggestion is a good one. The following code works correctly:
QGLWidget tmpwidget;
if(!tmpwidget.isValid())
{
std::cout << "Cannot create GL context" << std::endl;
return false;
}
tmpwidget.makeCurrent();
callLegacyOpenGLCode();

Related

Get context used by Qt/QML 5.X in WebAssembly build

Lately I've been trying to build a Qt/QML WebAssembly using Qt 5.15.2 ( compiled with -opengl es2 ) and Emscripten 1.39.7 with C++ on Windows.
This works as intended. I'm using a simple QML ApplicationWindow and it displays
just fine. From this point I assume that if QML is able to draw something, there must be
a context associated with it.
The next step for me is to grab the said context used by Qt to draw the QML Scene Graph.
I then proceed to create a simple QQuickItem of my own to test that.
From what I gathered from examples all around, I set this item handleWindowChanged signal to connect the beforeSynchronizing of the new Window in charge of the said item.
Long story short, I think I am now able to query whatever is at hand for the current context, the first thing I try is to get the the current display, context and surface like so :
EGLDisplay display = eglGetCurrentDisplay();
EGLContext context = eglGetCurrentContext();
EGLSurface surface = eglGetCurrentSurface (EGL_DRAW);
But to no avail, they all return null pointers.
I do not know much about Qt WebGL implementation, so at this point I think that perhaps I must query those by other means.
QOpenGLContext
I stumble upon QOpenGLContext which I found can be retrieved from my Window ( QQuickWindow ) for instance, so in my custom item :
QOpenGLContext* qtcontext = this->window()->openglContext();
qDebug() << "openGlModuleType : " << qtcontext->openGLModuleType();
qDebug() << "openGlModuleHandle : " << qtcontext->openGLModuleHandle();
qDebug() << "shared context openGlModuleHandle ? : " << qtcontext->shareContext()->openGLModuleHandle();
Output :
openGlModuleType : 1
openGlModuleHandle : 0x0
shared context openGlModuleHandle ? : 0x0
From this I gather that the context is of type QOpenGLContext::LibGLES ( OpenGL ES 2.0 or higher ) but can't retrieve the handle apparently either way ( own or shared one ).
QEGLNativeContext
Then, I tried another shot at QEGLNativeContext which can be made available by using the
private header ( QtPlatformHeaders/QEGLNativeContext ), only to find that nativeHandle was also returning a null value :
if(qtcontext->nativeHandle() == QVariant()) qDebug() << "null native handle";
QEGLNativeContext qteglcontext = qvariant_cast<QEGLNativeContext>(qtcontext->nativeHandle());
Emscripten
I found out that I can query the WebGL current context by Emscripten too :
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emcontext = emscripten_webgl_get_current_context();
This seems to return a non-null value, yet I found no way to retrieve the context, display or surface handle from this.
My goal here is to retrieve a valid EGLDisplay, EGLContext and EGLSurface.
I am not really familiar with WebGL, OpenGL ES, so I think I must be doing wrong calls or simply missing the point here.
Can someone share their experience on this matter ? Or point me in the right direction ?
That'd be nice.
Have a good day all.

Setting QSurfaceFormat has no effect

I am currently having issues with getting a debug context with Qt 5.8 on Windows.
I am using Qt 5.8 to write a small OpenGL application, using a viewer class declared like this
class GLViewer3DModel : public QOpenGLWidget, protected QOpenGLFunctions
{
//...
};
My main.cppfile uses this code, before QApplication is initialized:
QSurfaceFormat format;
format.setOption(QSurfaceFormat::DebugContext);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
In the 3D viewer's constructor, the QSurfaceFormat::DebugContext option seems to be properly set. However, if I test this again within my initializeGL override, the following code
void GLViewer3DModel::initializeGL()
{
initializeOpenGLFunctions();
QSurfaceFormat fmt = format();
bool hasDebug = fmt.testOption(QSurfaceFormat::DebugContext);
std::cout << "STILL DEBUG? " << hasDebug << std::endl;
}
prints "STILL DEBUG? 0", so for some reason the format has changed.
Can I do anything to make the debug context work? I would love to use QOpenGLDebugLogger to see where something might go wrong.
FWIW, the GL_KHR_debug extension is supported on my system.
Try setting a OpenGL version greater then 4.1 as I think that's when the debug was made core. The default constructed QSurfaceFormat requests GL 2.0 which doesn't support debug. See what you get then.
Also try initialising the logger and see what it spits back at you

opengl on Linux : unable to use a correct version

I tried to build a program using glfw + glew on Fedora 25.
part of it is:
int main()
{
glfwInit();
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_ANY_PROFILE);
//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
mainWindow = glfwCreateWindow(1024,768,"NONE",nullptr,nullptr);
if(mainWindow == nullptr)
{
std::cout<<"Creating window ERROR.\n"<<std::endl;
glfwTerminate();
return 1;
}
.....
}
If I use glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); to get the version 3.3, it'll be unable to create window though.
My hardware supports openGL 4.1.
upd: got the answer....
Just uncomment glfwWindowHint(GLFW_CONTEXT_VERSION_*,*) there.
While using core profile with glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE),
the explicit version needs to be requested.
Thanks to the comment of Dietrich Epp.
By the way, can anyone tell me how to get such information?

How to enumerate Bluetooth devices using Qt

I want to search bluetooth devices available and list them but the code I am following from documenation doesn't work.
BluetoothDevices::BluetoothDevices(QObject *parent) : QObject(parent)
{
}
// search Bluetooth devices
void BluetoothDevices::startDeviceDiscovery()
{
qDebug() << "Bluetooth discovery started";
// Create a discovery agent and connect to its signals
//QBluetoothDeviceDiscoveryAgent *discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(discoveryAgent, SIGNAL(deviceDiscovered(QBluetoothDeviceInfo)),
this, SLOT(deviceDiscovered(QBluetoothDeviceInfo)));
// Start a discovery
discoveryAgent->start();
}
void BluetoothDevices::deviceDiscovered(const QBluetoothDeviceInfo &device)
{
qDebug() << "Found new device:" << device.name() << '(' << device.address().toString() << ')';
}
In main window I start the search:
void MainWindow::on_pushButtonSearchBluetooth_clicked()
{
bluetoothDevices.startDeviceDiscovery();
}
I expect the deviceDiscovered() slot to get called with the device names as it gets found but this slot never gets called. I never hear anything back after initiating discovery. When I do search bluetooth devices manually from control panel, it does find couple of laptops. What else do I need to do to find them through my app?
I am using windows 7 and Qt 5.5.
I have the same problem. You can connect signal
connect(m_discoveryAgent, SIGNAL(error(QBluetoothServiceDiscoveryAgent::Error)), this, SLOT(error(QBluetoothServiceDiscoveryAgent::Error))); and you can see that slot emitted with error InvalidBluetoothAdapterError.
I try it on WIN7 and WIN10 and it not worked. In Ubuntu the same code work properly.
It seems that bluetooth not supported in windows platforms.
Currently, the API is supported on the following platforms: Android, iOS, Linux (BlueZ 4.x/5.x) and OS X.
from http://doc.qt.io/qt-5/qtbluetooth-index.html

'glCreateShader' was not declared in this scope?

Why am I getting these errors?
error: 'GL_VERTEX_SHADER' was not declared in this scope
error: 'glCreateShader' was not declared in this scope
Code:
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
And yes, I do have the includes to glut.
What does glGetString(GL_VERSION) return?
CreateShader is not in GLUT but OpenGL 2.0. If your "includes to glut" are not including gl.h for some reason or your GL version is less than 2.0, the headers will not declare it.
I'd also check your gl.h to see if CreateShader is actually declared there.
Edit: This OpenGL header version thing seems to be a general problem in Windows. Most people suggest using GLEW or another extension loader library to get around it.
You need to either use an OpenGL loading library to load OpenGL functions, or manually load the functions yourself. You can't just use gl.h and expect to get everything.
Make sure you are initializing your OpenGL context before you try to access any of the GL namespace. Eg. with GLAD:
// after initializing window
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}