# Dynamic Tile Sorting

Since version 1.0, Chromium supports dynamic tile sort configuration. This means that the subdivision of the mural into tiles can be changed dynamically at runtime; the number of tiles and tile sizes are not fixed.

## How it works

New tiling information can be specified either by the application program or by a special function in the Python configuration script.

An application may specify new tile information when its window is resized and/or if the application is trying to do load balancing.

Otherwise, a user-defined tile-layout function in the Python script will be called by the tilesort SPU when the tilesort's `tilesortspu_WindowSize()` function is called. This function would typically be called by the application stub when Chromium's `track_window_size` option is enabled.

Finally, the tilesort SPU itself can do a simple tile re-allocation in response to window size changes if neither of the above solutions are used.

## Application-controlled tile configuration

An application can specify new tiles to the tilesort SPU by calling

glChromiumParametervCR(GL_TILE_INFO_CR, GL_INT, count, params);

once for each server. The `params` array is built as follows:

params[0] = the server index in [0, number of servers - 1];
params[1] = new mural width;
params[2] = new mural height;
params[3] = number of tiles on this server (may be zero);
params[4] = first tile's x coord;
params[5] = first tile's y coord;
params[6] = first tile's width;
params[7] = first tile's height;
params[8] = second tile's x coord;
params[9] = second tile's y coord;
params[10] = second tile's width;
params[11] = second tile's height;
...
params[4 * n + 4] = tile n's x coord;
params[4 * n + 5] = tile n's y coord;
params[4 * n + 6] = tile n's width;
params[4 * n + 7] = tile n's height;

The `count` parameter is the total number of elements in the `params` array. It should be 4 + 4 * number-of-tiles.

If there are (for example) four servers connected to the tilesort SPU you'll have to call `glChromiumParametervCR()` four times, once per server. You would typically do this when your application detects that the window size has changed, or when you want to reconfigure the mural for better load balancing.

Look at progs/retile/retile.c for an example of this technique.

## Config script-controlled tile configuration

If you define a tile layout function in the Python configuration script, you can avoid modifying your application program.

Here is an example:

def LayoutTiles(muralWidth, muralHeight):
"""Return list of tuples of new tiles for the given mural size.
Each tuple is of the form (serverIndex, x, y, width, height)."""
# always create four tiles, two per server
w = muralWidth / 2
h = muralHeight / 2
tile0 = ( 0, 0, 0, w, h ) # lower-left
tile1 = ( 1, w, 0, muralWidth - w, h ) # lower-right
tile2 = ( 1, 0, h, w, muralHeight - h ) # upper-left
tile3 = ( 0, w, h, muralWidth - w, muralHeight - h ) # upper-right
# construct the results list
tiles = []
tiles.append( tile0 );
tiles.append( tile1 );
tiles.append( tile2 );
tiles.append( tile3 );
return tiles

In this simple example, we divide the mural into four tiles and assign them to two servers.

The layout function always takes two parameters: the new mural width and height in pixels. The layout function must return a list of tuples of the form `(serverIndex, x, y, width, height)` which describes all the tiles. An empty list is legal.

To register this function with the tilesort SPU, do the following:

tilesortspu.TileLayoutFunction( LayoutTiles )

Now the tilesort SPU will call your Python tile layout function when its internal `tilesortspu_WindowSize()` function is called. This is described in more detail in the next section.

Look at mothership/configs/reassemble.conf for an example of this technique.

You'll likely need a more sophisticated layout function than the one shown above. You may elect to use one of the predefined layout functions in mothership/server/tilelayout.py. These functions take extra arguments beyond `LayoutTiles()` so you'll have to provide a simple wrapper function which provides those arguments.

## Other configuration details

If you want Chromium to monitor the application window's size and call the tile layout function you'll need to set the `track_window_size` option, like this:

cr.Conf( 'track_window_size', 1 )

This tells the Chromium OpenGL stub library to poll the application window's size whenever `glClear()` or `glViewport()` are called. If the window size changes, the head SPU (typically the tilesort) `WindowSize()` function will be called with the new window size.

If your Chromium configuration is a tile reassember which uses the readback SPU, it's usually desirable to have the tail render SPU render back into the application window, rather than the SPU's private window. This can be accomplished by setting the `render_to_app_window` option for the render SPU. For example:

renderspu.Conf( 'render_to_app_window', 1 )

Again, see mothership/configs/reassemble.conf for an example of this.