* Using VirtualGL with Chromium
{anchor: Chromium}

Chromium is a powerful framework for performing various types of parallel
OpenGL rendering.  It is usually used on clusters of commodity Linux PC's to
divide up the task of rendering scenes with large geometries or large pixel
counts (such as when driving a display wall.)  Chromium is most often used in
one of three configurations:

	1. Sort-First Rendering (Image-Space Decomposition)
	2. Sort-First Rendering (Image-Space Decomposition) with Readback
	3. Sort-Last Rendering (Object-Space Decomposition)

** Configuration 1: Sort-First Rendering (Image-Space Decomposition)

#IMG: chromium-displaywall.png

Sort-First Rendering (Image-Space Decomposition) is used to overcome the
fill rate limitations of individual graphics cards.  When configured to use
sort-first rendering, Chromium divides up the scene based on which polygons
will be visible in a particular section of the final image.  It then instructs
each node of the cluster to render only the polygons that are necessary to
generate the image section ("tile") for that node.  This is primarily used to
drive high-resolution displays that would be impractical to drive from a single
graphics card due to limitations in the card's framebuffer memory, processing
power, or both.  Configuration 1 could be used, for instance, to drive a CAVE,
video wall, or even an extremely high-resolution monitor.  In this
configuration, each Chromium node generally uses all of its screen real estate
to render a section of the multi-screen image.

VirtualGL is generally not very useful with Configuration 1.  You could
theoretically install a separate copy of VirtualGL on each display node and use
it to redirect the output of each ''crserver'' instance to a separate VirtualGL
Client instance running on a multi-screen 2D X server elsewhere on the network.
However, synchronizing the frames on the remote end would require extensive
modifications to VirtualGL and perhaps to Chromium as well.  Such is left as an
exercise for the reader.

** Configuration 2: Sort-First Rendering (Image-Space Decomposition) with Readback

#IMG: chromium-sortfirst.png

Configuration 2 uses the same sort-first principle as Configuration 1, except
that each tile is only a fraction of a single screen, and the tiles are
recombined into a single window on Node 0.  This configuration is perhaps the
least often used of the three, but it is useful in cases where the scene
contains a large amount of textures (such as in volume rendering) and thus
rendering the whole scene on a single node would be prohibitively slow due to
fill rate limitations.

In this configuration, the application is allowed to choose a visual, create an
X window, and manage the window as it would normally do.  However, all other
OpenGL and GLX activity is intercepted by the Chromium App Faker (CrAppFaker)
so that the 3D rendering can be split up among the rendering nodes.  Once each
node has rendered its section of the final image, the image tiles are passed
back to a Chromium Server (CrServer) process running on Node 0.  This CrServer
process attaches to the previously-created application window and draws the
pixels into the window using ''glDrawPixels()''.

The general strategy for making this work with VirtualGL is to first make it
work without VirtualGL and then insert VirtualGL only into the processes that
run on Node 0.  VirtualGL must be inserted into the CrAppFaker process to
prevent CrAppFaker from sending ''glXChooseVisual()'' calls to the 2D X server
(which would fail if this X server did not support GLX.)  VirtualGL must be
inserted into the CrServer process on Node 0 to prevent it from sending
''glDrawPixels()'' calls to the 2D X server (which would similarly fail if the
2D X server didn't support GLX and which would create a performance issue if
the 2D X server was remote.)  Instead, VirtualGL forces CrServer to draw into a
Pbuffer, and VGL then takes charge of transmitting the pixels from the Pbuffer
to the 2D X server in the most efficient way possible.

As with any normal OpenGL application, CrServer can be launched using
''vglrun''.  However, because CrAppFaker also interposes OpenGL and GLX
functions, it must be handled differently in order to avoid interference with
VirtualGL.  Chromium provides an environment variable, ''CR_SYSTEM_GL_PATH'',
which allows one to specify an alternate path to be searched for ''libGL.so''.
On Linux and Unix systems, VirtualGL installs a symbolic link named
''libGL.so'', which points to the VirtualGL faker library (''librrfaker.so'').
This symbolic link is located in its own isolated directory, so that directory
can be passed to Chromium in the ''CR_SYSTEM_GL_PATH'' environment variable,
and this will cause Chromium to load VirtualGL rather than the "real" OpenGL
library.  Refer to the following table:

{anchor: CR_SYSTEM_GL_PATH_Table}
|| 32-bit Applications     || 64-bit Applications        ||
| ''/opt/VirtualGL/fakelib''   | ''/opt/VirtualGL/fakelib64''    |
#OPT: note="''CR_SYSTEM_GL_PATH'' setting required to use VirtualGL with Chromium" align=center

To run CrAppFaker, it is necessary to set this environment variable to the
appropriate value so that Chromium will load the interposed versions of OpenGL
and GLX functions from VirtualGL.  It is also necessary to set ''VGL_GLLIB'' to
the location of the "real" OpenGL library (example: ''/usr/lib/libGL.so.1'').
CrAppFaker creates its own fake version of ''libGL.so'', which is really just a
copy of Chromium's ''libcrfaker.so''.  Thus, if left to its own devices,
VirtualGL will unwittingly try to load ''libcrfaker.so'' instead of the "real"
OpenGL library.  Chromium's ''libcrfaker.so'' will, in turn, try to load
VirtualGL, and an endless loop will occur.

