1 | /* Copyright (c) 2001, Stanford University
|
---|
2 | * All rights reserved
|
---|
3 | *
|
---|
4 | * See the file LICENSE.txt for information on redistributing this software.
|
---|
5 | */
|
---|
6 |
|
---|
7 | #include "cr_pack.h"
|
---|
8 | #include "cr_mem.h"
|
---|
9 | #include "cr_net.h"
|
---|
10 | #include "cr_pixeldata.h"
|
---|
11 | #include "cr_protocol.h"
|
---|
12 | #include "cr_error.h"
|
---|
13 | #include "packspu.h"
|
---|
14 | #include "packspu_proto.h"
|
---|
15 |
|
---|
16 | uint32_t g_u32VBoxHostCaps = 0;
|
---|
17 |
|
---|
18 | static void
|
---|
19 | packspuWriteback( const CRMessageWriteback *wb )
|
---|
20 | {
|
---|
21 | int *writeback;
|
---|
22 | crMemcpy( &writeback, &(wb->writeback_ptr), sizeof( writeback ) );
|
---|
23 | *writeback = 0;
|
---|
24 | }
|
---|
25 |
|
---|
26 | /**
|
---|
27 | * XXX Note that this routine is identical to crNetRecvReadback except
|
---|
28 | * we set *writeback=0 instead of decrementing it. Hmmm.
|
---|
29 | */
|
---|
30 | static void
|
---|
31 | packspuReadback( const CRMessageReadback *rb, unsigned int len )
|
---|
32 | {
|
---|
33 | /* minus the header, the destination pointer,
|
---|
34 | * *and* the implicit writeback pointer at the head. */
|
---|
35 |
|
---|
36 | int payload_len = len - sizeof( *rb );
|
---|
37 | int *writeback;
|
---|
38 | void *dest_ptr;
|
---|
39 | crMemcpy( &writeback, &(rb->writeback_ptr), sizeof( writeback ) );
|
---|
40 | crMemcpy( &dest_ptr, &(rb->readback_ptr), sizeof( dest_ptr ) );
|
---|
41 |
|
---|
42 | *writeback = 0;
|
---|
43 | crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb), payload_len );
|
---|
44 | }
|
---|
45 |
|
---|
46 | static void
|
---|
47 | packspuReadPixels( const CRMessageReadPixels *rp, unsigned int len )
|
---|
48 | {
|
---|
49 | crNetRecvReadPixels( rp, len );
|
---|
50 | --pack_spu.ReadPixels;
|
---|
51 | }
|
---|
52 |
|
---|
53 | static int
|
---|
54 | packspuReceiveData( CRConnection *conn, CRMessage *msg, unsigned int len )
|
---|
55 | {
|
---|
56 | if (msg->header.type == CR_MESSAGE_REDIR_PTR)
|
---|
57 | msg = (CRMessage*) msg->redirptr.pMessage;
|
---|
58 |
|
---|
59 | switch( msg->header.type )
|
---|
60 | {
|
---|
61 | case CR_MESSAGE_READ_PIXELS:
|
---|
62 | packspuReadPixels( &(msg->readPixels), len );
|
---|
63 | break;
|
---|
64 | case CR_MESSAGE_WRITEBACK:
|
---|
65 | packspuWriteback( &(msg->writeback) );
|
---|
66 | break;
|
---|
67 | case CR_MESSAGE_READBACK:
|
---|
68 | packspuReadback( &(msg->readback), len );
|
---|
69 | break;
|
---|
70 | default:
|
---|
71 | /*crWarning( "Why is the pack SPU getting a message of type 0x%x?", msg->type ); */
|
---|
72 | return 0; /* NOT HANDLED */
|
---|
73 | }
|
---|
74 | return 1; /* HANDLED */
|
---|
75 | }
|
---|
76 |
|
---|
77 | static CRMessageOpcodes *
|
---|
78 | __prependHeader( CRPackBuffer *buf, unsigned int *len, unsigned int senderID )
|
---|
79 | {
|
---|
80 | int num_opcodes;
|
---|
81 | CRMessageOpcodes *hdr;
|
---|
82 |
|
---|
83 | CRASSERT( buf );
|
---|
84 | CRASSERT( buf->opcode_current < buf->opcode_start );
|
---|
85 | CRASSERT( buf->opcode_current >= buf->opcode_end );
|
---|
86 | CRASSERT( buf->data_current > buf->data_start );
|
---|
87 | CRASSERT( buf->data_current <= buf->data_end );
|
---|
88 |
|
---|
89 | num_opcodes = buf->opcode_start - buf->opcode_current;
|
---|
90 | hdr = (CRMessageOpcodes *)
|
---|
91 | ( buf->data_start - ( ( num_opcodes + 3 ) & ~0x3 ) - sizeof(*hdr) );
|
---|
92 |
|
---|
93 | CRASSERT( (void *) hdr >= buf->pack );
|
---|
94 |
|
---|
95 | if (pack_spu.swap)
|
---|
96 | {
|
---|
97 | hdr->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES);
|
---|
98 | hdr->numOpcodes = SWAP32(num_opcodes);
|
---|
99 | }
|
---|
100 | else
|
---|
101 | {
|
---|
102 | hdr->header.type = CR_MESSAGE_OPCODES;
|
---|
103 | hdr->numOpcodes = num_opcodes;
|
---|
104 | }
|
---|
105 |
|
---|
106 | *len = buf->data_current - (unsigned char *) hdr;
|
---|
107 |
|
---|
108 | return hdr;
|
---|
109 | }
|
---|
110 |
|
---|
111 |
|
---|
112 | /*
|
---|
113 | * This is called from either the Pack SPU and the packer library whenever
|
---|
114 | * we need to send a data buffer to the server.
|
---|
115 | */
|
---|
116 | void packspuFlush(void *arg )
|
---|
117 | {
|
---|
118 | ThreadInfo *thread = (ThreadInfo *) arg;
|
---|
119 | ContextInfo *ctx;
|
---|
120 | unsigned int len;
|
---|
121 | CRMessageOpcodes *hdr;
|
---|
122 | CRPackBuffer *buf;
|
---|
123 |
|
---|
124 | /* we should _always_ pass a valid <arg> value */
|
---|
125 | CRASSERT(thread && thread->inUse);
|
---|
126 | #ifdef CHROMIUM_THREADSAFE
|
---|
127 | CR_LOCK_PACKER_CONTEXT(thread->packer);
|
---|
128 | #endif
|
---|
129 | ctx = thread->currentContext;
|
---|
130 | buf = &(thread->buffer);
|
---|
131 | CRASSERT(buf);
|
---|
132 |
|
---|
133 | if (ctx && ctx->fCheckZerroVertAttr)
|
---|
134 | crStateCurrentRecoverNew(ctx->clientState, &thread->packer->current);
|
---|
135 |
|
---|
136 | /* We're done packing into the current buffer, unbind it */
|
---|
137 | crPackReleaseBuffer( thread->packer );
|
---|
138 |
|
---|
139 | /*
|
---|
140 | printf("%s thread=%p thread->id = %d thread->pc=%p t2->id=%d t2->pc=%p packbuf=%p packbuf=%p\n",
|
---|
141 | __FUNCTION__, (void*) thread, (int) thread->id, thread->packer,
|
---|
142 | (int) t2->id, t2->packer,
|
---|
143 | buf->pack, thread->packer->buffer.pack);
|
---|
144 | */
|
---|
145 |
|
---|
146 | if ( buf->opcode_current == buf->opcode_start ) {
|
---|
147 | /*
|
---|
148 | printf("%s early return\n", __FUNCTION__);
|
---|
149 | */
|
---|
150 | /* XXX these calls seem to help, but might be appropriate */
|
---|
151 | crPackSetBuffer( thread->packer, buf );
|
---|
152 | crPackResetPointers(thread->packer);
|
---|
153 | #ifdef CHROMIUM_THREADSAFE
|
---|
154 | CR_UNLOCK_PACKER_CONTEXT(thread->packer);
|
---|
155 | #endif
|
---|
156 | return;
|
---|
157 | }
|
---|
158 |
|
---|
159 | hdr = __prependHeader( buf, &len, 0 );
|
---|
160 |
|
---|
161 | CRASSERT( thread->netServer.conn );
|
---|
162 |
|
---|
163 | if ( buf->holds_BeginEnd )
|
---|
164 | {
|
---|
165 | /*crDebug("crNetBarf %d, (%d)", len, buf->size);*/
|
---|
166 | crNetBarf( thread->netServer.conn, &(buf->pack), hdr, len );
|
---|
167 | }
|
---|
168 | else
|
---|
169 | {
|
---|
170 | /*crDebug("crNetSend %d, (%d)", len, buf->size);*/
|
---|
171 | crNetSend( thread->netServer.conn, &(buf->pack), hdr, len );
|
---|
172 | }
|
---|
173 |
|
---|
174 | buf->pack = crNetAlloc( thread->netServer.conn );
|
---|
175 |
|
---|
176 | /* The network may have found a new mtu */
|
---|
177 | buf->mtu = thread->netServer.conn->mtu;
|
---|
178 |
|
---|
179 | crPackSetBuffer( thread->packer, buf );
|
---|
180 |
|
---|
181 | crPackResetPointers(thread->packer);
|
---|
182 |
|
---|
183 | #ifdef CHROMIUM_THREADSAFE
|
---|
184 | CR_UNLOCK_PACKER_CONTEXT(thread->packer);
|
---|
185 | #endif
|
---|
186 | }
|
---|
187 |
|
---|
188 |
|
---|
189 | /**
|
---|
190 | * XXX NOTE: there's a lot of duplicate code here common to the
|
---|
191 | * pack, tilesort and replicate SPUs. Try to simplify someday!
|
---|
192 | */
|
---|
193 | void packspuHuge( CROpcode opcode, void *buf )
|
---|
194 | {
|
---|
195 | GET_THREAD(thread);
|
---|
196 | unsigned int len;
|
---|
197 | unsigned char *src;
|
---|
198 | CRMessageOpcodes *msg;
|
---|
199 |
|
---|
200 | CRASSERT(thread);
|
---|
201 |
|
---|
202 | /* packet length is indicated by the variable length field, and
|
---|
203 | includes an additional word for the opcode (with alignment) and
|
---|
204 | a header */
|
---|
205 | len = ((unsigned int *) buf)[-1];
|
---|
206 | if (pack_spu.swap)
|
---|
207 | {
|
---|
208 | /* It's already been swapped, swap it back. */
|
---|
209 | len = SWAP32(len);
|
---|
210 | }
|
---|
211 | len += 4 + sizeof(CRMessageOpcodes);
|
---|
212 |
|
---|
213 | /* write the opcode in just before the length */
|
---|
214 | ((unsigned char *) buf)[-5] = (unsigned char) opcode;
|
---|
215 |
|
---|
216 | /* fix up the pointer to the packet to include the length & opcode
|
---|
217 | & header */
|
---|
218 | src = (unsigned char *) buf - 8 - sizeof(CRMessageOpcodes);
|
---|
219 |
|
---|
220 | msg = (CRMessageOpcodes *) src;
|
---|
221 |
|
---|
222 | if (pack_spu.swap)
|
---|
223 | {
|
---|
224 | msg->header.type = (CRMessageType) SWAP32(CR_MESSAGE_OPCODES);
|
---|
225 | msg->numOpcodes = SWAP32(1);
|
---|
226 | }
|
---|
227 | else
|
---|
228 | {
|
---|
229 | msg->header.type = CR_MESSAGE_OPCODES;
|
---|
230 | msg->numOpcodes = 1;
|
---|
231 | }
|
---|
232 |
|
---|
233 | CRASSERT( thread->netServer.conn );
|
---|
234 | crNetSend( thread->netServer.conn, NULL, src, len );
|
---|
235 | }
|
---|
236 |
|
---|
237 | static void packspuFirstConnectToServer( CRNetServer *server
|
---|
238 | #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
|
---|
239 | , struct VBOXUHGSMI *pHgsmi
|
---|
240 | #endif
|
---|
241 | )
|
---|
242 | {
|
---|
243 | crNetInit( packspuReceiveData, NULL );
|
---|
244 | crNetServerConnect( server
|
---|
245 | #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
|
---|
246 | , pHgsmi
|
---|
247 | #endif
|
---|
248 | );
|
---|
249 | if (server->conn)
|
---|
250 | {
|
---|
251 | g_u32VBoxHostCaps = crNetHostCapsGet();
|
---|
252 | crPackCapsSet(g_u32VBoxHostCaps);
|
---|
253 | }
|
---|
254 | }
|
---|
255 |
|
---|
256 | void packspuConnectToServer( CRNetServer *server
|
---|
257 | #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
|
---|
258 | , struct VBOXUHGSMI *pHgsmi
|
---|
259 | #endif
|
---|
260 | )
|
---|
261 | {
|
---|
262 | if (pack_spu.numThreads == 0) {
|
---|
263 | packspuFirstConnectToServer( server
|
---|
264 | #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
|
---|
265 | , pHgsmi
|
---|
266 | #endif
|
---|
267 | );
|
---|
268 | if (!server->conn) {
|
---|
269 | crError("packspuConnectToServer: no connection on first create!");
|
---|
270 | return;
|
---|
271 | }
|
---|
272 | pack_spu.swap = server->conn->swap;
|
---|
273 | }
|
---|
274 | else {
|
---|
275 | /* a new pthread */
|
---|
276 | crNetNewClient(server
|
---|
277 | #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
|
---|
278 | , pHgsmi
|
---|
279 | #endif
|
---|
280 | );
|
---|
281 | }
|
---|
282 | }
|
---|