summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/portal/pipewire_utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/modules/portal/pipewire_utils.h')
-rw-r--r--third_party/libwebrtc/modules/portal/pipewire_utils.h75
1 files changed, 75 insertions, 0 deletions
diff --git a/third_party/libwebrtc/modules/portal/pipewire_utils.h b/third_party/libwebrtc/modules/portal/pipewire_utils.h
index 8344a8cefb..c1327b85c9 100644
--- a/third_party/libwebrtc/modules/portal/pipewire_utils.h
+++ b/third_party/libwebrtc/modules/portal/pipewire_utils.h
@@ -11,6 +11,21 @@
#ifndef MODULES_PORTAL_PIPEWIRE_UTILS_H_
#define MODULES_PORTAL_PIPEWIRE_UTILS_H_
+#include <errno.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+// static
+struct dma_buf_sync {
+ uint64_t flags;
+};
+#define DMA_BUF_SYNC_READ (1 << 0)
+#define DMA_BUF_SYNC_START (0 << 2)
+#define DMA_BUF_SYNC_END (1 << 2)
+#define DMA_BUF_BASE 'b'
+#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
+
struct pw_thread_loop;
namespace webrtc {
@@ -32,6 +47,66 @@ class PipeWireThreadLoopLock {
pw_thread_loop* const loop_;
};
+// We should synchronize DMA Buffer object access from CPU to avoid potential
+// cache incoherency and data loss.
+// See
+// https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html#cpu-access-to-dma-buffer-objects
+static bool SyncDmaBuf(int fd, uint64_t start_or_end) {
+ struct dma_buf_sync sync = {0};
+
+ sync.flags = start_or_end | DMA_BUF_SYNC_READ;
+
+ while (true) {
+ int ret;
+ ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync);
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ } else if (ret == -1) {
+ return false;
+ } else {
+ break;
+ }
+ }
+
+ return true;
+}
+
+class ScopedBuf {
+ public:
+ ScopedBuf() {}
+ ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false)
+ : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {}
+ ~ScopedBuf() {
+ if (map_ != MAP_FAILED) {
+ if (is_dma_buf_) {
+ SyncDmaBuf(fd_, DMA_BUF_SYNC_END);
+ }
+ munmap(map_, map_size_);
+ }
+ }
+
+ explicit operator bool() { return map_ != MAP_FAILED; }
+
+ void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) {
+ map_ = map;
+ map_size_ = map_size;
+ is_dma_buf_ = is_dma_buf;
+ fd_ = fd;
+
+ if (is_dma_buf_) {
+ SyncDmaBuf(fd_, DMA_BUF_SYNC_START);
+ }
+ }
+
+ uint8_t* get() { return map_; }
+
+ protected:
+ uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED);
+ int map_size_;
+ int fd_;
+ bool is_dma_buf_;
+};
+
} // namespace webrtc
#endif // MODULES_PORTAL_PIPEWIRE_UTILS_H_