QPainter Overwrites OpenGL state in QOpenGLWidget
-
I am using a QOpenGLWidget to render some 3D shapes using OpenGL. I occasionally want to render some text into the GL frame buffer, and QPainter seems to have support for this. I noticed that when I create a QPainter as a local member variable within the QOpenGLWidget instance via
// My OpenGL settings are valid here { QPainter painter(this); // ... code to render text with painter } // QPainter has overwritten my OpenGL settings here
that the QPainter overwrites my OpenGL settings, however (including multi-sampling settings that I set previously through QSurfaceFormat::setDefaultFormat). I see that QPainter has beginNativePainting and endNativePainting methods, but these don't seem to work in my case where I already have existing OpenGL state that I want restored when the QPainter is destructed:
{ QPainter painter; painter.endNativePainting(); // This doesn't work, QPainter prints 'Painter not active' at this line painter.begin(this); // ... code to render text with painter painter.end(); painter.beginNativePainting(); }
Is there a way to have the QPainter restore any settings that it overwrites? Restoring the settings manually seems brittle, and the documentation says that the overwritten settings may change in the future. I am using Qt 5.8 on OS X 10.11.6.
-
I believe this is known to happen; I think I read that somewhere. Anyway you just push all the OpenGL attributes and pop them when you are done with QPainter.
Example:
// QPainter changes one or more attributes so all relevent ones // are pushed then popped on end of QPainter glPushAttrib(GL_ACCUM_BUFFER_BIT); glPushAttrib(GL_VIEWPORT_BIT); glPushAttrib(GL_TRANSFORM_BIT); glPushAttrib(GL_POLYGON_BIT); glPushAttrib(GL_PIXEL_MODE_BIT); glPushAttrib(GL_MULTISAMPLE_BIT); glPushAttrib(GL_LIGHTING_BIT); glPushAttrib(GL_ENABLE_BIT); glPushAttrib(GL_DEPTH_BUFFER_BIT); glPushAttrib(GL_CURRENT_BIT); glPushAttrib(GL_COLOR_BUFFER_BIT); // start of QPainter QPainter painter(this); // painter stuff painter.end(); // restore OpenGL attributes glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib();
-
Thanks, I ended up manually pushing and popping the state that QPainter overwrites like you suggest. I was hoping that the widget would be able to tell me what state it overwrites (because who else would know!), but reading through the source code it appears there is nothing that offers this functionality.
-
I believe this is known to happen; I think I read that somewhere. Anyway you just push all the OpenGL attributes and pop them when you are done with QPainter.
Example:
// QPainter changes one or more attributes so all relevent ones // are pushed then popped on end of QPainter glPushAttrib(GL_ACCUM_BUFFER_BIT); glPushAttrib(GL_VIEWPORT_BIT); glPushAttrib(GL_TRANSFORM_BIT); glPushAttrib(GL_POLYGON_BIT); glPushAttrib(GL_PIXEL_MODE_BIT); glPushAttrib(GL_MULTISAMPLE_BIT); glPushAttrib(GL_LIGHTING_BIT); glPushAttrib(GL_ENABLE_BIT); glPushAttrib(GL_DEPTH_BUFFER_BIT); glPushAttrib(GL_CURRENT_BIT); glPushAttrib(GL_COLOR_BUFFER_BIT); // start of QPainter QPainter painter(this); // painter stuff painter.end(); // restore OpenGL attributes glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib(); glPopAttrib();
Unfortunately, I can not use this approach - glPushAttrib is deprecated, and even not available in GLES or Core 3.1 contexts.