VXAndroidUtils.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // Copyright (c) 2022 Vuplex Inc. All rights reserved.
  2. //
  3. // Licensed under the Vuplex Commercial Software Library License, you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at
  6. //
  7. // https://vuplex.com/commercial-library-license
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #if UNITY_ANDROID && !UNITY_EDITOR
  15. using System;
  16. using System.Collections.Generic;
  17. using System.Reflection;
  18. using UnityEngine;
  19. using UnityEngine.Rendering;
  20. namespace Vuplex.WebView.Internal {
  21. /// <summary>
  22. /// Static utility methods used internally by 3D WebView on Android.
  23. /// </summary>
  24. public static class VXAndroidUtils {
  25. public static Material CreateAndroidMaterial() {
  26. if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Vulkan) {
  27. return VXUtils.CreateDefaultMaterial();
  28. }
  29. var singlePassStereoRenderingEnabled = false;
  30. // For some headsets like HTC Vive Focus, XRSettings.eyeTextureDesc.vrUsage returns a value
  31. // other than VRTextureUsage.TwoEyes, so the VUPLEX_FORCE_SINGLE_PASS scripting symbol can be
  32. // used to force single pass in that scenario.
  33. #if VUPLEX_FORCE_SINGLE_PASS
  34. singlePassStereoRenderingEnabled = VXUtils.XRSettings.enabled;
  35. #elif UNITY_2017_2_OR_NEWER
  36. singlePassStereoRenderingEnabled = VXUtils.XRSettings.enabled && VXUtils.XRSettings.eyeTextureDesc.vrUsage == VRTextureUsage.TwoEyes;
  37. #endif
  38. var materialName = singlePassStereoRenderingEnabled ? "AndroidSinglePassViewportMaterial"
  39. : "AndroidViewportMaterial";
  40. // Construct a new material because Resources.Load<T>() returns a singleton.
  41. return new Material(Resources.Load<Material>(materialName));
  42. }
  43. public static byte[] ConvertFromJavaByteArray(AndroidJavaObject arrayObject) {
  44. // Unity 2019.1 and newer logs a warning that converting from byte[] is obsolete
  45. // but older versions are incapable of converting from sbyte[].
  46. #if UNITY_2019_1_OR_NEWER
  47. return (byte[])(Array)AndroidJNIHelper.ConvertFromJNIArray<sbyte[]>(arrayObject.GetRawObject());
  48. #else
  49. return AndroidJNIHelper.ConvertFromJNIArray<byte[]>(arrayObject.GetRawObject());
  50. #endif
  51. }
  52. public static void ThrowVulkanExtensionException() {
  53. throw new InvalidOperationException("The Vulkan Graphics API is in use, but this device does not support the VK_ANDROID_external_memory_android_hardware_buffer Vulkan API required by 3D WebView. Please switch to the OpenGLES Graphics API in Player Settings. For more info, see this page: https://support.vuplex.com/articles/vulkan");
  54. }
  55. public static AndroidJavaObject ToJavaMap(Dictionary<string, string> dictionary) {
  56. AndroidJavaObject map = new AndroidJavaObject("java.util.HashMap");
  57. IntPtr putMethod = AndroidJNIHelper.GetMethodID(map.GetRawClass(), "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
  58. foreach (var entry in dictionary) {
  59. AndroidJNI.CallObjectMethod(
  60. map.GetRawObject(),
  61. putMethod,
  62. AndroidJNIHelper.CreateJNIArgArray(new object[] { entry.Key, entry.Value })
  63. );
  64. }
  65. return map;
  66. }
  67. public static AndroidJavaObject ToJavaObject(IntPtr jobject) {
  68. if (jobject == IntPtr.Zero) {
  69. return null;
  70. }
  71. return (AndroidJavaObject)_androidJavaObjectIntPtrConstructor.Invoke(new object[] { jobject });
  72. }
  73. // Get a reference to AndroidJavaObject's hidden constructor that takes
  74. // the IntPtr for a jobject as a parameter.
  75. readonly static ConstructorInfo _androidJavaObjectIntPtrConstructor = typeof(AndroidJavaObject).GetConstructor(
  76. BindingFlags.Instance | BindingFlags.NonPublic,
  77. null,
  78. new []{ typeof(IntPtr) },
  79. null
  80. );
  81. }
  82. }
  83. #endif