Files
UnrealEngineUWP/Engine/Source/Runtime/OpenGLDrv/Private/Android/AndroidESDeferredOpenGL.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

618 lines
17 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#if PLATFORM_ANDROIDESDEFERRED
/*=============================================================================
AndroidESDeferredOpenGL.cpp: Manual loading of OpenGL functions from DLL.
=============================================================================*/
#include "OpenGLDrvPrivate.h"
#include "AndroidApplication.h"
#include "AndroidOpenGLPrivate.h"
#include <dlfcn.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#define LOG_TAG "UE4"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
///////////////////////////////////////////////////////////////////////////////
// OpenGL function pointers
#define DEFINE_GL_ENTRYPOINTS(Type,Func) Type Func = NULL;
ENUM_GL_ENTRYPOINTS_CORE(DEFINE_GL_ENTRYPOINTS) \
ENUM_GL_ENTRYPOINTS_MANUAL(DEFINE_GL_ENTRYPOINTS) \
ENUM_GL_ENTRYPOINTS_OPTIONAL(DEFINE_GL_ENTRYPOINTS)
///////////////////////////////////////////////////////////////////////////////
bool FAndroidESDeferredOpenGL::bSupportsBindlessTexture = false;
void FAndroidESDeferredOpenGL::ProcessExtensions(const FString& ExtensionsString)
{
FOpenGLESDeferred::ProcessExtensions(ExtensionsString);
bSupportsBindlessTexture = ExtensionsString.Contains(TEXT("GL_NV_bindless_texture"));
// Nexus 9 running Android < 6.0 runs slow with NvTimerQuery so disable it
if (FAndroidMisc::GetDeviceModel() == FString(TEXT("Nexus 9")))
{
TArray<FString> VersionParts;
FAndroidMisc::GetAndroidVersion().ParseIntoArray(VersionParts, TEXT("."), true);
if (VersionParts.Num() > 0 && FCString::Atoi(*VersionParts[0]) < 6)
{
UE_LOG(LogRHI, Log, TEXT("Disabling support for NvTimerQuery on Nexus 9 before Android 6.0"));
bSupportsNvTimerQuery = false;
}
}
}
///////////////////////////////////////////////////////////////////////////////
// OpenGL platform functions
class FScopeContext
{
public:
FScopeContext(FPlatformOpenGLContext* PlatformContext)
{
check(PlatformContext);
LastContext = eglGetCurrentContext();
LastSurface = eglGetCurrentSurface(EGL_DRAW);
bSameContextAndSurface = (LastContext == PlatformContext->eglContext) && (LastSurface == PlatformContext->eglSurface);
if (!bSameContextAndSurface)
{
eglMakeCurrent(AndroidEGL::GetInstance()->GetDisplay(), PlatformContext->eglSurface, PlatformContext->eglSurface, PlatformContext->eglContext);
}
}
~FScopeContext( void )
{
if (!bSameContextAndSurface)
{
if (LastContext)
{
eglMakeCurrent(AndroidEGL::GetInstance()->GetDisplay(), LastSurface, LastSurface, LastContext);
}
else
{
eglMakeCurrent(AndroidEGL::GetInstance()->GetDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
}
}
private:
EGLContext LastContext;
EGLSurface LastSurface;
bool bSameContextAndSurface;
};
/**
* Enable/Disable debug context from the commandline
*/
static bool PlatformOpenGLDebugCtx()
{
#if UE_BUILD_DEBUG
return ! FParse::Param(FCommandLine::Get(),TEXT("openglNoDebug"));
#else
return FParse::Param(FCommandLine::Get(),TEXT("openglDebug"));;
#endif
}
struct FPlatformOpenGLDevice
{
void SetCurrentSharedContext();
void SetCurrentRenderingContext();
void SetCurrentNULLContext();
FPlatformOpenGLDevice();
~FPlatformOpenGLDevice();
void Init();
void LoadEXT();
void Terminate();
void ReInit();
};
FPlatformOpenGLDevice::FPlatformOpenGLDevice()
{
}
FPlatformOpenGLDevice::~FPlatformOpenGLDevice()
{
AndroidEGL::GetInstance()->DestroyBackBuffer();
AndroidEGL::GetInstance()->Terminate();
}
void FPlatformOpenGLDevice::Init()
{
UE_LOG( LogRHI, Warning, TEXT("Entering FPlatformOpenGLDevice::Init"));
extern void InitDebugContext();
AndroidEGL::GetInstance()->InitSurface(false, true);
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;
}
// For MSAA
glFramebufferTexture2DMultisampleEXT = (PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)((void*)eglGetProcAddress("glFramebufferTexture2DMultisampleEXT"));
glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)((void*)eglGetProcAddress("glRenderbufferStorageMultisampleEXT"));
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 FPlatformOpenGLDevice::SetCurrentSharedContext()
{
AndroidEGL::GetInstance()->SetCurrentSharedContext();
}
void FPlatformOpenGLDevice::SetCurrentRenderingContext()
{
AndroidEGL::GetInstance()->SetCurrentRenderingContext();
}
FPlatformOpenGLDevice* PlatformCreateOpenGLDevice()
{
FPlatformOpenGLDevice* Device = new FPlatformOpenGLDevice();
Device->Init();
return Device;
}
bool PlatformCanEnableGPUCapture()
{
return false;
}
void PlatformDestroyOpenGLDevice(FPlatformOpenGLDevice* Device)
{
delete Device;
}
FPlatformOpenGLContext* PlatformCreateOpenGLContext(FPlatformOpenGLDevice* Device, void* InWindowHandle)
{
//Assumes Device is already initialized and context already created.
return AndroidEGL::GetInstance()->GetRenderingContext();
}
void PlatformReleaseOpenGLContext(FPlatformOpenGLDevice* Device, FPlatformOpenGLContext* PlatformContext)
{
// nothing to do for now
}
void* PlatformGetWindow(FPlatformOpenGLContext* Context, void** AddParam)
{
check(Context);
return (void*)&Context->eglContext;
}
void PlatformDestroyOpenGLContext(FPlatformOpenGLDevice* Device, FPlatformOpenGLContext* PlatformContext)
{
delete Device; //created here, destroyed here, but held by RHI.
}
bool PlatformBlitToViewport( FPlatformOpenGLDevice* Device, const FOpenGLViewport& Viewport, uint32 BackbufferSizeX, uint32 BackbufferSizeY, bool bPresent,bool bLockToVsync, int32 SyncInterval )
{
if (FOpenGL::IsES2())
{
AndroidEGL::GetInstance()->SwapBuffers();
}
else
{
FPlatformOpenGLContext* const Context = Viewport.GetGLContext();
check(Context && Context->eglContext );
FScopeContext ScopeContext(Context);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//Disabling for now to work around a GL_INVALID_OPERATION which might or might not be legit in the context of EGL.
//Note that the drawbuffer state is part of the FBO state, so we don't need to touch it per frame.
//glDrawBuffer(GL_BACK);
glBindFramebuffer(GL_READ_FRAMEBUFFER, Context->ViewportFramebuffer);
glReadBuffer(GL_COLOR_ATTACHMENT0);
//LOGD("PlatformBlitToViewport: backbuffer (%d, %d) to screen (%d, %d)", BackbufferSizeX, BackbufferSizeY, GRealScreenWidth, GRealScreenHeight);
uint32 GRealScreenHeight, GRealScreenWidth;
AndroidEGL::GetInstance()->GetDimensions( GRealScreenWidth, GRealScreenHeight);
glBlitFramebuffer(
0, 0, BackbufferSizeX, BackbufferSizeY,
0, GRealScreenHeight, GRealScreenWidth, 0,
GL_COLOR_BUFFER_BIT,
GL_LINEAR
);
if (bPresent)
{
uint32 IdleStart = FPlatformTime::Cycles();
AndroidEGL::GetInstance()->SwapBuffers();
REPORT_GL_END_BUFFER_EVENT_FOR_FRAME_DUMP();
// INITIATE_GL_FRAME_DUMP_EVERY_X_CALLS( 1000 );
GRenderThreadIdle[ERenderThreadIdleTypes::WaitingForGPUPresent] += FPlatformTime::Cycles() - IdleStart;
GRenderThreadNumIdle[ERenderThreadIdleTypes::WaitingForGPUPresent]++;
}
}
// return true;
//Do not want WaitForFrameEventCompletion
return false;
}
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()
{
}
FRHITexture* PlatformCreateBuiltinBackBuffer(FOpenGLDynamicRHI* OpenGLRHI, uint32 SizeX, uint32 SizeY)
{
FOpenGLTexture2D* Texture2D = NULL;
if ( FOpenGL::IsES2())
{
uint32 Flags = TexCreate_RenderTargetable;
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);
FScopeContext ScopeContext(Context);
if (FOpenGL::IsES2())
{
glViewport(0, 0, SizeX, SizeY);
VERIFY_GL(glViewport);
}
else
{
if (Context->ViewportFramebuffer == 0)
{
glGenFramebuffers(1, &Context->ViewportFramebuffer);
}
glBindFramebuffer(GL_FRAMEBUFFER, Context->ViewportFramebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, BackBufferTarget, BackBufferResource, 0);
#if UE_BUILD_DEBUG
glReadBuffer(GL_COLOR_ATTACHMENT0);
FOpenGL::DrawBuffer(GL_COLOR_ATTACHMENT0);
GLenum CompleteResult = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (CompleteResult != GL_FRAMEBUFFER_COMPLETE)
{
UE_LOG(LogRHI, Fatal, TEXT("PlatformResizeGLContext: Framebuffer not complete. Status = 0x%x"), CompleteResult);
}
#endif
glViewport(0, 0, SizeX, SizeY);
static GLfloat ZeroColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
glClearBufferfv(GL_COLOR, 0, ZeroColor);
}
}
void PlatformGetSupportedResolution(uint32 &Width, uint32 &Height)
{
}
bool PlatformGetAvailableResolutions(FScreenResolutionArray& Resolutions, bool bIgnoreRefreshRate)
{
return true;
}
bool PlatformInitOpenGL()
{
// Original location for querying function entrypoints
return true;
}
bool PlatformOpenGLContextValid()
{
return (eglGetCurrentContext() != EGL_NO_CONTEXT);
}
int32 PlatformGlGetError()
{
return glGetError();
}
void PlatformGetBackbufferDimensions( uint32& OutWidth, uint32& OutHeight )
{
AndroidEGL::GetInstance()->GetDimensions(OutWidth, OutHeight);
}
// =============================================================
/* Query management
* Queries can be per context, depending on the extension / version used
* This code attempts to be safe about it. The ES2 version of Android
* is #if 0 below
*/
// ES2 FALLBACK HACK
#if 0
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 PlatformContextIsCurrent( uint64 QueryContext )
{
return true;
}
#else
struct FOpenGLReleasedQuery
{
EGLContext Context;
GLuint Query;
};
static TArray<FOpenGLReleasedQuery> ReleasedQueries;
static FCriticalSection* ReleasedQueriesGuard;
void PlatformGetNewRenderQuery(GLuint* OutQuery, uint64* OutQueryContext)
{
if (!ReleasedQueriesGuard)
{
ReleasedQueriesGuard = new FCriticalSection;
}
{
FScopeLock Lock(ReleasedQueriesGuard);
#ifdef UE_BUILD_DEBUG
check(OutQuery && OutQueryContext);
#endif
EGLContext Context = eglGetCurrentContext();
check(Context);
GLuint NewQuery = 0;
/*
* Note, not reusing queries, because timestamp and occlusion are different
*/
if (!NewQuery)
{
FOpenGL::GenQueries(1, &NewQuery);
}
*OutQuery = NewQuery;
*OutQueryContext = (uint64)Context;
}
}
void PlatformReleaseRenderQuery(GLuint Query, uint64 QueryContext)
{
EGLContext Context = eglGetCurrentContext();
if ((uint64)Context == QueryContext)
{
FOpenGL::DeleteQueries(1, &Query);
}
else
{
FScopeLock Lock(ReleasedQueriesGuard);
#ifdef UE_BUILD_DEBUG
check(Query && QueryContext && ReleasedQueriesGuard);
#endif
FOpenGLReleasedQuery ReleasedQuery;
ReleasedQuery.Context = (EGLContext)QueryContext;
ReleasedQuery.Query = Query;
ReleasedQueries.Add(ReleasedQuery);
}
}
void DeleteOcclusionQueriesForCurrentContext(EGLContext Context)
{
if (!ReleasedQueriesGuard)
{
ReleasedQueriesGuard = new FCriticalSection;
}
{
FScopeLock Lock(ReleasedQueriesGuard);
for (int32 Index = 0; Index < ReleasedQueries.Num(); ++Index)
{
if (ReleasedQueries[Index].Context == Context)
{
FOpenGL::DeleteQueries(1, &ReleasedQueries[Index].Query);
ReleasedQueries.RemoveAtSwap(Index);
--Index;
}
}
}
}
bool PlatformContextIsCurrent( uint64 QueryContext )
{
return (uint64)eglGetCurrentContext() == QueryContext;
}
#endif
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()
{
const bool Debug = PlatformOpenGLDebugCtx();
// @todo vulkan: Yet another bit of FAndroidApp stuff that's in GL - and should be cleaned up if possible
if (!FAndroidMisc::ShouldUseVulkan())
{
//AndroidEGL::GetInstance()->Init(AndroidEGL::AV_OpenGLES, 3, 1, Debug);
AndroidEGL::GetInstance()->Init(AndroidEGL::AV_OpenGLES, 2, 0, Debug);
}
}
void FAndroidAppEntry::ReleaseEGL()
{
AndroidEGL* EGL = AndroidEGL::GetInstance();
if (EGL->IsInitialized())
{
EGL->DestroyBackBuffer();
EGL->Terminate();
}
}
#endif