Chapter 12. ClipTextures

As CPUs get faster and storage gets cheaper, applications are moving away from scenes with small, synthetic textures to large textures, taken from real environments, giving the viewer realistic renderings of actual locations.

There has customarily been a trade-off between the complexity of a texture and the area it covers: if a texture covers a large area, its resolution must be limited so that it can fit into texture memory; high-resolution textures are limited to small regions for the same reason.

A cliptexture allows you to circumvent many of these system resource restrictions by virtualizing MIPmapped textures. Only those parts of the texture needed to display the textured geometry from a given location are stored in system and texture memory. OpenGL Performer provides support for this technique, called cliptexturing, as a subclass of a pfTexture called a pfClipTexture. This functionality allows you to display textures too large to fit in texture memory or even in system memory; you can put the entire world into a single texture.

OpenGL Performer supports texture load management from disk to system memory and from system to texture memory, synchronizing clipped regions with the viewpoint, and many the other tasks needed to virtualize a texture relative to the viewer location.

This chapter describes cliptextures in the following parts:

Overview

Cliptexturing avoids the size limitations of normal MIPmaps by clipping the size of each level of a MIPmap texture to a fixed area, called the clip region. A MIPmap contains a range of levels, each four times the size of the previous one. If the clip region is larger than a particular level, the entire level is kept in texture memory. Levels larger than the clip region are clipped to the clip region's size. The clip region is set by the application, trading off texture memory consumption against image quality. The clip region size is set through the clip size, which is the length of the sides (in texels) of the clip region's sides.

Figure 12-1. Cliptexture Components


The clip region positioned so as to be centered about the clip center, or as close as possible to the clipcenter while remaining entirely within the cliptexture. The clipcenter is set by the application, usually to the location on the texture corresponding to the location closest to the viewer on the cliptextured geometry. The clipcenter is specified in texel coordinates, which is the texture coordinates (s and t values, ranging from 0.0 to 1.0, scaled by the dimensions of the finest level of the cliptexture, level 0).

Cliptexture Levels

Texture memory contains the MIPmap levels, the larger ones clipped to the clip region size; the rectangle of texture memory corresponding to each clipped level is called a tex region. As the viewer moves relative to the cliptextured geometry, the clipcenter must be updated. When this happens, the clipped MIPmap levels must have their texture data updated, in order to represent the area closest to the center. This updating usually must happen every frame, and is done by OpenGL Performer image caches.

To facilitate loading only portions of the texture at a time, the texture data must first be subdivided into a contiguous set of rectangular areas, called tiles. These tiles can then loaded individually from disk into texture memory.

Texture memory must be loaded from system memory; it can't be loaded directly from disk. In order to improve the performance of texel downloading, the region in system memory is made larger than the destination texture memory and organized into a lookahead cache, called the mem region.

Figure 12-2. Image Cache Components


Image caches must know three things in order to update clipped texture levels:

  • Where and how the data is stored on disk, so they can retrieve it,

  • Location and size of system memory cache, called the mem region,

  • The texture memory they are responsible to update when the cilpcenter moves (the tex region).

Cliptexture Assumptions

For the cliptexture algorithm to work seamlessly, applications must abide by the following assumptions:

  • An application can only view a clip region's worth of high resolution texel data on its textured geometry from any viewpoint.

  • The application views the texture from one location at a time. Multiple views require multiple cliptextures.

  • The viewer must move smoothly relative to the cliptextured geometry; no “teleporting” (abrupt changes in position).

Given these assumptions, your application can maintain a high-resolution texture by keeping only those parts of the texture closest to the viewer in texture memory; the remainder of the texture is on disk and cached in system memory.

Why Do These Assumptions Work?

Only the textured geometry closest to the viewer needs a high-resolution texture. Far away objects are smaller on the screen, so the texels used on that object also appear smaller (cover a smaller screen area). In normal MIPmapping, coarser MIPmap levels are chosen as the texel size gets smaller relative to the pixel size. These coarser levels contain less texels, since each texel covers a larger area on the textured geometry.

Cliptextures take advantage of this fact by storing only part of each large MIPmap level in texture memory, just enough so that when you look over the geometry, the MIPmap algorithm starts choosing texels from a lower level (because the texels are getting small on the screen) before you run out of texels on the clipped level. Because coarser levels have texels that cover a larger area, at a great enough distance, MIPmapping is choosing texels from the unclipped, smaller levels.

When a clip size is chosen, cliptexture levels can be thought of as belonging to one of two categories:

  • C lipped levels, which are texture levels that are larger than the clip size.

  • N on-clipped levels, which are small enough to fit entirely within the clip region.

The non-clipped levels are viewpoint independent; each non-clipped texture level is complete. Clipped levels, however, must be updated as the viewer moves relative to the textured geometry.

Image Cache

The image cache organizes its system memory as a grid of fixed size texture tiles. This grid of texture data forms a lookahead cache, called the mem region. The cache automatically anticipates texture download requirements, updating itself with texture tiles it expects to use soon.

Image caches update texture memory by transferring image data from disk files. The data is transferred in two steps. Data is moved from disk files a tile at a time into the mem region in system memory. The mem region is updated so that it always contains the image data corresponding to the tex region and its immediate surroundings. The border of extra surrounding data allows the image cache to update the tex region as necessary without having to wait for tiles to be loaded into the mem region from disk.

The image cache also contains a tex region, the rectangle of texel data in a given level's texture memory. This rectangle of data is in texture memory, and is being updated from a corresponding rectangle of data in the memregion. As the center moves, the tex region being loaded into texture memory can get close to the edge of the mem region. When this happens, tiles in the mem region are updated with new data from disk so that the tex region is moved closer to the center of the image data.

Figure 12-3. Mem Region Update


As the center moves, the clipped region on each clipped level of the image cache shifts position. The clipped regions on each level move at different rates; each coarser level only moves at one half the speed of the level above it. The image cache reflects the change on its level by tracking the position of the clipped region with its tex region. Data in texture memory must be updated to match the texel data in the translated tex region.

This updating is done by copying rectangles of texel data from the shifted tex region area in the mem region to the appropriate locations in texture memory. The amount of updating is minimized by only updating the portions of the texture memory that actually need new data. The majority of the tex region data only has to shift position in texture memory; this is done by translating texture coordinates, and taking advantage of the wrap mode when accessing texels from texture memory.

Figure 12-4. Tex Region Update


By loading textures to system memory before they are needed in texture memory, the latency caused by waiting for tiles downloading from a disk is reduced.

  1. Texture data on disk is cached into system memory in an image cache's mem region.

  2. Texture data in the tex region part of the mem region is used to update texture memory.

    Figure 12-5. Cliptexture Cache Hierarchy


Toroidal Loading

In order to minimize the bandwidth required to download texels from system to texture memory, the image cache's tex regions are updated using toroidal loading. A toroidal load assumes that changes in the contents of the clip region are incremental, such that the update consists of:

  • New texels that need to be loaded.

  • Texels that are no longer valid.

  • Texels that are still in the clip region, but have shifted position.

Toroidal loading minimizes texture downloading by only updating the part of the texture region that needs new texels. Shifting texels that remain visible is not necessary, since the coordinates of the clip region wrap around to the opposite side.

Invalid Borders

Being able to impose alignment requirements to the regions being downloaded to texture memory improves performance. Cliptextures support the concept of an invalid border to provide this feature. It is the area around the perimeter of a clip region that can't be used. The invalid border shrinks the usable area of the clip region, and can be used to dynamically change the effective size of the clip region. Shrinking the effective clip size can be a useful load control technique.

When texturing requires texels from a portion of an invalid border at a given MIPmap level, the texturing system moves down a level, and tries again. It keeps going down to coarser levels until it finds texels at the proper coordinates that are not in the invalid region. This is always guaranteed to happen, since each level covers the same area with less texels (coarser level texels cover more area on textured geometry). Even if the required texel is clipped out of every clipped level, the unclipped pyramid levels will contain it.

You can use an invalid border to force the use of lower levels of the MIPmap to do the following:

  • Reduce the abrupt discontinuity between MIPmap levels if the clip region is small: using coarser LODs blends MIPmap levels over a larger textured region.

  • Improve performance when a texture must be roamed very quickly.

Since the invalid border can be adjusted dynamically, it can reduce the texture and system memory loading requirements at the expense of a blurrier image.