Therefore, we must use the ''CR_SYSTEM_GL_PATH'' environment variable to tell
Chromium to pass OpenGL commands into VirtualGL, then we must use the
''VGL_GLLIB'' environment variable to tell VirtualGL __not__ to pass OpenGL
commands into Chromium.  For example:

#Verb: <<---
export CR_SYSTEM_GL_PATH=/opt/VirtualGL/fakelib
export VGL_GLLIB=/usr/lib/libGL.so.1
crappfaker
---

CrAppFaker will copy the application into a temporary directory and then copy
''libcrfaker.so'' to that same directory, renaming it as ''libGL.so''.  So, when
the application is started, it loads ''libcrfaker.so'' instead of ''libGL.so''.
''libcrfaker.so'' will then load VirtualGL instead of the "real" OpenGL
library, because we've overridden ''CR_SYSTEM_GL_PATH'' to point to VirtualGL's
fake ''libGL.so''.  VirtualGL will then use the library specified in
''VGL_GLLIB'' to make any "real" OpenGL calls that it needs to make.

	!!! NOTE: ''crappfaker'' should not be invoked with ''vglrun''.

So, putting this all together, here is an example of how you might start a
sort-first rendering job using Chromium and VirtualGL:

	#. Start the mothership on Node 0 with an appropriate configuration for
		performing sort-first rendering with readback

	#. Start ''crserver'' on each of the rendering nodes

		!!! NOTE: ''crserver'' should be run on display :0 (or whichever display is
		attached to the 3D hardware.)

	#. On Node 0, ''vglrun crserver &''

	#. On Node 0, set the ''CR_SYSTEM_GL_PATH'' environment variable to the
		appropriate value based on whether ''crappfaker'' was
		compiled as a 32-bit or a 64-bit app (see table above)

	#. On Node 0, set ''VGL_GLLIB'' to the location of the "real" OpenGL
		library (example: ''/usr/lib/libGL.so.1'' or ''/usr/lib64/libGL.so.1'').

	#. On Node 0, launch ''crappfaker'' (do not use ''vglrun'' here)

Again, it's always a good idea to make sure this works without VirtualGL before
adding VirtualGL into the mix.

{anchor: Force_Pbuffer}
*** Using VirtualGL to Force Pbuffer Rendering
#OPT: noList! plain!

In the procedure above, VirtualGL can also be used on the rendering nodes to
redirect the rendering commands from ''crserver'' into a Pbuffer instead of a
window.  If you wish to do this, then perform the following procedure in place
of step 2 above:

On each of the rendering nodes,

	* set the ''VGL_READBACK'' environment variable to ''0''
	* ''vglrun crserver''

	!!! NOTE: You must configure each of the rendering nodes as a VirtualGL
	server (that is, run '''vglserver_config''' as instructed in
	{ref prefix="Chapter ": Unix_Config}) in order for this to work when
	the rendering nodes are sitting at the login prompt.

** Configuration 3: Sort-Last Rendering (Object-Space Decomposition)

#IMG: chromium-sortlast.png

Sort-Last Rendering is used when the scene contains a huge number of polygons
and the rendering bottleneck is processing all of that geometry on a single
graphics card.  In this case, each node runs a separate copy of the
application, and for best results, the application needs to be aware that it is
running in a parallel environment so that it can give Chromium hints as to how
to distribute the various objects to be rendered.  Each node generates an image
of a particular portion of the object space, and these images must be
composited in such a way that the front-to-back ordering of pixels is
maintained.  This is generally done by collecting Z buffer data from each node
to determine whether a particular pixel on a particular node is visible in the
final image.  The rendered images from each node are often composited using a
"binary swap", whereby the nodes combine their images in a cascading tree so
that the overall compositing time is proportional to log{,2}(N) rather than N.

To make this configuration work with VirtualGL:

	#. Start the mothership on Node 0 with an appropriate configuration for
		performing sort-last rendering

	#. Start ''crappfaker'' on each of the rendering nodes

		!!! NOTE: ''crappfaker'' should be run on display :0 (or whichever display
		is attached to the 3D hardware.)

	#. On Node 0, ''vglrun crserver''

*** CRUT
#OPT: noList! plain!

The Chromium Utility Toolkit provides a convenient way for graphics
applications to specifically take advantage of Chromium's sort-last rendering
capabilities.  Such applications can use CRUT to explicitly specify how their
object space should be decomposed.  CRUT applications require an additional
piece of software, ''crutserver'', to be running on Node 0.  Therefore, the
following procedure should be used to make these applications work with
VirtualGL:

	#. Start the mothership on Node 0 with an appropriate configuration for
		performing sort-last rendering

	#. Start ''crappfaker'' on each of the rendering nodes

		!!! NOTE: ''crappfaker'' should be run on display :0 (or whichever display
		is attached to the 3D hardware.)

	#. On Node 0, ''vglrun crutserver &''

	#. On Node 0, ''vglrun crserver''

** A Note About Performance

Chromium's use of X11 is generally not very optimal.  It assumes a very fast
connection between the 2D X server and the Chromium Server.  In certain modes,
Chromium polls the 2D X server on every frame to determine whether windows have
been resized, etc.  Thus, we have observed that, even on a fast network,
Chromium tends to perform much better with VirtualGL running in an X proxy
as opposed to using the VGL Transport.
