José Fonseca | 2127819 | 2015-01-20 14:27:04 +0000 | [diff] [blame] | 1 | Basic usage |
| 2 | =========== |
| 3 | |
| 4 | Run the application you want to trace as |
| 5 | |
| 6 | apitrace trace --api API /path/to/application [args...] |
| 7 | |
| 8 | and it will generate a trace named `application.trace` in the current |
| 9 | directory. You can specify the written trace filename by passing the |
| 10 | `--output` command line option. |
| 11 | |
| 12 | Problems while tracing (e.g, if the application uses calls/parameters |
| 13 | unsupported by apitrace) will be reported via stderr output on Unices. On |
| 14 | Windows you'll need to run |
| 15 | [DebugView](http://technet.microsoft.com/en-us/sysinternals/bb896647) to view |
| 16 | these messages. |
| 17 | |
José Fonseca | 91da6b5 | 2015-01-20 14:48:03 +0000 | [diff] [blame] | 18 | If you cannot obtain a trace, check the [application specific instructions on |
| 19 | the wiki](https://github.com/apitrace/apitrace/wiki/Applications), or the |
| 20 | [manual tracing instructions below](#tracing-manually). |
José Fonseca | 2127819 | 2015-01-20 14:27:04 +0000 | [diff] [blame] | 21 | |
| 22 | View the trace with |
| 23 | |
| 24 | apitrace dump application.trace |
| 25 | |
| 26 | Replay an OpenGL trace with |
| 27 | |
| 28 | apitrace replay application.trace |
| 29 | |
| 30 | Pass the `--sb` option to use a single buffered visual. Pass `--help` to |
| 31 | `apitrace replay` for more options. |
| 32 | |
José Fonseca | 91da6b5 | 2015-01-20 14:48:03 +0000 | [diff] [blame] | 33 | If you run into problems [check if it is a known issue and file an issue if |
| 34 | not](BUGS.markdown). |
| 35 | |
José Fonseca | 2127819 | 2015-01-20 14:27:04 +0000 | [diff] [blame] | 36 | |
| 37 | Basic GUI usage |
| 38 | =============== |
| 39 | |
| 40 | Start the GUI as |
| 41 | |
| 42 | qapitrace application.trace |
| 43 | |
| 44 | You can also tell the GUI to go directly to a specific call |
| 45 | |
| 46 | qapitrace application.trace 12345 |
| 47 | |
Jose Fonseca | a5255fd | 2015-01-26 14:38:39 +0000 | [diff] [blame^] | 48 | Press `Ctrl-T` to see per-frame thumbnails. And while inspecting frame calls, |
| 49 | press again `Ctrl-T` to see per-draw call thumbnails. |
| 50 | |
José Fonseca | 2127819 | 2015-01-20 14:27:04 +0000 | [diff] [blame] | 51 | |
| 52 | Backtrace Capturing |
| 53 | =================== |
| 54 | |
José Fonseca | 91da6b5 | 2015-01-20 14:48:03 +0000 | [diff] [blame] | 55 | apitrace now has the ability to capture the call stack to an OpenGL call on |
| 56 | certain OSes (only Android and Linux at the moment). This can be helpful in |
| 57 | determing which piece of code made that glDrawArrays call. |
José Fonseca | 2127819 | 2015-01-20 14:27:04 +0000 | [diff] [blame] | 58 | |
| 59 | To use the feature you need to set an environment variable with the list of GL |
| 60 | call prefixes you wish to capture stack traces to. |
| 61 | |
| 62 | export APITRACE_BACKTRACE="glDraw* glUniform*" |
| 63 | |
| 64 | The backtrace data will show up in qapitrace in the bottom section as a new tab. |
| 65 | |
| 66 | |
| 67 | Advanced command line usage |
| 68 | =========================== |
| 69 | |
| 70 | |
| 71 | Call sets |
| 72 | --------- |
| 73 | |
| 74 | Several tools take `CALLSET` arguments, e.g: |
| 75 | |
| 76 | apitrace dump --calls=CALLSET foo.trace |
| 77 | apitrace dump-images --calls=CALLSET foo.trace |
| 78 | apitrace trim --calls=CALLSET1 --calls=CALLSET2 foo.trace |
| 79 | |
| 80 | The call syntax is very flexible. Here are a few examples: |
| 81 | |
| 82 | * `4` one call |
| 83 | |
| 84 | * `0,2,4,5` set of calls |
| 85 | |
| 86 | * `"0 2 4 5"` set of calls (commas are optional and can be replaced with whitespace) |
| 87 | |
| 88 | * `0-100/2` calls 1, 3, 5, ..., 99 |
| 89 | |
| 90 | * `0-1000/draw` all draw calls between 0 and 1000 |
| 91 | |
| 92 | * `0-1000/fbo` all fbo changes between calls 0 and 1000 |
| 93 | |
| 94 | * `frame` all calls at end of frames |
| 95 | |
| 96 | * `@foo.txt` read call numbers from `foo.txt`, using the same syntax as above |
| 97 | |
| 98 | |
| 99 | |
| 100 | Tracing manually |
| 101 | ---------------- |
| 102 | |
| 103 | ### Linux ### |
| 104 | |
| 105 | On 64 bits systems, you'll need to determine whether the application is 64 bits |
| 106 | or 32 bits. This can be done by doing |
| 107 | |
| 108 | file /path/to/application |
| 109 | |
| 110 | But beware of wrapper shell scripts -- what matters is the architecture of the |
| 111 | main process. |
| 112 | |
| 113 | Run the GLX application you want to trace as |
| 114 | |
| 115 | LD_PRELOAD=/path/to/apitrace/wrappers/glxtrace.so /path/to/application |
| 116 | |
| 117 | and it will generate a trace named `application.trace` in the current |
| 118 | directory. You can specify the written trace filename by setting the |
| 119 | `TRACE_FILE` environment variable before running. |
| 120 | |
| 121 | For EGL applications you will need to use `egltrace.so` instead of |
| 122 | `glxtrace.so`. |
| 123 | |
| 124 | The `LD_PRELOAD` mechanism should work with the majority of applications. There |
| 125 | are some applications (e.g., Unigine Heaven, Android GPU emulator, etc.), that |
| 126 | have global function pointers with the same name as OpenGL entrypoints, living in a |
| 127 | shared object that wasn't linked with `-Bsymbolic` flag, so relocations to |
| 128 | those global function pointers get overwritten with the address to our wrapper |
| 129 | library, and the application will segfault when trying to write to them. For |
| 130 | these applications it is possible to trace by using `glxtrace.so` as an |
| 131 | ordinary `libGL.so` and injecting it via `LD_LIBRARY_PATH`: |
| 132 | |
| 133 | ln -s glxtrace.so wrappers/libGL.so |
| 134 | ln -s glxtrace.so wrappers/libGL.so.1 |
| 135 | ln -s glxtrace.so wrappers/libGL.so.1.2 |
| 136 | export LD_LIBRARY_PATH=/path/to/apitrace/wrappers:$LD_LIBRARY_PATH |
| 137 | export TRACE_LIBGL=/path/to/real/libGL.so.1 |
| 138 | /path/to/application |
| 139 | |
| 140 | If you are an application developer, you can avoid this either by linking with |
| 141 | `-Bsymbolic` flag, or by using some unique prefix for your function pointers. |
| 142 | |
| 143 | See the `ld.so` man page for more information about `LD_PRELOAD` and |
| 144 | `LD_LIBRARY_PATH` environment flags. |
| 145 | |
| 146 | ### Android ### |
| 147 | |
| 148 | To trace standalone native OpenGL ES applications, use |
| 149 | `LD_PRELOAD=/path/to/egltrace.so /path/to/application` as described in the |
| 150 | previous section. To trace Java applications, refer to Dalvik.markdown. |
| 151 | |
| 152 | ### Mac OS X ### |
| 153 | |
| 154 | Run the application you want to trace as |
| 155 | |
| 156 | DYLD_FRAMEWORK_PATH=/path/to/apitrace/wrappers /path/to/application |
| 157 | |
| 158 | Note that although Mac OS X has an `LD_PRELOAD` equivalent, |
| 159 | `DYLD_INSERT_LIBRARIES`, it is mostly useless because it only works with |
| 160 | `DYLD_FORCE_FLAT_NAMESPACE=1` which breaks most applications. See the `dyld` man |
| 161 | page for more details about these environment flags. |
| 162 | |
| 163 | ### Windows ### |
| 164 | |
| 165 | When tracing third-party applications, you can identify the target |
| 166 | application's main executable, either by: |
| 167 | |
| 168 | * right clicking on the application's icon in the _Start Menu_, choose |
| 169 | _Properties_, and see the _Target_ field; |
| 170 | |
| 171 | * or by starting the application, run Windows Task Manager (taskmgr.exe), right |
| 172 | click on the application name in the _Applications_ tab, choose _Go To Process_, |
| 173 | note the highlighted _Image Name_, and search it on `C:\Program Files` or |
| 174 | `C:\Program Files (x86)`. |
| 175 | |
| 176 | On 64 bits Windows, you'll need to determine ether the application is a 64 bits |
| 177 | or 32 bits. 32 bits applications will have a `*32` suffix in the _Image Name_ |
| 178 | column of the _Processes_ tab of _Windows Task Manager_ window. |
| 179 | |
| 180 | You also need to know which graphics API is being used. If you are unsure, the |
| 181 | simplest way to determine what API an application uses is to: |
| 182 | |
| 183 | * download and run [Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) |
| 184 | |
| 185 | * search and select the application's process in _Process Explorer_ |
| 186 | |
| 187 | * list the DLLs by pressing `Ctrl + D` |
| 188 | |
| 189 | * sort DLLs alphabetically, and look for the DLLs such as `opengl32.dll`, |
| 190 | `d3d9.dll`, `d3d10.dll`, etc. |
| 191 | |
| 192 | Copy the appropriate `opengl32.dll`, `d3d8.dll`, or `d3d9.dll` from the |
| 193 | wrappers directory to the directory with the application you want to trace. |
| 194 | Then run the application as usual. |
| 195 | |
| 196 | You can specify the written trace filename by setting the `TRACE_FILE` |
| 197 | environment variable before running. |
| 198 | |
| 199 | For D3D10 and higher you really must use `apitrace trace -a DXGI ...`. This is |
| 200 | because D3D10-11 API span many DLLs which depend on each other, and once a DLL |
| 201 | with a given name is loaded Windows will reuse it for LoadLibrary calls of the |
| 202 | same name, causing internal calls to be traced erroneously. `apitrace trace` |
| 203 | solves this issue by injecting a DLL `dxgitrace.dll` and patching all modules |
| 204 | to hook only the APIs of interest. |
| 205 | |
| 206 | |
| 207 | Emitting annotations to the trace |
| 208 | --------------------------------- |
| 209 | |
| 210 | From within OpenGL applications you can embed annotations in the trace file |
| 211 | through the following extensions: |
| 212 | |
| 213 | * [`GL_KHR_debug`](http://www.opengl.org/registry/specs/KHR/debug.txt) |
| 214 | |
| 215 | * [`GL_ARB_debug_output`](http://www.opengl.org/registry/specs/ARB/debug_output.txt) |
| 216 | |
| 217 | * [`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt) |
| 218 | |
| 219 | * [`GL_EXT_debug_label`](http://www.opengl.org/registry/specs/EXT/EXT_debug_label.txt) |
| 220 | |
| 221 | * [`GL_AMD_debug_output`](http://www.opengl.org/registry/specs/AMD/debug_output.txt) |
| 222 | |
| 223 | * [`GL_GREMEDY_string_marker`](http://www.opengl.org/registry/specs/GREMEDY/string_marker.txt) |
| 224 | |
| 225 | * [`GL_GREMEDY_frame_terminator`](http://www.opengl.org/registry/specs/GREMEDY/frame_terminator.txt) |
| 226 | |
| 227 | **apitrace** will advertise and intercept these OpenGL extensions regardless |
| 228 | of whether the OpenGL implementation supports them or not. So all you have |
| 229 | to do is to use these extensions when available, and you can be sure they |
| 230 | will be available when tracing inside **apitrace**. |
| 231 | |
| 232 | For example, if you use [GLEW](http://glew.sourceforge.net/) to dynamically |
| 233 | detect and use OpenGL extensions, you could easily accomplish this by doing: |
| 234 | |
| 235 | void foo() { |
| 236 | |
| 237 | if (GLEW_KHR_debug) { |
| 238 | glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, __FUNCTION__); |
| 239 | } |
| 240 | |
| 241 | ... |
| 242 | |
| 243 | if (GLEW_KHR_debug) { |
| 244 | glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, |
| 245 | 0, GL_DEBUG_SEVERITY_MEDIUM, -1, "bla bla"); |
| 246 | } |
| 247 | |
| 248 | ... |
| 249 | |
| 250 | if (GLEW_KHR_debug) { |
| 251 | glPopDebugGroup(); |
| 252 | } |
| 253 | |
| 254 | } |
| 255 | |
| 256 | This has the added advantage of working equally well with other OpenGL debugging tools. |
| 257 | |
| 258 | Also, provided that the OpenGL implementation supports `GL_KHR_debug`, labels |
| 259 | defined via glObjectLabel() , and the labels of several objects (textures, |
| 260 | framebuffers, samplers, etc. ) will appear in the GUI state dumps, in the |
| 261 | parameters tab. |
| 262 | |
| 263 | |
| 264 | For OpenGL ES applications you can embed annotations in the trace file through the |
| 265 | [`GL_KHR_debug`](http://www.khronos.org/registry/gles/extensions/KHR/debug.txt) or |
| 266 | [`GL_EXT_debug_marker`](http://www.khronos.org/registry/gles/extensions/EXT/EXT_debug_marker.txt) |
| 267 | extensions. |
| 268 | |
| 269 | |
| 270 | For Direct3D applications you can follow the standard procedure for |
| 271 | [adding user defined events to Visual Studio Graphics Debugger / PIX](http://msdn.microsoft.com/en-us/library/vstudio/hh873200.aspx): |
| 272 | |
| 273 | - `D3DPERF_BeginEvent`, `D3DPERF_EndEvent`, and `D3DPERF_SetMarker` for D3D9 applications. |
| 274 | |
| 275 | - `ID3DUserDefinedAnnotation::BeginEvent`, |
| 276 | `ID3DUserDefinedAnnotation::EndEvent`, and |
| 277 | `ID3DUserDefinedAnnotation::SetMarker` for D3D11.1 applications. |
| 278 | |
| 279 | |
| 280 | Dump OpenGL state at a particular call |
| 281 | ---------------------------------- |
| 282 | |
| 283 | You can get a dump of the bound OpenGL state at call 12345 by doing: |
| 284 | |
| 285 | apitrace replay -D 12345 application.trace > 12345.json |
| 286 | |
| 287 | This is precisely the mechanism the GUI uses to obtain its own state. |
| 288 | |
| 289 | You can compare two state dumps by doing: |
| 290 | |
| 291 | apitrace diff-state 12345.json 67890.json |
| 292 | |
| 293 | |
| 294 | Comparing two traces side by side |
| 295 | --------------------------------- |
| 296 | |
| 297 | apitrace diff trace1.trace trace2.trace |
| 298 | |
| 299 | This works only on Unices, and it will truncate the traces due to performance |
| 300 | limitations. |
| 301 | |
| 302 | |
| 303 | Recording a video with FFmpeg/Libav |
| 304 | ----------------------------------- |
| 305 | |
| 306 | You can make a video of the output with FFmpeg by doing |
| 307 | |
| 308 | apitrace dump-images -o - application.trace \ |
| 309 | | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4 |
| 310 | |
| 311 | or Libav (which replaces FFmpeg on recent Debian/Ubuntu distros) doing |
| 312 | |
| 313 | apitrace dump-images -o - application.trace \ |
| 314 | | avconv -r 30 -f image2pipe -vcodec ppm -i - -vcodec mpeg4 -y output.mp4 |
| 315 | |
| 316 | Recording a video with gstreamer |
| 317 | -------------------------------------- |
| 318 | |
| 319 | You can make a video of the output with gstreamer by doing |
| 320 | |
| 321 | glretrace --snapshot-format=RGB -s - smokinguns.trace | gst-launch-0.10 fdsrc blocksize=409600 ! queue \ |
| 322 | ! videoparse format=rgb width=1920 height=1080 ! queue ! ffmpegcolorspace ! queue \ |
| 323 | ! vaapiupload direct-rendering=0 ! queue ! vaapiencodeh264 ! filesink location=xxx.264 |
| 324 | |
| 325 | Trimming a trace |
| 326 | ---------------- |
| 327 | |
| 328 | You can truncate a trace by doing: |
| 329 | |
| 330 | apitrace trim --exact --calls 0-12345 -o trimed.trace application.trace |
| 331 | |
| 332 | If you need precise control over which calls to trim you can specify the |
| 333 | individual call numbers in a plain text file, as described in the 'Call sets' |
| 334 | section above. |
| 335 | |
| 336 | There is also experimental support for automatically trimming the calls |
| 337 | necessary for a given frame or call: |
| 338 | |
| 339 | apitrace trim --auto --calls=12345 -o trimed.trace application.trace |
| 340 | apitrace trim --auto --frames=12345 -o trimed.trace application.trace |
| 341 | |
| 342 | |
| 343 | Profiling a trace |
| 344 | ----------------- |
| 345 | |
| 346 | You can perform gpu and cpu profiling with the command line options: |
| 347 | |
| 348 | * `--pgpu` record gpu times for frames and draw calls. |
| 349 | |
| 350 | * `--pcpu` record cpu times for frames and draw calls. |
| 351 | |
| 352 | * `--ppd` record pixels drawn for each draw call. |
| 353 | |
| 354 | The results from these can then be read by hand or analyzed with a script. |
| 355 | |
| 356 | `scripts/profileshader.py` will read the profile results and format them into a |
| 357 | table which displays profiling results per shader. |
| 358 | |
| 359 | For example, to record all profiling data and utilise the per shader script: |
| 360 | |
| 361 | apitrace replay --pgpu --pcpu --ppd foo.trace | ./scripts/profileshader.py |
| 362 | |
| 363 | |
| 364 | Advanced usage for OpenGL implementors |
| 365 | ====================================== |
| 366 | |
| 367 | There are several advanced usage examples meant for OpenGL implementors. |
| 368 | |
| 369 | |
| 370 | Regression testing |
| 371 | ------------------ |
| 372 | |
| 373 | These are the steps to create a regression test-suite around **apitrace**: |
| 374 | |
| 375 | * obtain a trace |
| 376 | |
| 377 | * obtain reference snapshots, by doing on a reference system: |
| 378 | |
| 379 | mkdir /path/to/reference/snapshots/ |
| 380 | apitrace dump-images -o /path/to/reference/snapshots/ application.trace |
| 381 | |
| 382 | * prune the snapshots which are not interesting |
| 383 | |
| 384 | * to do a regression test, use `apitrace diff-images`: |
| 385 | |
| 386 | apitrace dump-images -o /path/to/test/snapshots/ application.trace |
| 387 | apitrace diff-images --output summary.html /path/to/reference/snapshots/ /path/to/test/snapshots/ |
| 388 | |
| 389 | |
| 390 | Automated git-bisection |
| 391 | ----------------------- |
| 392 | |
| 393 | With tracecheck.py it is possible to automate git bisect and pinpoint the |
| 394 | commit responsible for a regression. |
| 395 | |
| 396 | Below is an example of using tracecheck.py to bisect a regression in the |
| 397 | Mesa-based Intel 965 driver. But the procedure could be applied to any OpenGL |
| 398 | driver hosted on a git repository. |
| 399 | |
| 400 | First, create a build script, named build-script.sh, containing: |
| 401 | |
| 402 | #!/bin/sh |
| 403 | set -e |
| 404 | export PATH=/usr/lib/ccache:$PATH |
| 405 | export CFLAGS='-g' |
| 406 | export CXXFLAGS='-g' |
| 407 | ./autogen.sh --disable-egl --disable-gallium --disable-glut --disable-glu --disable-glw --with-dri-drivers=i965 |
| 408 | make clean |
| 409 | make "$@" |
| 410 | |
| 411 | It is important that builds are both robust, and efficient. Due to broken |
| 412 | dependency discovery in Mesa's makefile system, it was necessary to invoke `make |
| 413 | clean` in every iteration step. `ccache` should be installed to avoid |
| 414 | recompiling unchanged source files. |
| 415 | |
| 416 | Then do: |
| 417 | |
| 418 | cd /path/to/mesa |
| 419 | export LIBGL_DEBUG=verbose |
| 420 | export LD_LIBRARY_PATH=$PWD/lib |
| 421 | export LIBGL_DRIVERS_DIR=$PWD/lib |
| 422 | git bisect start \ |
| 423 | 6491e9593d5cbc5644eb02593a2f562447efdcbb 71acbb54f49089b03d3498b6f88c1681d3f649ac \ |
| 424 | -- src/mesa/drivers/dri/intel src/mesa/drivers/dri/i965/ |
| 425 | git bisect run /path/to/tracecheck.py \ |
| 426 | --precision-threshold 8.0 \ |
| 427 | --build /path/to/build-script.sh \ |
| 428 | --gl-renderer '.*Mesa.*Intel.*' \ |
| 429 | --retrace=/path/to/glretrace \ |
| 430 | -c /path/to/reference/snapshots/ \ |
| 431 | topogun-1.06-orc-84k.trace |
| 432 | |
| 433 | The trace-check.py script will skip automatically when there are build |
| 434 | failures. |
| 435 | |
| 436 | The `--gl-renderer` option will also cause a commit to be skipped if the |
| 437 | `GL_RENDERER` is unexpected (e.g., when a software renderer or another OpenGL |
| 438 | driver is unintentionally loaded due to a missing symbol in the DRI driver, or |
| 439 | another runtime fault). |
| 440 | |
| 441 | |
| 442 | Side by side retracing |
| 443 | ---------------------- |
| 444 | |
| 445 | In order to determine which draw call a regression first manifests one could |
| 446 | generate snapshots for every draw call, using the `-S` option. That is, however, |
| 447 | very inefficient for big traces with many draw calls. |
| 448 | |
| 449 | A faster approach is to run both the bad and a good OpenGL driver side-by-side. |
| 450 | The latter can be either a previously known good build of the OpenGL driver, or a |
| 451 | reference software renderer. |
| 452 | |
| 453 | This can be achieved with retracediff.py script, which invokes glretrace with |
| 454 | different environments, allowing to choose the desired OpenGL driver by |
| 455 | manipulating variables such as `LD_LIBRARY_PATH`, `LIBGL_DRIVERS_DIR`, or |
| 456 | `TRACE_LIBGL`. |
| 457 | |
| 458 | For example, on Linux: |
| 459 | |
| 460 | ./scripts/retracediff.py \ |
| 461 | --ref-env LD_LIBRARY_PATH=/path/to/reference/OpenGL/implementation \ |
| 462 | --retrace /path/to/glretrace \ |
| 463 | --diff-prefix=/path/to/output/diffs \ |
| 464 | application.trace |
| 465 | |
| 466 | Or on Windows: |
| 467 | |
| 468 | python scripts\retracediff.py --retrace \path\to\glretrace.exe --ref-env TRACE_LIBGL=\path\to\reference\opengl32.dll application.trace |
| 469 | |
| 470 | |
| 471 | Advanced GUI usage |
| 472 | ================== |
| 473 | |
| 474 | qapitrace has rudimentary support for replaying traces on a remote |
| 475 | target device. This can be useful, for example, when developing for an |
| 476 | embedded system. The primary GUI will run on the local host, while any |
| 477 | replays will be performed on the target device. |
| 478 | |
| 479 | In order to target a remote device, use the command-line: |
| 480 | |
| 481 | qapitrace --remote-target <HOST> <trace-file> |
| 482 | |
| 483 | In order for this to work, the following must be available in the |
| 484 | system configuration: |
| 485 | |
| 486 | 1. It must be possible for the current user to initiate an ssh session |
| 487 | that has access to the target's window system. The command to be |
| 488 | exectuted by qapitrace will be: |
| 489 | |
| 490 | ssh <HOST> glretrace |
| 491 | |
| 492 | For example, if the target device is using the X window system, one |
| 493 | can test whether an ssh session has access to the target X server |
| 494 | with: |
| 495 | |
| 496 | ssh <HOST> xdpyinfo |
| 497 | |
| 498 | If this command fails with something like "cannot open display" |
| 499 | then the user will have to configure the target to set the DISPLAY |
| 500 | environment variable, (for example, setting DISPLAY=:0 in the |
| 501 | .bashrc file on the target or similar). |
| 502 | |
| 503 | Also, note that if the ssh session requires a custom username, then |
| 504 | this must be configured on the host side so that ssh can be |
| 505 | initiated without a username. |
| 506 | |
| 507 | For example, if you normally connect with `ssh user@192.168.0.2` |
| 508 | you could configure ~/.ssh/config on the host with a block such as: |
| 509 | |
| 510 | Host target |
| 511 | HostName 192.168.0.2 |
| 512 | User user |
| 513 | |
| 514 | And after this you should be able to connect with `ssh target` so |
| 515 | that you can also use `qapitrace --remote-target target`. |
| 516 | |
| 517 | 2. The target host must have a functional glretrace binary available |
| 518 | |
| 519 | 3. The target host must have access to <trace-file> at the same path |
| 520 | in the filesystem as the <trace-file> path on the host system being |
| 521 | passed to the qapitrace command line. |