Figure 12-6. Invalid Border


Updating the Clipce nter

To figure out what part of the texture must be loaded in each of the clipped levels, you must know where the viewer is relative to the geometry being textured. Often this position is computed by finding the location of the cliptextured geometry that is closest to the viewer, and converting that to a location on the texture. This position is called the cliptexture center and it must be updated every frame as the viewer moves relative to the cliptextured geometry.

Figure 12-7. Clipcenter Moving


The clipcenter is set by the application for level 0, The cliptexture code then derives the clipcenter location on all MIPmap levels. As the viewer roams over a cliptexture, the centers of each MIPmap level move at a different rate. For example, moving the clipcenter one unit corresponds to the center moving one half that distance in each dimension in the next-coarser MIPmap level.

Most of the work of cliptexturing is updating the center properly and updating the texture data in the clipped levels reliably and efficiently each frame.

Virtual Cliptextures

Cliptextures save texture memory by limiting the extent of texture levels. Every level in the mipmap is represented in texture memory, and can be accessed as the geometry is textured. There are limits to the number of levels the cliptexturing hardware can access while rendering, which restricts the cliptextures maximum size.

This limit can be exceeded by only accessing a subset of all the MIPmap's levels in texture memory on each piece of geometry, “virtualizing” the cliptexture. The virtual offset is sets a virtual “level 0” in the MIPmap, while the number of effective levels indicates how many levels starting from the new level 0 can be accessed. The minlod and maxlod parameters are used to ensure that only valid levels are displayed. The application typically divides the cliptextured terrain into pieces, using the relative position of the viewer and the terrain to update the parameter values as each piece is traversed.

Figure 12-8. Virtual Cliptexture Concepts


For more information about virtual cliptextures, see “Virtual ClipTextures”.

Cliptexture Support Requirements

Ideally, pfClipTextures would be interchangeable with pfTextures in OpenGL Performer. Unfortunately, this is only partially true. The following sections describe some of the differences between OpenGL Performer textures and cliptextures.

Centering

Every level is complete in a regular texture. Cliptextures have clipped levels, where only the portion of the level near the cliptexture center is complete. In order to look correct, a cliptextures center must be updated as the channel's viewport moves relative to the cliptextured geometry.

Cliptextures require functionality that recalculates the center position whenever the viewer moves (essentially each frame). This means that a relationship has to exist between the cliptexture and a channel.

Applying

Textures only need to be applied once. Cliptextures must be applied every time the center moves (essentially each frame). In order to apply at the right time, cliptextures need to be connected to a pfPipe.

Texel Data

A texture does not know where its data comes from. The application just supplies it as a pointer to a region of system memory when the texture is applied.

Cliptextures need to update their contents as the center moves and they are reapplied each frame. As a result, they need to know where their image data resides on the disk. In order to maximize performance, cliptextures also cache their texel data in system memory. As a result, cliptextures are a lot more work to configure, since you have to tell them how to find their data on disk, and how you want the data cached in system memory.

Special Features

Since cliptexture levels are so large, OpenGL Performer offers additional features not available to regular textures.

Insets

With certain restrictions, cliptexture levels can be partially populated, containing “islands” of high resolution data. This can be useful if the application only needs high-resolution texel data in relatively small, widely scattered areas of a large cliptexture. An example of this might be an airline flight simulator, where high resolution data is only needed in the vicinity of the airports used by the simulator.

For more information about insets, see “Cliptexture Insets”.

Virtualization

To further increase the size of cliptextures that OpenGL Performer can use, the levels themselves can be virtualized; It then selects a subset of all the available texture levels to be loaded into memory. This requires additional support by the application. Virtual cliptextures are described in detail in “Virtual ClipTextures”.

Multiple Pipe Support

Since cliptextures require both system and texture memory resources, OpenGL Performer has provided functionality to share the system memory resources when a cliptexture is used in a multipipe application. “Slave” cliptextures and a “master” cliptexture share system memory resources, but have their own classes and texture memory.

How Cliptextures Interact with the Rest of the System

As a result of their special requirements, cliptextures are used differently than pfTextures with many different OpenGL Performer classes. The following sections describe these differences.

Geostates

When everything is configured properly, a pfClipTexture is interchangeable with a pfTexture when used in a geostate.

Pipes

A pfClipTexture can be connected to a pfMPClipTexture, a multiprocessing component, which is connected to a pfPipe. From the pipe's point of view, a pfMPClipTexture is something it can apply to.

Channels

Some functionality must be supplied to update a cliptexture's center as the channel moves with respect to the cliptextured geometry. This functionality can be supplied by the application, or OpenGL Performer can do it automatically if the application uses clipcenter nodes.

A clipcenter node is added to the scenegraph and is traversed by the APP process just like every other node in the scenegraph. pfMPClipTexture, which contains the cliptextured geometry, should be a child node of the clipcenter node. When the clipcenter node is traversed by a channel, the clipcenter node computes the relationship between the cliptextured geometry and the channel's eyepoint, and updates the cliptexture's center appropriately.

Cliptexture Support in OpenGL Performer

Cliptexture is a large and diverse piece of functionality. As a result, cliptexture support is found in nearly every major library in OpenGL Performer.

libpr Support

The pfImageCache class defines image caches which manage the updating of clipped levels, pfImageTile classes are used to define non-clipped cliptexture levels and define pieces of clipped levels downloaded from disk to system memory. The pfQueue class supports read queues, which manage the read requests from disk to system memory in image caches, while the pfClipTexture class itself defines cliptextures themselves, virtual mipmaps composed of image caches and image tile levels. The pfTexLoad class defines download requests when image caches download texels from system to texture memory.

libpf Support

The libpf library adds multiprocessing support for using cliptextures in scene graphs. the pfMPClipTexture class ties together pfClipTextures, pfPipes, cliptexture centering functionality (often pfuClipCenterNode nodes) and the application itself in a multiprocessing environment. additional functionality in the pfPipe class ensures that cliptextures are applied properly.

libpfutil Support

The libpfutil library provides easy to use clipcentering functionality through the pfuClipCenterNode class, a subclass of the pfGroup class. This library also provides traversals to simplify the work of finding cliptextures in a scene graph using pfuFindClipTextures(), code for post loader configuration, where pfMPClipTextures are created, and attached to pipes and clipcenter nodes using pfuProcessClipCenters() and pfuProcessClipCentersWithChannel(). The pfuAddMPClipTextureToPipes() and pfuAddMPClipTexturesToPipes() routines connect pfMPClipTextures to the proper pipes, handling multipipe issues in a clean way. Load time configuration is simplified using the pfuInitClipTexConfig(), pfuMakeClipTexture(), and pfuFreeClipTexConfig() along with the appropriate callbacks for image caches and image tiles. Image cache configuration is supported with pfuInitImgCacheConfig(), pfuMakeImageCache(), and pfuFreeImgCacheConfig() routines.

libpfdu Support

The cliptexture configuration file parsers are supported here; pfdLoadClipTexture() and pfdLoadClipTextureState() work with cliptexture configuration files to simplify the creation and configuration of cliptextures. The companion programs that create and configure pfdLoadImageCache() and pfdLoadImageCacheState(). All of these parsers use the pfuMakeClipTexture() and pfuMakeImageCache() configuration routines.

libpfdb Support

Example cliptexture loaders, including the libpfim example cliptexture loader, the libpfct demo loader and libpfvct virtual pseudo loader are all included here.

Cliptexture Manipulation

While the scene graph is being viewed, the application may want to dynamically alter the appearance or performance characteristics of the cliptexture. The mpcliptexture provides functionality to support parameter changes in the APP process, providing frame-accurate updating. Here are some of the parameters that might be changed.

Load Cont rol

The DTR functionality (described in detail elsewhere in this chapter) is largely automatic. Some high performance applications may need to adjust DTR parameters to improve appearance performance trade-offs.

Invalid Border

The invalid border can be adjusted at runtime to shrink the effective size of the clip region. This might be done to provide additional load control beyond the per-level control that DTR provides.

S hare Masks

When operating master and slave cliptextures in a multipipe application, the application may want to change the sharemask, which controls the synchronization of parameters between master and slave cliptextures.

Read Function

The image cache creates requests to read image tiles from disk to the image cache's system memory cache. The read function processes these requests and actually does the data transfer. OpenGL Performer provides set of read functions that attempts to do direct-IO reads for speed, but falls back to normal reads if direct IO is not possible.

