mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-15 03:20:30 +00:00
Tidy up logic and move away from raw bytes where possible
This commit is contained in:
@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Testing;
|
||||
using OpenTK.Graphics;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
@@ -30,33 +31,35 @@ namespace osu.Framework.Tests.Visual
|
||||
public TestCaseCircularProgress()
|
||||
{
|
||||
const int width = 128;
|
||||
byte[] data = new byte[width * 4];
|
||||
Rgba32[] data = new Rgba32[width];
|
||||
|
||||
gradientTextureHorizontal = new Texture(width, 1, true);
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
float brightness = (float)i / (width - 1);
|
||||
int index = i * 4;
|
||||
data[index + 0] = (byte)(128 + (1 - brightness) * 127);
|
||||
data[index + 1] = (byte)(128 + brightness * 127);
|
||||
data[index + 2] = 128;
|
||||
data[index + 3] = 255;
|
||||
data[i] = new Rgba32(
|
||||
(byte)(128 + (1 - brightness) * 127),
|
||||
(byte)(128 + brightness * 127),
|
||||
128,
|
||||
255);
|
||||
}
|
||||
gradientTextureHorizontal.SetData(new TextureUpload(data));
|
||||
|
||||
gradientTextureHorizontal.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
|
||||
|
||||
gradientTextureVertical = new Texture(1, width, true);
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
float brightness = (float)i / (width - 1);
|
||||
int index = i * 4;
|
||||
data[index + 0] = (byte)(128 + (1 - brightness) * 127);
|
||||
data[index + 1] = (byte)(128 + brightness * 127);
|
||||
data[index + 2] = 128;
|
||||
data[index + 3] = 255;
|
||||
data[i] = new Rgba32(
|
||||
(byte)(128 + (1 - brightness) * 127),
|
||||
(byte)(128 + brightness * 127),
|
||||
128,
|
||||
255);
|
||||
}
|
||||
gradientTextureVertical.SetData(new TextureUpload(data));
|
||||
|
||||
byte[] data2 = new byte[width * width * 4];
|
||||
gradientTextureVertical.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
|
||||
|
||||
data = new Rgba32[width * width];
|
||||
gradientTextureBoth = new Texture(width, width, true);
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
@@ -64,15 +67,15 @@ namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
float brightness = (float)i / (width - 1);
|
||||
float brightness2 = (float)j / (width - 1);
|
||||
int index = i * 4 * width + j * 4;
|
||||
data2[index + 0] = (byte)(128 + (1 + brightness - brightness2) / 2 * 127);
|
||||
data2[index + 1] = (byte)(128 + (1 + brightness2 - brightness) / 2 * 127);
|
||||
data2[index + 2] = (byte)(128 + (brightness + brightness2) / 2 * 127);
|
||||
data2[index + 3] = 255;
|
||||
data[i * width + j] = new Rgba32(
|
||||
(byte)(128 + (1 + brightness - brightness2) / 2 * 127),
|
||||
(byte)(128 + (1 + brightness2 - brightness) / 2 * 127),
|
||||
(byte)(128 + (brightness + brightness2) / 2 * 127),
|
||||
255);
|
||||
}
|
||||
}
|
||||
gradientTextureBoth.SetData(new TextureUpload(data2));
|
||||
|
||||
gradientTextureBoth.SetData(new TextureUpload(new RawTextureRgba32(width, width, data)));
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ using osu.Framework.Input.States;
|
||||
using osu.Framework.Testing;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
@@ -20,17 +21,13 @@ namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
const int width = 20;
|
||||
Texture gradientTexture = new Texture(width, 1, true);
|
||||
byte[] data = new byte[width * 4];
|
||||
Rgba32[] data = new Rgba32[width];
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
float brightness = (float)i / (width - 1);
|
||||
int index = i * 4;
|
||||
data[index + 0] = (byte)(brightness * 255);
|
||||
data[index + 1] = (byte)(brightness * 255);
|
||||
data[index + 2] = (byte)(brightness * 255);
|
||||
data[index + 3] = 255;
|
||||
var brightnessByte = (byte)((float)i / (width - 1) * 255);
|
||||
data[i] = new Rgba32(brightnessByte, brightnessByte, brightnessByte);
|
||||
}
|
||||
gradientTexture.SetData(new TextureUpload(data));
|
||||
gradientTexture.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
|
||||
|
||||
Cell(0).AddRange(new[]
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ using osu.Framework.Input.States;
|
||||
using osu.Framework.Testing;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
@@ -22,17 +23,13 @@ namespace osu.Framework.Tests.Visual
|
||||
{
|
||||
const int width = 2;
|
||||
Texture gradientTexture = new Texture(width, 1, true);
|
||||
byte[] data = new byte[width * 4];
|
||||
Rgba32[] data = new Rgba32[width];
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
float brightness = (float)i / (width - 1);
|
||||
int index = i * 4;
|
||||
data[index + 0] = (byte)(brightness * 255);
|
||||
data[index + 1] = (byte)(brightness * 255);
|
||||
data[index + 2] = (byte)(brightness * 255);
|
||||
data[index + 3] = 255;
|
||||
var brightnessByte = (byte)((float)i / (width - 1) * 255);
|
||||
data[i] = new Rgba32(brightnessByte, brightnessByte, brightnessByte);
|
||||
}
|
||||
gradientTexture.SetData(new TextureUpload(data));
|
||||
gradientTexture.SetData(new TextureUpload(new RawTextureRgba32(width, 1, data)));
|
||||
|
||||
SpriteText[] text = new SpriteText[6];
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace osu.Framework.Tests.Visual
|
||||
var image = t.Result;
|
||||
|
||||
var tex = new Texture(image.Width, image.Height);
|
||||
tex.SetData(new TextureUpload(new RawTexture(image)));
|
||||
tex.SetData(new TextureUpload(new RawTextureImage(image)));
|
||||
|
||||
display.Texture = tex;
|
||||
}));
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.ES30;
|
||||
|
||||
@@ -60,7 +61,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
|
||||
if (withTexture)
|
||||
{
|
||||
Texture = new TextureGLSingle(1, 1, true, filteringMode);
|
||||
Texture.SetData(new TextureUpload(Array.Empty<byte>()));
|
||||
Texture.SetData(new TextureUpload(new RawTextureRgba32(0, 0)));
|
||||
Texture.Upload();
|
||||
|
||||
Bind();
|
||||
@@ -77,7 +78,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
|
||||
private Vector2 size = Vector2.One;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the size of the texture of this framebuffer.
|
||||
/// Sets the size of the texture of this frame buffer.
|
||||
/// </summary>
|
||||
public Vector2 Size
|
||||
{
|
||||
@@ -90,7 +91,7 @@ namespace osu.Framework.Graphics.OpenGL.Buffers
|
||||
|
||||
Texture.Width = (int)Math.Ceiling(size.X);
|
||||
Texture.Height = (int)Math.Ceiling(size.Y);
|
||||
Texture.SetData(new TextureUpload(Array.Empty<byte>()));
|
||||
Texture.SetData(new TextureUpload(new RawTextureRgba32(0, 0)));
|
||||
Texture.Upload();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using OpenTK.Graphics.ES30;
|
||||
using osu.Framework.Statistics;
|
||||
using osu.Framework.Graphics.Colour;
|
||||
using osu.Framework.Graphics.OpenGL.Vertices;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.OpenGL.Textures
|
||||
@@ -325,30 +324,9 @@ namespace osu.Framework.Graphics.OpenGL.Textures
|
||||
{
|
||||
while (uploadQueue.TryDequeue(out TextureUpload upload))
|
||||
{
|
||||
if (upload.ImageData != null)
|
||||
{
|
||||
fixed (Rgba32* ptr = &MemoryMarshal.GetReference(upload.ImageData.GetPixelSpan()))
|
||||
doUpload(upload, (IntPtr)ptr);
|
||||
didUpload = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IntPtr dataPointer;
|
||||
if (upload.Data.Length == 0)
|
||||
{
|
||||
dataPointer = IntPtr.Zero;
|
||||
doUpload(upload, dataPointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
GCHandle h0 = GCHandle.Alloc(upload.Data, GCHandleType.Pinned);
|
||||
dataPointer = h0.AddrOfPinnedObject();
|
||||
doUpload(upload, dataPointer);
|
||||
didUpload = true;
|
||||
h0.Free();
|
||||
}
|
||||
}
|
||||
|
||||
fixed (Rgba32* ptr = &MemoryMarshal.GetReference(upload.Data))
|
||||
doUpload(upload, (IntPtr)ptr);
|
||||
didUpload = true;
|
||||
upload.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using System;
|
||||
using OpenTK.Graphics.ES30;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.OpenGL.Textures
|
||||
@@ -30,27 +29,13 @@ namespace osu.Framework.Graphics.OpenGL.Textures
|
||||
/// </summary>
|
||||
public RectangleI Bounds;
|
||||
|
||||
/// <summary>
|
||||
/// The upload data.
|
||||
/// </summary>
|
||||
public readonly byte[] Data;
|
||||
|
||||
public Image<Rgba32> ImageData;
|
||||
public ReadOnlySpan<Rgba32> Data => texture.GetImageData();
|
||||
|
||||
/// <summary>
|
||||
/// The backing texture. A handle is kept to avoid early GC.
|
||||
/// </summary>
|
||||
private readonly RawTexture texture;
|
||||
|
||||
/// <summary>
|
||||
/// Create an upload with arbitrary raw data.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
public TextureUpload(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an upload from a <see cref="RawTexture"/>. This is the preferred method.
|
||||
/// </summary>
|
||||
@@ -58,9 +43,6 @@ namespace osu.Framework.Graphics.OpenGL.Textures
|
||||
public TextureUpload(RawTexture texture)
|
||||
{
|
||||
this.texture = texture;
|
||||
|
||||
ImageData = texture.ImageData;
|
||||
Data = texture.Data;
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
@@ -20,6 +20,7 @@ using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Input.EventArgs;
|
||||
using osu.Framework.Input.States;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.Performance
|
||||
{
|
||||
@@ -37,7 +38,7 @@ namespace osu.Framework.Graphics.Performance
|
||||
private const float alpha_when_active = 0.75f;
|
||||
|
||||
private readonly TimeBar[] timeBars;
|
||||
private readonly BufferStack<byte> textureBufferStack;
|
||||
private readonly BufferStack<Rgba32> textureBufferStack;
|
||||
|
||||
private static readonly Color4[] garbage_collect_colors = { Color4.Green, Color4.Yellow, Color4.Red };
|
||||
private readonly PerformanceMonitor monitor;
|
||||
@@ -228,29 +229,29 @@ namespace osu.Framework.Graphics.Performance
|
||||
}
|
||||
};
|
||||
|
||||
textureBufferStack = new BufferStack<byte>(timeBars.Length * WIDTH);
|
||||
textureBufferStack = new BufferStack<Rgba32>(timeBars.Length * WIDTH);
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
//initialise background
|
||||
byte[] column = new byte[HEIGHT * 4];
|
||||
byte[] fullBackground = new byte[WIDTH * HEIGHT * 4];
|
||||
Rgba32[] column = new Rgba32[HEIGHT];
|
||||
Rgba32[] fullBackground = new Rgba32[WIDTH * HEIGHT];
|
||||
|
||||
addArea(null, null, HEIGHT, column, amount_ms_steps);
|
||||
|
||||
for (int i = 0; i < HEIGHT; i++)
|
||||
for (int k = 0; k < WIDTH; k++)
|
||||
Buffer.BlockCopy(column, i * 4, fullBackground, i * WIDTH * 4 + k * 4, 4);
|
||||
fullBackground[k] = column[i];
|
||||
|
||||
addArea(null, null, HEIGHT, column, amount_count_steps);
|
||||
|
||||
counterBarBackground?.Texture.SetData(new TextureUpload(column));
|
||||
counterBarBackground?.Texture.SetData(new TextureUpload(new RawTextureRgba32(1, HEIGHT, column)));
|
||||
Schedule(() =>
|
||||
{
|
||||
foreach (var t in timeBars)
|
||||
t.Sprite.Texture.SetData(new TextureUpload(fullBackground));
|
||||
t.Sprite.Texture.SetData(new TextureUpload(new RawTextureRgba32(WIDTH, HEIGHT, fullBackground)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -348,7 +349,8 @@ namespace osu.Framework.Graphics.Performance
|
||||
private void applyFrameTime(FrameStatistics frame)
|
||||
{
|
||||
TimeBar timeBar = timeBars[timeBarIndex];
|
||||
TextureUpload upload = new TextureUpload(new RawTexture(1, HEIGHT, textureBufferStack))
|
||||
var raw = new RawTextureBufferStack(1, HEIGHT, textureBufferStack);
|
||||
TextureUpload upload = new TextureUpload(raw)
|
||||
{
|
||||
Bounds = new RectangleI(timeBarX, 0, 1, HEIGHT)
|
||||
};
|
||||
@@ -356,8 +358,8 @@ namespace osu.Framework.Graphics.Performance
|
||||
int currentHeight = HEIGHT;
|
||||
|
||||
for (int i = 0; i < FrameStatistics.NUM_PERFORMANCE_COLLECTION_TYPES; i++)
|
||||
currentHeight = addArea(frame, (PerformanceCollectionType)i, currentHeight, upload.Data, amount_ms_steps);
|
||||
addArea(frame, null, currentHeight, upload.Data, amount_ms_steps);
|
||||
currentHeight = addArea(frame, (PerformanceCollectionType)i, currentHeight, raw.Data, amount_ms_steps);
|
||||
addArea(frame, null, currentHeight, raw.Data, amount_ms_steps);
|
||||
|
||||
timeBar.Sprite.Texture.SetData(upload);
|
||||
|
||||
@@ -447,9 +449,9 @@ namespace osu.Framework.Graphics.Performance
|
||||
}
|
||||
}
|
||||
|
||||
private int addArea(FrameStatistics frame, PerformanceCollectionType? frameTimeType, int currentHeight, byte[] textureData, int amountSteps)
|
||||
private int addArea(FrameStatistics frame, PerformanceCollectionType? frameTimeType, int currentHeight, Rgba32[] textureData, int amountSteps)
|
||||
{
|
||||
Trace.Assert(textureData.Length >= HEIGHT * 4, $"textureData is too small ({textureData.Length}) to hold area data.");
|
||||
Trace.Assert(textureData.Length >= HEIGHT, $"textureData is too small ({textureData.Length}) to hold area data.");
|
||||
|
||||
int drawHeight;
|
||||
|
||||
@@ -480,11 +482,10 @@ namespace osu.Framework.Graphics.Performance
|
||||
else if (acceptableRange)
|
||||
brightnessAdjust *= 0.8f;
|
||||
|
||||
int index = i * 4;
|
||||
textureData[index] = (byte)(255 * col.R * brightnessAdjust);
|
||||
textureData[index + 1] = (byte)(255 * col.G * brightnessAdjust);
|
||||
textureData[index + 2] = (byte)(255 * col.B * brightnessAdjust);
|
||||
textureData[index + 3] = (byte)(255 * col.A);
|
||||
textureData[i].R= (byte)(255 * col.R * brightnessAdjust);
|
||||
textureData[i].G= (byte)(255 * col.G * brightnessAdjust);
|
||||
textureData[i].B= (byte)(255 * col.B * brightnessAdjust);
|
||||
textureData[i].A= (byte)(255 * col.A);
|
||||
|
||||
currentHeight--;
|
||||
}
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-framework/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using osu.Framework.Allocation;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using PixelFormat = OpenTK.Graphics.ES30.PixelFormat;
|
||||
|
||||
namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
/// <summary>
|
||||
/// Texture data in a raw byte format.
|
||||
/// Texture data in a raw Rgba32 format.
|
||||
/// </summary>
|
||||
public class RawTexture : IDisposable
|
||||
public abstract class RawTexture : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The width of the texture data.
|
||||
@@ -30,85 +27,10 @@ namespace osu.Framework.Graphics.Textures
|
||||
/// </summary>
|
||||
public readonly PixelFormat PixelFormat = PixelFormat.Rgba;
|
||||
|
||||
/// <summary>
|
||||
/// The texture data.
|
||||
/// </summary>
|
||||
public byte[] Data;
|
||||
|
||||
private readonly BufferStack<byte> bufferStack;
|
||||
|
||||
/// <summary>
|
||||
/// Create a raw texture from an arbitrary image stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The image content.</param>
|
||||
public RawTexture(Stream stream) : this(Image.Load(stream))
|
||||
{
|
||||
}
|
||||
|
||||
public RawTexture(Image<Rgba32> image)
|
||||
{
|
||||
ImageData = image;
|
||||
Width = ImageData.Width;
|
||||
Height = ImageData.Height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="bufferStack">The buffer stack to retrieve the byte[] from.</param>
|
||||
public RawTexture(int width, int height, BufferStack<byte> bufferStack = null)
|
||||
{
|
||||
int size = width * height * 4;
|
||||
|
||||
Width = width;
|
||||
Height = height;
|
||||
|
||||
if (bufferStack != null)
|
||||
{
|
||||
this.bufferStack = bufferStack;
|
||||
Data = this.bufferStack.ReserveBuffer(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = new byte[size];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the texture.</param>
|
||||
/// <param name="height">The heightof the texture.</param>
|
||||
/// <param name="data">The raw texture data.</param>
|
||||
public RawTexture(int width, int height, byte[] data)
|
||||
{
|
||||
int size = width * height * 4;
|
||||
|
||||
if (size != data.Length)
|
||||
throw new InvalidOperationException("Provided data does not match dimensions");
|
||||
|
||||
Data = data;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
#region IDisposable Support
|
||||
|
||||
private bool disposed;
|
||||
|
||||
public Image<Rgba32> ImageData;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
ImageData?.Dispose();
|
||||
|
||||
if (!disposed)
|
||||
{
|
||||
disposed = true;
|
||||
bufferStack?.FreeBuffer(Data);
|
||||
}
|
||||
}
|
||||
|
||||
~RawTexture()
|
||||
@@ -123,5 +45,7 @@ namespace osu.Framework.Graphics.Textures
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public abstract ReadOnlySpan<Rgba32> GetImageData();
|
||||
}
|
||||
}
|
||||
|
||||
28
osu.Framework/Graphics/Textures/RawTextureBufferStack.cs
Normal file
28
osu.Framework/Graphics/Textures/RawTextureBufferStack.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using osu.Framework.Allocation;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
public class RawTextureBufferStack : RawTextureRgba32
|
||||
{
|
||||
private readonly BufferStack<Rgba32> bufferStack;
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="bufferStack">The buffer stack to retrieve the Rgba32[] from.</param>
|
||||
public RawTextureBufferStack(int width, int height, BufferStack<Rgba32> bufferStack)
|
||||
: base(width, height, bufferStack.ReserveBuffer(width * height))
|
||||
{
|
||||
this.bufferStack = bufferStack;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
bufferStack?.FreeBuffer(Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
osu.Framework/Graphics/Textures/RawTextureImage.cs
Normal file
37
osu.Framework/Graphics/Textures/RawTextureImage.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
public class RawTextureImage : RawTexture
|
||||
{
|
||||
public readonly Image<Rgba32> Data;
|
||||
|
||||
/// <summary>
|
||||
/// Create a raw texture from an arbitrary image stream.
|
||||
/// </summary>
|
||||
/// <param name="stream">The image content.</param>
|
||||
public RawTextureImage(Stream stream)
|
||||
: this(Image.Load(stream))
|
||||
{
|
||||
}
|
||||
|
||||
public RawTextureImage(Image<Rgba32> data)
|
||||
{
|
||||
Data = data;
|
||||
Width = Data.Width;
|
||||
Height = Data.Height;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
Data.Dispose();
|
||||
}
|
||||
|
||||
public override ReadOnlySpan<Rgba32> GetImageData() => Data.GetPixelSpan();
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace osu.Framework.Graphics.Textures
|
||||
using (var stream = store.GetStream(name))
|
||||
{
|
||||
if (stream != null)
|
||||
return new RawTexture(stream);
|
||||
return new RawTextureImage(stream);
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
49
osu.Framework/Graphics/Textures/RawTextureRgba32.cs
Normal file
49
osu.Framework/Graphics/Textures/RawTextureRgba32.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using osu.Framework.Allocation;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
public class RawTextureRgba32 : RawTexture
|
||||
{
|
||||
/// <summary>
|
||||
/// The texture data.
|
||||
/// </summary>
|
||||
public readonly Rgba32[] Data;
|
||||
|
||||
/// <summary>
|
||||
/// Create an empty raw texture with an optional <see cref="BufferStack{T}"/>. backing.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The raw texture data.</param>
|
||||
public RawTextureRgba32(int width, int height, Rgba32[] data = null)
|
||||
{
|
||||
if (data == null)
|
||||
data = new Rgba32[width * height];
|
||||
|
||||
if (width * height != data.Length)
|
||||
throw new InvalidOperationException("Provided data does not match dimensions");
|
||||
|
||||
Data = data;
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a raw texture with arbitrary raw data.
|
||||
/// Note that this method requires a memory copy operation to convert from <see cref="Byte"/> to <see cref="Rgba32"/>.
|
||||
/// Where possible, use <see cref="RawTextureRgba32"/> instead.
|
||||
/// </summary>
|
||||
/// <param name="width">The width of the texture.</param>
|
||||
/// <param name="height">The height of the texture.</param>
|
||||
/// <param name="data">The raw texture data.</param>
|
||||
internal RawTextureRgba32(int width, int height, byte[] data)
|
||||
: this(width, height, Unsafe.As<Rgba32[]>(data))
|
||||
{
|
||||
}
|
||||
|
||||
public override ReadOnlySpan<Rgba32> GetImageData() => new Span<Rgba32>(Data);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using OpenTK.Graphics.ES30;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.Primitives;
|
||||
using osu.Framework.Logging;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
@@ -69,9 +70,9 @@ namespace osu.Framework.Graphics.Textures
|
||||
{
|
||||
// add an empty white rect to use for solid box drawing (shader optimisation).
|
||||
// see Texture.WhitePixel for usage.
|
||||
var raw = new RawTexture(whiteTex.Width, whiteTex.Height);
|
||||
var raw = new RawTextureRgba32(whiteTex.Width, whiteTex.Height);
|
||||
for (int i = 0; i < raw.Data.Length; i++)
|
||||
raw.Data[i] = 255;
|
||||
raw.Data[i] = Rgba32.White;
|
||||
whiteTex.SetData(new TextureUpload(raw));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ namespace osu.Framework.Graphics.Textures
|
||||
|
||||
try
|
||||
{
|
||||
RawTexture data = new RawTexture(stream);
|
||||
RawTexture data = new RawTextureImage(stream);
|
||||
Texture tex = atlas == null ? new Texture(data.Width, data.Height) : new Texture(atlas.Add(data.Width, data.Height));
|
||||
tex.SetData(new TextureUpload(data.Data));
|
||||
tex.SetData(new TextureUpload(data));
|
||||
return tex;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
@@ -67,7 +67,7 @@ namespace osu.Framework.Graphics.Textures
|
||||
|
||||
Texture tex = atlas == null ? new Texture(width, height) : new Texture(atlas.Add(width, height));
|
||||
|
||||
var upload = new TextureUpload(data) { Format = format };
|
||||
var upload = new TextureUpload(new RawTextureRgba32(width, height, data)) { Format = format };
|
||||
tex.SetData(upload);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Logging;
|
||||
using SixLabors.ImageSharp.Advanced;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace osu.Framework.IO.Stores
|
||||
{
|
||||
@@ -25,7 +25,7 @@ namespace osu.Framework.IO.Stores
|
||||
|
||||
protected BitmapFont Font => completionSource.Task.Result;
|
||||
|
||||
private readonly TimedExpiryCache<int, RawTexture> texturePages = new TimedExpiryCache<int, RawTexture>();
|
||||
private readonly TimedExpiryCache<int, RawTextureImage> texturePages = new TimedExpiryCache<int, RawTextureImage>();
|
||||
|
||||
private readonly TaskCompletionSource<BitmapFont> completionSource = new TaskCompletionSource<BitmapFont>();
|
||||
|
||||
@@ -91,82 +91,40 @@ namespace osu.Framework.IO.Stores
|
||||
|
||||
private RawTexture loadCharacter(Character c)
|
||||
{
|
||||
RawTexture page = getTexturePage(c.TexturePage);
|
||||
var page = getTexturePage(c.TexturePage);
|
||||
loadedGlyphCount++;
|
||||
|
||||
int width = c.Bounds.Width + c.Offset.X + 1;
|
||||
int height = c.Bounds.Height + c.Offset.Y + 1;
|
||||
int length = width * height * 4;
|
||||
byte[] pixels = new byte[length];
|
||||
int length = width * height;
|
||||
|
||||
var pixels = new Rgba32[length];
|
||||
|
||||
var span = page.GetImageData();
|
||||
|
||||
if (page.ImageData != null)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
var span = page.ImageData.GetPixelSpan();
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int dest = y * width + x;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int desti = y * width * 4 + x * 4;
|
||||
if (x >= c.Offset.X && y >= c.Offset.Y
|
||||
&& x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
|
||||
{
|
||||
int srci = (c.Bounds.Y + y - c.Offset.Y) * page.Width + (c.Bounds.X + x - c.Offset.X);
|
||||
var col = span[srci];
|
||||
pixels[desti] = col.R;
|
||||
pixels[desti + 1] = col.G;
|
||||
pixels[desti + 2] = col.B;
|
||||
pixels[desti + 3] = col.A;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels[desti] = 255;
|
||||
pixels[desti + 1] = 255;
|
||||
pixels[desti + 2] = 255;
|
||||
pixels[desti + 3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0; x < width; x++)
|
||||
{
|
||||
int desti = y * width * 4 + x * 4;
|
||||
if (x >= c.Offset.X && y >= c.Offset.Y
|
||||
&& x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
|
||||
{
|
||||
int srci = (c.Bounds.Y + y - c.Offset.Y) * page.Width * 4
|
||||
+ (c.Bounds.X + x - c.Offset.X) * 4;
|
||||
pixels[desti] = page.Data[srci];
|
||||
pixels[desti + 1] = page.Data[srci + 1];
|
||||
pixels[desti + 2] = page.Data[srci + 2];
|
||||
pixels[desti + 3] = page.Data[srci + 3];
|
||||
}
|
||||
else
|
||||
{
|
||||
pixels[desti] = 255;
|
||||
pixels[desti + 1] = 255;
|
||||
pixels[desti + 2] = 255;
|
||||
pixels[desti + 3] = 0;
|
||||
}
|
||||
}
|
||||
if (x >= c.Offset.X && y >= c.Offset.Y && x - c.Offset.X < c.Bounds.Width && y - c.Offset.Y < c.Bounds.Height)
|
||||
pixels[dest] = span[(c.Bounds.Y + y - c.Offset.Y) * page.Width + (c.Bounds.X + x - c.Offset.X)];
|
||||
else
|
||||
pixels[dest] = new Rgba32(255, 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new RawTexture(width, height, pixels);
|
||||
return new RawTextureRgba32(width, height, pixels);
|
||||
}
|
||||
|
||||
private RawTexture getTexturePage(int texturePage)
|
||||
private RawTextureImage getTexturePage(int texturePage)
|
||||
{
|
||||
if (!texturePages.TryGetValue(texturePage, out RawTexture t))
|
||||
if (!texturePages.TryGetValue(texturePage, out RawTextureImage t))
|
||||
{
|
||||
loadedPageCount++;
|
||||
using (var stream = store.GetStream($@"{assetName}_{texturePage.ToString().PadLeft((Font.Pages.Length - 1).ToString().Length, '0')}.png"))
|
||||
texturePages.Add(texturePage, t = new RawTexture(stream));
|
||||
texturePages.Add(texturePage, t = new RawTextureImage(stream));
|
||||
}
|
||||
|
||||
return t;
|
||||
|
||||
Reference in New Issue
Block a user