/**
 * Process a crBoundsInfoCR message/function.  This is a bounding box
 * followed by a payload of arbitrary Chromium rendering commands.
 * The tilesort SPU will send this.
 * Note: the bounding box is in mural pixel coordinates (y=0=bottom)
 */
void SERVER_DISPATCH_APIENTRY
crServerDispatchBoundsInfoCR( const CRrecti *bounds, const GLbyte *payload,
															GLint len, GLint num_opcodes )
{
	CRMuralInfo *mural = cr_server.curClient->currentMural;
	char *data_ptr = (char*)(payload + ((num_opcodes + 3 ) & ~0x03));
	unsigned int bx, by;

	/* Save current unpacker state */
	crUnpackPush();
#if 0
	/* pass bounds info to first SPU */
	{
		/* bias bounds to extent/window coords */
		CRrecti bounds2;
		const int dx = mural->extents[0].imagewindow.x1;
		const int dy = mural->extents[0].imagewindow.y1;
		if (bounds->x1 == -CR_MAXINT) {
			/* "infinite" bounds: convert to full image bounds */
			bounds2.x1 = 0;
			bounds2.y1 = 0;
			bounds2.x2 = mural->extents[0].imagewindow.x2 - dx; /* width */
			bounds2.y2 = mural->extents[0].imagewindow.y2 - dy; /* height */
		}
		else {
			bounds2.x1 = bounds->x1 - dx;
			bounds2.y1 = bounds->y1 - dy;
			bounds2.x2 = bounds->x2 - dx;
			bounds2.y2 = bounds->y2 - dy;
		}
		cr_server.head_spu->dispatch_table.BoundsInfoCR(&bounds2, NULL, 0, 0);
	}

	if (!mural->viewportValidated) {
		crServerComputeViewportBounds(&(cr_server.curClient->currentCtx->viewport),
																	mural);
	}

	bx = BKT_DOWNHASH(bounds->x1, mural->width);
	by = BKT_DOWNHASH(bounds->y1, mural->height);

	/* Check for out of bounds, and optimizeBucket to enable */
	if (mural->optimizeBucket && (bx <= HASHRANGE) && (by <= HASHRANGE))
	{
		const struct BucketingInfo *bucketInfo = mural->bucketInfo;
		const BucketRegion *r;
		const BucketRegion *p;

		CRASSERT(bucketInfo);

		for (r = bucketInfo->rhash[by][bx]; r && bounds->y2 >= r->extents.y1;
		     r = r->up)
		{
			for (p=r; p && bounds->x2 >= p->extents.x1; p = p->right)
			{
				if ( p->id != (unsigned int) -1 &&
					bounds->x1 < p->extents.x2  &&
					bounds->y1 < p->extents.y2 &&
					bounds->y2 >= p->extents.y1 )
				{
					mural->curExtent = p->id;
					if (cr_server.run_queue->client->currentCtx) {
						crServerSetOutputBounds( mural, mural->curExtent );
					}
					crUnpack( data_ptr, data_ptr-1, num_opcodes, &(cr_server.dispatch) );
				}
			}
		}
	} 
	else 
	{
		/* non-optimized bucketing - unpack/render for each tile/extent */
		int i;
		for ( i = 0; i < mural->numExtents; i++ )
		{
			CRExtent *extent = &mural->extents[i];

			if (cr_server.localTileSpec ||
			    (extent->imagewindow.x2 > bounds->x1 &&
					 extent->imagewindow.x1 < bounds->x2 &&
					 extent->imagewindow.y2 > bounds->y1 &&
					 extent->imagewindow.y1 < bounds->y2))
			{
				mural->curExtent = i;
				if (cr_server.run_queue->client->currentCtx) {
					crServerSetOutputBounds( mural, i );
				}
				crUnpack( data_ptr, data_ptr-1, num_opcodes, &(cr_server.dispatch) );
			}
		}
	}
#endif
	/* Restore previous unpacker state */
	crUnpackPop();
}
/*
 * At this point we know that the tiles are uniformly sized so we can use
 * a hash-based bucketing method.  Setup the hash table now.
 */
