keyrouter: Fix wrong return value
[platform/core/uifw/libds-tizen.git] / src / libds / output.c
1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include "libds/log.h"
5 #include "libds/output.h"
6 #include "libds/interfaces/output.h"
7
8 static void output_handle_display_destroy(struct wl_listener *listener,
9         void *data);
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);
14
15 WL_EXPORT void
16 ds_output_init(struct ds_output *output, struct ds_backend *backend,
17         const struct ds_output_interface *iface, struct wl_display *display)
18 {
19     assert(iface->commit);
20
21     output->backend = backend;
22     output->iface = iface;
23     output->display = display;
24
25     wl_list_init(&output->modes);
26
27     wl_signal_init(&output->events.destroy);
28     wl_signal_init(&output->events.frame);
29     wl_signal_init(&output->events.commit);
30
31     output->display_destroy.notify = output_handle_display_destroy;
32     wl_display_add_destroy_listener(display, &output->display_destroy);
33 }
34
35 WL_EXPORT void
36 ds_output_destroy(struct ds_output *output)
37 {
38     wl_list_remove(&output->display_destroy.link);
39
40     wl_signal_emit(&output->events.destroy, output);
41
42     if (output->iface && output->iface->destroy)
43         output->iface->destroy(output);
44     else
45         free(output);
46 }
47
48 void
49 ds_output_enable(struct ds_output *output)
50 {
51     output_enable(output, true);
52 }
53
54 void
55 ds_output_disable(struct ds_output *output)
56 {
57     output_enable(output, false);
58 }
59
60 WL_EXPORT bool
61 ds_output_commit(struct ds_output *output)
62 {
63     // TODO signal precommit
64
65     if (!output->iface->commit(output)) {
66         return false;
67     }
68
69     output_state_clear(&output->pending);
70
71     // TODO signal commit
72
73     return true;
74 }
75
76 WL_EXPORT void
77 ds_output_attach_buffer(struct ds_output *output, struct ds_buffer *buffer)
78 {
79     output_state_clear_buffer(&output->pending);
80     output->pending.committed |= DS_OUTPUT_STATE_BUFFER;
81     output->pending.buffer = ds_buffer_lock(buffer);
82 }
83
84 WL_EXPORT const struct ds_output_mode *
85 ds_output_get_preferred_mode(struct ds_output *output)
86 {
87     struct ds_output_mode *mode;
88
89     if (wl_list_empty(&output->modes))
90         return NULL;
91
92     wl_list_for_each(mode, &output->modes, link) {
93         if (mode->preferred)
94             return mode;
95     }
96
97     // No preferred mode, choose the first one
98     return wl_container_of(output->modes.next, mode, link);
99 }
100
101 WL_EXPORT void
102 ds_output_set_mode(struct ds_output *output, const struct ds_output_mode *mode)
103 {
104     output_state_clear_mode(&output->pending);
105
106     if (output->current_mode == mode) {
107         return;
108     }
109
110     output->pending.committed |= DS_OUTPUT_STATE_MODE;
111     output->pending.mode_type = DS_OUTPUT_STATE_MODE_FIXED;
112     output->pending.mode = mode;
113 }
114
115 WL_EXPORT void
116 ds_output_set_custom_mode(struct ds_output *output,
117         int32_t width, int32_t height, int32_t refresh)
118 {
119     output_state_clear_mode(&output->pending);
120
121     if (output->width == width && output->height == height &&
122             output->refresh == refresh)
123         return;
124
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;
130 }
131
132 WL_EXPORT void
133 ds_output_add_destroy_listener(struct ds_output *output,
134         struct wl_listener *listener)
135 {
136     wl_signal_add(&output->events.destroy, listener);
137 }
138
139 WL_EXPORT void
140 ds_output_add_frame_listener(struct ds_output *output,
141         struct wl_listener *listener)
142 {
143     wl_signal_add(&output->events.frame, listener);
144 }
145
146 WL_EXPORT void
147 ds_output_add_commit_listener(struct ds_output *output,
148         struct wl_listener *listener)
149 {
150     wl_signal_add(&output->events.commit, listener);
151 }
152
153 void
154 ds_output_update_custom_mode(struct ds_output *output,
155         int32_t width, int32_t height, int32_t refresh)
156 {
157     if (output->width == width && output->height == height &&
158             output->refresh == refresh)
159         return;
160
161     output->width = width;
162     output->height = height;
163     output->refresh = refresh;
164 }
165
166 static void
167 output_handle_display_destroy(struct wl_listener *listener, void *data)
168 {
169     struct ds_output *output;
170
171     output = wl_container_of(listener, output, display_destroy);
172     // TODO
173     // destroy wl_global
174 }
175
176 static void
177 output_state_clear(struct ds_output_state *state)
178 {
179     output_state_clear_buffer(state);
180     state->committed = 0;
181 }
182
183 static void
184 output_state_clear_buffer(struct ds_output_state *state)
185 {
186     if (!(state->committed & DS_OUTPUT_STATE_BUFFER))
187         return;
188
189     ds_buffer_unlock(state->buffer);
190     state->buffer = NULL;
191
192     state->committed &= ~DS_OUTPUT_STATE_BUFFER;
193 }
194
195 static void
196 output_enable(struct ds_output *output, bool enable)
197 {
198     if (output->enabled == enable) {
199         output->pending.committed &= ~DS_OUTPUT_STATE_ENABLED;
200         return;
201     }
202
203     output->pending.committed |= DS_OUTPUT_STATE_ENABLED;
204     output->pending.enabled = enable;
205 }
206
207 static void
208 output_state_clear_mode(struct ds_output_state *state)
209 {
210     if (!(state->committed & DS_OUTPUT_STATE_MODE))
211         return;
212
213     state->mode = NULL;
214     state->committed &= ~DS_OUTPUT_STATE_MODE;
215 }