using System; using System.Collections.Generic; using Microsoft.Xna.Framework.Graphics; namespace Foo { public class ManagedSamplerState { readonly List queuedStates = new List(), changeSet = new List(); readonly uint[] integerStates = new uint[9]; readonly float[] singleStates = new float[1]; internal void Refresh(ManagedSamplerState ss) { if (changeSet.Count > 0) foreach (byte state in changeSet) if (state < 9) TryQueueState(queuedStates, state, integerStates, ss.integerStates[state]); else TryQueueState(queuedStates, state, singleStates, ss.singleStates[0]); } internal void Reset(ManagedSamplerState ss) { Array.Copy(ss.integerStates, 0, integerStates, 0, 9); singleStates[0] = ss.singleStates[0]; queuedStates.Clear(); if (ss.queuedStates.Count > 0) queuedStates.AddRange(ss.queuedStates); changeSet.Clear(); } internal void Reset(SamplerState ss) { AddressU = ss.AddressU; AddressV = ss.AddressV; AddressW = ss.AddressW; BorderColor = ss.BorderColor; MagFilter = ss.MagFilter; MaxAnisotropy = ss.MaxAnisotropy; MaxMipLevel = ss.MaxMipLevel; MinFilter = ss.MinFilter; MipFilter = ss.MipFilter; MipMapLevelOfDetailBias = ss.MipMapLevelOfDetailBias; queuedStates.Clear(); changeSet.Clear(); } internal void Commit(SamplerState ss) { if (queuedStates.Count > 0) { //Console.WriteLine("Commiting " + queuedStates.Count + " sampler state(s)"); foreach (var state in queuedStates) switch (state) { case 0: ss.AddressU = (TextureAddressMode)integerStates[state]; break; case 1: ss.AddressV = (TextureAddressMode)integerStates[state]; break; case 2: ss.AddressW = (TextureAddressMode)integerStates[state]; break; case 3: ss.BorderColor = MathHelperEx.UnpackColor(integerStates[state]); break; case 4: ss.MagFilter = (TextureFilter)integerStates[state]; break; case 5: ss.MaxAnisotropy = (int)integerStates[state]; break; case 6: ss.MaxMipLevel = (int)integerStates[state]; break; case 7: ss.MinFilter = (TextureFilter)integerStates[state]; break; case 8: ss.MipFilter = (TextureFilter)integerStates[state]; break; case 9: ss.MipMapLevelOfDetailBias = singleStates[0]; break; } changeSet.AddRange(queuedStates); queuedStates.Clear(); } } public TextureAddressMode AddressU { get { return (TextureAddressMode)integerStates[0]; } set { TryQueueState(queuedStates, 0, integerStates, (uint)value); } } public TextureAddressMode AddressV { get { return (TextureAddressMode)integerStates[1]; } set { TryQueueState(queuedStates, 1, integerStates, (uint)value); } } public TextureAddressMode AddressW { get { return (TextureAddressMode)integerStates[2]; } set { TryQueueState(queuedStates, 2, integerStates, (uint)value); } } public Color BorderColor { get { return MathHelperEx.UnpackColor(integerStates[3]); } set { TryQueueState(queuedStates, 3, integerStates, value.PackedValue); } } public TextureFilter MagFilter { get { return (TextureFilter)integerStates[4]; } set { TryQueueState(queuedStates, 4, integerStates, (uint)value); } } public int MaxAnisotropy { get { return (int)integerStates[5]; } set { TryQueueState(queuedStates, 5, integerStates, (uint)value); } } public int MaxMipLevel { get { return (int)integerStates[6]; } set { TryQueueState(queuedStates, 6, integerStates, (uint)value); } } public TextureFilter MinFilter { get { return (TextureFilter)integerStates[7]; } set { TryQueueState(queuedStates, 7, integerStates, (uint)value); } } public TextureFilter MipFilter { get { return (TextureFilter)integerStates[8]; } set { TryQueueState(queuedStates, 8, integerStates, (uint)value); } } public float MipMapLevelOfDetailBias { get { return singleStates[0]; } set { TryQueueState(queuedStates, 0, singleStates, value); } } static void TryQueueState(ICollection queue, byte state, T[] states, T value) where T : IEquatable { if (states[state].Equals(value)) return; states[state] = value; if (!queue.Contains(state)) queue.Add(state); } public void SetFiltering(FilteringMode mode) { switch (mode) { case FilteringMode.NearestPoint: MinFilter = MagFilter = TextureFilter.Point; MipFilter = TextureFilter.None; break; case FilteringMode.Bilinear: MinFilter = MagFilter = TextureFilter.Linear; MipFilter = TextureFilter.None; break; case FilteringMode.Trilinear: MinFilter = MagFilter = MipFilter = TextureFilter.Linear; break; case FilteringMode.Anisotropic: MinFilter = MagFilter = TextureFilter.Anisotropic; MipFilter = TextureFilter.Linear; MaxAnisotropy = 16; break; } } } public enum FilteringMode { NearestPoint, Bilinear, Trilinear, Anisotropic } public static class MathHelperEx { public static Color UnpackColor(uint packedValue) { return new Color { B = (byte)(packedValue), G = (byte)(packedValue >> 8), R = (byte)(packedValue >> 16), A = (byte)(packedValue >> 24) }; } } }