Merging //UE4/Dev-Main @ 4356719 to Dev-Core (//UE4/Dev-Core)

#rb none

[CL 4357040 by Robert Manuszewski in Dev-Core branch]
This commit is contained in:
Robert Manuszewski
2018-09-11 02:45:29 -04:00
parent 04c4f83f28
commit ec82e184bd
183 changed files with 6437 additions and 2566 deletions

View File

@@ -25,6 +25,12 @@
#include "Interfaces/IAndroidDeviceDetectionModule.h"
#include "ITcpMessagingModule.h"
#include "PIEPreviewDeviceSpecification.h"
#include "JsonObjectConverter.h"
#include "Dom/JsonObject.h"
#include "Misc/FileHelper.h"
#include "Misc/MessageDialog.h"
#define LOCTEXT_NAMESPACE "FAndroidDeviceDetectionModule"
DEFINE_LOG_CATEGORY_STATIC(AndroidDeviceDetectionLog, Log, All);
@@ -128,6 +134,99 @@ private:
return true;
}
// searches for 'DPIString' and
int32 ExtractDPI(const FString& SurfaceFlingerOutput, const FString& DPIString)
{
int32 FoundDpi = INDEX_NONE;
int32 DpiIndex = SurfaceFlingerOutput.Find(DPIString);
if (DpiIndex != INDEX_NONE)
{
int32 StartIndex = INDEX_NONE;
for (int32 i = DpiIndex; i < SurfaceFlingerOutput.Len(); ++i)
{
// if we somehow hit a line break character something went wrong and no digits were found on this line
// we don't want to search the SurfaceFlinger feed so exit now
if (FChar::IsLinebreak(SurfaceFlingerOutput[i]))
{
break;
}
// search for the first digit aka the beginning of the DPI value
if (StartIndex == INDEX_NONE && FChar::IsDigit(SurfaceFlingerOutput[i]))
{
StartIndex = i;
}
// if we hit some non-numeric character extract the number and exit
else if (StartIndex != INDEX_NONE && !FChar::IsDigit(SurfaceFlingerOutput[i]))
{
FString str = SurfaceFlingerOutput.Mid(StartIndex, i - StartIndex);
FoundDpi = FCString::Atoi(*str);
break;
}
}
}
return FoundDpi;
}
// retrieve the string between 'InOutStartIndex' and the start position of the next 'Token' substring
// the white spaces of the resulting string are trimmed out at both ends
FString ExtractNextToken(int32& InOutStartIndex, const FString& SurfaceFlingerOutput, const FString& Token)
{
FString OutString;
int32 StartIndex = InOutStartIndex;
int32 EndIndex = SurfaceFlingerOutput.Find(Token, ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex);
if (EndIndex != INDEX_NONE)
{
InOutStartIndex = EndIndex + 1;
// the index should point to the position before the token start
--EndIndex;
for (int32 i = StartIndex; i < EndIndex; ++i)
{
if (!FChar::IsWhitespace(SurfaceFlingerOutput[i]))
{
StartIndex = i;
break;
}
}
for (int32 i = EndIndex; i > StartIndex; --i)
{
if (!FChar::IsWhitespace(SurfaceFlingerOutput[i]))
{
EndIndex = i;
break;
}
}
OutString = SurfaceFlingerOutput.Mid(StartIndex, FMath::Max(0, EndIndex - StartIndex + 1));
}
return OutString;
}
void ExtractGPUInfo(FString& outGLVersion, FString& outGPUFamily, const FString& SurfaceFlingerOutput)
{
int32 FoundDpi = INDEX_NONE;
int32 LineIndex = SurfaceFlingerOutput.Find(TEXT("GLES:"));
if (LineIndex != INDEX_NONE)
{
int32 StartIndex = SurfaceFlingerOutput.Find(TEXT(":"), ESearchCase::IgnoreCase, ESearchDir::FromStart, LineIndex);
if (StartIndex != INDEX_NONE)
{
++StartIndex;
FString GPUVendorString = ExtractNextToken(StartIndex, SurfaceFlingerOutput, TEXT(","));
outGPUFamily = ExtractNextToken(StartIndex, SurfaceFlingerOutput, TEXT(","));
outGLVersion = ExtractNextToken(StartIndex, SurfaceFlingerOutput, TEXT("\n"));
}
}
}
void QueryConnectedDevices()
{
// grab the list of devices via adb
@@ -241,6 +340,62 @@ private:
{
continue;
}
// extract DPI information
int32 XDpi = ExtractDPI(NewDeviceInfo.GLESExtensions, TEXT("x-dpi"));
int32 YDpi = ExtractDPI(NewDeviceInfo.GLESExtensions, TEXT("y-dpi"));
if (XDpi != INDEX_NONE && YDpi != INDEX_NONE)
{
NewDeviceInfo.DeviceDPI = (XDpi + YDpi) / 2;
}
// extract OpenGL version and GPU family name
ExtractGPUInfo(NewDeviceInfo.OpenGLVersionString, NewDeviceInfo.GPUFamilyString, NewDeviceInfo.GLESExtensions);
}
// grab device brand
{
FString ExecCommand = FString::Printf(TEXT("-s %s %s ro.product.brand"), *NewDeviceInfo.SerialNumber, *GetPropCommand);
FString RoProductBrand;
ExecuteAdbCommand(*ExecCommand, &RoProductBrand, nullptr);
const TCHAR* Ptr = *RoProductBrand;
FParse::Line(&Ptr, NewDeviceInfo.DeviceBrand);
}
// grab screen resolution
{
FString ResolutionString;
const FString ExecCommand = FString::Printf(TEXT("-s %s shell wm size"), *NewDeviceInfo.SerialNumber);
if (ExecuteAdbCommand(*ExecCommand, &ResolutionString, nullptr))
{
bool bFoundResX = false;
int32 StartIndex = INDEX_NONE;
for (int32 Index = 0; Index < ResolutionString.Len(); ++Index)
{
if (StartIndex == INDEX_NONE && FChar::IsDigit(ResolutionString[Index]))
{
StartIndex = Index;
}
else if (StartIndex != INDEX_NONE && !FChar::IsDigit(ResolutionString[Index]))
{
FString str = ResolutionString.Mid(StartIndex, Index - StartIndex);
if (bFoundResX)
{
NewDeviceInfo.ResolutionY = FCString::Atoi(*str);
break;
}
else
{
NewDeviceInfo.ResolutionX = FCString::Atoi(*str);
bFoundResX = true;
StartIndex = INDEX_NONE;
}
}
}
}
}
// grab the GL ES version
@@ -494,6 +649,89 @@ public:
DetectionThreadRunnable->UpdateADBPath(ADBPath, GetPropCommand, bGetExtensionsViaSurfaceFlinger, bForLumin);
}
virtual void ExportDeviceProfile(const FString& OutPath, const FString& DeviceName) override
{
// instantiate an FPIEPreviewDeviceSpecifications instance and its values
FPIEPreviewDeviceSpecifications DeviceSpecs;
bool bOpenGL3x = false;
{
FScopeLock ExportLock(GetDeviceMapLock());
const FAndroidDeviceInfo* DeviceInfo = GetDeviceMap().Find(DeviceName);
if (DeviceInfo == nullptr)
{
FText TitleMessage = LOCTEXT("loc_ExportError_Title", "File export error.");
FMessageDialog::Open(EAppMsgType::Ok, EAppReturnType::Ok, LOCTEXT("loc_ExportError_Message", "Device disconnected!"), &TitleMessage);
return;
}
// generic values
DeviceSpecs.DevicePlatform = EPIEPreviewDeviceType::Android;
DeviceSpecs.ResolutionX = DeviceInfo->ResolutionX;
DeviceSpecs.ResolutionY = DeviceInfo->ResolutionY;
DeviceSpecs.ResolutionYImmersiveMode = 0;
DeviceSpecs.PPI = DeviceInfo->DeviceDPI;
DeviceSpecs.ScaleFactors = { 0.25f, 0.5f, 0.75f, 1.0f };
// Android specific values
DeviceSpecs.AndroidProperties.AndroidVersion = DeviceInfo->HumanAndroidVersion;
DeviceSpecs.AndroidProperties.DeviceModel = DeviceInfo->Model;
DeviceSpecs.AndroidProperties.DeviceMake = DeviceInfo->DeviceBrand;
DeviceSpecs.AndroidProperties.GLVersion = DeviceInfo->OpenGLVersionString;
DeviceSpecs.AndroidProperties.GPUFamily = DeviceInfo->GPUFamilyString;
DeviceSpecs.AndroidProperties.VulkanVersion = "0.0.0";
DeviceSpecs.AndroidProperties.UsingHoudini = false;
DeviceSpecs.AndroidProperties.VulkanAvailable = false;
// OpenGL ES 3.x
bOpenGL3x = DeviceInfo->OpenGLVersionString.Contains(TEXT("OpenGL ES 3"));
if (bOpenGL3x)
{
DeviceSpecs.AndroidProperties.GLES31RHIState.SupportsInstancing = true;
DeviceSpecs.AndroidProperties.GLES31RHIState.MaxTextureDimensions = 2048;
DeviceSpecs.AndroidProperties.GLES31RHIState.MaxShadowDepthBufferSizeX = 2048;
DeviceSpecs.AndroidProperties.GLES31RHIState.MaxShadowDepthBufferSizeY = 2048;
DeviceSpecs.AndroidProperties.GLES31RHIState.MaxCubeTextureDimensions = 2048;
DeviceSpecs.AndroidProperties.GLES31RHIState.SupportsRenderTargetFormat_PF_G8 = true;
DeviceSpecs.AndroidProperties.GLES31RHIState.SupportsRenderTargetFormat_PF_FloatRGBA = DeviceInfo->GLESExtensions.Contains(TEXT("GL_EXT_color_buffer_half_float"));
DeviceSpecs.AndroidProperties.GLES31RHIState.SupportsMultipleRenderTargets = true;
}
// OpenGL ES 2.0
{
DeviceSpecs.AndroidProperties.GLES2RHIState.SupportsInstancing = false;
DeviceSpecs.AndroidProperties.GLES2RHIState.MaxTextureDimensions = 1024;
DeviceSpecs.AndroidProperties.GLES2RHIState.MaxShadowDepthBufferSizeX = 1024;
DeviceSpecs.AndroidProperties.GLES2RHIState.MaxShadowDepthBufferSizeY = 1024;
DeviceSpecs.AndroidProperties.GLES2RHIState.MaxCubeTextureDimensions = 512;
DeviceSpecs.AndroidProperties.GLES2RHIState.SupportsRenderTargetFormat_PF_G8 = true;
DeviceSpecs.AndroidProperties.GLES2RHIState.SupportsRenderTargetFormat_PF_FloatRGBA = DeviceInfo->GLESExtensions.Contains(TEXT("GL_EXT_color_buffer_half_float"));
DeviceSpecs.AndroidProperties.GLES2RHIState.SupportsMultipleRenderTargets = false;
}
} // FScopeLock ExportLock released
// create a JSon object from the above structure
TSharedPtr<FJsonObject> JsonObject = FJsonObjectConverter::UStructToJsonObject<FPIEPreviewDeviceSpecifications>(DeviceSpecs);
// if device does not support OpenGL 3.x avoid exporting anything about it
if (!bOpenGL3x)
{
JsonObject->RemoveField("GLES31RHIState");
}
// remove IOS fields
JsonObject->RemoveField("IOSProperties");
// serialize the JSon object to string
FString OutputString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutputString);
FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);
// export file to disk
FFileHelper::SaveStringToFile(OutputString, *OutPath);
} // end of virtual void ExportDeviceProfile(...)
private:
// path to the adb command (local)