/*
=====================
idRenderSystemLocal::SwapCommandBuffers_FinishRendering
=====================
*/
void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( 
												uint64 * frontEndMicroSec,
												uint64 * backEndMicroSec,
												uint64 * shadowMicroSec,
												uint64 * gpuMicroSec )  {
	SCOPED_PROFILE_EVENT( "SwapCommandBuffers" );

	if ( gpuMicroSec != NULL ) {
		*gpuMicroSec = 0;		// until shown otherwise
	}

	if ( !R_IsInitialized() ) {
		return;
	}


	// After coming back from an autoswap, we won't have anything to render
	if ( frameData->cmdHead->next != NULL ) {
		// wait for our fence to hit, which means the swap has actually happened
		// We must do this before clearing any resources the GPU may be using
		void GL_BlockingSwapBuffers();
		GL_BlockingSwapBuffers();
	}

	// read back the start and end timer queries from the previous frame
	if ( glConfig.timerQueryAvailable ) {
		uint64 drawingTimeNanoseconds = 0;
		if ( tr.timerQueryId != 0 ) {
			qglGetQueryObjectui64vEXT( tr.timerQueryId, GL_QUERY_RESULT, &drawingTimeNanoseconds );
		}
		if ( gpuMicroSec != NULL ) {
			*gpuMicroSec = drawingTimeNanoseconds / 1000;
		}
	}

	//------------------------------

	// save out timing information
	if ( frontEndMicroSec != NULL ) {
		*frontEndMicroSec = pc.frontEndMicroSec;
	}
	if ( backEndMicroSec != NULL ) {
		*backEndMicroSec = backEnd.pc.totalMicroSec;
	}
	if ( shadowMicroSec != NULL ) {
		*shadowMicroSec = backEnd.pc.shadowMicroSec;
	}

	// print any other statistics and clear all of them
	R_PerformanceCounters();

	// check for dynamic changes that require some initialization
	R_CheckCvars();

    // check for errors
	GL_CheckErrors();
}
/*
=============
EndFrame

Returns the number of msec spent in the back end
=============
*/
void idRenderSystemLocal::EndFrame( int *frontEndMsec, int *backEndMsec, bool swapFrontBack ) {
	emptyCommand_t *cmd;

	if ( !glConfig.isInitialized ) {
		return;
	}

	// close any gui drawing
	guiModel->EmitFullScreen();
	guiModel->Clear();

	// save out timing information
	if ( frontEndMsec ) {
		*frontEndMsec = pc.frontEndMsec;
	}
	if ( backEndMsec ) {
		*backEndMsec = backEnd.pc.msec;
	}

	// print any other statistics and clear all of them
	R_PerformanceCounters();

	// check for dynamic changes that require some initialization
	R_CheckCvars();

    // check for errors
	GL_CheckErrors();

	// add the swapbuffers command
	if(swapFrontBack)
	{
		cmd = (emptyCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) );
		cmd->commandId = RC_SWAP_BUFFERS;
	}

	// start the back end up again with the new command list
	R_IssueRenderCommands();

	// use the other buffers next frame, because another CPU
	// may still be rendering into the current buffers
	R_ToggleSmpFrame();

	// we can now release the vertexes used this frame
	vertexCache.EndFrame();

	if ( session->writeDemo ) {
		session->writeDemo->WriteInt( DS_RENDER );
		session->writeDemo->WriteInt( DC_END_FRAME );
		if ( r_showDemo.GetBool() ) {
			common->Printf( "write DC_END_FRAME\n" );
		}
	}

}