private static bool ValidateTexture(HeaderDXT10 header, HeaderFlags flags, out int depth, out PixelFormat format, out ResourceDimension resDim, out int arraySize, out bool isCubeMap) { depth = 0; format = Renderer.PixelFormat.Unknown; resDim = ResourceDimension.Unknown; arraySize = 0x1; isCubeMap = false; arraySize = header.ArraySize; if (arraySize == 0) { return(false); } if (header.MiscFlag2 != FlagsDX10.AlphaModeUnknown) { return(false); } if (DDSPixelFormat.BitsPerPixel(header.DXGIFormat) == 0) { return(false); } format = header.DXGIFormat; switch (header.Dimension) { case ResourceDimension.Texture1D: depth = 1; break; case ResourceDimension.Texture2D: if (header.MiscFlag.HasFlag(ResourceOptionFlags.TextureCube)) { arraySize *= 6; isCubeMap = true; } depth = 1; break; case ResourceDimension.Texture3D: if (!flags.HasFlag(HeaderFlags.Depth)) { return(false); } if (arraySize > 1) { return(false); } break; default: return(false); } resDim = header.Dimension; return(true); }
private static void EncodeDDSHeader(BinaryWriter writer, TextureDescription description, DdsFlags flags) { if (!TextureHelper.IsValidDds(description.Format)) throw new ArgumentException("Invalid texture format.", "description"); if (TextureHelper.IsPalettized(description.Format)) throw new NotSupportedException("Palettized texture formats are not supported."); if (description.ArraySize > 1) { if (description.ArraySize != 6 || description.Dimension != TextureDimension.Texture2D || description.Dimension != TextureDimension.TextureCube) { // Texture1D arrays, Texture2D arrays, and TextureCube arrays must be stored using 'DX10' extended header flags |= DdsFlags.ForceDX10Ext; } } if ((flags & DdsFlags.ForceDX10ExtMisc2) != 0) flags |= DdsFlags.ForceDX10Ext; PixelFormat ddpf = default(PixelFormat); if ((flags & DdsFlags.ForceDX10Ext) == 0) { switch (description.Format) { case DataFormat.R8G8B8A8_UNORM: ddpf = PixelFormat.A8B8G8R8; break; case DataFormat.R16G16_UNORM: ddpf = PixelFormat.G16R16; break; case DataFormat.R8G8_UNORM: ddpf = PixelFormat.A8L8; break; case DataFormat.R16_UNORM: ddpf = PixelFormat.L16; break; case DataFormat.R8_UNORM: ddpf = PixelFormat.L8; break; case DataFormat.A8_UNORM: ddpf = PixelFormat.A8; break; case DataFormat.R8G8_B8G8_UNORM: ddpf = PixelFormat.R8G8_B8G8; break; case DataFormat.G8R8_G8B8_UNORM: ddpf = PixelFormat.G8R8_G8B8; break; case DataFormat.BC1_UNORM: ddpf = PixelFormat.DXT1; break; case DataFormat.BC2_UNORM: ddpf = /* (description.AlphaMode == AlphaMode.Premultiplied) ? PixelFormat.DXT2 : */ PixelFormat.DXT3; break; case DataFormat.BC3_UNORM: ddpf = /* (description.AlphaMode == AlphaMode.Premultiplied) ? PixelFormat.DXT2 : */ PixelFormat.DXT5; break; case DataFormat.BC4_UNORM: ddpf = PixelFormat.BC4_UNorm; break; case DataFormat.BC4_SNORM: ddpf = PixelFormat.BC4_SNorm; break; case DataFormat.BC5_UNORM: ddpf = PixelFormat.BC5_UNorm; break; case DataFormat.BC5_SNORM: ddpf = PixelFormat.BC5_SNorm; break; case DataFormat.B5G6R5_UNORM: ddpf = PixelFormat.R5G6B5; break; case DataFormat.B5G5R5A1_UNORM: ddpf = PixelFormat.A1R5G5B5; break; case DataFormat.R8G8_SNORM: ddpf = PixelFormat.V8U8; break; case DataFormat.R8G8B8A8_SNORM: ddpf = PixelFormat.Q8W8V8U8; break; case DataFormat.R16G16_SNORM: ddpf = PixelFormat.V16U16; break; case DataFormat.B8G8R8A8_UNORM: ddpf = PixelFormat.A8R8G8B8; break; // DXGI 1.1 case DataFormat.B8G8R8X8_UNORM: ddpf = PixelFormat.X8R8G8B8; break; // DXGI 1.1 //#if DIRECTX11_1 case DataFormat.B4G4R4A4_UNORM: ddpf = PixelFormat.A4R4G4B4; break; case DataFormat.YUY2: ddpf = PixelFormat.YUY2; break; //#endif // Legacy D3DX formats using D3DFMT enum value as FourCC case DataFormat.R32G32B32A32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 116; // D3DFMT_A32B32G32R32F break; case DataFormat.R16G16B16A16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 113; // D3DFMT_A16B16G16R16F break; case DataFormat.R16G16B16A16_UNORM: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 36; // D3DFMT_A16B16G16R16 break; case DataFormat.R16G16B16A16_SNORM: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 110; // D3DFMT_Q16W16V16U16 break; case DataFormat.R32G32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 115; // D3DFMT_G32R32F break; case DataFormat.R16G16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 112; // D3DFMT_G16R16F break; case DataFormat.R32_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 114; // D3DFMT_R32F break; case DataFormat.R16_FLOAT: ddpf.Size = Marshal.SizeOf(typeof(PixelFormat)); ddpf.Flags = PixelFormatFlags.FourCC; ddpf.FourCC = 111; // D3DFMT_R16F break; } } writer.Write(MagicHeader); var header = new Header(); header.Size = Marshal.SizeOf(typeof(Header)); header.Flags = HeaderFlags.Texture; header.SurfaceFlags = SurfaceFlags.Texture; if (description.MipLevels > 0) { header.Flags |= HeaderFlags.Mipmap; header.MipMapCount = description.MipLevels; if (header.MipMapCount > 1) header.SurfaceFlags |= SurfaceFlags.Mipmap; } switch (description.Dimension) { case TextureDimension.Texture1D: header.Height = description.Height; header.Width = header.Depth = 1; break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: header.Height = description.Height; header.Width = description.Width; header.Depth = 1; if (description.Dimension == TextureDimension.TextureCube) { header.SurfaceFlags |= SurfaceFlags.Cubemap; header.CubemapFlags |= CubemapFlags.AllFaces; } break; case TextureDimension.Texture3D: header.Flags |= HeaderFlags.Volume; header.CubemapFlags |= CubemapFlags.Volume; header.Height = description.Height; header.Width = description.Width; header.Depth = description.Depth; break; default: throw new NotSupportedException("The specified texture dimension is not supported."); } int rowPitch, slicePitch; TextureHelper.ComputePitch(description.Format, description.Width, description.Height, out rowPitch, out slicePitch); if (TextureHelper.IsBCn(description.Format)) { header.Flags |= HeaderFlags.LinearSize; header.PitchOrLinearSize = slicePitch; } else { header.Flags |= HeaderFlags.Pitch; header.PitchOrLinearSize = rowPitch; } if (ddpf.Size != 0) { header.PixelFormat = ddpf; writer.BaseStream.WriteStruct(header); } else { header.PixelFormat = PixelFormat.DX10; var ext = new HeaderDXT10(); ext.DXGIFormat = description.Format; switch (description.Dimension) { case TextureDimension.Texture1D: ext.ResourceDimension = ResourceDimension.Texture1D; break; case TextureDimension.Texture2D: case TextureDimension.TextureCube: ext.ResourceDimension = ResourceDimension.Texture2D; break; case TextureDimension.Texture3D: ext.ResourceDimension = ResourceDimension.Texture3D; break; } if (description.Dimension == TextureDimension.TextureCube) { ext.MiscFlags |= ResourceOptionFlags.TextureCube; ext.ArraySize = description.ArraySize / 6; } else { ext.ArraySize = description.ArraySize; } if ((flags & DdsFlags.ForceDX10ExtMisc2) != 0) { // This was formerly 'reserved'. D3DX10 and D3DX11 will fail if this value is anything other than 0. //ext.MiscFlags2 = description.MiscFlags2; throw new NotImplementedException("DdsFlags.ForceDX10ExtMisc2 is not implemented."); } writer.BaseStream.WriteStruct(header); writer.BaseStream.WriteStruct(ext); } }