The application can replace the OpenGL Performer default function with its own custom read function. This could be useful for implementing special functionality, such as dynamic decompression pfClipTexture data.

Read Queue Sorting

The read queue provides dynamic sorting of the read requests to improve performance and minimize latency. The application can provide custom sorting routines.

Cliptexture API

Cliptexturing has a large API. Not only is there are lot of cliptexture functionality scattered throughout the library, but there is often more than one way to use a particular piece of functionality. In order to make things clearer, and make it easier to use the API described here, the cliptexture API is grouped and ordered in the same way an application writer would use it.

The API is grouped into four sections:

  • Preprocessing the cliptexture data.

  • Configuring cliptextures and image caches.

  • Post-load-time configuration.

  • Run-time manipulation.

Preprocessing ClipTextures

Before using cliptextures, large textures must be preprocessed, as follows:

  1. Start with the highest-resolution version of the image (texture) and build a MIPmap of the image.

  2. Choose a clip size.

  3. Tile each MIPmap level.

    Every image that is larger than the clip size must be cut into tiles. All of the tiles in one MIPmap level must be equal in size. You generally choose a tile size that is about 1/4 of the clip size or less.

  4. Divide the levels into separate files to maximize download performance.

    The files should be named properly so that the image caches can access them.

  5. If the configuration parsers are used, cliptexture configuration files are also created at this time.

The following sections describe the steps in this procedure in greater detail.

Building a MIPmap

Building a MIPmap of an image requires an algorithm that performs the following tasks:

  1. Start with the highest-resolution version of the image (texture). The image dimensions in pixels must be in powers of 2, for example, 8192 X 8192.

  2. Average every four adjacent texels of a high resolution image into a single texture (essentially blurring it and shrinking it by a factor of two in both dimensions).

  3. Save the result as a new, blurrier, smaller image.

  4. Convert the MIPmaps into a compatible format.

  5. Repeat the first two steps with each blurrier image until you have a single texel whose color is the average of all the texel colors in the original image.

Each successive reduction is called a level of detail (LOD). The more the reduction, the higher the level of detail, the coarser the image.

There are a variety of tools that tile textures. OpenGL Performer provides some simple ones available in the /usr/share/Performer/src/tools directory. They are listed in Table 12-1.

Table 12-1. Tiling Algorithms

Program

Description

rsets

Shrinks and tiles one or more .rgb image files recursively. rsets stops tiling when it reaches the clip size you give it. rsets assumes that the original image is square.

rgb2raw

Converts .rgb images into a raw format that can be downloaded directly into texture memory. Files should be in a raw format to avoid conversions at download time.

shrink

Is a subset of rsets functionality; makes a tree-like structure of LOD images from an .rgb image.

to5551

Converts from .rgb to the 5551 raw format.

to888

Converts from .rgb to the 888 raw format.

to8888

Converts from .rgb to the 8888 raw format.

viewtile

Enables you to view a raw format image tile.

For more information about MIPmaps, see the OpenGL Programming Guide.

Formatting Im age Data

The texel data must be in a format that can be used in OpenGL Performer textures. This means the texels must have contiguous color components, whose size and type match a supported format. Keep in mind that these texels will be loaded dynamically, on an as-needed basis, so the smaller the size of each texel, the better the performance of the cliptexture. You should choose the smallest texel format that provides acceptable color quality. A good choice might be RGBA 5551, which takes up 16 bits per texel. OpenGL Performer provides some tools for converting from rgb format to 5551 or 888 RGBA. They are named to5551 and to888 and are found in /usr/share/Performer/src/tools.

For more information about file formats, see “Building a MIPmap”.

Tiling an Im age

Dividing a texture into tiles allows you to look at a subset of all texels in the texture. In this way, you can selectively download from disk into the texture memory only those texels that the user is viewing and those they might soon look at. Since downloading texture tile files from disk to texture memory takes a long time, the image cashes decide which tiles a viewer might need next and download them in advance.


Note: In the highest resolution LOD, one texel corresponds to one pixel.

T exel tiles in each level are loaded into memory separately, from coarsest to finest. The high-resolution tiles take longer to download than the coarser tiles. If a viewer advances through a scene so quickly that the high-resolution tiles cannot download from disk into texture memory in time, lower-resolution tiles are displayed instead. The effect is that if the viewer goes too fast, the tiles become blurry. When the viewer slows down, the tiles displayed are less coarse.

Using lower instead of higher-resolution levels is controlled by cliptexture's load control mechanism, DTR. Without DTR, OpenGL Performer waits for all of the levels to download before displaying any one of them. DTR removes this restriction, displaying the levels that have been downloaded.

If you want to break up a .rgb image into tiles, OpenGL Performer provides the subimg program in /usr/share/Performer/src/tools.

Tile Size

Small tiles, while less efficient, are better at load leveling, since the time it takes to load a new tile into system memory is smaller. It also means that the total size of an image cache in system memory can be smaller. We've found that tile sizes of 512 x 512 and 1024 x 1024 provide a good trade-off between download efficiency and low latency, but download performance is very sensitive to system configuration. Experimenting is the best way to find a good tile size.

Cliptexture Configuration

After preprocessing the texture data, you need to configure cliptextures. Configuration is actually a two step process; the configuration that can be done by the scenegraph loader, and the configuration that requires pfPipes and pfChannels to be present. This section describes the first stage of configuration.

Configuration Considerations

An application must configure the cliptexture in two steps:

  • Loader—when the scene graph is constructed.

  • Post-loading—when the channel and pipes are known to the application.

This process is complex. OpenGL Performer supplies a number of utilities to make the job easier.

To manipulate cliptexture parameters, the application makes calls to the pfMPClipTexture in the APP process. The pfMPClipTexture updates the cliptexture in a frame-accurate manner.

Load-Time Configuration

This is the time the scene graph is being constructed. Geostates are pointed to cliptextures; the cliptextures themselves are created and configured using the cliptexture configuration files and the libpfdu parsers. If the application does its own configuration, it should use the libpfutil routines to simplify the process and to ensure adequate error checking. If the application opts to use OpenGL Performer clipcentering support, clipcenter nodes are inserted into the scene graph at the root of the cliptextured geometry and connected to the corresponding cliptexture.

Post-Load-Time Configuration

At this stage the scene graph has been created and the channels and pipes have been defined. The libpfutil traversers ( pfuProcessClipCenters() or pfuProcessClipCentersWithChannel()) are used to create pfMPClipTextures, connecting them with the appropriate cliptextures and clipcenter nodes. These routines return a list of pfMPClipTextures, which can be used to with pfuAddMPClipTextureToPipes() and pfuAddMPClipTexturesToPipes() to attach the pfMPClipTextures to the appropriate pfPipes. These routines can be used for single pipe and multipipe applications with little or no change to the calling sequence.

Configuration API

Since cliptexture configuration is complex, we provide three different cliptexture configuration API layers, allowing different trade-offs between flexibility and simplicity.

libpr Functionality

The lowest layer, using the libpr calls, is the most complex and difficult. A cliptexture has the same configuration requirements as a MIPmapped pfTexture, where texel format, type and texture dimensions must be configured. In addition, cliptextures have to know about system memory caching, the file configuration of the texture data, load control, read queue, and other cliptexture specific configurations.

Using the libpr layer directly is not recommended, since it is error prone and does not buy much flexibility compared to the libpfutil configuration routines. In the following subsections are the libpr calls you must consider when configuring a cliptexture directly.

These are the functions needed to configure the cliptexture itself. The cliptexture contains two types of levels: image cache levels and image tile levels. Image caches support clipped levels in a cliptexture. They know where their texture data resides on disk, they understand clip regions, and set up system memory caching and updating. Every properly-configured image cache points to an image tile, called a proto tile, which contains global information about the texel format, size, and file information about the image tiles the image cache uses to update clipped texture levels.

Configuring an Image Cache Level

Image tiles can be used by themselves to represent unclipped levels. Essentially the unclipped level is represented by a single tile covering the entire level. Because image tiles do not understand clip regions and cannot do dynamic updating, image tiles cannot be used to represent clipped levels.

To configure an image cache level, use the following calls:

  • pfNewClipTexture()

  • pfTexName()

  • pfClipTextureVirtualSize()

  • pfClipTextureClipSize()

  • pfTexImage()

  • pfTexFormat()

  • pfClipTextureInvalidBorder()

  • pfClipTextureEffectiveLevels()

  • pfClipTextureAllocatedLevels()

  • pfClipTextureLevel()

