gst: don't use volatile to mean atomic
[platform/upstream/gstreamer.git] / gst-libs / gst / vulkan / android / gstvkwindow_android.c
1 /*
2  * GStreamer
3  * Copyright (C) 2019 Matthew Waters <matthew@centricular.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26
27 #include <gst/vulkan/vulkan.h>
28
29 #include "gstvkwindow_android.h"
30 #include "gstvkdisplay_android.h"
31
32 #define GET_PRIV(o) gst_vulkan_window_android_get_instance_private (o)
33
34 #define GST_CAT_DEFAULT gst_vulkan_window_android_debug
35 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
36
37 static void
38 _init_debug (void)
39 {
40   static gsize _init = 0;
41
42   if (g_once_init_enter (&_init)) {
43     GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "vulkanwindowandroid", 0,
44         "Vulkan Android Window");
45     g_once_init_leave (&_init, 1);
46   }
47 }
48
49 enum
50 {
51   PROP_0,
52 };
53
54 struct _GstVulkanWindowAndroidPrivate
55 {
56   struct ANativeWindow *internal_window;
57   gint window_width, window_height;
58
59   gint preferred_width;
60   gint preferred_height;
61 };
62
63 #define gst_vulkan_window_android_parent_class parent_class
64 G_DEFINE_TYPE_WITH_CODE (GstVulkanWindowAndroid, gst_vulkan_window_android,
65     GST_TYPE_VULKAN_WINDOW,
66     G_ADD_PRIVATE (GstVulkanWindowAndroid) _init_debug ());
67
68 static VkSurfaceKHR gst_vulkan_window_android_get_surface (GstVulkanWindow *
69     window, GError ** error);
70 static gboolean
71 gst_vulkan_window_android_get_presentation_support (GstVulkanWindow * window,
72     GstVulkanDevice * device, guint32 queue_family_idx);
73 static gboolean gst_vulkan_window_android_open (GstVulkanWindow * window,
74     GError ** error);
75 static void gst_vulkan_window_android_close (GstVulkanWindow * window);
76 static void gst_vulkan_window_android_set_window_handle (GstVulkanWindow *
77     window, guintptr window_handle);
78
79 static void
80 gst_vulkan_window_android_class_init (GstVulkanWindowAndroidClass * klass)
81 {
82   GstVulkanWindowClass *window_class = (GstVulkanWindowClass *) klass;
83
84   window_class->open = GST_DEBUG_FUNCPTR (gst_vulkan_window_android_open);
85   window_class->close = GST_DEBUG_FUNCPTR (gst_vulkan_window_android_close);
86   window_class->get_surface = gst_vulkan_window_android_get_surface;
87   window_class->get_presentation_support =
88       gst_vulkan_window_android_get_presentation_support;
89   window_class->set_window_handle = gst_vulkan_window_android_set_window_handle;
90 }
91
92 static void
93 gst_vulkan_window_android_init (GstVulkanWindowAndroid * window)
94 {
95   GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window);
96
97   priv->preferred_width = 320;
98   priv->preferred_height = 240;
99 }
100
101 /* Must be called in the gl thread */
102 GstVulkanWindowAndroid *
103 gst_vulkan_window_android_new (GstVulkanDisplay * display)
104 {
105   GstVulkanWindowAndroid *window;
106
107   _init_debug ();
108
109   if ((gst_vulkan_display_get_handle_type (display) &
110           GST_VULKAN_DISPLAY_TYPE_ANDROID)
111       == GST_VULKAN_DISPLAY_TYPE_NONE) {
112     GST_INFO ("Wrong display type %u for this window type %u", display->type,
113         GST_VULKAN_DISPLAY_TYPE_ANDROID);
114     return NULL;
115   }
116
117   window = g_object_new (GST_TYPE_VULKAN_WINDOW_ANDROID, NULL);
118   gst_object_ref_sink (window);
119
120   return window;
121 }
122
123 gboolean
124 gst_vulkan_window_android_create_window (GstVulkanWindowAndroid *
125     window_android)
126 {
127   GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android);
128
129   if (!priv->internal_window) {
130     GST_WARNING_OBJECT (window_android, "No ANativeWindow provided");
131     return FALSE;
132   }
133
134   return TRUE;
135 }
136
137 static VkSurfaceKHR
138 gst_vulkan_window_android_get_surface (GstVulkanWindow * window,
139     GError ** error)
140 {
141   GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window);
142   GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android);
143   VkAndroidSurfaceCreateInfoKHR info = { 0, };
144   VkSurfaceKHR ret;
145   VkResult err;
146
147   if (!priv->internal_window) {
148     g_set_error_literal (error, GST_VULKAN_ERROR,
149         VK_ERROR_INITIALIZATION_FAILED,
150         "No layer to retrieve surface for. Has create_window() been called?");
151     return 0;
152   }
153
154   info.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
155   info.pNext = NULL;
156   info.flags = 0;
157   info.window = priv->internal_window;
158
159   if (!window_android->CreateAndroidSurface)
160     window_android->CreateAndroidSurface =
161         gst_vulkan_instance_get_proc_address (window->display->instance,
162         "vkCreateAndroidSurfaceKHR");
163   if (!window_android->CreateAndroidSurface) {
164     g_set_error_literal (error, GST_VULKAN_ERROR, VK_ERROR_FEATURE_NOT_PRESENT,
165         "Could not retrieve \"vkCreateAndroidSurfaceKHR\" function pointer");
166     return 0;
167   }
168
169   err =
170       window_android->CreateAndroidSurface (window->display->instance->instance,
171       &info, NULL, &ret);
172   if (gst_vulkan_error_to_g_error (err, error, "vkCreateAndroidSurfaceKHR") < 0)
173     return 0;
174
175   return ret;
176 }
177
178 static gboolean
179 gst_vulkan_window_android_get_presentation_support (GstVulkanWindow * window,
180     GstVulkanDevice * device, guint32 queue_family_idx)
181 {
182   return TRUE;
183 }
184
185 static gboolean
186 gst_vulkan_window_android_open (GstVulkanWindow * window, GError ** error)
187 {
188   GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window);
189
190   if (!GST_VULKAN_WINDOW_CLASS (parent_class)->open (window, error))
191     return FALSE;
192
193   return gst_vulkan_window_android_create_window (window_android);
194 }
195
196 static void
197 gst_vulkan_window_android_close (GstVulkanWindow * window)
198 {
199   GST_VULKAN_WINDOW_CLASS (parent_class)->close (window);
200 }
201
202 static void
203 gst_vulkan_window_android_set_window_handle (GstVulkanWindow * window,
204     guintptr window_handle)
205 {
206   GstVulkanWindowAndroid *window_android = GST_VULKAN_WINDOW_ANDROID (window);
207   GstVulkanWindowAndroidPrivate *priv = GET_PRIV (window_android);
208   struct ANativeWindow *native_window = (struct ANativeWindow *) window_handle;
209
210   g_return_if_fail (native_window != NULL);
211
212   if (priv->internal_window && priv->internal_window != native_window) {
213     GST_FIXME_OBJECT (window_android, "View changes are not implemented");
214     return;
215   }
216
217   priv->internal_window = native_window;
218 }