Files
UnrealEngineUWP/Engine/Source/Runtime/OpenGLDrv/Private/Android/AndroidOpenGL.cpp
Chris Babcock 093fd5df10 Copying //UE4/Dev-Mobile to //UE4/Dev-Main (Source: //UE4/Dev-Mobile @ 3155909)
#lockdown Nick.Penwarden
#rb none

==========================
MAJOR FEATURES + CHANGES
==========================

Change 3118534 on 2016/09/08 by Steve.Cano

	Certain non-looping SFX would not properly fire "Stop" events when the effect was finished, and therefore Sound Mixes that should end at the end of a SFX (such as ducking the BGM volume) were not properly finishing. Fixing the IsSourceFinished call to check the Position of the player to determine if we are actually done playing, which was not working properly before for PCM sounds.

	#jira UE-35016
	#ue4
	#android

Change 3119125 on 2016/09/09 by Dmitriy.Dyomin

	Mobile launcher profile wizard:
	Fixed case where DLC will not be built if user selects non Development build configuration
	Fixed case where project maps will be empty if UE4 and project located on different drives

Change 3122584 on 2016/09/13 by Allan.Bentham

	Add simple clip plane for planar reflections.
	#jira UE-32449

Change 3129390 on 2016/09/16 by Chris.Babcock

	Fixed ES 3.1 detection to also support devices returning ES 3.2 support (eg Note 7)
	#jira UE-35598

Change 3129867 on 2016/09/18 by Jack.Porter

	Fixed ES 3.1 detection to also support devices returning ES 3.2 support (eg Note 7)
	#jira UE-35598

Change 3131961 on 2016/09/20 by Allan.Bentham

	Fix missing editor widgets and gamma incorrectness when mobileHDR == false.
	Fix editor widget rendering when hdr encoding is active.

	#jira UE-34281

Change 3132717 on 2016/09/20 by Chris.Babcock

	Add $S(ProjectDir) to UPL
	#jira UE-35483
	#ue4

Change 3132940 on 2016/09/20 by Chris.Babcock

	Corrected case for some include files (contributed by Yukariin)
	#jira UE-33816
	#PR #2636
	#ue4
	#android

Change 3134098 on 2016/09/21 by Allan.Bentham

	Mobile CSM shadow quality controllable via quality levels.
	#jira UEMOB-74

Change 3134931 on 2016/09/21 by Chris.Babcock

	Allow Windows types in vulkan.h
	#jira UE-36270
	#ue4
	#vulkan

Change 3135380 on 2016/09/21 by Dmitriy.Dyomin

	Plugin which exposes some of BuildPatchServices functionality to BP. Inteded to be used on mobile platforms for donwloading game content.
	Right now misses: IOS download directory and iOS WiFi detection
	#jira UEMOB-157

Change 3136004 on 2016/09/22 by Allan.Bentham

	Add project option to disable vertex fog on mobile.
	Vertex fog is now enabled even when mobile HDR is not.

	#jira UEMOB-148

Change 3137377 on 2016/09/22 by Dmitriy.Dyomin

	Fix compile error from CL# 3135380

Change 3139571 on 2016/09/26 by Jack.Porter

	Applied deferred change CL 3101462 to mobile to make planar reflections no longer update GPU particles

Change 3139663 on 2016/09/26 by Jack.Porter

	Include Android shader cache files when packaging

Change 3142839 on 2016/09/28 by Dmitriy.Dyomin

	Added WiFi connection detection on iOS

Change 3142845 on 2016/09/28 by Jack.Porter

	Fixed various issues with TcpMessageTransport discovered when transferring automation testing screenshots from mobile devices
	- socket not readable or writable is not an error condition if output buffer is full
	- messages were previously limited to 64kb but screenshots overflowed this
	- messages over 8kb were not reliably received as the inbound buffer was full so the available bytes was always less than the message length
	- sending large messages was not reliable due to the output buffer being full

Change 3143280 on 2016/09/28 by Jack.Porter

	Clear out UnbuiltInstanceBoundsList when async building a tree with no instances

Change 3143282 on 2016/09/28 by Jack.Porter

	Fix issue where client functional tests in the current map do not appear on clients running with cooked content.
	Problem is that the AssetRegistry uses in-memory metadata created on load for currently-loaded assets, but cooked content only has the serialized AssetRegistry and individual assets do not contain any metadata.

Change 3143808 on 2016/09/28 by Steve.Cano

	Assume that the app starts in focus at startup and don't wait for an "APP_EVENT_STATE_WINDOW_GAINED_FOCUS" event to fire, as this event will not come down from SplashActivity since it is not a NativeActivity. If the user then rotates the device in Sensor or FullSensor orientation during SplashActivity and forces an eglSurface recreation, the initial Create will properly execute if we're "in focus". Previously, the create-destroy-create cycle would not properly execute due to the EventManager thinking the app was not yet in focus, and would cause the second create to get a 0x3003 error (EGL_BAD_ALLOC)

	#jira UE-35004
	#ue4
	#android

Change 3144880 on 2016/09/29 by Jack.Porter

	Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)

Change 3146220 on 2016/09/30 by Dmitriy.Dyomin

	Adjusted device button style to make it more readable.
	#jira UE-21881

