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 = ▭
371 }
372 return klass->put_surface (texture, surface, crop_rect, flags);
373 }
374