Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to take reliable QGLWidget snapshot

In my application I take snapshots of a QGLWidget's contents for two purposes:

  • Not redraw the scene all the time when only an overlay changes, using a cached pixmap instead
  • Lat the user take screenshots of the particular plots (3D scene)

The first thing I tried is grabFrameBuffer(). It is natural to use this function as for the first application, what is currently visible in the widget is exactly what I want to cache. PROBLEM: On some hardware (e.g. Intel integrade graphics, Mac OS X with GeForce graphics), the image obtained does not contain the current screen content, but the content before that. So if the scene would be drawn two times, on the screen you see the second drawing, in the image you see the first drawing (which should be the content of the backbuffer?).

The second thing I tried is renderToPixmap(). This renders using paintGL(), but not using paint(). I have all my stuff in paint(), as I use Qt's painting functionality and only a small piece of the code uses native GL (beginNativePainting(), endNativePainting()).

I also tried the regular QWidget's snapshot capability (QPixmap::fromWidget(), or what it is called), but there the GL framebuffer is black.

Any ideas on how to resolve the issue and get a reliable depiction of the currently drawn scene?

like image 925
ypnos Avatar asked May 03 '12 10:05

ypnos


3 Answers

How to take reliable QGLWidget snapshot

Render current scene to framebuffer, save data from framebuffer to file. Or grab current backbuffer after glFlush. Anything else might include artifacts or incomplete scene.

like image 95
SigTerm Avatar answered Sep 21 '22 00:09

SigTerm


It seems that QGLWidget::grabFrameBuffer() internally calls glReadPixels() from OpenGL. On double-bufferd configurations the initial mode reads the back buffer (GL_BACK), switch with the OpenGL call glReadBuffer(GL_FRONT) to the front buffer before using QGLWidget::grabFrameBuffer() displaying an image on the screen.

like image 24
Andreas Avatar answered Sep 21 '22 00:09

Andreas


The result of QGLWidget::grabFrameBuffer(), like every other OpenGL calls, depends on the video driver. Qt merely forwards your call to the driver and grabs the image it returns, but the content of the image is not under Qt's control. Other than making sure you have installed the latest driver for your video card, there is not much you can do except report a bug to your video card manufacturer and pray.

like image 40
Fred Avatar answered Sep 24 '22 00:09

Fred