Display Connections

Display connections are used to receive tile data as a byte stream from a pipe or socket that is connected to a mental ray process running on the local or a remote machine. In principle, any number of simultaneous stream connections are supported by mental ray. In practice, one image pipe can be specified on mental ray command line, and the number of possible socket connections is determined by the number of image file outputs in the rendered scene.

mental ray runs a separate thread for tile display purposes parallel to rendering. It handles the communication and data transport through connections with external processes, as well as display callbacks to parent applications. This ensures that communication delays or even blocking has no noticeable performance impact on mental ray rendering. The rendered tiles are stored in mental ray frame buffers, thus they can be sent at any time, even if connections are established late like at the end of rendering.

The following section provides C-like pseudo-code examples for common tasks in tile display clients.

Examples

How to detect a valid socket file:

char buffer[128];

if (read(file, buffer, size(buffer)) == 128) {

        char    hostname[64];
        int     image_width = 0, image_height = 0;
    int     socketId = 0, processId = 0;
    float   gamma = 1.0f;

    /* expect ray3 protocol */

        if (sscanf(buffer, "ray3.3,%u,%u,%[^,],%d,%f,%d",
		&image_width, &image_height, hostname,
		&socketId, &gamma, &processId) == 6) {

	    ...	/* valid mental ray socket file */

                return true;
                }
        }

How to establish a socket connection to mental ray:

SOCKET connect_ray(const char *hostname, const int socketId)
{
    SOCKET socket_;
    struct sockaddr_in sadd;
    struct hostent *host;

    if ((host = gethostbyname(hostname)) == NULL)
	return INVALID_SOCKET;

    if ((socket_ = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
	return INVALID_SOCKET;

    memset(&sadd, 0, sizeof(sadd));
    memcpy(&sadd.sin_addr, host->h_addr, host->h_length);

    sadd.sin_family = host->h_addrtype;
    sadd.sin_port   = htons(socketId);

    if (connect(socket_, (void *)&sadd, sizeof(sadd)) == SOCKET_ERROR) {
	close(socket_);
	return INVALID_SOCKET;
	}

return socket_;	/* successful connection */
}

How to decode the tile packet header received from a socket or pipe:

typedef struct {
    int left; int right; int top; int bottom;
} RECT;

int buffer[5], op;

if (read(streamId, buffer, sizeof(buffer)) == sizeof(buffer)) {

/* convert integers to local host byte order */

op              = ntohl(buffer[0]);
rect->left      = ntohl(buffer[1]);
rect->right     = ntohl(buffer[2]);
rect->top       = ntohl(buffer[3]);
rect->bottom    = ntohl(buffer[4]);

switch(op) {
	case 5: /* pipe header */
		...	/* read header */
		break;

	case 6:	/* new frame */
		frame_number = rect->left;
		...	/* possibly clear display */
		break;

	case 2: /* tile data */
		...	/* read tile into local buffer */
		break;

	case 4: /* image completed */
		...	/* refresh display */
		break;

	case 3: /* rejected */
		break;

	default: /* unknown op-code */
		break;
	}
}

How to decode the tile image data received from a socket or pipe:

unsigned int byte_width = image_width * 4; /* RGBA pixel format */

read_tile(
RECT	*rect,	/* tile position and size */
miUchar	*image) /* image buffer in RGBA pixel format */
{
    unsigned int    x, y;
    unsigned int    tsize = (rect->right - rect->left + 1) * 4;
    unsigned char	*taskbuf = malloc(tsize)); /* one line in tile */
    unsigned char   *c;

    for (y = rect->bottom; y <= rect-="">top; y++) {
            /* compute offset in image */
            miUchar *p = image + y * byte_width + rect->left * 4;

            if (read(streamId, taskbuf, tsize))
	for(x = rect->left, c = taskbuf; x <= rect-="">right; x++, c+=4) {
                    *p++ = c[0]; /* R */
                    *p++ = c[1]; /* G */
                    *p++ = c[2]; /* B */
                    *p++ = c[3]; /* A */
                    }
            }
}
Copyright © 1986, 2015 NVIDIA ARC GmbH. All rights reserved.