1 /*
2  *  gstvaapitexture.c - VA texture abstraction
3  *
4  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
5  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
6  *  Copyright (C) 2012-2013 Intel Corporation
7  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public License
11  *  as published by the Free Software Foundation; either version 2.1
12  *  of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free
21  *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301 USA
23  */
24 
25 /**
26  * SECTION:gstvaapitexture
27  * @short_description: VA/GLX texture abstraction
28  */
29 
30 #include "sysdeps.h"
31 #include "gstvaapitexture.h"
32 #include "gstvaapitexture_priv.h"
33 
34 #define DEBUG 1
35 #include "gstvaapidebug.h"
36 
37 #define GST_VAAPI_TEXTURE_ORIENTATION_FLAGS \
38   (GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED | \
39    GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED)
40 
41 static void
gst_vaapi_texture_init(GstVaapiTexture * texture,GstVaapiID id,guint target,guint format,guint width,guint height)42 gst_vaapi_texture_init (GstVaapiTexture * texture, GstVaapiID id,
43     guint target, guint format, guint width, guint height)
44 {
45   texture->is_wrapped = id != GST_VAAPI_ID_INVALID;
46   GST_VAAPI_OBJECT_ID (texture) = texture->is_wrapped ? id : 0;
47   texture->gl_target = target;
48   texture->gl_format = format;
49   texture->width = width;
50   texture->height = height;
51 }
52 
53 static inline gboolean
gst_vaapi_texture_allocate(GstVaapiTexture * texture)54 gst_vaapi_texture_allocate (GstVaapiTexture * texture)
55 {
56   return GST_VAAPI_TEXTURE_GET_CLASS (texture)->allocate (texture);
57 }
58 
59 GstVaapiTexture *
gst_vaapi_texture_new_internal(const GstVaapiTextureClass * klass,GstVaapiDisplay * display,GstVaapiID id,guint target,guint format,guint width,guint height)60 gst_vaapi_texture_new_internal (const GstVaapiTextureClass * klass,
61     GstVaapiDisplay * display, GstVaapiID id, guint target, guint format,
62     guint width, guint height)
63 {
64   GstVaapiTexture *texture;
65 
66   g_return_val_if_fail (target != 0, NULL);
67   g_return_val_if_fail (format != 0, NULL);
68   g_return_val_if_fail (width > 0, NULL);
69   g_return_val_if_fail (height > 0, NULL);
70 
71   texture = gst_vaapi_object_new (GST_VAAPI_OBJECT_CLASS (klass), display);
72   if (!texture)
73     return NULL;
74 
75   gst_vaapi_texture_init (texture, id, target, format, width, height);
76   if (!gst_vaapi_texture_allocate (texture))
77     goto error;
78   return texture;
79 
80   /* ERRORS */
81 error:
82   {
83     gst_vaapi_object_unref (texture);
84     return NULL;
85   }
86 }
87 
88 /**
89  * gst_vaapi_texture_new:
90  * @display: a #GstVaapiDisplay
91  * @target: the target to which the texture is bound
92  * @format: the format of the pixel data
93  * @width: the requested width, in pixels
94  * @height: the requested height, in pixels
95  *
96  * Creates a texture with the specified dimensions, @target and
97  * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or
98  * GL_BGRA formats are supported at this time.
99  *
100  * The application shall maintain the live GL context itself.
101  *
102  * Return value: the newly created #GstVaapiTexture object
103  */
104 GstVaapiTexture *
gst_vaapi_texture_new(GstVaapiDisplay * display,guint target,guint format,guint width,guint height)105 gst_vaapi_texture_new (GstVaapiDisplay * display, guint target, guint format,
106     guint width, guint height)
107 {
108   GstVaapiDisplayClass *dpy_class;
109 
110   g_return_val_if_fail (display != NULL, NULL);
111   g_return_val_if_fail (gst_vaapi_display_has_opengl (display), NULL);
112 
113   dpy_class = GST_VAAPI_DISPLAY_GET_CLASS (display);
114   if (G_UNLIKELY (!dpy_class->create_texture))
115     return NULL;
116   return dpy_class->create_texture (display, GST_VAAPI_ID_INVALID, target,
117       format, width, height);
118 }
119 
120 /**
121  * gst_vaapi_texture_new_wrapped:
122  * @display: a #GstVaapiDisplay
123  * @texture_id: the foreign GL texture name to use
124  * @target: the target to which the texture is bound
125  * @format: the format of the pixel data
126  * @width: the suggested width, in pixels
127  * @height: the suggested height, in pixels
128  *
129  * Creates a texture with the specified dimensions, @target and
130  * @format. Note that only GL_TEXTURE_2D @target and GL_RGBA or
131  * GL_BGRA formats are supported at this time.
132  *
133  * The size arguments @width and @height are only a suggestion. Should
134  * this be 0x0, then the actual size of the allocated texture storage
135  * would be either inherited from the original texture storage, if any
136  * and/or if possible, or derived from the VA surface in subsequent
137  * gst_vaapi_texture_put_surface() calls.
138  *
139  * The application shall maintain the live GL context itself.
140  *
141  * Return value: the newly created #GstVaapiTexture object
142  */
143 GstVaapiTexture *
gst_vaapi_texture_new_wrapped(GstVaapiDisplay * display,guint id,guint target,guint format,guint width,guint height)144 gst_vaapi_texture_new_wrapped (GstVaapiDisplay * display, guint id,
145     guint target, guint format, guint width, guint height)
146 {
147   GstVaapiDisplayClass *dpy_class;
148 
149   g_return_val_if_fail (display != NULL, NULL);
150   g_return_val_if_fail (gst_vaapi_display_has_opengl (display), NULL);
151 
152   dpy_class = GST_VAAPI_DISPLAY_GET_CLASS (display);
153   if (G_UNLIKELY (!dpy_class->create_texture))
154     return NULL;
155   return dpy_class->create_texture (display, id, target, format, width, height);
156 }
157 
158 /**
159  * gst_vaapi_texture_ref:
160  * @texture: a #GstVaapiTexture
161  *
162  * Atomically increases the reference count of the given @texture by one.
163  *
164  * Returns: The same @texture argument
165  */
166 GstVaapiTexture *
gst_vaapi_texture_ref(GstVaapiTexture * texture)167 gst_vaapi_texture_ref (GstVaapiTexture * texture)
168 {
169   return gst_vaapi_object_ref (GST_VAAPI_OBJECT (texture));
170 }
171 
172 /**
173  * gst_vaapi_texture_unref:
174  * @texture: a #GstVaapiTexture
175  *
176  * Atomically decreases the reference count of the @texture by one. If
177  * the reference count reaches zero, the texture will be free'd.
178  */
179 void
gst_vaapi_texture_unref(GstVaapiTexture * texture)180 gst_vaapi_texture_unref (GstVaapiTexture * texture)
181 {
182   gst_vaapi_object_unref (GST_VAAPI_OBJECT (texture));
183 }
184 
185 /**
186  * gst_vaapi_texture_replace:
187  * @old_texture_ptr: a pointer to a #GstVaapiTexture
188  * @new_texture: a #GstVaapiTexture
189  *
190  * Atomically replaces the texture texture held in @old_texture_ptr
191  * with @new_texture. This means that @old_texture_ptr shall reference
192  * a valid texture. However, @new_texture can be NULL.
193  */
194 void
gst_vaapi_texture_replace(GstVaapiTexture ** old_texture_ptr,GstVaapiTexture * new_texture)195 gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr,
196     GstVaapiTexture * new_texture)
197 {
198   gst_vaapi_object_replace ((GstVaapiObject **) (old_texture_ptr),
199       GST_VAAPI_OBJECT (new_texture));
200 }
201 
202 /**
203  * gst_vaapi_texture_get_id:
204  * @texture: a #GstVaapiTexture
205  *
206  * Returns the underlying texture id of the @texture.
207  *
208  * Return value: the underlying texture id of the @texture
209  */
210 guint
gst_vaapi_texture_get_id(GstVaapiTexture * texture)211 gst_vaapi_texture_get_id (GstVaapiTexture * texture)
212 {
213   g_return_val_if_fail (texture != NULL, 0);
214 
215   return GST_VAAPI_TEXTURE_ID (texture);
216 }
217 
218 /**
219  * gst_vaapi_texture_get_target:
220  * @texture: a #GstVaapiTexture
221  *
222  * Returns the @texture target type
223  *
224  * Return value: the texture target
225  */
226 guint
gst_vaapi_texture_get_target(GstVaapiTexture * texture)227 gst_vaapi_texture_get_target (GstVaapiTexture * texture)
228 {
229   g_return_val_if_fail (texture != NULL, 0);
230 
231   return GST_VAAPI_TEXTURE_TARGET (texture);
232 }
233 
234 /**
235  * gst_vaapi_texture_get_format
236  * @texture: a #GstVaapiTexture
237  *
238  * Returns the @texture format
239  *
240  * Return value: the texture format
241  */
242 guint
gst_vaapi_texture_get_format(GstVaapiTexture * texture)243 gst_vaapi_texture_get_format (GstVaapiTexture * texture)
244 {
245   g_return_val_if_fail (texture != NULL, 0);
246 
247   return GST_VAAPI_TEXTURE_FORMAT (texture);
248 }
249 
250 /**
251  * gst_vaapi_texture_get_width:
252  * @texture: a #GstVaapiTexture
253  *
254  * Returns the @texture width.
255  *
256  * Return value: the texture width, in pixels
257  */
258 guint
gst_vaapi_texture_get_width(GstVaapiTexture * texture)259 gst_vaapi_texture_get_width (GstVaapiTexture * texture)
260 {
261   g_return_val_if_fail (texture != NULL, 0);
262 
263   return GST_VAAPI_TEXTURE_WIDTH (texture);
264 }
265 
266 /**
267  * gst_vaapi_texture_get_height:
268  * @texture: a #GstVaapiTexture
269  *
270  * Returns the @texture height.
271  *
272  * Return value: the texture height, in pixels.
273  */
274 guint
gst_vaapi_texture_get_height(GstVaapiTexture * texture)275 gst_vaapi_texture_get_height (GstVaapiTexture * texture)
276 {
277   g_return_val_if_fail (texture != NULL, 0);
278 
279   return GST_VAAPI_TEXTURE_HEIGHT (texture);
280 }
281 
282 /**
283  * gst_vaapi_texture_get_size:
284  * @texture: a #GstVaapiTexture
285  * @width_ptr: return location for the width, or %NULL
286  * @height_ptr: return location for the height, or %NULL
287  *
288  * Retrieves the dimensions of a #GstVaapiTexture.
289  */
290 void
gst_vaapi_texture_get_size(GstVaapiTexture * texture,guint * width_ptr,guint * height_ptr)291 gst_vaapi_texture_get_size (GstVaapiTexture * texture,
292     guint * width_ptr, guint * height_ptr)
293 {
294   g_return_if_fail (texture != NULL);
295 
296   if (width_ptr)
297     *width_ptr = GST_VAAPI_TEXTURE_WIDTH (texture);
298 
299   if (height_ptr)
300     *height_ptr = GST_VAAPI_TEXTURE_HEIGHT (texture);
301 }
302 
303 /**
304  * gst_vaapi_texture_get_orientation_flags:
305  * @texture: a #GstVaapiTexture
306  *
307  * Retrieves the texture memory layout flags, i.e. orientation.
308  *
309  * Return value: the #GstVaapiTextureOrientationFlags.
310  */
311 guint
gst_vaapi_texture_get_orientation_flags(GstVaapiTexture * texture)312 gst_vaapi_texture_get_orientation_flags (GstVaapiTexture * texture)
313 {
314   g_return_val_if_fail (texture != NULL, 0);
315 
316   return GST_VAAPI_TEXTURE_FLAGS (texture) &
317       GST_VAAPI_TEXTURE_ORIENTATION_FLAGS;
318 }
319 
320 /**
321  * gst_vaapi_texture_set_orientation_flags:
322  * @texture: a #GstVaapiTexture
323  * @flags: a bitmask of #GstVaapiTextureOrientationFlags
324  *
325  * Reset the texture orientation flags to the supplied set of
326  * @flags. This completely replaces the previously installed
327  * flags. So, should they still be needed, then they shall be
328  * retrieved first with gst_vaapi_texture_get_orientation_flags().
329  */
330 void
gst_vaapi_texture_set_orientation_flags(GstVaapiTexture * texture,guint flags)331 gst_vaapi_texture_set_orientation_flags (GstVaapiTexture * texture, guint flags)
332 {
333   g_return_if_fail (texture != NULL);
334   g_return_if_fail ((flags & ~GST_VAAPI_TEXTURE_ORIENTATION_FLAGS) == 0);
335 
336   GST_VAAPI_TEXTURE_FLAG_UNSET (texture, GST_VAAPI_TEXTURE_ORIENTATION_FLAGS);
337   GST_VAAPI_TEXTURE_FLAG_SET (texture, flags);
338 }
339 
340 /**
341  * gst_vaapi_texture_put_surface:
342  * @texture: a #GstVaapiTexture
343  * @surface: a #GstVaapiSurface
344  * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags
345  *
346  * Renders the @surface into the àtexture. The @flags specify how
347  * de-interlacing (if needed), color space conversion, scaling and
348  * other postprocessing transformations are performed.
349  *
350  * Return value: %TRUE on success
351  */
352 gboolean
gst_vaapi_texture_put_surface(GstVaapiTexture * texture,GstVaapiSurface * surface,const GstVaapiRectangle * crop_rect,guint flags)353 gst_vaapi_texture_put_surface (GstVaapiTexture * texture,
354     GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
355 {
356   const GstVaapiTextureClass *klass;
357   GstVaapiRectangle rect;
358 
359   g_return_val_if_fail (texture != NULL, FALSE);
360   g_return_val_if_fail (surface != NULL, FALSE);
361 
362   klass = GST_VAAPI_TEXTURE_GET_CLASS (texture);
363   if (!klass)
364     return FALSE;
365 
366   if (!crop_rect) {
367     rect.x = 0;
368     rect.y = 0;
369     gst_vaapi_surface_get_size (surface, &rect.width, &rect.height);
370     crop_rect = &rect;
371   }
372   return klass->put_surface (texture, surface, crop_rect, flags);
373 }
374