<commit_before>/* Copyright (c) 2001, Stanford University
 * All rights reserved
 *
 * See the file LICENSE.txt for information on redistributing this software.
 */

#include "cr_packfunctions.h"
#include "cr_glstate.h"
#include "cr_error.h"
#include "cr_net.h"
#include "tilesortspu.h"
#include "tilesortspu_proto.h"
#include "cr_pixeldata.h"
#include "cr_mem.h"
#include "cr_dlm.h"


/**
 * Execute glDrawPixels().  Immediate mode only.
 */
void TILESORTSPU_APIENTRY
tilesortspu_DrawPixels(GLsizei width, GLsizei height, GLenum format,
		       GLenum type, const GLvoid *pixels)
{
	GET_CONTEXT(ctx);
	CRCurrentState *c = &(ctx->current);
	CRViewportState *v = &(ctx->viewport);
	CRPixelState *p = &(ctx->pixel);
	WindowInfo *winInfo = thread->currentContext->currentWindow;
	GLfloat screen_bbox[8];
	GLenum hint;
	GLint zoomedWidth, zoomedHeight;
	GLfloat zoomX, zoomY;
	GLfloat oldZoomX, oldZoomY;

	(void) v;

	CRASSERT(ctx->lists.mode == 0);

	if (c->inBeginEnd)
	{
		crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawPixels" );
		return;
	}

	if (width < 0 || height < 0)
	{
		crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, "glDrawPixels" );
		return;
	}

	if (!c->rasterValid)
	{
		return;
	}

	if (crImageSize(format, type, width, height)
		+ sizeof(format) + sizeof(type) + sizeof(width) + sizeof(height)
		> tilesort_spu.MTU ) {
		crWarning("DrawPixels called with insufficient MTU size\n"
			"Needed %d, but currently MTU is set at %d\n", 
			crImageSize(format, type, width, height), 
			tilesort_spu.MTU );
		return;
	}

	tilesortspuFlush( thread );
	
	oldZoomX = p->xZoom;
	oldZoomY = p->yZoom;
	if (tilesort_spu.scaleImages) {
		 /* Zoom the pixels up to match the output.  If an app draws to
			* the full size of it's window, for the output to look right on
			* a tiled display, we should zoom here as well.
			*/
		 zoomX = oldZoomX * winInfo->widthScale;
		 zoomY = oldZoomY * winInfo->heightScale;
		 crStatePixelZoom(zoomX, zoomY);
	}
	else {
		 zoomX = oldZoomX;
		 zoomY = oldZoomY;
	}

	/* The "+ 0.5" causes a round up when we cast to int */
	zoomedWidth  = (GLint) (zoomX * width  + 0.5);
	zoomedHeight = (GLint) (zoomY * height + 0.5);

	/* min x, y, z, w */
	screen_bbox[0] = c->rasterAttrib[VERT_ATTRIB_POS][0] / v->viewportW;
	screen_bbox[1] = c->rasterAttrib[VERT_ATTRIB_POS][1] / v->viewportH;
	screen_bbox[2] = 0.0;
	screen_bbox[3] = 1.0;
	/* max x, y, z, w */
	screen_bbox[4] = (c->rasterAttrib[VERT_ATTRIB_POS][0] + zoomedWidth) / v->viewportW;
	screen_bbox[5] = (c->rasterAttrib[VERT_ATTRIB_POS][1] + zoomedHeight) / v->viewportH;
	screen_bbox[6] = 0.0;
	screen_bbox[7] = 1.0;

	/* compute NDC coords */
	screen_bbox[0] = screen_bbox[0] * 2.0f - 1.0f;
	screen_bbox[1] = screen_bbox[1] * 2.0f - 1.0f;
	screen_bbox[4] = screen_bbox[4] * 2.0f - 1.0f;
	screen_bbox[5] = screen_bbox[5] * 2.0f - 1.0f;

	hint = thread->currentContext->providedBBOX;
	tilesortspu_ChromiumParametervCR(GL_SCREEN_BBOX_CR, GL_FLOAT, 8, screen_bbox);

	/* 
	 * don't do a flush, DrawPixels understand that it needs to flush,
	 * and will handle all that for us.  our HugeFunc routine will
	 * specially handle the DrawPixels call
	 */

	thread->currentContext->inDrawPixels = GL_TRUE;
	if (tilesort_spu.swap)
	     crPackDrawPixelsSWAP(width, height, format, type, 
				  pixels, &(ctx->client.unpack));
	else
	     crPackDrawPixels(width, height, format, type, 
			      pixels, &(ctx->client.unpack));

	if (thread->packer->buffer.data_current != thread->packer->buffer.data_start)
	{
		tilesortspuFlush( thread );
	}
	thread->currentContext->inDrawPixels = GL_FALSE;

	thread->currentContext->providedBBOX = hint;
	crStatePixelZoom(oldZoomX, oldZoomY);
}


