// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace SharpDX.DXGI
{
///
/// Helper to use with .
///
public static class FormatHelper
{
private static readonly int[] sizeOfInBits = new int[256];
private static readonly bool[] compressedFormats = new bool[256];
private static readonly bool[] srgbFormats = new bool[256];
private static readonly bool[] typelessFormats = new bool[256];
///
/// Calculates the size of a in bytes. Can be 0 for compressed format (as they are less than 1 byte)
///
/// The DXGI format.
/// size of in bytes
public static int SizeOfInBytes(this Format format)
{
var sizeInBits = SizeOfInBits(format);
return sizeInBits >> 3;
}
///
/// Calculates the size of a in bits.
///
/// The DXGI format.
/// size of in bits
public static int SizeOfInBits(this Format format)
{
return sizeOfInBits[(int) format];
}
///
/// Returns true if the is valid.
///
/// A format to validate
/// True if the is valid.
public static bool IsValid(this Format format)
{
return ( (int)(format) >= 1 && (int)(format) <= 115 );
}
///
/// Returns true if the is a compressed format.
///
/// The format to check for compressed.
/// True if the is a compressed format
public static bool IsCompressed(this Format format)
{
return compressedFormats[(int) format];
}
///
/// Determines whether the specified is packed.
///
/// The DXGI Format.
/// true if the specified is packed; otherwise, false.
public static bool IsPacked(this Format format )
{
return ((format == Format.R8G8_B8G8_UNorm) || (format == Format.G8R8_G8B8_UNorm));
}
///
/// Determines whether the specified is video.
///
/// The .
/// true if the specified is video; otherwise, false.
public static bool IsVideo(this Format format )
{
switch ( format )
{
case Format.AYUV:
case Format.Y410:
case Format.Y416:
case Format.NV12:
case Format.P010:
case Format.P016:
case Format.YUY2:
case Format.Y210:
case Format.Y216:
case Format.NV11:
// These video formats can be used with the 3D pipeline through special view mappings
return true;
case Format.Opaque420:
case Format.AI44:
case Format.IA44:
case Format.P8:
case Format.A8P8:
// These are limited use video formats not usable in any way by the 3D pipeline
return true;
default:
return false;
}
}
///
/// Determines whether the specified is a SRGB format.
///
/// The .
/// true if the specified is a SRGB format; otherwise, false.
public static bool IsSRgb(this Format format )
{
return srgbFormats[(int) format];
}
///
/// Determines whether the specified is typeless.
///
/// The .
/// true if the specified is typeless; otherwise, false.
public static bool IsTypeless(this Format format )
{
return typelessFormats[(int) format];
}
///
/// Computes the scanline count (number of scanlines).
///
/// The .
/// The height.
/// The scanline count.
public static int ComputeScanlineCount(this Format format, int height)
{
switch (format)
{
case Format.BC1_Typeless:
case Format.BC1_UNorm:
case Format.BC1_UNorm_SRgb:
case Format.BC2_Typeless:
case Format.BC2_UNorm:
case Format.BC2_UNorm_SRgb:
case Format.BC3_Typeless:
case Format.BC3_UNorm:
case Format.BC3_UNorm_SRgb:
case Format.BC4_Typeless:
case Format.BC4_UNorm:
case Format.BC4_SNorm:
case Format.BC5_Typeless:
case Format.BC5_UNorm:
case Format.BC5_SNorm:
case Format.BC6H_Typeless:
case Format.BC6H_Uf16:
case Format.BC6H_Sf16:
case Format.BC7_Typeless:
case Format.BC7_UNorm:
case Format.BC7_UNorm_SRgb:
return Math.Max(1, (height + 3) / 4);
default:
return height;
}
}
///
/// Static initializer to speed up size calculation (not sure the JIT is enough "smart" for this kind of thing).
///
static FormatHelper()
{
InitFormat(new[] { Format.R1_UNorm }, 1);
InitFormat(new[] { Format.A8_UNorm, Format.R8_SInt, Format.R8_SNorm, Format.R8_Typeless, Format.R8_UInt, Format.R8_UNorm }, 8);
InitFormat(new[] {
Format.B5G5R5A1_UNorm,
Format.B5G6R5_UNorm,
Format.D16_UNorm,
Format.R16_Float,
Format.R16_SInt,
Format.R16_SNorm,
Format.R16_Typeless,
Format.R16_UInt,
Format.R16_UNorm,
Format.R8G8_SInt,
Format.R8G8_SNorm,
Format.R8G8_Typeless,
Format.R8G8_UInt,
Format.R8G8_UNorm,
Format.B4G4R4A4_UNorm,
}, 16);
InitFormat(new[] {
Format.B8G8R8X8_Typeless,
Format.B8G8R8X8_UNorm,
Format.B8G8R8X8_UNorm_SRgb,
Format.D24_UNorm_S8_UInt,
Format.D32_Float,
Format.D32_Float_S8X24_UInt,
Format.G8R8_G8B8_UNorm,
Format.R10G10B10_Xr_Bias_A2_UNorm,
Format.R10G10B10A2_Typeless,
Format.R10G10B10A2_UInt,
Format.R10G10B10A2_UNorm,
Format.R11G11B10_Float,
Format.R16G16_Float,
Format.R16G16_SInt,
Format.R16G16_SNorm,
Format.R16G16_Typeless,
Format.R16G16_UInt,
Format.R16G16_UNorm,
Format.R24_UNorm_X8_Typeless,
Format.R24G8_Typeless,
Format.R32_Float,
Format.R32_Float_X8X24_Typeless,
Format.R32_SInt,
Format.R32_Typeless,
Format.R32_UInt,
Format.R8G8_B8G8_UNorm,
Format.R8G8B8A8_SInt,
Format.R8G8B8A8_SNorm,
Format.R8G8B8A8_Typeless,
Format.R8G8B8A8_UInt,
Format.R8G8B8A8_UNorm,
Format.R8G8B8A8_UNorm_SRgb,
Format.B8G8R8A8_Typeless,
Format.B8G8R8A8_UNorm,
Format.B8G8R8A8_UNorm_SRgb,
Format.R9G9B9E5_Sharedexp,
Format.X24_Typeless_G8_UInt,
Format.X32_Typeless_G8X24_UInt,
}, 32);
InitFormat(new[] {
Format.R16G16B16A16_Float,
Format.R16G16B16A16_SInt,
Format.R16G16B16A16_SNorm,
Format.R16G16B16A16_Typeless,
Format.R16G16B16A16_UInt,
Format.R16G16B16A16_UNorm,
Format.R32G32_Float,
Format.R32G32_SInt,
Format.R32G32_Typeless,
Format.R32G32_UInt,
Format.R32G8X24_Typeless,
}, 64);
InitFormat(new[] {
Format.R32G32B32_Float,
Format.R32G32B32_SInt,
Format.R32G32B32_Typeless,
Format.R32G32B32_UInt,
}, 96);
InitFormat(new[] {
Format.R32G32B32A32_Float,
Format.R32G32B32A32_SInt,
Format.R32G32B32A32_Typeless,
Format.R32G32B32A32_UInt,
}, 128);
InitFormat(new[] {
Format.BC1_Typeless,
Format.BC1_UNorm,
Format.BC1_UNorm_SRgb,
Format.BC4_SNorm,
Format.BC4_Typeless,
Format.BC4_UNorm,
}, 4);
InitFormat(new[] {
Format.BC2_Typeless,
Format.BC2_UNorm,
Format.BC2_UNorm_SRgb,
Format.BC3_Typeless,
Format.BC3_UNorm,
Format.BC3_UNorm_SRgb,
Format.BC5_SNorm,
Format.BC5_Typeless,
Format.BC5_UNorm,
Format.BC6H_Sf16,
Format.BC6H_Typeless,
Format.BC6H_Uf16,
Format.BC7_Typeless,
Format.BC7_UNorm,
Format.BC7_UNorm_SRgb,
}, 8);
// Init compressed formats
InitDefaults(new[]
{
Format.BC1_Typeless,
Format.BC1_UNorm,
Format.BC1_UNorm_SRgb,
Format.BC2_Typeless,
Format.BC2_UNorm,
Format.BC2_UNorm_SRgb,
Format.BC3_Typeless,
Format.BC3_UNorm,
Format.BC3_UNorm_SRgb,
Format.BC4_Typeless,
Format.BC4_UNorm,
Format.BC4_SNorm,
Format.BC5_Typeless,
Format.BC5_UNorm,
Format.BC5_SNorm,
Format.BC6H_Typeless,
Format.BC6H_Uf16,
Format.BC6H_Sf16,
Format.BC7_Typeless,
Format.BC7_UNorm,
Format.BC7_UNorm_SRgb,
}, compressedFormats);
// Init srgb formats
InitDefaults(new[]
{
Format.R8G8B8A8_UNorm_SRgb,
Format.BC1_UNorm_SRgb,
Format.BC2_UNorm_SRgb,
Format.BC3_UNorm_SRgb,
Format.B8G8R8A8_UNorm_SRgb,
Format.B8G8R8X8_UNorm_SRgb,
Format.BC7_UNorm_SRgb,
}, srgbFormats);
// Init typeless formats
InitDefaults(new[]
{
Format.R32G32B32A32_Typeless,
Format.R32G32B32_Typeless,
Format.R16G16B16A16_Typeless,
Format.R32G32_Typeless,
Format.R32G8X24_Typeless,
Format.R10G10B10A2_Typeless,
Format.R8G8B8A8_Typeless,
Format.R16G16_Typeless,
Format.R32_Typeless,
Format.R24G8_Typeless,
Format.R8G8_Typeless,
Format.R16_Typeless,
Format.R8_Typeless,
Format.BC1_Typeless,
Format.BC2_Typeless,
Format.BC3_Typeless,
Format.BC4_Typeless,
Format.BC5_Typeless,
Format.B8G8R8A8_Typeless,
Format.B8G8R8X8_Typeless,
Format.BC6H_Typeless,
Format.BC7_Typeless,
}, typelessFormats);
}
private static void InitFormat(IEnumerable formats, int bitCount)
{
foreach (var format in formats)
sizeOfInBits[(int)format] = bitCount;
}
private static void InitDefaults(IEnumerable formats, bool[] outputArray)
{
foreach (var format in formats)
outputArray[(int)format] = true;
}
}
}