Change 3146280 on 2016/09/30 by Dmitriy.Dyomin

	Replaced IBuildManifest::ComputeDownloadSize with a new function

Change 3146302 on 2016/09/30 by Allan.Bentham

	Added more stringent checks for ES3.1 compatibility
	#jira UE-36241

Change 3146435 on 2016/09/30 by Jack.Porter

	Prevent landscape grass being duplicated for PIE, causing ensure

	#jira UE-36531

Change 3147532 on 2016/09/30 by Chris.Babcock

	Use .sh extension for Android install scripts on Linux
	#jira UE-36669
	#ue4
	#android
	#linux

Change 3149851 on 2016/10/04 by Dmitriy.Dyomin

	Mobile: Added custom depth rendering
	Mobile: Added support for CustomDepth and SceneDepth in post-process materails

Change 3149852 on 2016/10/04 by Dmitriy.Dyomin

	Fixed comments for SortBasePass console variable

Change 3149857 on 2016/10/04 by Jack.Porter

	Remove dead code in ProceduralFoliageComponentDetails.cpp

Change 3149863 on 2016/10/04 by Jack.Porter

	Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)

Change 3149896 on 2016/10/04 by Dmitriy.Dyomin

	Fixed: SkyLight makes level entire green on Android devices
	#jira UE-34469

Change 3150102 on 2016/10/04 by Jack.Porter

	Bring Protostar 4.13 fixes back to Dev-Mobile

	Engine
	- MaxDescriptorSets = 16384 to prevent crash on Mali
	- Include texture formats in FRenderTargetLayoutHashableStruct to solve RT aliasing issue
	- Use ERenderTargetLoadAction::EClear for planar reflection target to work around Adreno issue
	- Default Adreno to SPIR-V

	Contents
	- Disable fog, reduce CSM shadow quality, fix device profiles
	- Add PSO cache

Change 3150113 on 2016/10/04 by Jack.Porter

	Ensure automation testing screenshots have Alpha=255 (fixes automation screenshots on Mobile)

Change 3150231 on 2016/10/04 by Jack.Porter

	Use a new SessionID GUID each time you use the launcher to launch a session.

Change 3150608 on 2016/10/04 by Jack.Porter

	Changes for automated testing screenshots on Android.

	- Prevent automation screenshots from changing resolution on platforms with fixed resolution
	- Set GRHIAdapterInternalDriverVersion for OpenGL and Vulkan
	- Parse ImgTec/ARM/Qualcomm GRHIVendorId on OpenGL
	- Added helper to convert GRHIVendorId to string

Change 3151318 on 2016/10/04 by Jack.Porter

	Fixed compile error with AdapterVendor

Change 3151366 on 2016/10/04 by Jack.Porter

	Prevent FTcpMessageTransportConnection deadlock on device disconnect

Change 3151397 on 2016/10/05 by Dmitriy.Dyomin

	More consistent BP categories for Mobile Patching utils

Change 3151576 on 2016/10/05 by Dmitriy.Dyomin

	Added on screen warning for invalid reflection captures, can be seen only in game running with FeatureLevel < SM4 and no valid capture data

Change 3151795 on 2016/10/05 by Dmitry.Rekman

	Linux: update UBT to use a v8 multiarch toolchain.

	- Also added toolchain build scripts and ct-ng configs.

Change 3151966 on 2016/10/05 by Allan.Bentham

	Add mobile support for inverse opacity to mobile scene captures as well as SCS_SceneColorSceneDepth and SCS_SceneDepth.
	#jira UEMOB-106

Change 3152664 on 2016/10/05 by Chris.Babcock

	Merging //UE4/Main to Dev-Mobile (//UE4/Dev-Mobile)

Change 3152675 on 2016/10/05 by Will.Fissler

	Fixed patching so that it searches for pak files as well as pkg files.
	#test Patch for QAGame

Change 3152728 on 2016/10/05 by Chris.Babcock

	Update ReflectionCaptureDDCVer (need to resave maps)

Change 3152910 on 2016/10/05 by Dmitry.Rekman

	Linux: Fix toolchain for non-AutoSDKs (github) case (UE-36899).

Change 3152966 on 2016/10/05 by Dmitry.Rekman

	Linux: Fix test for the installed SDK (UE-36899).

Change 3153004 on 2016/10/05 by Dmitry.Rekman

	Linux: fix CIS (UT server case-sens errors).

Change 3153694 on 2016/10/06 by Jack.Porter

	Rollback ReflectionCaptureDDCVer change as bug intended to fix UE-36919 does not repro

Change 3154766 on 2016/10/07 by Jack.Porter

	Merging //UE4/Dev-Main to Dev-Mobile (//UE4/Dev-Mobile)

Change 3154833 on 2016/10/07 by Jack.Porter

	Fix merge error of MobileShadingRenderer.cpp

Change 3154848 on 2016/10/07 by Allan.Bentham

	Fix mobile scene capture's clear code

Change 3154875 on 2016/10/07 by Allan.Bentham

	fix vk build issues

Change 3154941 on 2016/10/07 by Allan.Bentham

	Fix gearvr build fail

Change 3154950 on 2016/10/07 by Allan.Bentham

	Fix shadowed local variable vk build warning on android.

