IOSurface.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/OwnPtr.h>
  7. #include <LibCore/IOSurface.h>
  8. #if !defined(AK_OS_MACOS)
  9. static_assert(false, "This file must only be used for macOS");
  10. #endif
  11. #import <IOSurface/IOSurface.h>
  12. namespace Core {
  13. template<typename T>
  14. class RefAutoRelease {
  15. AK_MAKE_NONCOPYABLE(RefAutoRelease);
  16. public:
  17. RefAutoRelease(T ref)
  18. : m_ref(ref)
  19. {
  20. }
  21. ~RefAutoRelease()
  22. {
  23. if (m_ref)
  24. CFRelease(m_ref);
  25. m_ref = nullptr;
  26. }
  27. T ref() const { return m_ref; }
  28. private:
  29. T m_ref { nullptr };
  30. };
  31. struct IOSurfaceHandle::IOSurfaceRefWrapper {
  32. IOSurfaceRef ref;
  33. };
  34. IOSurfaceHandle::IOSurfaceHandle(OwnPtr<IOSurfaceRefWrapper>&& ref_wrapper)
  35. : m_ref_wrapper(move(ref_wrapper))
  36. {
  37. }
  38. IOSurfaceHandle::IOSurfaceHandle(IOSurfaceHandle&& other) = default;
  39. IOSurfaceHandle& IOSurfaceHandle::operator=(IOSurfaceHandle&& other) = default;
  40. IOSurfaceHandle::~IOSurfaceHandle()
  41. {
  42. if (m_ref_wrapper)
  43. CFRelease(m_ref_wrapper->ref);
  44. }
  45. IOSurfaceHandle IOSurfaceHandle::create(int width, int height)
  46. {
  47. size_t bytes_per_element = 4;
  48. uint32_t pixel_format = 'BGRA';
  49. RefAutoRelease<CFNumberRef> width_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &width);
  50. RefAutoRelease<CFNumberRef> height_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &height);
  51. RefAutoRelease<CFNumberRef> bytes_per_element_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &bytes_per_element);
  52. RefAutoRelease<CFNumberRef> pixel_format_number = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pixel_format);
  53. CFMutableDictionaryRef props = CFDictionaryCreateMutable(kCFAllocatorDefault,
  54. 0,
  55. &kCFTypeDictionaryKeyCallBacks,
  56. &kCFTypeDictionaryValueCallBacks);
  57. CFDictionarySetValue(props, kIOSurfaceWidth, width_number.ref());
  58. CFDictionarySetValue(props, kIOSurfaceHeight, height_number.ref());
  59. CFDictionarySetValue(props, kIOSurfaceBytesPerElement, bytes_per_element_number.ref());
  60. CFDictionarySetValue(props, kIOSurfacePixelFormat, pixel_format_number.ref());
  61. auto* ref = IOSurfaceCreate(props);
  62. VERIFY(ref);
  63. return IOSurfaceHandle(make<IOSurfaceRefWrapper>(ref));
  64. }
  65. MachPort IOSurfaceHandle::create_mach_port() const
  66. {
  67. auto port = IOSurfaceCreateMachPort(m_ref_wrapper->ref);
  68. return MachPort::adopt_right(port, MachPort::PortRight::Send);
  69. }
  70. IOSurfaceHandle IOSurfaceHandle::from_mach_port(MachPort const& port)
  71. {
  72. // NOTE: This call does not destroy the port
  73. auto* ref = IOSurfaceLookupFromMachPort(port.port());
  74. VERIFY(ref);
  75. return IOSurfaceHandle(make<IOSurfaceRefWrapper>(ref));
  76. }
  77. size_t IOSurfaceHandle::width() const
  78. {
  79. return IOSurfaceGetWidth(m_ref_wrapper->ref);
  80. }
  81. size_t IOSurfaceHandle::height() const
  82. {
  83. return IOSurfaceGetHeight(m_ref_wrapper->ref);
  84. }
  85. size_t IOSurfaceHandle::bytes_per_element() const
  86. {
  87. return IOSurfaceGetBytesPerElement(m_ref_wrapper->ref);
  88. }
  89. size_t IOSurfaceHandle::bytes_per_row() const
  90. {
  91. return IOSurfaceGetBytesPerRow(m_ref_wrapper->ref);
  92. }
  93. void* IOSurfaceHandle::data() const
  94. {
  95. return IOSurfaceGetBaseAddress(m_ref_wrapper->ref);
  96. }
  97. void* IOSurfaceHandle::core_foundation_pointer() const
  98. {
  99. return m_ref_wrapper->ref;
  100. }
  101. }