GraphicsTestFixture.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. namespace MonoGame.Extended.Tests.Fixtures;
  6. /// <summary>
  7. /// A test fixture that provides a fully initialized MonoGame environment
  8. /// for unit testing graphics-related functionality in headless CI environments.
  9. /// </summary>
  10. public sealed class GraphicsTestFixture : IDisposable
  11. {
  12. public Game Game { get; }
  13. public GraphicsDevice GraphicsDevice => Game.GraphicsDevice;
  14. public SpriteBatch SpriteBatch { get; }
  15. public GraphicsTestFixture()
  16. {
  17. Game = new TestGame();
  18. // Initialize the game completely
  19. Game.RunOneFrame();
  20. // Ensure we have a valid graphics device
  21. if (Game.GraphicsDevice == null)
  22. {
  23. throw new InvalidOperationException("Failed to initialize GraphicsDevice. This may indicate an issue with the headless environment setup.");
  24. }
  25. Console.WriteLine("===================");
  26. Console.WriteLine("Graphics Adapter: " + GraphicsDevice.Adapter.Description);
  27. Console.WriteLine("===================");
  28. // Create commonly used graphics objects for tests
  29. SpriteBatch = new SpriteBatch(Game.GraphicsDevice);
  30. }
  31. public void Dispose()
  32. {
  33. SpriteBatch?.Dispose();
  34. Game?.Dispose();
  35. }
  36. /// <summary>
  37. /// Creates a test texture with the specified dimensions and color.
  38. /// Useful for setting up test scenarios.
  39. /// </summary>
  40. public Texture2D CreateTestTexture(int width, int height, Color color)
  41. {
  42. Texture2D texture = new Texture2D(GraphicsDevice, width, height);
  43. Color[] data = new Color[width * height];
  44. Array.Fill(data, color);
  45. texture.SetData(data);
  46. return texture;
  47. }
  48. /// <summary>
  49. /// Creates a simple 1x1 white pixel texture for testing.
  50. /// </summary>
  51. public Texture2D CreatePixelTexture() => CreateTestTexture(1, 1, Color.White);
  52. /// <summary>
  53. /// Validates that the graphics device is properly initialized and functional.
  54. /// </summary>
  55. public void AssertGraphicsDeviceIsValid()
  56. {
  57. Assert.NotNull(GraphicsDevice);
  58. Assert.True(GraphicsDevice.Viewport.Width > 0);
  59. Assert.True(GraphicsDevice.Viewport.Height > 0);
  60. Assert.NotNull(GraphicsDevice.PresentationParameters);
  61. }
  62. private sealed class TestGame : Game
  63. {
  64. public GraphicsDeviceManager GraphicsDeviceManager { get; }
  65. public TestGame()
  66. {
  67. GraphicsDeviceManager = new GraphicsDeviceManager(this);
  68. // Configure for headless testing
  69. GraphicsDeviceManager.GraphicsProfile = GraphicsProfile.Reach;
  70. // Don't sync with vertical retrace for faster test execution
  71. GraphicsDeviceManager.SynchronizeWithVerticalRetrace = false;
  72. // On Windows, explicitly prefer WARP adapter for headless CI environments
  73. if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
  74. {
  75. // Force selection of WARP (software renderer) adapter
  76. // This is done before initialization to ensure WARP is used in headless environments
  77. GraphicsDeviceManager.PreparingDeviceSettings += OnPreparingDeviceSettings;
  78. }
  79. }
  80. private void OnPreparingDeviceSettings(object? sender, PreparingDeviceSettingsEventArgs e)
  81. {
  82. // Try to find the WARP adapter (Microsoft Basic Render Driver)
  83. GraphicsAdapter? warpAdapter = null;
  84. foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters)
  85. {
  86. if (adapter.Description.Contains("Microsoft Basic Render Driver") ||
  87. adapter.Description.Contains("WARP"))
  88. {
  89. warpAdapter = adapter;
  90. break;
  91. }
  92. }
  93. // If WARP adapter is found, use it
  94. if (warpAdapter != null)
  95. {
  96. e.GraphicsDeviceInformation.Adapter = warpAdapter;
  97. }
  98. }
  99. protected override void Draw(GameTime gameTime)
  100. {
  101. // Minimal draw for testing
  102. GraphicsDevice.Clear(Color.CornflowerBlue);
  103. base.Draw(gameTime);
  104. }
  105. }
  106. }