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

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

Change 3065209 on 2016/07/26 by Steve.Cano

Add Android Texture Format used for packaging/cooking to the Manifest File

#ue4
#android
#jira UE-33645

Change 3068915 on 2016/07/28 by Steve.Cano

Add an additional Texture Compression support line in the manifest for DXT

#ue4
#android
#jira UE-33645

Change 3075911 on 2016/08/03 by Steve.Cano

Make the "Running {ProjectName} on {Device}" toast stay up when launching a game to an Android device until we've finished running it, as it does on other platforms. This logic already existed but only ran if the "Prebuilt" flag was passed in, however we want this to always run now. Re-writing to run through waiting on each process to finish for each device launched on

#jira UE-3122
#ue4
#android

Change 3080981 on 2016/08/08 by Steve.Cano

Clear any input before removing the TouchInterface from the screen to prevent infinite input after it is cleared

#jira UE-33956
#ue4
#platform

Change 3092587 on 2016/08/17 by Steve.Cano

Adding "IsGamepadAttached" functionality to Android Application

#jira UE-33264
#ue4
#android

Change 3095840 on 2016/08/21 by Dmitriy.Dyomin

Fixed: Particle Cutout Crashes On Certain Devices (Samsung Galaxy Note 2)
Happens only with non-instanced path

#jira UE-34604

Change 3095855 on 2016/08/22 by Dmitriy.Dyomin

Allow UWorldComposition::GetTilesList to be used in runtime code
Licensee request https://udn.unrealengine.com/questions/307586/world-compositions-world-dimensions.html

Change 3096093 on 2016/08/22 by Allan.Bentham

Allow Vulkan api logging on android

Change 3096361 on 2016/08/22 by Steve.Cano

Github 2663 pull - Pass any extras used to launch SplashActivity down to GameActivity (Contributed by sangpan)

#jira UE-34050
#github #2663
#ue4
#android

Change 3097412 on 2016/08/23 by Dmitriy.Dyomin

Using BulkSerialize for cooked collision data to speed up serialization

Change 3098957 on 2016/08/23 by Jack.Porter

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

Change 3099058 on 2016/08/24 by Jack.Porter

Check EXT_debug_label and EXT_debug_marker functions were found before calling as a few devices to not implement these extensions
#UE-35087

Change 3099131 on 2016/08/24 by Dmitriy.Dyomin

Fixed: HDR compressed texture become black in some mali devices
Use sized internal format for half-float textures on ES3 devices, as ES3 spec expects it
#jira UE-35018

Change 3099150 on 2016/08/24 by Dmitriy.Dyomin

Enable HALF_FLOAT and UNSIGNED_INT_2_10_10_10_REV vertex formats on ES3+ devices, spec req

Change 3102252 on 2016/08/26 by Dmitriy.Dyomin

Prevent view uniform buffer crash on ES2 devices that do not support 3D textures

Change 3102258 on 2016/08/26 by Dmitriy.Dyomin

Enabled refraction on iPadMini4
#jira UE-35079

Change 3102651 on 2016/08/26 by Dmitriy.Dyomin

Fixed: instanced static mesh world normals
Also removed unnecessary instance matrix transposing
#jira UE-35075

Change 3109397 on 2016/09/01 by Jack.Porter

Fix problem with Android sessions not appearing in Session Frontend

#jira UE-35261

Change 3109490 on 2016/09/01 by Jack.Porter

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

Change 3111628 on 2016/09/02 by Jack.Porter

Landscape wireframe LOD visualization with tessellation

Change 3112809 on 2016/09/02 by Chris.Babcock

Update cached length when file is written to on Android
#jira UE-35558
#ue4
#android

Change 3113245 on 2016/09/04 by Dmitriy.Dyomin

Fixed: Subway Sequencer plays only a black screen when packaged for ESDSR (3.1+AEP)
#jira UE-34291

Change 3113249 on 2016/09/04 by Dmitriy.Dyomin

Replicated fix from 4.13: GPU particles no longer work on iOS or TVOS Metal devices
#jira UE-34782

Change 3113513 on 2016/09/05 by Allan.Bentham

Add vulkan version parameter to android device profile selector's source inputs .
reinstate Vulkan Disable cvar functionality.
Added mali no vulkan device profile.

Change 3113519 on 2016/09/05 by Allan.Bentham

Remove temp 4.13 hack to avoid public header changes.

Change 3113535 on 2016/09/05 by Allan.Bentham

Decode 32 bit HDR formats when using scene captures.
#jira UE-25444

Change 3113813 on 2016/09/06 by Dmitriy.Dyomin

Resend to server sub-levels visibility state right after world actors are initialized.
During seamless travel client loads always-loaded sub-levels before world actors are initialized and ServerUpdateLevelVisibility calls in UWorld::AddToWorld are skipped.

Change 3113870 on 2016/09/06 by Jack.Porter

Fix issue with ES2 Feature Level preview and Mobile Preview PIE not limiting materials to 8 textures
#jira UE-35591

Change 3115031 on 2016/09/06 by Chris.Babcock

Add Vulkan version code not moved over from 4.13.1
#jira UE-35642
#ue4
#android

Change 3115496 on 2016/09/07 by Dmitriy.Dyomin

Use the same DDC key for source reflection data and encoded data. Fixes broken reflections on mobile
#jira UE-35647

[CL 3116720 by Chris Babcock in Main branch]
2016-09-07 17:04:11 -04:00

607 lines
22 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;
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;
}
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.
const bool bES31Supported = FAndroidGPUInfo::Get().GLVersion.Contains(TEXT("OpenGL ES 3.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);
if (bES31Supported && bBuildForES31 && CVarDisableES31->GetValueOnAnyThread() == 0)
{
// shut down existing ES2 egl.
FAndroidAppEntry::ReleaseEGL();
// Re-init gles for 3.1
AndroidEGL::GetInstance()->Init(AndroidEGL::AV_OpenGLES, 3, 1, false);
}
else
{
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.
check(bBuildForES2);
}
}
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;
void FAndroidOpenGL::ProcessExtensions(const FString& ExtensionsString)
{
FOpenGLES2::ProcessExtensions(ExtensionsString);
FString VersionString = FString(ANSI_TO_TCHAR((const ANSICHAR*)glGetString(GL_VERSION)));
bES30Support = VersionString.Contains(TEXT("OpenGL ES 3."));
bES31Support = VersionString.Contains(TEXT("OpenGL ES 3.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 (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;
}
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