/* * Called via unpacker module. * Note: when there's a tilesort SPU upstream, the viewport dimensions * will typically match the mural size. That is, the viewport dimensions * probably won't be the same values that the application issues. */ void SERVER_DISPATCH_APIENTRY crServerDispatchViewport( GLint x, GLint y, GLsizei width, GLsizei height ) { CRMuralInfo *mural = cr_server.curClient->currentMural; CRContext *ctx = crStateGetCurrent(); if (ctx->viewport.viewportX != x || ctx->viewport.viewportY != y || ctx->viewport.viewportW != width || ctx->viewport.viewportH != height) { /* Note -- If there are tiles, this will be overridden in the * process of decoding the BoundsInfo packet, so no worries. */ crStateViewport( x, y, width, height ); mural->viewportValidated = GL_FALSE; } if (mural->numExtents == 0) { /* non-tiling arrangment */ cr_server.head_spu->dispatch_table.Viewport(x, y, width, height); } else { if (!mural->viewportValidated) { CRViewportState *vp = &(cr_server.curClient->currentCtx->viewport); crServerComputeViewportBounds(vp, mural); crServerSetOutputBounds(mural, 0); } } }
static SPUFunctions *feedbackSPUInit( int id, SPU *child, SPU *self, unsigned int context_id, unsigned int num_contexts ) { CRContext *ctx; (void) context_id; (void) num_contexts; feedback_spu.id = id; feedback_spu.has_child = 0; if (child) { crSPUInitDispatchTable( &(feedback_spu.child) ); crSPUCopyDispatchTable( &(feedback_spu.child), &(child->dispatch_table) ); feedback_spu.has_child = 1; } crSPUInitDispatchTable( &(feedback_spu.super) ); crSPUCopyDispatchTable( &(feedback_spu.super), &(self->superSPU->dispatch_table) ); feedbackspuGatherConfiguration(); /* create/init default state tracker */ crStateInit(); ctx = crStateGetCurrent(); CRASSERT(ctx); crStateSetCurrentPointers(ctx, &feedback_spu.current); return &feedback_functions; }
void crUnpackExtendLockArraysEXT(void) { GLint first = READ_DATA(sizeof(int) + 4, GLint); GLint count = READ_DATA(sizeof(int) + 8, GLint); int numenabled = READ_DATA(sizeof(int) + 12, int); CRContext *g = crStateGetCurrent(); CRClientState *c = &g->client; CRClientPointer *cp; int i, index, offset; unsigned char *data; offset = 2*sizeof(int)+12; /*crDebug("crUnpackExtendLockArraysEXT(%i, %i) ne=%i", first, count, numenabled);*/ for (i=0; i<numenabled; ++i) { index = READ_DATA(offset, int); offset += sizeof(int); cp = crStateGetClientPointerByIndex(index, &c->array); CRASSERT(cp && cp->enabled && (!cp->buffer || !cp->buffer->id)); data = crAlloc((first+count)*cp->bytesPerIndex); crMemcpy(data+first*cp->bytesPerIndex, DATA_POINTER(offset, GLvoid), count*cp->bytesPerIndex); offset += count*cp->bytesPerIndex; /*crDebug("crUnpackExtendLockArraysEXT: old cp(%i): en/l=%i(%i) p=%p size=%i type=0x%x n=%i str=%i pp=%p pstr=%i", index, cp->enabled, cp->locked, cp->p, cp->size, cp->type, cp->normalized, cp->stride, cp->prevPtr, cp->prevStride);*/ crUnpackSetClientPointerByIndex(index, cp->size, cp->type, cp->normalized, 0, data, c); /*crDebug("crUnpackExtendLockArraysEXT: new cp(%i): en/l=%i(%i) p=%p size=%i type=0x%x n=%i str=%i pp=%p pstr=%i", index, cp->enabled, cp->locked, cp->p, cp->size, cp->type, cp->normalized, cp->stride, cp->prevPtr, cp->prevStride);*/ } cr_unpackDispatch.LockArraysEXT(first, count); }
void PACK_APIENTRY crPackLockArraysEXT(GLint first, GLint count) { CRContext *g = crStateGetCurrent(); CRClientState *c = &g->client; unsigned char *data_ptr, *start_ptr; int packet_length = sizeof(int); /*extopcode*/ int vertex_size, i, numenabled; packet_length += sizeof(first) + sizeof(count); /*params*/ numenabled = crPack_GetNumEnabledArrays(c, &vertex_size); packet_length += sizeof(int) + numenabled*sizeof(int); /*numenabled + indices*/ packet_length += vertex_size * count; /*vertices data*/ start_ptr = data_ptr = (unsigned char *) crPackAlloc(packet_length); WRITE_DATA_AI(GLenum, CR_LOCKARRAYSEXT_EXTEND_OPCODE ); WRITE_DATA_AI(GLint, first); WRITE_DATA_AI(GLint, count); WRITE_DATA_AI(int, numenabled); for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) { crPackLockClientPointer(first, count, &data_ptr, i, c); } crHugePacket(CR_EXTEND_OPCODE, start_ptr); crPackFree(start_ptr); }
static void ARRAYSPU_APIENTRY arrayspu_Disable(GLenum cap) { if (cap == GL_VERTEX_PROGRAM_NV) { crStateGetCurrent()->program.vpEnabled = GL_FALSE; } array_spu.child.Disable(cap); }
void crServerRedirMuralFBO(CRMuralInfo *mural, GLboolean redir) { if (redir) { if (!crServerSupportRedirMuralFBO()) { crWarning("FBO not supported, can't redirect window output"); return; } cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE); if (mural->idFBO==0) { crServerCreateMuralFBO(mural); } if (!crStateGetCurrent()->framebufferobject.drawFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->idFBO); } if (!crStateGetCurrent()->framebufferobject.readFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->idFBO); } if (cr_server.curClient && cr_server.curClient->currentMural == mural) { crStateGetCurrent()->buffer.width = 0; crStateGetCurrent()->buffer.height = 0; } } else { cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible); if (mural->bUseFBO && crServerSupportRedirMuralFBO()) { if (!crStateGetCurrent()->framebufferobject.drawFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); } if (!crStateGetCurrent()->framebufferobject.readFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); } } if (cr_server.curClient && cr_server.curClient->currentMural == mural) { crStateGetCurrent()->buffer.width = mural->width; crStateGetCurrent()->buffer.height = mural->height; } } mural->bUseFBO = redir; }
void SERVER_DISPATCH_APIENTRY crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context ) { CRMuralInfo *mural; CRContextInfo *ctxInfo = NULL; if (context >= 0 && window >= 0) { mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window); if (!mural) { crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window); return; } /* Update the state tracker's current context */ ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context); if (!ctxInfo) { crWarning("CRserver: NULL context in MakeCurrent %d", context); return; } } else { #if 0 oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow); if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO()) { if (!crStateGetCurrent()->framebufferobject.drawFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); } if (!crStateGetCurrent()->framebufferobject.readFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); } } ctxInfo = &cr_server.MainContextInfo; window = -1; mural = NULL; #endif cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE; return; } crServerPerformMakeCurrent( mural, ctxInfo ); }
void PACK_APIENTRY crPackDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { unsigned char *data_ptr, *start_ptr; int packet_length = sizeof(int) + sizeof(mode) + sizeof(start) + sizeof(end) + sizeof(count) + sizeof(type) + sizeof(GLuint); GLsizei indexsize; #ifdef CR_ARB_vertex_buffer_object CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; packet_length += sizeof(GLint); if (elementsBuffer && elementsBuffer->id) { /*@todo not sure it's possible, and not sure what to do*/ if (!elementsBuffer->data) { crWarning("crPackDrawElements: trying to use bound but empty elements buffer, ignoring."); return; } indexsize = 0; } else #endif { indexsize = crPackElementsIndexSize(type); } packet_length += count * indexsize; start_ptr = data_ptr = (unsigned char *) crPackAlloc(packet_length); WRITE_DATA_AI(GLenum, CR_DRAWRANGEELEMENTS_EXTEND_OPCODE); WRITE_DATA_AI(GLenum, mode); WRITE_DATA_AI(GLuint, start); WRITE_DATA_AI(GLuint, end); WRITE_DATA_AI(GLsizei, count); WRITE_DATA_AI(GLenum, type); WRITE_DATA_AI(GLuint, (GLuint) ((uintptr_t) indices)); #ifdef CR_ARB_vertex_buffer_object WRITE_DATA_AI(GLint, (GLint) (indexsize>0)); #endif if (indexsize>0) { crMemcpy(data_ptr, indices, count * indexsize); } crHugePacket(CR_EXTEND_OPCODE, start_ptr); crPackFree(start_ptr); }
void SERVER_DISPATCH_APIENTRY crServerDispatchFinish(void) { CRContext *ctx = crStateGetCurrent(); cr_server.head_spu->dispatch_table.Finish(); if (cr_server.curClient->currentMural->bFbDraw && crServerIsRedirectedToFBO()) { crServerPresentFBO(cr_server.curClient->currentMural); } if (ctx->framebufferobject.drawFB || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT)) cr_server.curClient->currentMural->bFbDraw = GL_FALSE; }
/* * Called via unpacker module. * Note: when there's a tilesort SPU upstream, the viewport dimensions * will typically match the mural size. That is, the viewport dimensions * probably won't be the same values that the application issues. */ void SERVER_DISPATCH_APIENTRY crServerDispatchViewport( GLint x, GLint y, GLsizei width, GLsizei height ) { CRMuralInfo *mural = cr_server.curClient->currentMural; CRContext *ctx = crStateGetCurrent(); if (ctx->viewport.viewportX != x || ctx->viewport.viewportY != y || ctx->viewport.viewportW != width || ctx->viewport.viewportH != height) { /* Note -- If there are tiles, this will be overridden in the * process of decoding the BoundsInfo packet, so no worries. */ crStateViewport( x, y, width, height ); } /* always dispatch to be safe */ cr_server.head_spu->dispatch_table.Viewport( x, y, width, height ); }
void PACKSPU_APIENTRY packspu_LinkProgram(GLuint program) { #ifdef VBOX_WITH_CRPACKSPU_DUMPER GLint linkStatus = 0; #endif crStateLinkProgram(program); crPackLinkProgram(program); #ifdef VBOX_WITH_CRPACKSPU_DUMPER pack_spu.self.GetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &linkStatus); Assert(linkStatus); if (!linkStatus) { CRContext *ctx = crStateGetCurrent(); packspu_RecCheckInitRec(); crRecDumpProgram(&pack_spu.Recorder, ctx, program, program); } #endif }
void PACKSPU_APIENTRY packspu_CompileShader(GLuint shader) { #ifdef VBOX_WITH_CRPACKSPU_DUMPER GLint compileStatus = 0; #endif // crStateCompileShader(shader); crPackCompileShader(shader); #ifdef VBOX_WITH_CRPACKSPU_DUMPER pack_spu.self.GetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus); Assert(compileStatus); if (!compileStatus) { CRContext *ctx = crStateGetCurrent(); packspu_RecCheckInitRec(); crRecDumpShader(&pack_spu.Recorder, ctx, shader, shader); } #endif }
void crUnpackExtendUnlockArraysEXT(void) { int i; CRContext *g = crStateGetCurrent(); CRClientState *c = &g->client; CRClientPointer *cp; /*crDebug("crUnpackExtendUnlockArraysEXT");*/ cr_unpackDispatch.UnlockArraysEXT(); for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i) { cp = crStateGetClientPointerByIndex(i, &c->array); if (cp->enabled) { /*crDebug("crUnpackExtendUnlockArraysEXT: old cp(%i): en/l=%i(%i) p=%p size=%i type=0x%x n=%i str=%i pp=%p pstr=%i", i, cp->enabled, cp->locked, cp->p, cp->size, cp->type, cp->normalized, cp->stride, cp->prevPtr, cp->prevStride);*/ crUnpackSetClientPointerByIndex(i, cp->size, cp->type, cp->normalized, cp->prevStride, cp->prevPtr, c); /*crDebug("crUnpackExtendUnlockArraysEXT: new cp(%i): en/l=%i(%i) p=%p size=%i type=0x%x n=%i str=%i pp=%p pstr=%i", i, cp->enabled, cp->locked, cp->p, cp->size, cp->type, cp->normalized, cp->stride, cp->prevPtr, cp->prevStride);*/ } } }
void PACKSPU_APIENTRY packspu_DrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices ) { GLboolean serverArrays = GL_FALSE; #if CR_ARB_vertex_buffer_object GET_CONTEXT(ctx); GLboolean lockedArrays = GL_FALSE; CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; /*crDebug("DrawElements count=%d, indices=%p", count, indices);*/ if (ctx->clientState->extensions.ARB_vertex_buffer_object) serverArrays = crStateUseServerArrays(); # ifdef CR_USE_LOCKARRAYS if (!serverArrays && !ctx->clientState->client.array.locked && (count>3) && (!elementsBuffer || !elementsBuffer->id)) { GLuint min, max; GLsizei i; switch (type) { case GL_UNSIGNED_BYTE: { GLubyte *pIdx = (GLubyte *)indices; min = max = pIdx[0]; for (i=0; i<count; ++i) { if (pIdx[i]<min) min = pIdx[i]; else if (pIdx[i]>max) max = pIdx[i]; } break; } case GL_UNSIGNED_SHORT: { GLushort *pIdx = (GLushort *)indices; min = max = pIdx[0]; for (i=0; i<count; ++i) { if (pIdx[i]<min) min = pIdx[i]; else if (pIdx[i]>max) max = pIdx[i]; } break; } case GL_UNSIGNED_INT: { GLuint *pIdx = (GLuint *)indices; min = max = pIdx[0]; for (i=0; i<count; ++i) { if (pIdx[i]<min) min = pIdx[i]; else if (pIdx[i]>max) max = pIdx[i]; } break; } default: crError("Unknown type 0x%x", type); } if ((max-min)<(GLuint)(2*count)) { crStateLockArraysEXT(min, max-min+1); serverArrays = crStateUseServerArrays(); if (serverArrays) { lockedArrays = GL_TRUE; } else { crStateUnlockArraysEXT(); } } } # endif #endif if (serverArrays) { GET_CONTEXT(ctx); CRClientState *clientState = &(ctx->clientState->client); /*Note the comment in packspu_LockArraysEXT*/ if (clientState->array.locked && !clientState->array.synced) { crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount); clientState->array.synced = GL_TRUE; } /* Send the DrawArrays command over the wire */ if (pack_spu.swap) crPackDrawElementsSWAP( mode, count, type, indices ); else crPackDrawElements( mode, count, type, indices ); } else { /* evaluate locally */ GET_CONTEXT(ctx); CRClientState *clientState = &(ctx->clientState->client); if (pack_spu.swap) crPackExpandDrawElementsSWAP( mode, count, type, indices, clientState ); else { //packspu_Begin(mode); crPackExpandDrawElements( mode, count, type, indices, clientState ); //packspu_End(); } } #if CR_ARB_vertex_buffer_object if (lockedArrays) { packspu_UnlockArraysEXT(); } #endif }
/** * Expand glDrawElements into crPackBegin/Vertex/End, etc commands. * Note: if mode==999, don't call glBegin/glEnd. */ void crPackExpandDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, CRClientState *c) { int i; GLubyte *p = (GLubyte *)indices; #ifdef CR_ARB_vertex_buffer_object CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; #endif if (count < 0) { __PackError(__LINE__, __FILE__, GL_INVALID_VALUE, "crPackDrawElements(negative count)"); return; } if (mode > GL_POLYGON && mode != 999) { __PackError(__LINE__, __FILE__, GL_INVALID_ENUM, "crPackDrawElements(bad mode)"); return; } if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) { __PackError(__LINE__, __FILE__, GL_INVALID_ENUM, "crPackDrawElements(bad type)"); return; } #ifdef CR_ARB_vertex_buffer_object if (elementsBuffer && elementsBuffer->data) { p = (unsigned char *)(elementsBuffer->data) + (unsigned long)p; } #endif if (mode != 999) crPackBegin(mode); //crDebug("crPackExpandDrawElements mode:0x%x, count:%d, type:0x%x", mode, count, type); switch (type) { case GL_UNSIGNED_BYTE: for (i=0; i<count; i++) { crPackExpandArrayElement((GLint) *p++, c); } break; case GL_UNSIGNED_SHORT: for (i=0; i<count; i++) { crPackExpandArrayElement((GLint) * (GLushort *) p, c); p+=sizeof (GLushort); } break; case GL_UNSIGNED_INT: for (i=0; i<count; i++) { crPackExpandArrayElement((GLint) * (GLuint *) p, c); p+=sizeof (GLuint); } break; default: crError( "this can't happen: array_spu.self.DrawElements" ); break; } if (mode != 999) crPackEnd(); }
void SERVER_DISPATCH_APIENTRY crServerDispatchBindFramebufferEXT(GLenum target, GLuint framebuffer) { #ifdef DEBUG_misha GLint rfb = 0, dfb = 0; #endif crStateBindFramebufferEXT(target, framebuffer); if (0==framebuffer) { CRContext *ctx = crStateGetCurrent(); if (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT || ctx->buffer.drawBuffer == GL_FRONT_RIGHT) cr_server.curClient->currentMural->bFbDraw = GL_TRUE; } if (0==framebuffer && crServerIsRedirectedToFBO()) { if (target == GL_FRAMEBUFFER) { GLuint idDrawFBO = cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurDrawBuffer]; GLuint idReadFBO = cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurReadBuffer]; if (idDrawFBO == idReadFBO) cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_FRAMEBUFFER, idDrawFBO); else { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO); cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO); } } else if (target == GL_READ_FRAMEBUFFER) { GLuint idReadFBO = cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurReadBuffer]; cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO); } else if (target == GL_DRAW_FRAMEBUFFER) { GLuint idDrawFBO = cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurDrawBuffer]; cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO); } else { crWarning("unknown target %d", target); } #ifdef DEBUG_misha cr_server.head_spu->dispatch_table.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb); cr_server.head_spu->dispatch_table.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb); if (GL_FRAMEBUFFER_EXT == target) { Assert(rfb == cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurReadBuffer]); Assert(dfb == cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurDrawBuffer]); } else if (GL_READ_FRAMEBUFFER_EXT == target) { Assert(rfb == cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurReadBuffer]); } else if (GL_DRAW_FRAMEBUFFER_EXT == target) { Assert(dfb == cr_server.curClient->currentMural->aidFBOs[cr_server.curClient->currentMural->iCurDrawBuffer]); } else { Assert(0); } #endif } else { cr_server.head_spu->dispatch_table.BindFramebufferEXT(target, crStateGetFramebufferHWID(framebuffer)); #ifdef DEBUG_misha cr_server.head_spu->dispatch_table.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb); cr_server.head_spu->dispatch_table.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb); if (GL_FRAMEBUFFER_EXT == target) { Assert(rfb == crStateGetFramebufferHWID(framebuffer)); Assert(dfb == crStateGetFramebufferHWID(framebuffer)); } else if (GL_READ_FRAMEBUFFER_EXT == target) { Assert(rfb == crStateGetFramebufferHWID(framebuffer)); } else if (GL_DRAW_FRAMEBUFFER_EXT == target) { Assert(dfb == crStateGetFramebufferHWID(framebuffer)); } else { Assert(0); } #endif } }
/* * Expand glArrayElement into crPackVertex/Color/Normal/etc. */ void crPackExpandArrayElement(GLint index, CRClientState *c) { unsigned char *p; unsigned int unit, attr; const CRVertexArrays *array = &(c->array); const GLboolean vpEnabled = crStateGetCurrent()->program.vpEnabled; /*crDebug("crPackExpandArrayElement(%i)", index);*/ if (array->n.enabled && !(vpEnabled && array->a[VERT_ATTRIB_NORMAL].enabled)) { p = array->n.p + index * array->n.stride; #ifdef CR_ARB_vertex_buffer_object if (array->n.buffer && array->n.buffer->data) { p = (unsigned char *)(array->n.buffer->data) + (unsigned long)p; } #endif switch (array->n.type) { case GL_BYTE: crPackNormal3bv((GLbyte *)p); break; case GL_SHORT: crPackNormal3sv((GLshort *)p); break; case GL_INT: crPackNormal3iv((GLint *)p); break; case GL_FLOAT: crPackNormal3fv((GLfloat *)p); break; case GL_DOUBLE: crPackNormal3dv((GLdouble *)p); break; default: crWarning("Unhandled: crPackExpandArrayElement, array->n.type 0x%x", array->n.type); } } if (array->c.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR0].enabled)) { p = array->c.p + index * array->c.stride; #ifdef CR_ARB_vertex_buffer_object if (array->c.buffer && array->c.buffer->data) { p = (unsigned char *)(array->c.buffer->data) + (unsigned long)p; } #endif switch (array->c.type) { case GL_BYTE: switch (c->array.c.size) { case 3: crPackColor3bv((GLbyte *)p); break; case 4: crPackColor4bv((GLbyte *)p); break; } break; case GL_UNSIGNED_BYTE: switch (c->array.c.size) { case 3: crPackColor3ubv((GLubyte *)p); break; case 4: crPackColor4ubv((GLubyte *)p); break; } break; case GL_SHORT: switch (c->array.c.size) { case 3: crPackColor3sv((GLshort *)p); break; case 4: crPackColor4sv((GLshort *)p); break; } break; case GL_UNSIGNED_SHORT: switch (c->array.c.size) { case 3: crPackColor3usv((GLushort *)p); break; case 4: crPackColor4usv((GLushort *)p); break; } break; case GL_INT: switch (c->array.c.size) { case 3: crPackColor3iv((GLint *)p); break; case 4: crPackColor4iv((GLint *)p); break; } break; case GL_UNSIGNED_INT: switch (c->array.c.size) { case 3: crPackColor3uiv((GLuint *)p); break; case 4: crPackColor4uiv((GLuint *)p); break; } break; case GL_FLOAT: switch (c->array.c.size) { case 3: crPackColor3fv((GLfloat *)p); break; case 4: crPackColor4fv((GLfloat *)p); break; } break; case GL_DOUBLE: switch (c->array.c.size) { case 3: crPackColor3dv((GLdouble *)p); break; case 4: crPackColor4dv((GLdouble *)p); break; } break; default: crWarning("Unhandled: crPackExpandArrayElement, array->c.type 0x%x", array->c.type); } } #ifdef CR_EXT_secondary_color if (array->s.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR1].enabled)) { p = array->s.p + index * array->s.stride; #ifdef CR_ARB_vertex_buffer_object if (array->s.buffer && array->s.buffer->data) { p = (unsigned char *)(array->s.buffer->data) + (unsigned long)p; } #endif switch (array->s.type) { case GL_BYTE: crPackSecondaryColor3bvEXT((GLbyte *)p); break; case GL_UNSIGNED_BYTE: crPackSecondaryColor3ubvEXT((GLubyte *)p); break; case GL_SHORT: crPackSecondaryColor3svEXT((GLshort *)p); break; case GL_UNSIGNED_SHORT: crPackSecondaryColor3usvEXT((GLushort *)p); break; case GL_INT: crPackSecondaryColor3ivEXT((GLint *)p); break; case GL_UNSIGNED_INT: crPackSecondaryColor3uivEXT((GLuint *)p); break; case GL_FLOAT: crPackSecondaryColor3fvEXT((GLfloat *)p); break; case GL_DOUBLE: crPackSecondaryColor3dvEXT((GLdouble *)p); break; default: crWarning("Unhandled: crPackExpandArrayElement, array->s.type 0x%x", array->s.type); } } #endif // CR_EXT_secondary_color #ifdef CR_EXT_fog_coord if (array->f.enabled && !(vpEnabled && array->a[VERT_ATTRIB_FOG].enabled)) { p = array->f.p + index * array->f.stride; #ifdef CR_ARB_vertex_buffer_object if (array->f.buffer && array->f.buffer->data) { p = (unsigned char *)(array->f.buffer->data) + (unsigned long)p; } #endif crPackFogCoordfEXT( *((GLfloat *) p) ); } #endif // CR_EXT_fog_coord for (unit = 0 ; unit < CR_MAX_TEXTURE_UNITS ; unit++) { if (array->t[unit].enabled && !(vpEnabled && array->a[VERT_ATTRIB_TEX0+unit].enabled)) { p = array->t[unit].p + index * array->t[unit].stride; #ifdef CR_ARB_vertex_buffer_object if (array->t[unit].buffer && array->t[unit].buffer->data) { p = (unsigned char *)(array->t[unit].buffer->data) + (unsigned long)p; } #endif switch (array->t[unit].type) { case GL_SHORT: switch (array->t[unit].size) { case 1: crPackMultiTexCoord1svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 2: crPackMultiTexCoord2svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 3: crPackMultiTexCoord3svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 4: crPackMultiTexCoord4svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; } break; case GL_INT: switch (array->t[unit].size) { case 1: crPackMultiTexCoord1ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 2: crPackMultiTexCoord2ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 3: crPackMultiTexCoord3ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 4: crPackMultiTexCoord4ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; } break; case GL_FLOAT: switch (array->t[unit].size) { case 1: crPackMultiTexCoord1fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 2: crPackMultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 3: crPackMultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 4: crPackMultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->t[unit].size) { case 1: crPackMultiTexCoord1dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 2: crPackMultiTexCoord2dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 3: crPackMultiTexCoord3dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 4: crPackMultiTexCoord4dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; } break; default: crWarning("Unhandled: crPackExpandArrayElement, array->t[%i].type 0x%x", unit, array->t[unit].type); } } } if (array->i.enabled) { p = array->i.p + index * array->i.stride; #ifdef CR_ARB_vertex_buffer_object if (array->i.buffer && array->i.buffer->data) { p = (unsigned char *)(array->i.buffer->data) + (unsigned long)p; } #endif switch (array->i.type) { case GL_SHORT: crPackIndexsv((GLshort *)p); break; case GL_INT: crPackIndexiv((GLint *)p); break; case GL_FLOAT: crPackIndexfv((GLfloat *)p); break; case GL_DOUBLE: crPackIndexdv((GLdouble *)p); break; default: crWarning("Unhandled: crPackExpandArrayElement, array->i.type 0x%x", array->i.type); } } if (array->e.enabled) { p = array->e.p + index * array->e.stride; #ifdef CR_ARB_vertex_buffer_object if (array->e.buffer && array->e.buffer->data) { p = (unsigned char *)(array->e.buffer->data) + (unsigned long)p; } #endif crPackEdgeFlagv(p); } for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { if (array->a[attr].enabled) { crPackVertexAttrib(array, attr, index); } } if (array->a[VERT_ATTRIB_POS].enabled) { crPackVertexAttrib(array, VERT_ATTRIB_POS, index); } else if (array->v.enabled) { p = array->v.p + index * array->v.stride; #ifdef CR_ARB_vertex_buffer_object if (array->v.buffer && array->v.buffer->data) { p = (unsigned char *)(array->v.buffer->data) + (unsigned long)p; } #endif switch (array->v.type) { case GL_SHORT: switch (c->array.v.size) { case 2: crPackVertex2sv((GLshort *)p); break; case 3: crPackVertex3sv((GLshort *)p); break; case 4: crPackVertex4sv((GLshort *)p); break; } break; case GL_INT: switch (c->array.v.size) { case 2: crPackVertex2iv((GLint *)p); break; case 3: crPackVertex3iv((GLint *)p); break; case 4: crPackVertex4iv((GLint *)p); break; } break; case GL_FLOAT: switch (c->array.v.size) { case 2: crPackVertex2fv((GLfloat *)p); break; case 3: crPackVertex3fv((GLfloat *)p); break; case 4: crPackVertex4fv((GLfloat *)p); break; } break; case GL_DOUBLE: switch (c->array.v.size) { case 2: crPackVertex2dv((GLdouble *)p); break; case 3: crPackVertex3dv((GLdouble *)p); break; case 4: crPackVertex4dv((GLdouble *)p); break; } break; default: crWarning("Unhandled: crPackExpandArrayElement, array->v.type 0x%x", array->v.type); } } }
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; } }
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 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); } }
/** * Do CRServer initializations. After this, we can begin servicing clients. */ GLboolean crVBoxServerInit(void) { CRMuralInfo *defaultMural; #if DEBUG_FP_EXCEPTIONS { fpu_control_t mask; _FPU_GETCW(mask); mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM | _FPU_MASK_OM | _FPU_MASK_UM); _FPU_SETCW(mask); } #endif crNetInit(crServerRecv, crServerClose); cr_server.firstCallCreateContext = GL_TRUE; cr_server.firstCallMakeCurrent = GL_TRUE; cr_server.bIsInLoadingState = GL_FALSE; cr_server.bIsInSavingState = GL_FALSE; cr_server.pCleanupClient = NULL; /* * Create default mural info and hash table. */ cr_server.muralTable = crAllocHashtable(); defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo)); crHashtableAdd(cr_server.muralTable, 0, defaultMural); cr_server.programTable = crAllocHashtable(); crStateInit(); crStateLimitsInit( &(cr_server.limits) ); cr_server.barriers = crAllocHashtable(); cr_server.semaphores = crAllocHashtable(); crUnpackSetReturnPointer( &(cr_server.return_ptr) ); crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) ); /* * Default context */ cr_server.contextTable = crAllocHashtable(); cr_server.DummyContext = crStateCreateContext( &cr_server.limits, CR_RGB_BIT | CR_DEPTH_BIT, NULL ); cr_server.pContextCreateInfoTable = crAllocHashtable(); cr_server.pWindowCreateInfoTable = crAllocHashtable(); crServerSetVBoxConfigurationHGCM(); if (!cr_server.head_spu) return GL_FALSE; crServerInitDispatch(); crStateDiffAPI( &(cr_server.head_spu->dispatch_table) ); /*Check for PBO support*/ if (crStateGetCurrent()->extensions.ARB_pixel_buffer_object) { cr_server.bUsePBOForReadback=GL_TRUE; } return GL_TRUE; }
/*@todo: it's a hack, as GLSL shouldn't blindly reuse this bit from nv_vertex_program*/ static void ARRAYSPU_APIENTRY arrayspu_UseProgram(GLuint program) { crStateGetCurrent()->program.vpEnabled = program>0; array_spu.child.UseProgram(program); }
static void ARRAYSPU_APIENTRY arrayspu_ArrayElement( GLint index ) { const CRClientState *c = &(crStateGetCurrent()->client); const CRVertexArrays *array = &(c->array); const GLboolean vpEnabled = crStateGetCurrent()->program.vpEnabled; unsigned char *p; unsigned int unit, attr; if (array->e.enabled) { p = array->e.p + index * array->e.stride; #ifdef CR_ARB_vertex_buffer_object if (array->e.buffer && array->e.buffer->data) { p = (unsigned char *)(array->e.buffer->data) + (unsigned long)p; } #endif array_spu.self.EdgeFlagv(p); } /* * Vertex attribute arrays (GL_NV_vertex_program) have priority over * the conventional vertex arrays. */ if (vpEnabled) { for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { if (array->a[attr].enabled) { GLint *iPtr; p = array->a[attr].p + index * array->a[attr].stride; #ifdef CR_ARB_vertex_buffer_object if (array->a[attr].buffer && array->a[attr].buffer->data) { p = (unsigned char *)(array->a[attr].buffer->data) + (unsigned long)p; } #endif switch (array->a[attr].type) { case GL_SHORT: switch (array->a[attr].size) { case 1: array_spu.self.VertexAttrib1svARB(attr, (GLshort *)p); break; case 2: array_spu.self.VertexAttrib2svARB(attr, (GLshort *)p); break; case 3: array_spu.self.VertexAttrib3svARB(attr, (GLshort *)p); break; case 4: array_spu.self.VertexAttrib4svARB(attr, (GLshort *)p); break; } break; case GL_INT: iPtr = (GLint *) p; switch (array->a[attr].size) { case 1: array_spu.self.VertexAttrib1fARB(attr, p[0]); break; case 2: array_spu.self.VertexAttrib2fARB(attr, p[0], p[1]); break; case 3: array_spu.self.VertexAttrib3fARB(attr, p[0], p[1], p[2]); break; case 4: array_spu.self.VertexAttrib4fARB(attr, p[0], p[1], p[2], p[3]); break; } break; case GL_FLOAT: switch (array->a[attr].size) { case 1: array_spu.self.VertexAttrib1fvARB(attr, (GLfloat *)p); break; case 2: array_spu.self.VertexAttrib2fvARB(attr, (GLfloat *)p); break; case 3: array_spu.self.VertexAttrib3fvARB(attr, (GLfloat *)p); break; case 4: array_spu.self.VertexAttrib4fvARB(attr, (GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->a[attr].size) { case 1: array_spu.self.VertexAttrib1dvARB(attr, (GLdouble *)p); break; case 2: array_spu.self.VertexAttrib2dvARB(attr, (GLdouble *)p); break; case 3: array_spu.self.VertexAttrib3dvARB(attr, (GLdouble *)p); break; case 4: array_spu.self.VertexAttrib4dvARB(attr, (GLdouble *)p); break; } break; default: crWarning("Bad datatype for vertex attribute [%d] array: 0x%x\n", attr, array->a[attr].type); } } } } /* Now do conventional arrays, unless overridden by generic arrays above */ for (unit = 0 ; unit < crStateGetCurrent()->limits.maxTextureUnits ; unit++) { if (array->t[unit].enabled && !(vpEnabled && array->a[VERT_ATTRIB_TEX0+unit].enabled)) { p = array->t[unit].p + index * array->t[unit].stride; #ifdef CR_ARB_vertex_buffer_object if (array->t[unit].buffer && array->t[unit].buffer->data) { p = (unsigned char *)(array->t[unit].buffer->data) + (unsigned long)p; } #endif switch (array->t[unit].type) { case GL_SHORT: switch (array->t[unit].size) { case 1: array_spu.self.MultiTexCoord1svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 2: array_spu.self.MultiTexCoord2svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 3: array_spu.self.MultiTexCoord3svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; case 4: array_spu.self.MultiTexCoord4svARB(GL_TEXTURE0_ARB + unit, (GLshort *)p); break; } break; case GL_INT: switch (array->t[unit].size) { case 1: array_spu.self.MultiTexCoord1ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 2: array_spu.self.MultiTexCoord2ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 3: array_spu.self.MultiTexCoord3ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; case 4: array_spu.self.MultiTexCoord4ivARB(GL_TEXTURE0_ARB + unit, (GLint *)p); break; } break; case GL_FLOAT: switch (array->t[unit].size) { case 1: array_spu.self.MultiTexCoord1fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 2: array_spu.self.MultiTexCoord2fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 3: array_spu.self.MultiTexCoord3fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; case 4: array_spu.self.MultiTexCoord4fvARB(GL_TEXTURE0_ARB + unit, (GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->t[unit].size) { case 1: array_spu.self.MultiTexCoord1dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 2: array_spu.self.MultiTexCoord2dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 3: array_spu.self.MultiTexCoord3dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; case 4: array_spu.self.MultiTexCoord4dvARB(GL_TEXTURE0_ARB + unit, (GLdouble *)p); break; } break; } } } if (array->i.enabled) { p = array->i.p + index * array->i.stride; #ifdef CR_ARB_vertex_buffer_object if (array->i.buffer && array->i.buffer->data) { p = (unsigned char *)(array->i.buffer->data) + (unsigned long)p; } #endif switch (array->i.type) { case GL_SHORT: array_spu.self.Indexsv((GLshort *)p); break; case GL_INT: array_spu.self.Indexiv((GLint *)p); break; case GL_FLOAT: array_spu.self.Indexfv((GLfloat *)p); break; case GL_DOUBLE: array_spu.self.Indexdv((GLdouble *)p); break; } } if (array->c.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR0].enabled)) { p = array->c.p + index * array->c.stride; #ifdef CR_ARB_vertex_buffer_object if (array->c.buffer && array->c.buffer->data) { p = (unsigned char *)(array->c.buffer->data) + (unsigned long)p; } #endif switch (array->c.type) { case GL_BYTE: switch (array->c.size) { case 3: array_spu.self.Color3bv((GLbyte *)p); break; case 4: array_spu.self.Color4bv((GLbyte *)p); break; } break; case GL_UNSIGNED_BYTE: switch (array->c.size) { case 3: array_spu.self.Color3ubv((GLubyte *)p); break; case 4: array_spu.self.Color4ubv((GLubyte *)p); break; } break; case GL_SHORT: switch (array->c.size) { case 3: array_spu.self.Color3sv((GLshort *)p); break; case 4: array_spu.self.Color4sv((GLshort *)p); break; } break; case GL_UNSIGNED_SHORT: switch (array->c.size) { case 3: array_spu.self.Color3usv((GLushort *)p); break; case 4: array_spu.self.Color4usv((GLushort *)p); break; } break; case GL_INT: switch (array->c.size) { case 3: array_spu.self.Color3iv((GLint *)p); break; case 4: array_spu.self.Color4iv((GLint *)p); break; } break; case GL_UNSIGNED_INT: switch (array->c.size) { case 3: array_spu.self.Color3uiv((GLuint *)p); break; case 4: array_spu.self.Color4uiv((GLuint *)p); break; } break; case GL_FLOAT: switch (array->c.size) { case 3: array_spu.self.Color3fv((GLfloat *)p); break; case 4: array_spu.self.Color4fv((GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->c.size) { case 3: array_spu.self.Color3dv((GLdouble *)p); break; case 4: array_spu.self.Color4dv((GLdouble *)p); break; } break; } } if (array->n.enabled && !(vpEnabled && array->a[VERT_ATTRIB_NORMAL].enabled)) { p = array->n.p + index * array->n.stride; #ifdef CR_ARB_vertex_buffer_object if (array->n.buffer && array->n.buffer->data) { p = (unsigned char *)(array->n.buffer->data) + (unsigned long)p; } #endif switch (array->n.type) { case GL_BYTE: array_spu.self.Normal3bv((GLbyte *)p); break; case GL_SHORT: array_spu.self.Normal3sv((GLshort *)p); break; case GL_INT: array_spu.self.Normal3iv((GLint *)p); break; case GL_FLOAT: array_spu.self.Normal3fv((GLfloat *)p); break; case GL_DOUBLE: array_spu.self.Normal3dv((GLdouble *)p); break; } } #ifdef CR_EXT_secondary_color if (array->s.enabled && !(vpEnabled && array->a[VERT_ATTRIB_COLOR1].enabled)) { p = array->s.p + index * array->s.stride; #ifdef CR_ARB_vertex_buffer_object if (array->s.buffer && array->s.buffer->data) { p = (unsigned char *)(array->s.buffer->data) + (unsigned long)p; } #endif switch (array->s.type) { case GL_BYTE: array_spu.self.SecondaryColor3bvEXT((GLbyte *)p); break; case GL_UNSIGNED_BYTE: array_spu.self.SecondaryColor3ubvEXT((GLubyte *)p); break; case GL_SHORT: array_spu.self.SecondaryColor3svEXT((GLshort *)p); break; case GL_UNSIGNED_SHORT: array_spu.self.SecondaryColor3usvEXT((GLushort *)p); break; case GL_INT: array_spu.self.SecondaryColor3ivEXT((GLint *)p); break; case GL_UNSIGNED_INT: array_spu.self.SecondaryColor3uivEXT((GLuint *)p); break; case GL_FLOAT: array_spu.self.SecondaryColor3fvEXT((GLfloat *)p); break; case GL_DOUBLE: array_spu.self.SecondaryColor3dvEXT((GLdouble *)p); break; } } #endif // CR_EXT_secondary_color #ifdef CR_EXT_fog_coord if (array->f.enabled && !(vpEnabled && array->a[VERT_ATTRIB_FOG].enabled)) { p = array->f.p + index * array->f.stride; #ifdef CR_ARB_vertex_buffer_object if (array->f.buffer && array->f.buffer->data) { p = (unsigned char *)(array->f.buffer->data) + (unsigned long)p; } #endif array_spu.self.FogCoordfEXT( *((GLfloat *) p) ); } #endif // CR_EXT_fog_coord /* Need to do attrib[0] / vertex position last */ if (array->a[VERT_ATTRIB_POS].enabled) { GLint *iPtr; p = array->a[VERT_ATTRIB_POS].p + index * array->a[VERT_ATTRIB_POS].stride; #ifdef CR_ARB_vertex_buffer_object if (array->a[VERT_ATTRIB_POS].buffer && array->a[VERT_ATTRIB_POS].buffer->data) { p = (unsigned char *)(array->a[VERT_ATTRIB_POS].buffer->data) + (unsigned long)p; } #endif switch (array->a[VERT_ATTRIB_POS].type) { case GL_SHORT: switch (array->a[VERT_ATTRIB_POS].size) { case 1: array_spu.self.VertexAttrib1svARB(0, (GLshort *)p); break; case 2: array_spu.self.VertexAttrib2svARB(0, (GLshort *)p); break; case 3: array_spu.self.VertexAttrib3svARB(0, (GLshort *)p); break; case 4: array_spu.self.VertexAttrib4svARB(0, (GLshort *)p); break; } break; case GL_INT: iPtr = (GLint *) p; switch (array->a[VERT_ATTRIB_POS].size) { case 1: array_spu.self.VertexAttrib1fARB(0, p[0]); break; case 2: array_spu.self.VertexAttrib2fARB(0, p[0], p[1]); break; case 3: array_spu.self.VertexAttrib3fARB(0, p[0], p[1], p[2]); break; case 4: array_spu.self.VertexAttrib4fARB(0, p[0], p[1], p[2], p[3]); break; } break; case GL_FLOAT: switch (array->a[VERT_ATTRIB_POS].size) { case 1: array_spu.self.VertexAttrib1fvARB(0, (GLfloat *)p); break; case 2: array_spu.self.VertexAttrib2fvARB(0, (GLfloat *)p); break; case 3: array_spu.self.VertexAttrib3fvARB(0, (GLfloat *)p); break; case 4: array_spu.self.VertexAttrib4fvARB(0, (GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->a[VERT_ATTRIB_POS].size) { case 1: array_spu.self.VertexAttrib1dvARB(0, (GLdouble *)p); break; case 2: array_spu.self.VertexAttrib2dvARB(0, (GLdouble *)p); break; case 3: array_spu.self.VertexAttrib3dvARB(0, (GLdouble *)p); break; case 4: array_spu.self.VertexAttrib4dvARB(0, (GLdouble *)p); break; } break; default: crWarning("Bad datatype for vertex attribute [0] array: 0x%x\n", array->a[0].type); } } else if (array->v.enabled) { p = array->v.p + index * array->v.stride; #ifdef CR_ARB_vertex_buffer_object if (array->v.buffer && array->v.buffer->data) { p = (unsigned char *)(array->v.buffer->data) + (unsigned long)p; } #endif switch (array->v.type) { case GL_SHORT: switch (array->v.size) { case 2: array_spu.self.Vertex2sv((GLshort *)p); break; case 3: array_spu.self.Vertex3sv((GLshort *)p); break; case 4: array_spu.self.Vertex4sv((GLshort *)p); break; } break; case GL_INT: switch (array->v.size) { case 2: array_spu.self.Vertex2iv((GLint *)p); break; case 3: array_spu.self.Vertex3iv((GLint *)p); break; case 4: array_spu.self.Vertex4iv((GLint *)p); break; } break; case GL_FLOAT: switch (array->v.size) { case 2: array_spu.self.Vertex2fv((GLfloat *)p); break; case 3: array_spu.self.Vertex3fv((GLfloat *)p); break; case 4: array_spu.self.Vertex4fv((GLfloat *)p); break; } break; case GL_DOUBLE: switch (array->v.size) { case 2: array_spu.self.Vertex2dv((GLdouble *)p); break; case 3: array_spu.self.Vertex3dv((GLdouble *)p); break; case 4: array_spu.self.Vertex4dv((GLdouble *)p); break; } break; default: crWarning("Bad datatype for vertex array: 0x%x\n", array->v.type); } } }
void SERVER_DISPATCH_APIENTRY crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context ) { CRMuralInfo *mural, *oldMural; CRContextInfo *ctxInfo = NULL; CRContext *ctx, *oldCtx = NULL; if (context >= 0 && window >= 0) { mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window); if (!mural) { crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window); return; } /* Update the state tracker's current context */ ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context); if (!ctxInfo) { crWarning("CRserver: NULL context in MakeCurrent %d", context); return; } } else { #if 0 oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow); if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO()) { if (!crStateGetCurrent()->framebufferobject.drawFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0); } if (!crStateGetCurrent()->framebufferobject.readFB) { cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0); } } ctxInfo = &cr_server.MainContextInfo; window = -1; mural = NULL; #endif cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE; return; } cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE; ctx = ctxInfo->pContext; CRASSERT(ctx); oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow); /* Ubuntu 11.04 hosts misbehave if context window switch is * done with non-default framebuffer object settings. * crStateSwichPrepare & crStateSwichPostprocess are supposed to work around this problem * crStateSwichPrepare restores the FBO state to its default values before the context window switch, * while crStateSwichPostprocess restores it back to the original values */ oldCtx = crStateSwichPrepare(ctx, cr_server.bUseMultipleContexts, oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO() ? oldMural->idFBO : 0); /* 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, nativeWindow, ctxInfo->SpuContext >= 0 ? ctxInfo->SpuContext : cr_server.MainContextInfo.SpuContext); cr_server.firstCallMakeCurrent = GL_FALSE; cr_server.currentCtxInfo = ctxInfo; cr_server.currentWindow = window; cr_server.currentNativeWindow = nativeWindow; } /* This used to be earlier, after crStateUpdateColorBits() call */ crStateMakeCurrent( ctx ); crStateSwichPostprocess(oldCtx, cr_server.bUseMultipleContexts, mural->bUseFBO && crServerSupportRedirMuralFBO() ? mural->idFBO : 0); if (!ctx->framebufferobject.drawFB && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT)) cr_server.curClient->currentMural->bFbDraw = GL_TRUE; if (!mural->bUseFBO) { ctx->buffer.width = mural->width; ctx->buffer.height = mural->height; } else { ctx->buffer.width = 0; ctx->buffer.height = 0; } }
static void ARRAYSPU_APIENTRY arrayspu_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { int i; GLubyte *p = (GLubyte *)indices; #ifdef CR_ARB_vertex_buffer_object CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer; #endif if (count < 0) { crError("array_spu.self.DrawElements passed negative count: %d", count); } if (mode > GL_POLYGON) { crError("array_spu.self.DrawElements called with invalid mode: %d", mode); } if (type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT && type != GL_UNSIGNED_INT) { crError("array_spu.self.DrawElements called with invalid type: %d", type); } #ifdef CR_ARB_vertex_buffer_object if (elementsBuffer && elementsBuffer->data) { p = (unsigned char *)(elementsBuffer->data) + (unsigned long)p; } #endif //crDebug("arrayspu_DrawElements mode:0x%x, count:%d, type:0x%x", mode, count, type); array_spu.self.Begin(mode); switch (type) { case GL_UNSIGNED_BYTE: for (i=0; i<count; i++) { array_spu.self.ArrayElement((GLint) *p++); } break; case GL_UNSIGNED_SHORT: for (i=0; i<count; i++) { array_spu.self.ArrayElement((GLint) * (GLushort *) p); p+=sizeof (GLushort); } break; case GL_UNSIGNED_INT: for (i=0; i<count; i++) { array_spu.self.ArrayElement((GLint) * (GLuint *) p); p+=sizeof (GLuint); } break; default: crError( "this can't happen: array_spu.self.DrawElements" ); break; } array_spu.self.End(); }
void SERVER_DISPATCH_APIENTRY crServerDispatchSwapBuffers( GLint window, GLint flags ) { CRMuralInfo *mural; CRContext *ctx; #ifdef VBOXCR_LOGFPS static VBOXCRFPS Fps; static bool bFpsInited = false; if (!bFpsInited) { vboxCrFpsInit(&Fps, 64 /* cPeriods */); bFpsInited = true; } vboxCrFpsReportFrame(&Fps); if(!(vboxCrFpsGetNumFrames(&Fps) % 31)) { double fps = vboxCrFpsGetFps(&Fps); double bps = vboxCrFpsGetBps(&Fps); double bpsSent = vboxCrFpsGetBpsSent(&Fps); double cps = vboxCrFpsGetCps(&Fps); double ops = vboxCrFpsGetOps(&Fps); double tup = vboxCrFpsGetTimeProcPercent(&Fps); crDebug("fps: %f, rec Mbps: %.1f, send Mbps: %.1f, cps: %.1f, ops: %.0f, host %.1f%%", fps, bps/(1024.0*1024.0), bpsSent/(1024.0*1024.0), cps, ops, tup); } #endif mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window); if (!mural) { return; } if (cr_server.only_swap_once) { /* NOTE: we only do the clear for the _last_ client in the list. * This is because in multi-threaded apps the zeroeth client may * be idle and never call glClear at all. See threadtest.c * It's pretty likely that the last client will be active. */ if (cr_server.curClient != cr_server.clients[cr_server.numClients - 1]) { return; } } #if 0 if (cr_server.overlapBlending) { int a; CRPoly *p; GLboolean lighting, fog, blend, cull, tex[3]; GLenum mm, blendSrc, blendDst; GLcolorf col; CRContext *ctx = crStateGetCurrent(); const CRmatrix *baseProj; /* * I've probably missed some state here, or it * might be easier just to push/pop it.... */ lighting = ctx->lighting.lighting; fog = ctx->fog.enable; tex[0] = 0; for (a=0; a<CR_MAX_TEXTURE_UNITS; a++) { if (!ctx->texture.unit[a].enabled1D) continue; tex[0] = 1; break; } tex[1] = 0; for (a=0; a<CR_MAX_TEXTURE_UNITS; a++) { if (!ctx->texture.unit[a].enabled2D) continue; tex[1] = 1; break; } tex[2] = 0; for (a=0; a<CR_MAX_TEXTURE_UNITS; a++) { if (!ctx->texture.unit[a].enabled3D) continue; tex[2] = 1; break; } cull = ctx->polygon.cullFace; blend = ctx->buffer.blend; blendSrc = ctx->buffer.blendSrcRGB; blendDst = ctx->buffer.blendDstRGB; mm = ctx->transform.matrixMode; col.r = ctx->current.vertexAttrib[VERT_ATTRIB_COLOR0][0]; col.g = ctx->current.vertexAttrib[VERT_ATTRIB_COLOR0][1]; col.b = ctx->current.vertexAttrib[VERT_ATTRIB_COLOR0][2]; col.a = ctx->current.vertexAttrib[VERT_ATTRIB_COLOR0][3]; baseProj = &(cr_server.curClient->currentMural->extents[0].baseProjection); switch(mm) { case GL_PROJECTION: cr_server.head_spu->dispatch_table.PushMatrix(); cr_server.head_spu->dispatch_table.LoadMatrixf((GLfloat *) baseProj); cr_server.head_spu->dispatch_table.MultMatrixf(cr_server.unnormalized_alignment_matrix); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.PushMatrix(); cr_server.head_spu->dispatch_table.LoadIdentity(); break; default: cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); /* fall through */ case GL_MODELVIEW: cr_server.head_spu->dispatch_table.PushMatrix(); cr_server.head_spu->dispatch_table.LoadIdentity(); cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); cr_server.head_spu->dispatch_table.PushMatrix(); cr_server.head_spu->dispatch_table.LoadMatrixf((GLfloat *) baseProj); cr_server.head_spu->dispatch_table.MultMatrixf(cr_server.unnormalized_alignment_matrix); break; } /* fix state */ if (lighting) cr_server.head_spu->dispatch_table.Disable(GL_LIGHTING); if (fog) cr_server.head_spu->dispatch_table.Disable(GL_FOG); if (tex[0]) cr_server.head_spu->dispatch_table.Disable(GL_TEXTURE_1D); if (tex[1]) cr_server.head_spu->dispatch_table.Disable(GL_TEXTURE_2D); if (tex[2]) cr_server.head_spu->dispatch_table.Disable(GL_TEXTURE_3D); if (cull) cr_server.head_spu->dispatch_table.Disable(GL_CULL_FACE); /* Regular Blending */ if (cr_server.overlapBlending == 1) { if (!blend) cr_server.head_spu->dispatch_table.Enable(GL_BLEND); if ((blendSrc != GL_ZERO) && (blendDst != GL_SRC_ALPHA)) cr_server.head_spu->dispatch_table.BlendFunc(GL_ZERO, GL_SRC_ALPHA); /* draw the blends */ for (a=1; a<cr_server.num_overlap_levels; a++) { if (a-1 < cr_server.num_overlap_intens) { cr_server.head_spu->dispatch_table.Color4f(0, 0, 0, cr_server.overlap_intens[a-1]); } else { cr_server.head_spu->dispatch_table.Color4f(0, 0, 0, 1); } p = cr_server.overlap_geom[a]; while (p) { /* hopefully this isnt concave... */ __draw_poly(p); p = p->next; } } if (!blend) cr_server.head_spu->dispatch_table.Disable(GL_BLEND); if ((blendSrc != GL_ZERO) && (blendDst != GL_SRC_ALPHA)) cr_server.head_spu->dispatch_table.BlendFunc(blendSrc, blendDst); } else /* Knockout Blending */ { cr_server.head_spu->dispatch_table.Color4f(0, 0, 0, 1); if (blend) cr_server.head_spu->dispatch_table.Disable(GL_BLEND); p = cr_server.overlap_knockout; while (p) { __draw_poly(p); p = p->next; } if (blend) cr_server.head_spu->dispatch_table.Enable(GL_BLEND); } /* return things to normal */ switch (mm) { case GL_PROJECTION: cr_server.head_spu->dispatch_table.PopMatrix(); cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION); cr_server.head_spu->dispatch_table.PopMatrix(); break; case GL_MODELVIEW: cr_server.head_spu->dispatch_table.PopMatrix(); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.PopMatrix(); break; default: cr_server.head_spu->dispatch_table.PopMatrix(); cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW); cr_server.head_spu->dispatch_table.PopMatrix(); cr_server.head_spu->dispatch_table.MatrixMode(mm); break; } if (lighting) cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING); if (fog) cr_server.head_spu->dispatch_table.Enable(GL_FOG); if (tex[0]) cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_1D); if (tex[1]) cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D); if (tex[2]) cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_3D); if (cull) cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE); cr_server.head_spu->dispatch_table.Color4f(col.r, col.g, col.b, col.a); } #endif /* Check if using a file network */ if (!cr_server.clients[0]->conn->actual_network && window == MAGIC_OFFSET) window = 0; ctx = crStateGetCurrent(); if (ctx->framebufferobject.drawFB || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT)) cr_server.curClient->currentMural->bFbDraw = GL_FALSE; if (crServerIsRedirectedToFBO()) { crServerMuralFBOSwapBuffers(mural); crServerPresentFBO(mural); } else { cr_server.head_spu->dispatch_table.SwapBuffers( mural->spuWindow, flags ); } }