waylandsink : rollback getting video buffer size
[platform/upstream/gstreamer.git] / ext / wayland / wlwindow.c
1 /* GStreamer Wayland video sink
2  *
3  * Copyright (C) 2011 Intel Corporation
4  * Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
5  * Copyright (C) 2014 Collabora Ltd.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the Free
19  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301 USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
27 #include "gstwaylandsink.h"
28 #else
29 #include "wlwindow.h"
30 #endif
31 #include "wlshmallocator.h"
32 #include "wlbuffer.h"
33
34 enum
35 {
36   ROTATE_0_FLIP_NONE,
37   ROTATE_0_FLIP_HORIZONTAL,
38   ROTATE_0_FLIP_VERTICAL,
39   ROTATE_0_FLIP_BOTH,
40   ROTATE_90_FLIP_NONE = 10,
41   ROTATE_90_FLIP_HORIZONTAL,
42   ROTATE_90_FLIP_VERTICAL,
43   ROTATE_90_FLIP_BOTH,
44   ROTATE_180_FLIP_NONE = 20,
45   ROTATE_180_FLIP_HORIZONTAL,
46   ROTATE_180_FLIP_VERTICAL,
47   ROTATE_180_FLIP_BOTH,
48   ROTATE_270_FLIP_NONE = 30,
49   ROTATE_270_FLIP_HORIZONTAL,
50   ROTATE_270_FLIP_VERTICAL,
51   ROTATE_270_FLIP_BOTH,
52   ROTATE_NUM,
53 };
54
55 GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
56 #define GST_CAT_DEFAULT gstwayland_debug
57
58 G_DEFINE_TYPE (GstWlWindow, gst_wl_window, G_TYPE_OBJECT);
59
60 static void gst_wl_window_finalize (GObject * gobject);
61
62 static void
63 handle_ping (void *data, struct wl_shell_surface *shell_surface,
64     uint32_t serial)
65 {
66   wl_shell_surface_pong (shell_surface, serial);
67 }
68
69 static void
70 handle_configure (void *data, struct wl_shell_surface *shell_surface,
71     uint32_t edges, int32_t width, int32_t height)
72 {
73 }
74
75 static void
76 handle_popup_done (void *data, struct wl_shell_surface *shell_surface)
77 {
78 }
79
80 static const struct wl_shell_surface_listener shell_surface_listener = {
81   handle_ping,
82   handle_configure,
83   handle_popup_done
84 };
85
86 static void
87 gst_wl_window_class_init (GstWlWindowClass * klass)
88 {
89   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
90   FUNCTION;
91   gobject_class->finalize = gst_wl_window_finalize;
92 }
93
94 static void
95 gst_wl_window_init (GstWlWindow * self)
96 {
97   g_return_if_fail (self != NULL);
98   self->buffer_width = self->buffer_height = self->buffer_x = self->buffer_y =
99       0;
100 }
101
102 static void
103 gst_wl_window_finalize (GObject * gobject)
104 {
105   GstWlWindow *self = GST_WL_WINDOW (gobject);
106   FUNCTION;
107
108   if (self->shell_surface) {
109     wl_shell_surface_destroy (self->shell_surface);
110   }
111 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
112   if (self->video_object)
113     tizen_video_object_destroy (self->video_object);
114   if (self->tizen_area_viewport)
115     tizen_viewport_destroy (self->tizen_area_viewport);
116   if (self->tizen_video_viewport)
117     tizen_viewport_destroy (self->tizen_video_viewport);
118   if (self->tizen_video_dest_mode)
119     tizen_destination_mode_destroy (self->tizen_video_dest_mode);
120   if (self->tizen_area_dest_mode)
121     tizen_destination_mode_destroy (self->tizen_area_dest_mode);
122 #else
123   wl_viewport_destroy (self->video_viewport);
124   wl_viewport_destroy (self->area_viewport);
125 #endif
126   wl_subsurface_destroy (self->video_subsurface);
127   wl_surface_destroy (self->video_surface);
128
129   if (self->area_subsurface) {
130     wl_subsurface_destroy (self->area_subsurface);
131   }
132
133   wl_surface_destroy (self->area_surface);
134
135   g_clear_object (&self->display);
136
137   G_OBJECT_CLASS (gst_wl_window_parent_class)->finalize (gobject);
138 }
139
140 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
141 static void
142 gst_wl_window_map_sub_surface (GstWlDisplay * display, GstWlWindow * window,
143     GstVideoInfo * info)
144 {
145   /* A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
146    * and the parent surface is mapped */
147   GstBuffer *buf;
148   GstMapInfo mapinfo;
149   struct wl_buffer *wlbuf;
150   GstWlBuffer *gwlbuf;
151   GstWlShmAllocator *self = NULL;
152   FUNCTION;
153
154   g_return_if_fail (display != NULL);
155   g_return_if_fail (window != NULL);
156   g_return_if_fail (info != NULL);
157
158   self = GST_WL_SHM_ALLOCATOR (gst_wl_shm_allocator_get ());
159   self->display = display;
160
161   buf = gst_buffer_new_allocate (gst_wl_shm_allocator_get (), info->size, NULL);
162   gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
163   *((guint32 *) mapinfo.data) = 0;      /* paint it black */
164   gst_buffer_unmap (buf, &mapinfo);
165   wlbuf =
166       gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0),
167       display, info);
168
169   gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, display);
170   gst_wl_buffer_attach (gwlbuf, window->area_surface);
171
172   /* for tizen view port
173      When change area_surface, we don't need to commit anymore if we do below code.
174      such as gst_wl_window_set_render_rectangle() and */
175   GST_INFO
176       ("wl_surface_damage_buffer (area_surface(wl_surface)@%p, x@%d, y@%d, w@%d, h@%d)",
177       window->area_surface, 0, 0, info->width, info->height);
178   wl_surface_damage_buffer (window->area_surface, 0, 0, info->width,
179       info->height);
180   GST_INFO ("wl_surface_commit (area_surface(wl_surface)@%p)",
181       window->area_surface);
182   wl_surface_commit (window->area_surface);
183
184   /* at this point, the GstWlBuffer keeps the buffer
185    * alive and will free it on wl_buffer::release */
186   gst_buffer_unref (buf);
187 }
188 #endif
189
190 static GstWlWindow *
191 #if 1
192 /* for enlightment, we need to get parent to create  area_subsurface */
193 gst_wl_window_new_internal (GstWlDisplay * display, struct wl_surface *parent)
194 #else
195 gst_wl_window_new_internal (GstWlDisplay * display)
196 #endif
197 {
198   GstWlWindow *window;
199   GstVideoInfo info;
200 #ifndef TIZEN_FEATURE_WLSINK_ENHANCEMENT
201   GstBuffer *buf;
202   GstMapInfo mapinfo;
203   struct wl_buffer *wlbuf;
204   GstWlBuffer *gwlbuf;
205 #endif
206   struct wl_region *region;
207   FUNCTION;
208
209   window = g_object_new (GST_TYPE_WL_WINDOW, NULL);
210   window->display = g_object_ref (display);
211
212   window->area_surface = wl_compositor_create_surface (display->compositor);
213   GST_INFO
214       ("area_surface(wl_surface)@%p = wl_compositor_create_surface(wl_compositor@%p)",
215       window->area_surface, display->compositor);
216   window->video_surface = wl_compositor_create_surface (display->compositor);
217   GST_INFO
218       ("video_surface(wl_surface)@%p = wl_compositor_create_surface(wl_compositor@%p)",
219       window->video_surface, display->compositor);
220
221   GST_INFO ("wl_proxy_set_queue (area_surface@%p, wl_event_queue@%p)",
222       window->area_surface, display->queue);
223   wl_proxy_set_queue ((struct wl_proxy *) window->area_surface, display->queue);
224   GST_INFO ("wl_proxy_set_queue (video_surface@%p, wl_event_queue@%p)",
225       window->video_surface, display->queue);
226   wl_proxy_set_queue ((struct wl_proxy *) window->video_surface,
227       display->queue);
228
229 #if 1                           /* create shell_surface here for enlightenment */
230   /* go toplevel */
231   if (display->need_shell_surface) {
232     /* for internal window */
233     GST_INFO
234         ("wl_shell_surface@%p =  wl_shell_get_shell_surface (wl_shell@%p, area_subsurface(wl_surface)@%p)",
235         window->shell_surface, display->shell, window->area_surface);
236     window->shell_surface =
237         wl_shell_get_shell_surface (display->shell, window->area_surface);
238   } else if (display->use_parent_wl_surface) {
239 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
240     if (display->wl_surface_id && parent == NULL) {
241       window->area_subsurface =
242           tizen_policy_get_subsurface (display->tizen_policy,
243           window->area_surface, display->wl_surface_id);
244       GST_INFO
245           ("area_subsurface(wl_subsurface)@%p = tizen_policy_get_subsurface(tizen_policy@%p, area_surface(wl_surface)@%p, wl_surface_id@%d)",
246           window->area_subsurface, display->tizen_policy, window->area_surface,
247           display->wl_surface_id);
248       GST_INFO ("wl_subsurface_set_desync (area_subsurface(wl_subsurface)@%p)",
249           window->area_subsurface);
250       wl_subsurface_set_desync (window->area_subsurface);
251       GST_INFO ("wl_surface_commit (%p)", window->area_surface);
252       wl_surface_commit (window->area_surface);
253     } else {
254       GST_INFO (" wl_surface parent %p", parent);
255       window->area_subsurface =
256           wl_subcompositor_get_subsurface (display->subcompositor,
257           window->area_surface, parent);
258       GST_INFO
259           ("area_subsurface(wl_subsurface)@%p = wl_subcompositor_get_subsurface(wl_subcompositor@%p, area_surface(wl_surface)@%p, parent@%p)",
260           window->area_subsurface, display->subcompositor, window->area_surface,
261           parent);
262       GST_INFO ("wl_subsurface_set_desync (area_subsurface(wl_subsurface)@%p)",
263           window->area_subsurface);
264       wl_subsurface_set_desync (window->area_subsurface);
265     }
266 #else
267     /*for enlightment , below code is moved */
268     window->area_subsurface =
269         wl_subcompositor_get_subsurface (display->subcompositor,
270         window->area_surface, parent);
271     wl_subsurface_set_desync (window->area_subsurface);
272 #endif
273   }
274 #endif
275
276   /* embed video_surface in area_surface */
277   window->video_subsurface =
278       wl_subcompositor_get_subsurface (display->subcompositor,
279       window->video_surface, window->area_surface);
280   GST_INFO
281       ("video_subsurface(wl_subsurface)@%p = wl_subcompositor_get_subsurface(wl_subcompositor@%p, video_surface(wl_surface)@%p, area_surface(wl_surface)@%p)",
282       window->video_subsurface, display->subcompositor, window->video_surface,
283       window->area_surface);
284
285   GST_INFO ("wl_subsurface_set_desync (video_subsurface(wl_subsurface)@%p)",
286       window->video_subsurface);
287   wl_subsurface_set_desync (window->video_subsurface);
288   GST_INFO ("wl_surface_commit (%p)", window->video_surface);
289   wl_surface_commit (window->video_surface);
290
291 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
292   window->tizen_area_viewport =
293       tizen_video_get_viewport (display->tizen_video, window->area_surface);
294   GST_INFO
295       ("tizen_area_viewport(tizen_viewport)@%p = tizen_video_get_viewport(tizen_video@%p, area_surface(wl_surface)@%p)",
296       window->tizen_area_viewport, display->tizen_video, window->area_surface);
297   window->tizen_video_viewport =
298       tizen_video_get_viewport (display->tizen_video, window->video_surface);
299   GST_INFO
300       ("tizen_video_viewport(tizen_viewport)@%p = tizen_video_get_viewport(tizen_video@%p, video_surface(wl_surface)@%p)",
301       window->tizen_video_viewport, display->tizen_video,
302       window->video_surface);
303   window->tizen_video_dest_mode =
304       tizen_viewport_get_destination_mode (window->tizen_video_viewport);
305   GST_INFO
306       ("tizen_destination_mode@%p = tizen_viewport_get_destination_mode (tizen_video_viewport@%p)",
307       window->tizen_video_dest_mode, window->tizen_video_viewport);
308
309 #else
310   window->area_viewport = wl_scaler_get_viewport (display->scaler,
311       window->area_surface);
312   window->video_viewport = wl_scaler_get_viewport (display->scaler,
313       window->video_surface);
314 #endif
315   /* draw the area_subsurface */
316   gst_video_info_set_format (&info,
317       /* we want WL_SHM_FORMAT_XRGB8888 */
318 #if G_BYTE_ORDER == G_BIG_ENDIAN
319       GST_VIDEO_FORMAT_xRGB,
320 #else
321       GST_VIDEO_FORMAT_BGRx,
322 #endif
323       1, 1);
324
325 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
326   if (window->display->USE_TBM) {
327     /* Inform enlightenment of surface which render video */
328     /* tizen_video(tbm) render on video_surface */
329     window->video_object =
330         tizen_video_get_object (display->tizen_video, window->video_surface);
331
332     /* to use shm memory for mapping sub-surface, set FALSE to USE_TBM */
333     window->display->USE_TBM = FALSE;
334     gst_wl_window_map_sub_surface (display, window, &info);
335     /*restore USE_TBM */
336     window->display->USE_TBM = TRUE;
337   } else {
338     gst_wl_window_map_sub_surface (display, window, &info);
339   }
340 #else /* open source */
341   buf = gst_buffer_new_allocate (gst_wl_shm_allocator_get (), info.size, NULL);
342   gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
343   *((guint32 *) mapinfo.data) = 0;      /* paint it black */
344   gst_buffer_unmap (buf, &mapinfo);
345   wlbuf =
346       gst_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf, 0),
347       display, &info);
348   gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, display);
349   gst_wl_buffer_attach (gwlbuf, window->area_surface);
350
351   /* at this point, the GstWlBuffer keeps the buffer
352    * alive and will free it on wl_buffer::release */
353   gst_buffer_unref (buf);
354 #endif
355
356   /* do not accept input */
357   region = wl_compositor_create_region (display->compositor);
358   GST_INFO ("wl_region@%p = wl_compositor_create_region (wl_compositor@%p)",
359       region, display->compositor);
360   GST_INFO ("wl_surface_set_input_region (area_surface@%p, wl_region@%p)",
361       window->area_surface, region);
362   wl_surface_set_input_region (window->area_surface, region);
363   GST_INFO ("wl_region_destroy (wl_region@%p)", region);
364   wl_region_destroy (region);
365
366   region = wl_compositor_create_region (display->compositor);
367   GST_INFO ("wl_region@%p = wl_compositor_create_region (wl_compositor@%p)",
368       region, display->compositor);
369   GST_INFO ("wl_surface_set_input_region (video_surface@%p, wl_region@%p)",
370       window->video_surface, region);
371   wl_surface_set_input_region (window->video_surface, region);
372   GST_INFO ("wl_region_destroy (wl_region@%p)", region);
373   wl_region_destroy (region);
374
375 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
376   /* set area surface size by full mode(full size of parent window) , toplevel is set to fullmode too for convenient test */
377   if (window->tizen_area_viewport) {
378     int tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_FULL;
379
380     window->tizen_area_dest_mode =
381         tizen_viewport_get_destination_mode (window->tizen_area_viewport);
382     GST_INFO
383         ("tizen_destination_mode@%p = tizen_viewport_get_destination_mode (tizen_video_viewport@%p)",
384         window->tizen_area_dest_mode, window->tizen_area_viewport);
385     if (window->tizen_area_dest_mode) {
386       GST_INFO ("tizen_destination_mode_set (tizen_destination_mode@%p, @%d)",
387           window->tizen_area_dest_mode, tizen_disp_mode);
388       tizen_destination_mode_set (window->tizen_area_dest_mode,
389           tizen_disp_mode);
390     }
391     GST_INFO ("wl_surface_commit (area_surface@%p)", window->area_surface);
392     wl_surface_commit (window->area_surface);
393   }
394 #endif
395   return window;
396 }
397
398 GstWlWindow *
399 gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info)
400 {
401 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
402   GstWlWindow *window;
403   FUNCTION;
404
405 /* not create shell_surface here for enlightenment */
406   display->need_shell_surface = TRUE;
407   window = gst_wl_window_new_internal (display, NULL);
408
409   /* for tizen enlightenment */
410 #if 0
411   /* go toplevel */
412   window->shell_surface = wl_shell_get_shell_surface (display->shell,
413       window->area_surface);
414 #endif
415   if (window->shell_surface) {
416     GST_LOG
417         ("wl_shell_surface_add_listener (shell_surface@%p, wl_shell_surface_listener@%p, GstWlWindow@%p",
418         window->shell_surface, &shell_surface_listener, window);
419     wl_shell_surface_add_listener (window->shell_surface,
420         &shell_surface_listener, window);
421     GST_LOG ("wl_shell_surface_set_toplevel (shell_surface@%p",
422         window->shell_surface);
423     wl_shell_surface_set_toplevel (window->shell_surface);
424   } else {
425     GST_ERROR ("Unable to get wl_shell_surface");
426
427     g_object_unref (window);
428     return NULL;
429   }
430
431   /* toplevel is set to fullmode for convenient test in tizen_viewport enviroment, don't use below code */
432 #if 0
433   /* set the initial size to be the same as the reported video size */
434   width =
435       gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
436   gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
437 #endif
438   return window;
439
440 #else /* open source */
441   GstWlWindow *window;
442   gint width;
443
444   window = gst_wl_window_new_internal (display);
445
446   /* go toplevel */
447   window->shell_surface = wl_shell_get_shell_surface (display->shell,
448       window->area_surface);
449
450   if (window->shell_surface) {
451     wl_shell_surface_add_listener (window->shell_surface,
452         &shell_surface_listener, window);
453     wl_shell_surface_set_toplevel (window->shell_surface);
454   } else {
455     GST_ERROR ("Unable to get wl_shell_surface");
456
457     g_object_unref (window);
458     return NULL;
459   }
460
461   /* set the initial size to be the same as the reported video size */
462   width =
463       gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
464   gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
465
466   return window;
467 #endif
468 }
469
470
471 GstWlWindow *
472 gst_wl_window_new_in_surface (GstWlDisplay * display,
473     struct wl_surface * parent)
474 {
475 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
476   /* use App window */
477   GstWlWindow *window;
478   FUNCTION;
479
480   display->use_parent_wl_surface = TRUE;
481   if (parent) {
482     /*use wl_surface */
483     window = gst_wl_window_new_internal (display, parent);
484   } else {
485     /* use wl_surface id */
486     window = gst_wl_window_new_internal (display, NULL);
487   }
488
489   /*Area surface from App need to be under parent surface */
490   if (display->tizen_policy) {
491     GST_INFO ("tizen_policy_place_subsurface_below_parent (%p, %p)",
492         display->tizen_policy, window->area_subsurface);
493     tizen_policy_place_subsurface_below_parent (display->tizen_policy,
494         window->area_subsurface);
495     GST_INFO ("tizen_policy_place_subsurface_below_parent (%p, %p)",
496         display->tizen_policy, window->video_subsurface);
497     tizen_policy_place_subsurface_below_parent (display->tizen_policy,
498         window->video_subsurface);
499   }
500   return window;
501
502 #else /* open source */
503
504   GstWlWindow *window;
505   window = gst_wl_window_new_internal (display, parent);        //add parent for enlightment
506
507   /*for enlightment , move to gst_wl_window_new_internal() */
508 #if 0
509   /* embed in parent */
510   window->area_subsurface =
511       wl_subcompositor_get_subsurface (display->subcompositor,
512       window->area_surface, parent);
513   wl_subsurface_set_desync (window->area_subsurface);
514 #endif
515
516   return window;
517
518 #endif
519 }
520
521 GstWlDisplay *
522 gst_wl_window_get_display (GstWlWindow * window)
523 {
524   FUNCTION;
525   g_return_val_if_fail (window != NULL, NULL);
526
527   return g_object_ref (window->display);
528 }
529
530 struct wl_surface *
531 gst_wl_window_get_wl_surface (GstWlWindow * window)
532 {
533   FUNCTION;
534   g_return_val_if_fail (window != NULL, NULL);
535
536   return window->video_surface;
537 }
538
539 gboolean
540 gst_wl_window_is_toplevel (GstWlWindow * window)
541 {
542   FUNCTION;
543   g_return_val_if_fail (window != NULL, FALSE);
544
545   return (window->shell_surface != NULL);
546 }
547
548 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
549 static gint
550 gst_wl_window_find_transform (guint rotate_angle, guint flip)
551 {
552   gint transform = WL_OUTPUT_TRANSFORM_NORMAL;
553   guint combine = rotate_angle * 10 + flip;
554   FUNCTION;
555   GST_DEBUG ("rotate %d, flip %d, combine %d", rotate_angle, flip, combine);
556   switch (combine) {
557     case ROTATE_0_FLIP_NONE:
558       transform = WL_OUTPUT_TRANSFORM_NORMAL;
559       break;
560     case ROTATE_0_FLIP_HORIZONTAL:
561       transform = WL_OUTPUT_TRANSFORM_FLIPPED;
562       break;
563     case ROTATE_0_FLIP_VERTICAL:
564       transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
565       break;
566     case ROTATE_0_FLIP_BOTH:
567       transform = WL_OUTPUT_TRANSFORM_180;
568       break;
569     case ROTATE_90_FLIP_NONE:
570       transform = WL_OUTPUT_TRANSFORM_90;
571       break;
572     case ROTATE_90_FLIP_HORIZONTAL:
573       transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
574       break;
575     case ROTATE_90_FLIP_VERTICAL:
576       transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
577       break;
578     case ROTATE_90_FLIP_BOTH:
579       transform = WL_OUTPUT_TRANSFORM_270;
580       break;
581     case ROTATE_180_FLIP_NONE:
582       transform = WL_OUTPUT_TRANSFORM_180;
583       break;
584     case ROTATE_180_FLIP_HORIZONTAL:
585       transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
586       break;
587     case ROTATE_180_FLIP_VERTICAL:
588       transform = WL_OUTPUT_TRANSFORM_FLIPPED;
589       break;
590     case ROTATE_180_FLIP_BOTH:
591       transform = WL_OUTPUT_TRANSFORM_NORMAL;
592       break;
593     case ROTATE_270_FLIP_NONE:
594       transform = WL_OUTPUT_TRANSFORM_270;
595       break;
596     case ROTATE_270_FLIP_HORIZONTAL:
597       transform = WL_OUTPUT_TRANSFORM_FLIPPED_270;
598       break;
599     case ROTATE_270_FLIP_VERTICAL:
600       transform = WL_OUTPUT_TRANSFORM_FLIPPED_90;
601       break;
602     case ROTATE_270_FLIP_BOTH:
603       transform = WL_OUTPUT_TRANSFORM_90;
604       break;
605   }
606
607   return transform;
608 }
609
610 #endif
611 #if TIZEN_FEATURE_WLSINK_ENHANCEMENT
612 static void
613 gst_wl_window_resize_tizen_video_viewport (GstWlWindow * window,
614     gboolean commit)
615 {
616   gint transform = WL_OUTPUT_TRANSFORM_NORMAL;
617
618   FUNCTION;
619   g_return_if_fail (window->tizen_video_viewport != NULL);
620   g_return_if_fail (window->tizen_video_dest_mode != NULL);
621
622   /* Set source, wayland need to set "tizen_viewport_set_source" always when change video info,
623      aligned video issue=> ex) 854 x 480 video : aligned buffer size 864 x 480, so we need to set original video size by set source */
624   if (window->mode_crop.changed) {
625     /* we have known issue about mobile team kernel, when set orign green line can be shown with tbm */
626     GST_INFO
627         ("tizen_viewport_set_source (tizen_video_viewport@%p, x@%d, y@%d, w@%d, h@%d)",
628         window->tizen_video_viewport, window->mode_crop.x, window->mode_crop.y,
629         window->mode_crop.w, window->mode_crop.h);
630     tizen_viewport_set_source (window->tizen_video_viewport,
631         window->mode_crop.x, window->mode_crop.y, window->mode_crop.w,
632         window->mode_crop.h);
633     window->mode_crop.changed = FALSE;
634   }
635
636   /*set tizen destination mode */
637   if (window->disp_geo_method.changed) {
638     int tizen_disp_mode = -1;
639     switch (window->disp_geo_method.value) {
640
641       case DISP_GEO_METHOD_LETTER_BOX:
642         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_LETTER_BOX");
643         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_LETTER_BOX;
644         break;
645       case DISP_GEO_METHOD_ORIGIN_SIZE:
646         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_ORIGIN");
647         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_ORIGIN;
648         break;
649       case DISP_GEO_METHOD_FULL_SCREEN:
650         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_FULL");
651         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_FULL;
652         break;
653       case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
654         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_CROPPED_FULL");
655         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_CROPPED_FULL;
656         break;
657       case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
658         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER");
659         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER;
660         break;
661       case DISP_GEO_METHOD_CUSTOM_ROI:
662         GST_LOG ("DISP_GEO_METHOD_CUSTOM_ROI..need to set tizen disp mode");
663         GST_LOG ("Video need to set TIZEN_DESTINATION_MODE_TYPE_FULL");
664         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_FULL;
665         break;
666       default:
667         break;
668     }
669     if (tizen_disp_mode > -1) {
670       GST_INFO
671           ("tizen_destination_mode_set (tizen_destination_mode@%p, tizen_disp_mode@%d)",
672           window->tizen_video_dest_mode, tizen_disp_mode);
673       tizen_destination_mode_set (window->tizen_video_dest_mode,
674           tizen_disp_mode);
675     }
676     window->disp_geo_method.changed = FALSE;
677   }
678
679   if (window->disp_geo_method.value == DISP_GEO_METHOD_CUSTOM_ROI)
680     goto done;
681
682   /* Even though area_viewport is set to ROI mode, we can set below functions too if video_viewport is set to tizen_destination_mode_set. */
683 #ifdef ENABLE_FUNCTION
684   /* set or unset follow parent transform */
685   if (window->follow_parent_transform.changed
686       && !gst_wl_window_is_toplevel (window)) {
687     if (window->follow_parent_transform.value) {
688       GST_INFO
689           ("tizen_destination_mode_follow_parent_transform (tizen_destination_mode@%p)",
690           window->tizen_area_dest_mode);
691       tizen_destination_mode_follow_parent_transform
692           (window->tizen_area_dest_mode);
693       GST_INFO
694           ("tizen_destination_mode_follow_parent_transform (tizen_destination_mode@%p)",
695           window->tizen_video_dest_mode);
696       tizen_destination_mode_follow_parent_transform
697           (window->tizen_video_dest_mode);
698
699     } else {
700       GST_INFO
701           ("tizen_destination_mode_unfollow_parent_transform (tizen_destination_mode@%p)",
702           window->tizen_area_dest_mode);
703       tizen_destination_mode_unfollow_parent_transform
704           (window->tizen_area_dest_mode);
705       GST_INFO
706           ("tizen_destination_mode_unfollow_parent_transform (tizen_destination_mode@%p)",
707           window->tizen_video_dest_mode);
708       tizen_destination_mode_unfollow_parent_transform
709           (window->tizen_video_dest_mode);
710     }
711     window->follow_parent_transform.changed = FALSE;
712   }
713
714   /* set ratio */
715   if (window->mode_ratio.changed) {
716     wl_fixed_t f_width, f_height;
717     f_width = wl_fixed_from_double (window->mode_ratio.w);
718     f_height = wl_fixed_from_double (window->mode_ratio.h);
719
720     GST_INFO
721         ("tizen_destination_mode_set_ratio (tizen_destination_mode@%p, wl_fixed width@%f, wl_fixed height@%f)",
722         window->tizen_video_dest_mode, window->mode_ratio.w,
723         window->mode_ratio.h);
724     tizen_destination_mode_set_ratio (window->tizen_video_dest_mode, f_width,
725         f_height);
726     window->mode_ratio.changed = FALSE;
727   }
728
729   /* set offset */
730   if (window->mode_offset.changed) {
731     GST_INFO
732         ("tizen_destination_mode_set_offset (tizen_destination_mode@%p, x@%d, y@%d, w@%d, h@%d)",
733         window->tizen_video_dest_mode, window->mode_offset.x,
734         window->mode_offset.y, window->mode_offset.w, window->mode_offset.h);
735     tizen_destination_mode_set_offset (window->tizen_video_dest_mode,
736         window->mode_offset.x, window->mode_offset.y, window->mode_offset.w,
737         window->mode_offset.h);
738     window->mode_offset.changed = FALSE;
739   }
740
741   /* set scale */
742   if (window->mode_scale.changed) {
743     wl_fixed_t f_width, f_height;
744     f_width = wl_fixed_from_double (window->mode_scale.w);
745     f_height = wl_fixed_from_double (window->mode_scale.h);
746
747     GST_INFO
748         ("tizen_destination_mode_set_scale (tizen_destination_mode@%p, wl_fixed width@%f, wl_fixed height@%f)",
749         window->tizen_video_dest_mode, window->mode_scale.w,
750         window->mode_scale.h);
751     tizen_destination_mode_set_scale (window->tizen_video_dest_mode, f_width,
752         f_height);
753     window->mode_scale.changed = FALSE;
754   }
755
756   /* set align */
757   if (window->mode_align.changed) {
758     wl_fixed_t f_width, f_height;
759     f_width = wl_fixed_from_double (window->mode_align.w);
760     f_height = wl_fixed_from_double (window->mode_align.h);
761     GST_INFO
762         ("tizen_destination_mode_set_align (tizen_destination_mode@%p, wl_fixed_width@%f, wl_fixed_height@%f)",
763         window->tizen_video_dest_mode, window->mode_align.w,
764         window->mode_align.h);
765     tizen_destination_mode_set_align (window->tizen_video_dest_mode, f_width,
766         f_height);
767     window->mode_align.changed = FALSE;
768   }
769 #endif
770
771 done:
772
773   /* set transform */
774   if (window->rotate_angle.changed || window->flip.changed) {
775     GST_LOG ("rotate_angle(%d), flip(%d)", window->rotate_angle.value,
776         window->flip.value);
777     transform =
778         gst_wl_window_find_transform (window->rotate_angle.value,
779         window->flip.value);
780     GST_INFO
781         ("tizen_viewport_set_transform(tizen_video_viewport@%p, transform@%d)",
782         window->tizen_video_viewport, transform);
783     tizen_viewport_set_transform (window->tizen_video_viewport, transform);
784     window->rotate_angle.changed = window->flip.changed = FALSE;
785   }
786
787   if (commit) {
788     GST_INFO ("need to commit");
789     GST_INFO
790         ("wl_surface_damage_buffer (video_surface@%p, buffer_@x%d, buffer_y@%d, buffer_w@%d, buffer_h@%d)",
791         window->video_surface, window->buffer_x, window->buffer_y,
792         window->buffer_width, window->buffer_height);
793     wl_surface_damage_buffer (window->video_surface, window->buffer_x,
794         window->buffer_y, window->buffer_width, window->buffer_height);
795     GST_INFO ("wl_surface_commit (video_surface@%p)", window->video_surface);
796     wl_surface_commit (window->video_surface);
797   }
798 }
799 #else
800 static void
801 gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit)
802 {
803   GstVideoRectangle src = { 0, };
804   GstVideoRectangle dst = { 0, };
805   GstVideoRectangle res;
806
807   /* center the video_subsurface inside area_subsurface */
808   src.w = window->video_width;
809   src.h = window->video_height;
810   dst.w = window->render_rectangle.w;
811   dst.h = window->render_rectangle.h;
812   gst_video_sink_center_rect (src, dst, &res, TRUE);
813
814   wl_subsurface_set_position (window->video_subsurface, res.x, res.y);
815   wl_viewport_set_destination (window->video_viewport, res.w, res.h);
816
817   if (commit) {
818     wl_surface_damage (window->video_surface, 0, 0, res.w, res.h);
819     wl_surface_commit (window->video_surface);
820   }
821
822   if (gst_wl_window_is_toplevel (window)) {
823     struct wl_region *region;
824
825     region = wl_compositor_create_region (window->display->compositor);
826     wl_region_add (region, 0, 0, window->render_rectangle.w,
827         window->render_rectangle.h);
828     wl_surface_set_input_region (window->area_surface, region);
829     wl_region_destroy (region);
830   }
831
832   /* this is saved for use in wl_surface_damage */
833   window->surface_width = res.w;
834   window->surface_height = res.h;
835 }
836 #endif
837 void
838 gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
839     const GstVideoInfo * info)
840 {
841 #if TIZEN_FEATURE_WLSINK_ENHANCEMENT
842   FUNCTION;
843   /* check video buffer size for wl_surface_damage_buffer */
844   if (window->buffer_width != window->display->buffer_width
845       || window->buffer_height != window->display->buffer_height) {
846     window->buffer_width = window->display->buffer_width;
847     window->buffer_height = window->display->buffer_height;
848   }
849
850   if (G_UNLIKELY (info)) {
851     window->video_width =
852         gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
853     window->video_height = info->height;
854
855     wl_subsurface_set_sync (window->video_subsurface);
856     GST_INFO ("wl_subsurface_set_sync (video_subsurface@%p)",
857         window->video_subsurface);
858     /* check video_info_changed to remove repetitive IPC */
859     if (window->video_info_changed) {
860       gst_wl_window_resize_tizen_video_viewport (window, FALSE);
861       window->video_info_changed = FALSE;
862     }
863   }
864
865   GST_LOG ("GstWlBuffer(%p)", buffer);
866   if (G_LIKELY (buffer))
867     gst_wl_buffer_attach (buffer, window->video_surface);
868   else {
869     GST_INFO ("wl_surface_attach (video_surface@%p, NULL, 0, 0)",
870         window->video_surface);
871     wl_surface_attach (window->video_surface, NULL, 0, 0);
872   }
873   /* use tizen view port */
874   GST_INFO
875       ("wl_surface_damage_buffer (video_surface@%p, buffer_x@%d, buffer_y@%d, buffer_w@%d, buffer_h@%d)",
876       window->video_surface, window->buffer_x, window->buffer_y,
877       window->buffer_width, window->buffer_height);
878   wl_surface_damage_buffer (window->video_surface, window->buffer_x,
879       window->buffer_y, window->buffer_width, window->buffer_height);
880   /* wl_surface_commit change surface state, if wl_buffer is not attached newly,  then surface is not changed */
881   GST_INFO ("wl_surface_commit (video_surface@%p)", window->video_surface);
882   wl_surface_commit (window->video_surface);
883
884   if (G_UNLIKELY (info)) {
885     GST_INFO ("wl_surface_commit (area_surface@%p)", window->area_surface);
886     wl_surface_commit (window->area_surface);
887     GST_INFO ("wl_subsurface_set_desync (video_subsurface@%p)",
888         window->video_subsurface);
889     wl_subsurface_set_desync (window->video_subsurface);
890   }
891
892   wl_display_flush (window->display->display);
893
894 #else /* open source */
895
896   if (G_UNLIKELY (info)) {
897     window->video_width =
898         gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
899     window->video_height = info->height;
900
901     wl_subsurface_set_sync (window->video_subsurface);
902     gst_wl_window_resize_video_surface (window, FALSE);
903   }
904
905   GST_LOG ("GstWlBuffer(%p)", buffer);
906   if (G_LIKELY (buffer))
907     gst_wl_buffer_attach (buffer, window->video_surface);
908   else
909     wl_surface_attach (window->video_surface, NULL, 0, 0);
910
911   wl_surface_damage (window->video_surface, 0, 0, window->surface_width,
912       window->surface_height);
913   wl_surface_commit (window->video_surface);
914
915   if (G_UNLIKELY (info)) {
916     /* commit also the parent (area_surface) in order to change
917      * the position of the video_subsurface */
918     wl_surface_damage (window->area_surface, 0, 0, window->render_rectangle.w,
919         window->render_rectangle.h);
920     wl_surface_commit (window->area_surface);
921     wl_subsurface_set_desync (window->video_subsurface);
922   }
923
924   wl_display_flush (window->display->display);
925 #endif
926 }
927
928 void
929 gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
930     gint w, gint h)
931 {
932 #if TIZEN_FEATURE_WLSINK_ENHANCEMENT
933   FUNCTION;
934   g_return_if_fail (window != NULL);
935
936   if (window->disp_geo_method.value != DISP_GEO_METHOD_CUSTOM_ROI) {
937     GST_ERROR
938         ("must be set display-geometry-method to DISP_GEO_METHOD_CUSTOM_ROI before setting render rectangle()");
939     return;
940   }
941
942   /* position the area inside the parent - needs a parent commit to apply */
943   /* use tizen view port */
944   if (window->tizen_area_viewport) {
945     GST_INFO
946         ("tizen_viewport_set_destination (tizen_area_viewport(tizen_viewport)@%p, x@%d, y@%d, w@%d, h@%d)",
947         window->tizen_area_viewport, x, y, w, h);
948     tizen_viewport_set_destination (window->tizen_area_viewport, x, y, w, h);
949   }
950
951   if (window->video_width != 0) {
952     GST_INFO ("wl_subsurface_set_sync (video_subsurface@%p)",
953         window->video_subsurface);
954     wl_subsurface_set_sync (window->video_subsurface);
955     /* use tizen view port */
956     gst_wl_window_resize_tizen_video_viewport (window, TRUE);
957     GST_INFO ("wl_subsurface_set_desync (video_subsurface@%p)",
958         window->video_subsurface);
959     wl_subsurface_set_desync (window->video_subsurface);
960   }
961   GST_INFO ("wl_surface_commit (area_surface@%p)", window->area_surface);
962   wl_surface_commit (window->area_surface);
963
964 #else /* open source */
965
966   g_return_if_fail (window != NULL);
967
968   window->render_rectangle.x = x;
969   window->render_rectangle.y = y;
970   window->render_rectangle.w = w;
971   window->render_rectangle.h = h;
972
973   /* position the area inside the parent - needs a parent commit to apply */
974   if (window->area_subsurface)
975     wl_subsurface_set_position (window->area_subsurface, x, y);
976
977   /* change the size of the area */
978   wl_viewport_set_destination (window->area_viewport, w, h);
979
980   if (window->video_width != 0) {
981     wl_subsurface_set_sync (window->video_subsurface);
982     gst_wl_window_resize_video_surface (window, TRUE);
983   }
984
985   wl_surface_damage (window->area_surface, 0, 0, w, h);
986   wl_surface_commit (window->area_surface);
987
988   if (window->video_width != 0)
989     wl_subsurface_set_desync (window->video_subsurface);
990
991 #endif
992 }
993
994 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
995 void
996 gst_wl_window_set_rotate_angle (GstWlWindow * window, guint rotate_angle)
997 {
998   FUNCTION;
999   g_return_if_fail (window != NULL);
1000   window->rotate_angle.value = rotate_angle;
1001   GST_LOG ("rotate_angle value is (%d)", window->rotate_angle.value);
1002   window->rotate_angle.changed = TRUE;
1003 }
1004
1005 void
1006 gst_wl_window_set_destination_mode (GstWlWindow * window, guint disp_geo_method)
1007 {
1008   FUNCTION;
1009   g_return_if_fail (window != NULL);
1010   window->disp_geo_method.value = disp_geo_method;
1011   GST_LOG ("disp_geo_method value is (%d)", window->disp_geo_method.value);
1012   window->disp_geo_method.changed = TRUE;
1013 }
1014
1015 void
1016 gst_wl_window_set_flip (GstWlWindow * window, guint flip)
1017 {
1018   FUNCTION;
1019   g_return_if_fail (window != NULL);
1020   window->flip.value = flip;
1021   GST_LOG ("flip value is (%d)", window->flip.value);
1022   window->flip.changed = TRUE;
1023 }
1024
1025 void
1026 gst_wl_window_set_destination_mode_crop_wl_buffer (GstWlWindow * window,
1027     guint x, guint y, guint w, guint h)
1028 {
1029   FUNCTION;
1030   g_return_if_fail (window != NULL);
1031   GST_LOG ("set crop x@%d, y@%d, w@%d, h@%d", x, y, w, h);
1032   window->mode_crop.x = x;
1033   window->mode_crop.y = y;
1034   window->mode_crop.w = w;
1035   window->mode_crop.h = h;
1036   window->mode_crop.changed = TRUE;
1037 }
1038
1039 #ifdef ENABLE_FUNCTION
1040 void
1041 gst_wl_window_set_destination_mode_follow_parent_transform (GstWlWindow *
1042     window, gboolean follow_parent_transform)
1043 {
1044   FUNCTION;
1045   g_return_if_fail (window != NULL);
1046   window->follow_parent_transform.value = follow_parent_transform;
1047   GST_LOG ("follow_parent_transform value is (%d)",
1048       window->follow_parent_transform.value);
1049   window->follow_parent_transform.changed = TRUE;
1050 }
1051
1052
1053 void
1054 gst_wl_window_set_destination_mode_offset (GstWlWindow * window, guint x,
1055     guint y, guint w, guint h)
1056 {
1057   FUNCTION;
1058   g_return_if_fail (window != NULL);
1059   GST_LOG ("set offset x@%d, y@%d", x, y);
1060   window->mode_offset.x = x;
1061   window->mode_offset.y = y;
1062   window->mode_offset.w = w;
1063   window->mode_offset.h = h;
1064   window->mode_offset.changed = TRUE;
1065 }
1066
1067 void
1068 gst_wl_window_set_destination_mode_ratio (GstWlWindow * window, gdouble w,
1069     gdouble h)
1070 {
1071   FUNCTION;
1072   g_return_if_fail (window != NULL);
1073   GST_LOG ("set ratio w@%f, h@%f", w, h);
1074   window->mode_ratio.w = w;
1075   window->mode_ratio.h = h;
1076   window->mode_ratio.changed = TRUE;
1077 }
1078
1079 void
1080 gst_wl_window_set_destination_mode_scale (GstWlWindow * window, gdouble w,
1081     gdouble h)
1082 {
1083   FUNCTION;
1084   g_return_if_fail (window != NULL);
1085   GST_LOG ("set scale w@%f, h@%f", w, h);
1086   window->mode_scale.w = w;
1087   window->mode_scale.h = h;
1088   window->mode_scale.changed = TRUE;
1089 }
1090
1091 void
1092 gst_wl_window_set_destination_mode_align (GstWlWindow * window, gdouble w,
1093     gdouble h)
1094 {
1095   FUNCTION;
1096   g_return_if_fail (window != NULL);
1097   GST_LOG ("set align w@%f, h@%f", w, h);
1098   window->mode_align.w = w;
1099   window->mode_align.h = h;
1100   window->mode_align.changed = TRUE;
1101 }
1102 #endif
1103 void
1104 gst_wl_window_set_video_info_change (GstWlWindow * window, guint changed)
1105 {
1106   FUNCTION;
1107   g_return_if_fail (window != NULL);
1108   window->video_info_changed = changed;
1109   GST_LOG ("video_info_changed value is (%d)", window->video_info_changed);
1110 }
1111 #endif