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