A game framework written with osu! in mind.
at master 69 lines 2.5 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System.Collections.Generic; 5using System.Diagnostics; 6using System.Threading; 7using JetBrains.Annotations; 8using osu.Framework.IO.Stores; 9using osuTK.Graphics.ES30; 10 11namespace osu.Framework.Graphics.Textures 12{ 13 /// <summary> 14 /// A texture store that bypasses atlasing and removes textures from memory after dereferenced by all consumers. 15 /// </summary> 16 public class LargeTextureStore : TextureStore 17 { 18 private readonly object referenceCountLock = new object(); 19 private readonly Dictionary<string, TextureWithRefCount.ReferenceCount> referenceCounts = new Dictionary<string, TextureWithRefCount.ReferenceCount>(); 20 21 public LargeTextureStore(IResourceStore<TextureUpload> store = null, All filteringMode = All.Linear) 22 : base(store, false, filteringMode, true) 23 { 24 } 25 26 protected override bool TryGetCached(string lookupKey, out Texture texture) 27 { 28 lock (referenceCountLock) 29 { 30 if (base.TryGetCached(lookupKey, out var tex)) 31 { 32 texture = createTextureWithRefCount(lookupKey, tex); 33 return true; 34 } 35 36 texture = null; 37 return false; 38 } 39 } 40 41 protected override Texture CacheAndReturnTexture(string lookupKey, Texture texture) 42 { 43 lock (referenceCountLock) 44 return createTextureWithRefCount(lookupKey, base.CacheAndReturnTexture(lookupKey, texture)); 45 } 46 47 private TextureWithRefCount createTextureWithRefCount([NotNull] string lookupKey, [CanBeNull] Texture baseTexture) 48 { 49 if (baseTexture == null) 50 return null; 51 52 lock (referenceCountLock) 53 { 54 if (!referenceCounts.TryGetValue(lookupKey, out TextureWithRefCount.ReferenceCount count)) 55 referenceCounts[lookupKey] = count = new TextureWithRefCount.ReferenceCount(referenceCountLock, () => onAllReferencesLost(baseTexture)); 56 57 return new TextureWithRefCount(baseTexture.TextureGL, count); 58 } 59 } 60 61 private void onAllReferencesLost(Texture texture) 62 { 63 Debug.Assert(Monitor.IsEntered(referenceCountLock)); 64 65 referenceCounts.Remove(texture.LookupKey); 66 Purge(texture); 67 } 68 } 69}