protected virtual ExternalReference <CompiledEffectContent> OnBuildEffect(ExternalReference <EffectContent> effect, ContentProcessorContext context)
        {
#if MONOGAME
            return(context.BuildAsset <EffectContent, CompiledEffectContent>(effect, typeof(EffectProcessor).Name));
#else
            if (string.IsNullOrEmpty(ContentHelper.GetMonoGamePlatform()))
            {
                return(context.BuildAsset <EffectContent, CompiledEffectContent>(effect, typeof(EffectProcessor).Name));
            }
            else
            {
                return(context.BuildAsset <EffectContent, CompiledEffectContent>(effect, "MGEffectProcessor"));
            }
#endif
        }
        /// <summary>
        /// Called by the XNA Framework when importing an texture file to be used as a game asset. This
        /// is the method called by the XNA Framework when an asset is to be imported into an object
        /// that can be recognized by the Content Pipeline.
        /// </summary>
        /// <param name="filename">Name of a game asset file.</param>
        /// <param name="context">
        /// Contains information for importing a game asset, such as a logger interface.
        /// </param>
        /// <returns>Resulting game asset.</returns>
        public override TextureContent Import(string filename, ContentImporterContext context)
        {
            string extension = Path.GetExtension(filename);

            if (extension != null)
            {
                Texture texture = null;
                if (extension.Equals(".DDS", StringComparison.OrdinalIgnoreCase))
                {
                    using (var stream = File.OpenRead(filename))
                        texture = DdsHelper.Load(stream, DdsFlags.ForceRgb | DdsFlags.ExpandLuminance);
                }
                else if (extension.Equals(".TGA", StringComparison.OrdinalIgnoreCase))
                {
                    using (var stream = File.OpenRead(filename))
                        texture = TgaHelper.Load(stream);
                }

                if (texture != null)
                {
#if !MONOGAME
                    // When using the XNA content pipeline, check for MonoGame content.
                    if (!string.IsNullOrEmpty(ContentHelper.GetMonoGamePlatform()))
#endif
                    {
                        // These formats are not (yet) available in MonoGame.
                        switch (texture.Description.Format)
                        {
                        case DataFormat.B5G5R5A1_UNORM: // (16-bit TGA files.)
                        case DataFormat.R8_UNORM:
                        case DataFormat.A8_UNORM:
                            texture = texture.ConvertTo(DataFormat.R8G8B8A8_UNORM);
                            break;
                        }
                    }

                    // Convert DigitalRune Texture to XNA TextureContent.
                    var identity = new ContentIdentity(filename, "DigitalRune");
                    return(TextureHelper.ToContent(texture, identity));
                }
            }

            return(base.Import(filename, context));
        }
        //--------------------------------------------------------------
        #region Methods
        //--------------------------------------------------------------

        /// <summary>
        /// Processes a texture.
        /// </summary>
        /// <param name="input">The texture content to process.</param>
        /// <param name="context">Context for the specified processor.</param>
        /// <returns>The converted texture content.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="input"/> or <paramref name="context"/> is <see langword="null"/>.
        /// </exception>
        public override TextureContent Process(TextureContent input, ContentProcessorContext context)
        {
            if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            // Linear vs. sRGB:
            // XNA does not support _SRGB texture formats. Texture processing is designed
            // for non-sRGB formats. (sRGB formats require a different order of operations!
            // See section "Alpha Blending" in DigitalRune KB.)

            try
            {
                var mipmapChain = input.Faces[0]; // Mipmap chain.
                var level0      = mipmapChain[0]; // Most detailed mipmap level.
                int width       = level0.Width;
                int height      = level0.Height;

                // Early out?
                if (!ColorKeyEnabled &&
                    (!GenerateMipmaps || (width == 1 && height == 1) || // Does not need mipmaps
                     mipmapChain.Count > 1) &&                  // or already has mipmaps.
                    !PremultiplyAlpha &&
                    (!ResizeToPowerOfTwo || (MathHelper.IsPowerOf2(width) && MathHelper.IsPowerOf2(height))) &&
                    !ScaleAlphaToCoverage)
                {
                    if (Format == DRTextureFormat.NoChange)
                    {
                        // No processing required.
                        return(input);
                    }

                    SurfaceFormat surfaceFormat;
                    if (!level0.TryGetFormat(out surfaceFormat))
                    {
                        throw new InvalidContentException("Surface format is not supported.", input.Identity);
                    }

                    if ((Format == DRTextureFormat.Color && surfaceFormat == SurfaceFormat.Color) ||
                        (Format == DRTextureFormat.Dxt && IsDxt(surfaceFormat)))
                    {
                        // No processing required.
                        return(input);
                    }
                }

                var texture      = TextureHelper.ToTexture(input);
                var sourceFormat = texture.Description.Format;

                // Apply color keying.
                if (ColorKeyEnabled)
                {
                    // Apply color keying in RGBA 8:8:8:8.
                    texture = texture.ConvertTo(DataFormat.R8G8B8A8_UNORM);
                    TextureHelper.ApplyColorKey(texture, ColorKeyColor.R, ColorKeyColor.G, ColorKeyColor.B, ColorKeyColor.A);
                }

                // Normal maps require special treatment (no sRGB, etc.).
                bool isNormalMap = (Format == DRTextureFormat.Normal || Format == DRTextureFormat.NormalInvertY);
                if (isNormalMap)
                {
                    InputGamma       = 1.0f;
                    OutputGamma      = 1.0f;
                    PremultiplyAlpha = false;
                }

                // Check whether alpha channel is used.
                bool hasAlpha           = false; // true if alpha channel != 1.
                bool hasFractionalAlpha = false; // true if alpha channel has 0 < alpha < 1.
                if (!isNormalMap)
                {
                    if (GenerateMipmaps || ResizeToPowerOfTwo || PremultiplyAlpha || Format == DRTextureFormat.Dxt)
                    {
                        try
                        {
                            TextureHelper.HasAlpha(texture, out hasAlpha, out hasFractionalAlpha);
                        }
                        catch (NotSupportedException)
                        {
                            // HasAlpha() does not support the current format. Convert and try again.
                            texture = texture.ConvertTo(DataFormat.R32G32B32A32_FLOAT);
                            TextureHelper.HasAlpha(texture, out hasAlpha, out hasFractionalAlpha);
                        }
                    }
                }

                // Convert to high-precision, floating-point format for processing.
                texture = texture.ConvertTo(DataFormat.R32G32B32A32_FLOAT);

                if (!isNormalMap)
                {
                    // Convert texture from gamma space to linear space.
                    TextureHelper.GammaToLinear(texture, InputGamma);
                }
                else
                {
                    // Convert normal map from [0, 1] to [-1, 1].
                    TextureHelper.UnpackNormals(texture);
                }

                // The resize filter needs to consider alpha if the image is not already
                // premultiplied. PremultiplyAlpha indicates that the source image has
                // alpha, but is not yet premultiplied. (Premultiplication happen at the
                // end.)
                bool alphaTransparency = hasAlpha && PremultiplyAlpha;

                if (ResizeToPowerOfTwo || context.TargetProfile == GraphicsProfile.Reach && Format == DRTextureFormat.Dxt)
                {
                    // Resize to power-of-two.
                    int expectedWidth  = RoundUpToPowerOfTwo(texture.Description.Width);
                    int expectedHeight = RoundUpToPowerOfTwo(texture.Description.Height);
                    if (expectedWidth != texture.Description.Width || expectedHeight != texture.Description.Height)
                    {
                        texture = texture.Resize(expectedWidth, expectedHeight, texture.Description.Depth, ResizeFilter.Kaiser, alphaTransparency, TextureAddressMode.Clamp);
                    }
                }

                if (Format == DRTextureFormat.Dxt || Format == DRTextureFormat.Normal || Format == DRTextureFormat.NormalInvertY)
                {
                    // Resize to multiple of four.
                    int expectedWidth  = RoundToMultipleOfFour(texture.Description.Width);
                    int expectedHeight = RoundToMultipleOfFour(texture.Description.Height);
                    if (expectedWidth != texture.Description.Width || expectedHeight != texture.Description.Height)
                    {
                        texture = texture.Resize(expectedWidth, expectedHeight, texture.Description.Depth, ResizeFilter.Kaiser, alphaTransparency, TextureAddressMode.Clamp);
                    }
                }

                if (GenerateMipmaps && texture.Description.MipLevels <= 1)
                {
                    // Generate mipmaps.
                    texture.GenerateMipmaps(ResizeFilter.Box, alphaTransparency, TextureAddressMode.Repeat);
                }

                // For debugging:
                // ColorizeMipmaps(texture);

                if (!isNormalMap)
                {
                    if (ScaleAlphaToCoverage)
                    {
                        TextureHelper.ScaleAlphaToCoverage(texture, ReferenceAlpha, /* data not yet premultiplied */ false);
                    }

                    // Convert texture from linear space to gamma space.
                    TextureHelper.LinearToGamma(texture, OutputGamma);

                    // Premultiply alpha.
                    if (hasAlpha && PremultiplyAlpha)
                    {
                        TextureHelper.PremultiplyAlpha(texture);
                    }
                }
                else
                {
                    // Renormalize normal map and convert to DXT5nm.
                    TextureHelper.ProcessNormals(texture, Format == DRTextureFormat.NormalInvertY);
                }

#if !MONOGAME
                // No PVRTC in XNA build.
                string mgPlatform = ContentHelper.GetMonoGamePlatform();
                if (!string.IsNullOrEmpty(mgPlatform) && mgPlatform.ToUpperInvariant() == "IOS")
                {
                    Format = DRTextureFormat.Color;
                }
#endif

                // Convert to from floating-point format to requested output format.
                switch (Format)
                {
                case DRTextureFormat.NoChange:
                    texture = texture.ConvertTo(sourceFormat);
                    input   = TextureHelper.ToContent(texture, input.Identity);
                    break;

                case DRTextureFormat.Color:
                    texture = texture.ConvertTo(DataFormat.R8G8B8A8_UNORM);
                    input   = TextureHelper.ToContent(texture, input.Identity);
                    break;

                case DRTextureFormat.Dxt:
                    if (texture.Description.Dimension == TextureDimension.Texture3D)
                    {
                        texture = texture.ConvertTo(DataFormat.R8G8B8A8_UNORM);
                        input   = TextureHelper.ToContent(texture, input.Identity);
                    }
                    else
                    {
#if MONOGAME
                        input = Compress(context, texture, hasAlpha, hasFractionalAlpha, PremultiplyAlpha, input.Identity);
#else
                        if (hasFractionalAlpha)
                        {
                            texture = texture.ConvertTo(DataFormat.BC3_UNORM);
                        }
                        else
                        {
                            texture = texture.ConvertTo(DataFormat.BC1_UNORM);
                        }

                        input = TextureHelper.ToContent(texture, input.Identity);
#endif
                    }
                    break;

                case DRTextureFormat.Normal:
                case DRTextureFormat.NormalInvertY:
#if MONOGAME
                    input = Compress(context, texture, true, true, false, input.Identity);
#else
                    texture = texture.ConvertTo(DataFormat.BC3_UNORM);
                    input   = TextureHelper.ToContent(texture, input.Identity);
#endif
                    break;

                default:
                    throw new NotSupportedException("The specified output format is not supported.");
                }
            }
            catch (Exception ex)
            {
                throw new InvalidContentException(ex.Message, input.Identity);
            }

            return(input);
        }