[PATCH 0/2] Capture and display frame thumbnails in qapitrace

Dan McCabe zen3d.linux at gmail.com
Thu Mar 1 12:38:38 PST 2012


On 03/01/2012 09:04 AM, José Fonseca wrote:
> On Wed, Feb 29, 2012 at 7:56 PM, Dan McCabe<zen3d.linux at gmail.com>  wrote:
>> This patch set automatically captures and displays thumbnails for each
>> frame in qapitrace.
>>
>> qapitrace spawns glretrace in a separate process to replay traces and
>> capture relevent information about those traces. In the first patch, a
>> sequence of snapshots is generated and captured. In the second patch,
>> those snapshots are associated with the approproate ApiTraceFrame. When
>> the ApiTraceEvent is processed for each frame, the snapshot is reduced
>> in size for a thumbnail and that thumbnail is displayed at the front
>> of the frame's information.
> Thanks for doing this. This is a really nice feature!
>
> I've pushed your patches to a gui-thumbnails branch to facilitate testing.
>
> I'll defer to Zack comments on the gui implementation.
>
>> Open issue: the thumbnail isn't immediately displayed. However, the
>> instant the user interacts with the app, all thumbnails are displayed.
>> Suggestions on how to force the app to initiate that update without
>> user interaction would be appreciated.
> We should also have an option for glretrace to run headless (don't
> show any window), as they can be distracting sometimes.
>
>> Open issue: the communication of an image stream from glretrace to
>> qapitrace is a bit fragile. I have encountered several exceptions when
>> Qt runs out of memory in QProcess::readAllStandardOutput() and an
>> exception is thrown. Qt isn't particularly graceful about handling
>> this exception. There are ways to mitigate this running out of memory
>> and I am currently working on that. One way is to reduce the snapshot
>> size at the time of capture. I prototyped a snapshot scaling arg in
>> glretrace, but I'm open to other suggestions.
> readAllStandardOutput should be replaced with something that doesn't
> read the whole output. For example QProcess::setReadChannel()  and
> read()
>
>
> I'm also running into assert failures with any trace I try:
>
> ASSERT failure in QList<T>::at: "index out of range", file
> /usr/include/qt4/QtCore/qlist.h, line 456
>
> Program received signal SIGABRT, Aborted.
> 0x00007ffff3830475 in *__GI_raise (sig=<optimized out>) at
> ../nptl/sysdeps/unix/sysv/linux/raise.c:64
> 64	../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
> 	in ../nptl/sysdeps/unix/sysv/linux/raise.c
> (gdb) bt
> #0  0x00007ffff3830475 in *__GI_raise (sig=<optimized out>) at
> ../nptl/sysdeps/unix/sysv/linux/raise.c:64
> #1  0x00007ffff38336f0 in *__GI_abort () at abort.c:92
> #2  0x00007ffff4392571 in qt_message_output(QtMsgType, char const*) ()
> from /usr/lib/libQtCore.so.4
> #3  0x00007ffff43928ef in qt_message(QtMsgType, char const*,
> __va_list_tag*) () from /usr/lib/libQtCore.so.4
> #4  0x00007ffff4392a94 in qFatal(char const*, ...) () from
> /usr/lib/libQtCore.so.4
> #5  0x000000000043197d in QList<QImage>::at (this=0xb1c910, i=21) at
> /usr/include/qt4/QtCore/qlist.h:456
> #6  0x000000000042f77a in ApiTrace::bindSnapsToFrames (this=0x812500,
> snaps=0xb1c910) at
> /home/jfonseca/projects/apitrace/gui/apitrace.cpp:505
> #7  0x00000000004619cb in MainWindow::replaySnapsFound
> (this=0x7fffffffdcc0, snaps=0xb1c910) at
> /home/jfonseca/projects/apitrace/gui/mainwindow.cpp:855
> #8  0x0000000000464077 in MainWindow::qt_metacall
> (this=0x7fffffffdcc0, _c=QMetaObject::InvokeMetaMethod, _id=9,
> _a=0x7fffffffd350)
>      at /home/jfonseca/projects/apitrace/gui/mainwindow.moc:153
> #9  0x00007ffff4494eba in QMetaObject::activate(QObject*, QMetaObject
> const*, int, void**) () from /usr/lib/libQtCore.so.4
> #10 0x000000000046f0c5 in Retracer::foundSnaps (this=0x7db6a0,
> _t1=0xb1c910) at /home/jfonseca/projects/apitrace/gui/retracer.moc:234
> #11 0x000000000046ef9f in Retracer::qt_metacall (this=0x7db6a0,
> _c=QMetaObject::InvokeMetaMethod, _id=2, _a=0x8909a0) at
> /home/jfonseca/projects/apitrace/gui/retracer.moc:205
> #12 0x00007ffff4498a6a in QObject::event(QEvent*) () from
> /usr/lib/libQtCore.so.4
> #13 0x00007ffff4cbcc64 in QApplicationPrivate::notify_helper(QObject*,
> QEvent*) () from /usr/lib/libQtGui.so.4
> #14 0x00007ffff4cc1af1 in QApplication::notify(QObject*, QEvent*) ()
> from /usr/lib/libQtGui.so.4
> #15 0x00007ffff448228c in QCoreApplication::notifyInternal(QObject*,
> QEvent*) () from /usr/lib/libQtCore.so.4
> #16 0x00007ffff4485648 in
> QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*)
> () from /usr/lib/libQtCore.so.4
> #17 0x00007ffff44ac9d3 in postEventSourceDispatch(_GSource*, int
> (*)(void*), void*) () from /usr/lib/libQtCore.so.4
> #18 0x00007ffff1eaf0cf in g_main_dispatch (context=0x7034e0) at
> /tmp/buildd/glib2.0-2.30.2/./glib/gmain.c:2442
> #19 g_main_context_dispatch (context=0x7034e0) at
> /tmp/buildd/glib2.0-2.30.2/./glib/gmain.c:2998
> #20 0x00007ffff1eaf8c8 in g_main_context_iterate (context=0x7034e0,
> block=<optimized out>, dispatch=1, self=<optimized out>) at
> /tmp/buildd/glib2.0-2.30.2/./glib/gmain.c:3076
> #21 0x00007ffff1eafa99 in g_main_context_iteration (context=0x7034e0,
> may_block=1) at /tmp/buildd/glib2.0-2.30.2/./glib/gmain.c:3139
> #22 0x00007ffff44ace2f in
> QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
> () from /usr/lib/libQtCore.so.4
> #23 0x00007ffff4d60eee in
> QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)
> () from /usr/lib/libQtGui.so.4
> #24 0x00007ffff4481492 in
> QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
> from /usr/lib/libQtCore.so.4
> #25 0x00007ffff448168f in
> QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from
> /usr/lib/libQtCore.so.4
> #26 0x00007ffff4485837 in QCoreApplication::exec() () from
> /usr/lib/libQtCore.so.4
> #27 0x000000000046c544 in main (argc=2, argv=0x7fffffffe0e8) at
> /home/jfonseca/projects/apitrace/gui/main.cpp:65
>
> Jose

Hi Jose,

Thank you for the feedback.

Carl Worth gets the credit for suggesting adding this feature.

I absolutely agree on the need for a headless option for glretrace. I'll 
look into it in the future.

Regarding readAllStandardOutput, I used it simply because it was already 
being used and because I'm not familiar enough with Qt alternatives. I 
will look into using setReadChannel()/read().

One issue I had with the whole communication mechanism was the variable 
length of the PNM format. The issue is the need to parse the header. I 
played around with a non-standard variant of PNM that was purely binary 
and therefore the header was of fixed length, which simplified reading 
the stream. But it introduced a non-standard variant, so I put that on 
the back-burner.

I also ran into the assert issues early in the development, when I 
wasn't properly creating the list of images. But once I did that 
correctly for my test cases, I didn't see the issue anymore. I will look 
into this further. Also, avoiding the assert failure is pretty easy, 
even though it shouldn't occur with well formed data. I'll add a check 
to avoid that in the next rev of the patch.

Thanks again.

cheers, danm




More information about the apitrace mailing list