int crPackCanHoldBuffer( const CRPackBuffer *src ) { const int num_data = crPackNumData(src); const int num_opcode = crPackNumOpcodes(src); int res; CR_GET_PACKER_CONTEXT(pc); CR_LOCK_PACKER_CONTEXT(pc); res = crPackCanHoldOpcode( pc, num_opcode, num_data ); CR_UNLOCK_PACKER_CONTEXT(pc); return res; }
void crPackAppendBuffer( const CRPackBuffer *src ) { CR_GET_PACKER_CONTEXT(pc); const int num_data = crPackNumData(src); const int num_opcode = crPackNumOpcodes(src); CRASSERT(num_data >= 0); CRASSERT(num_opcode >= 0); CR_LOCK_PACKER_CONTEXT(pc); /* don't append onto ourself! */ CRASSERT(pc->currentBuffer); CRASSERT(pc->currentBuffer != src); if (!crPackCanHoldBuffer(src)) { if (src->holds_BeginEnd) { crWarning( "crPackAppendBuffer: overflowed the destination!" ); CR_UNLOCK_PACKER_CONTEXT(pc); return; } else { crError( "crPackAppendBuffer: overflowed the destination!" ); CR_UNLOCK_PACKER_CONTEXT(pc); } } /* Copy the buffer data/operands which are at the head of the buffer */ crMemcpy( pc->buffer.data_current, src->data_start, num_data ); pc->buffer.data_current += num_data; /* Copy the buffer opcodes which are at the tail of the buffer */ CRASSERT( pc->buffer.opcode_current - num_opcode >= pc->buffer.opcode_end ); crMemcpy( pc->buffer.opcode_current + 1 - num_opcode, src->opcode_current + 1, num_opcode ); pc->buffer.opcode_current -= num_opcode; pc->buffer.holds_BeginEnd |= src->holds_BeginEnd; pc->buffer.in_BeginEnd = src->in_BeginEnd; pc->buffer.holds_List |= src->holds_List; CR_UNLOCK_PACKER_CONTEXT(pc); }
void crPackAppendBoundedBuffer( const CRPackBuffer *src, const CRrecti *bounds ) { CR_GET_PACKER_CONTEXT(pc); const GLbyte *payload = (const GLbyte *) src->opcode_current + 1; const int num_opcodes = crPackNumOpcodes(src); const int length = src->data_current - src->opcode_current - 1; CRASSERT(pc); CR_LOCK_PACKER_CONTEXT(pc); CRASSERT(pc->currentBuffer); CRASSERT(pc->currentBuffer != src); /* * payload points to the block of opcodes immediately followed by operands. */ if ( !crPackCanHoldBoundedBuffer( src ) ) { if (src->holds_BeginEnd) { crWarning( "crPackAppendBoundedBuffer: overflowed the destination!" ); CR_UNLOCK_PACKER_CONTEXT(pc); return; } else { crError( "crPackAppendBoundedBuffer: overflowed the destination!" ); CR_UNLOCK_PACKER_CONTEXT(pc); } } if (pc->swapping) crPackBoundsInfoCRSWAP( bounds, payload, length, num_opcodes ); else crPackBoundsInfoCR( bounds, payload, length, num_opcodes ); pc->buffer.holds_BeginEnd |= src->holds_BeginEnd; pc->buffer.in_BeginEnd = src->in_BeginEnd; pc->buffer.holds_List |= src->holds_List; CR_UNLOCK_PACKER_CONTEXT(pc); }
void PACK_APIENTRY crPackBoundsInfoCR( const CRrecti *bounds, const GLbyte *payload, GLint len, GLint num_opcodes ) { CR_GET_PACKER_CONTEXT(pc); /* Don't get the buffered_ptr here because we've already * verified that there's enough space for everything. */ unsigned char *data_ptr; int len_aligned, total_len; CR_LOCK_PACKER_CONTEXT(pc); data_ptr = pc->buffer.data_current; len_aligned = ( len + 0x3 ) & ~0x3; total_len = 24 + len_aligned; WRITE_DATA( 0, int, total_len ); WRITE_DATA( 4, int, bounds->x1 ); WRITE_DATA( 8, int, bounds->y1 ); WRITE_DATA( 12, int, bounds->x2 ); WRITE_DATA( 16, int, bounds->y2 ); WRITE_DATA( 20, int, num_opcodes ); /* skip the BOUNDSINFO */ data_ptr += 24; /* put in padding opcodes (deliberately bogus) */ switch ( len_aligned - len ) { case 3: *data_ptr++ = 0xff; /* FALLTHROUGH */ case 2: *data_ptr++ = 0xff; /* FALLTHROUGH */ case 1: *data_ptr++ = 0xff; /* FALLTHROUGH */ default: break; } crMemcpy( data_ptr, payload, len ); WRITE_OPCODE( pc, CR_BOUNDSINFOCR_OPCODE ); pc->buffer.data_current += 24 + len_aligned; CR_UNLOCK_PACKER_CONTEXT(pc); }
/* * 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 ) { CR_GET_PACKER_CONTEXT(pc); unsigned char *data_ptr; /* include space for the length and make the payload word-aligned */ size = ( size + sizeof(unsigned int) + 0x3 ) & ~0x3; CR_LOCK_PACKER_CONTEXT(pc); if ( crPackCanHoldOpcode( pc, 1, size ) ) { /* we can just put it in the current buffer */ CR_GET_BUFFERED_POINTER_NOLOCK(pc, size ); /* NOTE: this sets data_ptr */ } else { /* Okay, it didn't fit. Maybe it will after we flush. */ CR_UNLOCK_PACKER_CONTEXT(pc); pc->Flush( pc->flush_arg ); CR_LOCK_PACKER_CONTEXT(pc); if ( crPackCanHoldOpcode( pc, 1, size ) ) { CR_GET_BUFFERED_POINTER_NOLOCK(pc, size ); /* NOTE: this sets data_ptr */ } 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 *) crAlloc( sizeof(CRMessageOpcodes) + 4 + size ); /* skip the header & opcode space */ data_ptr += sizeof(CRMessageOpcodes) + 4; } } /* 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 +------------------+ */ if (pc->swapping) { *((unsigned int *) data_ptr) = SWAP32(size); crDebug( "Just swapped the length, putting %d on the wire!", *((unsigned int *) data_ptr)); } else { *((unsigned int *) data_ptr) = size; } #ifndef CHROMIUM_THREADSAFE sanityCheckPointer = data_ptr + 4; #endif return data_ptr + 4; }
/* * This is called from either the Pack SPU and the packer library whenever * we need to send a data buffer to the server. */ void packspuFlush(void *arg ) { ThreadInfo *thread = (ThreadInfo *) arg; ContextInfo *ctx; unsigned int len; CRMessageOpcodes *hdr; CRPackBuffer *buf; /* we should _always_ pass a valid <arg> value */ CRASSERT(thread && thread->inUse); #ifdef CHROMIUM_THREADSAFE CR_LOCK_PACKER_CONTEXT(thread->packer); #endif ctx = thread->currentContext; buf = &(thread->buffer); CRASSERT(buf); /* We're done packing into the current buffer, unbind it */ crPackReleaseBuffer( thread->packer ); /* printf("%s thread=%p thread->id = %d thread->pc=%p t2->id=%d t2->pc=%p packbuf=%p packbuf=%p\n", __FUNCTION__, (void*) thread, (int) thread->id, thread->packer, (int) t2->id, t2->packer, buf->pack, thread->packer->buffer.pack); */ if ( buf->opcode_current == buf->opcode_start ) { /* printf("%s early return\n", __FUNCTION__); */ /* XXX these calls seem to help, but might be appropriate */ crPackSetBuffer( thread->packer, buf ); crPackResetPointers(thread->packer); #ifdef CHROMIUM_THREADSAFE CR_UNLOCK_PACKER_CONTEXT(thread->packer); #endif return; } hdr = __prependHeader( buf, &len, 0 ); CRASSERT( thread->netServer.conn ); if ( buf->holds_BeginEnd ) { /*crDebug("crNetBarf %d, (%d)", len, buf->size);*/ crNetBarf( thread->netServer.conn, &(buf->pack), hdr, len ); } else { /*crDebug("crNetSend %d, (%d)", len, buf->size);*/ crNetSend( thread->netServer.conn, &(buf->pack), hdr, len ); } buf->pack = crNetAlloc( thread->netServer.conn ); /* The network may have found a new mtu */ buf->mtu = thread->netServer.conn->mtu; crPackSetBuffer( thread->packer, buf ); crPackResetPointers(thread->packer); #ifdef CHROMIUM_THREADSAFE CR_UNLOCK_PACKER_CONTEXT(thread->packer); #endif }
void PACKSPU_APIENTRY packspu_VBoxDetachThread() { int i; GET_THREAD(thread); if (thread) { crLockMutex(&_PackMutex); for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID() && thread->netServer.conn) { CRASSERT(pack_spu.numThreads>0); packspuFlush((void *) thread); if (pack_spu.thread[i].packer) { CR_LOCK_PACKER_CONTEXT(thread->packer); crPackSetContext(NULL); CR_UNLOCK_PACKER_CONTEXT(thread->packer); crPackDeleteContext(pack_spu.thread[i].packer); } crNetFreeConnection(pack_spu.thread[i].netServer.conn); pack_spu.numThreads--; /*note can't shift the array here, because other threads have TLS references to array elements*/ crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo)); crSetTSD(&_PackTSD, NULL); if (i==pack_spu.idxThreadInUse) { for (i=0; i<MAX_THREADS; ++i) { if (pack_spu.thread[i].inUse) { pack_spu.idxThreadInUse=i; break; } } } break; } } for (i=0; i<CR_MAX_CONTEXTS; ++i) { ContextInfo *ctx = &pack_spu.context[i]; if (ctx->currentThread == thread) { CRASSERT(ctx->fAutoFlush); ctx->currentThread = NULL; } } crUnlockMutex(&_PackMutex); } crStateVBoxDetachThread(); }