Change 3155909 on 2016/10/07 by Ben.Marsh

	UBT: Attempt to work around C1076 error ("internal heap limit reached: use /Zm to specify a higher limit"), encountered when building with XGE. Specify the AutoReserveMemory attribute on XGE tool tasks that manipulate precompiled headers.

[CL 3155988 by Chris Babcock in Main branch]
2016-10-07 23:11:00 -04:00

662 lines
25 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#if !PLATFORM_ANDROIDESDEFERRED
#include "OpenGLDrvPrivate.h"
#include "OpenGLES2.h"
#include "AndroidWindow.h"
#include "AndroidOpenGLPrivate.h"
PFNEGLGETSYSTEMTIMENVPROC eglGetSystemTimeNV;
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = NULL;
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = NULL;
PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = NULL;
// Occlusion Queries
PFNGLGENQUERIESEXTPROC glGenQueriesEXT = NULL;
PFNGLDELETEQUERIESEXTPROC glDeleteQueriesEXT = NULL;
PFNGLISQUERYEXTPROC glIsQueryEXT = NULL;
PFNGLBEGINQUERYEXTPROC glBeginQueryEXT = NULL;
PFNGLENDQUERYEXTPROC glEndQueryEXT = NULL;
PFNGLGETQUERYIVEXTPROC glGetQueryivEXT = NULL;
PFNGLGETQUERYOBJECTIVEXTPROC glGetQueryObjectivEXT = NULL;
PFNGLGETQUERYOBJECTUIVEXTPROC glGetQueryObjectuivEXT = NULL;
PFNGLQUERYCOUNTEREXTPROC glQueryCounterEXT = NULL;
PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT = NULL;
// Offscreen MSAA rendering
PFNBLITFRAMEBUFFERNVPROC glBlitFramebufferNV = NULL;
PFNGLDISCARDFRAMEBUFFEREXTPROC glDiscardFramebufferEXT = NULL;
PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT = NULL;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL;
PFNGLPUSHGROUPMARKEREXTPROC glPushGroupMarkerEXT = NULL;
PFNGLPOPGROUPMARKEREXTPROC glPopGroupMarkerEXT = NULL;
PFNGLLABELOBJECTEXTPROC glLabelObjectEXT = NULL;
PFNGLGETOBJECTLABELEXTPROC glGetObjectLabelEXT = NULL;
PFNGLMAPBUFFEROESPROC glMapBufferOESa = NULL;
PFNGLUNMAPBUFFEROESPROC glUnmapBufferOESa = NULL;
PFNGLTEXSTORAGE2DPROC glTexStorage2D = NULL;
// KHR_debug
PFNGLDEBUGMESSAGECONTROLKHRPROC glDebugMessageControlKHR = NULL;
PFNGLDEBUGMESSAGEINSERTKHRPROC glDebugMessageInsertKHR = NULL;
PFNGLDEBUGMESSAGECALLBACKKHRPROC glDebugMessageCallbackKHR = NULL;
PFNGLGETDEBUGMESSAGELOGKHRPROC glDebugMessageLogKHR = NULL;
PFNGLGETPOINTERVKHRPROC glGetPointervKHR = NULL;
PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR = NULL;
PFNGLPOPDEBUGGROUPKHRPROC glPopDebugGroupKHR = NULL;
PFNGLOBJECTLABELKHRPROC glObjectLabelKHR = NULL;
PFNGLGETOBJECTLABELKHRPROC glGetObjectLabelKHR = NULL;
PFNGLOBJECTPTRLABELKHRPROC glObjectPtrLabelKHR = NULL;
PFNGLGETOBJECTPTRLABELKHRPROC glGetObjectPtrLabelKHR = NULL;
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = NULL;
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced = NULL;
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor = NULL;
PFNGLUNIFORM4UIVPROC glUniform4uiv = NULL;
PFNGLTEXIMAGE3DPROC glTexImage3D = NULL;
PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = NULL;
PFNGLCOMPRESSEDTEXIMAGE3DPROC glCompressedTexImage3D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glCopyTexSubImage3D = NULL;
PFNGLCLEARBUFFERFIPROC glClearBufferfi = NULL;
PFNGLCLEARBUFFERFVPROC glClearBufferfv = NULL;
PFNGLCLEARBUFFERIVPROC glClearBufferiv = NULL;
PFNGLCLEARBUFFERUIVPROC glClearBufferuiv = NULL;
PFNGLDRAWBUFFERSPROC glDrawBuffers = NULL;
PFNGLTEXBUFFEREXTPROC glTexBufferEXT = NULL;
PFNGLGETPROGRAMBINARYOESPROC glGetProgramBinary = NULL;
PFNGLPROGRAMBINARYOESPROC glProgramBinary = NULL;
PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
PFNGLGETUNIFORMBLOCKINDEXPROC glGetUniformBlockIndex = NULL;
PFNGLUNIFORMBLOCKBINDINGPROC glUniformBlockBinding = NULL;
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR = NULL;
PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC glFramebufferTextureMultisampleMultiviewOVR = NULL;
struct FPlatformOpenGLDevice
{
void SetCurrentSharedContext();
void SetCurrentRenderingContext();
void SetCurrentNULLContext();
FPlatformOpenGLDevice();
~FPlatformOpenGLDevice();
void Init();
void LoadEXT();
void Terminate();
void ReInit();
};
FPlatformOpenGLDevice::~FPlatformOpenGLDevice()
{
FAndroidAppEntry::ReleaseEGL();
}
FPlatformOpenGLDevice::FPlatformOpenGLDevice()
{
}
// call out to JNI to see if the application was packaged for GearVR
extern bool AndroidThunkCpp_IsGearVRApplication();
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.
}
FPlatformOpenGLDevice* PlatformCreateOpenGLDevice()
{
FPlatformOpenGLDevice* Device = new FPlatformOpenGLDevice();
Device->Init();
return Device;
}
bool PlatformCanEnableGPUCapture()
{
return false;
}
void PlatformReleaseOpenGLContext(FPlatformOpenGLDevice* Device, FPlatformOpenGLContext* Context)
{
}
void* PlatformGetWindow(FPlatformOpenGLContext* Context, void** AddParam)
{
check(Context);
return (void*)&Context->eglContext;
}
bool PlatformBlitToViewport( FPlatformOpenGLDevice* Device, const FOpenGLViewport& Viewport, uint32 BackbufferSizeX, uint32 BackbufferSizeY, bool bPresent,bool bLockToVsync, int32 SyncInterval )
{
if (bPresent && Viewport.GetCustomPresent())
{
bPresent = Viewport.GetCustomPresent()->Present(SyncInterval);
}
if (bPresent)
{
AndroidEGL::GetInstance()->SwapBuffers();
}
return bPresent;
}
void PlatformRenderingContextSetup(FPlatformOpenGLDevice* Device)
{
Device->SetCurrentRenderingContext();
}
void PlatformFlushIfNeeded()
{
}
void PlatformRebindResources(FPlatformOpenGLDevice* Device)
{
}
void PlatformSharedContextSetup(FPlatformOpenGLDevice* Device)
{
Device->SetCurrentSharedContext();
}
void PlatformNULLContextSetup()
{
AndroidEGL::GetInstance()->SetCurrentContext(EGL_NO_CONTEXT, EGL_NO_SURFACE);
}
EOpenGLCurrentContext PlatformOpenGLCurrentContext(FPlatformOpenGLDevice* Device)
{
return (EOpenGLCurrentContext)AndroidEGL::GetInstance()->GetCurrentContextType();
}
void PlatformRestoreDesktopDisplayMode()
{
}
bool PlatformInitOpenGL()
{
check(!FAndroidMisc::ShouldUseVulkan());
{
// determine ES version. PlatformInitOpenGL happens before ProcessExtensions and therefore FAndroidOpenGL::bES31Support.
FString SubVersion;
const bool bES31Supported = FAndroidGPUInfo::Get().GLVersion.Split(TEXT("OpenGL ES 3."), nullptr, &SubVersion) && FCString::Atoi(*SubVersion) >= 1;
static const auto CVarDisableES31 = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.Android.DisableOpenGLES31Support"));
bool bBuildForES31 = false;
GConfig->GetBool(TEXT("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings"), TEXT("bBuildForES31"), bBuildForES31, GEngineIni);
const bool bSupportsFloatingPointRTs = FAndroidMisc::SupportsFloatingPointRenderTargets();
const bool bSupportsShaderIOBlocks = FAndroidMisc::SupportsShaderIOBlocks();
if (bBuildForES31 && bES31Supported && bSupportsFloatingPointRTs && bSupportsShaderIOBlocks && CVarDisableES31->GetValueOnAnyThread() == 0)
{
FAndroidOpenGL::CurrentFeatureLevelSupport = FAndroidOpenGL::EFeatureLevelSupport::ES31;
// shut down existing ES2 egl.
UE_LOG(LogRHI, Log, TEXT("App is packaged for OpenGL ES 3.1 and an ES 3.1-capable device was detected. Reinitializing OpenGL ES with a 3.1 context."));
FAndroidAppEntry::ReleaseEGL();
// Re-init gles for 3.1
AndroidEGL::GetInstance()->Init(AndroidEGL::AV_OpenGLES, 3, 1, false);
}
else
{
FAndroidOpenGL::CurrentFeatureLevelSupport = FAndroidOpenGL::EFeatureLevelSupport::ES2;
if (bBuildForES31)
{
UE_LOG(LogRHI, Log, TEXT("App is packaged for OpenGL ES 3.1 but device has not met all the requirements for ES 3.1 :"));
if (CVarDisableES31->GetValueOnAnyThread())
{
UE_LOG(LogRHI, Log, TEXT(" ES 3.1 support was disabled via r.Android.DisableOpenGLES31Support"));
}
UE_LOG(LogRHI, Log, TEXT(" Device has OpenGL ES 3.1 support: %s"), bES31Supported ? TEXT("YES") : TEXT("NO"));
UE_LOG(LogRHI, Log, TEXT(" Floating point render target support: %s"), bSupportsFloatingPointRTs ? TEXT("YES") : TEXT("NO"));
UE_LOG(LogRHI, Log, TEXT(" EXT_shader_io_blocks support: %s"), bSupportsShaderIOBlocks ? TEXT("YES") : TEXT("NO"));
}
bool bBuildForES2 = false;
GConfig->GetBool(TEXT("/Script/AndroidRuntimeSettings.AndroidRuntimeSettings"), TEXT("bBuildForES2"), bBuildForES2, GEngineIni);
// If we're here and there's no ES2 data then we're in trouble.
checkf(bBuildForES2, TEXT("This device only supports OpenGL ES 2 but the app was not packaged with ES2 support."));
}
}
return true;
}
bool PlatformOpenGLContextValid()
{
return AndroidEGL::GetInstance()->IsCurrentContextValid();
}
void PlatformGetBackbufferDimensions( uint32& OutWidth, uint32& OutHeight )
{
AndroidEGL::GetInstance()->GetDimensions(OutWidth, OutHeight);
}
// =============================================================
void PlatformGetNewOcclusionQuery( GLuint* OutQuery, uint64* OutQueryContext )
{
}
bool PlatformContextIsCurrent( uint64 QueryContext )
{
return true;
}
void FPlatformOpenGLDevice::LoadEXT()
{
eglGetSystemTimeNV = (PFNEGLGETSYSTEMTIMENVPROC)((void*)eglGetProcAddress("eglGetSystemTimeNV"));
eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)((void*)eglGetProcAddress("eglCreateSyncKHR"));
eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)((void*)eglGetProcAddress("eglDestroySyncKHR"));
eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)((void*)eglGetProcAddress("eglClientWaitSyncKHR"));
glDebugMessageControlKHR = (PFNGLDEBUGMESSAGECONTROLKHRPROC)((void*)eglGetProcAddress("glDebugMessageControlKHR"));
// Some PowerVR drivers (Rogue Han and Intel-based devices) are crashing using glDebugMessageControlKHR (causes signal 11 crash)
if (glDebugMessageControlKHR != NULL && FAndroidMisc::GetGPUFamily().Contains(TEXT("PowerVR")))
{
glDebugMessageControlKHR = NULL;
}
glDebugMessageInsertKHR = (PFNGLDEBUGMESSAGEINSERTKHRPROC)((void*)eglGetProcAddress("glDebugMessageInsertKHR"));
glDebugMessageCallbackKHR = (PFNGLDEBUGMESSAGECALLBACKKHRPROC)((void*)eglGetProcAddress("glDebugMessageCallbackKHR"));
glDebugMessageLogKHR = (PFNGLGETDEBUGMESSAGELOGKHRPROC)((void*)eglGetProcAddress("glDebugMessageLogKHR"));
glGetPointervKHR = (PFNGLGETPOINTERVKHRPROC)((void*)eglGetProcAddress("glGetPointervKHR"));
glPushDebugGroupKHR = (PFNGLPUSHDEBUGGROUPKHRPROC)((void*)eglGetProcAddress("glPushDebugGroupKHR"));
glPopDebugGroupKHR = (PFNGLPOPDEBUGGROUPKHRPROC)((void*)eglGetProcAddress("glPopDebugGroupKHR"));
glObjectLabelKHR = (PFNGLOBJECTLABELKHRPROC)((void*)eglGetProcAddress("glObjectLabelKHR"));
glGetObjectLabelKHR = (PFNGLGETOBJECTLABELKHRPROC)((void*)eglGetProcAddress("glGetObjectLabelKHR"));
glObjectPtrLabelKHR = (PFNGLOBJECTPTRLABELKHRPROC)((void*)eglGetProcAddress("glObjectPtrLabelKHR"));
glGetObjectPtrLabelKHR = (PFNGLGETOBJECTPTRLABELKHRPROC)((void*)eglGetProcAddress("glGetObjectPtrLabelKHR"));
glGetProgramBinary = (PFNGLGETPROGRAMBINARYOESPROC)((void*)eglGetProcAddress("glGetProgramBinaryOES"));
glProgramBinary = (PFNGLPROGRAMBINARYOESPROC)((void*)eglGetProcAddress("glProgramBinaryOES"));
}
FPlatformOpenGLContext* PlatformCreateOpenGLContext(FPlatformOpenGLDevice* Device, void* InWindowHandle)
{
//Assumes Device is already initialized and context already created.
return AndroidEGL::GetInstance()->GetRenderingContext();
}
void PlatformDestroyOpenGLContext(FPlatformOpenGLDevice* Device, FPlatformOpenGLContext* Context)
{
delete Device; //created here, destroyed here, but held by RHI.
}
FRHITexture* PlatformCreateBuiltinBackBuffer(FOpenGLDynamicRHI* OpenGLRHI, uint32 SizeX, uint32 SizeY)
{
uint32 Flags = TexCreate_RenderTargetable;
FOpenGLTexture2D* Texture2D = new FOpenGLTexture2D(OpenGLRHI, AndroidEGL::GetInstance()->GetOnScreenColorRenderBuffer(), GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, SizeX, SizeY, 0, 1, 1, 1, PF_B8G8R8A8, false, false, Flags, nullptr, FClearValueBinding::Transparent);
OpenGLTextureAllocated(Texture2D, Flags);
return Texture2D;
}
void PlatformResizeGLContext( FPlatformOpenGLDevice* Device, FPlatformOpenGLContext* Context, uint32 SizeX, uint32 SizeY, bool bFullscreen, bool bWasFullscreen, GLenum BackBufferTarget, GLuint BackBufferResource)
{
check(Context);
glViewport(0, 0, SizeX, SizeY);
VERIFY_GL(glViewport);
}
void PlatformGetSupportedResolution(uint32 &Width, uint32 &Height)
{
}
bool PlatformGetAvailableResolutions(FScreenResolutionArray& Resolutions, bool bIgnoreRefreshRate)
{
return true;
}
int32 PlatformGlGetError()
{
return glGetError();
}
// =============================================================
void PlatformReleaseOcclusionQuery( GLuint Query, uint64 QueryContext )
{
}
void FPlatformOpenGLDevice::SetCurrentSharedContext()
{
AndroidEGL::GetInstance()->SetCurrentSharedContext();
}
void PlatformDestroyOpenGLDevice(FPlatformOpenGLDevice* Device)
{
delete Device;
}
void FPlatformOpenGLDevice::SetCurrentRenderingContext()
{
AndroidEGL::GetInstance()->SetCurrentRenderingContext();
}
void PlatformLabelObjects()
{
// @todo: Check that there is a valid id (non-zero) as LabelObject will fail otherwise
GLuint RenderBuffer = AndroidEGL::GetInstance()->GetOnScreenColorRenderBuffer();
if (RenderBuffer != 0)
{
FOpenGL::LabelObject(GL_RENDERBUFFER, RenderBuffer, "OnScreenColorRB");
}
GLuint FrameBuffer = AndroidEGL::GetInstance()->GetResolveFrameBuffer();
if (FrameBuffer != 0)
{
FOpenGL::LabelObject(GL_FRAMEBUFFER, FrameBuffer, "ResolveFB");
}
}
//--------------------------------
void PlatformGetNewRenderQuery( GLuint* OutQuery, uint64* OutQueryContext )
{
GLuint NewQuery = 0;
FOpenGL::GenQueries( 1, &NewQuery );
*OutQuery = NewQuery;
*OutQueryContext = 0;
}
void PlatformReleaseRenderQuery( GLuint Query, uint64 QueryContext )
{
FOpenGL::DeleteQueries(1, &Query );
}
bool FAndroidOpenGL::bUseHalfFloatTexStorage = false;
bool FAndroidOpenGL::bSupportsTextureBuffer = false;
bool FAndroidOpenGL::bUseES30ShadingLanguage = false;
bool FAndroidOpenGL::bES30Support = false;
bool FAndroidOpenGL::bES31Support = false;
bool FAndroidOpenGL::bSupportsInstancing = false;
bool FAndroidOpenGL::bHasHardwareHiddenSurfaceRemoval = false;
bool FAndroidOpenGL::bSupportsMobileMultiView = false;
FAndroidOpenGL::EFeatureLevelSupport FAndroidOpenGL::CurrentFeatureLevelSupport = FAndroidOpenGL::EFeatureLevelSupport::Invalid;
void FAndroidOpenGL::ProcessExtensions(const FString& ExtensionsString)
{
FOpenGLES2::ProcessExtensions(ExtensionsString);
FString VersionString = FString(ANSI_TO_TCHAR((const ANSICHAR*)glGetString(GL_VERSION)));
FString SubVersionString;
bES30Support = VersionString.Split(TEXT("OpenGL ES 3."), nullptr, &SubVersionString);
bES31Support = bES30Support && FCString::Atoi(*SubVersionString) >= 1;
// Get procedures
if (bSupportsOcclusionQueries || bSupportsDisjointTimeQueries)
{
glGenQueriesEXT = (PFNGLGENQUERIESEXTPROC) ((void*)eglGetProcAddress("glGenQueriesEXT"));
glDeleteQueriesEXT = (PFNGLDELETEQUERIESEXTPROC) ((void*)eglGetProcAddress("glDeleteQueriesEXT"));
glIsQueryEXT = (PFNGLISQUERYEXTPROC) ((void*)eglGetProcAddress("glIsQueryEXT"));
glBeginQueryEXT = (PFNGLBEGINQUERYEXTPROC) ((void*)eglGetProcAddress("glBeginQueryEXT"));
glEndQueryEXT = (PFNGLENDQUERYEXTPROC) ((void*)eglGetProcAddress("glEndQueryEXT"));
glGetQueryivEXT = (PFNGLGETQUERYIVEXTPROC) ((void*)eglGetProcAddress("glGetQueryivEXT"));
glGetQueryObjectivEXT = (PFNGLGETQUERYOBJECTIVEXTPROC) ((void*)eglGetProcAddress("glGetQueryObjectivEXT"));
glGetQueryObjectuivEXT = (PFNGLGETQUERYOBJECTUIVEXTPROC)((void*)eglGetProcAddress("glGetQueryObjectuivEXT"));
}
if (bSupportsDisjointTimeQueries)
{
glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC) ((void*)eglGetProcAddress("glQueryCounterEXT"));
glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC) ((void*)eglGetProcAddress("glGetQueryObjectui64vEXT"));
// If EXT_disjoint_timer_query wasn't found, NV_timer_query might be available
if (glQueryCounterEXT == NULL)
{
glQueryCounterEXT = (PFNGLQUERYCOUNTEREXTPROC)eglGetProcAddress("glQueryCounterNV");
}
if (glGetQueryObjectui64vEXT == NULL)
{
glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)eglGetProcAddress("glGetQueryObjectui64vNV");
}
}
glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)((void*)eglGetProcAddress("glDiscardFramebufferEXT"));
glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)((void*)eglGetProcAddress("glFramebufferTexture2DMultisampleEXT"));
glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)((void*)eglGetProcAddress("glRenderbufferStorageMultisampleEXT"));
glPushGroupMarkerEXT = (PFNGLPUSHGROUPMARKEREXTPROC)((void*)eglGetProcAddress("glPushGroupMarkerEXT"));
glPopGroupMarkerEXT = (PFNGLPOPGROUPMARKEREXTPROC)((void*)eglGetProcAddress("glPopGroupMarkerEXT"));
glLabelObjectEXT = (PFNGLLABELOBJECTEXTPROC)((void*)eglGetProcAddress("glLabelObjectEXT"));
glGetObjectLabelEXT = (PFNGLGETOBJECTLABELEXTPROC)((void*)eglGetProcAddress("glGetObjectLabelEXT"));
bSupportsETC2 = bES30Support;
bUseES30ShadingLanguage = bES30Support;
FString RendererString = FString(ANSI_TO_TCHAR((const ANSICHAR*)glGetString(GL_RENDERER)));
if (RendererString.Contains(TEXT("SGX 540")))
{
UE_LOG(LogRHI, Warning, TEXT("Disabling support for GL_OES_packed_depth_stencil on SGX 540"));
bSupportsPackedDepthStencil = false;
bRequiresTexture2DPrecisionHack = true;
}
const bool bIsPoverVRBased = RendererString.Contains(TEXT("PowerVR"));
if (bIsPoverVRBased)
{
bHasHardwareHiddenSurfaceRemoval = true;
UE_LOG(LogRHI, Log, TEXT("Enabling support for Hidden Surface Removal on PowerVR"));
}
const bool bIsAdrenoBased = RendererString.Contains(TEXT("Adreno"));
if (bIsAdrenoBased)
{
// This is to avoid a bug in Adreno drivers that define GL_EXT_shader_framebuffer_fetch even when device does not support this extension
// OpenGL ES 3.1 V@127.0 (GIT@I1af360237c)
bRequiresShaderFramebufferFetchUndef = !bSupportsShaderFramebufferFetch;
bRequiresARMShaderFramebufferFetchDepthStencilUndef = !bSupportsShaderDepthStencilFetch;
// Adreno 2xx doesn't work with packed depth stencil enabled
if (RendererString.Contains(TEXT("Adreno (TM) 2")))
{
UE_LOG(LogRHI, Warning, TEXT("Disabling support for GL_OES_packed_depth_stencil on Adreno 2xx"));
bSupportsPackedDepthStencil = false;
}
}
if (bES30Support)
{
glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)((void*)eglGetProcAddress("glDrawElementsInstanced"));
glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)((void*)eglGetProcAddress("glDrawArraysInstanced"));
glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)((void*)eglGetProcAddress("glVertexAttribDivisor"));
glUniform4uiv = (PFNGLUNIFORM4UIVPROC)((void*)eglGetProcAddress("glUniform4uiv"));
glTexImage3D = (PFNGLTEXIMAGE3DPROC)((void*)eglGetProcAddress("glTexImage3D"));
glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC)((void*)eglGetProcAddress("glTexSubImage3D"));
glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC)((void*)eglGetProcAddress("glCompressedTexImage3D"));
glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)((void*)eglGetProcAddress("glCompressedTexSubImage3D"));
glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC)((void*)eglGetProcAddress("glCopyTexSubImage3D"));
glClearBufferfi = (PFNGLCLEARBUFFERFIPROC)((void*)eglGetProcAddress("glClearBufferfi"));
glClearBufferfv = (PFNGLCLEARBUFFERFVPROC)((void*)eglGetProcAddress("glClearBufferfv"));
glClearBufferiv = (PFNGLCLEARBUFFERIVPROC)((void*)eglGetProcAddress("glClearBufferiv"));
glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC)((void*)eglGetProcAddress("glClearBufferuiv"));
glDrawBuffers = (PFNGLDRAWBUFFERSPROC)((void*)eglGetProcAddress("glDrawBuffers"));
glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)((void*)eglGetProcAddress("glBindBufferRange"));
glBindBufferBase = (PFNGLBINDBUFFERBASEPROC)((void*)eglGetProcAddress("glBindBufferBase"));
glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)((void*)eglGetProcAddress("glGetUniformBlockIndex"));
glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)((void*)eglGetProcAddress("glUniformBlockBinding"));
// Required by the ES3 spec
bSupportsInstancing = true;
bSupportsTextureFloat = true;
bSupportsTextureHalfFloat = true;
bSupportsRGB10A2 = true;
bSupportsVertexHalfFloat = true;
// According to https://www.khronos.org/registry/gles/extensions/EXT/EXT_color_buffer_float.txt
bSupportsColorBufferHalfFloat = (bSupportsColorBufferHalfFloat || bSupportsColorBufferFloat);
}
if (bES30Support)
{
// Mobile multi-view setup
const bool bMultiViewSupport = ExtensionsString.Contains(TEXT("GL_OVR_multiview"));
const bool bMultiView2Support = ExtensionsString.Contains(TEXT("GL_OVR_multiview2"));
const bool bMultiViewMultiSampleSupport = ExtensionsString.Contains(TEXT("GL_OVR_multiview_multisampled_render_to_texture"));
if (bMultiViewSupport && bMultiView2Support && bMultiViewMultiSampleSupport)
{
glFramebufferTextureMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC)((void*)eglGetProcAddress("glFramebufferTextureMultiviewOVR"));
glFramebufferTextureMultisampleMultiviewOVR = (PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC)((void*)eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
bSupportsMobileMultiView = (glFramebufferTextureMultiviewOVR != NULL) && (glFramebufferTextureMultisampleMultiviewOVR != NULL);
// Just because the driver declares multi-view support and hands us valid function pointers doesn't actually guarantee the feature works...
if (bSupportsMobileMultiView)
{
UE_LOG(LogRHI, Log, TEXT("Device supports mobile multi-view."));
}
}
}
if (bES31Support)
{
bSupportsTextureBuffer = ExtensionsString.Contains(TEXT("GL_EXT_texture_buffer"));
if (bSupportsTextureBuffer)
{
glTexBufferEXT = (PFNGLTEXBUFFEREXTPROC)((void*)eglGetProcAddress("glTexBufferEXT"));
}
}
if (bES30Support || bIsAdrenoBased)
{
// Attempt to find ES 3.0 glTexStorage2D if we're on an ES 3.0 device
glTexStorage2D = (PFNGLTEXSTORAGE2DPROC)((void*)eglGetProcAddress("glTexStorage2D"));
if( glTexStorage2D != NULL )
{
bUseHalfFloatTexStorage = true;
}
else
{
// need to disable GL_EXT_color_buffer_half_float support because we have no way to allocate the storage and the driver doesn't work without it.
UE_LOG(LogRHI,Warning,TEXT("Disabling support for GL_EXT_color_buffer_half_float as we cannot bind glTexStorage2D"));
bSupportsColorBufferHalfFloat = false;
}
}
//@todo android: need GMSAAAllowed ?
if (bSupportsNVFrameBufferBlit)
{
glBlitFramebufferNV = (PFNBLITFRAMEBUFFERNVPROC)((void*)eglGetProcAddress("glBlitFramebufferNV"));
}
glMapBufferOESa = (PFNGLMAPBUFFEROESPROC)((void*)eglGetProcAddress("glMapBufferOES"));
glUnmapBufferOESa = (PFNGLUNMAPBUFFEROESPROC)((void*)eglGetProcAddress("glUnmapBufferOES"));
//On Android, there are problems compiling shaders with textureCubeLodEXT calls in the glsl code,
// so we set this to false to modify the glsl manually at compile-time.
bSupportsTextureCubeLodEXT = false;
// On some Android devices with Mali GPUs textureCubeLod is not available.
if (RendererString.Contains(TEXT("Mali-400")))
{
bSupportsShaderTextureCubeLod = false;
}
// Nexus 5 (Android 4.4.2) doesn't like glVertexAttribDivisor(index, 0) called when not using a glDrawElementsInstanced
if (bIsAdrenoBased && VersionString.Contains(TEXT("OpenGL ES 3.0 V@66.0 AU@ (CL@)")))
{
UE_LOG(LogRHI, Warning, TEXT("Disabling support for hardware instancing on Adreno 330 OpenGL ES 3.0 V@66.0 AU@ (CL@)"));
bSupportsInstancing = false;
}
if (bSupportsBGRA8888)
{
// Check whether device supports BGRA as color attachment
GLuint FrameBuffer;
glGenFramebuffers(1, &FrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, FrameBuffer);
GLuint BGRA8888Texture;
glGenTextures(1, &BGRA8888Texture);
glBindTexture(GL_TEXTURE_2D, BGRA8888Texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 256, 256, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, BGRA8888Texture, 0);
bSupportsBGRA8888RenderTarget = (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
glDeleteTextures(1, &BGRA8888Texture);
glDeleteFramebuffers(1, &FrameBuffer);
}
}
FString FAndroidMisc::GetGPUFamily()
{
return FAndroidGPUInfo::Get().GPUFamily;
}
FString FAndroidMisc::GetGLVersion()
{
return FAndroidGPUInfo::Get().GLVersion;
}
bool FAndroidMisc::SupportsFloatingPointRenderTargets()
{
return FAndroidGPUInfo::Get().bSupportsFloatingPointRenderTargets;
}
bool FAndroidMisc::SupportsShaderFramebufferFetch()
{
return FAndroidGPUInfo::Get().bSupportsFrameBufferFetch;
}
bool FAndroidMisc::SupportsShaderIOBlocks()
{
return FAndroidGPUInfo::Get().bSupportsShaderIOBlocks;
}
void FAndroidMisc::GetValidTargetPlatforms(TArray<FString>& TargetPlatformNames)
{
TargetPlatformNames = FAndroidGPUInfo::Get().TargetPlatformNames;
}
void FAndroidAppEntry::PlatformInit()
{
// create an ES2 EGL here for gpu queries.
AndroidEGL::GetInstance()->Init(AndroidEGL::AV_OpenGLES, 2, 0, false);
}
void FAndroidAppEntry::ReleaseEGL()
{
AndroidEGL* EGL = AndroidEGL::GetInstance();
if (EGL->IsInitialized())
{
EGL->DestroyBackBuffer();
EGL->Terminate();
}
}
#endif