/**
 * Wrapper for crPackDrawPixels to provide the unpacking state.
 */
void TILESORTSPU_APIENTRY
tilesortspu_PackDrawPixels(GLsizei width, GLsizei height, GLenum format,
													 GLenum type, const GLvoid *pixels)
{
	if (tilesort_spu.swap)
		 crPackDrawPixelsSWAP(width, height, format, type, pixels,
													&crStateNativePixelPacking);
	else
		 crPackDrawPixels(width, height, format, type, pixels,
											&crStateNativePixelPacking);
}
<commit_msg>Optimized glDrawPixels so that the image is broken into sub-images which match the display tiling.  We used to send the whole image to all tile servers which the image overlapped. This optimization currently only works for PixelZoom(1,1).<commit_after>/* Copyright (c) 2001, Stanford University
 * All rights reserved
 *
 * See the file LICENSE.txt for information on redistributing this software.
 */

#include "cr_packfunctions.h"
#include "cr_glstate.h"
#include "cr_error.h"
#include "cr_net.h"
#include "tilesortspu.h"
#include "tilesortspu_proto.h"
#include "cr_pixeldata.h"
#include "cr_mem.h"
#include "cr_dlm.h"


/**
 * Given the position (x, y) and size (width, height) of a glDrawPixels
 * command, the UNPACK_SKIP_PIXELS and UNPACK_SKIP_ROWS values and a scissor
 * box, return modified x, y, width, height, skipPixels and skipRows
 * values so that drawing the image will result in only the pixels inside
 * the scissor box being drawn.
 * \return GL_TRUE if there's something to draw, otherwise GL_FALSE if
 * there's nothing left to draw.
 */
static GLboolean
ComputeSubImage(GLint *x, GLint *y, GLsizei *width, GLsizei *height,
								GLint *skipPixels, GLint *skipRows,
								const CRrecti *scissor)
{
	GLint clip; /* number of clipped pixels */

	if (*x + *width <= scissor->x1 ||
			*x >= scissor->x2 ||
			*y + *height <= scissor->y1 ||
			*y >= scissor->y2) {
		/* totally clipped */
		return GL_FALSE;
	}

	if (*x < scissor->x1) {
		/* image crosses left edge of scissor box */
		CRASSERT(*x + *width > scissor->x1);
		clip = scissor->x1 - *x;
		CRASSERT(clip > 0);
		*x = scissor->x1;
		*skipPixels += clip;
		*width -= clip;
	}
	if (*y < scissor->y1) {
		/* image crosses bottom edge of scissor box */
		CRASSERT(*y + *height > scissor->y1);
		clip = scissor->y1 - *y;
		CRASSERT(clip > 0);
		*y = scissor->y1;
		*skipRows += clip;
		*height -= clip;
	}
	if (*x + *width > scissor->x2) {
		/* image crossed right edge of scissor box */
		CRASSERT(*x <= scissor->x2);
		clip = *x + *width - scissor->x2;
		CRASSERT(clip > 0);
		*width -= clip;
	}
	if (*y + *height > scissor->y2) {
		/* image crossed top edge of scissor box */
		CRASSERT(*y <= scissor->y2);
		clip = *y + *height - scissor->y2;
		CRASSERT(clip > 0);
		*height -= clip;
	}

	return GL_TRUE;
}



