Unsolved DrawPixmapFragments on OpenGL crash when passing in large data size
-
Hi all,
I have tried using drawPixmapFragments on QOpenGLWidget to render pixmaps in batch and came upon this crash when I send a pretty large data count right after a small data count.
Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000114404000 Exception Note: EXC_CORPSE_NOTIFY Termination Signal: Segmentation fault: 11 Termination Reason: Namespace SIGNAL, Code 0xb Terminating Process: exc handler [0] VM Regions Near 0x114404000: MALLOC_LARGE 0000000114381000-00000001143db000 [ 360K] rw-/rwx SM=COW --> MALLOC_LARGE 000000011441b000-000000011451b000 [ 1024K] rw-/rwx SM=COW Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 ??? 0x00000001149db12d 0 + 4640846125 1 GLEngine 0x00007fffd8605c60 glDrawArrays_IMM_Exec + 811 2 libQt5Gui_debug.5.dylib 0x000000010af8e143 QOpenGLFunctions::glDrawArrays(unsigned int, int, int) + 99 3 libQt5Gui_debug.5.dylib 0x000000010af95e3c QOpenGL2PaintEngineExPrivate::drawPixmapFragments(QPainter::PixmapFragment const*, int, QPixmap const&, QFlags<QPainter::PixmapFragmentHint>) + 2700 4 libQt5Gui_debug.5.dylib 0x000000010af9539a QOpenGL2PaintEngineEx::drawPixmapFragments(QPainter::PixmapFragment const*, int, QPixmap const&, QFlags<QPainter::PixmapFragmentHint>) + 298 5 libQt5Gui_debug.5.dylib 0x000000010aeaecef QPainter::drawPixmapFragments(QPainter::PixmapFragment const*, int, QPixmap const&, QFlags<QPainter::PixmapFragmentHint>) + 543
Here is the example code of what I mean. The below code doesn't make sense. But in actual, I can confirm that I am calling drawPixmapFragments function back to back with valid data, correct size and a valid pixmaps. The only difference is the data size and the pixmap itself.
typedef QVarLengthArray<QPainter::PixmapFragment, 9> QPixmapFragmentsArray; static void s_AppendFragments(const QRect& pixmapRect, const QRectF& rcDest, QPixmapFragmentsArray& pixmapFragmentArray, int num) { for (int i = 0; i < num; ++i) { QPainter::PixmapFragment d; d.opacity = 1.0; d.rotation = 0.0; d.sourceLeft = pixmapRect.left(); d.sourceTop = pixmapRect.top(); d.width = pixmapRect.width(); d.height = pixmapRect.height(); d.scaleX = rcDest.width() / d.width; d.scaleY = rcDest.height() / d.height; d.y = rcDest.center().y(); d.x = rcDest.center().x(); pixmapFragmentArray.append(d); } } static void TestFunc(QPainter* painter, const QPixmap& pixmap1, const QPixmap& pixmap2) // called from paint { QPixmapFragmentsArray data1; QPixmapFragmentsArray data2; s_AppendFragments(pixmap1.rect(), QRectF(10, 10, 50, 50), data1, 5940); s_AppendFragments(pixmap2.rect(), QRectF(10, 10, 50, 50), data2, 35640); if (!data1.isEmpty()) { painter->drawPixmapFragments(data1.data(), data1.size(), pixmap1); } if (!data2.isEmpty()) { painter->drawPixmapFragments(data2.data(), data2.size(), pixmap2); } }
I am on MacOS Sierra (10.12.2)
Qt 5.4.1Thanks in advance :)
-
Hi,
What kind of data size are you trying to manipulate ?
-
@SGaist , Sorry, I am not getting your question. The first call to drawPixmapFragments is being fed with an array of PixmapFragment of size 5940, and the second call with size of 35640.
I kind of doubt the QDataBuffer that is used by QOpenGL2PEXVertexArray in QOpenGLPaintEngine which will try to reserve memory using realloc when it is adding vertex. But I am really not sure in this. The crash happens when the second call give a pretty large size of array as compared to the first call. If the second call has just slightly higher array size as compared to the first, then I will see some artifact in drawing for that one frame. However, if the first call itself was giving the large array size, then there is no problem.
-
With the help of a friend, I found out that the issue is indeed in Qt's OpenGLPaintEngine. When we try to realloc a bigger data size than the previous one, realloc might be giving a buffer pointed to different memory address. However, in QOpenGL2PaintEngineExPrivate::transferMode, if the mode are the same back to back, then it did not bother to update the vertex attribute pointer to the new buffer address. Should I raise a bug?
-
@Sivan Sounds like a bug, you should raise a bug in the bug tracker.
-
@jsulm Sure, here is the link https://bugreports.qt.io/browse/QTBUG-70644