File: buffer.c

package info (click to toggle)
wlroots 0.19.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,592 kB
  • sloc: ansic: 75,754; xml: 2,739; sh: 33; makefile: 23
file content (137 lines) | stat: -rw-r--r-- 3,488 bytes parent folder | download | duplicates (3)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <assert.h>
#include <drm_fourcc.h>
#include <string.h>
#include <wlr/interfaces/wlr_buffer.h>
#include "render/pixel_format.h"
#include "types/wlr_buffer.h"

void wlr_buffer_init(struct wlr_buffer *buffer,
		const struct wlr_buffer_impl *impl, int width, int height) {
	assert(impl->destroy);
	if (impl->begin_data_ptr_access || impl->end_data_ptr_access) {
		assert(impl->begin_data_ptr_access && impl->end_data_ptr_access);
	}

	*buffer = (struct wlr_buffer){
		.impl = impl,
		.width = width,
		.height = height,
	};

	wl_signal_init(&buffer->events.destroy);
	wl_signal_init(&buffer->events.release);

	wlr_addon_set_init(&buffer->addons);
}

void wlr_buffer_finish(struct wlr_buffer *buffer) {
	wl_signal_emit_mutable(&buffer->events.destroy, NULL);
	wlr_addon_set_finish(&buffer->addons);

	assert(wl_list_empty(&buffer->events.destroy.listener_list));
	assert(wl_list_empty(&buffer->events.release.listener_list));
}

static void buffer_consider_destroy(struct wlr_buffer *buffer) {
	if (!buffer->dropped || buffer->n_locks > 0) {
		return;
	}

	assert(!buffer->accessing_data_ptr);

	buffer->impl->destroy(buffer);
}

void wlr_buffer_drop(struct wlr_buffer *buffer) {
	if (buffer == NULL) {
		return;
	}

	assert(!buffer->dropped);
	buffer->dropped = true;
	buffer_consider_destroy(buffer);
}

struct wlr_buffer *wlr_buffer_lock(struct wlr_buffer *buffer) {
	buffer->n_locks++;
	return buffer;
}

void wlr_buffer_unlock(struct wlr_buffer *buffer) {
	if (buffer == NULL) {
		return;
	}

	assert(buffer->n_locks > 0);
	buffer->n_locks--;

	if (buffer->n_locks == 0) {
		wl_signal_emit_mutable(&buffer->events.release, NULL);
	}

	buffer_consider_destroy(buffer);
}

bool wlr_buffer_get_dmabuf(struct wlr_buffer *buffer,
		struct wlr_dmabuf_attributes *attribs) {
	if (!buffer->impl->get_dmabuf) {
		return false;
	}
	return buffer->impl->get_dmabuf(buffer, attribs);
}

bool wlr_buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags,
		void **data, uint32_t *format, size_t *stride) {
	assert(!buffer->accessing_data_ptr);
	if (!buffer->impl->begin_data_ptr_access) {
		return false;
	}
	if (!buffer->impl->begin_data_ptr_access(buffer, flags, data, format, stride)) {
		return false;
	}
	buffer->accessing_data_ptr = true;
	return true;
}

void wlr_buffer_end_data_ptr_access(struct wlr_buffer *buffer) {
	assert(buffer->accessing_data_ptr);
	buffer->impl->end_data_ptr_access(buffer);
	buffer->accessing_data_ptr = false;
}

bool wlr_buffer_get_shm(struct wlr_buffer *buffer,
		struct wlr_shm_attributes *attribs) {
	if (!buffer->impl->get_shm) {
		return false;
	}
	return buffer->impl->get_shm(buffer, attribs);
}

bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) {
	void *data;
	uint32_t format;
	size_t stride;
	struct wlr_dmabuf_attributes dmabuf;
	struct wlr_shm_attributes shm;
	if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
		format = dmabuf.format;
	} else if (wlr_buffer_get_shm(buffer, &shm)) {
		format = shm.format;
	} else if (wlr_buffer_begin_data_ptr_access(buffer,
			WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
		bool opaque = false;
		if (buffer->width == 1 && buffer->height == 1 && format == DRM_FORMAT_ARGB8888) {
			// Special case for single-pixel-buffer-v1
			const uint8_t *argb8888 = data; // little-endian byte order
			opaque = argb8888[3] == 0xFF;
		}
		wlr_buffer_end_data_ptr_access(buffer);
		if (opaque) {
			return true;
		}
	} else {
		return false;
	}

	return !pixel_format_has_alpha(format);
}