static GLboolean
fillBucketingHash(CRMuralInfo *mural)
{
#if 0
	int i, j, k, m;
	int r_len = 0;
	int xinc, yinc;
	int rlist_alloc = 64 * 128;
	BucketRegion *rptr;
	struct BucketingInfo *bucketInfo;

	if (mural->bucketInfo) {
		crFree(mural->bucketInfo->rlist);
		crFree(mural->bucketInfo);
		mural->bucketInfo = NULL;
	}

	bucketInfo = (struct BucketingInfo *) crCalloc(sizeof(struct BucketingInfo));
	if (!bucketInfo)
		return GL_FALSE;

	/* Allocate rlist (don't free it!!!) */
	bucketInfo->rlist = (BucketRegion *) crAlloc(rlist_alloc * sizeof(BucketRegion));

	for ( i = 0; i < HASHRANGE; i++ )
	{
		for ( j = 0; j < HASHRANGE; j++ )
		{
			bucketInfo->rhash[i][j] = NULL;
		}
	}

	/* Fill the rlist */
	xinc = mural->extents[0].imagewindow.x2 - mural->extents[0].imagewindow.x1;
	yinc = mural->extents[0].imagewindow.y2 - mural->extents[0].imagewindow.y1;
	CRASSERT(xinc > 0 || mural->width == 0);
	CRASSERT(yinc > 0 || mural->height == 0);

	rptr = bucketInfo->rlist;
	for (i=0; i < (int) mural->width; i+=xinc) 
	{
		for (j=0; j < (int) mural->height; j+=yinc) 
		{
			for (k=0; k < mural->numExtents; k++) 
			{
				if (mural->extents[k].imagewindow.x1 == i &&
						mural->extents[k].imagewindow.y1 == j) 
				{
					rptr->extents = mural->extents[k].imagewindow; /* x1,y1,x2,y2 */
					rptr->id = k;
					break;
				}
			}
			if (k == mural->numExtents) 
			{
				rptr->extents.x1 = i;
				rptr->extents.y1 = j;
				rptr->extents.x2 = i + xinc;
				rptr->extents.y2 = j + yinc;
				rptr->id = -1;
			}
			rptr++;
		}
	}
	r_len = rptr - bucketInfo->rlist;

	/* Fill hash table */
	for (i = 0; i < r_len; i++)
	{
		BucketRegion *r = &bucketInfo->rlist[i];

		for (k=BKT_DOWNHASH(r->extents.x1, (int)mural->width);
		     k<=BKT_UPHASH(r->extents.x2, (int)mural->width) &&
			     k < HASHRANGE;
		     k++) 
		{
			for (m=BKT_DOWNHASH(r->extents.y1, (int)mural->height);
			     m<=BKT_UPHASH(r->extents.y2, (int)mural->height) &&
				     m < HASHRANGE;
			     m++) 
			{
				if ( bucketInfo->rhash[m][k] == NULL ||
				     (bucketInfo->rhash[m][k]->extents.x1 > r->extents.x1 &&
				      bucketInfo->rhash[m][k]->extents.y1 > r->extents.y1))
				{
					bucketInfo->rhash[m][k] = r;
				}
			}
		}
	}

	/* Initialize links */
	for (i=0; i<r_len; i++) 
	{
		BucketRegion *r = &bucketInfo->rlist[i];
		r->right = NULL;
		r->up    = NULL;
	}

	/* Build links */
	for (i=0; i<r_len; i++) 
	{
		BucketRegion *r = &bucketInfo->rlist[i];
		for (j=0; j<r_len; j++) 
		{
			BucketRegion *q = &bucketInfo->rlist[j];
			if (r==q)
				continue;

			/* Right Edge */
			if (r->extents.x2 == q->extents.x1 &&
			    r->extents.y1 == q->extents.y1 &&
			    r->extents.y2 == q->extents.y2) 
			{
				r->right = q;
			}

			/* Upper Edge */
			if (r->extents.y2 == q->extents.y1 &&
			    r->extents.x1 == q->extents.x1 &&
			    r->extents.x2 == q->extents.x2) 
			{
				r->up = q;
			}
		}
	}

	mural->bucketInfo = bucketInfo;
#endif
	return GL_TRUE;
}
Exemple #3
0
/**
 * Initialize the hash table used for optimized UNIFORM_GRID bucketing.
 * \param  winInfo - which window/mural
 * \return  GL_FALSE - invalid tile size(s) or position(s)
 *         GL_TRUE - success!
 */