Configuring an Image Cache Proto Tile

There are also image tile calls in this sequence. They are used to configure the image cache's proto tile, which is used as a template for the tiles the image cache will use to load texel data from disk to system memory cache.

To configure an image cache proto tile, use the following calls:

  • pfNewImageTile()

  • pfImageTileReadFunc()

  • pfGetImageTileMemInfo (page size)

  • pfImageTileMemInfo()

  • pfImageTileReadQueue()

  • pfImageTileHeaderOffset()

  • pfImageTileNumFileTiles()

  • pfImageTileSize()

  • pfImageTileFileName()

  • pfImageTileFileImageType()

  • pfImageTileMemImageType()

Configuring an Image Cache

To configure an image cache, use the following calls:

  • pfImageCacheName()

  • pfImageCacheTexRegionOrigin()

  • pfImageCacheMemRegionOrigin()

  • pfImageCacheImageSize()

  • pfImageCacheMemRegionSize()

  • pfImageCacheTileFileNameFormat()

  • pfImageCacheTexRegionSize()

  • pfImageCacheMemRegionSize()

  • pfImageCacheTex()

  • pfImageCacheTexSize()

  • pfImageCacheFileStreamServer()

  • pfImageCacheProtoTile()—Copies the information into the image cache's proto tile.

  • pfDelete (tmp_proto_tile)—Now that it is copied into the image cache, you can delete it.

Configuring a pfTexture

Image caches can be used independently of cliptextures, if they are, they need to be associated with a pfTexture, and that texture needed to be configured.

To configure a pfTexture, use the following calls:

  • pfTexImage()

  • pfTexFormat()

Configuring the Default Tile

Image caches can have a de fault tile defined, which is the tile to use if a tile on disk can't be found. Default tiles can be useful for “filling in” border regions of a cliptexture level. Default tiles are covered in more detail in section “default_tile”.

To configure the default tile, use the following calls:

  • pfNewImageTile()

  • pfCopy() (proto to default)

  • pfImageTileFileName()

  • pfImageTileReadQueue()

  • pfImageTileDefaultTile()

Configuring Image Tiles

Image tiles need their own configuration, since they need to know about the file they should load from texel formats, etc.

To configure an image tile, use the following calls:

  • pfNewImageTile()

  • pfImageTileMemImageFormat()

  • pfImageTileFileImageFormat()

  • pfImageTileMemImageType()

  • pfImageTileSize()

  • pfImageTileHeaderOffset()

  • pfClipTextureLevel()

  • pfLoadImageTile()

Configuration Utilities

Using the libpr calls to configure a cliptexture is difficult and error prone. OpenGL Performer provides utilities to make cliptexture configuration easier and more robust. The configuration utility API is broken into two groups. One group is used to configure cliptextures, the other configures image caches. Each group contains three functions, an init function, a config function, and a free function. These functions work with a structure that the application fills in.

The initialize function initializes the optional fields in the structure with default values, and the mandatory fields with invalid values. Configuring the structure allows the configuration function to do more error checking, and to allow the application to avoid the tedium of filling in optional field. The application then sets fields in the structure to parameterize how the cliptexture or image cache should be configured. The application then calls the configuration function on the filled in structure. The free function is then called with the structure to ensure that all allocated values are freed.

Cliptexture Configuration

Methods to configure the cliptexture include the following:

pfuInitClipTexConfig(pfuClipTexConfig *config) 

Initialize the values of the pfuClipTexConfig structure that has been allocated by the application.

pfuMakeClipTexture(pfuClipTexConfig *config) 

Return a cliptexture configured as directed by the values in the pfuClipTexConfig structure.

pfuFreeClipTexConfig(pfuClipTexConfig *config)  

Free any malloc'd structures that the application or the initialize function may have created.

Image Cache Configuration

Methods to configure the image cache include the following:

pfuInitImgCacheConfig(pfuImgCacheConfig *config) 

Initialize the values of the pfuClipTexConfig structure that has been allocated by the application.

pfuMakeImageCache(pfuImgCacheConfig *config) 

Return a cliptexture configured as directed by the values in the pfuClipTexConfig structure.

pfuFreeImgCacheConfig(pfuImgCacheConfig *config) 

Free any malloc'd structures that the application or the init() function may have created.

All of these functions are defined in libpfutil/cliptexture.c. The structures themselves are defined in pfutil.h.

Filling in the Structures

Filling the pfuImgCacheConfig structure to create and configure the image cache is considerably simpler than setting fields in the pfuClipTexConfig structure. This is because the cliptexture configuration must also create and configure image cache and image tiles to populate its levels. The configuration code does this supplying a function pointer to configure the image cache levels and a function pointer for configuring image tile levels. Each function pointer also has a void data pointer so you can pass data to the functions. The function pointers expect functions with the following forms:

pfImageCache *exampleICacheConfigFunction(pfClipTexture *ct,
    int level, struct _pfuCilpTexConfig *icInfo)
 
pfImageTile *exampleITileConfigFunction(pfClipTexture *ct, 
    int level, struct _pfuClipTexConfig *icInfo)

The cliptexture and image cache configuration parsers, described in the next section, use the configuration utilities. You can look at the parsers as example code. For example, you may want to look at  pfdLoadImageTileFormat() and pfdLoadImageCache() formats for example functions for the function pointers. The parsers are in the /usr/share/Performer/src/lib/libpfdu/pfdLoadImage.c file.

Configuration Files

The easiest and most commonly used method to configure cliptextures is to create cliptexture and image cache configuration files, then use the configuration parsers to create and configure cliptextures. The configuration files can be created and stored along with the texture data files. Configuration files allow an application or loader to simply call a single function to create and configure cliptextures.

Configuration files are ascii text files containing a token parameter format. Values are separated by white space and the token parameter sequences can be placed in the file in arbitrary order. Comments can also added to the configuration files, making them self-documenting.

Using Configuration Files

Four parser functions are available to create and configure cliptextures and image caches using configuration files:

pfClipTexture *pfdLoadClipTexture(const char *fileName)
 
pfImageCache *pfdLoadImageCache(const char *fileName)

These parser functions take a configuration file name, and use it to configure and create a cliptexture or an image cache respectively. The cliptexture configuration file may refer to image cache configuration files, which will be searched for and used automatically.

Two other versions of these parsers also take a pointer to a configuration utility structure. This allows you to preconfigure using the configuration structure and then finish with the parser and configuration files.

pfClipTexture *pfdLoadClipTextureState(const char *fileName,
    pfuClipTexConfig *state)
 
pfImageCache *pfdLoadImageCacheState(const char *fileName,
    pfuImgCacheConfig *state)

The parsers use OpenGL Performer's pfFindFile() functionality to search for the configuration files. The parsers support environment variable expansion and relative pathnames to make it simpler to create configuration files that refer to other configuration or data files.

Creating Configuration Files

To successfully use cliptextures, you must first prepare the texture data and create the configuration files:

  1. Create an image cache configuration file for each level using an image cache in the cliptexture.

    The configuration file should describe the following:

    • Format and tiling of the texture data.

    • Location and names of the files containing the texture data.

    • Size of the tex region in texture memory.

    • Size and layout of the mem region in system memory.

  2. Create a cliptexture configuration file.

    It contains the following:

    • Name and location of each image cache configuration file.

    • Names and locations of the texture data for each image tile level in the cliptexture. Remember, image tile levels cannot be clipped levels; so, they can only be used in the pyramid levels. Image cache levels can be used anywhere.

    • General properties of the cliptexture.

    • Look at the example cliptexture configuration files in the /usr/share/Performer/data/clipdata directory. The cliptexture configuration files use the .ct suffix. The image cache configuration files use .ic for their suffixes.

  3. Test the image cache configuration files individually, using the pguide/libpr/C/icache program.

  4. Test the cliptexture configuration file using the /pguide/libpr/C/cliptex or the /pguide/libpf/C/cliptex programs

  5. When the configuration and data files are complete and tested, your application can create and configure a cliptexture by calling pfdLoadClipTexture(fname) using the name of the cliptexture configuration file. If more control is needed, you can use pfdLoadClipTextureState(fname, state) initializing and configuring the configuration utility cliptexture structure, pfuClipTexConfig.

