Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [Unreleased]

### Fixed
- Screenshot readback preserves the caller's active render target before `Graphics.Blit` changes it. The temporary readback texture is unbound before release, avoiding `Releasing render texture that is set to be RenderTexture.active!` warnings and leaving the previous target intact.

## [0.6.10] - 2026-10-04

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions Editor/Tools/Builtins/ScreenshotFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,8 @@ internal static void FlipTextureVertically(Texture2D texture)
internal static Texture2D ReadTextureToTexture2D(Texture sourceTexture, int width, int height, bool flipVertically)
{
RenderTexture readableRenderTexture = null;
RenderTexture previousActive = null;
// Blit binds its destination, so preserve the caller's target before rendering.
RenderTexture previousActive = RenderTexture.active;
Texture2D screenshot = null;

try
Expand All @@ -1292,7 +1293,6 @@ internal static Texture2D ReadTextureToTexture2D(Texture sourceTexture, int widt
readableRenderTexture.Create();
Graphics.Blit(sourceTexture, readableRenderTexture);

previousActive = RenderTexture.active;
RenderTexture.active = readableRenderTexture;

screenshot = ReadActiveRenderTextureToTexture2D(width, height, flipVertically);
Expand Down
43 changes: 43 additions & 0 deletions Tests/Editor/ScreenshotFunctionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (C) Funplay. Licensed under MIT.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
Expand Down Expand Up @@ -113,6 +114,48 @@ public void ShouldFlipPlayModeViewRenderTexture_DefaultsToTrue()
Assert.IsTrue(ScreenshotFunctions.ShouldFlipPlayModeViewRenderTexture());
}

[TestCase(false)]
[TestCase(true)]
public void ReadTextureToTexture2D_RestoresPreviousTargetWithoutReleasingAnActiveTexture(bool bindPrevious)
{
var originalActive = RenderTexture.active;
var previous = new RenderTexture(2, 2, 0, RenderTextureFormat.ARGB32);
var source = new Texture2D(2, 2, TextureFormat.RGBA32, false);
var warnings = new List<string>();
Texture2D screenshot = null;
Application.LogCallback onLog = (message, stack, type) =>
{
if (type == LogType.Warning)
warnings.Add(message);
};

try
{
previous.Create();
Fill(source, Color.red);
var expected = bindPrevious ? previous : null;
RenderTexture.active = expected;
Application.logMessageReceived += onLog;

screenshot = ScreenshotFunctions.ReadTextureToTexture2D(source, 2, 2, flipVertically: false);

Assert.AreEqual(expected, RenderTexture.active, "Screenshot readback must preserve the caller's active target.");
Assert.IsFalse(warnings.Any(message => message.Contains("Releasing render texture")),
"The temporary readback target must be unbound before release.");
AssertRed(screenshot.GetPixel(0, 0));
}
finally
{
Application.logMessageReceived -= onLog;
RenderTexture.active = originalActive;
if (screenshot != null)
UnityEngine.Object.DestroyImmediate(screenshot);
previous.Release();
UnityEngine.Object.DestroyImmediate(previous);
UnityEngine.Object.DestroyImmediate(source);
}
}

[Test]
public void ShouldFlipCameraRenderTexture_DefaultsToFalse()
{
Expand Down
Loading