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); }
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); } }