Configuration File Tips

Unfortunately, cliptexture configuration is not trivial, even with documentation and example programs. Success in creating working configuration files requires a two-prong approach:

  • Keep them simple: set the minimum number of fields possible. Take advantage of default value. Try to find a similar example configuration file to copy from.

  • Work bottom-up: create and test image cache configuration files first, gradually building up to the cliptexture configuration file.

We have found that parameterized naming of the image caches and tile files works the best. If you have named your files consistently, this can be easy. If things do not work, you can fall back and name your file explicitly as a sanity check. Read the error messages carefully; they try to point out where in the configuration file the parser found problems. If you need more information, try rerunning the program with PFNFYLEVEL set to 5 or 9.

A number of example configuration files and cliptextures are available on the OpenGL Performer release. Working from one of them can save a lot of time. Some places to look are the following:

  • data/clipdata/hunter 

  • data/clipdata/moffett 

  • data/asddata 

Cliptexture Loaders

Finally, your application might be able to take advantage of some of the cliptexture loaders. The libpfim loader supports loading a cliptexture, and updating its center as a function of viewposition. The libpfct loader creates a cliptexture with simple terrain. Virtual cliptextures, mentioned in “Virtual ClipTextures”, can also be created using the libpfspherepatch or  libpfvct loaders. These loaders can be used as examples if you need to write your own loader that supports cliptextures.

Image Cache Configuration File Details

I mage cache configuration files supply the following information to OpenGL Performer:

  • Format of the texel data.

  • Size of the entire texture at a particular MIPmap level.

  • How to find the files containing the texel data for this image cache.

  • Size and layout of image cache tiles in memory.

  • Size of the image cache that should be kept in texture memory.

  • A default image tile to use if one is missing.

  • The size each level should be clipped to.

  • The amount of border that should be invalidated at each level.

  • How to find the image cache configuration files

  • How to find the tiles comprising the levels that are not image caches

Configuration Fields

C onfiguration fields are either tokens or parameter values, as listed in Table 12-2. All fields are character strings and all parameters must be separated by white space. The token names marked with an asterisk (*) are optional and default to reasonable values.

Table 12-2. Image Cache Configuration File Fields

Token Name

Parameters

Description

ic_version2.0

no data field

Start of image cache config files: type and version

*tex_size

3 integers

Area of tex memory for level if not tex_region_size

*header_offset

integer

Beginning of file to skip over in bytes

*tiles_in_file

3 integers

Dimensions of grid of tiles stored in each file

*s_streams

filepath list

List of streams used to access files in S dimension

*t_streams

filepath list

List of streams used to access files in T dimension

*r_streams

filepath list

List of streams used to access files in R dimensions

*default_tile

filepath string

Tile to use if expected tile is not available

*page_size

integer

System page size; memory allocation alignment

*read_func

1 or 2 strings

Custom read function; library, func or func in app

*lookahead

integer

Extra tiles in mem region for lookahead caching

ext_format

string

External format of stored texels

int_format

string

Internal format used by graphics hw

img_format

string

Image format of stored texels

icache_size

3 integers

Size of complete image level in texels

tex_region_size

3 integers

Area to load in texture memory; matches clip size

mem_region_size

3 integers

Dimensions of system memory cache in tiles

tile_size

3 integers

Dimensions of each file in texels

tile_format

scanf-style string

Parameterized path to tile files

tile_params

list of symbols

Parameter types in order in tile_format string


Image Cache Configuration File Description

The ic_version2.0 token must be first in an image cache configuration file. This token identifies the file as an image cache configuration file and the format (version) of the configuration file.

Next the parser looks for tokens and any associated data values. In general, the order of the tokens in the file must follow the sequence specified in the table above. The tokens marked with an asterisk are optional. Optional tokens have default values, which are used if the token and value are omitted.Tokens can have the following:

  • No arguments

  • A fixed number of arguments

  • A variable number of arguments

If a token has a fixed number of arguments, the token must be followed by a white space-separated list containing the specified number of arguments. If the token has a variable number of arguments, one of its arguments specifies the number of arguments used.

Any time a token is expected by the parser, a comment can be substituted. A comment cannot be put anywhere in the file, however. For example, if a token expects arguments, you cannot place a comment between any of them; you have to place it after all of the previous tokens arguments. There are a variety of supported comment tokens; they are interchangeable. The comment tokens are #, //, ;, comment, or rem.

ext_format, int_format, and img_format

One of the first things that must be specified in an image cache is the format of the texel data. This includes the external format (ext_format), internal format (int_format) and image format (img_format). The arguments expected by these format parameters are the ASCII string names of the format's enumerates. For example, a valid external format would be ext_format PFTEX_FLOAT. Consult the pfTexture man pages for a list of the valid formats of each type.

icache_size, mem_region_size, and tex_region_size

The next set of parameters that must be specified in the image cache configuration file is its size on disk, in system memory, and in texture memory. The icache_size token requires the size of the image cache. This means the dimensions, in texels, in the s, t, and r dimensions of the complete texture at this level. Since three dimensional textures are not currently supported, the r parameter will always be 1.

An image cache's texels are organized into a set of fixed sized pieces, called tiles. Both in system memory and on disk, the texels are broken up this way. At any given time, an array of these texel tiles are cached in system memory. They are arranged as an array in system memory. If the center of the image cache nears the edge of this array, the most distant tiles are dropped out, and new tiles are read in from disk. The larger the array of tiles in system memory, the more of the complete texture is cached there, and the less likely new tiles may need to be swapped in. The benefit is offset by the cost of tying up more system memory to hold the texel tiles.

The arrangement and dimensions of tiles in system is defined for each image cache, and is set with the mem_region_size token. This token expects three arguments which determine the number of tiles in the s, t, and r dimensions of the grid. Since three dimensional textures aren't currently supported, the r dimension is always 1.

A subset of the texels in system memory are cached in the texture memory itself. These texels are arranged in a rectangular region. The dimensions of this region are defined by the tex_region_size token. It expects three arguments, the number of texels in the s, t, and r dimensions. Again, since three dimensional textures are not supported, the r value is always 1.

The image cache configuration file allows some leeway in the arrangement of texel tiles on disk. There can be one or more tiles on each disk file, and the file itself could contain non-texel information at the beginning of the file. The tiles themselves can have user-specified dimensions. While there is some flexibility in how tiles are stored in files on disk, there are restrictions also. Any header must be the same size for every file in an image cache. The same is true for the tile size, and the number and layout of tiles in each file. If there is more than one tile in a file, the tiles must be arranged in row-major order. In other words, as you pass from the first tile to the last, the s dimension must be incrementing fastest.

tile_format and tile_params

The image cache texel data is stored in one or more files. The configuration file provides a way for OpenGL Performer to find these files. The files usually have similar names, varying in a predictable way, such as by tile position in the image cache array and size of the image cache. The files themselves are grouped in on or more directories. The file name and file path information is divided into a number of groups within the configuration file. There is a scanf-style string specifying the path to find image cache files. There are a number of parameters in the string that vary as a function of the tile required and the characteristics of the image cache.

The next group of tokens describes the location of the configuration files defining the location of the texture data tiles for the image cache. You can define the texture tile configuration filenames with a scanf-style string containing parameter values, as is done with image caches. To create parameterized image cache names, you must define the tile_format and tile_params tokens.

The tile_format token is followed by a scanf-style string describing the file path and filename of the image cache configuration files. The argument contains constant parts, interspersed with %d or %s parameters. The number of parameters must match the number of symbols supplied as parameters to the tile_params token. If the tile_format string starts with the pattern $ENVNAME, ${ENVNAME}, or $(ENVNAME), then the value of ENVNAME will be assumed to be an environment variable and expanded into the base name.

The possible values of the image tile file name parameters is given in the table below.

Table 12-3. Image Tile Filename Tokens

Image Tile Filename Tokens

Description

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_S

Virtual size S width

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_T

Virtual size T width

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_R

Virtual size R width

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_S

Tiles from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_T

Tiles from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_R

Tiles from origin in R

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_S

Texels from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_T

Texels from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_R

Texels from origin in R

PFIMAGECACHE_TILE_FILENAMEARG_STREAMSERVERNAME

From streams

PFIMAGECACHE_TILE_FILENAMEARG_CACHENAME

The tile_base value

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_S

