Merge pull request #5712 from RoosterDragon/sheet-release-buffer
Release sheet buffers
This commit is contained in:
@@ -271,6 +271,8 @@ namespace OpenRA
|
||||
orderManager.LastTickTime = Environment.TickCount;
|
||||
orderManager.StartGame();
|
||||
worldRenderer.RefreshPalette();
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public static bool IsHost
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace OpenRA.Graphics
|
||||
var spriteLoader = new SpriteLoader(new string[0], new SheetBuilder(SheetType.Indexed));
|
||||
foreach (var s in nodesDict["Cursors"].Nodes)
|
||||
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
|
||||
spriteLoader.SheetBuilder.Current.ReleaseBuffer();
|
||||
|
||||
palette.Initialize();
|
||||
}
|
||||
|
||||
@@ -18,18 +18,21 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
public class Sheet
|
||||
{
|
||||
ITexture texture;
|
||||
readonly object textureLock = new object();
|
||||
bool dirty;
|
||||
readonly byte[] data;
|
||||
readonly object dirtyLock = new object();
|
||||
bool releaseBufferOnCommit;
|
||||
ITexture texture;
|
||||
byte[] data;
|
||||
|
||||
public readonly Size Size;
|
||||
public byte[] Data { get { return data ?? texture.GetData(); } }
|
||||
public bool Buffered { get { return data != null; } }
|
||||
|
||||
public Sheet(Size size)
|
||||
public Sheet(Size size, bool buffered)
|
||||
{
|
||||
Size = size;
|
||||
data = new byte[4 * Size.Width * Size.Height];
|
||||
if (buffered)
|
||||
data = new byte[4 * Size.Width * Size.Height];
|
||||
}
|
||||
|
||||
public Sheet(ITexture texture)
|
||||
@@ -54,6 +57,8 @@ namespace OpenRA.Graphics
|
||||
Marshal.Copy(IntPtr.Add(bd.Scan0, y * bd.Stride), data, y * dataStride, dataStride);
|
||||
bitmap.UnlockBits(bd);
|
||||
}
|
||||
|
||||
ReleaseBuffer();
|
||||
}
|
||||
|
||||
public ITexture Texture
|
||||
@@ -62,22 +67,31 @@ namespace OpenRA.Graphics
|
||||
// is set from other threads too via CommitData().
|
||||
get
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
GenerateTexture();
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
lock (dirtyLock)
|
||||
void GenerateTexture()
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
texture = Game.Renderer.Device.CreateTexture();
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (Buffered)
|
||||
{
|
||||
lock (textureLock)
|
||||
{
|
||||
if (dirty)
|
||||
{
|
||||
texture.SetData(data, Size.Width, Size.Height);
|
||||
dirty = false;
|
||||
if (releaseBufferOnCommit)
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +133,7 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(bd);
|
||||
|
||||
return bitmap;
|
||||
@@ -126,11 +141,20 @@ namespace OpenRA.Graphics
|
||||
|
||||
public void CommitData()
|
||||
{
|
||||
if (data == null)
|
||||
throw new InvalidOperationException("Texture-wrappers are read-only");
|
||||
if (!Buffered)
|
||||
throw new InvalidOperationException(
|
||||
"This sheet is unbuffered. You cannot call CommitData on an unbuffered sheet. " +
|
||||
"If you need to completely replace the texture data you should set data into the texture directly. " +
|
||||
"If you need to make only small changes to the texture data consider creating a buffered sheet instead.");
|
||||
|
||||
lock (dirtyLock)
|
||||
lock (textureLock)
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
public void ReleaseBuffer()
|
||||
{
|
||||
lock (textureLock)
|
||||
releaseBufferOnCommit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -17,7 +17,7 @@ namespace OpenRA.Graphics
|
||||
public class SheetOverflowException : Exception
|
||||
{
|
||||
public SheetOverflowException(string message)
|
||||
: base(message) {}
|
||||
: base(message) { }
|
||||
}
|
||||
|
||||
public enum SheetType
|
||||
@@ -38,11 +38,11 @@ namespace OpenRA.Graphics
|
||||
|
||||
public static Sheet AllocateSheet()
|
||||
{
|
||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));
|
||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize), true);
|
||||
}
|
||||
|
||||
public SheetBuilder(SheetType t)
|
||||
: this(t, AllocateSheet) {}
|
||||
: this(t, AllocateSheet) { }
|
||||
|
||||
public SheetBuilder(SheetType t, Func<Sheet> allocateSheet)
|
||||
{
|
||||
@@ -109,6 +109,7 @@ namespace OpenRA.Graphics
|
||||
var next = NextChannel(channel);
|
||||
if (next == null)
|
||||
{
|
||||
current.ReleaseBuffer();
|
||||
current = allocateSheet();
|
||||
channel = TextureChannel.Red;
|
||||
}
|
||||
@@ -116,7 +117,7 @@ namespace OpenRA.Graphics
|
||||
channel = next.Value;
|
||||
|
||||
rowHeight = imageSize.Height;
|
||||
p = new Point(0,0);
|
||||
p = new Point(0, 0);
|
||||
}
|
||||
|
||||
var rect = new Sprite(current, new Rectangle(p, imageSize), spriteOffset, channel, BlendMode.Alpha);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Graphics
|
||||
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
|
||||
allocated = true;
|
||||
|
||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
|
||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true);
|
||||
};
|
||||
|
||||
var sourceCache = new Dictionary<string, ISpriteSource>();
|
||||
@@ -69,6 +69,8 @@ namespace OpenRA.Graphics
|
||||
|
||||
// 1x1px transparent tile
|
||||
missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1));
|
||||
|
||||
Sheet.ReleaseBuffer();
|
||||
}
|
||||
|
||||
public Sprite TileSprite(TerrainTile r)
|
||||
|
||||
@@ -179,6 +179,7 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
// Sheet overflow - allocate a new sheet and try once more
|
||||
Log.Write("debug", "Voxel sheet overflow! Generating new sheet");
|
||||
sheetBuilder.Current.ReleaseBuffer();
|
||||
sheetBuilder = CreateSheetBuilder();
|
||||
v = GenerateSlicePlanes(l).SelectMany(x => x).ToArray();
|
||||
}
|
||||
@@ -223,5 +224,10 @@ namespace OpenRA.Graphics
|
||||
{
|
||||
return voxels[Pair.New(vxl, hva)];
|
||||
}
|
||||
|
||||
public void Finish()
|
||||
{
|
||||
sheetBuilder.Current.ReleaseBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace OpenRA
|
||||
FieldLoader.Translations = new Dictionary<string, string>();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var yaml = Manifest.Translations.Select(MiniYaml.FromFile).Aggregate(MiniYaml.MergeLiberal);
|
||||
Languages = yaml.Select(t => t.Key).ToArray();
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace OpenRA
|
||||
else if (y.Key == Game.Settings.Graphics.DefaultLanguage)
|
||||
defaultTranslations = y.Value.ToDictionary(my => my.Value ?? "");
|
||||
}
|
||||
|
||||
|
||||
var translations = new Dictionary<string, string>();
|
||||
foreach (var tkv in defaultTranslations.Concat(selectedTranslations))
|
||||
{
|
||||
@@ -140,6 +140,7 @@ namespace OpenRA
|
||||
map.SequenceProvider.Preload();
|
||||
|
||||
VoxelProvider.Initialize(Manifest.VoxelSequences, map.VoxelSequenceDefinitions);
|
||||
VoxelLoader.Finish();
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -27,14 +27,13 @@ namespace OpenRA.Widgets
|
||||
bool stopped;
|
||||
bool paused;
|
||||
|
||||
Action OnComplete;
|
||||
Action onComplete;
|
||||
|
||||
public bool Paused { get { return paused; } }
|
||||
|
||||
|
||||
readonly World world;
|
||||
[ObjectCreator.UseCtor]
|
||||
public VqaPlayerWidget( World world )
|
||||
public VqaPlayerWidget(World world)
|
||||
{
|
||||
this.world = world;
|
||||
}
|
||||
@@ -48,33 +47,35 @@ namespace OpenRA.Widgets
|
||||
stopped = true;
|
||||
paused = true;
|
||||
Sound.StopVideo();
|
||||
OnComplete = () => {};
|
||||
onComplete = () => { };
|
||||
|
||||
cachedVideo = filename;
|
||||
video = new VqaReader(GlobalFileSystem.Open(filename));
|
||||
|
||||
invLength = video.Framerate*1f/video.Frames;
|
||||
invLength = video.Framerate * 1f / video.Frames;
|
||||
|
||||
var size = Math.Max(video.Width, video.Height);
|
||||
var textureSize = Exts.NextPowerOf2(size);
|
||||
videoSprite = new Sprite(new Sheet(new Size(textureSize,textureSize)), new Rectangle( 0, 0, video.Width, video.Height ), TextureChannel.Alpha);
|
||||
videoSprite.sheet.Texture.SetData(video.FrameData);
|
||||
var videoSheet = new Sheet(new Size(textureSize, textureSize), false);
|
||||
videoSheet.Texture.SetData(video.FrameData);
|
||||
videoSprite = new Sprite(videoSheet, new Rectangle(0, 0, video.Width, video.Height), TextureChannel.Alpha);
|
||||
|
||||
var scale = Math.Min(RenderBounds.Width / video.Width, RenderBounds.Height / video.Height);
|
||||
videoOrigin = new float2(RenderBounds.X + (RenderBounds.Width - scale*video.Width)/2, RenderBounds.Y + (RenderBounds.Height - scale*video.Height)/2);
|
||||
videoOrigin = new float2(RenderBounds.X + (RenderBounds.Width - scale * video.Width) / 2, RenderBounds.Y + (RenderBounds.Height - scale * video.Height) / 2);
|
||||
videoSize = new float2(video.Width * scale, video.Height * scale);
|
||||
|
||||
if (!DrawOverlay)
|
||||
return;
|
||||
|
||||
overlay = new uint[2*textureSize, 2*textureSize];
|
||||
overlay = new uint[2 * textureSize, 2 * textureSize];
|
||||
var black = (uint)255 << 24;
|
||||
for (var y = 0; y < video.Height; y++)
|
||||
for (var x = 0; x < video.Width; x++)
|
||||
overlay[2*y,x] = black;
|
||||
overlay[2 * y, x] = black;
|
||||
|
||||
overlaySprite = new Sprite(new Sheet(new Size(2*textureSize,2*textureSize)), new Rectangle( 0, 0, video.Width, 2*video.Height ), TextureChannel.Alpha);
|
||||
overlaySprite.sheet.Texture.SetData(overlay);
|
||||
var overlaySheet = new Sheet(new Size(2 * textureSize, 2 * textureSize), false);
|
||||
overlaySheet.Texture.SetData(overlay);
|
||||
overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, video.Width, 2 * video.Height), TextureChannel.Alpha);
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
@@ -84,7 +85,7 @@ namespace OpenRA.Widgets
|
||||
|
||||
if (!(stopped || paused))
|
||||
{
|
||||
var nextFrame = (int)float2.Lerp(0, video.Frames, Sound.VideoSeekPosition*invLength);
|
||||
var nextFrame = (int)float2.Lerp(0, video.Frames, Sound.VideoSeekPosition * invLength);
|
||||
if (nextFrame > video.Frames)
|
||||
{
|
||||
Stop();
|
||||
@@ -115,12 +116,13 @@ namespace OpenRA.Widgets
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Play()
|
||||
{
|
||||
PlayThen(() => {});
|
||||
PlayThen(() => { });
|
||||
}
|
||||
|
||||
public void PlayThen(Action after)
|
||||
@@ -128,7 +130,7 @@ namespace OpenRA.Widgets
|
||||
if (video == null)
|
||||
return;
|
||||
|
||||
OnComplete = after;
|
||||
onComplete = after;
|
||||
if (stopped)
|
||||
Sound.PlayVideo(video.AudioData);
|
||||
else
|
||||
@@ -156,7 +158,7 @@ namespace OpenRA.Widgets
|
||||
Sound.StopVideo();
|
||||
video.Reset();
|
||||
videoSprite.sheet.Texture.SetData(video.FrameData);
|
||||
world.AddFrameEndTask(_ => OnComplete());
|
||||
world.AddFrameEndTask(_ => onComplete());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,8 +51,9 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
back = new byte[4*256*256];
|
||||
|
||||
var rect = new Rectangle((int)(255*SRange[0]), (int)(255*(1 - VRange[1])), (int)(255*(SRange[1] - SRange[0]))+1, (int)(255*(VRange[1] - VRange[0])) + 1);
|
||||
mixerSprite = new Sprite(new Sheet(new Size(256, 256)), rect, TextureChannel.Alpha);
|
||||
mixerSprite.sheet.Texture.SetData(front, 256, 256);
|
||||
var mixerSheet = new Sheet(new Size(256, 256), false);
|
||||
mixerSheet.Texture.SetData(front, 256, 256);
|
||||
mixerSprite = new Sprite(mixerSheet, rect, TextureChannel.Alpha);
|
||||
}
|
||||
|
||||
void GenerateBitmap()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
||||
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||
* This file is part of OpenRA, which is free software. It is made
|
||||
* available to you under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation. For more information,
|
||||
@@ -19,8 +19,8 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
Sprite hueSprite;
|
||||
|
||||
public HueSliderWidget() {}
|
||||
public HueSliderWidget(HueSliderWidget other) : base(other) {}
|
||||
public HueSliderWidget() { }
|
||||
public HueSliderWidget(HueSliderWidget other) : base(other) { }
|
||||
|
||||
public override void Initialize(WidgetArgs args)
|
||||
{
|
||||
@@ -28,7 +28,8 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
|
||||
using (var hueBitmap = new Bitmap(256, 256))
|
||||
{
|
||||
hueSprite = new Sprite(new Sheet(new Size(256, 256)), new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
|
||||
var hueSheet = new Sheet(new Size(256, 256), false);
|
||||
hueSprite = new Sprite(hueSheet, new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
|
||||
|
||||
var bitmapData = hueBitmap.LockBits(hueBitmap.Bounds(),
|
||||
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||
@@ -39,8 +40,7 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
*(c + h) = HSLColor.FromHSV(h / 255f, 1, 1).RGB.ToArgb();
|
||||
}
|
||||
hueBitmap.UnlockBits(bitmapData);
|
||||
|
||||
hueSprite.sheet.Texture.SetData(hueBitmap);
|
||||
hueSheet.Texture.SetData(hueBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +54,8 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(hueSprite, ro, new float2(rb.Size));
|
||||
|
||||
var sprite = ChromeProvider.GetImage("lobby-bits", "huepicker");
|
||||
var pos = RenderOrigin + new int2(PxFromValue(Value).Clamp(0, rb.Width-1) - sprite.bounds.Width/2, (rb.Height-sprite.bounds.Height)/2);
|
||||
var pos = RenderOrigin + new int2(PxFromValue(Value).Clamp(0, rb.Width - 1) - sprite.bounds.Width / 2, (rb.Height - sprite.bounds.Height) / 2);
|
||||
Game.Renderer.RgbaSpriteRenderer.DrawSprite(sprite, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,13 +72,14 @@ namespace OpenRA.Mods.RA.Widgets
|
||||
{
|
||||
var r = new Rectangle(0, 0, width, height);
|
||||
var s = new Size(terrainBitmap.Width, terrainBitmap.Height);
|
||||
terrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||
terrainSprite.sheet.Texture.SetData(terrainBitmap);
|
||||
var terrainSheet = new Sheet(s, false);
|
||||
terrainSheet.Texture.SetData(terrainBitmap);
|
||||
terrainSprite = new Sprite(terrainSheet, r, TextureChannel.Alpha);
|
||||
|
||||
// Data is set in Tick()
|
||||
customTerrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||
actorSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||
shroudSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||
customTerrainSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
||||
actorSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
||||
shroudSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user