/** * Process incoming/pending message for the given client (queue entry). * \return CLIENT_GONE if this client has gone away/exited, * CLIENT_NEXT if we can advance to the next client * CLIENT_MORE if we have to process more messages for this client. */ static ClientStatus crServerServiceClient(const RunQueue *qEntry) { CRMessage *msg; CRConnection *conn; /* set current client pointer */ cr_server.curClient = qEntry->client; conn = cr_server.run_queue->client->conn; /* service current client as long as we can */ while (conn && conn->type != CR_NO_CONNECTION && crNetNumMessages(conn) > 0) { unsigned int len; /* crDebug("%d messages on %p", crNetNumMessages(conn), (void *) conn); */ /* Don't use GetMessage, because we want to do our own crNetRecv() calls * here ourself. * Note that crNetPeekMessage() DOES remove the message from the queue * if there is one. */ len = crNetPeekMessage( conn, &msg ); CRASSERT(len > 0); if (msg->header.type != CR_MESSAGE_OPCODES) { crError( "SPU %d sent me CRAP (type=0x%x)", cr_server.curClient->spu_id, msg->header.type ); } /* Do the context switch here. No sense in switching before we * really have any work to process. This is a no-op if we're * not really switching contexts. * * XXX This isn't entirely sound. The crStateMakeCurrent() call * will compute the state difference and dispatch it using * the head SPU's dispatch table. * * This is a problem if this is the first buffer coming in, * and the head SPU hasn't had a chance to do a MakeCurrent() * yet (likely because the MakeCurrent() command is in the * buffer itself). * * At best, in this case, the functions are no-ops, and * are essentially ignored by the SPU. In the typical * case, things aren't too bad; if the SPU just calls * crState*() functions to update local state, everything * will work just fine. * * In the worst (but unusual) case where a nontrivial * SPU is at the head of a crserver's SPU chain (say, * in a multiple-tiered "tilesort" arrangement, as * seen in the "multitilesort.conf" configuration), the * SPU may rely on state set during the MakeCurrent() that * may not be present yet, because no MakeCurrent() has * yet been dispatched. * * This headache will have to be revisited in the future; * for now, SPUs that could head a crserver's SPU chain * will have to detect the case that their functions are * being called outside of a MakeCurrent(), and will have * to handle the situation gracefully. (This is currently * the case with the "tilesort" SPU.) */ #if 0 crStateMakeCurrent( cr_server.curClient->currentCtx ); #else crStateMakeCurrent( cr_server.curClient->currentCtx ); /* Check if the current window is the one that the client wants to * draw into. If not, dispatch a MakeCurrent to activate the proper * window. */ if (cr_server.curClient) { int clientWindow = cr_server.curClient->currentWindow; int clientContext = cr_server.curClient->currentContextNumber; if (clientWindow && clientWindow != cr_server.currentWindow) { crServerDispatchMakeCurrent(clientWindow, 0, clientContext); /* CRASSERT(cr_server.currentWindow == clientWindow); */ } } #endif /* Force scissor, viewport and projection matrix update in * crServerSetOutputBounds(). */ cr_server.currentSerialNo = 0; /* Commands get dispatched here */ crServerDispatchMessage(msg); crNetFree( conn, msg ); if (qEntry->blocked) { /* Note/assert: we should not be inside a glBegin/End or glNewList/ * glEndList pair at this time! */ return CLIENT_NEXT; } } /* while */ /* * Check if client/connection is gone */ if (!conn || conn->type == CR_NO_CONNECTION) { crDebug("Delete client %p at %d", cr_server.run_queue->client, __LINE__); crServerDeleteClient( cr_server.run_queue->client ); return CLIENT_GONE; } /* * Determine if we can advance to next client. * If we're currently inside a glBegin/End primitive or building a display * list we can't service another client until we're done with the * primitive/list. */ if (crServerClientInBeginEnd(cr_server.curClient)) { /* The next message has to come from the current client's connection. */ CRASSERT(!qEntry->blocked); return CLIENT_MORE; } else { /* get next client */ return CLIENT_NEXT; } }
/** * Receive the next message on the given connection. * If we're being called by crSDPRecv(), we already know there's * something to receive. */ static void crSDPReceiveMessage(CRConnection *conn) { CRMessage *msg; CRMessageType cached_type; CRSDPBuffer *sdp_buffer; unsigned int len, total, leftover; const CRSocket sock = conn->sdp_socket; /* this reads the length of the message */ if ( __sdp_read_exact( sock, &len, sizeof(len)) <= 0 ) { __sdp_dead_connection( conn ); return; } if (conn->swap) len = SWAP32(len); CRASSERT( len > 0 ); if ( len <= conn->buffer_size ) { sdp_buffer = (CRSDPBuffer *) crSDPAlloc( conn ) - 1; CRASSERT(sdp_buffer->magic == CR_SDP_BUFFER_MAGIC); CRASSERT(sdp_buffer->allocated > 0); } else { crWarning("Sending as BIG, the performance is going to tank!!!. You need larger buffers!!!"); sdp_buffer = (CRSDPBuffer *) crAlloc( sizeof(*sdp_buffer) + len ); sdp_buffer->magic = CR_SDP_BUFFER_MAGIC; sdp_buffer->kind = CRSDPMemoryBig; sdp_buffer->pad = 0; } sdp_buffer->len = len; /* if we have set a userbuf, and there is room in it, we probably * want to stick the message into that, instead of our allocated * buffer. */ leftover = 0; total = len; if ((conn->userbuf != NULL) && (conn->userbuf_len >= (int) sizeof(CRMessageHeader))) { leftover = len - sizeof(CRMessageHeader); total = sizeof(CRMessageHeader); } if ( __sdp_read_exact( sock, sdp_buffer + 1, total) <= 0 ) { crWarning( "Bad juju: %d %d on sock %x", sdp_buffer->allocated, total, sock ); crFree( sdp_buffer ); __sdp_dead_connection( conn ); return; } conn->recv_credits -= total; conn->total_bytes_recv += total; msg = (CRMessage *) (sdp_buffer + 1); cached_type = msg->header.type; if (conn->swap) { msg->header.type = (CRMessageType) SWAP32( msg->header.type ); msg->header.conn_id = (CRMessageType) SWAP32( msg->header.conn_id ); } /* if there is still data pending, it should go into the user buffer */ if (leftover) { unsigned int handled = crSDPUserbufRecv(conn, msg); /* if there is anything left, plop it into the recv_buffer */ if (leftover - handled) { if ( __sdp_read_exact( sock, sdp_buffer + 1 + total, leftover-handled) <= 0 ) { crWarning( "Bad juju: %d %d", sdp_buffer->allocated, leftover-handled); crFree( sdp_buffer ); __sdp_dead_connection( conn ); return; } } conn->recv_credits -= handled; conn->total_bytes_recv += handled; } crNetDispatchMessage( cr_sdp.recv_list, conn, msg, len ); /* CR_MESSAGE_OPCODES is freed in crserverlib/server_stream.c with crNetFree. * OOB messages are the programmer's problem. -- Humper 12/17/01 */ if (cached_type != CR_MESSAGE_OPCODES && cached_type != CR_MESSAGE_OOB && cached_type != CR_MESSAGE_GATHER) { crSDPFree( conn, sdp_buffer + 1 ); } }
static DWORD WINAPI renderSPUWindowThreadProc(void* unused) { MSG msg; bool bRet; (void) unused; /* Force system to create the message queue. * Else, there's a chance that render spu will issue PostThreadMessage * before this thread calls GetMessage for first time. */ PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); crDebug("RenderSPU: Window thread started (%x)", crThreadID()); SetEvent(render_spu.hWinThreadReadyEvent); while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0) { if (bRet == -1) { crError("RenderSPU: Window thread GetMessage failed (%x)", GetLastError()); break; } else { if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW) { LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam; HWND *phWnd; CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams); phWnd = pCS->lpCreateParams; *phWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style, pCS->x, pCS->y, pCS->cx, pCS->cy, pCS->hwndParent, pCS->hMenu, pCS->hInstance, &render_spu); SetEvent(render_spu.hWinThreadReadyEvent); } else if (msg.message == WM_VBOX_RENDERSPU_DESTROY_WINDOW) { CRASSERT(msg.lParam && !msg.wParam); DestroyWindow(((VBOX_RENDERSPU_DESTROY_WINDOW*) msg.lParam)->hWnd); SetEvent(render_spu.hWinThreadReadyEvent); } else { TranslateMessage(&msg); DispatchMessage(&msg); } } } render_spu.dwWinThreadId = 0; crDebug("RenderSPU: Window thread stopped (%x)", crThreadID()); SetEvent(render_spu.hWinThreadReadyEvent); return 0; }
int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer) { CRClient *pClient = NULL; int32_t i; #ifdef VBOXCR_LOGFPS uint64_t tstart, tend; #endif /*crDebug("=>crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] && cr_server.clients[i]->conn && cr_server.clients[i]->conn->u32ClientID==u32ClientID) { pClient = cr_server.clients[i]; break; } } if (!pClient) return VERR_INVALID_PARAMETER; if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED; #ifdef VBOXCR_LOGFPS tstart = RTTimeNanoTS(); #endif CRASSERT(pBuffer); /* This should never fire unless we start to multithread */ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); /* Check if there's a blocker in queue and it's not this client */ if (cr_server.run_queue->client != pClient && crServerClientInBeginEnd(cr_server.run_queue->client)) { crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID); pClient->conn->allow_redir_ptr = 0; } else { pClient->conn->allow_redir_ptr = 1; } pClient->conn->pBuffer = pBuffer; pClient->conn->cbBuffer = cbBuffer; crNetRecv(); CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0); crServerServiceClients(); #if 0 if (pClient->currentMural) { crStateViewport( 0, 0, 500, 500 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 ); crStateViewport( 0, 0, 600, 600 ); pClient->currentMural->viewportValidated = GL_FALSE; cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 ); crStateMatrixMode(GL_PROJECTION); cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); crServerDispatchLoadIdentity(); crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crStateMatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); crServerDispatchLoadIdentity(); crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); crServerDispatchLoadIdentity(); } #endif crStateResetCurrentPointers(&cr_server.current); CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0); #ifdef VBOXCR_LOGFPS tend = RTTimeNanoTS(); pClient->timeUsed += tend-tstart; #endif /*crDebug("<=crServer: ClientWrite u32ClientID=%d", u32ClientID);*/ return VINF_SUCCESS; }
DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version) { int32_t rc, i; uint32_t ui, uiNumElems; unsigned long key; if (!cr_server.bIsInLoadingState) { /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */ cr_server.bIsInLoadingState = GL_TRUE; /* Read number of clients */ rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft); AssertRCReturn(rc, rc); } g_hackVBoxServerSaveLoadCallsLeft--; /* Do nothing until we're being called last time */ if (g_hackVBoxServerSaveLoadCallsLeft>0) { return VINF_SUCCESS; } if (version!=SHCROGL_SSM_VERSION) { return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; } /* Load and recreate rendering contexts */ rc = SSMR3GetU32(pSSM, &uiNumElems); AssertRCReturn(rc, rc); for (ui=0; ui<uiNumElems; ++ui) { CRCreateInfo_t createInfo; char psz[200]; GLint ctxID; CRContext* pContext; rc = SSMR3GetMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo)); AssertRCReturn(rc, rc); if (createInfo.pszDpyName) { rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL); AssertRCReturn(rc, rc); createInfo.pszDpyName = psz; } ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID); CRASSERT((int64_t)ctxID == (int64_t)key); pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key); CRASSERT(pContext); pContext->shared->id=-1; } /* Restore context state data */ for (ui=0; ui<uiNumElems; ++ui) { CRContext *pContext; rc = SSMR3GetMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key); CRASSERT(pContext); rc = crStateLoadContext(pContext, cr_server.contextTable, pSSM); AssertRCReturn(rc, rc); } /* Load windows */ rc = SSMR3GetU32(pSSM, &uiNumElems); AssertRCReturn(rc, rc); for (ui=0; ui<uiNumElems; ++ui) { CRCreateInfo_t createInfo; char psz[200]; GLint winID; unsigned long key; rc = SSMR3GetMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo)); AssertRCReturn(rc, rc); if (createInfo.pszDpyName) { rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL); AssertRCReturn(rc, rc); createInfo.pszDpyName = psz; } winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key); CRASSERT((int64_t)winID == (int64_t)key); } /* Load cr_server.muralTable */ rc = SSMR3GetU32(pSSM, &uiNumElems); AssertRCReturn(rc, rc); for (ui=0; ui<uiNumElems; ++ui) { CRMuralInfo muralInfo; rc = SSMR3GetMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo)); AssertRCReturn(rc, rc); if (muralInfo.pVisibleRects) { muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects); if (!muralInfo.pVisibleRects) { return VERR_NO_MEMORY; } rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects); AssertRCReturn(rc, rc); } /* Restore windows geometry info */ crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height); crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY); /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/ if (muralInfo.bReceivedRects) { crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects); } crServerDispatchWindowShow(key, muralInfo.bVisible); if (muralInfo.pVisibleRects) { crFree(muralInfo.pVisibleRects); } } /* Load starting free context and window IDs */ rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool)); CRASSERT(rc == VINF_SUCCESS); /* Load clients info */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] && cr_server.clients[i]->conn) { CRClient *pClient = cr_server.clients[i]; CRClient client; unsigned long ctxID=-1, winID=-1; rc = SSMR3GetU32(pSSM, &ui); AssertRCReturn(rc, rc); /* If this assert fires, then we should search correct client in the list first*/ CRASSERT(ui == pClient->conn->u32ClientID); if (version>=4) { rc = SSMR3GetU32(pSSM, &pClient->conn->vMajor); AssertRCReturn(rc, rc); rc = SSMR3GetU32(pSSM, &pClient->conn->vMinor); AssertRCReturn(rc, rc); } rc = SSMR3GetMem(pSSM, &client, sizeof(client)); CRASSERT(rc == VINF_SUCCESS); client.conn = pClient->conn; /* We can't reassign client number, as we'd get wrong results in TranslateTextureID * and fail to bind old textures. */ /*client.number = pClient->number;*/ *pClient = client; pClient->currentContextNumber = -1; pClient->currentCtx = cr_server.DummyContext; pClient->currentMural = NULL; pClient->currentWindow = -1; cr_server.curClient = pClient; if (client.currentCtx && client.currentContextNumber>=0) { rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID)); AssertRCReturn(rc, rc); client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID); CRASSERT(client.currentCtx); //pClient->currentCtx = client.currentCtx; //pClient->currentContextNumber = ctxID; } if (client.currentMural && client.currentWindow>=0) { rc = SSMR3GetMem(pSSM, &winID, sizeof(winID)); AssertRCReturn(rc, rc); client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID); CRASSERT(client.currentMural); //pClient->currentMural = client.currentMural; //pClient->currentWindow = winID; } /* Restore client active context and window */ crServerDispatchMakeCurrent(winID, 0, ctxID); if (0) { CRContext *tmpCtx; CRCreateInfo_t *createInfo; GLfloat one[4] = { 1, 1, 1, 1 }; GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f }; crServerDispatchMakeCurrent(winID, 0, ctxID); crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx); crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE); crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE); crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE); #ifdef CR_ARB_texture_cube_map crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE); #endif #ifdef CR_NV_texture_rectangle //@todo this doesn't work as expected //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE); #endif /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb); cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb); cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one); cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING); cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0); cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1); cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE); cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/ //crStateViewport( 0, 0, 600, 600 ); //pClient->currentMural->viewportValidated = GL_FALSE; //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 ); //crStateMatrixMode(GL_PROJECTION); //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); //crStateLoadIdentity(); //cr_server.head_spu->dispatch_table.LoadIdentity(); //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); //crStateMatrixMode(GL_MODELVIEW); //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); //crServerDispatchLoadIdentity(); //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0); //crServerDispatchLoadIdentity(); /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID); CRASSERT(createInfo); tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL); CRASSERT(tmpCtx); crStateDiffContext(tmpCtx, client.currentCtx); crStateDestroyContext(tmpCtx);*/ } } } //crServerDispatchMakeCurrent(-1, 0, -1); cr_server.curClient = NULL; { GLenum err = crServerDispatchGetError(); if (err != GL_NO_ERROR) { crWarning("crServer: glGetError %d after loading snapshot", err); } } cr_server.bIsInLoadingState = GL_FALSE; return VINF_SUCCESS; }
DECLEXPORT(void) STATE_APIENTRY crStateGLSLProgramCacheUniforms(GLuint program, GLsizei maxcbData, GLsizei *cbData, GLvoid *pData) { CRGLSLProgram *pProgram = crStateGetProgramObj(program); GLint maxUniformLen, activeUniforms=0, fakeUniformsCount, i, j; char *pCurrent = pData; GLsizei cbWritten; if (!pProgram) { crWarning("Unknown program %d", program); return; } diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen); diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms); *cbData = 0; cbWritten = sizeof(GLsizei); if (cbWritten>maxcbData) { crWarning("crStateGLSLProgramCacheUniforms: buffer too small"); return; } ((GLsizei*)pCurrent)[0] = activeUniforms; fakeUniformsCount = activeUniforms; pCurrent += sizeof(GLsizei); crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", activeUniforms); if (activeUniforms>0) { /*+8 to make sure our array uniforms with higher indices and [] will fit in as well*/ GLchar *name = (GLchar *) crAlloc(maxUniformLen+8); GLenum type; GLint size; GLsizei cbName; GLint location; if (!name) { crWarning("crStateGLSLProgramCacheUniforms: no memory"); return; } for (i=0; i<activeUniforms; ++i) { diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, &cbName, &size, &type, name); location = diff_api.GetUniformLocation(pProgram->hwid, name); if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) return; /* Only one active uniform variable will be reported for a uniform array by glGetActiveUniform, * so we insert fake elements for other array elements. */ if (size!=1) { char *pIndexStr = crStrchr(name, '['); GLint firstIndex=1; fakeUniformsCount += size; crDebug("crStateGLSLProgramCacheUniforms: expanding array uniform, size=%i", size); /*For array uniforms it's valid to query location of 1st element as both uniform and uniform[0]. *The name returned by glGetActiveUniform is driver dependent, *atleast it's with [0] on win/ati and without [0] on linux/nvidia. */ if (!pIndexStr) { pIndexStr = name+cbName; firstIndex=0; } else { cbName = pIndexStr-name; if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) return; } for (j=firstIndex; j<size; ++j) { sprintf(pIndexStr, "[%i]", j); cbName = crStrlen(name); location = diff_api.GetUniformLocation(pProgram->hwid, name); if (!crStateGLSLProgramCacheOneUniform(location, cbName, name, &pCurrent, &cbWritten, maxcbData)) return; } } } crFree(name); } if (fakeUniformsCount!=activeUniforms) { ((GLsizei*)pData)[0] = fakeUniformsCount; crDebug("FakeCount %i", fakeUniformsCount); } *cbData = cbWritten; CRASSERT((pCurrent-((char*)pData))==cbWritten); }
static void crStateBufferObjectIntCmp(CRBufferObjectBits *bb, CRbitvalue *bitID, CRContext *fromCtx, CRContext *toCtx, GLboolean bSwitch) { CRBufferObjectState *from = &(fromCtx->bufferobject); const CRBufferObjectState *to = &(toCtx->bufferobject); /* ARRAY_BUFFER */ if (CHECKDIRTY(bb->arrayBinding, bitID)) { if (from->arrayBuffer != to->arrayBuffer) { GLuint bufferID = to->arrayBuffer ? to->arrayBuffer->hwid : 0; diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, bufferID); if (bSwitch) { FILLDIRTY(bb->arrayBinding); FILLDIRTY(bb->dirty); } else { CLEARDIRTY2(bb->arrayBinding, bitID); from->arrayBuffer = to->arrayBuffer; } } if (bSwitch) CLEARDIRTY2(bb->arrayBinding, bitID); } if (to->arrayBuffer && CHECKDIRTY(to->arrayBuffer->dirty, bitID)) { /* update array buffer data */ CRBufferObject *bufObj = to->arrayBuffer; CRASSERT(bufObj); if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) { /* update whole buffer */ diff_api.BufferDataARB(GL_ARRAY_BUFFER_ARB, bufObj->size, bufObj->data, bufObj->usage); } else { /* update sub buffer */ diff_api.BufferSubDataARB(GL_ARRAY_BUFFER_ARB, bufObj->dirtyStart, bufObj->dirtyLength, (char *) bufObj->data + bufObj->dirtyStart); } if (bSwitch) FILLDIRTY(bufObj->dirty); CLEARDIRTY2(bufObj->dirty, bitID); } /* ELEMENTS_BUFFER */ if (CHECKDIRTY(bb->elementsBinding, bitID)) { if (from->elementsBuffer != to->elementsBuffer) { GLuint bufferID = to->elementsBuffer ? to->elementsBuffer->hwid : 0; diff_api.BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferID); if (bSwitch) { FILLDIRTY(bb->elementsBinding); FILLDIRTY(bb->dirty); } else { CLEARDIRTY2(bb->elementsBinding, bitID); from->elementsBuffer = to->elementsBuffer; } } if (bSwitch) CLEARDIRTY2(bb->elementsBinding, bitID); } if (to->elementsBuffer && CHECKDIRTY(to->elementsBuffer->dirty, bitID)) { /* update array buffer data */ CRBufferObject *bufObj = to->elementsBuffer; CRASSERT(bufObj); if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) { /* update whole buffer */ diff_api.BufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->size, bufObj->data, bufObj->usage); } else { /* update sub buffer */ diff_api.BufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufObj->dirtyStart, bufObj->dirtyLength, (char *) bufObj->data + bufObj->dirtyStart); } if (bSwitch) FILLDIRTY(bufObj->dirty); CLEARDIRTY2(bufObj->dirty, bitID); } #ifdef CR_ARB_pixel_buffer_object /* PIXEL_PACK_BUFFER */ if (CHECKDIRTY(bb->packBinding, bitID)) { if (from->packBuffer != to->packBuffer) { GLuint bufferID = to->packBuffer ? to->packBuffer->hwid : 0; diff_api.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, bufferID); if (bSwitch) { FILLDIRTY(bb->packBinding); FILLDIRTY(bb->dirty); } else { CLEARDIRTY2(bb->packBinding, bitID); from->packBuffer = to->packBuffer; } } if (bSwitch) CLEARDIRTY2(bb->packBinding, bitID); } if (to->packBuffer && CHECKDIRTY(to->packBuffer->dirty, bitID)) { /* update array buffer data */ CRBufferObject *bufObj = to->packBuffer; CRASSERT(bufObj); if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) { /* update whole buffer */ diff_api.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->size, bufObj->data, bufObj->usage); } else { /* update sub buffer */ diff_api.BufferSubDataARB(GL_PIXEL_PACK_BUFFER_ARB, bufObj->dirtyStart, bufObj->dirtyLength, (char *) bufObj->data + bufObj->dirtyStart); } if (bSwitch) FILLDIRTY(bufObj->dirty); CLEARDIRTY2(bufObj->dirty, bitID); } /* PIXEL_UNPACK_BUFFER */ if (CHECKDIRTY(bb->unpackBinding, bitID)) { if (from->unpackBuffer != to->unpackBuffer) { GLuint bufferID = to->unpackBuffer ? to->unpackBuffer->hwid : 0; diff_api.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID); if (bSwitch) { FILLDIRTY(bb->unpackBinding); FILLDIRTY(bb->dirty); } else { CLEARDIRTY2(bb->unpackBinding, bitID); from->unpackBuffer = to->unpackBuffer; } } if (bSwitch) CLEARDIRTY2(bb->unpackBinding, bitID); } if (to->unpackBuffer && CHECKDIRTY(to->unpackBuffer->dirty, bitID)) { /* update array buffer data */ CRBufferObject *bufObj = to->unpackBuffer; CRASSERT(bufObj); if (bufObj->dirtyStart == 0 && bufObj->dirtyLength == (int) bufObj->size) { /* update whole buffer */ diff_api.BufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->size, bufObj->data, bufObj->usage); } else { /* update sub buffer */ diff_api.BufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, bufObj->dirtyStart, bufObj->dirtyLength, (char *) bufObj->data + bufObj->dirtyStart); } if (bSwitch) FILLDIRTY(bufObj->dirty); CLEARDIRTY2(bufObj->dirty, bitID); } #endif /*ifdef CR_ARB_pixel_buffer_object*/ }
void crServerCheckMuralGeometry(CRMuralInfo *mural) { int tlS, brS, trS, blS; int overlappingScreenCount, primaryS, i; if (!mural->width || !mural->height) return; if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering) { CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId]; CRASSERT(cr_server.screenCount>0); mural->hX = mural->gX-cr_server.screen[0].x; mural->hY = mural->gY-cr_server.screen[0].y; cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y); return; } tlS = crServerGetPointScreen(mural->gX, mural->gY); brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1); if (tlS==brS && tlS>=0) { overlappingScreenCount = 1; primaryS = tlS; } else { trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY); blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1); primaryS = -1; overlappingScreenCount = 0; for (i=0; i<cr_server.screenCount; ++i) { if ((i==tlS) || (i==brS) || (i==trS) || (i==blS) || crServerMuralCoverScreen(mural, i)) { overlappingScreenCount++; primaryS = primaryS<0 ? i:primaryS; } } if (!overlappingScreenCount) { primaryS = 0; } } if (primaryS!=mural->screenId) { mural->screenId = primaryS; renderspuSetWindowId(cr_server.screen[primaryS].winID); renderspuReparentWindow(mural->spuWindow); renderspuSetWindowId(cr_server.screen[0].winID); } mural->hX = mural->gX-cr_server.screen[primaryS].x; mural->hY = mural->gY-cr_server.screen[primaryS].y; if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering) { CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId]; if (mural->bUseFBO) { crServerRedirMuralFBO(mural, GL_FALSE); crServerDeleteMuralFBO(mural); } cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y); } else { if (mural->spuWindow) { if (!mural->bUseFBO) { crServerRedirMuralFBO(mural, GL_TRUE); } else { if (mural->width!=mural->fboWidth || mural->height!=mural->height) { crServerRedirMuralFBO(mural, GL_FALSE); crServerDeleteMuralFBO(mural); crServerRedirMuralFBO(mural, GL_TRUE); } } } #ifdef DEBUG_misha else { Assert(!mural->bUseFBO); } #endif if (!mural->bUseFBO) { CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId]; cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y); } } if (mural->pvOutputRedirectInstance) { cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance, mural->hX, mural->hY, mural->width, mural->height); } }
/* * Helper for crStateCreateContext, below. */ static CRContext * crStateCreateContextId(int i, const CRLimitsState *limits, GLint visBits, CRContext *shareCtx) { CRContext *ctx = (CRContext *) crCalloc( sizeof( *ctx ) ); int j; int node32 = i >> 5; int node = i & 0x1f; ctx->id = i; #ifdef CHROMIUM_THREADSAFE VBoxTlsRefInit(ctx, crStateContextDtor); #endif ctx->flush_func = NULL; for (j=0;j<CR_MAX_BITARRAY;j++){ if (j == node32) { ctx->bitid[j] = (1 << node); } else { ctx->bitid[j] = 0; } ctx->neg_bitid[j] = ~(ctx->bitid[j]); } if (shareCtx) { CRASSERT(shareCtx->shared); ctx->shared = shareCtx->shared; ctx->shared->refCount ++; } else { ctx->shared = crStateAllocShared(); ctx->shared->id = ctx->id; } /* use Chromium's OpenGL defaults */ crStateLimitsInit( &(ctx->limits) ); crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) ); crStateBufferObjectInit( ctx ); /* must precede client state init! */ crStateClientInit( &(ctx->client) ); crStateBufferInit( ctx ); crStateCurrentInit( ctx ); crStateEvaluatorInit( ctx ); crStateFogInit( ctx ); crStateHintInit( ctx ); crStateLightingInit( ctx ); crStateLineInit( ctx ); crStateListsInit( ctx ); crStateMultisampleInit( ctx ); crStateOcclusionInit( ctx ); crStatePixelInit( ctx ); crStatePolygonInit( ctx ); crStatePointInit( ctx ); crStateProgramInit( ctx ); crStateRegCombinerInit( ctx ); crStateStencilInit( ctx ); crStateTextureInit( ctx ); crStateTransformInit( ctx ); crStateViewportInit ( ctx ); crStateFramebufferObjectInit(ctx); crStateGLSLInit(ctx); /* This has to come last. */ crStateAttribInit( &(ctx->attrib) ); ctx->renderMode = GL_RENDER; /* Initialize values that depend on the visual mode */ if (visBits & CR_DOUBLE_BIT) { ctx->limits.doubleBuffer = GL_TRUE; } if (visBits & CR_RGB_BIT) { ctx->limits.redBits = 8; ctx->limits.greenBits = 8; ctx->limits.blueBits = 8; if (visBits & CR_ALPHA_BIT) { ctx->limits.alphaBits = 8; } } else { ctx->limits.indexBits = 8; } if (visBits & CR_DEPTH_BIT) { ctx->limits.depthBits = 24; } if (visBits & CR_STENCIL_BIT) { ctx->limits.stencilBits = 8; } if (visBits & CR_ACCUM_BIT) { ctx->limits.accumRedBits = 16; ctx->limits.accumGreenBits = 16; ctx->limits.accumBlueBits = 16; if (visBits & CR_ALPHA_BIT) { ctx->limits.accumAlphaBits = 16; } } if (visBits & CR_STEREO_BIT) { ctx->limits.stereo = GL_TRUE; } if (visBits & CR_MULTISAMPLE_BIT) { ctx->limits.sampleBuffers = 1; ctx->limits.samples = 4; ctx->multisample.enabled = GL_TRUE; } if (visBits & CR_OVERLAY_BIT) { ctx->limits.level = 1; } return ctx; }
void crServerCreateMuralFBO(CRMuralInfo *mural) { CRContext *ctx = crStateGetCurrent(); GLuint uid; GLenum status; SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table; CRContextInfo *pMuralContextInfo; int RestoreSpuWindow = -1; int RestoreSpuContext = -1; CRASSERT(mural->idFBO==0); pMuralContextInfo = cr_server.currentCtxInfo; if (!pMuralContextInfo) { /* happens on saved state load */ CRASSERT(cr_server.MainContextInfo.SpuContext); pMuralContextInfo = &cr_server.MainContextInfo; cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext); RestoreSpuWindow = 0; RestoreSpuContext = 0; } /*Color texture*/ gl->GenTextures(1, &mural->idColorTex); gl->BindTexture(GL_TEXTURE_2D, mural->idColorTex); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) { gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); } gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); /*Depth&Stencil*/ gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB); gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB); gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mural->width, mural->height); /*FBO*/ gl->GenFramebuffersEXT(1, &mural->idFBO); gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->idFBO); gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, mural->idColorTex, 0); gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mural->idDepthStencilRB); gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mural->idDepthStencilRB); status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status!=GL_FRAMEBUFFER_COMPLETE_EXT) { crWarning("FBO status(0x%x) isn't complete", status); } mural->fboWidth = mural->width; mural->fboHeight = mural->height; /*PBO*/ if (cr_server.bUsePBOForReadback) { gl->GenBuffersARB(1, &mural->idPBO); gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO); gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB); gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid); if (!mural->idPBO) { crWarning("PBO create failed"); } } /*Restore gl state*/ uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid; gl->BindTexture(GL_TEXTURE_2D, uid); uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0; gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid); uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0; gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid); uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0; gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid); if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB)) { gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid); } if (RestoreSpuWindow >= 0 && RestoreSpuContext >= 0) { cr_server.head_spu->dispatch_table.MakeCurrent(RestoreSpuWindow, 0, RestoreSpuContext); } }
void crServerPresentFBO(CRMuralInfo *mural) { char *pixels=NULL, *tmppixels; GLuint uid; int i, j; CRrecti rect, rectwr, sectr; GLboolean bUsePBO; CRContext *ctx = crStateGetCurrent(); CRASSERT(cr_server.pfnPresentFBO); if (!mural->bVisible) { return; } if (!mural->width || !mural->height) { return; } if (cr_server.bUsePBOForReadback && !mural->idPBO) { crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!"); } bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO; cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->idColorTex); if (bUsePBO) { CRASSERT(mural->idPBO); cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO); } else { if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) { cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0); } pixels = crAlloc(4*mural->fboWidth*mural->fboHeight); if (!pixels) { crWarning("Out of memory in crServerPresentFBO"); return; } } /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/ cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels); /*restore gl state*/ uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid; cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid); if (bUsePBO) { pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY); if (!pixels) { crWarning("Failed to MapBuffer in crServerPresentFBO"); return; } } for (i=0; i<cr_server.screenCount; ++i) { if (crServerIntersectScreen(mural, i, &rect)) { /* rect in window relative coords */ crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY); if (!mural->pVisibleRects) { /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/ if (!mural->bReceivedRects) { tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1)); if (!tmppixels) { crWarning("Out of memory in crServerPresentFBO"); crFree(pixels); return; } crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight); /*Note: pfnPresentFBO would free tmppixels*/ cr_server.pfnPresentFBO(tmppixels, i, rect.x1-cr_server.screen[i].x, rect.y1-cr_server.screen[i].y, rect.x2-rect.x1, rect.y2-rect.y1); } } else { for (j=0; j<mural->cVisibleRects; ++j) { if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], §r)) { tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1)); if (!tmppixels) { crWarning("Out of memory in crServerPresentFBO"); crFree(pixels); return; } crServerCopySubImage(tmppixels, pixels, §r, mural->fboWidth, mural->fboHeight); /*Note: pfnPresentFBO would free tmppixels*/ cr_server.pfnPresentFBO(tmppixels, i, sectr.x1+mural->gX-cr_server.screen[i].x, sectr.y1+mural->gY-cr_server.screen[i].y, sectr.x2-sectr.x1, sectr.y2-sectr.y1); } } } } } if (mural->pvOutputRedirectInstance) { /* @todo find out why presentfbo is not called but crorframe is called. */ cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance, pixels, 4 * mural->fboWidth * mural->fboHeight); } if (bUsePBO) { cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB); cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid); } else { crFree(pixels); if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB)) { cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid); } } }
void crStatePointSwitch(CRPointBits *b, CRbitvalue *bitID, CRContext *fromCtx, CRContext *toCtx) { PCRStateTracker pState = fromCtx->pStateTracker; CRPointState *from = &(fromCtx->point); CRPointState *to = &(toCtx->point); unsigned int j, i; GLboolean fEnabled; CRbitvalue nbitID[CR_MAX_BITARRAY]; CRASSERT(fromCtx->pStateTracker == toCtx->pStateTracker); for (j=0;j<CR_MAX_BITARRAY;j++) nbitID[j] = ~bitID[j]; i = 0; /* silence compiler */ if (CHECKDIRTY(b->enableSmooth, bitID)) { glAble able[2]; able[0] = pState->diff_api.Disable; able[1] = pState->diff_api.Enable; if (from->pointSmooth != to->pointSmooth) { able[to->pointSmooth](GL_POINT_SMOOTH); FILLDIRTY(b->enableSmooth); FILLDIRTY(b->dirty); } CLEARDIRTY(b->enableSmooth, nbitID); } if (CHECKDIRTY(b->size, bitID)) { if (from->pointSize != to->pointSize) { pState->diff_api.PointSize (to->pointSize); FILLDIRTY(b->size); FILLDIRTY(b->dirty); } CLEARDIRTY(b->size, nbitID); } if (CHECKDIRTY(b->minSize, bitID)) { if (from->minSize != to->minSize) { pState->diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize); FILLDIRTY(b->minSize); FILLDIRTY(b->dirty); } CLEARDIRTY(b->minSize, nbitID); } if (CHECKDIRTY(b->maxSize, bitID)) { if (from->maxSize != to->maxSize) { pState->diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize); FILLDIRTY(b->maxSize); FILLDIRTY(b->dirty); } CLEARDIRTY(b->maxSize, nbitID); } if (CHECKDIRTY(b->fadeThresholdSize, bitID)) { if (from->fadeThresholdSize != to->fadeThresholdSize) { pState->diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize); FILLDIRTY(b->fadeThresholdSize); FILLDIRTY(b->dirty); } CLEARDIRTY(b->fadeThresholdSize, nbitID); } if (CHECKDIRTY(b->spriteCoordOrigin, bitID)) { if (from->spriteCoordOrigin != to->spriteCoordOrigin) { pState->diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin); FILLDIRTY(b->spriteCoordOrigin); FILLDIRTY(b->dirty); } CLEARDIRTY(b->spriteCoordOrigin, nbitID); } if (CHECKDIRTY(b->distanceAttenuation, bitID)) { if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { pState->diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); FILLDIRTY(b->distanceAttenuation); FILLDIRTY(b->dirty); } CLEARDIRTY(b->distanceAttenuation, nbitID); } fEnabled = from->pointSprite; { unsigned int activeUnit = (unsigned int) -1; for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { if (CHECKDIRTY(b->coordReplacement[i], bitID)) { if (!fEnabled) { pState->diff_api.Enable(GL_POINT_SPRITE_ARB); fEnabled = GL_TRUE; } #if 0 /*don't set coord replacement, it will be set just before drawing points when necessary, * to work around gpu driver bugs * See crServerDispatch[Begin|End|Draw*] */ GLint replacement = to->coordReplacement[i]; if (activeUnit != i) { diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB ); activeUnit = i; } diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement); #endif CLEARDIRTY(b->coordReplacement[i], nbitID); } } if (activeUnit != toCtx->texture.curTextureUnit) pState->diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit); } if (CHECKDIRTY(b->enableSprite, bitID)) { glAble able[2]; able[0] = pState->diff_api.Disable; able[1] = pState->diff_api.Enable; if (fEnabled != to->pointSprite) { able[to->pointSprite](GL_POINT_SPRITE_ARB); FILLDIRTY(b->enableSprite); FILLDIRTY(b->dirty); } CLEARDIRTY(b->enableSprite, nbitID); } else if (fEnabled != to->pointSprite) { glAble able[2]; able[0] = pState->diff_api.Disable; able[1] = pState->diff_api.Enable; able[to->pointSprite](GL_POINT_SPRITE_ARB); } CLEARDIRTY(b->dirty, nbitID); }
void crStatePointDiff(CRPointBits *b, CRbitvalue *bitID, CRContext *fromCtx, CRContext *toCtx) { PCRStateTracker pState = fromCtx->pStateTracker; CRPointState *from = &(fromCtx->point); CRPointState *to = &(toCtx->point); unsigned int j, i; CRbitvalue nbitID[CR_MAX_BITARRAY]; Assert(0); /** @todo Is this never called? */ CRASSERT(fromCtx->pStateTracker == toCtx->pStateTracker); for (j=0;j<CR_MAX_BITARRAY;j++) nbitID[j] = ~bitID[j]; i = 0; /* silence compiler */ if (CHECKDIRTY(b->enableSmooth, bitID)) { glAble able[2]; able[0] = pState->diff_api.Disable; able[1] = pState->diff_api.Enable; if (from->pointSmooth != to->pointSmooth) { able[to->pointSmooth](GL_POINT_SMOOTH); from->pointSmooth = to->pointSmooth; } CLEARDIRTY(b->enableSmooth, nbitID); } if (CHECKDIRTY(b->size, bitID)) { if (from->pointSize != to->pointSize) { pState->diff_api.PointSize (to->pointSize); from->pointSize = to->pointSize; } CLEARDIRTY(b->size, nbitID); } if (CHECKDIRTY(b->minSize, bitID)) { if (from->minSize != to->minSize) { pState->diff_api.PointParameterfARB (GL_POINT_SIZE_MIN_ARB, to->minSize); from->minSize = to->minSize; } CLEARDIRTY(b->minSize, nbitID); } if (CHECKDIRTY(b->maxSize, bitID)) { if (from->maxSize != to->maxSize) { pState->diff_api.PointParameterfARB (GL_POINT_SIZE_MAX_ARB, to->maxSize); from->maxSize = to->maxSize; } CLEARDIRTY(b->maxSize, nbitID); } if (CHECKDIRTY(b->fadeThresholdSize, bitID)) { if (from->fadeThresholdSize != to->fadeThresholdSize) { pState->diff_api.PointParameterfARB (GL_POINT_FADE_THRESHOLD_SIZE_ARB, to->fadeThresholdSize); from->fadeThresholdSize = to->fadeThresholdSize; } CLEARDIRTY(b->fadeThresholdSize, nbitID); } if (CHECKDIRTY(b->spriteCoordOrigin, bitID)) { if (from->spriteCoordOrigin != to->spriteCoordOrigin) { pState->diff_api.PointParameterfARB (GL_POINT_SPRITE_COORD_ORIGIN, to->spriteCoordOrigin); from->spriteCoordOrigin = to->spriteCoordOrigin; } CLEARDIRTY(b->spriteCoordOrigin, nbitID); } if (CHECKDIRTY(b->distanceAttenuation, bitID)) { if (from->distanceAttenuation[0] != to->distanceAttenuation[0] || from->distanceAttenuation[1] != to->distanceAttenuation[1] || from->distanceAttenuation[2] != to->distanceAttenuation[2]) { pState->diff_api.PointParameterfvARB (GL_POINT_DISTANCE_ATTENUATION_ARB, to->distanceAttenuation); from->distanceAttenuation[0] = to->distanceAttenuation[0]; from->distanceAttenuation[1] = to->distanceAttenuation[1]; from->distanceAttenuation[2] = to->distanceAttenuation[2]; } CLEARDIRTY(b->distanceAttenuation, nbitID); } if (CHECKDIRTY(b->enableSprite, bitID)) { glAble able[2]; able[0] = pState->diff_api.Disable; able[1] = pState->diff_api.Enable; if (from->pointSprite != to->pointSprite) { able[to->pointSprite](GL_POINT_SPRITE_ARB); from->pointSprite = to->pointSprite; } CLEARDIRTY(b->enableSprite, nbitID); } { unsigned int activeUnit = (unsigned int) -1; for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++) { if (CHECKDIRTY(b->coordReplacement[i], bitID)) { GLint replacement = to->coordReplacement[i]; if (activeUnit != i) { pState->diff_api.ActiveTextureARB(i + GL_TEXTURE0_ARB ); activeUnit = i; } pState->diff_api.TexEnviv(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, &replacement); from->coordReplacement[i] = to->coordReplacement[i]; CLEARDIRTY(b->coordReplacement[i], nbitID); } } if (activeUnit != toCtx->texture.curTextureUnit) pState->diff_api.ActiveTextureARB(GL_TEXTURE0 + toCtx->texture.curTextureUnit); } CLEARDIRTY(b->dirty, nbitID); }
GLint RENDER_APIENTRY renderspuWindowCreate( const char *dpyName, GLint visBits ) { WindowInfo *window; VisualInfo *visual; GLboolean showIt; if (!dpyName || crStrlen(render_spu.display_string) > 0) dpyName = render_spu.display_string; visual = renderspuFindVisual( dpyName, visBits ); if (!visual) { crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" ); return -1; } /* Allocate WindowInfo */ window = (WindowInfo *) crCalloc(sizeof(WindowInfo)); if (!window) { crWarning( "Render SPU: Couldn't create a window" ); return -1; } crHashtableAdd(render_spu.windowTable, render_spu.window_id, window); window->id = render_spu.window_id; render_spu.window_id++; window->x = render_spu.defaultX; window->y = render_spu.defaultY; window->width = render_spu.defaultWidth; window->height = render_spu.defaultHeight; if ((render_spu.render_to_app_window || render_spu.render_to_crut_window) && !crGetenv("CRNEWSERVER")) showIt = 0; else showIt = window->id > 0; /* Set window->title, replacing %i with the window ID number */ { const char *s = crStrstr(render_spu.window_title, "%i"); if (s) { int i, j, k; window->title = crAlloc(crStrlen(render_spu.window_title) + 10); for (i = 0; render_spu.window_title[i] != '%'; i++) window->title[i] = render_spu.window_title[i]; k = sprintf(window->title + i, "%d", window->id); CRASSERT(k < 10); i++; /* skip the 'i' after the '%' */ j = i + k; for (; (window->title[j] = s[i]) != 0; i++, j++) ; } else { window->title = crStrdup(render_spu.window_title); } } /* crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->id); */ /* Have GLX/WGL/AGL create the window */ if (!renderspu_SystemCreateWindow( visual, showIt, window )) { crFree(window); crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" ); return -1; } CRASSERT(window->visual == visual); return window->id; }
static void crStateGLSLCreateProgramCB(unsigned long key, void *data1, void *data2) { CRGLSLProgram *pProgram = (CRGLSLProgram*) data1; CRContext *ctx = (CRContext *) data2; GLuint i; pProgram->hwid = diff_api.CreateProgram(); if (pProgram->linked) { CRASSERT(pProgram->activeState.attachedShaders); crHashtableWalk(pProgram->activeState.attachedShaders, crStateFixAttachedShaderHWIDsCB, ctx); crHashtableWalk(pProgram->activeState.attachedShaders, crStateAttachShaderCB, pProgram); for (i=0; i<pProgram->activeState.cAttribs; ++i) { diff_api.BindAttribLocation(pProgram->hwid, pProgram->activeState.pAttribs[i].index, pProgram->activeState.pAttribs[i].name); } if (pProgram->validated) diff_api.ValidateProgram(pProgram->hwid); diff_api.LinkProgram(pProgram->hwid); } diff_api.UseProgram(pProgram->hwid); for (i=0; i<pProgram->cUniforms; ++i) { GLint location; GLfloat *pFdata = (GLfloat*)pProgram->pUniforms[i].data; GLint *pIdata = (GLint*)pProgram->pUniforms[i].data; location = diff_api.GetUniformLocation(pProgram->hwid, pProgram->pUniforms[i].name); switch (pProgram->pUniforms[i].type) { case GL_FLOAT: diff_api.Uniform1fv(location, 1, pFdata); break; case GL_FLOAT_VEC2: diff_api.Uniform2fv(location, 1, pFdata); break; case GL_FLOAT_VEC3: diff_api.Uniform3fv(location, 1, pFdata); break; case GL_FLOAT_VEC4: diff_api.Uniform4fv(location, 1, pFdata); break; case GL_INT: case GL_BOOL: diff_api.Uniform1iv(location, 1, pIdata); break; case GL_INT_VEC2: case GL_BOOL_VEC2: diff_api.Uniform2iv(location, 1, pIdata); break; case GL_INT_VEC3: case GL_BOOL_VEC3: diff_api.Uniform3iv(location, 1, pIdata); break; case GL_INT_VEC4: case GL_BOOL_VEC4: diff_api.Uniform4iv(location, 1, pIdata); break; case GL_FLOAT_MAT2: diff_api.UniformMatrix2fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT3: diff_api.UniformMatrix3fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT4: diff_api.UniformMatrix4fv(location, 1, GL_FALSE, pFdata); break; case GL_SAMPLER_1D: case GL_SAMPLER_2D: case GL_SAMPLER_3D: case GL_SAMPLER_CUBE: case GL_SAMPLER_1D_SHADOW: case GL_SAMPLER_2D_SHADOW: case GL_SAMPLER_2D_RECT_ARB: case GL_SAMPLER_2D_RECT_SHADOW_ARB: diff_api.Uniform1iv(location, 1, pIdata); break; #ifdef CR_OPENGL_VERSION_2_1 case GL_FLOAT_MAT2x3: diff_api.UniformMatrix2x3fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT2x4: diff_api.UniformMatrix2x4fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT3x2: diff_api.UniformMatrix3x2fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT3x4: diff_api.UniformMatrix3x4fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT4x2: diff_api.UniformMatrix4x2fv(location, 1, GL_FALSE, pFdata); break; case GL_FLOAT_MAT4x3: diff_api.UniformMatrix4x3fv(location, 1, GL_FALSE, pFdata); break; #endif default: crWarning("crStateGLSLCreateProgramCB: unknown uniform type 0x%x", (GLint)pProgram->pUniforms[i].type); break; } crFree(pProgram->pUniforms[i].data); crFree(pProgram->pUniforms[i].name); } /*for (i=0; i<pProgram->cUniforms; ++i)*/ if (pProgram->pUniforms) crFree(pProgram->pUniforms); pProgram->pUniforms = NULL; pProgram->cUniforms = 0; crHashtableWalk(pProgram->activeState.attachedShaders, crStateDetachShaderCB, pProgram); crHashtableWalk(pProgram->currentState.attachedShaders, crStateAttachShaderCB, pProgram); }
void PACKSPU_APIENTRY packspu_VBoxPackDetachThread() { 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); } }
DECLEXPORT(void) STATE_APIENTRY crStateGLSLProgramCacheUniforms(GLuint program, GLsizei cbData, GLvoid *pData) { CRGLSLProgram *pProgram = crStateGetProgramObj(program); char *pCurrent = pData; GLsizei cbRead, cbName; GLuint i; if (!pProgram) { crWarning("Unknown program %d", program); return; } if (pProgram->bUniformsSynced) { crWarning("crStateGLSLProgramCacheUniforms: this shouldn't happen!"); crStateFreeProgramUniforms(pProgram); } if (cbData<sizeof(GLsizei)) { crWarning("crStateGLSLProgramCacheUniforms: data too short"); return; } pProgram->cUniforms = ((GLsizei*)pCurrent)[0]; pCurrent += sizeof(GLsizei); cbRead = sizeof(GLsizei); crDebug("crStateGLSLProgramCacheUniforms: %i active uniforms", pProgram->cUniforms); if (pProgram->cUniforms) { pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform)); if (!pProgram->pUniforms) { crWarning("crStateGLSLProgramCacheUniforms: no memory"); pProgram->cUniforms = 0; return; } } for (i=0; i<pProgram->cUniforms; ++i) { cbRead += sizeof(GLuint)+sizeof(GLsizei); if (cbRead>cbData) { crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform %i", i); return; } pProgram->pUniforms[i].data = NULL; pProgram->pUniforms[i].location = ((GLint*)pCurrent)[0]; pCurrent += sizeof(GLint); cbName = ((GLsizei*)pCurrent)[0]; pCurrent += sizeof(GLsizei); cbRead += cbName; if (cbRead>cbData) { crWarning("crStateGLSLProgramCacheUniforms: out of data reading uniform's name %i", i); return; } pProgram->pUniforms[i].name = crStrndup(pCurrent, cbName); pCurrent += cbName; crDebug("crStateGLSLProgramCacheUniforms: uniform[%i]=%d, %s", i, pProgram->pUniforms[i].location, pProgram->pUniforms[i].name); } pProgram->bUniformsSynced = GL_TRUE; CRASSERT((pCurrent-((char*)pData))==cbRead); CRASSERT(cbRead==cbData); }
void REPLICATESPU_APIENTRY replicatespu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx ) { unsigned int i; unsigned int show_window = 0; WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, window ); ContextInfo *newCtx = (ContextInfo *) crHashtableSearch( replicate_spu.contextTable, ctx ); GET_THREAD(thread); if (!winInfo) { crWarning("Replicate SPU: Invalid window ID %d passed to MakeCurrent", window); return; } if (thread) replicatespuFlushAll( (void *)thread ); if (!thread) { thread = replicatespuNewThread( crThreadID() ); } CRASSERT(thread); CRASSERT(thread->packer); if (newCtx && winInfo) { newCtx->currentWindow = winInfo; #if 000 /* This appears to be obsolete code */ if (replicate_spu.render_to_crut_window && !nativeWindow) { char response[8096]; CRConnection *conn = crMothershipConnect(); if (!conn) { crError("Replicate SPU: Couldn't connect to the mothership to get CRUT drawable-- " "I have no idea what to do!"); } crMothershipGetParam( conn, "crut_drawable", response ); nativeWindow = crStrToInt(response); crDebug("Replicate SPU: using CRUT drawable: 0x%x", nativeWindow); crMothershipDisconnect(conn); } #endif if (replicate_spu.glx_display && winInfo && winInfo->nativeWindow != nativeWindow) { winInfo->nativeWindow = nativeWindow; replicatespuMonitorWindow(winInfo); replicatespuRePositionWindow(winInfo); show_window = 1; } CRASSERT(newCtx->State); /* verify valid */ crPackSetContext( thread->packer ); } /* * Send the MakeCurrent to all crservers (vnc viewers) */ for (i = 0; i < CR_MAX_REPLICANTS; i++) { const GLint serverWin = winInfo ? winInfo->id[i] : -1; const GLint serverCtx = newCtx ? newCtx->rserverCtx[i] : -1; if (!IS_CONNECTED(replicate_spu.rserver[i].conn)) continue; /* Note: app's native window ID not needed on server side; pass zero */ if (replicate_spu.swap) crPackMakeCurrentSWAP(serverWin, 0, serverCtx); else crPackMakeCurrent(serverWin, 0, serverCtx); if (show_window) { /* We may find that the window was mapped before we * called MakeCurrent, if that's the case then ensure * the remote end gets the WindowShow event */ if (winInfo->viewable) { if (replicate_spu.swap) crPackWindowShowSWAP(serverWin, GL_TRUE); else crPackWindowShow(serverWin, GL_TRUE); } } replicatespuFlushOne(thread, i); } if (newCtx) { crStateMakeCurrent( newCtx->State ); crDLMSetCurrentState(newCtx->dlmState); } else { crStateMakeCurrent( NULL ); crDLMSetCurrentState(NULL); } thread->currentContext = newCtx; }
void STATE_APIENTRY crStateBindBufferARB (GLenum target, GLuint buffer) { CRContext *g = GetCurrentContext(); CRBufferObjectState *b = &(g->bufferobject); CRStateBits *sb = GetCurrentBits(); CRBufferObjectBits *bb = &(sb->bufferobject); CRBufferObject *oldObj, *newObj; if (g->current.inBeginEnd) { crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBindBufferARB called in begin/end"); return; } FLUSH(); oldObj = crStateGetBoundBufferObject(target, b); if (!oldObj) { crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBindBufferARB(target)"); return; } if (buffer == 0) { newObj = b->nullBuffer; } else { newObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, buffer); if (!newObj) { newObj = AllocBufferObject(buffer); if (!newObj) { crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBindBuffer"); return; } crHashtableAdd( g->shared->buffersTable, buffer, newObj ); } } newObj->refCount++; oldObj->refCount--; switch (target) { case GL_ARRAY_BUFFER_ARB: b->arrayBuffer = newObj; DIRTY(bb->dirty, g->neg_bitid); DIRTY(bb->arrayBinding, g->neg_bitid); break; case GL_ELEMENT_ARRAY_BUFFER_ARB: b->elementsBuffer = newObj; DIRTY(bb->dirty, g->neg_bitid); DIRTY(bb->elementsBinding, g->neg_bitid); break; #ifdef CR_ARB_pixel_buffer_object case GL_PIXEL_PACK_BUFFER_ARB: b->packBuffer = newObj; DIRTY(bb->dirty, g->neg_bitid); DIRTY(bb->packBinding, g->neg_bitid); break; case GL_PIXEL_UNPACK_BUFFER_ARB: b->unpackBuffer = newObj; DIRTY(bb->dirty, g->neg_bitid); DIRTY(bb->unpackBinding, g->neg_bitid); break; #endif default: /*can't get here*/ CRASSERT(false); return; } if (oldObj->refCount <= 0) { /*we shouldn't reach this point*/ CRASSERT(false); crHashtableDelete(g->shared->buffersTable, (unsigned long) oldObj->id, crStateFreeBufferObject); } #ifdef IN_GUEST if (target == GL_PIXEL_PACK_BUFFER_ARB) { newObj->bResyncOnRead = GL_TRUE; } #endif }
/** * Determine if the X VNC extension is available. * Get list of clients/viewers attached, and replicate to them. * Can't call this until we have an X display name (see CreateContext). */ static void replicatespuStartVnc(const char *dpyName) { int maj, min; #ifdef CHROMIUM_THREADSAFE_notyet crLockMutex(&_ReplicateMutex); #endif if (replicate_spu.StartedVnc) { #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif return; } #ifdef CHROMIUM_THREADSAFE_notyet crUnlockMutex(&_ReplicateMutex); #endif /* Open the named display */ if (!replicate_spu.glx_display) { replicate_spu.glx_display = XOpenDisplay(dpyName); if (!replicate_spu.glx_display) { /* Try local display */ crWarning("Replicate SPU: Unable to open X display %s, trying :0 next", dpyName); replicate_spu.glx_display = XOpenDisplay(":0"); } if (!replicate_spu.glx_display) { crError("Replicate SPU: Unable to open X display :0"); } } CRASSERT(replicate_spu.glx_display); /* NOTE: should probably check the major/minor version too!! */ if (!XVncQueryExtension(replicate_spu.glx_display, &maj, &min)) { crWarning("Replicate SPU: X server VNC extension is not available."); replicate_spu.vncAvailable = GL_FALSE; } else { crWarning("Replicate SPU: X server VNC extension available."); replicate_spu.vncAvailable = GL_TRUE; } if (replicate_spu.vncAvailable) { VncConnectionList *vnclist; int num_conn; int i; replicate_spu.VncEventsBase = XVncGetEventBase(replicate_spu.glx_display); XVncSelectNotify(replicate_spu.glx_display, 1); vnclist = XVncListConnections(replicate_spu.glx_display, &num_conn); crDebug("Replicate SPU: Found %d open VNC connections", num_conn); for (i = 0; i < num_conn; i++) { if (vnclist[i].ipaddress) { replicatespuReplicate(vnclist[i].ipaddress); } else { crWarning("Replicate SPU: vnc client connection with no ipaddress!"); } } } replicate_spu.StartedVnc = 1; }
int main(int argc, char *argv[]) { const int port = 10000; CRConnection *conn[MAX_SERVERS]; const char *servers[MAX_SERVERS]; int numServers = 0; int bufferSize = 10000; int numBuffers = 10; int autoMode = 0; int size; int i, j; if (argc < 2) { PrintHelp(); return 0; } for (i = 1; i < argc; i++) { if (!crStrcmp(argv[i], "-a")) { autoMode = 1; } else if (!crStrcmp(argv[i], "-b") && (i + 1 < argc)) { bufferSize = crStrToInt(argv[i + 1]); i++; } else if (!crStrcmp(argv[i], "-h")) { PrintHelp(); return 0; } else if (!crStrcmp(argv[i], "-m") && (i + 1 < argc)) { MTU = crStrToInt(argv[i + 1]); i++; } else if (!crStrcmp(argv[i], "-n") && (i + 1 < argc)) { numBuffers = crStrToInt(argv[i + 1]); i++; } else if ((argv[i][0] != '-') && (numServers < MAX_SERVERS)) { servers[numServers] = argv[i]; numServers++; } } if (numServers == 0) { printf("npclient error: need to specify at least one server\n"); return 1; } if (autoMode) printf("npclient: MTU=%d (automatic buffer sizing)\n", MTU); else printf("npclient: MTU=%d bufferSize=%d numBuffers=%d\n", MTU, bufferSize, numBuffers); MyTimer = crTimerNewTimer(); crNetInit( ReceiveFunc, CloseFunc ); printf("npclient: Connecting to servers\n"); for (i = 0; i < numServers; i++) { conn[i] = crNetConnectToServer(servers[i], (unsigned short) port, MTU, 0); if (conn[i]) { printf("npclient: Connection to %s OK.\n", servers[i]); } else { printf("npclient: Connection to %s failed!\n", servers[i]); exit(1); } } printf("npclient: Testing...\n"); if (autoMode) { bufferSize = 10000; for (size = 0; size < 5; size++) { double t0, t1, dt, rate; double bytes; int buffers; bytes = 0.0; buffers = 0; crStartTimer(MyTimer); t0 = crTimerTime(MyTimer); do { for (j = 0; j < numServers; j++) { SendOpcodes(conn[j], bufferSize, 0); } bytes += (double) bufferSize; buffers++; t1 = crTimerTime(MyTimer); } while (t1 - t0 < 5.0); crStopTimer(MyTimer); dt = t1 - t0; rate = (double) bytes / dt / 1000000.0; printf("npclient: %8.3f MB/s (%d bytes / buffer, %d buffers, %d servers)\n", rate, bufferSize, buffers, numServers); if (rate < 0.0) { char *t = 0; *t = 0; CRASSERT(rate >= 0.0); } bufferSize *= 10; } } else { double t0, t1, dt, rate; double bytes; crStartTimer(MyTimer); t0 = crTimerTime(MyTimer); bytes = 0.0; for (i = 0; i < numBuffers; i++) { for (j = 0; j < numServers; j++) { SendOpcodes(conn[j], bufferSize, 0); } bytes += (double) bufferSize; } t1 = crTimerTime(MyTimer); dt = t1 - t0; rate = (double) bytes / dt / 1000000.0; printf("npclient: %8.3f MB/s (%d bytes / buffer, %d buffers, %d servers)\n", rate, bufferSize, numBuffers, numServers); } /* Send exit message to servers */ for (j = 0; j < numServers; j++) { SendOpcodes(conn[j], 100, 1); } for (j = 0; j < numServers; j++) { crNetDisconnect(conn[j]); } printf("npclient: done!\n"); return 0; }
void SERVER_DISPATCH_APIENTRY crServerDispatchDestroyContext( GLint ctx ) { CRContextInfo *crCtxInfo; CRContext *crCtx; int32_t client; CRClientNode *pNode; int found=false; crCtxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, ctx); if (!crCtxInfo) { crWarning("CRServer: DestroyContext invalid context %d", ctx); return; } crCtx = crCtxInfo->pContext; CRASSERT(crCtx); crDebug("CRServer: DestroyContext context %d", ctx); if (cr_server.currentCtxInfo == crCtxInfo) { CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits); crServerPerformMakeCurrent(dummyMural, &cr_server.MainContextInfo); CRASSERT(cr_server.currentCtxInfo == &cr_server.MainContextInfo); } crHashtableWalk(cr_server.muralTable, crServerCleanupMuralCtxUsageCB, crCtx); crCtxInfo->currentMural = NULL; crHashtableDelete(cr_server.contextTable, ctx, NULL); crStateDestroyContext( crCtx ); if (crCtxInfo->CreateInfo.pszDpyName) crFree(crCtxInfo->CreateInfo.pszDpyName); if (crCtxInfo->SpuContext >= 0) cr_server.head_spu->dispatch_table.DestroyContext(crCtxInfo->SpuContext); crFree(crCtxInfo); if (cr_server.curClient) { /* If we delete our current context, default back to the null context */ if (cr_server.curClient->currentCtxInfo == crCtxInfo) { cr_server.curClient->currentContextNumber = -1; cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo; } found = crServerRemoveClientContext(cr_server.curClient, ctx); /*Some application call destroy context not in a thread where it was created...have do deal with it.*/ if (!found) { for (client=0; client<cr_server.numClients; ++client) { if (cr_server.clients[client]==cr_server.curClient) continue; found = crServerRemoveClientContext(cr_server.clients[client], ctx); if (found) break; } } if (!found) { pNode=cr_server.pCleanupClient; while (pNode && !found) { found = crServerRemoveClientContext(pNode->pClient, ctx); pNode = pNode->next; } } CRASSERT(found); } /*Make sure this context isn't active in other clients*/ for (client=0; client<cr_server.numClients; ++client) { if (cr_server.clients[client]->currentCtxInfo == crCtxInfo) { cr_server.clients[client]->currentContextNumber = -1; cr_server.clients[client]->currentCtxInfo = &cr_server.MainContextInfo; } } pNode=cr_server.pCleanupClient; while (pNode) { if (pNode->pClient->currentCtxInfo == crCtxInfo) { pNode->pClient->currentContextNumber = -1; pNode->pClient->currentCtxInfo = &cr_server.MainContextInfo; } pNode = pNode->next; } CRASSERT(cr_server.currentCtxInfo != crCtxInfo); }
DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM) { int32_t rc, i; uint32_t ui32; GLboolean b; unsigned long key; #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE unsigned long ctxID=-1, winID=-1; #endif /* We shouldn't be called if there's no clients at all*/ CRASSERT(cr_server.numClients>0); /* @todo it's hack atm */ /* We want to be called only once to save server state but atm we're being called from svcSaveState * for every connected client (e.g. guest opengl application) */ if (!cr_server.bIsInSavingState) /* It's first call */ { cr_server.bIsInSavingState = GL_TRUE; /* Store number of clients */ rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients); AssertRCReturn(rc, rc); g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients; } g_hackVBoxServerSaveLoadCallsLeft--; /* Do nothing until we're being called last time */ if (g_hackVBoxServerSaveLoadCallsLeft>0) { return VINF_SUCCESS; } /* Save rendering contexts creation info */ ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable); rc = SSMR3PutU32(pSSM, (uint32_t) ui32); AssertRCReturn(rc, rc); crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM); #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */ if (cr_server.curClient) { ctxID = cr_server.curClient->currentContextNumber; winID = cr_server.curClient->currentWindow; } #endif /* Save contexts state tracker data */ /* @todo For now just some blind data dumps, * but I've a feeling those should be saved/restored in a very strict sequence to * allow diff_api to work correctly. * Should be tested more with multiply guest opengl apps working when saving VM snapshot. */ crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM); #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE /* Restore original win and ctx IDs*/ if (cr_server.curClient) { crServerDispatchMakeCurrent(winID, 0, ctxID); } #endif /* Save windows creation info */ ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable); rc = SSMR3PutU32(pSSM, (uint32_t) ui32); AssertRCReturn(rc, rc); crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM); /* Save cr_server.muralTable * @todo we don't need it all, just geometry info actually */ ui32 = crHashtableNumElements(cr_server.muralTable); /* There should be default mural always */ CRASSERT(ui32>=1); rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1); AssertRCReturn(rc, rc); crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM); /* Save starting free context and window IDs */ rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool)); AssertRCReturn(rc, rc); /* Save clients info */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] && cr_server.clients[i]->conn) { CRClient *pClient = cr_server.clients[i]; rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID); AssertRCReturn(rc, rc); rc = SSMR3PutU32(pSSM, pClient->conn->vMajor); AssertRCReturn(rc, rc); rc = SSMR3PutU32(pSSM, pClient->conn->vMinor); AssertRCReturn(rc, rc); rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient)); AssertRCReturn(rc, rc); if (pClient->currentCtx && pClient->currentContextNumber>=0) { b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key); CRASSERT(b); rc = SSMR3PutMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); } if (pClient->currentMural && pClient->currentWindow>=0) { b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key); CRASSERT(b); rc = SSMR3PutMem(pSSM, &key, sizeof(key)); AssertRCReturn(rc, rc); } } } cr_server.bIsInSavingState = GL_FALSE; return VINF_SUCCESS; }
GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID) { GLint retVal = -1; CRContext *newCtx; CRContextInfo *pContextInfo; GLboolean fFirst = GL_FALSE; dpyName = ""; if (shareCtx > 0) { crWarning("CRServer: context sharing not implemented."); shareCtx = 0; } pContextInfo = (CRContextInfo *) crAlloc(sizeof (CRContextInfo)); if (!pContextInfo) { crWarning("failed to alloc context info!"); return -1; } pContextInfo->currentMural = NULL; pContextInfo->CreateInfo.requestedVisualBits = visualBits; if (cr_server.fVisualBitsDefault) visualBits = cr_server.fVisualBitsDefault; pContextInfo->CreateInfo.realVisualBits = visualBits; /* Since the Cr server serialized all incoming clients/contexts into * one outgoing GL stream, we only need to create one context for the * head SPU. We'll only have to make it current once too, below. */ if (cr_server.firstCallCreateContext) { cr_server.MainContextInfo.CreateInfo.realVisualBits = visualBits; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, shareCtx); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } cr_server.MainContextInfo.pContext = crStateCreateContext(&cr_server.limits, visualBits, NULL); CRASSERT(cr_server.MainContextInfo.pContext); cr_server.firstCallCreateContext = GL_FALSE; fFirst = GL_TRUE; cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext); } else { /* second or third or ... context */ if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.realVisualBits) != visualBits)) { int oldSpuContext; /* should never be here */ CRASSERT(0); /* the new context needs new visual attributes */ cr_server.MainContextInfo.CreateInfo.realVisualBits |= visualBits; crWarning("crServerDispatchCreateContext requires new visual (0x%x).", cr_server.MainContextInfo.CreateInfo.realVisualBits); /* Here, we used to just destroy the old rendering context. * Unfortunately, this had the side effect of destroying * all display lists and textures that had been loaded on * the old context as well. * * Now, first try to create a new context, with a suitable * visual, sharing display lists and textures with the * old context. Then destroy the old context. */ /* create new rendering context with suitable visual */ oldSpuContext = cr_server.MainContextInfo.SpuContext; cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext); /* destroy old rendering context */ cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext); if (cr_server.MainContextInfo.SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crFree(pContextInfo); return -1; } /* we do not need to clean up the old default context explicitly, since the above cr_server.head_spu->dispatch_table.DestroyContext call * will do that for us */ cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext); } } if (cr_server.bUseMultipleContexts) { pContextInfo->SpuContext = cr_server.head_spu->dispatch_table. CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext); if (pContextInfo->SpuContext < 0) { crWarning("crServerDispatchCreateContext() failed."); crStateEnableDiffOnMakeCurrent(GL_TRUE); cr_server.bUseMultipleContexts = GL_FALSE; if (!fFirst) crError("creating shared context failed, while it is expected to work!"); } else if (fFirst) { crStateEnableDiffOnMakeCurrent(GL_FALSE); } } else { pContextInfo->SpuContext = -1; } /* Now create a new state-tracker context and initialize the * dispatch function pointers. */ newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID); if (newCtx) { crStateSetCurrentPointers( newCtx, &(cr_server.current) ); crStateResetCurrentPointers(&(cr_server.current)); retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID; pContextInfo->pContext = newCtx; Assert(pContextInfo->CreateInfo.realVisualBits == visualBits); pContextInfo->CreateInfo.externalID = retVal; pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL; crHashtableAdd(cr_server.contextTable, retVal, pContextInfo); } if (retVal != -1 && !cr_server.bIsInLoadingState) { int pos; for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) { if (cr_server.curClient->contextList[pos] == 0) { cr_server.curClient->contextList[pos] = retVal; break; } } } crServerReturnValue( &retVal, sizeof(retVal) ); return retVal; }
/** * Transform a bounding box from object space to NDC space. * This routine is used by most of the bucketing algorithms. * \param winInfo - which window/mural * \param server - which server (usually not needed) * \param objMin, objMax - bounds in object space * \param xmin, ymin, zmin, xmax, ymax, zmax - bounds in NDC * \param ibounds - bounds in screen coords * \return GL_TRUE if the resulting screen-space NDC bbox is visible, * GL_FALSE if the resulting screen-space NDC bbox is not visible. */ static GLboolean TransformBBox(const WindowInfo *winInfo, int server, const GLvectorf *objMin, const GLvectorf *objMax, float *xmin, float *ymin, float *zmin, float *xmax, float *ymax, float *zmax, CRrecti *ibounds) { GET_THREAD(thread); CRContext *g = thread->currentContext->State; CRTransformState *t = &(g->transform); if (thread->currentContext->providedBBOX == GL_SCREEN_BBOX_CR) { /* objMin, objMax are in NDC screen coords already */ *xmin = objMin->x; *ymin = objMin->y; *zmin = objMin->z; *xmax = objMax->x; *ymax = objMax->y; *zmax = objMax->z; } else if (winInfo->matrixSource == MATRIX_SOURCE_SERVERS) { /* Use matrices obtained from the servers */ const ServerWindowInfo *servWinInfo = winInfo->server + server; CRmatrix pv, pvm; int eye = (thread->currentContext->stereoDestFlags & EYE_RIGHT) ? 1:0; /* XXX \todo we could multiply this earlier! */ /* pv = proj matrix * view matrix */ crMatrixMultiply(&pv, &servWinInfo->projectionMatrix[eye], &servWinInfo->viewMatrix[eye]); /* pvm = pv * model matrix */ crMatrixMultiply(&pvm, &pv, t->modelViewStack.top); /* Transform bbox by modelview * projection, and project to screen */ crTransformBBox( objMin->x, objMin->y, objMin->z, objMax->x, objMax->y, objMax->z, &pvm, xmin, ymin, zmin, xmax, ymax, zmax ); } else if (winInfo->matrixSource == MATRIX_SOURCE_CONFIG && thread->currentContext->stereoDestFlags != (EYE_LEFT | EYE_RIGHT)) { /* use special left or right eye matrices (set via config options) */ const int curEye = thread->currentContext->stereoDestFlags - 1; CRmatrix pv, pvm; CRASSERT(curEye == 0 || curEye == 1); /* XXX \todo we could multiply this earlier! */ /* pv = proj matrix * view matrix */ crMatrixMultiply(&pv, &tilesort_spu.stereoProjMatrices[curEye], &tilesort_spu.stereoViewMatrices[curEye]); /* pvm = pv * model matrix */ crMatrixMultiply(&pvm, &pv, t->modelViewStack.top); /* Transform bbox by modelview * projection, and project to screen */ crTransformBBox( objMin->x, objMin->y, objMin->z, objMax->x, objMax->y, objMax->z, &pvm, xmin, ymin, zmin, xmax, ymax, zmax ); } else { const CRmatrix *mvp = &(t->modelViewProjection); CRASSERT(winInfo->matrixSource == MATRIX_SOURCE_APP || thread->currentContext->stereoDestFlags == (EYE_LEFT | EYE_RIGHT)); /* Check to make sure the transform is valid */ if (!t->modelViewProjectionValid) { /* I'm pretty sure this is always the case, but I'll leave it. */ crStateTransformUpdateTransform(t); } /* Transform bbox by modelview * projection, and project to screen */ crTransformBBox( objMin->x, objMin->y, objMin->z, objMax->x, objMax->y, objMax->z, mvp, xmin, ymin, zmin, xmax, ymax, zmax ); } /* trivial rejection test */ if (*xmin > 1.0f || *ymin > 1.0f || *xmax < -1.0f || *ymax < -1.0f) { /* bbox doesn't intersect screen */ return GL_FALSE; } /* clamp */ if (*xmin < -1.0f) *xmin = -1.0f; if (*ymin < -1.0f) *ymin = -1.0f; if (*xmax > 1.0f) *xmax = 1.0f; if (*ymax > 1.0f) *ymax = 1.0f; if (ibounds) { /* return screen pixel coords too */ ibounds->x1 = (int) (winInfo->halfViewportWidth * *xmin + winInfo->viewportCenterX); ibounds->x2 = (int) (winInfo->halfViewportWidth * *xmax + winInfo->viewportCenterX); ibounds->y1 = (int) (winInfo->halfViewportHeight * *ymin + winInfo->viewportCenterY); ibounds->y2 = (int) (winInfo->halfViewportHeight * *ymax + winInfo->viewportCenterY); } return GL_TRUE; }
void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo ) { CRMuralInfo *oldMural; CRContext *ctx, *oldCtx = NULL; GLuint idDrawFBO, idReadFBO; GLint context = ctxInfo->CreateInfo.externalID; GLint window = mural->CreateInfo.externalID; cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE; ctx = ctxInfo->pContext; CRASSERT(ctx); oldMural = cr_server.currentMural; /* Ubuntu 11.04 hosts misbehave if context window switch is * done with non-default framebuffer object settings. * crStateSwitchPrepare & crStateSwitchPostprocess are supposed to work around this problem * crStateSwitchPrepare restores the FBO state to its default values before the context window switch, * while crStateSwitchPostprocess restores it back to the original values */ oldCtx = crStateGetCurrent(); if (oldMural && oldMural->fRedirected && crServerSupportRedirMuralFBO()) { idDrawFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurDrawBuffer); idReadFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurReadBuffer); } else { idDrawFBO = 0; idReadFBO = 0; } crStateSwitchPrepare(cr_server.bUseMultipleContexts ? NULL : ctx, oldCtx, idDrawFBO, idReadFBO); if (cr_server.curClient) { /* crDebug("**** %s client %d curCtx=%d curWin=%d", __func__, cr_server.curClient->number, ctxPos, window); */ cr_server.curClient->currentContextNumber = context; cr_server.curClient->currentCtxInfo = ctxInfo; cr_server.curClient->currentMural = mural; cr_server.curClient->currentWindow = window; CRASSERT(cr_server.curClient->currentCtxInfo); CRASSERT(cr_server.curClient->currentCtxInfo->pContext); } /* This is a hack to force updating the 'current' attribs */ crStateUpdateColorBits(); if (ctx) crStateSetCurrentPointers( ctx, &(cr_server.current) ); /* check if being made current for first time, update viewport */ #if 0 if (ctx) { /* initialize the viewport */ if (ctx->viewport.viewportW == 0) { ctx->viewport.viewportW = mural->width; ctx->viewport.viewportH = mural->height; ctx->viewport.scissorW = mural->width; ctx->viewport.scissorH = mural->height; } } #endif /* crDebug("**** %s currentWindow %d newWindow %d", __func__, cr_server.currentWindow, window); */ if (1/*cr_server.firstCallMakeCurrent || cr_server.currentWindow != window || cr_server.currentNativeWindow != nativeWindow*/) { /* Since the cr server serialized all incoming contexts/clients into * one output stream of GL commands, we only need to call the head * SPU's MakeCurrent() function once. * BUT, if we're rendering to multiple windows, we do have to issue * MakeCurrent() calls sometimes. The same GL context will always be * used though. */ cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow, 0, ctxInfo->SpuContext >= 0 ? ctxInfo->SpuContext : cr_server.MainContextInfo.SpuContext); CR_STATE_SHAREDOBJ_USAGE_SET(mural, ctx); if (cr_server.currentCtxInfo) cr_server.currentCtxInfo->currentMural = NULL; ctxInfo->currentMural = mural; cr_server.firstCallMakeCurrent = GL_FALSE; cr_server.currentCtxInfo = ctxInfo; cr_server.currentWindow = window; cr_server.currentNativeWindow = 0; cr_server.currentMural = mural; } /* This used to be earlier, after crStateUpdateColorBits() call */ crStateMakeCurrent( ctx ); if (mural && mural->fRedirected && crServerSupportRedirMuralFBO()) { GLuint id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer); if (id != mural->iCurDrawBuffer) { crDebug("DBO draw buffer changed on make current"); mural->iCurDrawBuffer = id; } id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer); if (id != mural->iCurReadBuffer) { crDebug("DBO read buffer changed on make current"); mural->iCurReadBuffer = id; } idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer); idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer); } else { idDrawFBO = 0; idReadFBO = 0; } crStateSwitchPostprocess(ctx, cr_server.bUseMultipleContexts ? NULL : oldCtx, idDrawFBO, idReadFBO); if (!ctx->framebufferobject.drawFB && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT) && cr_server.curClient) cr_server.curClient->currentMural->bFbDraw = GL_TRUE; if (!mural->fRedirected) { ctx->buffer.width = mural->width; ctx->buffer.height = mural->height; } else { ctx->buffer.width = 0; ctx->buffer.height = 0; } }
static SPUFunctions * renderSPUInit( int id, SPU *child, SPU *self, unsigned int context_id, unsigned int num_contexts ) { int numFuncs, numSpecial; GLint defaultWin, defaultCtx; WindowInfo *windowInfo; (void) child; (void) context_id; (void) num_contexts; self->privatePtr = (void *) &render_spu; #ifdef CHROMIUM_THREADSAFE crDebug("Render SPU: thread-safe"); #endif crMemZero(&render_spu, sizeof(render_spu)); render_spu.id = id; renderspuSetVBoxConfiguration(&render_spu); if (render_spu.swap_master_url) swapsyncConnect(); /* Get our special functions. */ numSpecial = renderspuCreateFunctions( _cr_render_table ); #ifdef RT_OS_WINDOWS /* Start thread to create windows and process window messages */ crDebug("RenderSPU: Starting windows serving thread"); render_spu.hWinThreadReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (!render_spu.hWinThreadReadyEvent) { crError("RenderSPU: Failed to create WinThreadReadyEvent! (%x)", GetLastError()); return NULL; } if (!CreateThread(NULL, 0, renderSPUWindowThreadProc, 0, 0, &render_spu.dwWinThreadId)) { crError("RenderSPU: Failed to start windows thread! (%x)", GetLastError()); return NULL; } WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE); #endif /* Get the OpenGL functions. */ numFuncs = crLoadOpenGL( &render_spu.ws, _cr_render_table + numSpecial ); if (numFuncs == 0) { crError("The render SPU was unable to load the native OpenGL library"); return NULL; } numFuncs += numSpecial; #ifdef GLX if (!render_spu.use_glxchoosevisual) { /* sometimes want to set this option with ATI drivers */ render_spu.ws.glXChooseVisual = NULL; } #endif render_spu.window_id = 0; render_spu.context_id = 0; render_spu.contextTable = crAllocHashtable(); render_spu.windowTable = crAllocHashtable(); CRASSERT(render_spu.default_visual & CR_RGB_BIT); #ifdef USE_OSMESA if (render_spu.use_osmesa) { if (!crLoadOSMesa(&render_spu.OSMesaCreateContext, &render_spu.OSMesaMakeCurrent, &render_spu.OSMesaDestroyContext)) { crError("Unable to load OSMesa library"); } } #endif #ifdef DARWIN # ifdef VBOX_WITH_COCOA_QT # else /* VBOX_WITH_COCOA_QT */ render_spu.hRootVisibleRegion = 0; render_spu.currentBufferName = 1; render_spu.uiDockUpdateTS = 0; /* Create a mutex for synchronizing events from the main Qt thread & this thread */ RTSemFastMutexCreate(&render_spu.syncMutex); /* Create our window groups */ CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pMasterGroup); CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse | kWindowGroupAttrFixedLevel, &render_spu.pParentGroup); /* Make the correct z-layering */ SendWindowGroupBehind (render_spu.pParentGroup, render_spu.pMasterGroup); /* and set the gParentGroup as parent for gMasterGroup. */ SetWindowGroupParent (render_spu.pMasterGroup, render_spu.pParentGroup); /* Install the event handlers */ EventTypeSpec eventList[] = { {kEventClassVBox, kEventVBoxUpdateContext}, /* Update the context after show/size/move events */ {kEventClassVBox, kEventVBoxBoundsChanged} /* Clip/Pos the OpenGL windows when the main window is changed in pos/size */ }; /* We need to process events from our main window */ render_spu.hParentEventHandler = NewEventHandlerUPP(windowEvtHndlr); InstallApplicationEventHandler (render_spu.hParentEventHandler, GetEventTypeCount(eventList), eventList, NULL, NULL); render_spu.fInit = true; # endif /* VBOX_WITH_COCOA_QT */ #endif /* DARWIN */ /* * Create the default window and context. Their indexes are zero and * a client can use them without calling CreateContext or WindowCreate. */ crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)", render_spu.default_visual); defaultWin = renderspuWindowCreate( NULL, render_spu.default_visual ); if (defaultWin != 0) { crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!"); return NULL; } crDebug( "Render SPU: WindowCreate returned %d (0=normal)", defaultWin ); crDebug("Render SPU: Creating default context, visBits=0x%x", render_spu.default_visual ); defaultCtx = renderspuCreateContext( NULL, render_spu.default_visual, 0 ); CRASSERT(defaultCtx == 0); renderspuMakeCurrent( defaultWin, 0, defaultCtx ); /* Get windowInfo for the default window */ windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, 0); CRASSERT(windowInfo); windowInfo->mapPending = GL_TRUE; /* * Get the OpenGL extension functions. * SIGH -- we have to wait until the very bitter end to load the * extensions, because the context has to be bound before * wglGetProcAddress will work correctly. No such issue with GLX though. */ numFuncs += crLoadOpenGLExtensions( &render_spu.ws, _cr_render_table + numFuncs ); CRASSERT(numFuncs < 1000); #ifdef WINDOWS /* * Same problem as above, these are extensions so we need to * load them after a context has been bound. As they're WGL * extensions too, we can't simply tag them into the spu_loader. * So we do them here for now. * Grrr, NVIDIA driver uses EXT for GetExtensionsStringEXT, * but ARB for others. Need further testing here.... */ render_spu.ws.wglGetExtensionsStringEXT = (wglGetExtensionsStringEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetExtensionsStringEXT" ); render_spu.ws.wglChoosePixelFormatEXT = (wglChoosePixelFormatEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglChoosePixelFormatARB" ); render_spu.ws.wglGetPixelFormatAttribivEXT = (wglGetPixelFormatAttribivEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribivARB" ); render_spu.ws.wglGetPixelFormatAttribfvEXT = (wglGetPixelFormatAttribfvEXTFunc_t) render_spu.ws.wglGetProcAddress( "wglGetPixelFormatAttribfvARB" ); if (render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D")) { _cr_render_table[numFuncs].name = crStrdup("CopyTexSubImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glCopyTexSubImage3D"); ++numFuncs; crDebug("Render SPU: Found glCopyTexSubImage3D function"); } if (render_spu.ws.wglGetProcAddress("glDrawRangeElements")) { _cr_render_table[numFuncs].name = crStrdup("DrawRangeElements"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glDrawRangeElements"); ++numFuncs; crDebug("Render SPU: Found glDrawRangeElements function"); } if (render_spu.ws.wglGetProcAddress("glTexSubImage3D")) { _cr_render_table[numFuncs].name = crStrdup("TexSubImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexSubImage3D"); ++numFuncs; crDebug("Render SPU: Found glTexSubImage3D function"); } if (render_spu.ws.wglGetProcAddress("glTexImage3D")) { _cr_render_table[numFuncs].name = crStrdup("TexImage3D"); _cr_render_table[numFuncs].fn = (SPUGenericFunction) render_spu.ws.wglGetProcAddress("glTexImage3D"); ++numFuncs; crDebug("Render SPU: Found glTexImage3D function"); } if (render_spu.ws.wglGetExtensionsStringEXT) { crDebug("WGL - found wglGetExtensionsStringEXT\n"); } if (render_spu.ws.wglChoosePixelFormatEXT) { crDebug("WGL - found wglChoosePixelFormatEXT\n"); } #endif render_spu.barrierHash = crAllocHashtable(); render_spu.cursorX = 0; render_spu.cursorY = 0; render_spu.use_L2 = 0; render_spu.gather_conns = NULL; crDebug("Render SPU: ---------- End of Init -------------"); return &render_functions; }
void CDX9Renderer::EndBatch() { if (batch.empty()) return; if(begin_scene_nest == 0) { // Its better if this doesn't happen...but if it does...force direct x to have // a begin scene otherwise it will crash. This messes up parallel processing, // but its better than the runtime crashing! - Davo CRASSERT(d3d9_device != NULL); hr = d3d9_device->BeginScene(); } batches_per_present++; #ifdef CR_DEBUG if (debug_save_next_batch) DoBatchLog(); #endif // Lock exactly the right number of indices and vertices vertex* vertex_mem; unsigned short* index_mem; unsigned int vertex_bytes = vertices_vector.size() * sizeof(vertex); unsigned int index_bytes = indices_vector.size() * sizeof(unsigned short); // Update only when bytes are to be copied (D3D interprets 0 as 'lock entire buffer'!) if (vertex_bytes != 0) { batch_buffer->Lock(0, vertex_bytes, (void**)&vertex_mem, D3DLOCK_DISCARD); memcpy(vertex_mem, &(vertices_vector.front()), vertex_bytes); batch_buffer->Unlock(); } if (index_bytes != 0) { index_buffer->Lock(0, index_bytes, (void**)&index_mem, D3DLOCK_DISCARD); memcpy(index_mem, &(indices_vector.front()), index_bytes); index_buffer->Unlock(); } // Loop the batch doing every item BatchIterator i = batch.begin(); BatchIterator batch_end = batch.end(); for ( ; i != batch_end; ++i) (*i)->Do(); if(begin_scene_nest == 0) { // Its better if this doesn't happen...but if it does...force direct x to have // a begin scene otherwise it will crash. This messes up parallel processing, // but its better than it crashing! - Davo CRASSERT(d3d9_device != NULL); hr = d3d9_device->EndScene(); } // Put everything back ResetBatch(); }
/** * Make sure the response matches the opt's parameters (right number * and type of values, etc.) * Return 1 if OK, 0 if error. */ static int validate_option( const SPUOptions *opt, const char *response ) { const char *min = opt->min; const char *max = opt->max; int i = 0; int retval; if (opt->type == CR_STRING) return 1; CRASSERT(opt->numValues > 0); /* skip leading [ for multi-value options */ if (opt->numValues > 1) { /* multi-valued options must be enclosed in brackets */ if (*response != '[') return 0; response++; /* skip [ */ /* make sure min and max are bracketed as well */ if (min) { CRASSERT(*min == '['); /* error in <foo>spu_config.c code!!! */ min++; } if (max) { CRASSERT(*max == '['); /* error in <foo>spu_config.c code!!! */ max++; } } for (;;) { if (!validate_one_option( opt, response, min, max )) { retval = 0; break; } if (++i == opt->numValues) { retval = 1; /* all done! */ break; } /* advance pointers to next item */ if (min) { while (*min != ' ' && *min) min++; while (*min == ' ') min++; } if (max) { while (*max != ' ' && *max) max++; while (*max == ' ') max++; } if (response) { while (*response != ' ' && *response) response++; while (*response == ' ') response++; } } return retval; }
static void crServerDeleteClient( CRClient *client ) { int i, j; crDebug("Deleting client %p (%d msgs left)", client, crNetNumMessages(client->conn)); #if 0 if (crNetNumMessages(client->conn) > 0) { crDebug("Delay destroying client: message still pending"); return; } #endif if (!FindClientInQueue(client)) { /* this should never happen */ crError("CRServer: client %p not found in the queue!", client); } /* remove from clients[] array */ for (i = 0; i < cr_server.numClients; i++) { if (cr_server.clients[i] == client) { /* found it */ for (j = i; j < cr_server.numClients - 1; j++) cr_server.clients[j] = cr_server.clients[j + 1]; cr_server.numClients--; break; } } /* remove from the run queue */ if (cr_server.run_queue) { RunQueue *q = cr_server.run_queue; RunQueue *qStart = cr_server.run_queue; do { if (q->client == client) { /* this test seems a bit excessive */ if ((q->next == q->prev) && (q->next == q) && (cr_server.run_queue == q)) { /* We're removing/deleting the only client */ CRASSERT(cr_server.numClients == 0); crFree(q); cr_server.run_queue = NULL; cr_server.curClient = NULL; crDebug("Last client deleted - empty run queue."); } else { /* remove from doubly linked list and free the node */ if (cr_server.curClient == q->client) cr_server.curClient = NULL; if (cr_server.run_queue == q) cr_server.run_queue = q->next; q->prev->next = q->next; q->next->prev = q->prev; crFree(q); } break; } q = q->next; } while (q != qStart); } crNetFreeConnection(client->conn); crFree(client); }