Files from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_T

Files from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_R

Files from origin in R


header_offset, tiles_in_file, and tile_size

The header_offset argument specifies the size of the file's header in bytes. This many bytes will be skipped over as a file is read. The tiles_in_file token requires three arguments, specifying the number of tiles in the s, t, and r dimensions. The r dimension must always be 1, since 3D textures are not supported. The tile_size parameter defines the texel dimensions of each tile in s, t, and r. Again, r must be 1. Both the header_offset and the tiles_in_file tokens are optional. They default to the values 0 and 1 1 1, respectively, specifying no header and a single tile in each file.

One of the major bottlenecks to sustained cliptexture performance is the speed of copying texels from disk to system memory. Cliptextures can be configured to maximize the bandwidth of this transfer by distributing image tiles over multiple disks and downloading them in parallel. The streams section of the configuration file is used for this purpose.

num_streams, s_streams, t_streams, and r_streams

A stream, short for stream device, can be thought of as a separate disk that can be accessed in parallel with other disks. Each disk is mounted in a file system and, therefore, has a unique filepath segment. The streams tokens allow you to identify these stream filepath segments and how the image tiles are distributed among them. The stream devices are arranged in a three dimensional grid with s, t, and r dimensions just like the image tiles are in memory. The stream device is accessed by taking the position of the tile, counting tiles from the origin in the s, t, and r directions, and generating a coordinate, modulo the number of stream devices in the corresponding s, t, and r directions. The s, t, and r values generated are used to look up the appropriate stream device. If the stream server name is part of the tile file name format string, it effects which disk is used to find the tile.

Stream servers improve bandwidth at the expense of duplicating image tiles over multiple disks. You must insure that the proper image tiles are available for any disk which is addressed by the tile's s, t, and r coordinates modulo the available number of stream servers for each of those dimensions. The stream server tokens are optional. The s_streams token is followed by a list of filepaths. These are the names that will be indexed from the list by taking the s coordinate of the tile's position in the image cache grid, modulo the number of s stream devices. The names in the s_stream list do not have to be unique.

The t_streams and r_streams tokens work in exactly the same way, in the t and r directions, respectively.

Sometimes only a subregion of the entire cliptexture is of interest to the application. This is especially true when you consider that the number of tiles in the s, t, and r directions must all be a power of two. To save space, improve performance, and make creating image caches more convenient, a default tile can be defined, and tiles of no interest can simply be omitted. If a tile cannot be found and a default tile is defined, then the default one is used in place of the missing one.

default_tile

Unlike normal tiles, which are read from disk as they are needed, the default tile is loaded as part of the configuration process. The tile is named in the configuration file as the argument to the default_tile token. The argument is a filepath to the default tile. If the tile_base token has been defined, it is pre-pended to the file path; otherwise, it is used as is.

Cliptexture Configuration File Details

Image cache configuration files supply the following information to OpenGL Performer:

  • format of the texel data

  • size of the entire texture at a particular MIPmap level

  • how to find the files containing the texel data for this image cache

  • size and layout of image cache tiles in memory

  • size of the image cache that should be kept in texture memory

  • a default image tile to use if one is missing

  • the size to which each level should be clipped

  • the amount of border that should be invalidated at each level

  • how to find the image cache configuration files

  • how to find the tiles consisting the levels that are not image caches

Configuration Fields

Configuration fields are either tokens or parameter values, as listed in Table 12-4. All fields are character strings and all parameters must be separated by white space.

Table 12-4. Cliptexture Configuration File Fields

Token Name

Parameters

Description

# or // or ; or comment

comment

comment symbols; comment to end of line

ct_version2.0

no data field

the beginning of the file: type and version

ext_format

string

external format of stored texels

int_format

string

internal format used by graphics hw

img_format

string

image format of stored texels

virt_size

3 integers

size of complete texture at level 0 (finest level)

clip_size

integer

size of clip region square for clipped levels

*invalid_border

integer

width of clip region perimeter to not use

*tile_size

3 integers

size of tiles (used when if no icache config files)

*smallest_icache

3 integers

smallest icache-level dimensions

*lookahead

integer

extra tiles in mem region

*icache_format

scanf string

icache fnames: no field? list files

*effective_levels

integer

levels used for texturing in virtual cliptexture

*icache_params

string list

format tokens in order

*icache_files

list of filenames

only if icache_format is default

*tile_files

list of filenames

pyramid; only if tile_format default

*effective_levels

integer

levels used for texturing in virtual cliptexture

*allocated_levels

integer

total virtual cliptexture levels in texture memory

*header_offset

1 integer

byte offset to skip user's file header

*tiles_in_file

3 integers

Image tile arrangement in each file

*read_func

1 or 2 strings

custom read function; lib & func or func in app

*tile_format

scanf string

Tile filename format

*tile_params

string list

format parameter tokens in order

*page_size

integer

system page size; memory allocation alignment


Cliptexture Configuration File Description

The ct_version2.0 token must be first in an cliptexture configuration file. This token identifies the file as an cliptexture configuration file and the format (version) of the configuration file.

Next the parser looks for tokens and any associated data values. In general, the order of the tokens in the file must follow the sequence specified in the table above. The tokens marked with an asterisk are optional. Optional tokens have default values, which are used if the token and value are omitted.

Tokens can have the following:

  • no arguments

  • afixed number of arguments

  • avariable number of arguments

If a token has a fixed number of arguments, the token must be followed by a white space-separated list containing the specified number of arguments. If the token has a variable number of arguments, one of its arguments specifies the number of arguments used.

Any time a token is expected by the parser, a comment can be substituted. A comment can't be put anywhere in the file, however. For example, if a token expects arguments, you can't place a comment between any of them; you have to place it after all of the previous tokens arguments. There are a variety of supported comment tokens; they are interchangeable. The comment tokens are #, //, ;, comment, or rem.

ext_format, int_format, and img_format

One of the first things that must be specified in a cliptexture is the format of the texel data. This includes the external format (ext_format), internal format (int_format) and image format (img_format). The arguments expected by these format parameters are the ASCII string names of the format's enumerates. For example, a valid external format would be ext_format PFTEX_FLOAT. Consult the pfTexture man pages for a list of the valid formats of each type.

virt_size and clip_size

The next group of tokens characterizes the image cache itself. The virt_size token expects three integer arguments. They define the s, t, and r dimensions of the level 0 layer of the cliptexture in texels. The clip_size token describes the size of each layer that exists in texture memory. It also takes three integers, describing the s, t, and r dimensions of the clipped region. This value is the same for all levels of a cliptexture. If the image cache configuration files' clip_size differs from this value, the cliptexture overrides it.

invalid_border

The invalid_border defines the region of each clipped level that should not be used. If a texel is needed in that region, the next level down is used instead. If the invalid border is large, the system may have to go down multiple levels, or even down to the pyramidal, unclipped part of the MIPmap. The invalid border argument is a single integer, describing the width of the border in texels.

smallest_icache

The smallest_icache token describes the s, t, and r dimensions of the lowest level that is described as an image cache. This parameter is needed because the unclipped, pyramidal part of the MIPmap can also be configured as image caches. This is an optional token. If it is not included in the file, the last clipped level is considered the smallest image cache in the cliptexture.

icache_files, icache_format and icache_params

The next group of tokens describes the location of the configuration files defining the image cache levels of the cliptexture. There are two methods of describing where the image cache configuration files. You can explicitly list the filenames in order with icache_files.

The other method is to define the image cache configuration filenames with a scanf-style string containing parameter values, as is done with image caches. This is usually the preferred method. To create parameterized image cache names, you must define the icache_format and icache_params tokens. If the format string starts with the pattern $ENVNAME, ${ENVNAME} or $(ENVNAME), then the value of ENVNAME will be assumed to be an environment variable and expanded into the base name.

The icache_format token is followed by a scanf-style string describing the file path and filename of the image cache configuration files. The argument contains constant parts, interspersed with %d or %s parameters. The number of parameters must match the integer given with the num_icache_params token. The tile parameters themselves follow the icache_params token.

icache_files

The number of parameters must match the number of parameters in icache_format. All of these parameters are optional. The list of available parameter tokens is given in Table 12-5.

Table 12-5. Parameter Tokens

Parameter Token Name

Description

PFCLIPTEX_FNAMEARG_LEVEL

Cliptexture level (top is 0)

