summaryrefslogtreecommitdiff
path: root/wm/somebar/src/shm_buffer.cpp
blob: 59baf6f474b90ba4a3f7235582b5f42768850be4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// somebar - dwl bar
// See LICENSE file for copyright and license details.

#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "shm_buffer.hpp"
#include "common.hpp"

static int createAnonShm();
constexpr int n = 2;

ShmBuffer::ShmBuffer(int w, int h, wl_shm_format format)
	: width(w)
	, height(h)
	, stride(w*4)
{
	auto oneSize = stride*size_t(h);
	auto totalSize = oneSize * n;
	auto fd = createAnonShm();
	if (fd < 0) {
		diesys("memfd_create");
	}
	if (ftruncate(fd, totalSize) < 0) {
		diesys("ftruncate");
	}
	auto pool = wl_shm_create_pool(shm, fd, totalSize);
	auto ptr = reinterpret_cast<uint8_t*>(mmap(nullptr, totalSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
	if (!ptr) {
		diesys("mmap");
	}
	_mapping = MemoryMapping {ptr, totalSize};
	close(fd);
	for (auto i=0; i<n; i++) {
		auto offset = oneSize*i;
		_buffers[i] = {
			ptr+offset,
			wl_unique_ptr<wl_buffer> { wl_shm_pool_create_buffer(pool, offset, width, height, stride, format) },
		};
	}
	wl_shm_pool_destroy(pool);
}

uint8_t* ShmBuffer::data()
{
	return _buffers[_current].data;
}

wl_buffer* ShmBuffer::buffer()
{
	return _buffers[_current].buffer.get();
}

void ShmBuffer::flip()
{
	_current = 1-_current;
}

#if defined(__linux__)
int createAnonShm() {
	return memfd_create("wl_shm", MFD_CLOEXEC);
}
#elif defined(__FreeBSD__)
int createAnonShm() {
	auto fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0600);
	setCloexec(fd);
	return fd;
}
#elif defined(__OpenBSD__)
int createAnonShm() {
	char name[] = "/wl_shm-XXXXXX";
	auto fd = shm_mkstemp(name);
	if (fd >= 0) {
		auto res = shm_unlink(name);
		if (res < 0) {
			return res;
		}
	}
	setCloexec(fd);
	return fd;
}
#else
#error "your system has no sane method of creating an anonymous shared memory object. no, calling shm_open in a loop is not sane."
#endif