QOpenGLFunctions glGetString(GL_EXTENSIONS) is null
-
#include <iostream> #include <stdio.h> #include <string.h> #include <Qt> #include <QCoreApplication> #include <QObject> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glext.h> #include <QtOpenGL/QtOpenGL> #include <QtOpenGL/QGL> #include <QtOpenGL/QGLFunctions> #include <QOpenGLFunctions> #include <QOpenGLContext> #include <QWidget> #include <QOpenGLWidget> int main() { QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL,true); void initializeGL(); void initializeOpenGLFunctions(); const GLubyte* gl_version = glGetString(GL_VERSION); const GLubyte* gl_extensions = glGetString(GL_EXTENSIONS); printf("GL_VERSION: %s\nGL_EXTENSIONS: %s\n",gl_version,gl_extensions); QOpenGLContext qc; QOpenGLFunctions* f=qc.shareContext()->functions(); const GLubyte* gl_version2 = f->glGetString(GL_VERSION); const GLubyte* gl_extensions2 = f->glGetString(GL_EXTENSIONS); printf("GL_VERSION from Context: %s\nGL_EXTENSIONS from Context: %s\n",gl_version2,gl_extensions2); return 0; }
GL_VERSION: (null) GL_EXTENSIONS: (null) Ошибка сегментирования (core dumped)
-
@Ilya-Indigo
Hello,
I'm not an expert on OpenGL, but you could try something like this:int main(int argc, char ** argv) { QGuiApplication app(argc, argv); QOpenGLWindow window; window.setSurfaceType(QSurface::OpenGLSurface); QSurfaceFormat format; if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { format.setVersion(4, 3); format.setProfile(QSurfaceFormat::CoreProfile); } format.setDepthBufferSize(24); format.setSamples(4); format.setStencilBufferSize(8); window.setFormat(format); window.create(); QOpenGLContext context; context.setFormat(format); context.setScreen(QGuiApplication::primaryScreen()); context.create(); QOpenGLFunctions * gl = context.functions(); const GLubyte* gl_version = gl->glGetString(GL_VERSION); // ... and so on ... }
I hope this helps.
Kind regards. -
@kshegunov Hello.
Unfortunately, still does not want to work.
QOpenGLFunctions created with non-current context Ошибка сегментирования (core dumped)
#include <iostream> #include <stdio.h> #include <string.h> #include <Qt> #include <QCoreApplication> #include <QGuiApplication> #include <QObject> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glext.h> #include <QtOpenGL/QtOpenGL> #include <QtOpenGL/QGL> #include <QtOpenGL/QGLFunctions> #include <QOpenGLFunctions> #include <QOpenGLContext> #include <QWidget> #include <QOpenGLWidget> int main(int argc, char ** argv) { /*QCoreApplication::setAttribute(Qt::AA_UseDesktopOpenGL,true); void initializeGL(); void initializeOpenGLFunctions(); const GLubyte* gl_version1 = glGetString(GL_VERSION); const GLubyte* gl_extensions1 = glGetString(GL_EXTENSIONS); printf("GL_VERSION: %s\nGL_EXTENSIONS: %s\n",gl_version1,gl_extensions1);*/ QGuiApplication app(argc, argv); QOpenGLWindow window; window.setSurfaceType(QSurface::OpenGLSurface); QSurfaceFormat format; if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { format.setVersion(1,2); format.setProfile(QSurfaceFormat::CoreProfile); } format.setDepthBufferSize(24); format.setSamples(4); format.setStencilBufferSize(8); window.setFormat(format); window.create(); QOpenGLContext context; context.setFormat(format); context.setScreen(QGuiApplication::primaryScreen()); context.create(); QOpenGLFunctions* gl = context.functions(); const GLubyte* gl_version2 = gl->glGetString(GL_VERSION); const GLubyte* gl_extensions2 = gl->glGetString(GL_EXTENSIONS); printf("GL_VERSION from Context: %s\nGL_EXTENSIONS from Context: %s\n",gl_version2,gl_extensions2); return 0; }
-
@Ilya-Indigo
Hm, try callingQOpenGLContext::makeCurrent
then. From your last code:// ... context.create(); context.makeCurrent(&window); //< Try inserting this line after creating the context and before retrieving the functions. QOpenGLFunctions* gl = context.functions(); // ...
-
All you need is an application object, surface and a context. Here's a minimal example:
#include <QApplication> #include <QOffscreenSurface> #include <QOpenGLContext> #include <QOpenGLFunctions> #include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); QOffscreenSurface surf; surf.create(); QOpenGLContext ctx; ctx.create(); ctx.makeCurrent(&surf); qDebug () << (const char*)ctx.functions()->glGetString(GL_VERSION); qDebug () << (const char*)ctx.functions()->glGetString(GL_EXTENSIONS); }
-
@kshegunov
Thank you very much for all your help! :-)
After adding this line, the code worked.
Although it is not the best, but it is working. :-)@Chris-Kawa
Thank you for working and best example, this is what I needed. :-)QT += opengl CONFIG += c++11 TARGET = test CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp
main.cpp
#include <QtOpenGL> int main(int argc, char *argv[]) { QApplication a(argc, argv); QOffscreenSurface surf; surf.create(); QOpenGLContext ctx; ctx.create(); ctx.makeCurrent(&surf); const GLubyte* extensions = ctx.functions()->glGetString(GL_EXTENSIONS); std::string ext = "\t"; int l = strlen((char*)extensions); for (int i=0;i<l;i++) { if (extensions[i] != ' ') ext += extensions[i]; else ext += "\n\t"; } printf("OpenGL: %s %s %s\n\n%s\n", ctx.functions()->glGetString(GL_VENDOR), ctx.functions()->glGetString(GL_RENDERER), ctx.functions()->glGetString(GL_VERSION), ext.c_str()); return 0; }
I wonder whether it was possible somehow to replace the spaces (in my code ' ' -> "\n\t", but would be satisfied with a simple ' ' -> '\n') at the line breaks more optimally than I did?
replace()/find() doing a little bit more, and with replace_if I did not understand. -
Well, since you're using Qt anyway why not go all the way:
QString exts = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(" ", "\n\t");
or, if you prefer a list instead of one string:
QStringList exts = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).split(' ');
-
@Chris-Kawa said:
Well, since you're using Qt anyway why not go all the way:
I'm still starting to learn Qt and still do not know about all of its features.
QString exts = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(" ", "\n\t");
Oh great, what you need.
const char* ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toStdString().c_str();
or, if you prefer a list instead of one string: ```cpp QStringList exts = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).split(' ');
It reminded me explode(' ') / foreach() in PHP or split(' ').join('\n\t') in JS.
In PHP foreach through the easiest process, but there is no native JS recursive replacement, this had to be split into an array.
But in Qt would like to do is normal, especially if there is native support this. :-)
Although it is not surprised that there is Qt and foreach(), which works the same way as in PHP. :-) -
@Ilya-Indigo said:
const char* ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toStdString().c_str();
Don't do that! The string generated by
toStdString
is a temporary destroyed at the end of this line. The resulting pointerext
points to garbage memory this way!Do it like this:
QByteArray ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toUtf8(); someFunctionthatExpectsConstCharStar(ext.constData());
or, if you want std::string, like this:
std::string ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toStdString(); someFunctionthatExpectsConstCharStar(ext.c_str());
you can store that pointer (almost always bad idea), as long as the original string lives:
std::string ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toStdString(); const char* ext_c_str = ext.c_str(); someFunctionthatExpectsConstCharStar(ext_c_str);
but don't ever store a pointer to a temporary like you did.
-
@Chris-Kawa
Thank you for your comment and clarification. :-)
If I correctly understood and grasped the essence, the "const char *" should be used only in the case of constant declarations.const char* var_name = "Constant string";
And if it is not constant, and any expression, it is better to use std :: string?
std::string var_name = a+b+c.some_string_method() ... etc ... ;
-
It's not that general. It's better to understand what's the difference.
std:string, QString, CString and any other kind of library strings are containers. They store data and manage its lifetime. They are responsible for it. The data goes away when the object goes away. Because they do this bookkeeping they are a little heavier to initialize and destroy.
Pointer is just a finger pointing to a place in memory. It carries no notion of ownership or lifetime. The data it points to has no ties to it. It doesn't go away when data goes away. The data doesn't go away when the pointer does. Because of this pointers are ultra-light but also a lot more dangerous.Pointers to characters are generally good for api-boundary situations. When you have a container type string it usually gives you a raw pointer to its internal data so you can "look" at it from some functions.
A rule of thumb is that you should avoid conversions between container types whenever possible, as they allocate memory, copy stuff around and are generally heavy. If you're using STL stick to std::string. If you're using Qt stick to QString.
Pointers are good and cheap when used for their purpose - pointing at things. They should not be used to manage lifetimes.
For exampleconst char* foo = "bar bazz";
just points at some static data in memory. The data is not going away so its safe to keep this pointer around too. On the other handconst char* foo = someFuncThatGivesMeAPointer()
is more vague. Who is responsible for that memory? should you calldelete foo
at some point or is the memory managed by someone? If it is then when is it released and can you keep thefoo
pointer and use without worrying that someone releases the memory from under it?Qt uses a lot of pointers, but it has strict policies about the lifetimes of stuff it gives you pointers to. These are not, however, rules enforced by a compiler, only a general programmer-documentation contract.
-
@Chris-Kawa
Thanks for your reply. I am now much clearer. -
@Chris-Kawa said in QOpenGLFunctions glGetString(GL_EXTENSIONS) is null:
QString exts = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(" ", "\n\t");
I have a same question. I try to show OpenGL version but I get empty string:
QString version = QString::fromLatin1((const char*)glGetString(GL_VERSION)); qDebug() << version;
-
@8Observer8 said in QOpenGLFunctions glGetString(GL_EXTENSIONS) is null:
I have a same question. I try to show OpenGL version but I get empty string:
I solved the problem. I activated a second video card on my laptop from code in main.cpp:
#ifdef _WIN32 #include <windows.h> extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001; #endif #include "Widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
It works too (without
QString::fromLatin1
):qDebug() << (const char*)glGetString(GL_VERSION);