diff options
Diffstat (limited to 'src/VBox/Additions/common/crOpenGL/pack/packspu_net.c')
-rw-r--r-- | src/VBox/Additions/common/crOpenGL/pack/packspu_net.c | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c new file mode 100644 index 00000000..6d5d41d6 --- /dev/null +++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_net.c @@ -0,0 +1,284 @@ +/* Copyright (c) 2001, Stanford University + * All rights reserved + * + * See the file LICENSE.txt for information on redistributing this software. + */ + +#include "cr_pack.h" +#include "cr_mem.h" +#include "cr_net.h" +#include "cr_pixeldata.h" +#include "cr_protocol.h" +#include "cr_error.h" +#include "packspu.h" +#include "packspu_proto.h" + +uint32_t g_u32VBoxHostCaps = 0; + +static void +packspuWriteback( const CRMessageWriteback *wb ) +{ + int *writeback; + crMemcpy( &writeback, &(wb->writeback_ptr), sizeof( writeback ) ); + *writeback = 0; +} + +/** + * XXX Note that this routine is identical to crNetRecvReadback except + * we set *writeback=0 instead of decrementing it. Hmmm. + */ +static void +packspuReadback( const CRMessageReadback *rb, unsigned int len ) +{ + /* minus the header, the destination pointer, + * *and* the implicit writeback pointer at the head. */ + + int payload_len = len - sizeof( *rb ); + int *writeback; + void *dest_ptr; + crMemcpy( &writeback, &(rb->writeback_ptr), sizeof( writeback ) ); + crMemcpy( &dest_ptr, &(rb->readback_ptr), sizeof( dest_ptr ) ); + + *writeback = 0; + crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len ); +} + +static void +packspuReadPixels( const CRMessageReadPixels *rp, unsigned int len ) +{ + crNetRecvReadPixels( rp, len ); + --pack_spu.ReadPixels; +} + +static int +packspuReceiveData( CRConnection *conn, CRMessage *msg, unsigned int len ) +{ + RT_NOREF(conn); + if (msg->header.type == CR_MESSAGE_REDIR_PTR) + msg = (CRMessage*) msg->redirptr.pMessage; + + switch( msg->header.type ) + { + case CR_MESSAGE_READ_PIXELS: + packspuReadPixels( &(msg->readPixels), len ); + break; + case CR_MESSAGE_WRITEBACK: + packspuWriteback( &(msg->writeback) ); + break; + case CR_MESSAGE_READBACK: + packspuReadback( &(msg->readback), len ); + break; + default: + /*crWarning( "Why is the pack SPU getting a message of type 0x%x?", msg->type ); */ + return 0; /* NOT HANDLED */ + } + return 1; /* HANDLED */ +} + +static CRMessageOpcodes * +__prependHeader( CRPackBuffer *buf, unsigned int *len, unsigned int senderID ) +{ + int num_opcodes; + CRMessageOpcodes *hdr; + RT_NOREF(senderID); + + CRASSERT( buf ); + CRASSERT( buf->opcode_current < buf->opcode_start ); + CRASSERT( buf->opcode_current >= buf->opcode_end ); + CRASSERT( buf->data_current > buf->data_start ); + CRASSERT( buf->data_current <= buf->data_end ); + + num_opcodes = buf->opcode_start - buf->opcode_current; + hdr = (CRMessageOpcodes *) + ( buf->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) ); + + CRASSERT( (void *) hdr >= buf->pack ); + + if (pack_spu.swap) + { + hdr->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES); + hdr->numOpcodes = SWAP32(num_opcodes); + } + else + { + hdr->header.type = CR_MESSAGE_OPCODES; + hdr->numOpcodes = num_opcodes; + } + + *len = buf->data_current - (unsigned char *) hdr; + + return hdr; +} + + +/* + * 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); + + if (ctx && ctx->fCheckZerroVertAttr) + crStateCurrentRecoverNew(ctx->clientState, &thread->packer->current); + + /* 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 +} + + +/** + * XXX NOTE: there's a lot of duplicate code here common to the + * pack, tilesort and replicate SPUs. Try to simplify someday! + */ +void packspuHuge( CROpcode opcode, void *buf ) +{ + GET_THREAD(thread); + unsigned int len; + unsigned char *src; + CRMessageOpcodes *msg; + + CRASSERT(thread); + + /* packet length is indicated by the variable length field, and + includes an additional word for the opcode (with alignment) and + a header */ + len = ((unsigned int *) buf)[-1]; + if (pack_spu.swap) + { + /* It's already been swapped, swap it back. */ + len = SWAP32(len); + } + len += 4 + sizeof(CRMessageOpcodes); + + /* write the opcode in just before the length */ + ((unsigned char *) buf)[-5] = (unsigned char) opcode; + + /* fix up the pointer to the packet to include the length & opcode + & header */ + src = (unsigned char *) buf - 8 - sizeof(CRMessageOpcodes); + + msg = (CRMessageOpcodes *) src; + + if (pack_spu.swap) + { + msg->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES); + msg->numOpcodes = SWAP32(1); + } + else + { + msg->header.type = CR_MESSAGE_OPCODES; + msg->numOpcodes = 1; + } + + CRASSERT( thread->netServer.conn ); + crNetSend( thread->netServer.conn, NULL, src, len ); +} + +static void packspuFirstConnectToServer( CRNetServer *server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ) +{ + crNetInit( packspuReceiveData, NULL ); + crNetServerConnect( server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + if (server->conn) + { + g_u32VBoxHostCaps = crNetHostCapsGet(); + crPackCapsSet(g_u32VBoxHostCaps); + } +} + +void packspuConnectToServer( CRNetServer *server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , struct VBOXUHGSMI *pHgsmi +#endif + ) +{ + if (pack_spu.numThreads == 0) { + packspuFirstConnectToServer( server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + if (!server->conn) { + crError("packspuConnectToServer: no connection on first create!"); + return; + } + pack_spu.swap = server->conn->swap; + } + else { + /* a new pthread */ + crNetNewClient(server +#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) + , pHgsmi +#endif + ); + } +} |