server_tiles.c revision e0e0c19eefceaf5d4ec40f9466b58a771f50e799
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include <stdlib.h>
#include "server.h"
#include "cr_mem.h"
#include "cr_warp.h"
#include "cr_hull.h"
#include "cr_string.h"
/*
* Given the mural->extents[i].imagewindow parameters, compute the
* mural->extents[i].bounds and outputwindow parameters.
* This includes allocating space in the render SPU's window for each
* of the tiles.
*/
static void
initializeExtents(CRMuralInfo *mural)
{
const int leftMargin = cr_server.useL2 ? 2 : 0;
int i;
int x, y, w, h, maxTileHeight;
x = leftMargin;
y = 0;
maxTileHeight = 0;
/* Basically just copy the server's list of tiles to the RunQueue
* and compute some derived tile information.
*/
for ( i = 0; i < mural->numExtents; i++ )
{
CRExtent *extent = &mural->extents[i];
CRASSERT(mural->width > 0);
CRASSERT(mural->height > 0);
/* extent->display = find_output_display( extent->imagewindow ); */
/* Compute normalized tile bounds.
* That is, x1, y1, x2, y2 will be in the range [-1, 1] where
* x1=-1, y1=-1, x2=1, y2=1 corresponds to the whole mural.
*/
extent->bounds.x1 = ( (GLfloat) (2*extent->imagewindow.x1) /
mural->width - 1.0f );
extent->bounds.y1 = ( (GLfloat) (2*extent->imagewindow.y1) /
mural->height - 1.0f );
extent->bounds.x2 = ( (GLfloat) (2*extent->imagewindow.x2) /
mural->width - 1.0f );
extent->bounds.y2 = ( (GLfloat) (2*extent->imagewindow.y2) /
mural->height - 1.0f );
/* Width and height of tile, in mural pixels */
w = mural->extents[i].imagewindow.x2 - mural->extents[i].imagewindow.x1;
h = mural->extents[i].imagewindow.y2 - mural->extents[i].imagewindow.y1;
if (cr_server.useDMX) {
/* Tile layout is easy!
* Remember, the X window we're drawing into (tileosort::xsubwin)
* is already adjusted to the right mural position.
*/
extent->outputwindow.x1 = 0;
extent->outputwindow.y1 = 0;
extent->outputwindow.x2 = w;
extent->outputwindow.y2 = h;
#if 0
printf("OutputWindow %d, %d .. %d, %d\n",
extent->outputwindow.x1,
extent->outputwindow.y1,
extent->outputwindow.x2,
extent->outputwindow.y2);
#endif
}
else {
/* Carve space out of the underlying (render SPU) window for this tile.
*/
if ( x + w > (int) mural->underlyingDisplay[2] )
{
if (x == leftMargin) {
crWarning("No room for %dx%d tile in this server's window (%d x %d)!",
w, h,
mural->underlyingDisplay[2], mural->underlyingDisplay[3]);
}
y += maxTileHeight;
x = leftMargin;
maxTileHeight = 0;
}
/* Allocate space from window in bottom-to-top order.
* This allows multi-level tilesort configurations to work better.
*/
extent->outputwindow.x1 = x;
extent->outputwindow.y1 = y;
extent->outputwindow.x2 = x + w;
extent->outputwindow.y2 = y + h;
if ((unsigned int)extent->outputwindow.y2 > mural->underlyingDisplay[3])
crWarning("No room for %dx%d tile in this server's window (%d x %d)!",
w, h,
mural->underlyingDisplay[2], mural->underlyingDisplay[3]);
if (h > maxTileHeight)
maxTileHeight = h;
x += w + leftMargin;
} /* useDMX */
}
}
/*
* This needs to be called when the tiling changes. Compute max tile
* height and check if optimized bucketing can be used, etc.
*/
void
crServerInitializeTiling(CRMuralInfo *mural)
{
int i;
/* The imagespace rect is useful in a few places (but redundant) */
/* XXX not used anymore??? (grep) */
mural->imagespace.x1 = 0;
mural->imagespace.y1 = 0;
mural->imagespace.x2 = mural->width;
mural->imagespace.y2 = mural->height;
/* find max tile height */
mural->maxTileHeight = 0;
for (i = 0; i < mural->numExtents; i++)
{
const int h = mural->extents[i].imagewindow.y2 -
mural->extents[i].imagewindow.y1;
if (h > mural->maxTileHeight)
mural->maxTileHeight = h;
}
/* compute extent bounds, outputwindow, etc */
initializeExtents(mural);
/* optimized hash-based bucketing setup */
if (cr_server.optimizeBucket) {
mural->optimizeBucket = crServerInitializeBucketing(mural);
}
else {
mural->optimizeBucket = GL_FALSE;
}
}
/*
* Change the tiling for a mural.
* The boundaries are specified in mural space.
* Input: muralWidth/muralHeight - new window/mural size
* numTiles - number of tiles
* Input: tileBounds[0] = bounds[0].x
* tileBounds[1] = bounds[0].y
* tileBounds[2] = bounds[0].width
* tileBounds[3] = bounds[0].height
* tileBounds[4] = bounds[1].x
* ...
*/
void
crServerNewMuralTiling(CRMuralInfo *mural,
GLint muralWidth, GLint muralHeight,
GLint numTiles, const GLint *tileBounds)
{
int i;
CRASSERT(numTiles >= 0);
crDebug("Reconfiguring tiles in crServerNewMuralTiling:");
crDebug(" New mural size: %d x %d", muralWidth, muralHeight);
for (i = 0; i < numTiles; i++)
{
crDebug(" Tile %d: %d, %d %d x %d", i,
tileBounds[i*4], tileBounds[i*4+1],
tileBounds[i*4+2], tileBounds[i*4+3]);
}
/*
* This section basically mimics what's done during crServerGetTileInfo()
*/
mural->width = muralWidth;
mural->height = muralHeight;
mural->numExtents = numTiles;
for (i = 0; i < numTiles; i++)
{
const GLint x = tileBounds[i * 4 + 0];
const GLint y = tileBounds[i * 4 + 1];
const GLint w = tileBounds[i * 4 + 2];
const GLint h = tileBounds[i * 4 + 3];
mural->extents[i].imagewindow.x1 = x;
mural->extents[i].imagewindow.y1 = y;
mural->extents[i].imagewindow.x2 = x + w;
mural->extents[i].imagewindow.y2 = y + h;
}
crServerInitializeTiling(mural);
}
static float
absf(float a)
{
if (a < 0)
return -a;
return a;
}