You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user