tizenwlsink: Add null checking for 'tizen_video_viewport'
[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   if (window->tizen_video_viewport) {
306     window->tizen_video_dest_mode =
307         tizen_viewport_get_destination_mode (window->tizen_video_viewport);
308     GST_WARNING
309         ("tizen_video_dest_mode(tizen_destination_mode)@%p = tizen_viewport_get_destination_mode (tizen_video_viewport@%p)",
310         window->tizen_video_dest_mode, window->tizen_video_viewport);
311     /* video surface always follow area surface by below code. */
312     GST_WARNING
313         ("tizen_viewport_follow_parent_transform(tizen_video_viewport@%p)",
314         window->tizen_video_viewport);
315     tizen_viewport_follow_parent_transform (window->tizen_video_viewport);
316   }
317
318 #else
319   window->area_viewport = wl_scaler_get_viewport (display->scaler,
320       window->area_surface);
321   window->video_viewport = wl_scaler_get_viewport (display->scaler,
322       window->video_surface);
323 #endif
324   /* draw the area_subsurface */
325   gst_video_info_set_format (&info,
326       /* we want WL_SHM_FORMAT_XRGB8888 */
327 #if G_BYTE_ORDER == G_BIG_ENDIAN
328       GST_VIDEO_FORMAT_xRGB,
329 #else
330       GST_VIDEO_FORMAT_BGRx,
331 #endif
332       1, 1);
333
334 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
335   if (window->display->use_tbm) {
336     /* Inform enlightenment of surface which render video */
337     /* tizen_video(tbm) render on video_surface */
338     window->video_object =
339         tizen_video_get_object (display->tizen_video, window->video_surface);
340   }
341
342   gst_wl_window_mapping_sub_surface (display, window, &info);
343 #else /* open source */
344   buf =
345       gst_buffer_new_allocate (gst_tizen_wl_shm_allocator_get (), info.size,
346       NULL);
347   gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
348   *((guint32 *) mapinfo.data) = 0;      /* paint it black */
349   gst_buffer_unmap (buf, &mapinfo);
350   wlbuf =
351       gst_tizen_wl_shm_memory_construct_wl_buffer (gst_buffer_peek_memory (buf,
352           0), display, &info);
353   gwlbuf = gst_buffer_add_wl_buffer (buf, wlbuf, display);
354   gst_wl_buffer_attach (gwlbuf, window->area_surface);
355
356   /* at this point, the GstWlBuffer keeps the buffer
357    * alive and will free it on wl_buffer::release */
358   gst_buffer_unref (buf);
359 #endif
360
361   /* do not accept input */
362   region = wl_compositor_create_region (display->compositor);
363   GST_WARNING ("wl_region@%p = wl_compositor_create_region (wl_compositor@%p)",
364       region, display->compositor);
365   GST_WARNING ("wl_surface_set_input_region (area_surface@%p, wl_region@%p)",
366       window->area_surface, region);
367   wl_surface_set_input_region (window->area_surface, region);
368   GST_WARNING ("wl_region_destroy (wl_region@%p)", region);
369   wl_region_destroy (region);
370
371   region = wl_compositor_create_region (display->compositor);
372   GST_WARNING ("wl_region@%p = wl_compositor_create_region (wl_compositor@%p)",
373       region, display->compositor);
374   GST_WARNING ("wl_surface_set_input_region (video_surface@%p, wl_region@%p)",
375       window->video_surface, region);
376   wl_surface_set_input_region (window->video_surface, region);
377   GST_WARNING ("wl_region_destroy (wl_region@%p)", region);
378   wl_region_destroy (region);
379
380 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
381   /* set area surface size by full mode(full size of parent window) , toplevel is set to fullmode too for convenient test */
382   if (window->tizen_area_viewport) {
383     int tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_FULL;
384
385     window->tizen_area_dest_mode =
386         tizen_viewport_get_destination_mode (window->tizen_area_viewport);
387     GST_WARNING
388         ("tizen_area_dest_mode(tizen_destination_mode)@%p = tizen_viewport_get_destination_mode (tizen_area_viewport@%p)",
389         window->tizen_area_dest_mode, window->tizen_area_viewport);
390     if (window->tizen_area_dest_mode) {
391       GST_WARNING
392           ("tizen_destination_mode_set (tizen_destination_mode@%p, @%d, 3 is FULL)",
393           window->tizen_area_dest_mode, tizen_disp_mode);
394       tizen_destination_mode_set (window->tizen_area_dest_mode,
395           tizen_disp_mode);
396     }
397     GST_WARNING ("wl_surface_commit (area_surface@%p)", window->area_surface);
398     wl_surface_commit (window->area_surface);
399   }
400 #endif
401   return window;
402 }
403
404 GstWlWindow *
405 gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
406     GMutex * render_lock)
407 {
408 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
409   GstWlWindow *window;
410   FUNCTION;
411
412 /* not create shell_surface here for enlightenment */
413   display->need_shell_surface = TRUE;
414   window = gst_wl_window_new_internal (display, NULL, render_lock);
415
416   /* for tizen enlightenment */
417 #if 0
418   /* go toplevel */
419   window->shell_surface = wl_shell_get_shell_surface (display->shell,
420       window->area_surface);
421 #endif
422   if (window->shell_surface) {
423     GST_INFO
424         ("wl_shell_surface_add_listener (shell_surface@%p, wl_shell_surface_listener@%p, GstWlWindow@%p",
425         window->shell_surface, &shell_surface_listener, window);
426     wl_shell_surface_add_listener (window->shell_surface,
427         &shell_surface_listener, window);
428     GST_INFO ("wl_shell_surface_set_toplevel (shell_surface@%p",
429         window->shell_surface);
430     wl_shell_surface_set_toplevel (window->shell_surface);
431   } else {
432     GST_ERROR ("Unable to get wl_shell_surface");
433
434     g_object_unref (window);
435     return NULL;
436   }
437
438   /* toplevel is set to fullmode for convenient test in tizen_viewport enviroment, don't use below code */
439 #if 0
440   /* set the initial size to be the same as the reported video size */
441   width =
442       gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
443   gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
444 #endif
445   return window;
446
447 #else /* open source */
448   GstWlWindow *window;
449   gint width;
450
451   window = gst_wl_window_new_internal (display);
452
453   /* go toplevel */
454   window->shell_surface = wl_shell_get_shell_surface (display->shell,
455       window->area_surface);
456
457   if (window->shell_surface) {
458     wl_shell_surface_add_listener (window->shell_surface,
459         &shell_surface_listener, window);
460     wl_shell_surface_set_toplevel (window->shell_surface);
461   } else {
462     GST_ERROR ("Unable to get wl_shell_surface");
463
464     g_object_unref (window);
465     return NULL;
466   }
467
468   /* set the initial size to be the same as the reported video size */
469
470   width =
471       gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
472   gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
473
474   return window;
475 #endif
476 }
477
478 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
479 static void
480 foreign_shell_cb_destroyed(void *data,
481                            struct wtz_foreign_shell *foreign_shell)
482 {
483    GST_INFO("Destroyed the reference of foreign shell.");
484 }
485
486 static void
487 foreign_shell_cb_destination_changed(void *data,
488                                      struct wtz_foreign_shell *foreign_shell,
489                                      int32_t width, int32_t height)
490 {
491    GST_INFO("Changed destination (%d x %d) of foreign shell.", width, height);
492 }
493
494 static void
495 foreign_shell_cb_transform_changed(void *data,
496                                    struct wtz_foreign_shell *foreign_shell,
497                                    int32_t transform)
498 {
499    GST_INFO("Changed transform (%d) of foreign shell.", transform);
500 }
501
502 static const struct wtz_foreign_shell_listener foreign_shell_listener =
503 {
504    foreign_shell_cb_destroyed,
505    foreign_shell_cb_destination_changed,
506    foreign_shell_cb_transform_changed,
507 };
508
509 static GstWlWindow *
510 gst_wl_window_new_with_foreign_shell(GstWlDisplay * display)
511 {
512   GstWlWindow *window;
513   struct wl_surface *video_surface;
514   struct wl_region *region;
515
516   g_return_val_if_fail (display, NULL);
517
518   video_surface = wl_compositor_create_surface (display->compositor);
519   if (!video_surface) {
520     GST_ERROR ("wl_compositor_create_surface(wl_compositor@%p) failed", display->compositor);
521     return NULL;
522   }
523
524   window = g_object_new (GST_TYPE_WL_WINDOW, NULL);
525   window->display = g_object_ref (display);
526   window->video_surface = video_surface;
527
528   GST_WARNING
529       ("video_surface(wl_surface)@%p = wl_compositor_create_surface(wl_compositor@%p)",
530       window->video_surface, display->compositor);
531
532   window->wtz_foreign_shell = wtz_importer_import_shell (display->wtz_importer,
533                                 window->video_surface, display->wtz_exported_shell_handle);
534   GST_WARNING
535       ("wtz_foreign_shell@%p = wtz_importer_import_shell(wtz_importer@%p, video_surface@%p, wtz_exported_shell_handle@%s",
536         window->wtz_foreign_shell, display->wtz_importer, window->video_surface, display->wtz_exported_shell_handle);
537
538   wtz_foreign_shell_add_listener (window->wtz_foreign_shell, &foreign_shell_listener, window);
539   GST_WARNING
540       ("wtz_foreign_shell_add_listener (wtz_foreign_shell@%p, &foreign_shell_listener@%p, window@%p)",
541       window->wtz_foreign_shell, &foreign_shell_listener, window);
542
543   GST_WARNING ("wl_proxy_set_queue (video_surface@%p, wl_event_queue@%p)",
544       window->video_surface, display->queue);
545   wl_proxy_set_queue ((struct wl_proxy *) window->video_surface,
546       display->queue);
547
548   if (window->display->use_tbm) {
549     /* Inform enlightenment of surface which render video */
550     /* tizen_video(tbm) render on video_surface */
551     window->video_object =
552         tizen_video_get_object (display->tizen_video, window->video_surface);
553   }
554
555   region = wl_compositor_create_region (display->compositor);
556   GST_WARNING ("wl_region@%p = wl_compositor_create_region (wl_compositor@%p)",
557       region, display->compositor);
558   GST_WARNING ("wl_surface_set_input_region (video_surface@%p, wl_region@%p)",
559       window->video_surface, region);
560   wl_surface_set_input_region (window->video_surface, region);
561   GST_WARNING ("wl_region_destroy (wl_region@%p)", region);
562   wl_region_destroy (region);
563
564   return window;
565 }
566 #endif
567
568 GstWlWindow *
569 gst_wl_window_new_in_surface (GstWlDisplay * display,
570     struct wl_surface * parent, GMutex * render_lock)
571 {
572 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
573   /* use App window */
574   GstWlWindow *window;
575   FUNCTION;
576
577   if (display->wtz_exported_shell_handle) {
578     window = gst_wl_window_new_with_foreign_shell (display);
579     return window;
580   }
581
582   display->use_parent_wl_surface = TRUE;
583   if (parent) {
584     /*use wl_surface */
585     window = gst_wl_window_new_internal (display, parent, render_lock);
586   } else {
587     /* use wl_surface id */
588     window = gst_wl_window_new_internal (display, NULL, render_lock);
589   }
590
591   /*Area surface from App need to be under parent surface */
592   if (display->tizen_policy) {
593     GST_INFO
594         ("tizen_policy_place_subsurface_below_parent (tizen_policy@%p, area_subsurface@%p)",
595         display->tizen_policy, window->area_subsurface);
596     tizen_policy_place_subsurface_below_parent (display->tizen_policy,
597         window->area_subsurface);
598     GST_INFO
599         ("tizen_policy_place_subsurface_below_parent (tizen_policy@%p, video_subsurface@%p)",
600         display->tizen_policy, window->video_subsurface);
601     tizen_policy_place_subsurface_below_parent (display->tizen_policy,
602         window->video_subsurface);
603   }
604   return window;
605 #endif
606 }
607
608 GstWlDisplay *
609 gst_wl_window_get_display (GstWlWindow * window)
610 {
611   FUNCTION;
612   g_return_val_if_fail (window != NULL, NULL);
613
614   return g_object_ref (window->display);
615 }
616
617 struct wl_surface *
618 gst_wl_window_get_wl_surface (GstWlWindow * window)
619 {
620   FUNCTION;
621   g_return_val_if_fail (window != NULL, NULL);
622
623   return window->video_surface;
624 }
625
626 gboolean
627 gst_wl_window_is_toplevel (GstWlWindow * window)
628 {
629   FUNCTION;
630   g_return_val_if_fail (window != NULL, FALSE);
631
632   return (window->shell_surface != NULL);
633 }
634
635 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
636 static gint
637 gst_wl_window_find_rotate_transform (guint rotate_angle)
638 {
639   gint transform = WL_OUTPUT_TRANSFORM_NORMAL;
640   FUNCTION;
641
642   GST_DEBUG ("rotate (%d)", rotate_angle);
643   switch (rotate_angle) {
644     case DEGREE_0:
645       transform = WL_OUTPUT_TRANSFORM_NORMAL;
646       break;
647     case DEGREE_90:
648       transform = WL_OUTPUT_TRANSFORM_90;
649       break;
650     case DEGREE_180:
651       transform = WL_OUTPUT_TRANSFORM_180;
652       break;
653     case DEGREE_270:
654       transform = WL_OUTPUT_TRANSFORM_270;
655       break;
656   }
657   return transform;
658 }
659
660 static gint
661 gst_wl_window_find_flip_transform (guint flip)
662 {
663   gint transform = WL_OUTPUT_TRANSFORM_NORMAL;
664   FUNCTION;
665
666   GST_DEBUG ("flip (%d)", flip);
667   switch (flip) {
668     case FLIP_NONE:
669       transform = WL_OUTPUT_TRANSFORM_NORMAL;
670       break;
671     case FLIP_HORIZONTAL:
672       transform = WL_OUTPUT_TRANSFORM_FLIPPED;
673       break;
674     case FLIP_VERTICAL:
675       transform = WL_OUTPUT_TRANSFORM_FLIPPED_180;
676       break;
677     case FLIP_BOTH:
678       transform = WL_OUTPUT_TRANSFORM_180;
679       break;
680   }
681   return transform;
682
683 }
684
685 #endif
686 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
687 static void
688 gst_wl_window_resize_tizen_video_viewport (GstWlWindow * window,
689     gboolean commit)
690 {
691   gint transform = WL_OUTPUT_TRANSFORM_NORMAL;
692
693   FUNCTION;
694   g_return_if_fail (window->tizen_video_viewport != NULL);
695   g_return_if_fail (window->tizen_video_dest_mode != NULL);
696
697   /* Set source, wayland need to set "tizen_viewport_set_source" always when change video info,
698      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 */
699   if (window->set_source.changed) {
700     /* we have known issue about mobile team kernel, when set orign green line can be shown with tbm */
701     GST_INFO
702         ("tizen_viewport_set_source (tizen_video_viewport@%p, x@%d, y@%d, w@%d, h@%d)",
703         window->tizen_video_viewport, window->set_source.x,
704         window->set_source.y, window->set_source.w, window->set_source.h);
705     tizen_viewport_set_source (window->tizen_video_viewport,
706         window->set_source.x, window->set_source.y, window->set_source.w,
707         window->set_source.h);
708
709     window->set_source.changed = FALSE;
710   }
711
712   /*set tizen destination mode */
713   if (window->disp_geo_method.changed
714       || (window->disp_geo_method.value == DISP_GEO_METHOD_CUSTOM_ROI
715           && window->roi_area_changed)) {
716     int tizen_disp_mode = -1;
717     switch (window->disp_geo_method.value) {
718
719       case DISP_GEO_METHOD_LETTER_BOX:
720         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_LETTER_BOX");
721         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_LETTER_BOX;
722         break;
723       case DISP_GEO_METHOD_ORIGIN_SIZE:
724         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_ORIGIN");
725         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_ORIGIN;
726         break;
727       case DISP_GEO_METHOD_FULL_SCREEN:
728         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_FULL");
729         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_FULL;
730         break;
731       case DISP_GEO_METHOD_CROPPED_FULL_SCREEN:
732         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_CROPPED_FULL");
733         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_CROPPED_FULL;
734         break;
735       case DISP_GEO_METHOD_ORIGIN_SIZE_OR_LETTER_BOX:
736         GST_LOG ("TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER");
737         tizen_disp_mode = TIZEN_DESTINATION_MODE_TYPE_ORIGIN_OR_LETTER;
738         break;
739       case DISP_GEO_METHOD_CUSTOM_ROI:
740         GST_LOG ("DISP_GEO_METHOD_CUSTOM_ROI..need to set destination ROI");
741         tizen_disp_mode = -1;
742         break;
743       default:
744         break;
745     }
746     if (tizen_disp_mode > -1) {
747       GST_INFO
748           ("tizen_destination_mode_set (tizen_destination_mode@%p, tizen_disp_mode@%d)",
749           window->tizen_video_dest_mode, tizen_disp_mode);
750       tizen_destination_mode_set (window->tizen_video_dest_mode,
751           tizen_disp_mode);
752     }
753     if (window->disp_geo_method.value == DISP_GEO_METHOD_CUSTOM_ROI) {
754       /* set ROI destination */
755       GST_INFO
756           ("tizen_viewport_set_destination (tizen_video_viewport(tizen_viewport)@%p, x@%d, y@%d, w@%d, h@%d)",
757           window->tizen_video_viewport, window->roi.x, window->roi.y,
758           window->roi.w, window->roi.h);
759       if (window->roi.x == 0 && window->roi.y == 0 && window->roi.w == 0
760           && window->roi.h == 0) {
761         GST_WARNING ("ROI Area isn't set");
762         return;
763       }
764
765       tizen_viewport_set_destination (window->tizen_video_viewport,
766           window->roi.x, window->roi.y, window->roi.w, window->roi.h);
767       window->roi_area_changed = FALSE;
768     }
769     window->disp_geo_method.changed = FALSE;
770   }
771
772
773   goto done;
774
775   /* 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. */
776 #ifdef ENABLE_FUNCTION
777   /* set or unset follow parent transform */
778   if (window->follow_parent_transform.changed
779       && !gst_wl_window_is_toplevel (window)) {
780     if (window->follow_parent_transform.value) {
781       GST_INFO
782           ("tizen_destination_mode_follow_parent_transform (tizen_destination_mode@%p)",
783           window->tizen_area_dest_mode);
784       tizen_destination_mode_follow_parent_transform
785           (window->tizen_area_dest_mode);
786       GST_INFO
787           ("tizen_destination_mode_follow_parent_transform (tizen_destination_mode@%p)",
788           window->tizen_video_dest_mode);
789       tizen_destination_mode_follow_parent_transform
790           (window->tizen_video_dest_mode);
791
792     } else {
793       GST_INFO
794           ("tizen_destination_mode_unfollow_parent_transform (tizen_destination_mode@%p)",
795           window->tizen_area_dest_mode);
796       tizen_destination_mode_unfollow_parent_transform
797           (window->tizen_area_dest_mode);
798       GST_INFO
799           ("tizen_destination_mode_unfollow_parent_transform (tizen_destination_mode@%p)",
800           window->tizen_video_dest_mode);
801       tizen_destination_mode_unfollow_parent_transform
802           (window->tizen_video_dest_mode);
803     }
804     window->follow_parent_transform.changed = FALSE;
805   }
806
807   /* set ratio */
808   if (window->mode_ratio.changed) {
809     wl_fixed_t f_width, f_height;
810     f_width = wl_fixed_from_double (window->mode_ratio.w);
811     f_height = wl_fixed_from_double (window->mode_ratio.h);
812
813     GST_INFO
814         ("tizen_destination_mode_set_ratio (tizen_destination_mode@%p, wl_fixed width@%f, wl_fixed height@%f)",
815         window->tizen_video_dest_mode, window->mode_ratio.w,
816         window->mode_ratio.h);
817     tizen_destination_mode_set_ratio (window->tizen_video_dest_mode, f_width,
818         f_height);
819     window->mode_ratio.changed = FALSE;
820   }
821
822   /* set offset */
823   if (window->mode_offset.changed) {
824     GST_INFO
825         ("tizen_destination_mode_set_offset (tizen_destination_mode@%p, x@%d, y@%d, w@%d, h@%d)",
826         window->tizen_video_dest_mode, window->mode_offset.x,
827         window->mode_offset.y, window->mode_offset.w, window->mode_offset.h);
828     tizen_destination_mode_set_offset (window->tizen_video_dest_mode,
829         window->mode_offset.x, window->mode_offset.y, window->mode_offset.w,
830         window->mode_offset.h);
831     window->mode_offset.changed = FALSE;
832   }
833
834   /* set scale */
835   if (window->mode_scale.changed) {
836     wl_fixed_t f_width, f_height;
837     f_width = wl_fixed_from_double (window->mode_scale.w);
838     f_height = wl_fixed_from_double (window->mode_scale.h);
839
840     GST_INFO
841         ("tizen_destination_mode_set_scale (tizen_destination_mode@%p, wl_fixed width@%f, wl_fixed height@%f)",
842         window->tizen_video_dest_mode, window->mode_scale.w,
843         window->mode_scale.h);
844     tizen_destination_mode_set_scale (window->tizen_video_dest_mode, f_width,
845         f_height);
846     window->mode_scale.changed = FALSE;
847   }
848
849   /* set align */
850   if (window->mode_align.changed) {
851     wl_fixed_t f_width, f_height;
852     f_width = wl_fixed_from_double (window->mode_align.w);
853     f_height = wl_fixed_from_double (window->mode_align.h);
854     GST_INFO
855         ("tizen_destination_mode_set_align (tizen_destination_mode@%p, wl_fixed_width@%f, wl_fixed_height@%f)",
856         window->tizen_video_dest_mode, window->mode_align.w,
857         window->mode_align.h);
858     tizen_destination_mode_set_align (window->tizen_video_dest_mode, f_width,
859         f_height);
860     window->mode_align.changed = FALSE;
861   }
862 #endif
863
864 done:
865   /* set rotate */
866   if (window->rotate_angle.changed) {
867     GST_LOG ("set rotate_angle(%d)", window->rotate_angle.value);
868     transform =
869         gst_wl_window_find_rotate_transform (window->rotate_angle.value);
870     GST_INFO
871         ("tizen_viewport_set_transform(tizen_area_viewport@%p, transform@%d)",
872         window->tizen_area_viewport, transform);
873     tizen_viewport_set_transform (window->tizen_area_viewport, transform);
874     window->rotate_angle.changed = FALSE;
875   }
876   /* set flip */
877   if (window->flip.changed) {
878     GST_LOG ("set flip(%d)", window->flip.value);
879
880     transform = gst_wl_window_find_flip_transform (window->flip.value);
881     GST_INFO
882         ("tizen_viewport_set_transform(tizen_video_viewport@%p, transform@%d)",
883         window->tizen_video_viewport, transform);
884     tizen_viewport_set_transform (window->tizen_video_viewport, transform);
885     window->flip.changed = FALSE;
886   }
887
888   if (commit) {
889     GST_LOG ("need to commit");
890     GST_INFO
891         ("wl_surface_damage_buffer (video_surface@%p, buffer_@x%d, buffer_y@%d, buffer_w@%d, buffer_h@%d)",
892         window->video_surface, window->buffer_x, window->buffer_y,
893         window->buffer_width, window->buffer_height);
894     wl_surface_damage_buffer (window->video_surface, window->buffer_x,
895         window->buffer_y, window->buffer_width, window->buffer_height);
896     GST_INFO ("wl_surface_commit (video_surface@%p)", window->video_surface);
897     wl_surface_commit (window->video_surface);
898   }
899 }
900 #else
901 static void
902 gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit)
903 {
904   GstVideoRectangle src = { 0, };
905   GstVideoRectangle dst = { 0, };
906   GstVideoRectangle res;
907
908   /* center the video_subsurface inside area_subsurface */
909   src.w = window->video_width;
910   src.h = window->video_height;
911   dst.w = window->render_rectangle.w;
912   dst.h = window->render_rectangle.h;
913   gst_video_sink_center_rect (src, dst, &res, TRUE);
914
915   wl_subsurface_set_position (window->video_subsurface, res.x, res.y);
916   wl_viewport_set_destination (window->video_viewport, res.w, res.h);
917
918   if (commit) {
919     wl_surface_damage (window->video_surface, 0, 0, res.w, res.h);
920     wl_surface_commit (window->video_surface);
921   }
922
923   if (gst_wl_window_is_toplevel (window)) {
924     struct wl_region *region;
925
926     region = wl_compositor_create_region (window->display->compositor);
927     wl_region_add (region, 0, 0, window->render_rectangle.w,
928         window->render_rectangle.h);
929     wl_surface_set_input_region (window->area_surface, region);
930     wl_region_destroy (region);
931   }
932
933   /* this is saved for use in wl_surface_damage */
934   window->surface_width = res.w;
935   window->surface_height = res.h;
936 }
937 #endif
938 void
939 gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
940     const GstVideoInfo * info)
941 {
942 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
943   FUNCTION;
944   /* check video buffer size for wl_surface_damage_buffer */
945   if (window->buffer_width != window->display->buffer_width
946       || window->buffer_height != window->display->buffer_height) {
947     window->buffer_width = window->display->buffer_width;
948     window->buffer_height = window->display->buffer_height;
949     GST_LOG ("buffer_width(%d) buffer_height(%d)",
950         window->display->buffer_width, window->display->buffer_height);
951   }
952   GST_LOG ("buffer_width(%d) buffer_height(%d)", window->display->buffer_width,
953       window->display->buffer_height);
954
955   if (G_UNLIKELY (info)) {
956     window->video_width =
957         gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
958     window->video_height = info->height;
959
960     wl_subsurface_set_sync (window->video_subsurface);
961     GST_INFO ("wl_subsurface_set_sync (video_subsurface@%p)",
962         window->video_subsurface);
963     /* check video_info_changed to remove repetitive IPC */
964     if (window->video_info_changed) {
965       gst_wl_window_resize_tizen_video_viewport (window, FALSE);
966       window->video_info_changed = FALSE;
967     }
968   }
969
970   GST_LOG ("GstWlBuffer(%p)", buffer);
971   if (G_LIKELY (buffer))
972     gst_wl_buffer_attach (buffer, window->video_surface);
973   else {
974     GST_INFO ("wl_surface_attach (video_surface@%p, NULL, 0, 0)",
975         window->video_surface);
976     wl_surface_attach (window->video_surface, NULL, 0, 0);
977   }
978   /* use tizen view port */
979   GST_INFO
980       ("wl_surface_damage_buffer (video_surface@%p, buffer_x@%d, buffer_y@%d, buffer_w@%d, buffer_h@%d)",
981       window->video_surface, window->buffer_x, window->buffer_y,
982       window->buffer_width, window->buffer_height);
983   wl_surface_damage_buffer (window->video_surface, window->buffer_x,
984       window->buffer_y, window->buffer_width, window->buffer_height);
985   /* wl_surface_commit change surface state, if wl_buffer is not attached newly,  then surface is not changed */
986   GST_INFO ("wl_surface_commit (video_surface@%p)", window->video_surface);
987   wl_surface_commit (window->video_surface);
988
989   if (G_UNLIKELY (info)) {
990     GST_INFO ("wl_surface_commit (area_surface@%p)", window->area_surface);
991     wl_surface_commit (window->area_surface);
992     GST_INFO ("wl_subsurface_set_desync (video_subsurface@%p)",
993         window->video_subsurface);
994     wl_subsurface_set_desync (window->video_subsurface);
995   }
996
997   wl_display_flush (window->display->display);
998 #endif
999 }
1000
1001 #ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
1002 gboolean
1003 gst_wl_window_set_roi_area (GstWlWindow * window, gint x, gint y,
1004     gint w, gint h)
1005 {
1006   FUNCTION;
1007   g_return_val_if_fail (window != NULL, FALSE);
1008
1009   if (w < 0 || h < 0) {
1010     GST_ERROR ("Error : wrong roi size w(%d), h(%d)", w, h);
1011     return FALSE;
1012   }
1013
1014   window->roi.x = x;
1015   window->roi.y = y;
1016   window->roi.w = w;
1017   window->roi.h = h;
1018   GST_LOG ("set roi x(%d), y(%d), w(%d), h(%d)", x, y, w, h);
1019   window->roi_area_changed = TRUE;
1020
1021   return TRUE;
1022 }
1023
1024 void
1025 gst_wl_window_set_rotate_angle (GstWlWindow * window, guint rotate_angle)
1026 {
1027   FUNCTION;
1028   g_return_if_fail (window != NULL);
1029   window->rotate_angle.value = rotate_angle;
1030   GST_LOG ("rotate_angle value is (%d)", window->rotate_angle.value);
1031   window->rotate_angle.changed = TRUE;
1032 }
1033
1034 void
1035 gst_wl_window_set_destination_mode (GstWlWindow * window, guint disp_geo_method)
1036 {
1037   FUNCTION;
1038   g_return_if_fail (window != NULL);
1039   window->disp_geo_method.value = disp_geo_method;
1040   GST_LOG ("disp_geo_method value is (%d)", window->disp_geo_method.value);
1041   window->disp_geo_method.changed = TRUE;
1042 }
1043
1044 void
1045 gst_wl_window_set_flip (GstWlWindow * window, guint flip)
1046 {
1047   FUNCTION;
1048   g_return_if_fail (window != NULL);
1049   window->flip.value = flip;
1050   GST_LOG ("flip value is (%d)", window->flip.value);
1051   window->flip.changed = TRUE;
1052 }
1053
1054 void
1055 gst_wl_window_set_source_wl_buffer (GstWlWindow * window,
1056     guint x, guint y, guint w, guint h)
1057 {
1058   FUNCTION;
1059   g_return_if_fail (window != NULL);
1060   g_return_if_fail (w > 0 && h > 0);
1061   GST_WARNING ("set video source x@%d, y@%d, w@%d, h@%d", x, y, w, h);
1062   window->set_source.x = x;
1063   window->set_source.y = y;
1064   window->set_source.w = w;
1065   window->set_source.h = h;
1066   window->set_source.changed = TRUE;
1067 }
1068
1069 #ifdef ENABLE_FUNCTION
1070 void
1071 gst_wl_window_set_destination_mode_follow_parent_transform (GstWlWindow *
1072     window, gboolean follow_parent_transform)
1073 {
1074   FUNCTION;
1075   g_return_if_fail (window != NULL);
1076   window->follow_parent_transform.value = follow_parent_transform;
1077   GST_LOG ("follow_parent_transform value is (%d)",
1078       window->follow_parent_transform.value);
1079   window->follow_parent_transform.changed = TRUE;
1080 }
1081
1082
1083 void
1084 gst_wl_window_set_destination_mode_offset (GstWlWindow * window, guint x,
1085     guint y, guint w, guint h)
1086 {
1087   FUNCTION;
1088   g_return_if_fail (window != NULL);
1089   GST_LOG ("set offset x@%d, y@%d", x, y);
1090   window->mode_offset.x = x;
1091   window->mode_offset.y = y;
1092   window->mode_offset.w = w;
1093   window->mode_offset.h = h;
1094   window->mode_offset.changed = TRUE;
1095 }
1096
1097 void
1098 gst_wl_window_set_destination_mode_ratio (GstWlWindow * window, gdouble w,
1099     gdouble h)
1100 {
1101   FUNCTION;
1102   g_return_if_fail (window != NULL);
1103   GST_LOG ("set ratio w@%f, h@%f", w, h);
1104   window->mode_ratio.w = w;
1105   window->mode_ratio.h = h;
1106   window->mode_ratio.changed = TRUE;
1107 }
1108
1109 void
1110 gst_wl_window_set_destination_mode_scale (GstWlWindow * window, gdouble w,
1111     gdouble h)
1112 {
1113   FUNCTION;
1114   g_return_if_fail (window != NULL);
1115   GST_LOG ("set scale w@%f, h@%f", w, h);
1116   window->mode_scale.w = w;
1117   window->mode_scale.h = h;
1118   window->mode_scale.changed = TRUE;
1119 }
1120
1121 void
1122 gst_wl_window_set_destination_mode_align (GstWlWindow * window, gdouble w,
1123     gdouble h)
1124 {
1125   FUNCTION;
1126   g_return_if_fail (window != NULL);
1127   GST_LOG ("set align w@%f, h@%f", w, h);
1128   window->mode_align.w = w;
1129   window->mode_align.h = h;
1130   window->mode_align.changed = TRUE;
1131 }
1132 #endif
1133 void
1134 gst_wl_window_set_video_info_change (GstWlWindow * window, guint changed)
1135 {
1136   FUNCTION;
1137   g_return_if_fail (window != NULL);
1138   window->video_info_changed = changed;
1139   GST_LOG ("video_info_changed value is (%d)", window->video_info_changed);
1140 }
1141 #endif