summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Michael <cp.michael@samsung.com>2019-03-19 09:57:12 -0400
committerChristopher Michael <cp.michael@samsung.com>2019-03-21 14:00:15 -0400
commitf74faaa00d60e3190b73bf83edee872ee8d2dbc5 (patch)
tree9a50664dec0aa3694d01b789893ebf51db366a70
parent1dd78ad7a551fefed496a93b34973e2a765b7379 (diff)
evas drm: Fix software output rotation
Don't use redraws_clear to handle buffer swapping. Buffer swapping should be done on outbuf_flush. This patch fixes evas drm software output rotation (along with other patches in the series). ref T7690 @fix Differential Revision: https://phab.enlightenment.org/D8403
-rw-r--r--src/modules/evas/engines/drm/evas_engine.h1
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c252
2 files changed, 124 insertions, 129 deletions
diff --git a/src/modules/evas/engines/drm/evas_engine.h b/src/modules/evas/engines/drm/evas_engine.h
index ea8a6cec03..ecaedc5c1b 100644
--- a/src/modules/evas/engines/drm/evas_engine.h
+++ b/src/modules/evas/engines/drm/evas_engine.h
@@ -82,6 +82,5 @@ Render_Output_Swap_Mode _outbuf_state_get(Outbuf *ob);
82void *_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); 82void *_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
83void _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); 83void _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
84void _outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage, Tilebuf_Rect *buffer_damage, Evas_Render_Mode render_mode); 84void _outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage, Tilebuf_Rect *buffer_damage, Evas_Render_Mode render_mode);
85void _outbuf_redraws_clear(Outbuf *ob);
86 85
87#endif 86#endif
diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c
index f53f9683db..1da70a495e 100644
--- a/src/modules/evas/engines/drm/evas_outbuf.c
+++ b/src/modules/evas/engines/drm/evas_outbuf.c
@@ -8,26 +8,6 @@
8#define MAX_BUFFERS 10 8#define MAX_BUFFERS 10
9#define QUEUE_TRIM_DURATION 100 9#define QUEUE_TRIM_DURATION 100
10 10
11static void
12_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
13{
14 /* Ecore_Drm2_Plane *plane; */
15 Outbuf_Fb *ofb;
16
17 ofb = ob->priv.draw;
18 if (!ofb) return;
19
20 ecore_drm2_fb_dirty(ofb->fb, rects, count);
21
22 if (!ob->priv.plane)
23 ob->priv.plane = ecore_drm2_plane_assign(ob->priv.output, ofb->fb, 0, 0);
24 else ecore_drm2_plane_fb_set(ob->priv.plane, ofb->fb);
25
26 ecore_drm2_fb_flip(ofb->fb, ob->priv.output);
27 ofb->drawn = EINA_TRUE;
28 ofb->age = 0;
29}
30
31static Outbuf_Fb * 11static Outbuf_Fb *
32_outbuf_fb_create(Outbuf *ob, int w, int h) 12_outbuf_fb_create(Outbuf *ob, int w, int h)
33{ 13{
@@ -65,6 +45,126 @@ _outbuf_fb_destroy(Outbuf_Fb *ofb)
65 free(ofb); 45 free(ofb);
66} 46}
67 47
48static Outbuf_Fb *
49_outbuf_fb_wait(Outbuf *ob)
50{
51 Eina_List *l;
52 Outbuf_Fb *ofb, *best = NULL;
53 int best_age = -1, num_required = 1, num_allocated = 0;
54
55 /* We pick the oldest available buffer to avoid using the same two
56 * repeatedly and then having the third be stale when we need it
57 */
58 EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb)
59 {
60 num_allocated++;
61 if (ecore_drm2_fb_busy_get(ofb->fb))
62 {
63 num_required++;
64 continue;
65 }
66 if (ofb->valid && (ofb->age > best_age))
67 {
68 best = ofb;
69 best_age = best->age;
70 }
71 }
72
73 if (num_required < num_allocated)
74 ob->priv.unused_duration++;
75 else
76 ob->priv.unused_duration = 0;
77
78 /* If we've had unused buffers for longer than QUEUE_TRIM_DURATION, then
79 * destroy the oldest buffer (currently in best) and recursively call
80 * ourself to get the next oldest.
81 */
82 if (best && (ob->priv.unused_duration > QUEUE_TRIM_DURATION))
83 {
84 ob->priv.unused_duration = 0;
85 ob->priv.fb_list = eina_list_remove(ob->priv.fb_list, best);
86 _outbuf_fb_destroy(best);
87 best = _outbuf_fb_wait(ob);
88 }
89
90 return best;
91}
92
93static Outbuf_Fb *
94_outbuf_fb_assign(Outbuf *ob)
95{
96 int fw = 0, fh = 0;
97 Outbuf_Fb *ofb;
98 Eina_List *l;
99
100 ob->priv.draw = _outbuf_fb_wait(ob);
101 if (!ob->priv.draw)
102 {
103 EINA_SAFETY_ON_TRUE_RETURN_VAL(eina_list_count(ob->priv.fb_list) >= MAX_BUFFERS, NULL);
104
105 if ((ob->rotation == 0) || (ob->rotation == 180))
106 {
107 fw = ob->w;
108 fh = ob->h;
109 }
110 else if ((ob->rotation == 90) || (ob->rotation == 270))
111 {
112 fw = ob->h;
113 fh = ob->w;
114 }
115 ob->priv.draw = _outbuf_fb_create(ob, fw, fh);
116 if (ob->priv.draw)
117 ob->priv.fb_list = eina_list_append(ob->priv.fb_list, ob->priv.draw);
118 }
119
120 while (!ob->priv.draw)
121 {
122 ecore_drm2_fb_release(ob->priv.output, EINA_TRUE);
123 ob->priv.draw = _outbuf_fb_wait(ob);
124 }
125
126 EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb)
127 {
128 if ((ofb->valid) && (ofb->drawn))
129 {
130 ofb->age++;
131 if (ofb->age > 4)
132 {
133 ofb->age = 0;
134 ofb->drawn = EINA_FALSE;
135 }
136 }
137 }
138
139 return ob->priv.draw;
140}
141
142static void
143_outbuf_buffer_swap(Outbuf *ob)
144{
145 Outbuf_Fb *ofb;
146
147 ofb = ob->priv.draw;
148 if (!ofb)
149 {
150 ecore_drm2_fb_release(ob->priv.output, EINA_TRUE);
151 ofb = _outbuf_fb_assign(ob);
152 if (!ofb)
153 {
154 ERR("Could not assign front buffer");
155 return;
156 }
157 }
158
159 if (!ob->priv.plane)
160 ob->priv.plane = ecore_drm2_plane_assign(ob->priv.output, ofb->fb, 0, 0);
161 else ecore_drm2_plane_fb_set(ob->priv.plane, ofb->fb);
162
163 ecore_drm2_fb_flip(ofb->fb, ob->priv.output);
164 ofb->drawn = EINA_TRUE;
165 ofb->age = 0;
166}
167
68Outbuf * 168Outbuf *
69_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) 169_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
70{ 170{
@@ -128,7 +228,6 @@ _outbuf_rotation_get(Outbuf *ob)
128void 228void
129_outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth) 229_outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth)
130{ 230{
131 Outbuf_Fb *ofb;
132 unsigned int format = DRM_FORMAT_ARGB8888; 231 unsigned int format = DRM_FORMAT_ARGB8888;
133 232
134 switch (depth) 233 switch (depth)
@@ -174,6 +273,8 @@ _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth)
174 (ob->depth == depth) && (ob->format == format)) 273 (ob->depth == depth) && (ob->format == format))
175 return; 274 return;
176 275
276 while (ecore_drm2_fb_release(ob->priv.output, EINA_TRUE));
277
177 ob->w = w; 278 ob->w = w;
178 ob->h = h; 279 ob->h = h;
179 ob->depth = depth; 280 ob->depth = depth;
@@ -181,112 +282,15 @@ _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth)
181 ob->rotation = rotation; 282 ob->rotation = rotation;
182 ob->priv.unused_duration = 0; 283 ob->priv.unused_duration = 0;
183 284
184 EINA_LIST_FREE(ob->priv.fb_list, ofb)
185 _outbuf_fb_destroy(ofb);
186
187 /* TODO: idle flush */ 285 /* TODO: idle flush */
188} 286}
189 287
190static Outbuf_Fb *
191_outbuf_fb_wait(Outbuf *ob)
192{
193 Eina_List *l;
194 Outbuf_Fb *ofb, *best = NULL;
195 int best_age = -1, num_required = 1, num_allocated = 0;
196
197 /* We pick the oldest available buffer to avoid using the same two
198 * repeatedly and then having the third be stale when we need it
199 */
200 EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb)
201 {
202 num_allocated++;
203 if (ecore_drm2_fb_busy_get(ofb->fb))
204 {
205 num_required++;
206 continue;
207 }
208 if (ofb->valid && (ofb->age > best_age))
209 {
210 best = ofb;
211 best_age = best->age;
212 }
213 }
214
215 if (num_required < num_allocated)
216 ob->priv.unused_duration++;
217 else
218 ob->priv.unused_duration = 0;
219
220 /* If we've had unused buffers for longer than QUEUE_TRIM_DURATION, then
221 * destroy the oldest buffer (currently in best) and recursively call
222 * ourself to get the next oldest.
223 */
224 if (best && (ob->priv.unused_duration > QUEUE_TRIM_DURATION))
225 {
226 ob->priv.unused_duration = 0;
227 ob->priv.fb_list = eina_list_remove(ob->priv.fb_list, best);
228 _outbuf_fb_destroy(best);
229 best = _outbuf_fb_wait(ob);
230 }
231
232 return best;
233}
234
235static Eina_Bool
236_outbuf_fb_assign(Outbuf *ob)
237{
238 int fw = 0, fh = 0;
239 Outbuf_Fb *ofb;
240 Eina_List *l;
241
242 ob->priv.draw = _outbuf_fb_wait(ob);
243 if (!ob->priv.draw)
244 {
245 EINA_SAFETY_ON_TRUE_RETURN_VAL(eina_list_count(ob->priv.fb_list) >= MAX_BUFFERS, EINA_FALSE);
246
247 if ((ob->rotation == 0) || (ob->rotation == 180))
248 {
249 fw = ob->w;
250 fh = ob->h;
251 }
252 else if ((ob->rotation == 90) || (ob->rotation == 270))
253 {
254 fw = ob->h;
255 fh = ob->w;
256 }
257 ob->priv.draw = _outbuf_fb_create(ob, fw, fh);
258 if (ob->priv.draw)
259 ob->priv.fb_list = eina_list_append(ob->priv.fb_list, ob->priv.draw);
260 }
261
262 while (!ob->priv.draw)
263 {
264 ecore_drm2_fb_release(ob->priv.output, EINA_TRUE);
265 ob->priv.draw = _outbuf_fb_wait(ob);
266 }
267
268 EINA_LIST_FOREACH(ob->priv.fb_list, l, ofb)
269 {
270 if ((ofb->valid) && (ofb->drawn))
271 {
272 ofb->age++;
273 if (ofb->age > 4)
274 {
275 ofb->age = 0;
276 ofb->drawn = EINA_FALSE;
277 }
278 }
279 }
280
281 return EINA_TRUE;
282}
283
284Render_Output_Swap_Mode 288Render_Output_Swap_Mode
285_outbuf_state_get(Outbuf *ob) 289_outbuf_state_get(Outbuf *ob)
286{ 290{
287 int age; 291 int age;
288 292
289 if (!_outbuf_fb_assign(ob)) return MODE_FULL; 293 if (!ob->priv.draw) return MODE_FULL;
290 294
291 age = ob->priv.draw->age; 295 age = ob->priv.draw->age;
292 if (age > 4) return MODE_FULL; 296 if (age > 4) return MODE_FULL;
@@ -538,14 +542,6 @@ _outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf_Rect
538 542
539 i++; 543 i++;
540 } 544 }
541}
542
543void
544_outbuf_redraws_clear(Outbuf *ob)
545{
546 if (!ob->priv.rect_count) return;
547 545
548 _outbuf_buffer_swap(ob, ob->priv.rects, ob->priv.rect_count); 546 _outbuf_buffer_swap(ob);
549 free(ob->priv.rects);
550 ob->priv.rect_count = 0;
551} 547}