Show More
Commit Description:
Rename constant to something clearer.
Commit Description:
Rename constant to something clearer.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/TextureCube.cs
409 lines | 7.6 KiB | text/x-csharp | CSharpLexer
409 lines | 7.6 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
r690 | * Copyright 2009-2022 Ethan Lee and the MonoGame Team | |||
r0 | * | |||
* Released under the Microsoft Public License. | ||||
* See LICENSE for details. | ||||
*/ | ||||
#endregion | ||||
#region Using Statements | ||||
using System; | ||||
r690 | using System.IO; | |||
r0 | using System.Runtime.InteropServices; | |||
#endregion | ||||
namespace Microsoft.Xna.Framework.Graphics | ||||
{ | ||||
public class TextureCube : Texture | ||||
{ | ||||
#region Public Properties | ||||
/// <summary> | ||||
/// Gets the width and height of the cube map face in pixels. | ||||
/// </summary> | ||||
/// <value>The width and height of a cube map face in pixels.</value> | ||||
public int Size | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
#endregion | ||||
#region Public Constructor | ||||
public TextureCube( | ||||
GraphicsDevice graphicsDevice, | ||||
int size, | ||||
bool mipMap, | ||||
SurfaceFormat format | ||||
) { | ||||
if (graphicsDevice == null) | ||||
{ | ||||
throw new ArgumentNullException("graphicsDevice"); | ||||
} | ||||
GraphicsDevice = graphicsDevice; | ||||
Size = size; | ||||
LevelCount = mipMap ? CalculateMipLevels(size) : 1; | ||||
// TODO: Use QueryRenderTargetFormat! | ||||
r690 | if (this is IRenderTarget) | |||
r0 | { | |||
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; | ||||
} | ||||
r0 | } | |||
else | ||||
{ | ||||
Format = format; | ||||
} | ||||
r690 | texture = FNA3D.FNA3D_CreateTextureCube( | |||
GraphicsDevice.GLDevice, | ||||
r0 | Format, | |||
Size, | ||||
LevelCount, | ||||
r690 | (byte) ((this is IRenderTarget) ? 1 : 0) | |||
r0 | ); | |||
} | ||||
#endregion | ||||
#region Public SetData Methods | ||||
public void SetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
T[] data | ||||
) where T : struct { | ||||
SetData( | ||||
cubeMapFace, | ||||
0, | ||||
null, | ||||
data, | ||||
0, | ||||
data.Length | ||||
); | ||||
} | ||||
public void SetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
SetData( | ||||
cubeMapFace, | ||||
0, | ||||
null, | ||||
data, | ||||
startIndex, | ||||
elementCount | ||||
); | ||||
} | ||||
public void SetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
int level, | ||||
Rectangle? rect, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
if (data == null) | ||||
{ | ||||
throw new ArgumentNullException("data"); | ||||
} | ||||
int xOffset, yOffset, width, height; | ||||
if (rect.HasValue) | ||||
{ | ||||
xOffset = rect.Value.X; | ||||
yOffset = rect.Value.Y; | ||||
width = rect.Value.Width; | ||||
height = rect.Value.Height; | ||||
} | ||||
else | ||||
{ | ||||
xOffset = 0; | ||||
yOffset = 0; | ||||
width = Math.Max(1, Size >> level); | ||||
height = Math.Max(1, Size >> level); | ||||
} | ||||
int elementSizeInBytes = Marshal.SizeOf(typeof(T)); | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
r690 | FNA3D.FNA3D_SetTextureDataCube( | |||
GraphicsDevice.GLDevice, | ||||
r0 | texture, | |||
xOffset, | ||||
yOffset, | ||||
width, | ||||
height, | ||||
cubeMapFace, | ||||
level, | ||||
handle.AddrOfPinnedObject() + startIndex * elementSizeInBytes, | ||||
elementCount * elementSizeInBytes | ||||
); | ||||
handle.Free(); | ||||
} | ||||
public void SetDataPointerEXT( | ||||
CubeMapFace cubeMapFace, | ||||
int level, | ||||
Rectangle? rect, | ||||
IntPtr data, | ||||
int dataLength | ||||
) { | ||||
if (data == IntPtr.Zero) | ||||
{ | ||||
throw new ArgumentNullException("data"); | ||||
} | ||||
int xOffset, yOffset, width, height; | ||||
if (rect.HasValue) | ||||
{ | ||||
xOffset = rect.Value.X; | ||||
yOffset = rect.Value.Y; | ||||
width = rect.Value.Width; | ||||
height = rect.Value.Height; | ||||
} | ||||
else | ||||
{ | ||||
xOffset = 0; | ||||
yOffset = 0; | ||||
width = Math.Max(1, Size >> level); | ||||
height = Math.Max(1, Size >> level); | ||||
} | ||||
r690 | FNA3D.FNA3D_SetTextureDataCube( | |||
GraphicsDevice.GLDevice, | ||||
r0 | texture, | |||
xOffset, | ||||
yOffset, | ||||
width, | ||||
height, | ||||
cubeMapFace, | ||||
level, | ||||
data, | ||||
dataLength | ||||
); | ||||
} | ||||
#endregion | ||||
#region Public GetData Method | ||||
public void GetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
T[] data | ||||
) where T : struct { | ||||
GetData( | ||||
cubeMapFace, | ||||
0, | ||||
null, | ||||
data, | ||||
0, | ||||
data.Length | ||||
); | ||||
} | ||||
public void GetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
GetData( | ||||
cubeMapFace, | ||||
0, | ||||
null, | ||||
data, | ||||
startIndex, | ||||
elementCount | ||||
); | ||||
} | ||||
public void GetData<T>( | ||||
CubeMapFace cubeMapFace, | ||||
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 = Size >> level; | ||||
subH = Size >> level; | ||||
} | ||||
else | ||||
{ | ||||
subX = rect.Value.X; | ||||
subY = rect.Value.Y; | ||||
subW = rect.Value.Width; | ||||
subH = rect.Value.Height; | ||||
} | ||||
r690 | int elementSizeInBytes = Marshal.SizeOf(typeof(T)); | |||
ValidateGetDataFormat(Format, elementSizeInBytes); | ||||
r0 | GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | |||
r690 | FNA3D.FNA3D_GetTextureDataCube( | |||
GraphicsDevice.GLDevice, | ||||
r0 | texture, | |||
subX, | ||||
subY, | ||||
subW, | ||||
subH, | ||||
r690 | cubeMapFace, | |||
level, | ||||
handle.AddrOfPinnedObject() + (startIndex * elementSizeInBytes), | ||||
elementCount * elementSizeInBytes | ||||
r0 | ); | |||
handle.Free(); | ||||
} | ||||
#endregion | ||||
r690 | ||||
#region Public Static TextureCube Extensions | ||||
public static TextureCube DDSFromStreamEXT( | ||||
GraphicsDevice graphicsDevice, | ||||
Stream stream | ||||
) { | ||||
TextureCube result; | ||||
// Begin BinaryReader, ignoring a tab! | ||||
using (BinaryReader reader = new BinaryReader(stream)) | ||||
{ | ||||
int width, height, levels; | ||||
bool isCube; | ||||
SurfaceFormat format; | ||||
Texture.ParseDDS( | ||||
reader, | ||||
out format, | ||||
out width, | ||||
out height, | ||||
out levels, | ||||
out isCube | ||||
); | ||||
if (!isCube) | ||||
{ | ||||
throw new FormatException("This file does not contain cube data!"); | ||||
} | ||||
// Allocate/Load texture | ||||
result = new TextureCube( | ||||
graphicsDevice, | ||||
width, | ||||
levels > 1, | ||||
format | ||||
); | ||||
byte[] tex = null; | ||||
if ( stream is MemoryStream && | ||||
((MemoryStream) stream).TryGetBuffer(out tex) ) | ||||
{ | ||||
for (int face = 0; face < 6; face += 1) | ||||
{ | ||||
for (int i = 0; i < levels; i += 1) | ||||
{ | ||||
int mipLevelSize = Texture.CalculateDDSLevelSize( | ||||
width >> i, | ||||
width >> i, | ||||
format | ||||
); | ||||
result.SetData( | ||||
(CubeMapFace) face, | ||||
i, | ||||
null, | ||||
tex, | ||||
(int) stream.Seek(0, SeekOrigin.Current), | ||||
mipLevelSize | ||||
); | ||||
stream.Seek( | ||||
mipLevelSize, | ||||
SeekOrigin.Current | ||||
); | ||||
} | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
for (int face = 0; face < 6; face += 1) | ||||
{ | ||||
for (int i = 0; i < levels; i += 1) | ||||
{ | ||||
tex = reader.ReadBytes(Texture.CalculateDDSLevelSize( | ||||
width >> i, | ||||
width >> i, | ||||
format | ||||
)); | ||||
result.SetData( | ||||
(CubeMapFace) face, | ||||
i, | ||||
null, | ||||
tex, | ||||
0, | ||||
tex.Length | ||||
); | ||||
} | ||||
} | ||||
} | ||||
// End BinaryReader | ||||
} | ||||
// Finally. | ||||
return result; | ||||
} | ||||
#endregion | ||||
r0 | } | |||
} | ||||