5 #include "libds/output.h"
6 #include "libds/interfaces/output.h"
8 static void output_handle_display_destroy(struct wl_listener *listener,
10 static void output_enable(struct ds_output *output, bool enable);
11 static void output_state_clear(struct ds_output_state *state);
12 static void output_state_clear_buffer(struct ds_output_state *state);
13 static void output_state_clear_mode(struct ds_output_state *state);
16 ds_output_init(struct ds_output *output, struct ds_backend *backend,
17 const struct ds_output_interface *iface, struct wl_display *display)
19 assert(iface->commit);
21 output->backend = backend;
22 output->iface = iface;
23 output->display = display;
25 wl_list_init(&output->modes);
27 wl_signal_init(&output->events.destroy);
28 wl_signal_init(&output->events.frame);
29 wl_signal_init(&output->events.commit);
31 output->display_destroy.notify = output_handle_display_destroy;
32 wl_display_add_destroy_listener(display, &output->display_destroy);
36 ds_output_destroy(struct ds_output *output)
38 wl_list_remove(&output->display_destroy.link);
40 wl_signal_emit(&output->events.destroy, output);
42 if (output->iface && output->iface->destroy)
43 output->iface->destroy(output);
49 ds_output_enable(struct ds_output *output)
51 output_enable(output, true);
55 ds_output_disable(struct ds_output *output)
57 output_enable(output, false);
61 ds_output_commit(struct ds_output *output)
63 // TODO signal precommit
65 if (!output->iface->commit(output)) {
69 output_state_clear(&output->pending);
77 ds_output_attach_buffer(struct ds_output *output, struct ds_buffer *buffer)
79 output_state_clear_buffer(&output->pending);
80 output->pending.committed |= DS_OUTPUT_STATE_BUFFER;
81 output->pending.buffer = ds_buffer_lock(buffer);
84 WL_EXPORT const struct ds_output_mode *
85 ds_output_get_preferred_mode(struct ds_output *output)
87 struct ds_output_mode *mode;
89 if (wl_list_empty(&output->modes))
92 wl_list_for_each(mode, &output->modes, link) {
97 // No preferred mode, choose the first one
98 return wl_container_of(output->modes.next, mode, link);
102 ds_output_set_mode(struct ds_output *output, const struct ds_output_mode *mode)
104 output_state_clear_mode(&output->pending);
106 if (output->current_mode == mode) {
110 output->pending.committed |= DS_OUTPUT_STATE_MODE;
111 output->pending.mode_type = DS_OUTPUT_STATE_MODE_FIXED;
112 output->pending.mode = mode;
116 ds_output_set_custom_mode(struct ds_output *output,
117 int32_t width, int32_t height, int32_t refresh)
119 output_state_clear_mode(&output->pending);
121 if (output->width == width && output->height == height &&
122 output->refresh == refresh)
125 output->pending.committed |= DS_OUTPUT_STATE_MODE;
126 output->pending.mode_type = DS_OUTPUT_STATE_MODE_CUSTOM;
127 output->pending.custom_mode.width = width;
128 output->pending.custom_mode.height = height;
129 output->pending.custom_mode.refresh = refresh;
133 ds_output_add_destroy_listener(struct ds_output *output,
134 struct wl_listener *listener)
136 wl_signal_add(&output->events.destroy, listener);
140 ds_output_add_frame_listener(struct ds_output *output,
141 struct wl_listener *listener)
143 wl_signal_add(&output->events.frame, listener);
147 ds_output_add_commit_listener(struct ds_output *output,
148 struct wl_listener *listener)
150 wl_signal_add(&output->events.commit, listener);
154 ds_output_update_custom_mode(struct ds_output *output,
155 int32_t width, int32_t height, int32_t refresh)
157 if (output->width == width && output->height == height &&
158 output->refresh == refresh)
161 output->width = width;
162 output->height = height;
163 output->refresh = refresh;
167 output_handle_display_destroy(struct wl_listener *listener, void *data)
169 struct ds_output *output;
171 output = wl_container_of(listener, output, display_destroy);
177 output_state_clear(struct ds_output_state *state)
179 output_state_clear_buffer(state);
180 state->committed = 0;
184 output_state_clear_buffer(struct ds_output_state *state)
186 if (!(state->committed & DS_OUTPUT_STATE_BUFFER))
189 ds_buffer_unlock(state->buffer);
190 state->buffer = NULL;
192 state->committed &= ~DS_OUTPUT_STATE_BUFFER;
196 output_enable(struct ds_output *output, bool enable)
198 if (output->enabled == enable) {
199 output->pending.committed &= ~DS_OUTPUT_STATE_ENABLED;
203 output->pending.committed |= DS_OUTPUT_STATE_ENABLED;
204 output->pending.enabled = enable;
208 output_state_clear_mode(struct ds_output_state *state)
210 if (!(state->committed & DS_OUTPUT_STATE_MODE))
214 state->committed &= ~DS_OUTPUT_STATE_MODE;