pack_buffer.c revision d0a71f63bd810b54e0359223fe53b07730154dc5
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include "cr_mem.h"
#include "cr_string.h"
#include "packer.h"
#include "cr_error.h"
#include "cr_protocol.h"
#ifndef IN_RING0
#include "cr_unpack.h"
#endif
#ifndef IN_RING0
void crWriteUnalignedDouble( void *buffer, double d )
{
ui[0] = ((unsigned int *) &d)[0];
}
void crWriteSwappedDouble( void *buffer, double d )
{
}
double crReadUnalignedDouble( const void *buffer )
{
double d;
((unsigned int *) &d)[0] = ui[0];
return d;
}
#endif
/*
* We need the packer to run as efficiently as possible. To avoid one
* pointer dereference from the CRPackContext to the current CRPackBuffer,
* we keep a _copy_ of the current CRPackBuffer in the CRPackContext and
* operate on the fields in CRPackContext, rather than the CRPackBuffer.
*
* To keep things in sync, when we change a context's
*/
{
return; /* re-bind is no-op */
if (pc->currentBuffer) {
/* Another buffer currently bound to this packer (shouldn't normally occur)
* Release it. Fixes Ensight issue.
*/
}
/* bind context to buffer */
/* update the context's packing fields with those from the buffer */
}
#ifndef IN_RING0
/* This is useful for debugging packer problems */
{
/* record debugging info */
}
#endif
/*
* Release the buffer currently attached to the context.
*/
{
if (!pc->currentBuffer) {
crWarning("crPackReleaseBuffer called with no current buffer");
return; /* nothing to do */
}
/* buffer to release */
/* copy context's fields back into the buffer to update it */
/* unbind buffer from context */
/* zero-out context's packing fields just to be safe */
/* update the debugging fields */
}
{
}
{
}
{
}
/*
* This basically resets the buffer attached to <pc> to the default, empty
* state.
*/
{
}
/**
* Return max number of opcodes that'll fit in the given buffer size.
* Each opcode has at least a 1-word payload, so opcodes can occupy at most
* 20% of the space.
*/
int
crPackMaxOpcodes( int buffer_size )
{
/* Don't forget to add one here in case the buffer size is not
* divisible by 4. Thanks to Ken Moreland for finding this.
*/
n++;
/* round up to multiple of 4 */
n = (n + 0x3) & (~0x3);
return n;
}
/**
* Return max number of data bytes that'll fit in the given buffer size.
*/
int
crPackMaxData( int buffer_size )
{
int n = buffer_size - sizeof(CRMessageOpcodes);
n -= crPackMaxOpcodes(buffer_size);
return n;
}
/**
* Initialize the given CRPackBuffer object.
* The buffer may or may not be currently bound to a CRPackContext.
*
* Opcodes and operands are packed into a buffer in a special way.
* Opcodes start at opcode_start and go downward in memory while operands
* start at data_start and go upward in memory. The buffer is full when we
* either run out of opcode space or operand space.
*
* Diagram (memory addresses increase upward):
*
* data_end -> | | <- buf->pack + buf->size
* +---------+
* | |
* | |
* | operands|
* | |
* | |
* data_start -> +---------+
* opcode_start -> | |
* | |
* | opcodes |
* | |
* | |
* opcode_end -> +---------+ <- buf->pack
*
* \param buf the CRPackBuffer to initialize
* \param size size of the buffer, in bytes
* \param mtu max transmission unit size, in bytes. When the buffer
* has 'mtu' bytes in it, we have to send it. The MTU might
* be somewhat smaller than the buffer size.
*/
{
unsigned int num_opcodes;
buf->data_start =
/* Also reset context's packing fields */
/*crMemcpy( &(pc->buffer), buf, sizeof(*buf) );*/
}
}
{
int res;
return res;
}
{
/* 24 is the size of the bounds-info packet... */
}
{
CRASSERT(num_opcode >= 0);
/* don't append onto ourself! */
if (!crPackCanHoldBuffer(src))
{
if (src->holds_BeginEnd)
{
crWarning( "crPackAppendBuffer: overflowed the destination!" );
return;
}
else
{
crError( "crPackAppendBuffer: overflowed the destination!" );
}
}
/* Copy the buffer opcodes which are at the tail of the buffer */
num_opcode );
}
void
{
/*
* payload points to the block of opcodes immediately followed by operands.
*/
if ( !crPackCanHoldBoundedBuffer( src ) )
{
if (src->holds_BeginEnd)
{
crWarning( "crPackAppendBoundedBuffer: overflowed the destination!" );
return;
}
else
{
crError( "crPackAppendBoundedBuffer: overflowed the destination!" );
}
}
else
}
#ifndef CHROMIUM_THREADSAFE
static unsigned char *sanityCheckPointer = NULL;
#endif
/*
* Allocate space for a command that might be very large, such as
* glTexImage2D or glBufferDataARB call.
* The command buffer _MUST_ then be transmitted by calling crHugePacket.
*/
void *crPackAlloc( unsigned int size )
{
unsigned char *data_ptr;
/* include space for the length and make the payload word-aligned */
{
/* we can just put it in the current buffer */
}
else
{
/* Okay, it didn't fit. Maybe it will after we flush. */
{
}
else
{
/* It's really way too big, so allocate a temporary packet
* with space for the single opcode plus the payload &
* header.
*/
data_ptr = (unsigned char *)
/* skip the header & opcode space */
}
}
/* At the top of the function, we added four to the request size and
* rounded it up to the next multiple of four.
*
* At this point, we have:
*
* HIGH MEM | byte size - 1 | \
* ... |
* ... | - original 'size' bytes for data
* | operand data | |
* return value -> | operand data | /
* | byte 3 | \
* | byte 2 | |- These bytes will store 'size'
* | byte 1 | |
* data_ptr -> | byte 0 | /
* | CR opcode | <- Set in packspuHuge()
* | unused |
* | unused |
* | unused |
* | CRMessageOpcodes |
* | CRMessageOpcodes |
* ...
* | CRMessageOpcodes |
* | CRMessageOpcodes |
* LOW MEM +------------------+
*/
{
}
else
{
}
#ifndef CHROMIUM_THREADSAFE
#endif
return data_ptr + 4;
}
#define IS_BUFFERED( packet ) \
/*
* Transmit a packet which was allocated with crPackAlloc.
*/
{
#ifndef CHROMIUM_THREADSAFE
#endif
if ( IS_BUFFERED( packet ) )
else
}
void crPackFree( void *packet )
{
if ( IS_BUFFERED( packet ) )
{
return;
}
/* the pointer passed in doesn't include the space for the single
* opcode (4 bytes because of the alignment requirement) or the
* length field or the header */
}
{
/* init CRNetworkPointer with invalid values */
/* copy the pointer's value into the CRNetworkPointer */
/* if either assertion fails, it probably means that a packer function
* (which returns a value) was called without setting up the writeback
* pointer, or something like that.
*/
}