Show More
Commit Description:
Add basic infrastructure to store and display visitor count....
Commit Description:
Add basic infrastructure to store and display visitor count. May eventually move to simulating visitors as entities. We'll see.
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/Texture2D.cs
616 lines | 11.6 KiB | text/x-csharp | CSharpLexer
Early working version (including all dependencies, lol).
r0 #region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
Upgrade FNA to 22.12...
r690 * Copyright 2009-2022 Ethan Lee and the MonoGame Team
Early working version (including all dependencies, lol).
r0 *
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.IO;
using System.Runtime.InteropServices;
#endregion
namespace Microsoft.Xna.Framework.Graphics
{
public class Texture2D : Texture
{
#region Public Properties
public int Width
{
get;
private set;
}
public int Height
{
get;
private set;
}
public Rectangle Bounds
{
get
{
return new Rectangle(0, 0, Width, Height);
}
}
#endregion
#region Public Constructors
public Texture2D(
GraphicsDevice graphicsDevice,
int width,
int height
) : this(
graphicsDevice,
width,
height,
false,
SurfaceFormat.Color
) {
}
public Texture2D(
GraphicsDevice graphicsDevice,
int width,
int height,
bool mipMap,
SurfaceFormat format
) {
if (graphicsDevice == null)
{
throw new ArgumentNullException("graphicsDevice");
}
GraphicsDevice = graphicsDevice;
Width = width;
Height = height;
LevelCount = mipMap ? CalculateMipLevels(width, height) : 1;
// TODO: Use QueryRenderTargetFormat!
Upgrade FNA to 22.12...
r690 if (this is IRenderTarget)
Early working version (including all dependencies, lol).
r0 {
Upgrade FNA to 22.12...
r690 if (format == SurfaceFormat.ColorSrgbEXT)
{
if (FNA3D.FNA3D_SupportsSRGBRenderTargets(GraphicsDevice.GLDevice) == 0)
{
// Renderable but not on this device
Format = SurfaceFormat.Color;
}
else
{
Format = format;
}
}
else if ( format != SurfaceFormat.Color &&
format != SurfaceFormat.Rgba1010102 &&
format != SurfaceFormat.Rg32 &&
format != SurfaceFormat.Rgba64 &&
format != SurfaceFormat.Single &&
format != SurfaceFormat.Vector2 &&
format != SurfaceFormat.Vector4 &&
format != SurfaceFormat.HalfSingle &&
format != SurfaceFormat.HalfVector2 &&
format != SurfaceFormat.HalfVector4 &&
format != SurfaceFormat.HdrBlendable )
{
// Not a renderable format period
Format = SurfaceFormat.Color;
}
else
{
Format = format;
}
Early working version (including all dependencies, lol).
r0 }
else
{
Format = format;
}
Upgrade FNA to 22.12...
r690 texture = FNA3D.FNA3D_CreateTexture2D(
GraphicsDevice.GLDevice,
Early working version (including all dependencies, lol).
r0 Format,
Width,
Height,
LevelCount,
Upgrade FNA to 22.12...
r690 (byte) ((this is IRenderTarget) ? 1 : 0)
Early working version (including all dependencies, lol).
r0 );
}
#endregion
#region Public SetData Methods
public void SetData<T>(T[] data) where T : struct
{
SetData(
0,
null,
data,
0,
data.Length
);
}
public void SetData<T>(
T[] data,
int startIndex,
int elementCount
) where T : struct {
SetData(
0,
null,
data,
startIndex,
elementCount
);
}
public void SetData<T>(
int level,
Rectangle? rect,
T[] data,
int startIndex,
int elementCount
) where T : struct {
if (data == null)
{
throw new ArgumentNullException("data");
}
Upgrade FNA to 22.12...
r690 if (startIndex < 0)
{
throw new ArgumentOutOfRangeException("startIndex");
}
if (data.Length < (elementCount + startIndex))
{
throw new ArgumentOutOfRangeException("elementCount");
}
Early working version (including all dependencies, lol).
r0
int x, y, w, h;
if (rect.HasValue)
{
x = rect.Value.X;
y = rect.Value.Y;
w = rect.Value.Width;
h = rect.Value.Height;
}
else
{
x = 0;
y = 0;
w = Math.Max(Width >> level, 1);
h = Math.Max(Height >> level, 1);
}
int elementSize = Marshal.SizeOf(typeof(T));
Upgrade FNA to 22.12...
r690 int requiredBytes = (w * h * GetFormatSize(Format)) / GetBlockSizeSquared(Format);
int availableBytes = elementCount * elementSize;
if (requiredBytes > availableBytes)
{
throw new ArgumentOutOfRangeException("rect", "The region you are trying to upload is larger than the amount of data you provided.");
}
Early working version (including all dependencies, lol).
r0 GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Upgrade FNA to 22.12...
r690 FNA3D.FNA3D_SetTextureData2D(
GraphicsDevice.GLDevice,
Early working version (including all dependencies, lol).
r0 texture,
x,
y,
w,
h,
level,
handle.AddrOfPinnedObject() + startIndex * elementSize,
elementCount * elementSize
);
handle.Free();
}
public void SetDataPointerEXT(
int level,
Rectangle? rect,
IntPtr data,
int dataLength
) {
if (data == IntPtr.Zero)
{
throw new ArgumentNullException("data");
}
int x, y, w, h;
if (rect.HasValue)
{
x = rect.Value.X;
y = rect.Value.Y;
w = rect.Value.Width;
h = rect.Value.Height;
}
else
{
x = 0;
y = 0;
w = Math.Max(Width >> level, 1);
h = Math.Max(Height >> level, 1);
}
Upgrade FNA to 22.12...
r690 FNA3D.FNA3D_SetTextureData2D(
GraphicsDevice.GLDevice,
Early working version (including all dependencies, lol).
r0 texture,
x,
y,
w,
h,
level,
data,
dataLength
);
}
#endregion
#region Public GetData Methods
public void GetData<T>(T[] data) where T : struct
{
GetData(
0,
null,
data,
0,
data.Length
);
}
public void GetData<T>(
T[] data,
int startIndex,
int elementCount
) where T : struct {
GetData(
0,
null,
data,
startIndex,
elementCount
);
}
public void GetData<T>(
int level,
Rectangle? rect,
T[] data,
int startIndex,
int elementCount
) where T : struct {
if (data == null || data.Length == 0)
{
throw new ArgumentException("data cannot be null");
}
if (data.Length < startIndex + elementCount)
{
throw new ArgumentException(
"The data passed has a length of " + data.Length.ToString() +
" but " + elementCount.ToString() + " pixels have been requested."
);
}
int subX, subY, subW, subH;
if (rect == null)
{
subX = 0;
subY = 0;
subW = Width >> level;
subH = Height >> level;
}
else
{
subX = rect.Value.X;
subY = rect.Value.Y;
subW = rect.Value.Width;
subH = rect.Value.Height;
}
Upgrade FNA to 22.12...
r690 int elementSizeInBytes = Marshal.SizeOf(typeof(T));
ValidateGetDataFormat(Format, elementSizeInBytes);
Early working version (including all dependencies, lol).
r0 GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
Upgrade FNA to 22.12...
r690 FNA3D.FNA3D_GetTextureData2D(
GraphicsDevice.GLDevice,
Early working version (including all dependencies, lol).
r0 texture,
subX,
subY,
subW,
subH,
Upgrade FNA to 22.12...
r690 level,
handle.AddrOfPinnedObject() + (startIndex * elementSizeInBytes),
elementCount * elementSizeInBytes
Early working version (including all dependencies, lol).
r0 );
handle.Free();
}
#endregion
#region Public Texture2D Save Methods
public void SaveAsJpeg(Stream stream, int width, int height)
{
Upgrade FNA to 22.12...
r690 int quality;
string qualityString = Environment.GetEnvironmentVariable("FNA_GRAPHICS_JPEG_SAVE_QUALITY");
if (string.IsNullOrEmpty(qualityString) || !int.TryParse(qualityString, out quality))
{
quality = 100; // FIXME: What does XNA pick for quality? -flibit
}
int len = Width * Height * GetFormatSize(Format);
IntPtr data = Marshal.AllocHGlobal(len);
FNA3D.FNA3D_GetTextureData2D(
GraphicsDevice.GLDevice,
texture,
0,
0,
Width,
height,
0,
data,
len
);
FNA3D.WriteJPGStream(
Early working version (including all dependencies, lol).
r0 stream,
Upgrade FNA to 22.12...
r690 Width,
Height,
Early working version (including all dependencies, lol).
r0 width,
height,
Upgrade FNA to 22.12...
r690 data,
quality
Early working version (including all dependencies, lol).
r0 );
Upgrade FNA to 22.12...
r690
Marshal.FreeHGlobal(data);
Early working version (including all dependencies, lol).
r0 }
public void SaveAsPng(Stream stream, int width, int height)
{
Upgrade FNA to 22.12...
r690 int len = Width * Height * GetFormatSize(Format);
IntPtr data = Marshal.AllocHGlobal(len);
FNA3D.FNA3D_GetTextureData2D(
GraphicsDevice.GLDevice,
texture,
0,
0,
Width,
height,
0,
data,
len
);
FNA3D.WritePNGStream(
Early working version (including all dependencies, lol).
r0 stream,
Upgrade FNA to 22.12...
r690 Width,
Height,
Early working version (including all dependencies, lol).
r0 width,
height,
data
);
Upgrade FNA to 22.12...
r690
Marshal.FreeHGlobal(data);
Early working version (including all dependencies, lol).
r0 }
#endregion
#region Public Static Texture2D Load Methods
public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
if (stream.CanSeek && stream.Position == stream.Length)
{
stream.Seek(0, SeekOrigin.Begin);
}
int width, height, len;
Upgrade FNA to 22.12...
r690 IntPtr pixels = FNA3D.ReadImageStream(
Early working version (including all dependencies, lol).
r0 stream,
out width,
out height,
out len
);
Texture2D result = new Texture2D(
graphicsDevice,
width,
height
);
result.SetDataPointerEXT(
0,
null,
pixels,
len
);
Upgrade FNA to 22.12...
r690
FNA3D.FNA3D_Image_Free(pixels);
Early working version (including all dependencies, lol).
r0 return result;
}
public static Texture2D FromStream(
GraphicsDevice graphicsDevice,
Stream stream,
int width,
int height,
bool zoom
) {
Upgrade FNA to 22.12...
r690 if (stream.CanSeek && stream.Position == stream.Length)
{
stream.Seek(0, SeekOrigin.Begin);
}
Early working version (including all dependencies, lol).
r0 int realWidth, realHeight, len;
Upgrade FNA to 22.12...
r690 IntPtr pixels = FNA3D.ReadImageStream(
Early working version (including all dependencies, lol).
r0 stream,
out realWidth,
out realHeight,
out len,
width,
height,
zoom
);
Texture2D result = new Texture2D(
graphicsDevice,
realWidth,
realHeight
);
result.SetDataPointerEXT(
0,
null,
pixels,
len
);
Upgrade FNA to 22.12...
r690
FNA3D.FNA3D_Image_Free(pixels);
Early working version (including all dependencies, lol).
r0 return result;
}
#endregion
#region Public Static Texture2D Extensions
Upgrade FNA to 22.12...
r690
Early working version (including all dependencies, lol).
r0 /// <summary>
/// Loads image data from a given stream.
/// </summary>
/// <remarks>
/// This is an extension of XNA 4 and is not compatible with XNA. It exists to help with dynamically reloading
/// textures while games are running. Games can use this method to read a stream into memory and then call
/// SetData on a texture with that data, rather than having to dispose the texture and recreate it entirely.
/// </remarks>
/// <param name="stream">The stream from which to read the image data.</param>
/// <param name="width">Outputs the width of the image.</param>
/// <param name="height">Outputs the height of the image.</param>
/// <param name="pixels">Outputs the pixel data of the image, in non-premultiplied RGBA format.</param>
/// <param name="requestedWidth">Preferred width of the resulting image data</param>
/// <param name="requestedHeight">Preferred height of the resulting image data</param>
/// <param name="zoom">false to maintain aspect ratio, true to crop image</param>
public static void TextureDataFromStreamEXT(
Stream stream,
out int width,
out int height,
out byte[] pixels,
int requestedWidth = -1,
int requestedHeight = -1,
bool zoom = false
) {
Upgrade FNA to 22.12...
r690 if (stream.CanSeek && stream.Position == stream.Length)
{
stream.Seek(0, SeekOrigin.Begin);
}
int len;
IntPtr pixPtr = FNA3D.ReadImageStream(
Early working version (including all dependencies, lol).
r0 stream,
out width,
out height,
Upgrade FNA to 22.12...
r690 out len,
Early working version (including all dependencies, lol).
r0 requestedWidth,
requestedHeight,
zoom
);
Upgrade FNA to 22.12...
r690
pixels = new byte[len];
Marshal.Copy(pixPtr, pixels, 0, len);
FNA3D.FNA3D_Image_Free(pixPtr);
Early working version (including all dependencies, lol).
r0 }
public static Texture2D DDSFromStreamEXT(
GraphicsDevice graphicsDevice,
Stream stream
) {
Texture2D result;
// Begin BinaryReader, ignoring a tab!
using (BinaryReader reader = new BinaryReader(stream))
{
Upgrade FNA to 22.12...
r690 int width, height, levels;
bool isCube;
SurfaceFormat format;
Texture.ParseDDS(
reader,
out format,
out width,
out height,
out levels,
out isCube
);
Early working version (including all dependencies, lol).
r0
Upgrade FNA to 22.12...
r690 if (isCube)
Early working version (including all dependencies, lol).
r0 {
Upgrade FNA to 22.12...
r690 throw new FormatException("This file contains cube map data!");
Early working version (including all dependencies, lol).
r0 }
// Allocate/Load texture
result = new Texture2D(
graphicsDevice,
width,
height,
levels > 1,
format
);
Upgrade FNA to 22.12...
r690
Early working version (including all dependencies, lol).
r0 byte[] tex = null;
if ( stream is MemoryStream &&
((MemoryStream) stream).TryGetBuffer(out tex) )
{
for (int i = 0; i < levels; i += 1)
{
Upgrade FNA to 22.12...
r690 int levelSize = Texture.CalculateDDSLevelSize(
width >> i,
height >> i,
format
);
Early working version (including all dependencies, lol).
r0 result.SetData(
i,
null,
tex,
(int) stream.Seek(0, SeekOrigin.Current),
levelSize
);
stream.Seek(
levelSize,
SeekOrigin.Current
);
}
}
else
{
for (int i = 0; i < levels; i += 1)
{
Upgrade FNA to 22.12...
r690 tex = reader.ReadBytes(Texture.CalculateDDSLevelSize(
width >> i,
height >> i,
format
));
Early working version (including all dependencies, lol).
r0 result.SetData(
i,
null,
tex,
0,
tex.Length
);
}
}
// End BinaryReader
}
// Finally.
return result;
}
#endregion
}
}