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

Dan McCabe zen3d.linux at gmail.com
Thu Mar 1 15:18:02 PST 2012


On 03/01/2012 12:38 PM, Dan McCabe wrote:
> 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
>
>

Follow-up: my initial prototype using setReadChannel()/read() looks a 
lot more robust. Thanks for the suggestion.

I still have a bit of clean-up to do, since I'm doing some unnatural 
things to merge into my previous code :). But stability is improved.

cheers, danm




More information about the apitrace mailing list