Ejemplo n.º 1
0
        internal static bool Validate(Texture2D texture)
        {
            var meta = texture.Meta();

            if (!meta.ScaleValid)
            {
                return(false);
            }

            if (texture is ManagedTexture2D)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', is already scaled");
                }
                return(meta.ScaleValid = false);
            }

            if (texture is RenderTarget2D)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', render targets unsupported");
                }
                return(meta.ScaleValid = false);
            }

            if (Math.Max(texture.Width, texture.Height) <= Config.Resample.MinimumTextureDimensions)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', texture is too small to qualify");
                }
                return(meta.ScaleValid = false);
            }

            if (texture.Area() == 0)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', zero area");
                }
                return(meta.ScaleValid = false);
            }

            // TODO pComPtr check?
            if (texture.IsDisposed || texture.GraphicsDevice.IsDisposed)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', Is Zombie");
                }
                return(meta.ScaleValid = false);
            }

            if (Config.IgnoreUnknownTextures && texture.Anonymous())
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', Is Unknown Texture");
                }
                return(meta.ScaleValid = false);
            }


            if (texture.LevelCount > 1)
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', Multi-Level Textures Unsupported: {texture.LevelCount} levels");
                }
                return(meta.ScaleValid = false);
            }

            if (!LegalFormat(texture))
            {
                if (!meta.TracePrinted)
                {
                    meta.TracePrinted = true;
                    Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', Format Unsupported: {texture.Format}");
                }
                return(meta.ScaleValid = false);
            }

            if (!texture.Anonymous())
            {
                foreach (var blacklisted in Config.Resample.Blacklist)
                {
                    if (texture.SafeName().StartsWith(blacklisted))
                    {
                        if (!meta.TracePrinted)
                        {
                            meta.TracePrinted = true;
                            Debug.TraceLn($"Not Scaling Texture '{texture.SafeName()}', Is Blacklisted");
                        }
                        return(meta.ScaleValid = false);
                    }
                }
            }

            return(true);
        }
Ejemplo n.º 2
0
        static internal ScaledTexture Get(Texture2D texture, Bounds source, uint expectedScale)
        {
            using var _ = Performance.Track();

            if (SpriteMap.TryGet(texture, source, expectedScale, out var scaleTexture))
            {
                return(scaleTexture);
            }

            if (!Validate(texture))
            {
                return(null);
            }

            bool useAsync = (Config.AsyncScaling.EnabledForUnknownTextures || !texture.Anonymous()) && (texture.Area() >= Config.AsyncScaling.MinimumSizeTexels);
            // !texture.Meta().HasCachedData

            var         estimatedDuration = GetTimer(texture: texture, async: useAsync).Estimate(texture.Area());
            const float multiplier        = 0.75f;
            var         remainingTime     = DrawState.RemainingFrameTime(multiplier: multiplier);

            if (DrawState.PushedUpdateWithin(1) && estimatedDuration >= remainingTime)
            {
                return(null);
            }

            // TODO : We should really only populate the average when we are performing an expensive operation like GetData.
            var begin = DateTime.Now;

            bool       isSprite = (!source.Offset.IsZero || source.Extent != texture.Extent());
            SpriteInfo textureWrapper;
            ulong      hash;

            using (Performance.Track("new SpriteInfo"))
                textureWrapper = new SpriteInfo(reference: texture, dimensions: source, expectedScale: expectedScale);

            // If this is null, it can only happen due to something being blocked, so we should try again later.
            if (textureWrapper.Data == null)
            {
                return(null);
            }

            DrawState.PushedUpdateThisFrame = true;

            try {
                using (Performance.Track("Upscaler.GetHash"))
                    hash = Upscaler.GetHash(textureWrapper, isSprite);

                var newTexture = new ScaledTexture(
                    assetName: texture.SafeName(),
                    textureWrapper: textureWrapper,
                    sourceRectangle: source,
                    isSprite: isSprite,
                    hash: hash,
                    async: useAsync,
                    expectedScale: expectedScale
                    );
                if (useAsync && Config.AsyncScaling.Enabled)
                {
                    // It adds itself to the relevant maps.
                    if (newTexture.IsReady && newTexture.Texture != null)
                    {
                        return(newTexture);
                    }
                    return(null);
                }
                else
                {
                    return(newTexture);
                }
            }
            finally {
                var averager = GetTimer(cached: textureWrapper.WasCached, async: useAsync);
                averager.Add(texture.Area(), DateTime.Now - begin);
            }
        }