1From e1f73551e144f25cac6953bbab9201b6a2f47fcb Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Fri, 28 Apr 2023 18:34:49 +0800
4Subject: [PATCH 16/16] xvimagesink: Apply toplevel window's position
5
6Tested on RK3588 evb with:
7gst-launch-1.0 videotestsrc ! xvimagesink render-rectangle='<100,200,300,400>'
8
9Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
10---
11 sys/xvimage/xvcontext.c        | 18 +++++++++++---
12 sys/xvimage/xvcontext.h        |  1 +
13 sys/xvimage/xvimageallocator.c | 45 ++++++++++++++++++++++------------
14 sys/xvimage/xvimagesink.c      | 20 ++++++++++++---
15 4 files changed, 60 insertions(+), 24 deletions(-)
16
17diff --git a/sys/xvimage/xvcontext.c b/sys/xvimage/xvcontext.c
18index 97962d9..5fd1c85 100644
19--- a/sys/xvimage/xvcontext.c
20+++ b/sys/xvimage/xvcontext.c
21@@ -1048,19 +1048,21 @@ gst_xv_touchdevice_free (GstXvTouchDevice * device)
22 #endif
23
24 GstXWindow *
25-gst_xvcontext_create_xwindow (GstXvContext * context, gint width, gint height,
26-    gboolean decorations)
27+gst_xvcontext_create_xwindow (GstXvContext * context, gint x, gint y,
28+    gint width, gint height, gboolean decorations)
29 {
30   GstXWindow *window;
31   Atom wm_delete;
32   Atom hints_atom = None;
33+  XSizeHints hints;
34
35   g_return_val_if_fail (GST_IS_XVCONTEXT (context), NULL);
36
37   window = g_slice_new0 (GstXWindow);
38
39   window->context = gst_xvcontext_ref (context);
40-  window->render_rect.x = window->render_rect.y = 0;
41+  window->render_rect.x = x;
42+  window->render_rect.y = y;
43   window->render_rect.w = width;
44   window->render_rect.h = height;
45   window->have_render_rect = FALSE;
46@@ -1079,7 +1081,15 @@ gst_xvcontext_create_xwindow (GstXvContext * context, gint width, gint height,
47   g_mutex_lock (&context->lock);
48
49   window->win = XCreateSimpleWindow (context->disp,
50-      context->root, 0, 0, width, height, 0, 0, context->black);
51+      context->root, x, y, width, height, 0, 0, context->black);
52+
53+  /* Apply size hints */
54+  hints.flags  = USPosition | USSize;
55+  hints.x = x;
56+  hints.y = y;
57+  hints.width  = width;
58+  hints.height = height;
59+  XSetWMNormalHints (context->disp, window->win, &hints);
60
61   /* We have to do that to prevent X from redrawing the background on
62    * ConfigureNotify. This takes away flickering of video when resizing. */
63diff --git a/sys/xvimage/xvcontext.h b/sys/xvimage/xvcontext.h
64index 1fb7614..9f535ae 100644
65--- a/sys/xvimage/xvcontext.h
66+++ b/sys/xvimage/xvcontext.h
67@@ -287,6 +287,7 @@ struct _GstXvTouchDevice {
68 G_END_DECLS
69
70 GstXWindow *   gst_xvcontext_create_xwindow     (GstXvContext * context,
71+                                                 gint x, gint y,
72                                                  gint width, gint height,
73                                                  gboolean decorations);
74 GstXWindow *   gst_xvcontext_create_xwindow_from_xid (GstXvContext * context, XID xid);
75diff --git a/sys/xvimage/xvimageallocator.c b/sys/xvimage/xvimageallocator.c
76index a6d8432..e5264b7 100644
77--- a/sys/xvimage/xvimageallocator.c
78+++ b/sys/xvimage/xvimageallocator.c
79@@ -590,46 +590,48 @@ xattach_failed:
80
81 /* We are called with the x_lock taken */
82 static void
83-gst_xwindow_draw_borders (GstXWindow * window, GstVideoRectangle * rect)
84+gst_xwindow_draw_borders (GstXWindow * window, GstVideoRectangle * render_rect,
85+    GstVideoRectangle * video_rect)
86 {
87   gint t1, t2;
88   GstXvContext *context;
89
90   g_return_if_fail (window != NULL);
91-  g_return_if_fail (rect != NULL);
92+  g_return_if_fail (render_rect != NULL);
93+  g_return_if_fail (video_rect != NULL);
94
95   context = window->context;
96
97   XSetForeground (context->disp, window->gc, context->black);
98
99   /* Left border */
100-  if (rect->x > window->render_rect.x) {
101+  if (video_rect->x > render_rect->x) {
102     XFillRectangle (context->disp, window->win, window->gc,
103-        window->render_rect.x, window->render_rect.y,
104-        rect->x - window->render_rect.x, window->render_rect.h);
105+        render_rect->x, render_rect->y,
106+        video_rect->x - render_rect->x, render_rect->h);
107   }
108
109   /* Right border */
110-  t1 = rect->x + rect->w;
111-  t2 = window->render_rect.x + window->render_rect.w;
112+  t1 = video_rect->x + video_rect->w;
113+  t2 = render_rect->x + render_rect->w;
114   if (t1 < t2) {
115     XFillRectangle (context->disp, window->win, window->gc,
116-        t1, window->render_rect.y, t2 - t1, window->render_rect.h);
117+        t1, render_rect->y, t2 - t1, render_rect->h);
118   }
119
120   /* Top border */
121-  if (rect->y > window->render_rect.y) {
122+  if (video_rect->y > render_rect->y) {
123     XFillRectangle (context->disp, window->win, window->gc,
124-        window->render_rect.x, window->render_rect.y,
125-        window->render_rect.w, rect->y - window->render_rect.y);
126+        render_rect->x, render_rect->y,
127+        render_rect->w, video_rect->y - render_rect->y);
128   }
129
130   /* Bottom border */
131-  t1 = rect->y + rect->h;
132-  t2 = window->render_rect.y + window->render_rect.h;
133+  t1 = video_rect->y + video_rect->h;
134+  t2 = render_rect->y + render_rect->h;
135   if (t1 < t2) {
136     XFillRectangle (context->disp, window->win, window->gc,
137-        window->render_rect.x, t1, window->render_rect.w, t2 - t1);
138+        render_rect->x, t1, render_rect->w, t2 - t1);
139   }
140 }
141
142@@ -639,15 +641,26 @@ gst_xvimage_memory_render (GstXvImageMemory * mem, GstVideoRectangle * src_crop,
143 {
144   GstXvContext *context;
145   XvImage *xvimage;
146+  GstVideoRectangle render_rect;
147
148   context = window->context;
149
150   g_mutex_lock (&context->lock);
151   xvimage = gst_xvimage_memory_get_xvimage (mem);
152
153-  if (draw_border) {
154-    gst_xwindow_draw_borders (window, dst_crop);
155+  render_rect = window->render_rect;
156+  if (window->internal) {
157+    XMoveResizeWindow (context->disp, window->win,
158+        window->render_rect.x, window->render_rect.y,
159+        window->render_rect.w, window->render_rect.h);
160+    dst_crop->x -= window->render_rect.x;
161+    dst_crop->y -= window->render_rect.y;
162+    render_rect.x = render_rect.y = 0;
163   }
164+
165+  if (draw_border)
166+    gst_xwindow_draw_borders (window, &render_rect, dst_crop);
167+
168 #ifdef HAVE_XSHM
169   if (context->use_xshm) {
170     GST_LOG ("XvShmPutImage with image %dx%d and window %dx%d, from xvimage %p",
171diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c
172index a0fa468..9f8b594 100644
173--- a/sys/xvimage/xvimagesink.c
174+++ b/sys/xvimage/xvimagesink.c
175@@ -548,7 +548,7 @@ gst_xv_image_sink_xwindow_set_title (GstXvImageSink * xvimagesink,
176 /* This function handles a GstXWindow creation
177  * The width and height are the actual pixel size on the display */
178 static GstXWindow *
179-gst_xv_image_sink_xwindow_new (GstXvImageSink * xvimagesink,
180+gst_xv_image_sink_xwindow_new (GstXvImageSink * xvimagesink, gint x, gint y,
181     gint width, gint height)
182 {
183   GstXWindow *xwindow = NULL;
184@@ -558,7 +558,7 @@ gst_xv_image_sink_xwindow_new (GstXvImageSink * xvimagesink,
185
186   context = xvimagesink->context;
187
188-  xwindow = gst_xvcontext_create_xwindow (context, width, height,
189+  xwindow = gst_xvcontext_create_xwindow (context, x, y, width, height,
190       xvimagesink->decorations);
191
192   /* set application name as a title */
193@@ -1156,9 +1156,21 @@ gst_xv_image_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
194   if (!xvimagesink->xwindow_id) {
195     GST_WARNING_OBJECT (xvimagesink, "overlay window not ready");
196   } else if (!xvimagesink->xwindow) {
197+    gint x, y, w, h;
198+
199+    if (xvimagesink->pending_render_rect) {
200+      x = xvimagesink->render_rect.x;
201+      y = xvimagesink->render_rect.y;
202+      w = xvimagesink->render_rect.w;
203+      h = xvimagesink->render_rect.h;
204+    } else {
205+      x = y = 0;
206+      w = GST_VIDEO_SINK_WIDTH (xvimagesink);
207+      h = GST_VIDEO_SINK_HEIGHT (xvimagesink);
208+    }
209+
210     xvimagesink->xwindow = gst_xv_image_sink_xwindow_new (xvimagesink,
211-        GST_VIDEO_SINK_WIDTH (xvimagesink),
212-        GST_VIDEO_SINK_HEIGHT (xvimagesink));
213+        x, y, w, h);
214   }
215
216   if (xvimagesink->pending_render_rect) {
217--
2182.20.1
219
220