/**
 * Execute glDrawPixels().  Immediate mode only.
 */
void TILESORTSPU_APIENTRY
tilesortspu_DrawPixels(GLsizei width, GLsizei height, GLenum format,
		       GLenum type, const GLvoid *pixels)
{
	GET_CONTEXT(ctx);
	CRCurrentState *c = &(ctx->current);
	CRViewportState *v = &(ctx->viewport);
	CRPixelState *p = &(ctx->pixel);
	WindowInfo *winInfo = thread->currentContext->currentWindow;
	GLfloat screen_bbox[8];
	GLint zoomedWidth, zoomedHeight;
	GLfloat zoomX, zoomY;
	GLfloat oldZoomX, oldZoomY;

	CRASSERT(ctx->lists.mode == 0);

	if (c->inBeginEnd)
	{
		crStateError( __LINE__, __FILE__, GL_INVALID_OPERATION, "glDrawPixels" );
		return;
	}

	if (width < 0 || height < 0)
	{
		crStateError( __LINE__, __FILE__, GL_INVALID_VALUE, "glDrawPixels" );
		return;
	}

	if (!c->rasterValid)
	{
		return;
	}

	if (crImageSize(format, type, width, height)
		+ sizeof(format) + sizeof(type) + sizeof(width) + sizeof(height)
		> tilesort_spu.MTU ) {
		crWarning("DrawPixels called with insufficient MTU size\n"
			"Needed %d, but currently MTU is set at %d\n", 
			crImageSize(format, type, width, height), 
			tilesort_spu.MTU );
		return;
	}

	tilesortspuFlush( thread );
	
	oldZoomX = p->xZoom;
	oldZoomY = p->yZoom;
	if (tilesort_spu.scaleImages) {
		 /* Zoom the pixels up to match the output.  If an app draws to
			* the full size of it's window, for the output to look right on
			* a tiled display, we should zoom here as well.
			*/
		 zoomX = oldZoomX * winInfo->widthScale;
		 zoomY = oldZoomY * winInfo->heightScale;
		 crStatePixelZoom(zoomX, zoomY);
	}
	else {
		 zoomX = oldZoomX;
		 zoomY = oldZoomY;
	}

	/* The "+ 0.5" causes a round up when we cast to int */
	zoomedWidth  = (GLint) (zoomX * width  + 0.5);
	zoomedHeight = (GLint) (zoomY * height + 0.5);

	/* min x, y, z, w */
	screen_bbox[0] = c->rasterAttrib[VERT_ATTRIB_POS][0] / v->viewportW;
	screen_bbox[1] = c->rasterAttrib[VERT_ATTRIB_POS][1] / v->viewportH;
	screen_bbox[2] = 0.0;
	screen_bbox[3] = 1.0;
	/* max x, y, z, w */
	screen_bbox[4] = (c->rasterAttrib[VERT_ATTRIB_POS][0] + zoomedWidth) / v->viewportW;
	screen_bbox[5] = (c->rasterAttrib[VERT_ATTRIB_POS][1] + zoomedHeight) / v->viewportH;
	screen_bbox[6] = 0.0;
	screen_bbox[7] = 1.0;

	/* compute NDC coords */
	screen_bbox[0] = screen_bbox[0] * 2.0f - 1.0f;
	screen_bbox[1] = screen_bbox[1] * 2.0f - 1.0f;
	screen_bbox[4] = screen_bbox[4] * 2.0f - 1.0f;
	screen_bbox[5] = screen_bbox[5] * 2.0f - 1.0f;

	thread->currentContext->inDrawPixels = GL_TRUE;

	if (winInfo->bucketMode != BROADCAST && oldZoomX == 1.0 && oldZoomY == 1.0) {
		/* Test glDrawPixels image bounds against all tile extents and only
		 * send sub-images instead of full-size images.
		 */
		int i;

		/* release current geometry buffer */
		crPackReleaseBuffer(thread->packer);

		for (i = 0; i < tilesort_spu.num_servers; i++)
		{
			int j;

			crPackSetBuffer( thread->packer, &(thread->buffer[i]) );

			/* Determine if the DrawPixel destination region overlaps any
			 * tile extents of this server
			 */
			for (j = 0; j < winInfo->server[i].num_extents; j++) {
				CRPixelPackState unpacking = ctx->client.unpack;
				int newX = c->rasterAttrib[VERT_ATTRIB_POS][0];
				int newY = c->rasterAttrib[VERT_ATTRIB_POS][1];
				int newWidth = zoomedWidth;
				int newHeight = zoomedHeight;
				if (ComputeSubImage(&newX, &newY, &newWidth, &newHeight,
														&unpacking.skipPixels, &unpacking.skipRows,
														&winInfo->server[i].extents[j])) {
					/*
					printf("clipped: %d, %d  %d x %d  skip %d, %d\n",
								 newX, newY, newWidth, newHeight,
								 unpacking.skipPixels, unpacking.skipRows);
					*/
					if (tilesort_spu.swap) {
						 crPackWindowPos2iARBSWAP(newX, newY);
						 crPackDrawPixelsSWAP(newWidth, newHeight, format, type, pixels,
																	&unpacking);
					}
					else {
						 crPackWindowPos2iARB(newX, newY);
						 crPackDrawPixels(newWidth, newHeight, format, type, pixels,
															&unpacking);
					}
				}
			}

			/* release server buffer */
			crPackReleaseBuffer(thread->packer);

			/* Flush buffer (send to server) */
			tilesortspuSendServerBuffer(i);
		}

		/* Restore the default geometry pack buffer */
		crPackSetBuffer( thread->packer, &(thread->geometry_buffer) );
	}
	else {
		/*
		 * Send the whole image to all servers chosen by bucketing
		 */
		GLenum hint = thread->currentContext->providedBBOX;
		tilesortspu_ChromiumParametervCR(GL_SCREEN_BBOX_CR, GL_FLOAT, 8, screen_bbox);

		/* 
		 * don't do a flush, DrawPixels understand that it needs to flush,
		 * and will handle all that for us.  our HugeFunc routine will
		 * specially handle the DrawPixels call
		 */

		if (tilesort_spu.swap)
			crPackDrawPixelsSWAP(width, height, format, type, 
													 pixels, &(ctx->client.unpack));
		else
			crPackDrawPixels(width, height, format, type, 
											 pixels, &(ctx->client.unpack));

		if (thread->packer->buffer.data_current != thread->packer->buffer.data_start)
		{
			tilesortspuFlush( thread );
		}

		thread->currentContext->providedBBOX = hint;
	}

	thread->currentContext->inDrawPixels = GL_FALSE;
	crStatePixelZoom(oldZoomX, oldZoomY);
}


/**
 * Wrapper for crPackDrawPixels to provide the unpacking state.
 */
void TILESORTSPU_APIENTRY
tilesortspu_PackDrawPixels(GLsizei width, GLsizei height, GLenum format,
													 GLenum type, const GLvoid *pixels)
{
	if (tilesort_spu.swap)
		 crPackDrawPixelsSWAP(width, height, format, type, pixels,
													&crStateNativePixelPacking);
	else
		 crPackDrawPixels(width, height, format, type, pixels,
											&crStateNativePixelPacking);
}

{'fraction_non_alphanumeric': 0.13227601096072408, 'fraction_numerical': 0.012621439840571286, 'mean_word_length': 3.6198695818948985, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 113, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1666143', 'n_tokens_mistral': 5025, 'n_tokens_neox': 4505, 'n_words': 1100}