QOpenGLFunctions glGetString(GL_EXTENSIONS) is null
-
Qt 5.5.1
I want to see which extensions (GL_EXTENSIONS) supports my graphics card (GeForce 7000M), but it always is null.
Here is the correct minimum code for this task.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); std::string ext = QString::fromLatin1((const char*)ctx.functions()->glGetString(GL_EXTENSIONS)).replace(' ', "\n\t").toStdString(); printf("OpenGL: %s %s %s\n\n\t%s\n", ctx.functions()->glGetString(GL_VENDOR), ctx.functions()->glGetString(GL_RENDERER), ctx.functions()->glGetString(GL_VERSION), ext.c_str()); return 0; }
stdout
OpenGL: nouveau Gallium 0.4 on NV67 2.1 Mesa 11.1.2 GL_ARB_multisample GL_EXT_abgr GL_EXT_bgra GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_copy_texture GL_EXT_polygon_offset GL_EXT_subtexture GL_EXT_texture_object GL_EXT_vertex_array GL_EXT_compiled_vertex_array GL_EXT_texture GL_EXT_texture3D GL_IBM_rasterpos_clip GL_ARB_point_parameters GL_EXT_draw_range_elements GL_EXT_packed_pixels GL_EXT_point_parameters GL_EXT_rescale_normal GL_EXT_separate_specular_color GL_EXT_texture_edge_clamp GL_SGIS_generate_mipmap GL_SGIS_texture_border_clamp GL_SGIS_texture_edge_clamp GL_SGIS_texture_lod GL_ARB_multitexture GL_IBM_multimode_draw_arrays GL_IBM_texture_mirrored_repeat GL_ARB_texture_cube_map GL_ARB_texture_env_add GL_ARB_transpose_matrix GL_EXT_blend_func_separate GL_EXT_fog_coord GL_EXT_multi_draw_arrays GL_EXT_secondary_color GL_EXT_texture_env_add GL_EXT_texture_filter_anisotropic GL_EXT_texture_lod_bias GL_INGR_blend_func_separate GL_NV_blend_square GL_NV_light_max_exponent GL_NV_texgen_reflection GL_NV_texture_env_combine4 GL_S3_s3tc GL_SUN_multi_draw_arrays GL_ARB_texture_border_clamp GL_ARB_texture_compression GL_EXT_framebuffer_object GL_EXT_texture_compression_s3tc GL_EXT_texture_env_combine GL_EXT_texture_env_dot3 GL_MESA_window_pos GL_NV_packed_depth_stencil GL_NV_texture_rectangle GL_ARB_depth_texture GL_ARB_occlusion_query GL_ARB_shadow GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar GL_ARB_texture_env_dot3 GL_ARB_texture_mirrored_repeat GL_ARB_window_pos GL_EXT_stencil_two_side GL_EXT_texture_cube_map GL_NV_depth_clamp GL_NV_fog_distance GL_APPLE_packed_pixels GL_APPLE_vertex_array_object GL_ARB_draw_buffers GL_ARB_fragment_program GL_ARB_fragment_shader GL_ARB_shader_objects GL_ARB_vertex_program GL_ARB_vertex_shader GL_ATI_draw_buffers GL_ATI_texture_env_combine3 GL_EXT_depth_bounds_test GL_EXT_shadow_funcs GL_EXT_stencil_wrap GL_MESA_pack_invert GL_NV_primitive_restart GL_ARB_depth_clamp GL_ARB_fragment_program_shadow GL_ARB_half_float_pixel GL_ARB_occlusion_query2 GL_ARB_point_sprite GL_ARB_shading_language_100 GL_ARB_sync GL_ARB_texture_non_power_of_two GL_ARB_vertex_buffer_object GL_ATI_blend_equation_separate GL_EXT_blend_equation_separate GL_OES_read_format GL_ARB_pixel_buffer_object GL_ARB_texture_rectangle GL_EXT_pixel_buffer_object GL_EXT_texture_compression_dxt1 GL_EXT_texture_mirror_clamp GL_EXT_texture_rectangle GL_EXT_texture_sRGB GL_EXT_framebuffer_blit GL_EXT_packed_depth_stencil GL_ARB_vertex_array_object GL_ATI_separate_stencil GL_ATI_texture_mirror_once GL_EXT_gpu_program_parameters GL_EXT_texture_sRGB_decode GL_EXT_timer_query GL_OES_EGL_image GL_ARB_copy_buffer GL_ARB_half_float_vertex GL_ARB_map_buffer_range GL_ARB_texture_swizzle GL_ARB_vertex_array_bgra GL_EXT_texture_swizzle GL_EXT_vertex_array_bgra GL_NV_conditional_render GL_ARB_ES2_compatibility GL_ARB_debug_output GL_ARB_draw_elements_base_vertex GL_ARB_explicit_attrib_location GL_ARB_fragment_coord_conventions GL_ARB_provoking_vertex GL_ARB_sampler_objects GL_EXT_provoking_vertex GL_EXT_texture_snorm GL_MESA_texture_signed_rgba GL_ARB_get_program_binary GL_ARB_robustness GL_ARB_separate_shader_objects GL_ARB_timer_query GL_ANGLE_texture_compression_dxt3 GL_ANGLE_texture_compression_dxt5 GL_ARB_compressed_texture_pixel_storage GL_ARB_internalformat_query GL_ARB_map_buffer_alignment GL_ARB_texture_storage GL_AMD_shader_trinary_minmax GL_ARB_clear_buffer_object GL_ARB_explicit_uniform_location GL_ARB_invalidate_subdata GL_ARB_program_interface_query GL_ARB_vertex_attrib_binding GL_KHR_debug GL_ARB_buffer_storage GL_ARB_multi_bind GL_ARB_texture_mirror_clamp_to_edge GL_ARB_get_texture_sub_image GL_KHR_context_flush_control
-
@Ilya-Indigo
You're calling a non-static function as static. That's the problem. Create an object of typeQOpenGLFunctions
and then query your version and extensions.QOpenGLFunctions gl; const GLubyte * version = gl.glGetString(GL_VERSION); // ... and so on ...
Kind regards.
-
#include <iostream> #include <stdio.h> #include <string.h> #include <GL/gl.h> #include <GL/glu.h> #include <GL/glext.h> #include <QtOpenGL/QtOpenGL> #include <QtOpenGL/QGL> #include <QtOpenGL/QGLFunctions> #include <QtGui/QOpenGLFunctions> int main() { QOpenGLFunctions gl; //gl.initializeOpenGLFunctions(); const GLubyte* gl_version = gl.glGetString(GL_VERSION); const GLubyte* gl_extensions = gl.glGetString(GL_EXTENSIONS); printf("GL_VERSION:\n%s\n\nGL_EXTENSIONS:\n%s\n",gl_version,gl_extensions); return 0; }
/tmp/test/test/main.cpp:-1: error: undefined reference to `QOpenGLFunctions::QOpenGLFunctions()' :-1: error: collect2: error: ld returned 1 exit status
http://doc.qt.io/qt-5/qopenglfunctions.html#glGetString
What's wrong now?
QOpenGLFunctions seem included. -
@Ilya-Indigo
Do you haveQT += gui
in your.pro
file? -
@kshegunov No.
QT += core QT -= gui CONFIG += c++11 TARGET = test CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += main.cpp
-
@Ilya-Indigo
Then you should add it, so the linker doesn't complain. :)
Substitute this:QT -= gui
with
QT += gui
Additionally it seems you need a open gl context to resolve the functions (after calling
initializeOpenGLFunctions()
). You may need to create that as well. -
@kshegunov Thank you, I do it
QT += core QT += gui .........
but if I'am use object stdout is empty, even constant in printf don't printed/
int main() { QOpenGLFunctions gl; gl.initializeOpenGLFunctions(); const GLubyte* gl_version = gl.glGetString(GL_VERSION); const GLubyte* gl_extensions = gl.glGetString(GL_EXTENSIONS); printf("GL_VERSION:\n%s\n\nGL_EXTENSIONS:\n%s\n",gl_version,gl_extensions); return 0; }
stdout is empty and /tmp/test/build-test-Desktop-Release/test crashed (segmenation fail (core dumped))
if i don't use object values is null
int main() { void initializeGL(); void initializeOpenGLFunctions(); const GLubyte* gl_version = glGetString(GL_VERSION); const GLubyte* gl_extensions = glGetString(GL_EXTENSIONS); printf("GL_VERSION:\n%s\n\nGL_EXTENSIONS:\n%s\n",gl_version,gl_extensions); return 0; }
GL_VERSION: (null) GL_EXTENSIONS: (null)
-
@kshegunov
What is it "open gl context"?
How create it?
A lot of this is about where I read, but nowhere is an example of what it is and how to create it. -
#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.