PFCLIPTEX_FNAMEARG_LEVEL_SIZE

Largest value of level's virtual size

PFCLIPTEX_FNAMEARG_IMAGE_CACHE_BASE

Value of icache_base

PFCLIPTEX_FNAMEARG_TILE_BASE

Value of tile_base

Uniquely naming that file for each level of the cliptexture, the parameter values are used to construct the name of the image cache configuration file.

Near the bottom of the cliptexture, the size of lower levels are too small to warrant image caches. These levels are specified directly, referring to a single filename containing a single image tile for each level. The filenames for these tile files are specified in exactly the same way as the image cache configuration files are. Instead of icache_base, icache_format, num_icache_parameters, and icache_parameters, tile_base, tile_format, num_tile_parameters, and tile_parameters are used. The parameters available for use in the tile_format string are identical to the ones used for icache_format.

tile_files

If image cache configuration files and/or image tiles are to be explicitly named, they are listed in order, from the top (largest) level to the bottom, using the icache_files and tile_files tokens. These tokens can only be used if the corresponding format, num_parameters, and parameter tokens are not. The number of filenames listed after icache_files and tile_files must exactly match the number of cached and uncached levels, respectively, in the cliptexture.

header_offset, tiles_in_file, and tile_size

The header_offset argument specifies the size of the file's header in bytes. This many bytes will be skipped over as a file is read. The tiles_in_file token requires three arguments, specifying the number of tiles in the s, t, and r dimensions. The r dimension must always be 1, since 3D textures are not supported. The tile_size parameter defines the texel dimensions of each tile in s, t, and r. Again, r must be 1. Both the header_offset and the tiles_in_file tokens are optional. They default to the values 0 and 1 1 1, respectively, specifying no header and a single tile in each file.

The image cache texel data is stored in one or more files. The configuration file provides a way for OpenGL Performer to find these files. The files usually have similar names, varying in a predictable way, such as by tile position in the image cache array and size of the image cache. The files themselves are grouped in on or more directories. The file name and file path information is divided into a number of groups within the configuration file. There is a scanf-style string specifying the path to find image cache files. There are a number of parameters in the string that vary as a function of the tile required, and characteristics of the image cache.

tile_base, tile_format and tile_params

The tile_format token expects a scanf-style argument. If the string starts with the pattern $ENVNAME, ${ENVNAME} or $(ENVNAME), then the value of ENVNAME will be assumed to be an environment variable and expanded into the base name.

The argument contains constant parts, interpersed with %d or %s parameters.The tile parameters themselves follow the tile_params token. The number of parameters must match the number of parameters in tile_format.

The possible values of the image tile file name parameters are given in the table below.

Table 12-6. Image Tile Filename Tokens

Image Tile Filename Tokens

Description

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_S

Virtual size S width

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_T

Virtual size T width

PFIMAGECACHE_TILE_FILENAMEARG_VSIZE_R

Virtual size R width

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_S

Tiles from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_T

Tiles from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_TILENUM_R

Tiles from origin in R

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_S

Texels from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_T

Texels from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_TILEORG_R

Texels from origin in R

PFIMAGECACHE_TILE_FILENAMEARG_STREAMSERVERNAME

From streams

PFIMAGECACHE_TILE_FILENAMEARG_CACHENAME

The tile_base value

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_S

Files from origin in S

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_T

Files from origin in T

PFIMAGECACHE_TILE_FILENAMEARG_FILENUM_R

Files from origin in R


Optional Image Cache Configuration Files

If the cliptexture has a very regular structure from level to level, the cliptexture configuration file can be augmented with some extra fields, and the image cache configuration files dispensed with. We recommend you start with the image cache configuration files, however, because it makes it easier to gradually create and test your configuration files using the icache and cliptex utilities in the /usr/share/Performer/src/pguide/libpr/C directory.

Image cache configuration files can be removed if the image caches of the cliptexture are essentially the same, and configuration of each image cache is simple. The image caches should only different in size between levels; the tile size, formats, tile filename format, etc. should be the same. Also image cache configuration files are not optional when features like streams are configured.

To stop using image cache configuration files, you should add a tile_size token to the cliptexture configuration file, and be sure to have tile_format and tile_params specified.The tile specification in the cliptexture configuration file will be used for all tile files the ones used by the image caches and the ones in representing pyramid levels.

In order to make the parser stop using the image cache configuration files, remove the entries referring to them such as icache_format, icache_params, or icache_tiles.

An example of a cliptexture configuration file that does not use image cache configuration files is /usr/share/Performer/data/clipdata/hunter/hl.noic.ct.

Post-Scene Graph Load Configuration

There are a number of cliptexture configuration steps that cannot be completed until the OpenGL Performer application's pipes and channels have been created. This configuration stage centers around configuring cliptextures to be properly applied and centered each frame.

Two jobs must be accomplished. Each cliptexture must be attached to a pipe through its own pfMPClipTexture so it can be applied each frame, and a centering callback must be established to update the cliptexture as the channel's viewpoint moves with respect to the cliptextured geometry.

MPClipTextures

pfMPClipTexture is a multiprocess wrapper for a pfClipTexture. A pfMPClipTexture allows you to do the following:

  • Change the center of the pfClipTexture in the APP process.

  • Automatically perform the necessary texture downloading (applying) in the CULL process.

  • Control the cliptexture parameters in the APP process.

    Figure 12-9. pfMPClipTexture Connections


Connecting MPcliptextures to pfPipes

To automatically apply of the pfClipTexture at the correct times and in the correct processes, you must do the following:

  1. Create a pfMPClipTexture object.

  2. Attach the pfMPClipTexture to the cliptexture you want to control.

  3. Attach the pfMPClipTexture object to a pfPipe using the pfPipe.


    Note: If you use pfMPClipTexture, you should never call either pfUpdateMPClipTexture() or pfApplyMPClipTexture(); the pfPipe should do the applying.


When you attach a pfMPClipTexture to a pfPipe using pfAddMPClipTextureToPipes() or pfAddMPClipTexturesToPipes(), pfPipe automatically updates and applies pfClipTexture at the correct time. The functions take three arguments: a pfMPClipTexture or list of pfMPClipTextures, a pipe to which to attach (called the master pipe), and a list of other pipes the application wants to use with the pfMPClipTextures.

  • pfAddMPClipTextureToPipes(pfMPClipTexture, masterpipe, pipe_list)

  • pfAddMPClipTexturesToPipes(pfMPClipTexture_list, masterpipe, pipe_list)

The pipe_list is used for multipipe applications. It is the list of pipes that slave pfMPClipTextures should attached to. Setting pipe_list to NULL is equivalent to adding slave pfMPClipTextures to every other pipe in the application.

There are additional libpf routines that can be useful:

  • pfRemoveMPClipTexture() detaches a pfMPClipTexture from a pfPipe. If a pfMPClipTexture is removed that is the master of other pfMPClipTextures, the slaves will be removed from their pipes as well.

  • pfGetNumMPClipTextures() returns the number of pfMPClipTextures attached to a pfPipe.

  • pfGetMPClipTexture() returns a pointer to the pfMPClipTexture that is attached to a pfPipe.

libpf Functionality

You can do this directly with the libpf API using the following calls:

  • pfNewMPClipTexture()—Create a new pfMPClipTexture.

  • pfMPClipTextureClipTexture()—Attach the pfMPClipTexture to the cliptexture.

  • pfAddMPClipTexture() - (a pfPipeCall)—Attach the pfMPClipTexture to a pipe.

  • pfMPClipTexturePipe()—Specifies to the pfMPClipTexture the pipe to which it is attached.

pfMPClipTexture Utilities

OpenGL Performer provides utilities to make it easy to attach pfMPClipTextures to pipes, and to automatically do pfMPClipTexture centering as well. As a bonus, the utility code requires little or no changes to convert a single pipe application to a multipipe one.

To use the pfMPClipTexture utilities, you need to use OpenGL Performer's clipcenter nodes to center the pfMPClipTexture. clipcenter nodes are a subclass of pfGroup nodes. They have additional functionality that allows them to connect to a pfMPClipTexture, the cliptextured geometry (through their child nodes), and properly update the pfMPClipTexture's center each frame. At load time, clipcenter nodes are placed at the root of the subtree containing the cliptextured geometry. All the cliptextures in the scene are created configured and attached to the clipcenter node at this time as well.

