diff --git a/MonoGame.Framework/Graphics/GraphicsCapabilities.DirectX.cs b/MonoGame.Framework/Graphics/GraphicsCapabilities.DirectX.cs
index 4fa17cffd7e..a1378b5b5cc 100644
--- a/MonoGame.Framework/Graphics/GraphicsCapabilities.DirectX.cs
+++ b/MonoGame.Framework/Graphics/GraphicsCapabilities.DirectX.cs
@@ -25,6 +25,9 @@ private void PlatformInitialize(GraphicsDevice device)
SupportsTextureArrays = device.GraphicsProfile == GraphicsProfile.HiDef;
SupportsDepthClamp = device.GraphicsProfile == GraphicsProfile.HiDef;
SupportsVertexTextures = device.GraphicsProfile == GraphicsProfile.HiDef;
+ SupportsFloatTextures = true;
+ SupportsHalfFloatTextures = true;
+ SupportsNormalized = true;
SupportsInstancing = true;
diff --git a/MonoGame.Framework/Graphics/GraphicsCapabilities.OpenGL.cs b/MonoGame.Framework/Graphics/GraphicsCapabilities.OpenGL.cs
index d76d20fa702..b21ef766eb1 100644
--- a/MonoGame.Framework/Graphics/GraphicsCapabilities.OpenGL.cs
+++ b/MonoGame.Framework/Graphics/GraphicsCapabilities.OpenGL.cs
@@ -92,8 +92,14 @@ private void PlatformInitialize(GraphicsDevice device)
// sRGB
#if GLES
SupportsSRgb = GL.Extensions.Contains("GL_EXT_sRGB");
+ SupportsFloatTextures = GL.BoundApi == GL.RenderApi.ES && (device.glMajorVersion >= 3 || GL.Extensions.Contains("GL_EXT_color_buffer_float"));
+ SupportsHalfFloatTextures = GL.BoundApi == GL.RenderApi.ES && (device.glMajorVersion >= 3 || GL.Extensions.Contains("GL_EXT_color_buffer_half_float"));
+ SupportsNormalized = GL.BoundApi == GL.RenderApi.ES && (device.glMajorVersion >= 3 && GL.Extensions.Contains("GL_EXT_texture_norm16"));
#else
SupportsSRgb = GL.Extensions.Contains("GL_EXT_texture_sRGB") && GL.Extensions.Contains("GL_EXT_framebuffer_sRGB");
+ SupportsFloatTextures = GL.BoundApi == GL.RenderApi.GL && (device.glMajorVersion >= 3 || GL.Extensions.Contains("GL_ARB_texture_float"));
+ SupportsHalfFloatTextures = GL.BoundApi == GL.RenderApi.GL && (device.glMajorVersion >= 3 || GL.Extensions.Contains("GL_ARB_half_float_pixel"));;
+ SupportsNormalized = GL.BoundApi == GL.RenderApi.GL && (device.glMajorVersion >= 3 || GL.Extensions.Contains("GL_EXT_texture_norm16"));;
#endif
// TODO: Implement OpenGL support for texture arrays
@@ -107,11 +113,7 @@ private void PlatformInitialize(GraphicsDevice device)
GL.GetInteger((GetPName)GetParamName.MaxSamples, out _maxMultiSampleCount);
-#if GLES
- SupportsInstancing = false;
-#else
SupportsInstancing = GL.VertexAttribDivisor != null;
-#endif
}
}
diff --git a/MonoGame.Framework/Graphics/GraphicsCapabilities.cs b/MonoGame.Framework/Graphics/GraphicsCapabilities.cs
index 59a9dd23c74..9996c234bed 100644
--- a/MonoGame.Framework/Graphics/GraphicsCapabilities.cs
+++ b/MonoGame.Framework/Graphics/GraphicsCapabilities.cs
@@ -30,11 +30,11 @@ internal void Initialize(GraphicsDevice device)
///
internal bool SupportsTextureFilterAnisotropic { get; private set; }
- internal bool SupportsDepth24 { get; private set; }
+ internal bool SupportsDepth24 { get; private set; }
- internal bool SupportsPackedDepthStencil { get; private set; }
+ internal bool SupportsPackedDepthStencil { get; private set; }
- internal bool SupportsDepthNonLinear { get; private set; }
+ internal bool SupportsDepthNonLinear { get; private set; }
///
/// Gets the support for DXT1
@@ -69,13 +69,35 @@ internal void Initialize(GraphicsDevice device)
/// and texture sRGB are supported.
///
internal bool SupportsSRgb { get; private set; }
-
+
internal bool SupportsTextureArrays { get; private set; }
internal bool SupportsDepthClamp { get; private set; }
internal bool SupportsVertexTextures { get; private set; }
+ ///
+ /// True, if the underlying platform supports floating point textures.
+ /// For Direct3D platforms this is always true
.
+ /// For OpenGL Desktop platforms it is always true
.
+ /// For OpenGL Mobile platforms it requires `GL_EXT_color_buffer_float`.
+ /// If the requested format is not supported an NotSupportedException
+ /// will be thrown.
+ ///
+ internal bool SupportsFloatTextures { get; private set; }
+
+ ///
+ /// True, if the underlying platform supports half floating point textures.
+ /// For Direct3D platforms this is always true
.
+ /// For OpenGL Desktop platforms it is always true
.
+ /// For OpenGL Mobile platforms it requires `GL_EXT_color_buffer_half_float`.
+ /// If the requested format is not supported an NotSupportedException
+ /// will be thrown.
+ ///
+ internal bool SupportsHalfFloatTextures { get; private set; }
+
+ internal bool SupportsNormalized { get; private set; }
+
///
/// Gets the max texture anisotropy. This value typically lies
/// between 0 and 16, where 0 means anisotropic filtering is not
diff --git a/MonoGame.Framework/Graphics/GraphicsDevice.OpenGL.cs b/MonoGame.Framework/Graphics/GraphicsDevice.OpenGL.cs
index 9b6827190ec..d25a40f92c8 100644
--- a/MonoGame.Framework/Graphics/GraphicsDevice.OpenGL.cs
+++ b/MonoGame.Framework/Graphics/GraphicsDevice.OpenGL.cs
@@ -200,7 +200,7 @@ private void ApplyAttribs(Shader shader, int baseVertex)
// If instancing is not supported, but InstanceFrequency of the buffer is not zero, throw an exception
if (!GraphicsCapabilities.SupportsInstancing && vertexBufferBinding.InstanceFrequency > 0)
- throw new PlatformNotSupportedException("Instanced geometry drawing requires at least OpenGL 3.2. Try upgrading your graphics drivers.");
+ throw new PlatformNotSupportedException("Instanced geometry drawing requires at least OpenGL 3.2 or GLES 3.2. Try upgrading your graphics drivers.");
foreach (var element in attrInfo.Elements)
{
@@ -211,11 +211,9 @@ private void ApplyAttribs(Shader shader, int baseVertex)
vertexStride,
(IntPtr)(offset.ToInt64() + element.Offset));
-#if !(GLES || MONOMAC)
// only set the divisor if instancing is supported
if (GraphicsCapabilities.SupportsInstancing)
GL.VertexAttribDivisor(element.AttributeLocation, vertexBufferBinding.InstanceFrequency);
-#endif
GraphicsExtensions.CheckGLError();
}
@@ -1173,11 +1171,8 @@ private void PlatformDrawUserIndexedPrimitives(PrimitiveType primitiveType, T
private void PlatformDrawInstancedPrimitives(PrimitiveType primitiveType, int baseVertex, int startIndex, int primitiveCount, int instanceCount)
{
-#if GLES || MONOMAC
- throw new PlatformNotSupportedException("Instanced geometry drawing is not supported yet for GLES or MONOMAC.");
-#else
if (!GraphicsCapabilities.SupportsInstancing)
- throw new PlatformNotSupportedException("Instanced geometry drawing requires at least OpenGL 3.2. Try upgrading your graphics card drivers.");
+ throw new PlatformNotSupportedException("Instanced geometry drawing requires at least OpenGL 3.2 or GLES 3.2. Try upgrading your graphics card drivers.");
ApplyState(true);
var shortIndices = _indexBuffer.IndexElementSize == IndexElementSize.SixteenBits;
@@ -1196,7 +1191,6 @@ private void PlatformDrawInstancedPrimitives(PrimitiveType primitiveType, int ba
indexOffsetInBytes,
instanceCount);
GraphicsExtensions.CheckGLError();
-#endif
}
private void PlatformGetBackBufferData(Rectangle? rectangle, T[] data, int startIndex, int count) where T : struct
diff --git a/MonoGame.Framework/Graphics/GraphicsExtensions.cs b/MonoGame.Framework/Graphics/GraphicsExtensions.cs
index 2973042013f..16bb9a1de77 100644
--- a/MonoGame.Framework/Graphics/GraphicsExtensions.cs
+++ b/MonoGame.Framework/Graphics/GraphicsExtensions.cs
@@ -495,8 +495,8 @@ internal static int GetSwapInterval(this PresentInterval interval)
}
}
#endif
-
-
+
+ const SurfaceFormat InvalidFormat = (SurfaceFormat)int.MaxValue;
internal static void GetGLFormat (this SurfaceFormat format,
GraphicsDevice graphicsDevice,
out PixelInternalFormat glInternalFormat,
@@ -508,7 +508,15 @@ internal static void GetGLFormat (this SurfaceFormat format,
glType = PixelType.UnsignedByte;
var supportsSRgb = graphicsDevice.GraphicsCapabilities.SupportsSRgb;
-
+ var supportsS3tc = graphicsDevice.GraphicsCapabilities.SupportsS3tc;
+ var supportsPvrtc = graphicsDevice.GraphicsCapabilities.SupportsPvrtc;
+ var supportsEtc1 = graphicsDevice.GraphicsCapabilities.SupportsEtc1;
+ var supportsAtitc = graphicsDevice.GraphicsCapabilities.SupportsAtitc;
+ var supportsFloat = graphicsDevice.GraphicsCapabilities.SupportsFloatTextures;
+ var supportsHalfFloat = graphicsDevice.GraphicsCapabilities.SupportsHalfFloatTextures;
+ var supportsNormalized = graphicsDevice.GraphicsCapabilities.SupportsNormalized;
+ var isGLES2 = GL.BoundApi == GL.RenderApi.ES && graphicsDevice.glMajorVersion == 2;
+
switch (format) {
case SurfaceFormat.Color:
glInternalFormat = PixelInternalFormat.Rgba;
@@ -518,7 +526,7 @@ internal static void GetGLFormat (this SurfaceFormat format,
case SurfaceFormat.ColorSRgb:
if (!supportsSRgb)
goto case SurfaceFormat.Color;
- glInternalFormat = (PixelInternalFormat) 0x8C40; // PixelInternalFormat.Srgb;
+ glInternalFormat = PixelInternalFormat.Srgb;
glFormat = PixelFormat.Rgba;
glType = PixelType.UnsignedByte;
break;
@@ -546,8 +554,9 @@ internal static void GetGLFormat (this SurfaceFormat format,
glFormat = PixelFormat.Luminance;
glType = PixelType.UnsignedByte;
break;
-#if !IOS && !ANDROID && !ANGLE
case SurfaceFormat.Dxt1:
+ if (!supportsS3tc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbS3tcDxt1Ext;
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
@@ -558,10 +567,14 @@ internal static void GetGLFormat (this SurfaceFormat format,
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.Dxt1a:
+ if (!supportsS3tc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.Dxt3:
+ if (!supportsS3tc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
@@ -572,6 +585,8 @@ internal static void GetGLFormat (this SurfaceFormat format,
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.Dxt5:
+ if (!supportsS3tc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
@@ -581,14 +596,24 @@ internal static void GetGLFormat (this SurfaceFormat format,
glInternalFormat = PixelInternalFormat.CompressedSrgbAlphaS3tcDxt5Ext;
glFormat = (PixelFormat)GLPixelFormat.CompressedTextureFormats;
break;
-
- case SurfaceFormat.Single:
- glInternalFormat = PixelInternalFormat.R32f;
- glFormat = PixelFormat.Red;
- glType = PixelType.Float;
- break;
+#if !IOS && !ANDROID && !ANGLE
+ case SurfaceFormat.Rgba1010102:
+ glInternalFormat = PixelInternalFormat.Rgb10A2ui;
+ glFormat = PixelFormat.Rgba;
+ glType = PixelType.UnsignedInt1010102;
+ break;
+#endif
+ case SurfaceFormat.Single:
+ if (!supportsFloat)
+ goto case InvalidFormat;
+ glInternalFormat = PixelInternalFormat.R32f;
+ glFormat = PixelFormat.Red;
+ glType = PixelType.Float;
+ break;
case SurfaceFormat.HalfVector2:
+ if (!supportsHalfFloat)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rg16f;
glFormat = PixelFormat.Rg;
glType = PixelType.HalfFloat;
@@ -597,131 +622,113 @@ internal static void GetGLFormat (this SurfaceFormat format,
// HdrBlendable implemented as HalfVector4 (see http://blogs.msdn.com/b/shawnhar/archive/2010/07/09/surfaceformat-hdrblendable.aspx)
case SurfaceFormat.HdrBlendable:
case SurfaceFormat.HalfVector4:
+ if (!supportsHalfFloat)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rgba16f;
glFormat = PixelFormat.Rgba;
glType = PixelType.HalfFloat;
break;
case SurfaceFormat.HalfSingle:
+ if (!supportsHalfFloat)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.R16f;
glFormat = PixelFormat.Red;
- glType = PixelType.HalfFloat;
+ glType = isGLES2 ? PixelType.HalfFloatOES : PixelType.HalfFloat;
break;
case SurfaceFormat.Vector2:
+ if (!supportsFloat)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rg32f;
glFormat = PixelFormat.Rg;
glType = PixelType.Float;
break;
case SurfaceFormat.Vector4:
+ if (!supportsFloat)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rgba32f;
glFormat = PixelFormat.Rgba;
glType = PixelType.Float;
break;
case SurfaceFormat.NormalizedByte2:
+ if (!supportsNormalized)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rg8i;
glFormat = PixelFormat.Rg;
glType = PixelType.Byte;
break;
case SurfaceFormat.NormalizedByte4:
+ if (!supportsNormalized)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rgba8i;
glFormat = PixelFormat.Rgba;
glType = PixelType.Byte;
break;
case SurfaceFormat.Rg32:
+ if (!supportsNormalized)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rg16ui;
glFormat = PixelFormat.Rg;
glType = PixelType.UnsignedShort;
break;
case SurfaceFormat.Rgba64:
+ if (!supportsNormalized)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.Rgba16;
glFormat = PixelFormat.Rgba;
glType = PixelType.UnsignedShort;
break;
-
- case SurfaceFormat.Rgba1010102:
- glInternalFormat = PixelInternalFormat.Rgb10A2ui;
- glFormat = PixelFormat.Rgba;
- glType = PixelType.UnsignedInt1010102;
- break;
-#endif
-
-#if ANDROID
- case SurfaceFormat.Dxt1:
- // 0x83F0 is the RGB version, 0x83F1 is the RGBA version (1-bit alpha)
- // XNA uses the RGB version.
- glInternalFormat = (PixelInternalFormat)0x83F0;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt1SRgb:
- if (!supportsSRgb)
- goto case SurfaceFormat.Dxt1;
- glInternalFormat = (PixelInternalFormat)0x8C4C;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt1a:
- // 0x83F0 is the RGB version, 0x83F1 is the RGBA version (1-bit alpha)
- glInternalFormat = (PixelInternalFormat)0x83F1;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt3:
- glInternalFormat = (PixelInternalFormat)0x83F2;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt3SRgb:
- if (!supportsSRgb)
- goto case SurfaceFormat.Dxt3;
- glInternalFormat = (PixelInternalFormat)0x8C4E;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt5:
- glInternalFormat = (PixelInternalFormat)0x83F3;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
- case SurfaceFormat.Dxt5SRgb:
- if (!supportsSRgb)
- goto case SurfaceFormat.Dxt5;
- glInternalFormat = (PixelInternalFormat)0x8C4F;
- glFormat = PixelFormat.CompressedTextureFormats;
- break;
case SurfaceFormat.RgbaAtcExplicitAlpha:
+ if (!supportsAtitc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.AtcRgbaExplicitAlphaAmd;
glFormat = PixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.RgbaAtcInterpolatedAlpha:
+ if (!supportsAtitc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.AtcRgbaInterpolatedAlphaAmd;
glFormat = PixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.RgbEtc1:
- glInternalFormat = (PixelInternalFormat)0x8D64; // GL_ETC1_RGB8_OES
+ if (!supportsEtc1)
+ goto case InvalidFormat;
+ glInternalFormat = PixelInternalFormat.Etc1; // GL_ETC1_RGB8_OES
glFormat = PixelFormat.CompressedTextureFormats;
break;
-#endif
-#if IOS || ANDROID
case SurfaceFormat.RgbPvrtc2Bpp:
+ if (!supportsPvrtc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbPvrtc2Bppv1Img;
glFormat = PixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.RgbPvrtc4Bpp:
+ if (!supportsPvrtc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbPvrtc4Bppv1Img;
glFormat = PixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.RgbaPvrtc2Bpp:
+ if (!supportsPvrtc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbaPvrtc2Bppv1Img;
glFormat = PixelFormat.CompressedTextureFormats;
break;
case SurfaceFormat.RgbaPvrtc4Bpp:
+ if (!supportsPvrtc)
+ goto case InvalidFormat;
glInternalFormat = PixelInternalFormat.CompressedRgbaPvrtc4Bppv1Img;
glFormat = PixelFormat.CompressedTextureFormats;
break;
-#endif
+ case InvalidFormat:
default:
- throw new NotSupportedException();
+ throw new NotSupportedException(string.Format("The requested SurfaceFormat `{0}` is not supported.", format));
}
}
diff --git a/MonoGame.Framework/Graphics/OpenGL.cs b/MonoGame.Framework/Graphics/OpenGL.cs
index ebae11b04b9..a929c749225 100644
--- a/MonoGame.Framework/Graphics/OpenGL.cs
+++ b/MonoGame.Framework/Graphics/OpenGL.cs
@@ -411,7 +411,9 @@ internal enum PixelInternalFormat
// ATITC
AtcRgbaExplicitAlphaAmd = 0x8C93,
AtcRgbaInterpolatedAlphaAmd = 0x87EE,
- // DXT
+ // ETC1
+ Etc1 = 0x8D64,
+ Srgb = 0x8C40,
}
@@ -433,6 +435,7 @@ internal enum PixelType
UnsignedShort5551 = 0x8034,
Float = 0x1406,
HalfFloat = 0x140B,
+ HalfFloatOES = 0x8D61,
Byte = 0x1400,
UnsignedShort = 0x1403,
UnsignedInt1010102 = 0x8036,