AndroidFramebuffer.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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, double scaling)
  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 = ANativeWindow_getWidth(_window),
  22. bottom = ANativeWindow_getHeight(_window)
  23. };
  24. Size = new PixelSize(rc.right, rc.bottom);
  25. ANativeWindow_lock(_window, out buffer, ref rc);
  26. Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565
  27. ? PixelFormat.Rgb565 : PixelFormat.Rgba8888;
  28. RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4);
  29. Address = buffer.bits;
  30. Dpi = new Vector(96, 96) * scaling;
  31. }
  32. public void Dispose()
  33. {
  34. ANativeWindow_unlockAndPost(_window);
  35. ANativeWindow_release(_window);
  36. _window = IntPtr.Zero;
  37. Address = IntPtr.Zero;
  38. }
  39. public IntPtr Address { get; set; }
  40. public PixelSize Size { get; }
  41. public int RowBytes { get; }
  42. public Vector Dpi { get; }
  43. public PixelFormat Format { get; }
  44. [DllImport("android")]
  45. internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
  46. [DllImport("android")]
  47. internal static extern int ANativeWindow_getWidth(IntPtr window);
  48. [DllImport("android")]
  49. internal static extern int ANativeWindow_getHeight(IntPtr window);
  50. [DllImport("android")]
  51. internal static extern void ANativeWindow_release(IntPtr window);
  52. [DllImport("android")]
  53. internal static extern void ANativeWindow_unlockAndPost(IntPtr window);
  54. [DllImport("android")]
  55. internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds);
  56. public enum AndroidPixelFormat
  57. {
  58. WINDOW_FORMAT_RGBA_8888 = 1,
  59. WINDOW_FORMAT_RGBX_8888 = 2,
  60. WINDOW_FORMAT_RGB_565 = 4,
  61. }
  62. internal struct ARect
  63. {
  64. public int left;
  65. public int top;
  66. public int right;
  67. public int bottom;
  68. }
  69. internal struct ANativeWindow_Buffer
  70. {
  71. // The number of pixels that are show horizontally.
  72. public int width;
  73. // The number of pixels that are shown vertically.
  74. public int height;
  75. // The number of *pixels* that a line in the buffer takes in
  76. // memory. This may be >= width.
  77. public int stride;
  78. // The format of the buffer. One of WINDOW_FORMAT_*
  79. public AndroidPixelFormat format;
  80. // The actual bits.
  81. public IntPtr bits;
  82. // Do not touch.
  83. uint reserved1;
  84. uint reserved2;
  85. uint reserved3;
  86. uint reserved4;
  87. uint reserved5;
  88. uint reserved6;
  89. }
  90. }
  91. }