static GLboolean
initHashBucketing(WindowInfo *winInfo) 
{
	int i, j, k, m;
	int r_len = 0;
	int id;
	int rlist_alloc = 64 * 128;
	HashInfo *hash;

	hash = (HashInfo *) crCalloc(sizeof(HashInfo));
	if (!hash)
		return GL_FALSE;

	/* First, check that all the tiles are the same size! */
	{
		int reqWidth = 0, reqHeight = 0;

		for (i = 0; i < tilesort_spu.num_servers; i++)
		{
			ServerWindowInfo *servWinInfo = winInfo->server + i;
			for (j = 0; j < servWinInfo->num_extents; j++)
			{
				int x = servWinInfo->extents[j].x1;
				int y = servWinInfo->extents[j].y1;
				int w = servWinInfo->extents[j].x2 - x;
				int h = servWinInfo->extents[j].y2 - y;

				if (reqWidth == 0 || reqHeight == 0)
				{
					reqWidth = w;
					reqHeight = h;
				}
				else if (w != reqWidth || h != reqHeight)
				{
					crWarning("Tile %d on server %d is not the right size!", j, i);
					crWarning("All tiles must be same size when bucket_mode = "
										"'Uniform Grid'.");
					return GL_FALSE;
				}
				else if ((x % reqWidth) != 0 || (y % reqHeight) != 0)
				{
					/* (x,y) should be an integer multiple of the tile size */
					crWarning("Tile %d on server %d is not positioned correctly!", j, i);
					crWarning("Position (%d, %d) is not an integer multiple of the "
										"tile size (%d x %d)", x, y, reqWidth, reqHeight);
					return GL_FALSE;
				}
			}
		}
	}

	/* rlist_alloc = GLCONFIG_MAX_PROJECTORS*GLCONFIG_MAX_EXTENTS; */
	hash->rlist = (BucketRegion *) crAlloc(rlist_alloc * sizeof(BucketRegion));
	if (!hash->rlist) {
		crFree(hash);
		return GL_FALSE;
	}

	for (i=0; i<HASHRANGE; i++) 
	{
		for (j=0; j<HASHRANGE; j++) 
		{
			hash->rhash[i][j] = NULL;
		}
	}

	/* Fill hash table */
	id = 0;
	for (i = 0; i < tilesort_spu.num_servers; i++)
	{
		ServerWindowInfo *servWinInfo = winInfo->server + i;
		int node32 = i >> 5;
		int node = i & 0x1f;
		for (j = 0; j < servWinInfo->num_extents; j++) 
		{
			BucketRegion *r = &hash->rlist[id++];
			for (k=0;k<CR_MAX_BITARRAY;k++)
				r->id[k] = 0;
			r->id[node32] = (1 << node);
			r->extents = servWinInfo->extents[j]; /* copy x1,y1,x2,y2 */

			for (k=BKT_DOWNHASH(r->extents.x1, winInfo->muralWidth);
				   k<=BKT_UPHASH(r->extents.x2, winInfo->muralWidth) && k < HASHRANGE;
				   k++) 
			{
				for (m=BKT_DOWNHASH(r->extents.y1, winInfo->muralHeight);
				     m<=BKT_UPHASH(r->extents.y2, winInfo->muralHeight) && m < HASHRANGE;
					   m++)
				{
					if ( hash->rhash[m][k] == NULL ||
						   (hash->rhash[m][k]->extents.x1 > r->extents.x1 &&
						    hash->rhash[m][k]->extents.y1 > r->extents.y1)) 
					{
						 hash->rhash[m][k] = r;
					}
				}
			}
		}
	}
	r_len = id;

	/* Initialize links */
	for (i=0; i<r_len; i++) 
	{
		BucketRegion *r = &hash->rlist[i];
		r->right = NULL;
		r->up    = NULL;
	}

	/* Build links */
	for (i=0; i<r_len; i++) 
	{
		BucketRegion *r = &hash->rlist[i];
		for (j=0; j<r_len; j++) 
		{
			BucketRegion *q = &hash->rlist[j];
			if (r==q) 
			{
				continue;
			}

			/* Right Edge */
			if (r->extents.x2 == q->extents.x1 &&
				  r->extents.y1 == q->extents.y1 &&
				  r->extents.y2 == q->extents.y2) 
			{
				r->right = q;
			}

			/* Upper Edge */
			if (r->extents.y2 == q->extents.y1 &&
				  r->extents.x1 == q->extents.x1 &&
				  r->extents.x2 == q->extents.x2) 
			{
				r->up = q;
			}
		}
	}

	winInfo->bucketInfo = (void *) hash;
	return GL_TRUE;
}