AndroidFramebuffer.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Android.Runtime;
  4. using Android.Views;
  5. using Avalonia.Platform;
  6. namespace Avalonia.Android.Platform.SkiaPlatform
  7. {
  8. class AndroidFramebuffer : ILockedFramebuffer
  9. {
  10. private IntPtr _window;
  11. public AndroidFramebuffer(Surface surface)
  12. {
  13. if(surface == null)
  14. throw new ArgumentNullException(nameof(surface));
  15. _window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle);
  16. if (_window == IntPtr.Zero)
  17. throw new Exception("Unable to obtain ANativeWindow");
  18. ANativeWindow_Buffer buffer;
  19. var rc = new ARect()
  20. {
  21. right = Width = ANativeWindow_getWidth(_window),
  22. bottom = Height = ANativeWindow_getHeight(_window)
  23. };
  24. ANativeWindow_lock(_window, out buffer, ref rc);
  25. Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565
  26. ? PixelFormat.Rgb565 : PixelFormat.Rgba8888;
  27. RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4);
  28. Address = buffer.bits;
  29. }
  30. public void Dispose()
  31. {
  32. ANativeWindow_unlockAndPost(_window);
  33. ANativeWindow_release(_window);
  34. _window = IntPtr.Zero;
  35. Address = IntPtr.Zero;
  36. }
  37. public IntPtr Address { get; set; }
  38. public int Width { get; }
  39. public int Height { get; }
  40. public int RowBytes { get; }
  41. public Vector Dpi { get; } = new Vector(96, 96);
  42. public PixelFormat Format { get; }
  43. [DllImport("android")]
  44. internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
  45. [DllImport("android")]
  46. internal static extern int ANativeWindow_getWidth(IntPtr window);
  47. [DllImport("android")]
  48. internal static extern int ANativeWindow_getHeight(IntPtr window);
  49. [DllImport("android")]
  50. internal static extern void ANativeWindow_release(IntPtr window);
  51. [DllImport("android")]
  52. internal static extern void ANativeWindow_unlockAndPost(IntPtr window);
  53. [DllImport("android")]
  54. internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds);
  55. public enum AndroidPixelFormat
  56. {
  57. WINDOW_FORMAT_RGBA_8888 = 1,
  58. WINDOW_FORMAT_RGBX_8888 = 2,
  59. WINDOW_FORMAT_RGB_565 = 4,
  60. }
  61. internal struct ARect
  62. {
  63. public int left;
  64. public int top;
  65. public int right;
  66. public int bottom;
  67. }
  68. internal struct ANativeWindow_Buffer
  69. {
  70. // The number of pixels that are show horizontally.
  71. public int width;
  72. // The number of pixels that are shown vertically.
  73. public int height;
  74. // The number of *pixels* that a line in the buffer takes in
  75. // memory. This may be >= width.
  76. public int stride;
  77. // The format of the buffer. One of WINDOW_FORMAT_*
  78. public AndroidPixelFormat format;
  79. // The actual bits.
  80. public IntPtr bits;
  81. // Do not touch.
  82. uint reserved1;
  83. uint reserved2;
  84. uint reserved3;
  85. uint reserved4;
  86. uint reserved5;
  87. uint reserved6;
  88. }
  89. }
  90. }