AndroidTextureCreator.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /**
  2. * Copyright (c) 2021 Vuplex Inc. All rights reserved.
  3. *
  4. * Licensed under the Vuplex Commercial Software Library License, you may
  5. * not use this file except in compliance with the License. You may obtain
  6. * a copy of the License at
  7. *
  8. * https://vuplex.com/commercial-library-license
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #if UNITY_ANDROID && !UNITY_EDITOR
  17. using System;
  18. using System.Collections;
  19. using System.Collections.Generic;
  20. using System.Linq;
  21. using System.Runtime.InteropServices;
  22. using UnityEngine;
  23. using UnityEngine.Rendering;
  24. namespace Vuplex.WebView {
  25. struct TextureCreatorInvocation {
  26. public int id;
  27. public int nativeWidth;
  28. public int nativeHeight;
  29. public Action<Texture2D> callback;
  30. }
  31. public class AndroidTextureCreator : MonoBehaviour {
  32. public static AndroidTextureCreator Instance {
  33. get {
  34. if (!_instance) {
  35. _instance = (AndroidTextureCreator) new GameObject("AndroidTextureCreator").AddComponent<AndroidTextureCreator>();
  36. DontDestroyOnLoad(_instance.gameObject);
  37. }
  38. return _instance;
  39. }
  40. }
  41. public void CreateTexture(float width, float height, Action<Texture2D> callback) {
  42. var error = Utils.GetGraphicsApiErrorMessage(SystemInfo.graphicsDeviceType, new GraphicsDeviceType[] { GraphicsDeviceType.OpenGLES3, GraphicsDeviceType.OpenGLES2 });
  43. if (error != null) {
  44. throw new SettingsException(error);
  45. }
  46. // Textures must be created on the render thread, so we send the arguments to the
  47. // native code, which queues the invocation so that the texture can be created on
  48. // the next render pass.
  49. var invocation = new TextureCreatorInvocation {
  50. // Just use the first 8 bytes of the guid to fit into a uint32
  51. id = int.Parse(Guid.NewGuid().ToString().Split(new char[] {'-'})[0], System.Globalization.NumberStyles.HexNumber),
  52. nativeWidth = _convertUnityUnitsToPixels(width),
  53. nativeHeight = _convertUnityUnitsToPixels(height),
  54. callback = callback
  55. };
  56. _pendingInvocations.Add(invocation);
  57. _invocationIdsToTrigger.Add(invocation.id);
  58. WebView_addCreateTextureInvocation(invocation.id, invocation.nativeWidth, invocation.nativeHeight);
  59. }
  60. static AndroidTextureCreator _instance;
  61. List<int> _invocationIdsToTrigger = new List<int>();
  62. List<TextureCreatorInvocation> _pendingInvocations = new List<TextureCreatorInvocation>();
  63. readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame();
  64. IEnumerator _callPluginOncePerFrame() {
  65. while (true) {
  66. yield return _waitForEndOfFrame;
  67. if (_invocationIdsToTrigger.Count > 0) {
  68. foreach (var invocationId in _invocationIdsToTrigger) {
  69. GL.IssuePluginEvent(WebView_getCreateTextureFunction(), invocationId);
  70. }
  71. _invocationIdsToTrigger.Clear();
  72. }
  73. }
  74. }
  75. int _convertUnityUnitsToPixels(float unityUnits) {
  76. return (int)(unityUnits * Config.NumberOfPixelsPerUnityUnit);
  77. }
  78. /// <summary>
  79. /// The native plugin invokes this method.
  80. /// </summary>
  81. void HandleTextureCreated(string parameterString) {
  82. var parameters = parameterString.Split(new char[]{';'});
  83. var invocationId = int.Parse(parameters[0]);
  84. var nativeTexture = new IntPtr(int.Parse(parameters[1]));
  85. var invocation = _pendingInvocations.Find(i => i.id == invocationId);
  86. _pendingInvocations.Remove(invocation);
  87. Texture2D texture = Texture2D.CreateExternalTexture(
  88. invocation.nativeWidth,
  89. invocation.nativeHeight,
  90. TextureFormat.RGBA32,
  91. false,
  92. false,
  93. nativeTexture
  94. );
  95. invocation.callback(texture);
  96. }
  97. void Start() {
  98. StartCoroutine(_callPluginOncePerFrame());
  99. }
  100. [DllImport("VuplexWebViewAndroid")]
  101. static extern void WebView_addCreateTextureInvocation(int invocationId, int width, int height);
  102. [DllImport("VuplexWebViewAndroid")]
  103. static extern IntPtr WebView_getCreateTextureFunction();
  104. }
  105. }
  106. #endif