How to attach a drawing surface to QMainWindow? - qt

The top-level view in the application I am working on is not Qt-based. This view has its own APIs to draw lines, pixels, etc. I would like to take a rectangular portion of this view and attach it to QMainWindow instance. I guess there must be some mechanism within Qt that attaches a screen (Windows, x-windows, etc.) to QMainWindow. Can you please direct me to the abstract class that Qt uses for drawing to the actual surface? Regards.

If you're using Qt4 there's QX11EmbedWidget, which doesn't actually seem to exist in Qt5 and I can't find a good replacement. In terms of surface rendering everything is done as a QPaintDevice if it's subclassed from QWidget (which as far as I know every GUI element is).

The default raster backend draws on a QImage, so what you paint on with a QPainter in any widget is a QImage.
The backing store QImage shares the image bits with the underlying platform. On Windows, the QImage accesses a DIB section's data directly. On X11, the QImage accesses a shared memory XImage.
In all cases, assuming that your non-Qt code expects a bitmap to paint on, you can pass the data pointer from the QImage to the non-Qt code, within the paint event:
QImage * image = dynamic_cast<QImage*>(backingStore()->paintDevice());
The non-Qt code needs to properly interface to a large bitmap: it needs to accept a starting scan line to draw on, an X offset, and scanline length.

Related

QGLWidget is slower than QWidget

The problem mainly is determined in the title. I tried out the Qt's example (2dpainting) and noticed, that the same code consumes more CPU power if I try to draw on QGLWidget and less if I try to draw simply on QWidget. I thought that the QGLWidget should be faster. And one more interesting phenomenon: In QGLWidget the antialiasing hint seems to be ignored.
OpenGL version: 3.3.0
So why is that?
Firstly, note this text at the bottom of the documentation that you link to:
The example shows the same painting operations performed at the same
time in a Widget and a GLWidget. The quality and speed of rendering in
the GLWidget depends on the level of support for multisampling and
hardware acceleration that your system's OpenGL driver provides. If
support for either of these is lacking, the driver may fall back on a
software renderer that may trade quality for speed.
Putting that aside, hardware rendering is not always guaranteed to be faster than software rendering; it all depends upon what the renderer is being asked to do.
An example of where software can exceed hardware is if the goal of the item being rendered is constantly changing. So, if you have a drawing program that draws a line being created by the mouse being constantly moved and it is implemented by adding points to a painter path that is drawn every frame, a hardware renderer will be subject to constant pipeline stalls as new points are added to the painter path. Setting up the graphics pipeline from a stall takes time, which is not something a software renderer has to deal with.
In the 2dPainting example you ask about, the helper class, which performs the paint calls, is doing a lot of unnecessary work; saving the painter state; setting the pen / brush; rotating the painter; restoring the brush. All of this is a bigger overhead in hardware than software. To really see hardware rendering outperform software, pre-calculating the objects' positions outside of the render loop (paint function) and then doing nothing put actually rendering in the paint function is likely to display a noticeable difference here.
Finally, regarding anti-aliasing, the documentation that you linked to states: "the QGLWidget will also use anti-aliasing if the required extensions are supported by your system's OpenGL driver"

Vertex shader to create and animate geometry in QQuickItem

I'm reading through the comments on this Qt bug report:
https://bugreports.qt-project.org/browse/QTBUG-32741
That bug report suggests using a vertex shader with the QSGGeometry and animating in C++. I know the QML side supports shaders, but how do you access a shader from a QSGGeometry material that is handled via a C++ subclass of QQuickItem (as I interpret the bug report to suggest)? The vertex shaders accessed within QML are generally for deforming existing geometry, not really for creating new geometry or animating geometry, from what I can tell.
Or is the report suggesting to bypass QML completely for this task?
It would be pretty cool to pass data to a vertex shader for raw drawing and have the GL viewport be the Quick Item, but I don't think the QML shaders are designed for this.
In your subclass of QQuickItem override updatePaintNode() method should create (and update when needed) instance of QSGGeometryNode and set it up with a QSGGeometry configured for specific geometry type. That will allow you to directly control Vertex Buffer Object (just one, but with arbitrary layout of vertex attributes) and use your custom shaders.
See "Custom Geometry" example in qt documentation. Full project is in official repository.
Even more interesting example is "Texture in SGNode". It uses QQuickWindow::beforeRendering() signal to be able to run completely arbitrary OpenGL code. In this example custom rendering goes to Frame Buffer Object. Later this FBO is used as texture in a QSGSimpleTextureNode subclass.

