Lazily generate buffer in Sheet.
The managed byte buffer is created on demand, meaning a newly allocated sheet will not waste memory holding onto the buffer until some changes are actually required to be written. This avoids a newly allocated sheet wasting memory on buffers that do not differ from their backing texture.
This commit is contained in:
committed by
RoosterDragon
parent
e6852e2b50
commit
ff16690b86
@@ -25,14 +25,25 @@ namespace OpenRA.Graphics
|
|||||||
byte[] data;
|
byte[] data;
|
||||||
|
|
||||||
public readonly Size Size;
|
public readonly Size Size;
|
||||||
public byte[] Data { get { return data ?? texture.GetData(); } }
|
public byte[] Data
|
||||||
public bool Buffered { get { return data != null; } }
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (data != null)
|
||||||
|
return data;
|
||||||
|
if (texture == null)
|
||||||
|
data = new byte[4 * Size.Width * Size.Height];
|
||||||
|
else
|
||||||
|
data = texture.GetData();
|
||||||
|
releaseBufferOnCommit = false;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool Buffered { get { return data != null || texture == null; } }
|
||||||
|
|
||||||
public Sheet(Size size, bool buffered)
|
public Sheet(Size size)
|
||||||
{
|
{
|
||||||
Size = size;
|
Size = size;
|
||||||
if (buffered)
|
|
||||||
data = new byte[4 * Size.Width * Size.Height];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sheet(ITexture texture)
|
public Sheet(ITexture texture)
|
||||||
@@ -80,7 +91,7 @@ namespace OpenRA.Graphics
|
|||||||
dirty = true;
|
dirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Buffered)
|
if (data != null)
|
||||||
{
|
{
|
||||||
lock (textureLock)
|
lock (textureLock)
|
||||||
{
|
{
|
||||||
@@ -141,20 +152,28 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void CommitData()
|
public void CommitData()
|
||||||
{
|
{
|
||||||
if (!Buffered)
|
CommitData(false);
|
||||||
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 (textureLock)
|
|
||||||
dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReleaseBuffer()
|
public void ReleaseBuffer()
|
||||||
|
{
|
||||||
|
CommitData(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommitData(bool releaseBuffer)
|
||||||
{
|
{
|
||||||
lock (textureLock)
|
lock (textureLock)
|
||||||
releaseBufferOnCommit = true;
|
{
|
||||||
|
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.");
|
||||||
|
|
||||||
|
dirty = true;
|
||||||
|
if (releaseBuffer)
|
||||||
|
releaseBufferOnCommit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public static Sheet AllocateSheet()
|
public static Sheet AllocateSheet()
|
||||||
{
|
{
|
||||||
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize), true);
|
return new Sheet(new Size(Renderer.SheetSize, Renderer.SheetSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SheetBuilder(SheetType t)
|
public SheetBuilder(SheetType t)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace OpenRA.Graphics
|
|||||||
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
|
throw new SheetOverflowException("Terrain sheet overflow. Try increasing the tileset SheetSize parameter.");
|
||||||
allocated = true;
|
allocated = true;
|
||||||
|
|
||||||
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true);
|
return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize));
|
||||||
};
|
};
|
||||||
|
|
||||||
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace OpenRA.Widgets
|
|||||||
|
|
||||||
var size = Math.Max(video.Width, video.Height);
|
var size = Math.Max(video.Width, video.Height);
|
||||||
var textureSize = Exts.NextPowerOf2(size);
|
var textureSize = Exts.NextPowerOf2(size);
|
||||||
var videoSheet = new Sheet(new Size(textureSize, textureSize), false);
|
var videoSheet = new Sheet(new Size(textureSize, textureSize));
|
||||||
|
|
||||||
videoSheet.Texture.ScaleFilter = TextureScaleFilter.Linear;
|
videoSheet.Texture.ScaleFilter = TextureScaleFilter.Linear;
|
||||||
videoSheet.Texture.SetData(video.FrameData);
|
videoSheet.Texture.SetData(video.FrameData);
|
||||||
@@ -89,7 +89,7 @@ namespace OpenRA.Widgets
|
|||||||
for (var y = 0; y < scaledHeight; y += 2)
|
for (var y = 0; y < scaledHeight; y += 2)
|
||||||
overlay[y, 0] = black;
|
overlay[y, 0] = black;
|
||||||
|
|
||||||
var overlaySheet = new Sheet(new Size(1, Exts.NextPowerOf2(scaledHeight)), false);
|
var overlaySheet = new Sheet(new Size(1, Exts.NextPowerOf2(scaledHeight)));
|
||||||
overlaySheet.Texture.SetData(overlay);
|
overlaySheet.Texture.SetData(overlay);
|
||||||
overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, scaledHeight), TextureChannel.Alpha);
|
overlaySprite = new Sprite(overlaySheet, new Rectangle(0, 0, 1, scaledHeight), TextureChannel.Alpha);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
back = new byte[4*256*256];
|
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);
|
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);
|
||||||
var mixerSheet = new Sheet(new Size(256, 256), false);
|
var mixerSheet = new Sheet(new Size(256, 256));
|
||||||
mixerSheet.Texture.SetData(front, 256, 256);
|
mixerSheet.Texture.SetData(front, 256, 256);
|
||||||
mixerSprite = new Sprite(mixerSheet, rect, TextureChannel.Alpha);
|
mixerSprite = new Sprite(mixerSheet, rect, TextureChannel.Alpha);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
using (var hueBitmap = new Bitmap(256, 256))
|
using (var hueBitmap = new Bitmap(256, 256))
|
||||||
{
|
{
|
||||||
var hueSheet = new Sheet(new Size(256, 256), false);
|
var hueSheet = new Sheet(new Size(256, 256));
|
||||||
hueSprite = new Sprite(hueSheet, new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
|
hueSprite = new Sprite(hueSheet, new Rectangle(0, 0, 256, 1), TextureChannel.Alpha);
|
||||||
|
|
||||||
var bitmapData = hueBitmap.LockBits(hueBitmap.Bounds(),
|
var bitmapData = hueBitmap.LockBits(hueBitmap.Bounds(),
|
||||||
|
|||||||
@@ -73,14 +73,14 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
{
|
{
|
||||||
var r = new Rectangle(0, 0, width, height);
|
var r = new Rectangle(0, 0, width, height);
|
||||||
var s = new Size(terrainBitmap.Width, terrainBitmap.Height);
|
var s = new Size(terrainBitmap.Width, terrainBitmap.Height);
|
||||||
var terrainSheet = new Sheet(s, false);
|
var terrainSheet = new Sheet(s);
|
||||||
terrainSheet.Texture.SetData(terrainBitmap);
|
terrainSheet.Texture.SetData(terrainBitmap);
|
||||||
terrainSprite = new Sprite(terrainSheet, r, TextureChannel.Alpha);
|
terrainSprite = new Sprite(terrainSheet, r, TextureChannel.Alpha);
|
||||||
|
|
||||||
// Data is set in Tick()
|
// Data is set in Tick()
|
||||||
customTerrainSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
customTerrainSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||||
actorSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
actorSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||||
shroudSprite = new Sprite(new Sheet(s, false), r, TextureChannel.Alpha);
|
shroudSprite = new Sprite(new Sheet(s), r, TextureChannel.Alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user