vulkan: move fullscreenquad object to library
[platform/upstream/gstreamer.git] / ext / vulkan / vkimageidentity.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 /**
22  * SECTION:element-vulkanimageidentity
23  * @title: vulkanimgeidentity
24  *
25  * vulkanimageidentity produces a vulkan image that is a copy of the input image.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <string.h>
33
34 #include "vkimageidentity.h"
35
36 #include "shaders/identity.vert.h"
37 #include "shaders/identity.frag.h"
38
39 GST_DEBUG_CATEGORY (gst_debug_vulkan_image_identity);
40 #define GST_CAT_DEFAULT gst_debug_vulkan_image_identity
41
42 static gboolean gst_vulkan_image_identity_start (GstBaseTransform * bt);
43 static gboolean gst_vulkan_image_identity_stop (GstBaseTransform * bt);
44
45 static GstFlowReturn gst_vulkan_image_identity_transform (GstBaseTransform * bt,
46     GstBuffer * inbuf, GstBuffer * outbuf);
47 static gboolean gst_vulkan_image_identity_set_caps (GstBaseTransform * bt,
48     GstCaps * in_caps, GstCaps * out_caps);
49
50 #define IMAGE_FORMATS " { BGRA }"
51
52 static GstStaticPadTemplate gst_vulkan_sink_template =
53 GST_STATIC_PAD_TEMPLATE ("sink",
54     GST_PAD_SINK,
55     GST_PAD_ALWAYS,
56     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
57         (GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE,
58             IMAGE_FORMATS)));
59
60 static GstStaticPadTemplate gst_vulkan_src_template =
61 GST_STATIC_PAD_TEMPLATE ("src",
62     GST_PAD_SRC,
63     GST_PAD_ALWAYS,
64     GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
65         (GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE,
66             IMAGE_FORMATS)));
67
68 enum
69 {
70   PROP_0,
71 };
72
73 enum
74 {
75   SIGNAL_0,
76   LAST_SIGNAL
77 };
78
79 /* static guint gst_vulkan_image_identity_signals[LAST_SIGNAL] = { 0 }; */
80
81 #define gst_vulkan_image_identity_parent_class parent_class
82 G_DEFINE_TYPE_WITH_CODE (GstVulkanImageIdentity, gst_vulkan_image_identity,
83     GST_TYPE_VULKAN_VIDEO_FILTER,
84     GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_image_identity,
85         "vulkanimageidentity", 0, "Vulkan Image identity"));
86
87 static void
88 gst_vulkan_image_identity_class_init (GstVulkanImageIdentityClass * klass)
89 {
90   GstElementClass *gstelement_class;
91   GstBaseTransformClass *gstbasetransform_class;
92
93   gstelement_class = (GstElementClass *) klass;
94   gstbasetransform_class = (GstBaseTransformClass *) klass;
95
96   gst_element_class_set_metadata (gstelement_class, "Vulkan Image Identity",
97       "Filter/Video", "A Vulkan image copier",
98       "Matthew Waters <matthew@centricular.com>");
99
100   gst_element_class_add_static_pad_template (gstelement_class,
101       &gst_vulkan_sink_template);
102   gst_element_class_add_static_pad_template (gstelement_class,
103       &gst_vulkan_src_template);
104
105   gstbasetransform_class->start =
106       GST_DEBUG_FUNCPTR (gst_vulkan_image_identity_start);
107   gstbasetransform_class->stop =
108       GST_DEBUG_FUNCPTR (gst_vulkan_image_identity_stop);
109   gstbasetransform_class->set_caps = gst_vulkan_image_identity_set_caps;
110   gstbasetransform_class->transform = gst_vulkan_image_identity_transform;
111 }
112
113 static void
114 gst_vulkan_image_identity_init (GstVulkanImageIdentity * vk_identity)
115 {
116 }
117
118 static gboolean
119 gst_vulkan_image_identity_set_caps (GstBaseTransform * bt, GstCaps * in_caps,
120     GstCaps * out_caps)
121 {
122   GstVulkanVideoFilter *vfilter = GST_VULKAN_VIDEO_FILTER (bt);
123   GstVulkanImageIdentity *vk_identity = GST_VULKAN_IMAGE_IDENTITY (bt);
124
125   if (!GST_BASE_TRANSFORM_CLASS (parent_class)->set_caps (bt, in_caps,
126           out_caps))
127     return FALSE;
128
129   if (!gst_vulkan_full_screen_quad_set_info (vk_identity->quad,
130           &vfilter->in_info, &vfilter->out_info))
131     return FALSE;
132
133   return TRUE;
134 }
135
136 static gboolean
137 gst_vulkan_image_identity_start (GstBaseTransform * bt)
138 {
139   GstVulkanImageIdentity *vk_identity = GST_VULKAN_IMAGE_IDENTITY (bt);
140   GstVulkanVideoFilter *vfilter = GST_VULKAN_VIDEO_FILTER (vk_identity);
141   GstVulkanHandle *vert, *frag;
142   GError *error = NULL;
143
144   if (!GST_BASE_TRANSFORM_CLASS (parent_class)->start (bt))
145     return FALSE;
146
147   vk_identity->quad = gst_vulkan_full_screen_quad_new (vfilter->queue);
148
149   if (!(vert = gst_vulkan_create_shader (vfilter->device, identity_vert,
150               identity_vert_size, &error)))
151     goto error;
152   if (!(frag = gst_vulkan_create_shader (vfilter->device, identity_frag,
153               identity_frag_size, &error))) {
154     gst_vulkan_handle_unref (vert);
155     goto error;
156   }
157   gst_vulkan_full_screen_quad_set_shaders (vk_identity->quad, vert, frag);
158
159   gst_vulkan_handle_unref (vert);
160   gst_vulkan_handle_unref (frag);
161
162   return TRUE;
163
164 error:
165   GST_ELEMENT_ERROR (bt, RESOURCE, NOT_FOUND, ("%s", error->message), (NULL));
166   return FALSE;
167 }
168
169 static gboolean
170 gst_vulkan_image_identity_stop (GstBaseTransform * bt)
171 {
172   GstVulkanImageIdentity *vk_identity = GST_VULKAN_IMAGE_IDENTITY (bt);
173
174   gst_clear_object (&vk_identity->quad);
175
176   return GST_BASE_TRANSFORM_CLASS (parent_class)->stop (bt);
177 }
178
179 static GstFlowReturn
180 gst_vulkan_image_identity_transform (GstBaseTransform * bt, GstBuffer * inbuf,
181     GstBuffer * outbuf)
182 {
183   GstVulkanImageIdentity *vk_identity = GST_VULKAN_IMAGE_IDENTITY (bt);
184   GError *error = NULL;
185
186   if (!gst_vulkan_full_screen_quad_set_input_buffer (vk_identity->quad, inbuf,
187           &error))
188     goto error;
189   if (!gst_vulkan_full_screen_quad_set_output_buffer (vk_identity->quad, outbuf,
190           &error))
191     goto error;
192
193   if (!gst_vulkan_full_screen_quad_draw (vk_identity->quad, &error))
194     goto error;
195
196   return GST_FLOW_OK;
197
198 error:
199   GST_ELEMENT_ERROR (bt, LIBRARY, FAILED, ("%s", error->message), (NULL));
200   g_clear_error (&error);
201   return GST_FLOW_ERROR;
202 }