Is openGl usefull to display a map?

I have to display a tiled map to display the result of a simulation
One can zoom/unzoom on the map, so if the zoom is far, there will be much more tiles displayed.
I am using QGraphicsPixmapItem to add the tiles to a QGraphicsScene.
I wonder whether openGl would be able to speed things up
I am using QGraphicsPixmapItem to add the tiles to a QGraphicsScene.
QGraphicsScene already uses methods like spatial subdivision (Kd trees) to determine which parts of a scene are visible and which not. In addition QGraphicsScene can use OpenGL as a rendering backend.
I strongly suggest you stick with QGraphicsScene, you'll hardly get more efficient than this, especially considering your next question:
I wonder whether openGl would be able to speed things up
Not if used naively. OpenGL is not a scene graph. I can't cull away and not issue drawing commands for geometry not visible. If you send it drawing commands it will process them. Unlike QGraphicsScene, which maintains scene data, OpenGL will carry out whatever drawing operation you ask it to do. Even if the final result may be invisible. Only in the very last processing steps (clipping, early fragment rejection) invisible fragments are discarded.

Can I draw Qt objects directly to Win32 DC (Device Context)?

I can draw Qt objects to an QImage and then draw the image to HDC or CDC. This may hurt our application's performance. It would be great if I can draw Qt objects directly to Win32 HDC or MFC CDC. I expect that there is a class, say QWin32Image for clear, then I can use it in this way:
QWin32Image image(hdc, 100, 100, Format_ARGB32_Premultiplied);
QPainter painter(&image);
painter.drawText(....);
Is it possible for my thought? Or is there a better way to do that?
Short answer - No. AFAIK in Qt, they abstract the entire UI for platform independence at application code level. Qt paints all of its widgets to it's own buffer and then paints to the screen.
Long answer - Qualified Yes.
Qt offers Win/MFC Integration Library which will allow Qt objects to interact with HDC and MFC objects. This library does work well. But I found using it somewhat confusing until I understood how it works.
What this library does allows you display QWindows in MFC window or MFC window in at Qt frame. As long as you keep this in mind, you can make it work.
Alternately, QImage.scanLine(0) points to the entire raw bitmap that you can use to write directly to the screen using one of the windows functions. Even though function name is scanline, using it this way points to start of the raw pixel buffer.

jamvm1.5+classpath-0.96+qt4.3 QPixmap: It is not safe to use pixmaps outside the GUI thread

jamvm -Dawt.toolkit=gnu.java.awt.peer.qt test
QPixmap: It is not safe to use pixmaps outside the GUI thread
I'm new to Qt, I don't know how to deal with it.
I have no experience whatsoever with the jamvm, but here's the Qt doc quote that might be helpful:
Qt provides four classes for handling
image data: QImage, QPixmap, QBitmap
and QPicture. QImage is designed and
optimized for I/O, and for direct
pixel access and manipulation, while
QPixmap is designed and optimized for
showing images on screen.
Try using QImage instead of QPixmap and see if there is the same warning/error message.
Since QPixmap is a device-dependent representation, and many display drivers and systems aren't thread-safe, QPixmap is restricted to only being used in the main or GUI thread, which is the same thread your QApplication object should be instantiated in. You can see a brief bit in the documentation here, and read more information about it in this discussion thread.

Resources