void R_Init( void ) { int i; byte *ptr; // Com_Printf ("----- R_Init -----\n" ); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); #ifndef DEDICATED Com_Memset( &tess, 0, sizeof( tess ) ); #endif // Swap_Init(); #ifndef DEDICATED #ifndef FINAL_BUILD if ( (int)tess.xyz & 15 ) { Com_Printf( "WARNING: tess.xyz not 16 byte aligned (%x)\n",(int)tess.xyz & 15 ); } #endif #endif // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } #ifndef DEDICATED R_InitFogTable(); R_NoiseInit(); #endif R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; ptr = (byte *)Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData )); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys); #ifndef DEDICATED R_ToggleSmpFrame(); for(i = 0; i < MAX_LIGHT_STYLES; i++) { RE_SetLightStyle(i, -1); } InitOpenGL(); R_InitImages(); R_InitShaders(qfalse); R_InitSkins(); R_TerrainInit(); //rwwRMG - added R_InitFonts(); #endif R_ModelInit(); G2VertSpaceServer = &CMiniHeap_singleton; #ifndef DEDICATED R_InitDecals ( ); R_InitWorldEffects(); int err = qglGetError(); if ( err != GL_NO_ERROR ) Com_Printf ( "glGetError() = 0x%x\n", err); #endif // Com_Printf ("----- finished R_Init -----\n" ); }
/* =============== R_Init =============== */ void R_Init( void ) { int i; byte *ptr; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); #ifndef DEDICATED Com_Memset( &tess, 0, sizeof( tess ) ); #endif // Swap_Init(); #ifndef DEDICATED Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); #endif // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } #ifndef DEDICATED R_InitFogTable(); R_NoiseInit(); #endif R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; ptr = (unsigned char *)ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData[0] = (backEndData_t *) ptr; backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] )); backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys); if ( r_smp->integer ) { ptr = (unsigned char *)ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData[1] = (backEndData_t *) ptr; backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] )); backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys); } else { backEndData[1] = NULL; } #ifndef DEDICATED R_ToggleSmpFrame(); for(i = 0; i < MAX_LIGHT_STYLES; i++) { RE_SetLightStyle(i, -1); } InitOpenGL(); // gamma correction if (r_gammamethod->integer == GAMMA_POSTPROCESSING && !glConfig.deviceSupportsPostprocessingGamma) { r_gammamethod->integer = GAMMA_HARDWARE; // temporary fallback to hardware gamma } R_InitImages(); R_InitShaders(); R_InitSkins(); R_InitFonts(); #endif R_ModelInit(); #ifndef DEDICATED #ifdef G2_COLLISION_ENABLED if (!G2VertSpaceServer) { G2VertSpaceServer = new CMiniHeap(G2_VERT_SPACE_SERVER_SIZE * 1024); } #endif int err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); #endif ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // NVidia stuff // #ifndef VCMODS_OPENGLES // fog control if ( glConfig.NVFogAvailable && r_nv_fogdist_mode->modified ) { r_nv_fogdist_mode->modified = qfalse; if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE_ABSOLUTE_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE_ABSOLUTE_NV; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_RADIAL_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; } else { // in case this was really 'else', store a valid value for next time glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; ri.Cvar_Set( "r_nv_fogdist_mode", "GL_EYE_RADIAL_NV" ); } } #endif // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err ); } } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* =============== R_Init =============== */ void R_Init( void ) { static qboolean firstTime = qtrue; int err; int i; byte *ptr; ri.Printf(PRINT_DEVELOPER, "----- R_Init -----\n"); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); // Swap_Init(); if ( refHeadless ) { // dummy shader tr.defaultShader = ri.Hunk_Alloc( sizeof( shader_t ), h_low ); tr.defaultShader->defaultShader = qtrue; Q_strncpyz(tr.defaultShader->name, "<default>", MAX_QPATH); // dedicated server only uses model data R_ModelInit(); return; } if ( (intptr_t)tess.xyz & 15 ) { ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" ); } Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); R_NoiseInit(); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; tr.noiseTable[i] = R_NoiseGet4f(0, 0, 0, i); if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } R_InitFogTable(); R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; max_polybuffers = r_maxpolybuffers->integer; if (max_polybuffers < MAX_POLYBUFFERS) max_polybuffers = MAX_POLYBUFFERS; ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts + sizeof(srfPolyBuffer_t) * max_polybuffers, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData )); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys); backEndData->polybuffers = (srfPolyBuffer_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts); R_InitNextFrame(); InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); if (firstTime) { firstTime = qfalse; // print info GfxInfo_f(); } ri.Printf(PRINT_DEVELOPER, "----- finished R_Init -----\n"); }
/* * R_CreateMeshVBO * * Create two static buffer objects: vertex buffer and elements buffer, the real * data is uploaded by calling R_UploadVBOVertexData and R_UploadVBOElemData. * * Tag allows vertex buffer objects to be grouped and released simultaneously. */ mesh_vbo_t *R_CreateMeshVBO( void *owner, int numVerts, int numElems, int numInstances, vattribmask_t vattribs, vbo_tag_t tag, vattribmask_t halfFloatVattribs ) { int i; size_t size; GLuint vbo_id; vbohandle_t *vboh = NULL; mesh_vbo_t *vbo = NULL; GLenum array_usage = VBO_ARRAY_USAGE_FOR_TAG(tag); GLenum elem_usage = VBO_ELEM_USAGE_FOR_TAG(tag); size_t vertexSize; vattribbit_t lmattrbit; if( !glConfig.ext.vertex_buffer_object ) return NULL; if( !r_free_vbohandles ) return NULL; if( !glConfig.ext.half_float_vertex ) { halfFloatVattribs = 0; } else { if( !(halfFloatVattribs & VATTRIB_POSITION_BIT) ) { halfFloatVattribs &= ~(VATTRIB_AUTOSPRITE_BIT); } halfFloatVattribs &= ~VATTRIB_COLORS_BITS; halfFloatVattribs &= ~VATTRIB_BONES_BITS; // TODO: convert quaternion component of instance_t to half-float // when uploading instances data halfFloatVattribs &= ~VATTRIB_INSTANCES_BITS; } vboh = r_free_vbohandles; vbo = &r_mesh_vbo[vboh->index]; memset( vbo, 0, sizeof( *vbo ) ); // vertex data vertexSize = 0; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_POSITION_BIT, halfFloatVattribs) * 4; // normals data if( vattribs & VATTRIB_NORMAL_BIT ) { assert( !(vertexSize & 3) ); vbo->normalsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_NORMAL_BIT, halfFloatVattribs) * 4; } // s-vectors (tangent vectors) if( vattribs & VATTRIB_SVECTOR_BIT ) { assert( !(vertexSize & 3) ); vbo->sVectorsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_SVECTOR_BIT, halfFloatVattribs) * 4; } // texture coordinates if( vattribs & VATTRIB_TEXCOORDS_BIT ) { assert( !(vertexSize & 3) ); vbo->stOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_TEXCOORDS_BIT, halfFloatVattribs) * 2; } // lightmap texture coordinates lmattrbit = VATTRIB_LMCOORDS0_BIT; for( i = 0; i < MAX_LIGHTMAPS/2; i++ ) { if( !(vattribs & lmattrbit) ) { break; } assert( !(vertexSize & 3) ); vbo->lmstOffset[i] = vertexSize; vbo->lmstSize[i] = vattribs & VATTRIB_LMCOORDS0_BIT<<1 ? 4 : 2; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_LMCOORDS0_BIT, halfFloatVattribs) * vbo->lmstSize[i]; lmattrbit = ( vattribbit_t )( ( vattribmask_t )lmattrbit << 2 ); } // vertex colors if( vattribs & VATTRIB_COLOR0_BIT ) { assert( !(vertexSize & 3) ); vbo->colorsOffset[0] = vertexSize; vertexSize += sizeof( int ); } // bones data for skeletal animation if( (vattribs & VATTRIB_BONES_BITS) == VATTRIB_BONES_BITS ) { assert( SKM_MAX_WEIGHTS == 4 ); assert( !(vertexSize & 3) ); vbo->bonesIndicesOffset = vertexSize; vertexSize += sizeof( int ); assert( !(vertexSize & 3) ); vbo->bonesWeightsOffset = vertexSize; vertexSize += sizeof( int ); } // autosprites // FIXME: autosprite2 requires waaaay too much data for such a trivial // transformation.. if( (vattribs & VATTRIB_AUTOSPRITE_BIT) == VATTRIB_AUTOSPRITE_BIT ) { assert( !(vertexSize & 3) ); vbo->spritePointsOffset = vertexSize; vertexSize += FLOAT_VATTRIB_SIZE(VATTRIB_AUTOSPRITE_BIT, halfFloatVattribs) * 4; } size = vertexSize * numVerts; // instances data if( ( (vattribs & VATTRIB_INSTANCES_BITS) == VATTRIB_INSTANCES_BITS ) && numInstances && glConfig.ext.instanced_arrays ) { assert( !(vertexSize & 3) ); vbo->instancesOffset = size; size += numInstances * sizeof( GLfloat ) * 8; } // pre-allocate vertex buffer vbo_id = 0; qglGenBuffersARB( 1, &vbo_id ); if( !vbo_id ) goto error; vbo->vertexId = vbo_id; RB_BindArrayBuffer( vbo->vertexId ); qglBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, array_usage ); if( qglGetError () == GL_OUT_OF_MEMORY ) goto error; vbo->arrayBufferSize = size; // pre-allocate elements buffer vbo_id = 0; qglGenBuffersARB( 1, &vbo_id ); if( !vbo_id ) goto error; vbo->elemId = vbo_id; size = numElems * sizeof( elem_t ); RB_BindElementArrayBuffer( vbo->elemId ); qglBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, size, NULL, elem_usage ); if( qglGetError () == GL_OUT_OF_MEMORY ) goto error; vbo->elemBufferSize = size; r_free_vbohandles = vboh->next; // link to the list of active vbo handles vboh->prev = &r_vbohandles_headnode; vboh->next = r_vbohandles_headnode.next; vboh->next->prev = vboh; vboh->prev->next = vboh; r_num_active_vbos++; vbo->registrationSequence = rsh.registrationSequence; vbo->vertexSize = vertexSize; vbo->numVerts = numVerts; vbo->numElems = numElems; vbo->owner = owner; vbo->index = vboh->index + 1; vbo->tag = tag; vbo->halfFloatAttribs = halfFloatVattribs; return vbo; error: if( vbo ) R_ReleaseMeshVBO( vbo ); RB_BindArrayBuffer( 0 ); RB_BindElementArrayBuffer( 0 ); return NULL; }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ((err = qglGetError()) != GL_NO_ERROR) ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err); } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = GL_FALSE; backEnd.colorMask[1] = GL_FALSE; backEnd.colorMask[2] = GL_FALSE; backEnd.colorMask[3] = GL_FALSE; qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); if (glRefConfig.framebufferObject) { // clear all framebuffers if (tr.msaaResolveFbo) { FBO_Bind(tr.msaaResolveFbo); qglClear(GL_COLOR_BUFFER_BIT); } if (tr.renderFbo) { FBO_Bind(tr.renderFbo); qglClear(GL_COLOR_BUFFER_BIT); } if (tr.screenScratchFbo) { FBO_Bind(tr.screenScratchFbo); qglClear(GL_COLOR_BUFFER_BIT); } FBO_Bind(NULL); } qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = 0; backEnd.colorMask[1] = 0; backEnd.colorMask[2] = 0; backEnd.colorMask[3] = 0; r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* =============== R_Init =============== */ void R_Init( void ) { int err; int i; byte *ptr; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); if(sizeof(glconfig_t) != 11332) ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t)); // Swap_Init(); if ( (intptr_t)tess.xyz & 15 ) { ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" ); } Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); R_BloomInit(); R_PostprocessingInit(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; ptr = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData[0] = (backEndData_t *) ptr; backEndData[0]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[0] )); backEndData[0]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[0] ) + sizeof(srfPoly_t) * max_polys); if ( r_smp->integer ) { ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData[1] = (backEndData_t *) ptr; backEndData[1]->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData[1] )); backEndData[1]->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData[1] ) + sizeof(srfPoly_t) * max_polys); } else { backEndData[1] = NULL; } R_ToggleSmpFrame(); InitOpenGL(); R_InitImages(); R_GLSL_Init(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); // print info GfxInfo_f(); ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, glConfig.oculusFBL); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, glConfig.oculusDepthRenderBufferLeft); glViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight); if (vr_warpingShader->integer) { if (stereoFrame == STEREO_LEFT) { glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); } else { glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); } } if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_SyncRenderThread(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_SyncRenderThread(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_SyncRenderThread(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_SyncRenderThread(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_SyncRenderThread(); if ((err = qglGetError()) != GL_NO_ERROR) ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err); } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/* ================ rvGEWorkspace::Render Renders the workspace to the given DC ================ */ void rvGEWorkspace::Render ( HDC hdc ) { int front; int back; float scale; scale = g_ZoomScales[mZoom]; // Switch GL contexts to our dc if (!qwglMakeCurrent( hdc, win32.hGLRC )) { common->Printf("ERROR: wglMakeCurrent failed.. Error:%i\n", qglGetError()); common->Printf("Please restart Q3Radiant if the Map view is not working\n"); return; } // Prepare the view and clear it GL_State( GLS_DEFAULT ); qglViewport(0, 0, mWindowWidth, mWindowHeight ); qglScissor(0, 0, mWindowWidth, mWindowHeight ); qglClearColor ( 0.75f, 0.75f, 0.75f, 0 ); qglDisable(GL_DEPTH_TEST); qglDisable(GL_CULL_FACE); qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render the workspace below glMatrixMode(GL_PROJECTION); glLoadIdentity(); qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); qglColor3f ( mApplication->GetOptions().GetWorkspaceColor()[0], mApplication->GetOptions().GetWorkspaceColor()[1], mApplication->GetOptions().GetWorkspaceColor()[2] ); qglBegin ( GL_QUADS ); qglVertex2f ( mRect.x, mRect.y ); qglVertex2f ( mRect.x + mRect.w, mRect.y ); qglVertex2f ( mRect.x + mRect.w, mRect.y + mRect.h ); qglVertex2f ( mRect.x, mRect.y + mRect.h ); qglEnd ( ); // Prepare the renderSystem view to draw the GUI in viewDef_t viewDef; memset ( &viewDef, 0, sizeof(viewDef) ); tr.viewDef = &viewDef; tr.viewDef->renderView.x = mRect.x; tr.viewDef->renderView.y = mWindowHeight - mRect.y - mRect.h; tr.viewDef->renderView.width = mRect.w; tr.viewDef->renderView.height = mRect.h; tr.viewDef->scissor.x1 = 0; tr.viewDef->scissor.y1 = 0; tr.viewDef->scissor.x2 = mRect.w; tr.viewDef->scissor.y2 = mRect.h; tr.viewDef->isEditor = true; renderSystem->BeginFrame(mWindowWidth, mWindowHeight ); // Draw the gui mInterface->Redraw ( 0 ); // eventLoop->Milliseconds() ); // We are done using the renderSystem now renderSystem->EndFrame( &front, &back ); if ( mApplication->GetActiveWorkspace ( ) == this ) { mApplication->GetStatusBar().SetTriangles ( backEnd.pc.c_drawIndexes/3 ); } // Prepare the viewport for drawing selections, etc. GL_State( GLS_DEFAULT ); qglDisable( GL_TEXTURE_CUBE_MAP_EXT ); // qglDisable(GL_BLEND); qglDisable(GL_CULL_FACE); qglViewport(0, 0, mWindowWidth, mWindowHeight ); qglScissor(0, 0, mWindowWidth, mWindowHeight ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); qglOrtho(0,mWindowWidth, mWindowHeight, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); RenderGrid ( ); mSelections.Render ( ); qglFinish ( ); qwglSwapBuffers(hdc); qglEnable( GL_TEXTURE_CUBE_MAP_EXT ); qglEnable( GL_CULL_FACE); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_SyncRenderThread(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_SyncRenderThread(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_SyncRenderThread(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // NVidia stuff // // fog control if ( glConfig.NVFogAvailable && r_nv_fogdist_mode->modified ) { r_nv_fogdist_mode->modified = qfalse; if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE_ABSOLUTE_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE_ABSOLUTE_NV; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_RADIAL_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; } else { // in case this was really 'else', store a valid value for next time glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; ri.Cvar_Set( "r_nv_fogdist_mode", "GL_EYE_RADIAL_NV" ); } } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_SyncRenderThread(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_SyncRenderThread(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err ); } } // // draw buffer stuff // cmd = R_GetCommandBuffer( sizeof( *cmd ) ); if ( !cmd ) { return; } cmd->commandId = RC_DRAW_BUFFER; if ( glConfig.stereoEnabled ) { if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if ( stereoFrame != STEREO_CENTER ) { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); } if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) { cmd->buffer = (int)GL_FRONT; } else { cmd->buffer = (int)GL_BACK; } } }
/* =============== R_Init =============== */ void R_Init( void ) { int err; int i; byte *ptr; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state memset( &tr, 0, sizeof( tr ) ); memset( &backEnd, 0, sizeof( backEnd ) ); memset( &tess, 0, sizeof( tess ) ); if(sizeof(glconfig_t) != 7268) ri.Error( ERR_FATAL, "Mod ABI incompatible: sizeof(glconfig_t) == %u != 11332", (unsigned int) sizeof(glconfig_t)); // Swap_Init(); if ( (intptr_t)tess.xyz & 15 ) { ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" ); } memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE / 2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2]; } } // Ridah, init the virtual memory R_Hunk_Begin(); R_InitFogTable(); R_NoiseInit(); R_Register(); #ifdef USE_BLOOM R_BloomInit(); #endif max_polys = r_maxpolys->integer; if ( max_polys < MAX_POLYS ) { max_polys = MAX_POLYS; } max_polyverts = r_maxpolyverts->integer; if ( max_polyverts < MAX_POLYVERTS ) { max_polyverts = MAX_POLYVERTS; } ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData )); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys); R_InitNextFrame(); InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); err = qglGetError(); if ( err != GL_NO_ERROR ) { ri.Printf( PRINT_ALL, "glGetError() = 0x%x\n", err ); } ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
void R_Init( void ) { int err; int i; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); ShaderEntryPtrs_Clear(); // clear all our internal state memset( &tr, 0, sizeof( tr ) ); memset( &backEnd, 0, sizeof( backEnd ) ); memset( &tess, 0, sizeof( tess ) ); Swap_Init(); #ifndef FINAL_BUILD if ( (int)tess.xyz & 15 ) { Com_Printf( "WARNING: tess.xyz not 16 byte aligned (%x)\n",(int)tess.xyz & 15 ); } #endif memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0 - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); backEndData[0] = (backEndData_t *) ri.Hunk_Alloc( sizeof( *backEndData[0] ), qtrue ); if ( r_smp->integer ) { backEndData[1] = (backEndData_t *) ri.Hunk_Alloc( sizeof( *backEndData[1] ), qtrue ); } else { backEndData[1] = NULL; } R_ToggleSmpFrame(); const color4ub_t color = {0xff, 0xff, 0xff, 0xff}; for(i=0;i<MAX_LIGHT_STYLES;i++) { RE_SetLightStyle(i, *(int*)color); } InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); // R_InitWorldEffects(); R_InitFonts(); err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* =============== R_Init =============== */ void R_Init( void ) { int err; int i; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state memset( &tr, 0, sizeof( tr ) ); memset( &backEnd, 0, sizeof( backEnd ) ); memset( &tess, 0, sizeof( tess ) ); Swap_Init(); if ( (intptr_t)tess.xyz & 15 ) { Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" ); } memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE / 2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); // Ridah, init the virtual memory R_Hunk_Begin(); max_polys = r_maxpolys->integer; if ( max_polys < MAX_POLYS ) { max_polys = MAX_POLYS; } max_polyverts = r_maxpolyverts->integer; if ( max_polyverts < MAX_POLYVERTS ) { max_polyverts = MAX_POLYVERTS; } // backEndData[0] = ri.Hunk_Alloc( sizeof( *backEndData[0] ), h_low ); backEndData[0] = ri.Hunk_Alloc( sizeof( *backEndData[0] ) + sizeof( srfPoly_t ) * max_polys + sizeof( polyVert_t ) * max_polyverts, h_low ); if ( r_smp->integer ) { // backEndData[1] = ri.Hunk_Alloc( sizeof( *backEndData[1] ), h_low ); backEndData[1] = ri.Hunk_Alloc( sizeof( *backEndData[1] ) + sizeof( srfPoly_t ) * max_polys + sizeof( polyVert_t ) * max_polyverts, h_low ); } else { backEndData[1] = NULL; } R_ToggleSmpFrame(); InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); RB_ZombieFXInit(); err = qglGetError(); if ( err != GL_NO_ERROR ) { ri.Printf( PRINT_ALL, "glGetError() = 0x%x\n", err ); } ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* =============== R_Init =============== */ void R_Init( void ) { int err; int i; byte *ptr; waitforit("R_Init 1"); ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); // Swap_Init(); waitforit("R_Init 2"); if ((int)tess.xyz & 15) { Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" ); } Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // waitforit("R_Init 3"); for (i = 0; i < FUNCTABLE_SIZE; i++) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } waitforit("R_Init 4"); R_InitFogTable(); waitforit("R_Init 5"); R_NoiseInit(); waitforit("R_Init 6"); R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; waitforit("R_Init 7"); max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; waitforit("R_Init 8"); ptr = ri.Hunk_Alloc(sizeof(*backEndData[0]), h_low); backEndData[0] = (backEndData_t *) ptr; if ( r_smp->integer ) { ptr = ri.Hunk_Alloc( sizeof( *backEndData[1] ), h_low); backEndData[1] = (backEndData_t *) ptr; } else { backEndData[1] = NULL; } waitforit("R_Init 9"); R_ToggleSmpFrame(); waitforit("R_Init A"); InitOpenGL(); waitforit("R_Init B"); R_InitImages(); waitforit("R_Init C"); R_InitShaders(); waitforit("R_Init D"); R_InitSkins(); waitforit("R_Init E"); R_ModelInit(); waitforit("R_Init F"); R_InitFreeType(); waitforit("R_Init G"); err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); waitforit("R_Init H"); ri.Printf(PRINT_ALL, "----- finished R_Init -----\n"); waitforit("R_Init I"); }
/* ================= R_LoadARBProgram ================= */ void R_LoadARBProgram( int progIndex ) { int ofs; int err; idStr fullPath = "glprogs/"; fullPath += progs[progIndex].name; char *fileBuffer; char *buffer; char *start, *end; common->Printf( "%s", fullPath.c_str() ); // load the program even if we don't support it, so // fs_copyfiles can generate cross-platform data dumps fileSystem->ReadFile( fullPath.c_str(), (void **)&fileBuffer, NULL ); if ( !fileBuffer ) { common->Printf( ": File not found\n" ); return; } // copy to stack memory and free buffer = (char *)_alloca( strlen( fileBuffer ) + 1 ); strcpy( buffer, fileBuffer ); fileSystem->FreeFile( fileBuffer ); if ( !glConfig.isInitialized ) { return; } // // submit the program string at start to GL // if ( progs[progIndex].ident == 0 ) { // allocate a new identifier for this program progs[progIndex].ident = PROG_USER + progIndex; } // vertex and fragment programs can both be present in a single file, so // scan for the proper header to be the start point, and stamp a 0 in after the end if ( progs[progIndex].target == GL_VERTEX_PROGRAM_ARB ) { if ( !glConfig.ARBVertexProgramAvailable ) { common->Printf( ": GL_VERTEX_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBvp" ); } if ( progs[progIndex].target == GL_FRAGMENT_PROGRAM_ARB ) { if ( !glConfig.ARBFragmentProgramAvailable ) { common->Printf( ": GL_FRAGMENT_PROGRAM_ARB not available\n" ); return; } start = strstr( (char *)buffer, "!!ARBfp" ); } if ( !start ) { common->Printf( ": !!ARB not found\n" ); return; } end = strstr( start, "END" ); if ( !end ) { common->Printf( ": END not found\n" ); return; } end[3] = 0; qglBindProgramARB( progs[progIndex].target, progs[progIndex].ident ); qglGetError(); qglProgramStringARB( progs[progIndex].target, GL_PROGRAM_FORMAT_ASCII_ARB, strlen( start ), (unsigned char *)start ); err = qglGetError(); qglGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, (GLint *)&ofs ); if ( err == GL_INVALID_OPERATION ) { const GLubyte *str = qglGetString( GL_PROGRAM_ERROR_STRING_ARB ); common->Printf( "\nGL_PROGRAM_ERROR_STRING_ARB: %s\n", str ); if ( ofs < 0 ) { common->Printf( "GL_PROGRAM_ERROR_POSITION_ARB < 0 with error\n" ); } else if ( ofs >= (int)strlen( (char *)start ) ) { common->Printf( "error at end of program\n" ); } else { common->Printf( "error at %i:\n%s", ofs, start + ofs ); } return; } if ( ofs != -1 ) { common->Printf( "\nGL_PROGRAM_ERROR_POSITION_ARB != -1 without error\n" ); return; } common->Printf( "\n" ); }
void R_Init( void ) { int err; int i; //VID_Printf( PRINT_ALL, "----- R_Init -----\n" ); #ifdef _XBOX extern qboolean vidRestartReloadMap; if (!vidRestartReloadMap) { Hunk_Clear(); extern void CM_Free(void); CM_Free(); void CM_CleanLeafCache(void); CM_CleanLeafCache(); } #endif ShaderEntryPtrs_Clear(); #ifdef _XBOX //Save visibility info as it has already been set. SPARC<byte> *vis = tr.externalVisData; #endif // clear all our internal state memset( &tr, 0, sizeof( tr ) ); memset( &backEnd, 0, sizeof( backEnd ) ); memset( &tess, 0, sizeof( tess ) ); #ifdef _XBOX //Restore visibility info. tr.externalVisData = vis; #endif Swap_Init(); #ifndef FINAL_BUILD if ( (int)tess.xyz & 15 ) { Com_Printf( "WARNING: tess.xyz not 16 byte aligned (%x)\n",(int)tess.xyz & 15 ); } #endif // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0 - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); backEndData = (backEndData_t *) Hunk_Alloc( sizeof( backEndData_t ), qtrue ); R_ToggleSmpFrame(); //r_smp const color4ub_t color = {0xff, 0xff, 0xff, 0xff}; for(i=0;i<MAX_LIGHT_STYLES;i++) { RE_SetLightStyle(i, *(int*)color); } InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); #ifndef _XBOX R_TerrainInit(); #endif R_ModelInit(); // R_InitWorldEffects(); R_InitFonts(); err = qglGetError(); if ( err != GL_NO_ERROR ) VID_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); //VID_Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* =============== R_Init =============== */ void R_Init(void) { int err; int i; byte *ptr; ri.Printf(PRINT_ALL, "----- R_Init -----\n"); // clear all our internal state Com_Memset(&tr, 0, sizeof(tr)); Com_Memset(&backEnd, 0, sizeof(backEnd)); Com_Memset(&tess, 0, sizeof(tess)); tess.xyz = tess_xyz; tess.texCoords0 = tess_texCoords0; tess.texCoords1 = tess_texCoords1; tess.indexes = tess_indexes; tess.normal = tess_normal; tess.vertexColors = tess_vertexColors; tess.maxShaderVerts = SHADER_MAX_VERTEXES; tess.maxShaderIndicies = SHADER_MAX_INDEXES; if ((intptr_t) tess.xyz & 15) { ri.Printf(PRINT_WARNING, "tess.xyz not 16 byte aligned\n"); } Com_Memset(tess.constantColor255, 255, sizeof(tess.constantColor255)); // init function tables for (i = 0; i < FUNCTABLE_SIZE; i++) { tr.sinTable[i] = sin(DEG2RAD(i * 360.0f / (( float ) (FUNCTABLE_SIZE - 1)))); tr.squareTable[i] = (i < FUNCTABLE_SIZE / 2) ? 1.0f : -1.0f; tr.sawToothTable[i] = ( float ) i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if (i < FUNCTABLE_SIZE / 2) { if (i < FUNCTABLE_SIZE / 4) { tr.triangleTable[i] = ( float ) i / (FUNCTABLE_SIZE / 4); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2]; } } // init the virtual memory R_Hunk_Begin(); R_InitFogTable(); R_NoiseInit(); R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) { max_polys = MAX_POLYS; } max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) { max_polyverts = MAX_POLYVERTS; } ptr = ri.Hunk_Alloc(sizeof(*backEndData) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof(*backEndData)); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof(*backEndData) + sizeof(srfPoly_t) * max_polys); R_InitNextFrame(); InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); err = qglGetError(); if (err != GL_NO_ERROR) { ri.Printf(PRINT_ALL, "glGetError() = 0x%x\n", err); } ri.Printf(PRINT_ALL, "----- finished R_Init -----\n"); }
/* =============== R_Init =============== */ void R_Init( void ) { int err; int i; byte *ptr; ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &tess, 0, sizeof( tess ) ); // Swap_Init(); if ( (intptr_t)tess.xyz & 15 ) { ri.Printf( PRINT_WARNING, "tess.xyz not 16 byte aligned\n" ); } //Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) ); // // init function tables // for ( i = 0; i < FUNCTABLE_SIZE; i++ ) { tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if ( i < FUNCTABLE_SIZE / 2 ) { if ( i < FUNCTABLE_SIZE / 4 ) { tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; } } R_InitFogTable(); R_NoiseInit(); R_Register(); max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; max_polyverts = r_maxpolyverts->integer; if (max_polyverts < MAX_POLYVERTS) max_polyverts = MAX_POLYVERTS; ptr = ri.Hunk_Alloc( sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys + sizeof(polyVert_t) * max_polyverts, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof( *backEndData )); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof( *backEndData ) + sizeof(srfPoly_t) * max_polys); R_InitNextFrame(); InitOpenGL(); R_InitImages(); if (glRefConfig.framebufferObject) FBO_Init(); GLSL_InitGPUShaders(); R_InitVaos(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); R_InitQueries(); err = qglGetError(); if ( err != GL_NO_ERROR ) ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err); // print info GfxInfo_f(); ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // #ifndef _XBOX if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { VID_Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { VID_Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_SyncRenderThread(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_SyncRenderThread(); qglDisable( GL_STENCIL_TEST ); r_measureOverdraw->modified = qfalse; } } #endif // // texturemode stuff // if ( r_textureMode->modified || r_ext_texture_filter_anisotropic->modified) { R_SyncRenderThread(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; r_ext_texture_filter_anisotropic->modified = qfalse; } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_SyncRenderThread(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_SyncRenderThread(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { Com_Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err ); } } // // draw buffer stuff // cmd = (drawBufferCommand_t *) R_GetCommandBuffer( sizeof( *cmd ) ); if ( !cmd ) { return; } cmd->commandId = RC_DRAW_BUFFER; if ( glConfig.stereoEnabled ) { if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { Com_Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if ( stereoFrame != STEREO_CENTER ) { Com_Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); } // if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) { // cmd->buffer = (int)GL_FRONT; // } else { cmd->buffer = (int)GL_BACK; } } }
/* * RFB_BlitObject * * The target FBO must be equal or greater in both dimentions than * the currently bound FBO! */ void RFB_BlitObject( int src, int dest, int bitMask, int mode, int filter, int readAtt, int drawAtt ) { int bits; int destObj; int dx, dy, dw, dh; r_fbo_t scrfbo; r_fbo_t *fbo; r_fbo_t *destfbo; if( !glConfig.ext.framebuffer_blit ) { return; } assert( src >= 0 && src <= r_num_framebuffer_objects ); if( src < 0 || src > r_num_framebuffer_objects ) { return; } if( src == 0 ) { fbo = &scrfbo; } else { fbo = r_framebuffer_objects + src - 1; } assert( dest >= 0 && dest <= r_num_framebuffer_objects ); if( dest < 0 || dest > r_num_framebuffer_objects ) { return; } if( dest ) { destfbo = r_framebuffer_objects + dest - 1; } else { destfbo = NULL; } bits = bitMask; if( !bits ) { return; } RB_ApplyScissor(); if( src == 0 ) { memset( fbo, 0, sizeof( *fbo ) ); fbo->width = glConfig.width; fbo->height = glConfig.height; } if( destfbo ) { dw = destfbo->width; dh = destfbo->height; destObj = destfbo->objectID; } else { dw = glConfig.width; dh = glConfig.height; destObj = 0; } switch( mode ) { case FBO_COPY_CENTREPOS: dx = ( dw - fbo->width ) / 2; dy = ( dh - fbo->height ) / 2; dw = fbo->width; dh = fbo->height; break; case FBO_COPY_INVERT_Y: dx = 0; dy = dh - fbo->height; dw = fbo->width; dh = fbo->height; break; case FBO_COPY_NORMAL_DST_SIZE: dx = 0; dy = 0; //dw = dw; //dh = dh; break; default: dx = 0; dy = 0; dw = fbo->width; dh = fbo->height; break; } qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, fbo->objectID ); qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, destObj ); #ifndef GL_ES_VERSION_2_0 if( src == 0 ) { qglReadBuffer( GL_BACK ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt ); } else { qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT + readAtt ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT + drawAtt ); } #endif qglBlitFramebufferEXT( 0, 0, fbo->width, fbo->height, dx, dy, dx + dw, dy + dh, bits, filter ); qglBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, 0 ); qglBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo->objectID ); #ifndef GL_ES_VERSION_2_0 if( src == 0 ) { qglReadBuffer( GL_BACK ); qglDrawBuffer( GL_BACK ); } else { qglReadBuffer( GL_COLOR_ATTACHMENT0_EXT ); qglDrawBuffer( GL_COLOR_ATTACHMENT0_EXT ); } #endif assert( qglGetError() == GL_NO_ERROR ); }
/* ==================== RE_BeginFrame If running in stereo, RE_BeginFrame will be called twice for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { drawBufferCommand_t *cmd = NULL; colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; } glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; // // do overdraw measurement // if ( r_measureOverdraw->integer ) { if ( glConfig.stencilBits < 4 ) { ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else if ( r_shadows->integer == 2 ) { ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" ); ri.Cvar_Set( "r_measureOverdraw", "0" ); r_measureOverdraw->modified = qfalse; } else { R_IssuePendingRenderCommands(); qglEnable( GL_STENCIL_TEST ); qglStencilMask( ~0U ); qglClearStencil( 0U ); qglStencilFunc( GL_ALWAYS, 0U, ~0U ); qglStencilOp( GL_KEEP, GL_INCR, GL_INCR ); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if ( r_measureOverdraw->modified ) { R_IssuePendingRenderCommands(); qglDisable( GL_STENCIL_TEST ); } r_measureOverdraw->modified = qfalse; } // // texturemode stuff // if ( r_textureMode->modified ) { R_IssuePendingRenderCommands(); GL_TextureMode( r_textureMode->string ); r_textureMode->modified = qfalse; } // // ATI stuff // // TRUFORM if ( qglPNTrianglesiATI ) { // tess if ( r_ati_truform_tess->modified ) { r_ati_truform_tess->modified = qfalse; // cap if necessary if ( r_ati_truform_tess->value > glConfig.ATIMaxTruformTess ) { ri.Cvar_Set( "r_ati_truform_tess", va( "%d",glConfig.ATIMaxTruformTess ) ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, r_ati_truform_tess->value ); } // point mode if ( r_ati_truform_pointmode->modified ) { r_ati_truform_pointmode->modified = qfalse; // GR - shorten the mode name if ( !Q_stricmp( r_ati_truform_pointmode->string, "LINEAR" ) ) { glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI; // GR - fix point mode change } else if ( !Q_stricmp( r_ati_truform_pointmode->string, "CUBIC" ) ) { glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI; } else { // bogus value, set to valid glConfig.ATIPointMode = (int)GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI; ri.Cvar_Set( "r_ati_truform_pointmode", "LINEAR" ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_POINT_MODE_ATI, glConfig.ATIPointMode ); } // normal mode if ( r_ati_truform_normalmode->modified ) { r_ati_truform_normalmode->modified = qfalse; // GR - shorten the mode name if ( !Q_stricmp( r_ati_truform_normalmode->string, "LINEAR" ) ) { glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI; // GR - fix normal mode change } else if ( !Q_stricmp( r_ati_truform_normalmode->string, "QUADRATIC" ) ) { glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI; } else { // bogus value, set to valid glConfig.ATINormalMode = (int)GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI; ri.Cvar_Set( "r_ati_truform_normalmode", "LINEAR" ); } qglPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, glConfig.ATINormalMode ); } } // // NVidia stuff // // fog control if ( glConfig.NVFogAvailable && r_nv_fogdist_mode->modified ) { r_nv_fogdist_mode->modified = qfalse; if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE_ABSOLUTE_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE_ABSOLUTE_NV; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_PLANE" ) ) { glConfig.NVFogMode = (int)GL_EYE_PLANE; } else if ( !Q_stricmp( r_nv_fogdist_mode->string, "GL_EYE_RADIAL_NV" ) ) { glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; } else { // in case this was really 'else', store a valid value for next time glConfig.NVFogMode = (int)GL_EYE_RADIAL_NV; ri.Cvar_Set( "r_nv_fogdist_mode", "GL_EYE_RADIAL_NV" ); } } // // gamma stuff // if ( r_gamma->modified ) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if ( !r_ignoreGLErrors->integer ) { int err; R_IssuePendingRenderCommands(); if ( ( err = qglGetError() ) != GL_NO_ERROR ) { ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!", err ); } } if (glConfig.stereoEnabled) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; cmd->commandId = RC_DRAW_BUFFER; if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { cmd->buffer = (int)GL_BACK_RIGHT; } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } } else { if(r_anaglyphMode->integer) { if(r_anaglyphMode->modified) { // clear both, front and backbuffer. qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = GL_FALSE; backEnd.colorMask[1] = GL_FALSE; backEnd.colorMask[2] = GL_FALSE; backEnd.colorMask[3] = GL_FALSE; if (glRefConfig.framebufferObject) { // clear all framebuffers if (tr.msaaResolveFbo) { FBO_Bind(tr.msaaResolveFbo); qglClear(GL_COLOR_BUFFER_BIT); } if (tr.renderFbo) { FBO_Bind(tr.renderFbo); qglClear(GL_COLOR_BUFFER_BIT); } FBO_Bind(NULL); } qglDrawBuffer(GL_FRONT); qglClear(GL_COLOR_BUFFER_BIT); qglDrawBuffer(GL_BACK); qglClear(GL_COLOR_BUFFER_BIT); r_anaglyphMode->modified = qfalse; } if(stereoFrame == STEREO_LEFT) { if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else if(stereoFrame == STEREO_RIGHT) { clearDepthCommand_t *cldcmd; if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) return; cldcmd->commandId = RC_CLEARDEPTH; if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) return; } else ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); colcmd->commandId = RC_COLORMASK; } else { if(stereoFrame != STEREO_CENTER) ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) return; } if(cmd) { cmd->commandId = RC_DRAW_BUFFER; if(r_anaglyphMode->modified) { qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); backEnd.colorMask[0] = 0; backEnd.colorMask[1] = 0; backEnd.colorMask[2] = 0; backEnd.colorMask[3] = 0; r_anaglyphMode->modified = qfalse; } if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) cmd->buffer = (int)GL_FRONT; else cmd->buffer = (int)GL_BACK; } } tr.refdef.stereoFrame = stereoFrame; }
/** * @brief R_Init */ void R_Init(void) { int err; int i; byte *ptr; Ren_Print("----- R_Init -----\n"); // clear all our internal state Com_Memset(&tr, 0, sizeof(tr)); Com_Memset(&backEnd, 0, sizeof(backEnd)); Com_Memset(&tess, 0, sizeof(tess)); if ((intptr_t) tess.xyz & 15) { Ren_Warning("tess.xyz not 16 byte aligned\n"); } Com_Memset(tess.constantColor255, 255, sizeof(tess.constantColor255)); // init function tables for (i = 0; i < FUNCTABLE_SIZE; i++) { tr.sinTable[i] = sin(DEG2RAD(i * 360.0f / (( float ) (FUNCTABLE_SIZE - 1)))); tr.squareTable[i] = (i < FUNCTABLE_SIZE / 2) ? 1.0f : -1.0f; tr.sawToothTable[i] = ( float ) i / FUNCTABLE_SIZE; tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; if (i < FUNCTABLE_SIZE / 2) { if (i < FUNCTABLE_SIZE / 4) { tr.triangleTable[i] = ( float ) i / (FUNCTABLE_SIZE / 4); } else { tr.triangleTable[i] = 1.0f - tr.triangleTable[i - FUNCTABLE_SIZE / 4]; } } else { tr.triangleTable[i] = -tr.triangleTable[i - FUNCTABLE_SIZE / 2]; } } // init the virtual memory R_Hunk_Begin(); R_NoiseInit(); R_Register(); ptr = ri.Hunk_Alloc(sizeof(*backEndData) + sizeof(srfPoly_t) * r_maxPolys->integer + sizeof(polyVert_t) * r_maxPolyVerts->integer, h_low); backEndData = (backEndData_t *) ptr; backEndData->polys = (srfPoly_t *) ((char *) ptr + sizeof(*backEndData)); backEndData->polyVerts = (polyVert_t *) ((char *) ptr + sizeof(*backEndData) + sizeof(srfPoly_t) * r_maxPolys->integer); R_InitNextFrame(); InitOpenGL(); R_InitImages(); R_InitShaders(); R_InitSkins(); R_ModelInit(); R_InitFreeType(); err = qglGetError(); if (err != GL_NO_ERROR) { Ren_Print("R_Init: glGetError() = 0x%x\n", err); } Ren_Print("----- finished R_Init -----\n"); }