GlRenderTarget.cs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System;
  2. using System.Reactive.Disposables;
  3. using Avalonia.OpenGL;
  4. using Avalonia.Platform;
  5. using Avalonia.Rendering;
  6. using SkiaSharp;
  7. using static Avalonia.OpenGL.GlConsts;
  8. namespace Avalonia.Skia
  9. {
  10. internal class GlRenderTarget : ISkiaGpuRenderTarget
  11. {
  12. private readonly GRContext _grContext;
  13. private IGlPlatformSurfaceRenderTarget _surface;
  14. public GlRenderTarget(GRContext grContext, IGlPlatformSurface glSurface)
  15. {
  16. _grContext = grContext;
  17. _surface = glSurface.CreateGlRenderTarget();
  18. }
  19. public void Dispose() => _surface.Dispose();
  20. public bool IsCorrupted => (_surface as IGlPlatformSurfaceRenderTargetWithCorruptionInfo)?.IsCorrupted == true;
  21. class GlGpuSession : ISkiaGpuRenderSession
  22. {
  23. private readonly GRBackendRenderTarget _backendRenderTarget;
  24. private readonly SKSurface _surface;
  25. private readonly IGlPlatformSurfaceRenderingSession _glSession;
  26. public GlGpuSession(GRContext grContext,
  27. GRBackendRenderTarget backendRenderTarget,
  28. SKSurface surface,
  29. IGlPlatformSurfaceRenderingSession glSession)
  30. {
  31. GrContext = grContext;
  32. _backendRenderTarget = backendRenderTarget;
  33. _surface = surface;
  34. _glSession = glSession;
  35. }
  36. public void Dispose()
  37. {
  38. _surface.Canvas.Flush();
  39. _surface.Dispose();
  40. _backendRenderTarget.Dispose();
  41. GrContext.Flush();
  42. _glSession.Dispose();
  43. }
  44. public GRContext GrContext { get; }
  45. public SKCanvas Canvas => _surface.Canvas;
  46. public double ScaleFactor => _glSession.Scaling;
  47. }
  48. public ISkiaGpuRenderSession BeginRenderingSession()
  49. {
  50. var glSession = _surface.BeginDraw();
  51. bool success = false;
  52. try
  53. {
  54. var disp = glSession.Context;
  55. var gl = disp.GlInterface;
  56. gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb);
  57. var size = glSession.Size;
  58. var scaling = glSession.Scaling;
  59. if (size.Width <= 0 || size.Height <= 0 || scaling < 0)
  60. {
  61. glSession.Dispose();
  62. throw new InvalidOperationException(
  63. $"Can't create drawing context for surface with {size} size and {scaling} scaling");
  64. }
  65. gl.Viewport(0, 0, size.Width, size.Height);
  66. gl.ClearStencil(0);
  67. gl.ClearColor(0, 0, 0, 0);
  68. gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  69. lock (_grContext)
  70. {
  71. _grContext.ResetContext();
  72. var renderTarget =
  73. new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize,
  74. new GRGlFramebufferInfo((uint)fb, GRPixelConfig.Rgba8888.ToGlSizedFormat()));
  75. var surface = SKSurface.Create(_grContext, renderTarget,
  76. glSession.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft,
  77. GRPixelConfig.Rgba8888.ToColorType());
  78. success = true;
  79. return new GlGpuSession(_grContext, renderTarget, surface, glSession);
  80. }
  81. }
  82. finally
  83. {
  84. if(!success)
  85. glSession.Dispose();
  86. }
  87. }
  88. }
  89. }