VideoRender.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_TVOS
  2. #define UNITY_PLATFORM_SUPPORTS_YPCBCR
  3. #endif
  4. #if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_IOS || UNITY_TVOS || UNITY_ANDROID || (UNITY_WEBGL && UNITY_2017_2_OR_NEWER)
  5. #define UNITY_PLATFORM_SUPPORTS_LINEAR
  6. #endif
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10. using UnityEngine.Rendering;
  11. //-----------------------------------------------------------------------------
  12. // Copyright 2015-2022 RenderHeads Ltd. All rights reserved.
  13. //-----------------------------------------------------------------------------
  14. namespace RenderHeads.Media.AVProVideo
  15. {
  16. #if AVPRO_FEATURE_VIDEORESOLVE
  17. [System.Serializable]
  18. public class VideoResolve : ITextureProducer
  19. {
  20. [SerializeField] VideoResolveOptions _options = VideoResolveOptions.Create();
  21. [SerializeField] RenderTexture _targetRenderTexture = null;
  22. [SerializeField] ScaleMode _targetRenderTextureScale = ScaleMode.ScaleToFit;
  23. void SetSource(ITextureProducer textureSource)
  24. {
  25. //_commandBuffer.IssuePluginEvent(blahCallback, 0);
  26. //Graphics.ExecuteCommandBuffer(_commandBuffer);
  27. }
  28. // ITextureProducer implementation
  29. /// <inheritdoc/>
  30. public int GetTextureCount() { return 1; }
  31. /// <inheritdoc/>
  32. public Texture GetTexture(int index = 0) { return _texture; }
  33. /// <inheritdoc/>
  34. public int GetTextureFrameCount() { return _textureSource.GetTextureFrameCount(); }
  35. /// <inheritdoc/>
  36. public bool SupportsTextureFrameCount() { return _textureSource.SupportsTextureFrameCount(); }
  37. /// <inheritdoc/>
  38. public long GetTextureTimeStamp() { return _textureSource.GetTextureTimeStamp(); }
  39. /// <inheritdoc/>
  40. public bool RequiresVerticalFlip() { return false; }
  41. /// <inheritdoc/>
  42. public StereoPacking GetTextureStereoPacking() { return StereoPacking.None; }
  43. /// <inheritdoc/>
  44. public TransparencyMode GetTextureTransparency() { return TransparencyMode.Transparent; }
  45. /// <inheritdoc/>
  46. public AlphaPacking GetTextureAlphaPacking() { return AlphaPacking.None; }
  47. /// <inheritdoc/>
  48. public Matrix4x4 GetYpCbCrTransform() { return Matrix4x4.identity; }
  49. private ITextureProducer _textureSource;
  50. private Texture _texture;
  51. private CommandBuffer _commandBuffer;
  52. }
  53. #endif
  54. public struct LazyShaderProperty
  55. {
  56. public LazyShaderProperty(string name)
  57. {
  58. _name = name;
  59. _id = 0;
  60. }
  61. public string Name { get { return _name;} }
  62. public int Id { get { if (_id == 0) { _id = Shader.PropertyToID(_name); } return _id; } }
  63. private string _name;
  64. private int _id;
  65. }
  66. /// <summary>Helper class for everything related to setting up materials for rendering/resolving videos</summary>
  67. public class VideoRender
  68. {
  69. public const string Shader_IMGUI = "AVProVideo/Internal/IMGUI/Texture Transparent";
  70. public const string Shader_Resolve = "AVProVideo/Internal/Resolve";
  71. public const string Shader_ResolveOES = "AVProVideo/Internal/ResolveOES";
  72. public const string Shader_Preview = "AVProVideo/Internal/Preview";
  73. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  74. public const string Keyword_UseYpCbCr = "USE_YPCBCR";
  75. #endif
  76. public const string Keyword_AlphaPackTopBottom = "ALPHAPACK_TOP_BOTTOM";
  77. public const string Keyword_AlphaPackLeftRight = "ALPHAPACK_LEFT_RIGHT";
  78. public const string Keyword_AlphaPackNone = "ALPHAPACK_NONE";
  79. public const string Keyword_StereoTopBottom = "STEREO_TOP_BOTTOM";
  80. public const string Keyword_StereoLeftRight = "STEREO_LEFT_RIGHT";
  81. public const string Keyword_StereoCustomUV = "STEREO_CUSTOM_UV";
  82. public const string Keyword_StereoTwoTextures = "STEREO_TWOTEXTURES";
  83. public const string Keyword_StereoNone = "MONOSCOPIC";
  84. public const string Keyword_StereoDebug = "STEREO_DEBUG";
  85. public const string Keyword_LayoutEquirect180 = "LAYOUT_EQUIRECT180";
  86. public const string Keyword_LayoutNone = "LAYOUT_NONE";
  87. public const string Keyword_ForceEyeNone = "FORCEEYE_NONE";
  88. public const string Keyword_ForceEyeLeft = "FORCEEYE_LEFT";
  89. public const string Keyword_ForceEyeRight = "FORCEEYE_RIGHT";
  90. public const string Keyword_ApplyGamma = "APPLY_GAMMA";
  91. public static readonly LazyShaderProperty PropChromaTex = new LazyShaderProperty("_ChromaTex");
  92. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  93. public static readonly LazyShaderProperty PropYpCbCrTransform = new LazyShaderProperty("_YpCbCrTransform");
  94. public static readonly LazyShaderProperty PropUseYpCbCr = new LazyShaderProperty("_UseYpCbCr");
  95. #endif
  96. public static readonly LazyShaderProperty PropVertScale = new LazyShaderProperty("_VertScale");
  97. public static readonly LazyShaderProperty PropApplyGamma = new LazyShaderProperty("_ApplyGamma");
  98. public static readonly LazyShaderProperty PropStereo = new LazyShaderProperty("Stereo");
  99. public static readonly LazyShaderProperty PropAlphaPack = new LazyShaderProperty("AlphaPack");
  100. public static readonly LazyShaderProperty PropLayout = new LazyShaderProperty("Layout");
  101. public static readonly LazyShaderProperty PropViewMatrix = new LazyShaderProperty("_ViewMatrix");
  102. public static readonly LazyShaderProperty PropTextureMatrix = new LazyShaderProperty("_TextureMatrix");
  103. public static string Keyword_UseHSBC = "USE_HSBC";
  104. public static readonly LazyShaderProperty PropHue = new LazyShaderProperty("_Hue");
  105. public static readonly LazyShaderProperty PropSaturation = new LazyShaderProperty("_Saturation");
  106. public static readonly LazyShaderProperty PropContrast = new LazyShaderProperty("_Contrast");
  107. public static readonly LazyShaderProperty PropBrightness = new LazyShaderProperty("_Brightness");
  108. public static readonly LazyShaderProperty PropInvGamma = new LazyShaderProperty("_InvGamma");
  109. public static Material CreateResolveMaterial(bool usingAndroidOES)
  110. {
  111. return new Material(Shader.Find( usingAndroidOES ? VideoRender.Shader_ResolveOES : VideoRender.Shader_Resolve ));
  112. }
  113. public static Material CreateIMGUIMaterial()
  114. {
  115. return new Material(Shader.Find(VideoRender.Shader_Preview));
  116. }
  117. public static void SetupLayoutMaterial(Material material, VideoMapping mapping)
  118. {
  119. switch (mapping)
  120. {
  121. default:
  122. material.DisableKeyword(Keyword_LayoutEquirect180);
  123. material.EnableKeyword(Keyword_LayoutNone);
  124. break;
  125. // Only EquiRectangular180 currently does anything in the shader
  126. case VideoMapping.EquiRectangular180:
  127. material.DisableKeyword(Keyword_LayoutNone);
  128. material.EnableKeyword(Keyword_LayoutEquirect180);
  129. break;
  130. }
  131. }
  132. public static void SetupStereoEyeModeMaterial(Material material, StereoEye mode)
  133. {
  134. switch (mode)
  135. {
  136. case StereoEye.Both:
  137. material.DisableKeyword(Keyword_ForceEyeLeft);
  138. material.DisableKeyword(Keyword_ForceEyeRight);
  139. material.EnableKeyword(Keyword_ForceEyeNone);
  140. break;
  141. case StereoEye.Left:
  142. material.DisableKeyword(Keyword_ForceEyeNone);
  143. material.DisableKeyword(Keyword_ForceEyeRight);
  144. material.EnableKeyword(Keyword_ForceEyeLeft);
  145. break;
  146. case StereoEye.Right:
  147. material.DisableKeyword(Keyword_ForceEyeNone);
  148. material.DisableKeyword(Keyword_ForceEyeLeft);
  149. material.EnableKeyword(Keyword_ForceEyeRight);
  150. break;
  151. }
  152. }
  153. public static void SetupStereoMaterial(Material material, StereoPacking packing)
  154. {
  155. switch (packing)
  156. {
  157. case StereoPacking.None:
  158. material.DisableKeyword(Keyword_StereoTopBottom);
  159. material.DisableKeyword(Keyword_StereoLeftRight);
  160. material.DisableKeyword(Keyword_StereoCustomUV);
  161. material.DisableKeyword(Keyword_StereoTwoTextures);
  162. material.EnableKeyword(Keyword_StereoNone);
  163. break;
  164. case StereoPacking.TopBottom:
  165. material.DisableKeyword(Keyword_StereoNone);
  166. material.DisableKeyword(Keyword_StereoLeftRight);
  167. material.DisableKeyword(Keyword_StereoCustomUV);
  168. material.DisableKeyword(Keyword_StereoTwoTextures);
  169. material.EnableKeyword(Keyword_StereoTopBottom);
  170. break;
  171. case StereoPacking.LeftRight:
  172. material.DisableKeyword(Keyword_StereoNone);
  173. material.DisableKeyword(Keyword_StereoTopBottom);
  174. material.DisableKeyword(Keyword_StereoTwoTextures);
  175. material.DisableKeyword(Keyword_StereoCustomUV);
  176. material.EnableKeyword(Keyword_StereoLeftRight);
  177. break;
  178. case StereoPacking.CustomUV:
  179. material.DisableKeyword(Keyword_StereoNone);
  180. material.DisableKeyword(Keyword_StereoTopBottom);
  181. material.DisableKeyword(Keyword_StereoLeftRight);
  182. material.DisableKeyword(Keyword_StereoTwoTextures);
  183. material.EnableKeyword(Keyword_StereoCustomUV);
  184. break;
  185. case StereoPacking.TwoTextures:
  186. material.DisableKeyword(Keyword_StereoNone);
  187. material.DisableKeyword(Keyword_StereoTopBottom);
  188. material.DisableKeyword(Keyword_StereoLeftRight);
  189. material.DisableKeyword(Keyword_StereoCustomUV);
  190. material.EnableKeyword(Keyword_StereoTwoTextures);
  191. break;
  192. }
  193. }
  194. public static void SetupGlobalDebugStereoTinting(bool enabled)
  195. {
  196. if (enabled)
  197. {
  198. Shader.EnableKeyword(Keyword_StereoDebug);
  199. }
  200. else
  201. {
  202. Shader.DisableKeyword(Keyword_StereoDebug);
  203. }
  204. }
  205. public static void SetupAlphaPackedMaterial(Material material, AlphaPacking packing)
  206. {
  207. switch (packing)
  208. {
  209. case AlphaPacking.None:
  210. material.DisableKeyword(Keyword_AlphaPackTopBottom);
  211. material.DisableKeyword(Keyword_AlphaPackLeftRight);
  212. material.EnableKeyword(Keyword_AlphaPackNone);
  213. break;
  214. case AlphaPacking.TopBottom:
  215. material.DisableKeyword(Keyword_AlphaPackNone);
  216. material.DisableKeyword(Keyword_AlphaPackLeftRight);
  217. material.EnableKeyword(Keyword_AlphaPackTopBottom);
  218. break;
  219. case AlphaPacking.LeftRight:
  220. material.DisableKeyword(Keyword_AlphaPackNone);
  221. material.DisableKeyword(Keyword_AlphaPackTopBottom);
  222. material.EnableKeyword(Keyword_AlphaPackLeftRight);
  223. break;
  224. }
  225. }
  226. public static void SetupGammaMaterial(Material material, bool playerSupportsLinear)
  227. {
  228. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  229. if (QualitySettings.activeColorSpace == ColorSpace.Linear && !playerSupportsLinear)
  230. {
  231. material.EnableKeyword(Keyword_ApplyGamma);
  232. }
  233. else
  234. {
  235. material.DisableKeyword(Keyword_ApplyGamma);
  236. }
  237. #endif
  238. }
  239. public static void SetupTextureMatrix(Material material, float[] transform)
  240. {
  241. #if (!UNITY_EDITOR && UNITY_ANDROID)
  242. // STE: HasProperty doesn't work on Matrix'
  243. // if (material != null && (material.HasProperty(VideoRender.PropTextureMatrix.Id)))
  244. {
  245. if (transform != null)
  246. {
  247. Matrix4x4 m = new Matrix4x4(new Vector4( transform[0], transform[1], transform[2], transform[3] ),
  248. new Vector4( transform[4], transform[5], transform[6], transform[7] ),
  249. new Vector4( transform[8], transform[9], transform[10], transform[11] ),
  250. new Vector4( transform[12], transform[13], transform[14], transform[15] ));
  251. material.SetMatrix(VideoRender.PropTextureMatrix.Id, m);
  252. }
  253. else
  254. {
  255. material.SetMatrix(VideoRender.PropTextureMatrix.Id, Matrix4x4.identity);
  256. }
  257. }
  258. #endif
  259. }
  260. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  261. public static void SetupYpCbCrMaterial(Material material, bool enable, Matrix4x4 transform, Texture texture)
  262. {
  263. if (material.HasProperty(VideoRender.PropUseYpCbCr.Id))
  264. {
  265. if (enable)
  266. {
  267. material.EnableKeyword(VideoRender.Keyword_UseYpCbCr);
  268. material.SetMatrix(VideoRender.PropYpCbCrTransform.Id, transform);
  269. material.SetTexture(VideoRender.PropChromaTex.Id, texture);
  270. }
  271. else
  272. {
  273. material.DisableKeyword(VideoRender.Keyword_UseYpCbCr);
  274. }
  275. }
  276. }
  277. #endif
  278. public static void SetupVerticalFlipMaterial(Material material, bool flip)
  279. {
  280. material.SetFloat(VideoRender.PropVertScale.Id, flip?-1f:1f);
  281. }
  282. public static Texture GetTexture(MediaPlayer mediaPlayer, int textureIndex)
  283. {
  284. Texture result = null;
  285. if (mediaPlayer != null)
  286. {
  287. if (mediaPlayer.UseResampler && mediaPlayer.FrameResampler != null && mediaPlayer.FrameResampler.OutputTexture != null)
  288. {
  289. if ( mediaPlayer.FrameResampler.OutputTexture.Length > textureIndex)
  290. {
  291. result = mediaPlayer.FrameResampler.OutputTexture[textureIndex];
  292. }
  293. }
  294. else if (mediaPlayer.TextureProducer != null)
  295. {
  296. if (mediaPlayer.TextureProducer.GetTextureCount() > textureIndex)
  297. {
  298. result = mediaPlayer.TextureProducer.GetTexture(textureIndex);
  299. }
  300. }
  301. }
  302. return result;
  303. }
  304. public static void SetupMaterialForMedia(Material material, MediaPlayer mediaPlayer, int texturePropId = -1, Texture fallbackTexture = null, bool forceFallbackTexture = false)
  305. {
  306. Debug.Assert(material != null);
  307. if (mediaPlayer != null)
  308. {
  309. Texture mainTexture = GetTexture(mediaPlayer, 0);
  310. Texture yCbCrTexture = GetTexture(mediaPlayer, 1);
  311. if (texturePropId != -1)
  312. {
  313. if (mainTexture == null || forceFallbackTexture)
  314. {
  315. mainTexture = fallbackTexture;
  316. }
  317. material.SetTexture(texturePropId, mainTexture);
  318. }
  319. SetupMaterial(material,
  320. (mediaPlayer.TextureProducer != null)?mediaPlayer.TextureProducer.RequiresVerticalFlip():false,
  321. (mediaPlayer.Info != null)?mediaPlayer.Info.PlayerSupportsLinearColorSpace():true,
  322. (mediaPlayer.TextureProducer != null)?mediaPlayer.TextureProducer.GetYpCbCrTransform():Matrix4x4.identity,
  323. yCbCrTexture,
  324. (mediaPlayer.Info != null && mediaPlayer.PlatformOptionsAndroid.useFastOesPath)?mediaPlayer.Info.GetTextureTransform():null,
  325. mediaPlayer.VideoLayoutMapping,
  326. (mediaPlayer.TextureProducer != null)?mediaPlayer.TextureProducer.GetTextureStereoPacking():StereoPacking.None,
  327. (mediaPlayer.TextureProducer != null)?mediaPlayer.TextureProducer.GetTextureAlphaPacking():AlphaPacking.None);
  328. }
  329. else
  330. {
  331. if (texturePropId != -1)
  332. {
  333. material.SetTexture(texturePropId, fallbackTexture);
  334. }
  335. SetupMaterial(material, false, true, Matrix4x4.identity, null);
  336. }
  337. }
  338. internal static void SetupMaterial(Material material, bool flipVertically, bool playerSupportsLinear, Matrix4x4 ycbcrTransform, Texture ycbcrTexture = null, float[] textureTransform = null,
  339. VideoMapping mapping = VideoMapping.Normal, StereoPacking stereoPacking = StereoPacking.None, AlphaPacking alphaPacking = AlphaPacking.None)
  340. {
  341. SetupVerticalFlipMaterial(material, flipVertically);
  342. // Apply changes for layout
  343. if (material.HasProperty(VideoRender.PropLayout.Id))
  344. {
  345. VideoRender.SetupLayoutMaterial(material, mapping);
  346. }
  347. // Apply changes for stereo videos
  348. if (material.HasProperty(VideoRender.PropStereo.Id))
  349. {
  350. VideoRender.SetupStereoMaterial(material, stereoPacking);
  351. }
  352. // Apply changes for alpha videos
  353. if (material.HasProperty(VideoRender.PropAlphaPack.Id))
  354. {
  355. VideoRender.SetupAlphaPackedMaterial(material, alphaPacking);
  356. }
  357. // Apply gamma correction
  358. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  359. if (material.HasProperty(VideoRender.PropApplyGamma.Id))
  360. {
  361. VideoRender.SetupGammaMaterial(material, playerSupportsLinear);
  362. }
  363. #endif
  364. // Adjust for cropping (when the decoder decodes in blocks that overrun the video frame size, it pads), OES only as we apply this lower down for none-OES
  365. #if (!UNITY_EDITOR && UNITY_ANDROID)
  366. // STE: HasProperty doesn't work on Matrix'
  367. // if (material.HasProperty(VideoRender.PropTextureMatrix.Id))
  368. {
  369. VideoRender.SetupTextureMatrix(material, textureTransform);
  370. }
  371. #endif
  372. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  373. VideoRender.SetupYpCbCrMaterial(material, ycbcrTexture != null, ycbcrTransform, ycbcrTexture);
  374. #endif
  375. }
  376. [System.Flags]
  377. public enum ResolveFlags : int
  378. {
  379. Mipmaps = 1 << 0,
  380. PackedAlpha = 1 << 1,
  381. StereoLeft = 1 << 2,
  382. StereoRight = 1 << 3,
  383. ColorspaceSRGB = 1 << 4,
  384. }
  385. public static void SetupResolveMaterial(Material material, VideoResolveOptions options)
  386. {
  387. if (options.IsColourAdjust())
  388. {
  389. material.EnableKeyword(VideoRender.Keyword_UseHSBC);
  390. material.SetFloat(VideoRender.PropHue.Id, options.hue);
  391. material.SetFloat(VideoRender.PropSaturation.Id, options.saturation);
  392. material.SetFloat(VideoRender.PropBrightness.Id, options.brightness);
  393. material.SetFloat(VideoRender.PropContrast.Id, options.contrast);
  394. material.SetFloat(VideoRender.PropInvGamma.Id, 1f / options.gamma);
  395. }
  396. else
  397. {
  398. material.DisableKeyword(VideoRender.Keyword_UseHSBC);
  399. }
  400. material.color = options.tint;
  401. }
  402. public static RenderTexture ResolveVideoToRenderTexture(Material resolveMaterial, RenderTexture targetTexture, ITextureProducer texture, ResolveFlags flags, ScaleMode scaleMode = ScaleMode.StretchToFill)
  403. {
  404. int targetWidth = texture.GetTexture(0).width;
  405. int targetHeight = texture.GetTexture(0).height;
  406. StereoEye eyeMode = StereoEye.Both;
  407. if (((flags & ResolveFlags.StereoLeft) == ResolveFlags.StereoLeft) &&
  408. ((flags & ResolveFlags.StereoRight) != ResolveFlags.StereoRight))
  409. {
  410. eyeMode = StereoEye.Left;
  411. }
  412. else if (((flags & ResolveFlags.StereoLeft) != ResolveFlags.StereoLeft) &&
  413. ((flags & ResolveFlags.StereoRight) == ResolveFlags.StereoRight))
  414. {
  415. eyeMode = StereoEye.Right;
  416. }
  417. // RJT NOTE: No longer passing in PAR as combined with larger videos (e.g. 8K+) it can lead to textures >16K which most platforms don't support
  418. // - Instead, the PAR is accounted for during drawing (which is more efficient too)
  419. // - https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1297
  420. GetResolveTextureSize(texture.GetTextureAlphaPacking(), texture.GetTextureStereoPacking(), eyeMode, /*texture.GetTexturePixelAspectRatio()*/1.0f, ref targetWidth, ref targetHeight);
  421. if (targetTexture)
  422. {
  423. bool sizeChanged = (targetTexture.width != targetWidth || targetTexture.height != targetHeight);
  424. if (sizeChanged)
  425. {
  426. RenderTexture.ReleaseTemporary(targetTexture); targetTexture = null;
  427. }
  428. }
  429. if (!targetTexture)
  430. {
  431. RenderTextureReadWrite readWrite = ((flags & ResolveFlags.ColorspaceSRGB) == ResolveFlags.ColorspaceSRGB) ? RenderTextureReadWrite.sRGB : RenderTextureReadWrite.Linear;
  432. targetTexture = RenderTexture.GetTemporary(targetWidth, targetHeight, 0, RenderTextureFormat.ARGB32, readWrite);
  433. }
  434. // Set target mipmap generation support
  435. {
  436. bool requiresMipmap = (flags & ResolveFlags.Mipmaps) == ResolveFlags.Mipmaps;
  437. bool requiresRecreate = (targetTexture.IsCreated() && targetTexture.useMipMap != requiresMipmap);
  438. if (requiresRecreate)
  439. {
  440. targetTexture.Release();
  441. }
  442. if (!targetTexture.IsCreated())
  443. {
  444. targetTexture.useMipMap = targetTexture.autoGenerateMips = requiresMipmap;
  445. targetTexture.Create();
  446. }
  447. }
  448. // Render resolve blit
  449. // TODO: combine these two paths into a single material blit
  450. {
  451. bool prevSRGB = GL.sRGBWrite;
  452. GL.sRGBWrite = targetTexture.sRGB;
  453. RenderTexture prev = RenderTexture.active;
  454. if (scaleMode == ScaleMode.StretchToFill)
  455. {
  456. Graphics.Blit(texture.GetTexture(0), targetTexture, resolveMaterial);
  457. }
  458. else
  459. {
  460. RenderTexture.active = targetTexture;
  461. bool partialAreaRender = (scaleMode == ScaleMode.ScaleToFit);
  462. if (partialAreaRender)
  463. {
  464. GL.Clear(false, true, Color.black);
  465. }
  466. VideoRender.DrawTexture(new Rect(0f, 0f, targetTexture.width, targetTexture.height), texture.GetTexture(0), scaleMode, texture.GetTextureAlphaPacking(), texture.GetTexturePixelAspectRatio(), resolveMaterial);
  467. }
  468. RenderTexture.active = prev;
  469. GL.sRGBWrite = prevSRGB;
  470. }
  471. return targetTexture;
  472. }
  473. public static void GetResolveTextureSize(AlphaPacking alphaPacking, StereoPacking stereoPacking, StereoEye eyeMode, float pixelAspectRatio, ref int width, ref int height)
  474. {
  475. switch (alphaPacking)
  476. {
  477. case AlphaPacking.LeftRight:
  478. width /= 2;
  479. break;
  480. case AlphaPacking.TopBottom:
  481. height /= 2;
  482. break;
  483. }
  484. if (eyeMode != StereoEye.Both)
  485. {
  486. switch (stereoPacking)
  487. {
  488. case StereoPacking.LeftRight:
  489. width /= 2;
  490. break;
  491. case StereoPacking.TopBottom:
  492. height /= 2;
  493. break;
  494. }
  495. }
  496. if (pixelAspectRatio > 0f)
  497. {
  498. if (pixelAspectRatio > 1f)
  499. {
  500. width = Mathf.RoundToInt(width * pixelAspectRatio);
  501. }
  502. else if (pixelAspectRatio < 1f)
  503. {
  504. height = Mathf.RoundToInt(height / pixelAspectRatio);
  505. }
  506. }
  507. // TODO: take into account rotation
  508. }
  509. public static bool RequiresResolve(ITextureProducer texture)
  510. {
  511. return (texture.GetTextureAlphaPacking() != AlphaPacking.None ||
  512. texture.RequiresVerticalFlip() ||
  513. texture.GetTextureStereoPacking() != StereoPacking.None ||
  514. texture.GetTextureCount() > 1
  515. );
  516. }
  517. public static void DrawTexture(Rect destRect, Texture texture, ScaleMode scaleMode, AlphaPacking alphaPacking, float pixelAspectRatio, Material material)
  518. {
  519. if (Event.current == null || Event.current.type == EventType.Repaint)
  520. {
  521. int sourceWidth = texture.width;
  522. int sourceHeight = texture.height;
  523. GetResolveTextureSize(alphaPacking, StereoPacking.Unknown, StereoEye.Both, pixelAspectRatio, ref sourceWidth, ref sourceHeight);
  524. float sourceRatio = (float)sourceWidth / (float)sourceHeight;
  525. Rect sourceRect = new Rect(0f, 0f, 1f, 1f);
  526. switch (scaleMode)
  527. {
  528. case ScaleMode.ScaleAndCrop:
  529. {
  530. float destRatio = destRect.width / destRect.height;
  531. if (destRatio > sourceRatio)
  532. {
  533. float adjust = sourceRatio / destRatio;
  534. sourceRect = new Rect(0f, (1f - adjust) * 0.5f, 1f, adjust);
  535. }
  536. else
  537. {
  538. float adjust = destRatio / sourceRatio;
  539. sourceRect = new Rect(0.5f - adjust * 0.5f, 0f, adjust, 1f);
  540. }
  541. }
  542. break;
  543. case ScaleMode.ScaleToFit:
  544. {
  545. float destRatio = destRect.width / destRect.height;
  546. if (destRatio > sourceRatio)
  547. {
  548. float adjust = sourceRatio / destRatio;
  549. destRect = new Rect(destRect.xMin + destRect.width * (1f - adjust) * 0.5f, destRect.yMin, adjust * destRect.width, destRect.height);
  550. }
  551. else
  552. {
  553. float adjust = destRatio / sourceRatio;
  554. destRect = new Rect(destRect.xMin, destRect.yMin + destRect.height * (1f - adjust) * 0.5f, destRect.width, adjust * destRect.height);
  555. }
  556. }
  557. break;
  558. case ScaleMode.StretchToFill:
  559. break;
  560. }
  561. GL.PushMatrix();
  562. if (RenderTexture.active == null)
  563. {
  564. //GL.LoadPixelMatrix();
  565. GL.LoadPixelMatrix(0f, Screen.width, Screen.height, 0f);
  566. }
  567. else
  568. {
  569. GL.LoadPixelMatrix(0f, RenderTexture.active.width, RenderTexture.active.height, 0f);
  570. }
  571. Graphics.DrawTexture(destRect, texture, sourceRect, 0, 0, 0, 0, GUI.color, material);
  572. GL.PopMatrix();
  573. }
  574. }
  575. }
  576. }