void FPlatformOpenGLDevice::Init()
{
	AndroidEGL::GetInstance()->InitSurface(false);
	PlatformRenderingContextSetup(this);
	InitDefaultGLContextState();

	PlatformSharedContextSetup(this);
	InitDefaultGLContextState();

	AndroidEGL::GetInstance()->InitBackBuffer(); //can be done only after context is made current.
	LoadEXT();
}
void FPlatformOpenGLDevice::Init()
{
	extern void InitDebugContext();

	FPlatformMisc::LowLevelOutputDebugString(TEXT("FPlatformOpenGLDevice:Init"));
	bool bCreateSurface = !AndroidThunkCpp_IsGearVRApplication();
	AndroidEGL::GetInstance()->InitSurface(false, bCreateSurface);
	PlatformRenderingContextSetup(this);

	LoadEXT();

	InitDefaultGLContextState();
	InitDebugContext();

	PlatformSharedContextSetup(this);
	InitDefaultGLContextState();
	InitDebugContext();

	AndroidEGL::GetInstance()->InitBackBuffer(); //can be done only after context is made current.
}
void FPlatformOpenGLDevice::Init()
{
	UE_LOG( LogRHI, Warning, TEXT("Entering FPlatformOpenGLDevice::Init"));
	extern void InitDebugContext();

	AndroidEGL::GetInstance()->InitSurface(false);
	AndroidEGL::GetInstance()->SetSingleThreadRenderingContext();

	// Initialize all of the entry points we have to query manually
#define GET_GL_ENTRYPOINTS(Type,Func) Func = (Type)eglGetProcAddress(#Func);
	ENUM_GL_ENTRYPOINTS_CORE(GET_GL_ENTRYPOINTS);
	ENUM_GL_ENTRYPOINTS_MANUAL(GET_GL_ENTRYPOINTS);
	ENUM_GL_ENTRYPOINTS_OPTIONAL(GET_GL_ENTRYPOINTS);

	// Check that all of the required entry points have been initialized
	bool bFoundAllEntryPoints = true;
#define CHECK_GL_ENTRYPOINTS(Type,Func) if (Func == NULL) { bFoundAllEntryPoints = false; UE_LOG(LogRHI, Warning, TEXT("Failed to find entry point for %s"), TEXT(#Func)); }
	ENUM_GL_ENTRYPOINTS_CORE(CHECK_GL_ENTRYPOINTS);

	checkf(bFoundAllEntryPoints, TEXT("Failed to find all required OpenGL entry points."));

	ENUM_GL_ENTRYPOINTS_MANUAL(CHECK_GL_ENTRYPOINTS);
	ENUM_GL_ENTRYPOINTS_OPTIONAL(CHECK_GL_ENTRYPOINTS);

	const FString ExtensionsString = ANSI_TO_TCHAR((const ANSICHAR*)glGetString(GL_EXTENSIONS));

	// If EXT_disjoint_timer_query wasn't found, NV_timer_query might be available
	{
		// These functions get exported under different names by different extensions
		// Can't just check for NULL, because Android returns and unimplemented function catch
		
		if ( !ExtensionsString.Contains(TEXT("GL_EXT_disjoint_timer_query")) && ExtensionsString.Contains(TEXT("GL_NV_timer_query")))
		{
			glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC)eglGetProcAddress("glQueryCounterNV");
			glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)eglGetProcAddress("glGetQueryObjectui64vNV");
		}
	}

	const bool bAdvancedFeatures = FOpenGL::SupportsAdvancedFeatures();

	// devices that have ES2.0 only might support some ES3.x core functionality with extensions
	if(!bAdvancedFeatures)
	{
		if(ExtensionsString.Contains(TEXT("GL_EXT_occlusion_query_boolean")))
		{
			glGenQueries = (PFNGLGENQUERIESPROC(eglGetProcAddress("glGenQueriesEXT")));
			glDeleteQueries = (PFNGLDELETEQUERIESPROC(eglGetProcAddress("glDeleteQueriesEXT")));
			glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC)((void*)eglGetProcAddress("glGetQueryObjectuivEXT"));

		}

		// Android doesn't setup formats completely compatible with glTexStorage in ES2 mode
		glTexStorage2D = nullptr;
		glTexStorage3D = nullptr;

	}

	if (!bFoundAllEntryPoints)
	{
		UE_LOG(LogRHI, Warning, TEXT("Failed to acquire all optional OpenGL entrypoints, may fall back to OpenGL ES 2.0"));
	}

	if (bAdvancedFeatures)
	{
		GLuint DefaultVertexArrayObject = 0;
		glGenVertexArrays(1, &DefaultVertexArrayObject);
		glBindVertexArray(DefaultVertexArrayObject);
	}
	InitDefaultGLContextState();
	InitDebugContext();

	AndroidEGL::GetInstance()->SetMultithreadRenderingContext();
	if (bAdvancedFeatures)
	{
		GLuint DefaultVertexArrayObject = 0;
		glGenVertexArrays(1, &DefaultVertexArrayObject);
		glBindVertexArray(DefaultVertexArrayObject);
	}
	InitDefaultGLContextState();
	InitDebugContext();

	AndroidEGL::GetInstance()->SetSharedContext();
	if (bAdvancedFeatures)
	{
		GLuint DefaultVertexArrayObject = 0;
		glGenVertexArrays(1, &DefaultVertexArrayObject);
		glBindVertexArray(DefaultVertexArrayObject);
	}
	InitDefaultGLContextState();
	InitDebugContext();

	PlatformSharedContextSetup(this);

	AndroidEGL::GetInstance()->InitBackBuffer(); //can be done only after context is made current.
}
void FOpenGLDynamicRHI::RHIEndDrawingViewport(FViewportRHIParamRef ViewportRHI,bool bPresent,bool bLockToVsync)
{
	VERIFY_GL_SCOPE();

	DYNAMIC_CAST_OPENGLRESOURCE(Viewport,Viewport);

	SCOPE_CYCLE_COUNTER(STAT_OpenGLPresentTime);

	check(DrawingViewport.GetReference() == Viewport);

	FOpenGLTexture2D* BackBuffer = Viewport->GetBackBuffer();

	uint32 IdleStart = FPlatformTime::Cycles();

	PlatformBlitToViewport(PlatformDevice,
		Viewport->OpenGLContext,
		BackBuffer->GetSizeX(),
		BackBuffer->GetSizeY(),
		bPresent,
		bLockToVsync,
		RHIOpenGLConsoleVariables::SyncInterval
	);

	DrawingViewport = NULL;

	// Don't wait on the GPU when using SLI, let the driver determine how many frames behind the GPU should be allowed to get
	if (GNumActiveGPUsForRendering == 1)
	{
		static const auto CFinishFrameVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.FinishCurrentFrame"));
		if (!CFinishFrameVar->GetValueOnRenderThread())
		{
			// Wait for the GPU to finish rendering the previous frame before finishing this frame.
			Viewport->WaitForFrameEventCompletion();
			Viewport->IssueFrameEvent();
		}
		else
		{
			// Finish current frame immediately to reduce latency
			Viewport->IssueFrameEvent();
			Viewport->WaitForFrameEventCompletion();
		}
		
		// If the input latency timer has been triggered, block until the GPU is completely
		// finished displaying this frame and calculate the delta time.
		if ( GInputLatencyTimer.RenderThreadTrigger )
		{
			Viewport->WaitForFrameEventCompletion();
			uint32 EndTime = FPlatformTime::Cycles();
			GInputLatencyTimer.DeltaTime = EndTime - GInputLatencyTimer.StartTime;
			GInputLatencyTimer.RenderThreadTrigger = false;
		}
	}

	GRenderThreadIdle[ERenderThreadIdleTypes::WaitingForGPUPresent] += FPlatformTime::Cycles() - IdleStart;

	if (bRevertToSharedContextAfterDrawingViewport)
	{
		PlatformSharedContextSetup(PlatformDevice);
		bRevertToSharedContextAfterDrawingViewport = false;
	}
}