Once you have a scenegraph with geometry, cliptextures, and clipcenter nodes, it is easy to make pfMPClipTextures, attach them to pipes and to centering callbacks. The function pfuProcessClipCenters() traverses the scene graph, looking for clipcenter nodes. As each node is encountered, the function creates an MP cliptexture, attaches it to the associated cliptexture and the clipcenter node, and saves a pointer to the MP cliptexture in a pfList. When the function returns, it provides the list of MP cliptextures that were created. The pfuProcessClipCentersWithChannel() routine performs the same operations but also sets a channel pointer in the clipcenter node. When the channel pointer is set, the clipcenter node only will update a pfMPClipTexture center when that channel traverses it. This is useful for multichannel applications.

Clipcenter Node

In order for cliptextures to be rendered correctly, the clipcenter must move along with the viewer. OpenGL Performer has made this task simpler by providing a special node for the scene graph that does this calculation and applies it to the cliptexture each frame. This node, called the clipcenter node, is a subclass of a pfGroup node. In addition to pfGroup functionality, pfuClipCenterNode's can do the following:

  • Points to the cliptexture. This allows cliptextures to be attached to clipcenter nodes at load time.

  • Points to the geometry textured by the clipcenter node's cliptexture. The clipcenter node is assumed rooted in the subtree containing the cliptextured geometry.

  • Points to an optional simplified version of the cliptextured geometry to make centering calculations go faster.

  • Points to the pfMPClipTexture attached to the cliptexture. The node also has API to automatically create an pfMPClipTexture and attach it to the cliptexture.

  • Contains a replaceable post-APP callback function for updating a pfMPClipTexture's center.

  • Can point to a pfChannel and only update the pfMPClipTexture center only when that pfChannel traverses the clipcenter node.

    Figure 12-10. pfuClipCenterNode Connections


The clipcenter node uses a simple algorithm, setting the cliptexture center to be the point on the textured geometry closest to the viewer. Other algorithms can be substituted by replacing the callback function.

Clipcenter nodes can be created by calling the utility routine pfuNewClipCenterNode(). There are set and get functions to attach cliptextures, channels, custom centering callbacks, simplified cliptextured geometry, as well as a get to return the pfMPClipTexture. See the pfuClipCenterNode man page for details on the API.

The clipcenter node source code is available in pfuClipCenterNode.C and pfuClipCenterNode.h in the /usr/share/Performer/src/lib/libputil directory. It is implemented as a C++ class with C++ and C API. It also has example code illustrating to subclass the clipcenternode further to customize it.

If the configuration has been done properly, and if pfuClipCenterNodes have been used for centering, most of the per-frame operations for cliptextures is automatic. Centering is computed and applied by the clipcenter nodes during the APP traversal, and cliptexture application is automatically handled by the pfPipes attached to the pfMPClipTextures.

Using Cliptextures with Multiple Pipes

Cliptextures use a lot of texture memory, system memory (for their caches) and disk I/O bandwidth. Many multipipe applications produce multiple views from the same location, looking in different directions. It would be very inefficient to create a completely separate cliptexture for each pipe; although there is separate texture memory and graphics hardware from each pipe, the system memory and disk resources are shared by the entire system.

Cliptextures have been designed to support multipipe rendering without excessive drain on system memory and disk I/O bandwidth. Cliptextures that are to be used in multiple pipes can be split into master and slave cliptextures. The master cliptexture is complete; it contains an image cache and a region of texture memory to control. A slave cliptexture points to its master and shares its image cache, using it to download into its own texture memory. All the slave cliptextures share their master's system memory cache and disk I/O resources, reducing the load on the system.

Figure 12-11. Master and Slave Cliptexture Resource Sharing


Making Masters and Slaves

Master and slave relationships can be established between image caches, cliptextures, and pfMPClipTextures. The process starts with an object already configured you way you want it. Then another object of the same type is created and is set to be a slave of the configured object. This is done with the setMaster() function. When an object is made the slave of another object, it automatically configures itself to match it's master. It also makes all the connections necessary to share its master's resources.

If two cliptextures are made into a master and slave, all of their image caches must have the same master-slave relationship. This is done automatically. This is also true for pfMPClipTextures. The pfMPClipTextures that will be the master and slave must be connected to cliptextures. Only the masters have to be configured, however. When the other pfMPClipTexture becomes a slave, it configures its cliptexture and makes it and its image caches slaves as well.

Multipipe Cliptexture API

OpenGL Performer tries to make multipipe cliptexturing as transparent as possible. Simply call setMaster() on a cliptexture and pass it a pointer to the cliptexture that should be its master:

  • pfMPClipTexture *slave_mct = pfNewMPClipTexture() 

  • pfClipTexture *slave_ct = pfNewClipTexture() 

  • pfMPClipTextureClipTexture(slave_mct, slave_ct) 

  • pfMPClipTextureMaster(slave_mct, master_mct) 

master_mct is a pfMPClipTexture that is already configured.

At this point, slave_mct and master_mct are connected; slave_mct is configured to match master_mct and shares i's image cache resources. The cliptextures and image caches are also configured and linked. To make pfClipTextures or pfImageCaches masters and slaves, use the same procedure.

When you attach a pfMPClipTexture to a pfPipe with pfAddMPClipTexture() provides automatic multipipe support. If a pfMPClipTexture is added to a pipe that is already connected to another pipe, the function silently creates a new pfMPClipTexture, makes it a slave of the pfMPClipTexture that is already connected to another pipe, and adds the slave to the pipe in place of the one passed as an argument to the function.

Multipipe Utilities

Although it is not difficult to set up master and slave cliptextures directly, it is usually not necessary.The previously described utility routines, pfuAddMPClipTextureToPipes() and pfuAddMPClipTexturesToPipes() can take multiple pipe arguments. A master pipe and a list of slave pipes is specified. The routine makes the pfMPClipTexture a master and attaches it to the master pipe. It then creates slave pfMPClipTextures, attaches them to the master cliptexture, and attaches a slave cliptexture to each pipe in the slave pipes list. This routine does extra checking of pipe and cliptexture state, and is guaranteed not to generate errors, even if the function is applied more than once.

Master/Slave Share Masks

A group of cliptextures grouped by master-slave relationships can do more than share mem region resources. By default, slave cliptextures also track a number of their master's attribute values. This means changing a master's center, for example, automatically causes the slaves to change their center locations to match their master's. The attributes that a slave can track are divided into groups called share groups. The application can control which groups are shared by setting a slave's share mask. Changing the sharing of a slave only affects that slave's sharing with its master. Changing the master share mask has no effect. The share mask is set with the following call:


pfMPClipTextureShareMask(uint mask)

The mask can be set using one or more of the following values:

  • PFMPCLIPTEXTURE_SHARE_CENTER—Slaves track the master's center.

  • PFMPCLIPTEXTURE_SHARE_DTR—Slaves track DTR: DTR mode, tex load time (actual or calculated), fade count, and blur margin.

  • PFMPCLIPTEXTURE_SHARE_EDGE—Slaves track texture level parameters, LODbias invalid border.

  • PFMPCLIPTEXTURE_SHARE_LOD—Slaves track minLOD and maxLOD.

  • PFMPCLIPTEXTURE_SHARE_VIRTUAL—Slaves track lodOffset and num effective levels.

  • PFMPCLIPTEXTURE_SHARE_DEFAULT—A bit-wise OR of all the masks listed above.

PFMPCLIPTEXTURE_SHARE_DEFAULT is the default share-mask value, which provides maximum sharing between master and slave cliptextures. If an application would like to control one or more slaves independently, it needs to change the slave's share mask; then start setting the slaves parameters directly as needed.

Texture Memory and Hardware Support Checking

At the first application or formatting of a cliptexture, OpenGL Performer compares the expected size of the cliptexture texel data in texture memory against the systems texture memory size. If it looks like the cliptexture will not fit into texture memory, it shrinks the clip size by two and tries again. It will keep shrinking the clip size until either the cliptexture will fit or the clip size is zero. The system taking into account texture memory banking and paging to come up with a more accurate estimate.

Note that the resizing mechanism does not take into account other textures or cliptextures in use by the application. You should adjust your application so that OpenGL Performer does not have to auto-shrink the cliptexture. See “Estimating Cliptexture Memory Usage” for calculating cliptexture system memory and texture memory usage.

During the checking phase, OpenGL Perfor