VideoRender.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. #if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
  2. #define UNITY_PLATFORM_SUPPORTS_YPCBCR
  3. #endif
  4. #if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || 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-2024 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("_MainTex_Xfrm");
  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 (material == null)
  242. return;
  243. if (transform == null || transform.Length != 6)
  244. transform = new float[6] { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
  245. Vector4 v0 = new Vector4(transform[0], transform[1], 0, 0);
  246. Vector4 v1 = new Vector4(transform[2], transform[3], 0, 0);
  247. Vector4 v2 = new Vector4(0, 0, 1, 0);
  248. Vector4 v3 = new Vector4(transform[4], transform[5], 0, 1);
  249. material.SetMatrix(PropTextureMatrix.Id, new Matrix4x4(v0, v1, v2, v3));
  250. }
  251. public static void SetupTextureMatrix(Material material, Matrix4x4 transform)
  252. {
  253. if (material == null)
  254. return;
  255. material.SetMatrix(PropTextureMatrix.Id, transform);
  256. }
  257. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  258. public static void SetupYpCbCrMaterial(Material material, bool enable, Matrix4x4 transform, Texture texture)
  259. {
  260. if (material.HasProperty(VideoRender.PropUseYpCbCr.Id))
  261. {
  262. if (enable)
  263. {
  264. material.EnableKeyword(VideoRender.Keyword_UseYpCbCr);
  265. material.SetMatrix(VideoRender.PropYpCbCrTransform.Id, transform);
  266. material.SetTexture(VideoRender.PropChromaTex.Id, texture);
  267. }
  268. else
  269. {
  270. material.DisableKeyword(VideoRender.Keyword_UseYpCbCr);
  271. }
  272. }
  273. }
  274. #endif
  275. public static void SetupVerticalFlipMaterial(Material material, bool flip)
  276. {
  277. material.SetFloat(VideoRender.PropVertScale.Id, flip?-1f:1f);
  278. }
  279. public static Texture GetTexture(MediaPlayer mediaPlayer, int textureIndex)
  280. {
  281. Texture result = null;
  282. if (mediaPlayer != null)
  283. {
  284. if (mediaPlayer.UseResampler && mediaPlayer.FrameResampler != null && mediaPlayer.FrameResampler.OutputTexture != null)
  285. {
  286. if ( mediaPlayer.FrameResampler.OutputTexture.Length > textureIndex)
  287. {
  288. result = mediaPlayer.FrameResampler.OutputTexture[textureIndex];
  289. }
  290. }
  291. else if (mediaPlayer.TextureProducer != null)
  292. {
  293. if (mediaPlayer.TextureProducer.GetTextureCount() > textureIndex)
  294. {
  295. result = mediaPlayer.TextureProducer.GetTexture(textureIndex);
  296. }
  297. }
  298. }
  299. return result;
  300. }
  301. public static void SetupMaterialForMedia(Material material, MediaPlayer mediaPlayer, int texturePropId = -1, Texture fallbackTexture = null, bool forceFallbackTexture = false)
  302. {
  303. Debug.Assert(material != null);
  304. if (mediaPlayer != null)
  305. {
  306. Texture mainTexture = GetTexture(mediaPlayer, 0);
  307. Matrix4x4 textureTransform = Matrix4x4.identity;
  308. Texture yCbCrTexture = GetTexture(mediaPlayer, 1);
  309. Matrix4x4 yCbCrTransform = Matrix4x4.identity;
  310. StereoPacking stereoPacking = StereoPacking.None;
  311. AlphaPacking alphaPacking = AlphaPacking.None;
  312. bool flipY = false;
  313. bool isLinear = false;
  314. if (texturePropId != -1)
  315. {
  316. if (mainTexture == null || forceFallbackTexture)
  317. {
  318. mainTexture = fallbackTexture;
  319. }
  320. material.SetTexture(texturePropId, mainTexture);
  321. }
  322. ITextureProducer textureProducer = mediaPlayer.TextureProducer;
  323. if (textureProducer != null)
  324. {
  325. flipY = textureProducer.RequiresVerticalFlip();
  326. yCbCrTransform = textureProducer.GetYpCbCrTransform();
  327. stereoPacking = textureProducer.GetTextureStereoPacking();
  328. alphaPacking = textureProducer.GetTextureAlphaPacking();
  329. textureTransform = textureProducer.GetTextureMatrix();
  330. }
  331. if (mediaPlayer.Info != null)
  332. {
  333. isLinear = mediaPlayer.Info.PlayerSupportsLinearColorSpace();
  334. }
  335. SetupMaterial(material, flipY, isLinear, yCbCrTransform, yCbCrTexture, textureTransform, mediaPlayer.VideoLayoutMapping, stereoPacking, alphaPacking);
  336. }
  337. else
  338. {
  339. if (texturePropId != -1)
  340. {
  341. material.SetTexture(texturePropId, fallbackTexture);
  342. }
  343. SetupMaterial(material, false, true, Matrix4x4.identity, null, Matrix4x4.identity);
  344. }
  345. }
  346. internal static void SetupMaterial(
  347. Material material,
  348. bool flipVertically,
  349. bool playerSupportsLinear,
  350. Matrix4x4 ycbcrTransform,
  351. Texture ycbcrTexture,
  352. Matrix4x4 textureTransform,
  353. VideoMapping mapping = VideoMapping.Normal,
  354. StereoPacking stereoPacking = StereoPacking.None,
  355. AlphaPacking alphaPacking = AlphaPacking.None)
  356. {
  357. SetupVerticalFlipMaterial(material, flipVertically);
  358. // Apply changes for layout
  359. if (material.HasProperty(VideoRender.PropLayout.Id))
  360. {
  361. VideoRender.SetupLayoutMaterial(material, mapping);
  362. }
  363. // Apply changes for stereo videos
  364. if (material.HasProperty(VideoRender.PropStereo.Id))
  365. {
  366. VideoRender.SetupStereoMaterial(material, stereoPacking);
  367. }
  368. // Apply changes for alpha videos
  369. if (material.HasProperty(VideoRender.PropAlphaPack.Id))
  370. {
  371. VideoRender.SetupAlphaPackedMaterial(material, alphaPacking);
  372. }
  373. // Apply gamma correction
  374. #if UNITY_PLATFORM_SUPPORTS_LINEAR
  375. if (material.HasProperty(VideoRender.PropApplyGamma.Id))
  376. {
  377. VideoRender.SetupGammaMaterial(material, playerSupportsLinear);
  378. }
  379. #endif
  380. // Adjust for cropping/orientation (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
  381. VideoRender.SetupTextureMatrix(material, textureTransform);
  382. #if UNITY_PLATFORM_SUPPORTS_YPCBCR
  383. VideoRender.SetupYpCbCrMaterial(material, ycbcrTexture != null, ycbcrTransform, ycbcrTexture);
  384. #endif
  385. }
  386. [System.Flags]
  387. public enum ResolveFlags : int
  388. {
  389. Mipmaps = 1 << 0,
  390. PackedAlpha = 1 << 1,
  391. StereoLeft = 1 << 2,
  392. StereoRight = 1 << 3,
  393. ColorspaceSRGB = 1 << 4,
  394. }
  395. public static void SetupResolveMaterial(Material material, VideoResolveOptions options)
  396. {
  397. if (options.IsColourAdjust())
  398. {
  399. material.EnableKeyword(VideoRender.Keyword_UseHSBC);
  400. material.SetFloat(VideoRender.PropHue.Id, options.hue);
  401. material.SetFloat(VideoRender.PropSaturation.Id, options.saturation);
  402. material.SetFloat(VideoRender.PropBrightness.Id, options.brightness);
  403. material.SetFloat(VideoRender.PropContrast.Id, options.contrast);
  404. material.SetFloat(VideoRender.PropInvGamma.Id, 1f / options.gamma);
  405. }
  406. else
  407. {
  408. material.DisableKeyword(VideoRender.Keyword_UseHSBC);
  409. }
  410. material.color = options.tint;
  411. }
  412. public static RenderTexture ResolveVideoToRenderTexture(Material resolveMaterial, RenderTexture targetTexture, ITextureProducer texture, ResolveFlags flags, ScaleMode scaleMode = ScaleMode.StretchToFill)
  413. {
  414. int targetWidth = texture.GetTexture(0).width;
  415. int targetHeight = texture.GetTexture(0).height;
  416. StereoEye eyeMode = StereoEye.Both;
  417. if (((flags & ResolveFlags.StereoLeft) == ResolveFlags.StereoLeft) &&
  418. ((flags & ResolveFlags.StereoRight) != ResolveFlags.StereoRight))
  419. {
  420. eyeMode = StereoEye.Left;
  421. }
  422. else if (((flags & ResolveFlags.StereoLeft) != ResolveFlags.StereoLeft) &&
  423. ((flags & ResolveFlags.StereoRight) == ResolveFlags.StereoRight))
  424. {
  425. eyeMode = StereoEye.Right;
  426. }
  427. // 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
  428. // - Instead, the PAR is accounted for during drawing (which is more efficient too)
  429. // - https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1297
  430. float pixelAspectRatio = 1.0f; // texture.GetTexturePixelAspectRatio();
  431. GetResolveTextureSize(
  432. texture.GetTextureAlphaPacking(),
  433. texture.GetTextureStereoPacking(),
  434. eyeMode,
  435. pixelAspectRatio,
  436. texture.GetTextureMatrix(),
  437. ref targetWidth,
  438. ref targetHeight);
  439. if (targetTexture)
  440. {
  441. bool sizeChanged = (targetTexture.width != targetWidth) || (targetTexture.height != targetHeight);
  442. if (sizeChanged)
  443. {
  444. RenderTexture.ReleaseTemporary(targetTexture);
  445. targetTexture = null;
  446. }
  447. }
  448. if (!targetTexture)
  449. {
  450. RenderTextureReadWrite readWrite = ((flags & ResolveFlags.ColorspaceSRGB) == ResolveFlags.ColorspaceSRGB) ? RenderTextureReadWrite.sRGB : RenderTextureReadWrite.Linear;
  451. targetTexture = RenderTexture.GetTemporary(targetWidth, targetHeight, 0, RenderTextureFormat.ARGB32, readWrite);
  452. }
  453. // Set target mipmap generation support
  454. {
  455. bool requiresMipmap = (flags & ResolveFlags.Mipmaps) == ResolveFlags.Mipmaps;
  456. bool requiresRecreate = (targetTexture.IsCreated() && targetTexture.useMipMap != requiresMipmap);
  457. if (requiresRecreate)
  458. {
  459. targetTexture.Release();
  460. }
  461. if (!targetTexture.IsCreated())
  462. {
  463. targetTexture.useMipMap = targetTexture.autoGenerateMips = requiresMipmap;
  464. targetTexture.Create();
  465. }
  466. }
  467. // Render resolve blit
  468. // TODO: combine these two paths into a single material blit
  469. {
  470. bool prevSRGB = GL.sRGBWrite;
  471. GL.sRGBWrite = targetTexture.sRGB;
  472. RenderTexture prev = RenderTexture.active;
  473. if (scaleMode == ScaleMode.StretchToFill)
  474. {
  475. Graphics.Blit(texture.GetTexture(0), targetTexture, resolveMaterial);
  476. }
  477. else
  478. {
  479. RenderTexture.active = targetTexture;
  480. bool partialAreaRender = (scaleMode == ScaleMode.ScaleToFit);
  481. if (partialAreaRender)
  482. {
  483. GL.Clear(false, true, Color.black);
  484. }
  485. VideoRender.DrawTexture(new Rect(0f, 0f, targetTexture.width, targetTexture.height), texture.GetTexture(0), scaleMode, texture.GetTextureAlphaPacking(), texture.GetTexturePixelAspectRatio(), resolveMaterial);
  486. }
  487. RenderTexture.active = prev;
  488. GL.sRGBWrite = prevSRGB;
  489. }
  490. return targetTexture;
  491. }
  492. public static void GetResolveTextureSize(AlphaPacking alphaPacking, StereoPacking stereoPacking, StereoEye eyeMode, float pixelAspectRatio, Matrix4x4 textureXfrm, ref int width, ref int height)
  493. {
  494. Vector4 size = new Vector4(width, height, 0, 0);
  495. size = textureXfrm * size;
  496. width = (int)Mathf.Abs(size.x);
  497. height = (int)Mathf.Abs(size.y);
  498. switch (alphaPacking)
  499. {
  500. case AlphaPacking.LeftRight:
  501. width /= 2;
  502. break;
  503. case AlphaPacking.TopBottom:
  504. height /= 2;
  505. break;
  506. }
  507. if (eyeMode != StereoEye.Both)
  508. {
  509. switch (stereoPacking)
  510. {
  511. case StereoPacking.LeftRight:
  512. width /= 2;
  513. break;
  514. case StereoPacking.TopBottom:
  515. height /= 2;
  516. break;
  517. }
  518. }
  519. if (pixelAspectRatio > 0f)
  520. {
  521. if (pixelAspectRatio > 1f)
  522. {
  523. width = Mathf.RoundToInt(width * pixelAspectRatio);
  524. }
  525. else if (pixelAspectRatio < 1f)
  526. {
  527. height = Mathf.RoundToInt(height / pixelAspectRatio);
  528. }
  529. }
  530. }
  531. public static bool RequiresResolve(ITextureProducer texture)
  532. {
  533. return (texture.GetTextureAlphaPacking() != AlphaPacking.None ||
  534. texture.RequiresVerticalFlip() ||
  535. texture.GetTextureStereoPacking() != StereoPacking.None ||
  536. texture.GetTextureCount() > 1
  537. );
  538. }
  539. public static void DrawTexture(Rect destRect, Texture texture, ScaleMode scaleMode, AlphaPacking alphaPacking, float pixelAspectRatio, Material material)
  540. {
  541. if (Event.current == null || Event.current.type == EventType.Repaint)
  542. {
  543. int sourceWidth = texture.width;
  544. int sourceHeight = texture.height;
  545. Matrix4x4 textureXfrm = Matrix4x4.identity;
  546. GetResolveTextureSize(alphaPacking, StereoPacking.Unknown, StereoEye.Both, pixelAspectRatio, textureXfrm, ref sourceWidth, ref sourceHeight);
  547. float sourceRatio = (float)sourceWidth / (float)sourceHeight;
  548. Rect sourceRect = new Rect(0f, 0f, 1f, 1f);
  549. switch (scaleMode)
  550. {
  551. case ScaleMode.ScaleAndCrop:
  552. {
  553. float destRatio = destRect.width / destRect.height;
  554. if (destRatio > sourceRatio)
  555. {
  556. float adjust = sourceRatio / destRatio;
  557. sourceRect = new Rect(0f, (1f - adjust) * 0.5f, 1f, adjust);
  558. }
  559. else
  560. {
  561. float adjust = destRatio / sourceRatio;
  562. sourceRect = new Rect(0.5f - adjust * 0.5f, 0f, adjust, 1f);
  563. }
  564. }
  565. break;
  566. case ScaleMode.ScaleToFit:
  567. {
  568. float destRatio = destRect.width / destRect.height;
  569. if (destRatio > sourceRatio)
  570. {
  571. float adjust = sourceRatio / destRatio;
  572. destRect = new Rect(destRect.xMin + destRect.width * (1f - adjust) * 0.5f, destRect.yMin, adjust * destRect.width, destRect.height);
  573. }
  574. else
  575. {
  576. float adjust = destRatio / sourceRatio;
  577. destRect = new Rect(destRect.xMin, destRect.yMin + destRect.height * (1f - adjust) * 0.5f, destRect.width, adjust * destRect.height);
  578. }
  579. }
  580. break;
  581. case ScaleMode.StretchToFill:
  582. break;
  583. }
  584. GL.PushMatrix();
  585. if (RenderTexture.active == null)
  586. {
  587. //GL.LoadPixelMatrix();
  588. GL.LoadPixelMatrix(0f, Screen.width, Screen.height, 0f);
  589. }
  590. else
  591. {
  592. GL.LoadPixelMatrix(0f, RenderTexture.active.width, RenderTexture.active.height, 0f);
  593. }
  594. Graphics.DrawTexture(destRect, texture, sourceRect, 0, 0, 0, 0, GUI.color, material);
  595. GL.PopMatrix();
  596. }
  597. }
  598. }
  599. }