Add initial VA/GLX texture abstraction though the API is not good enough yet.
authorgb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Fri, 26 Mar 2010 16:52:07 +0000 (16:52 +0000)
committergb <gb@5584edef-b1fe-4b99-b61b-dd2bab72e969>
Fri, 26 Mar 2010 16:52:07 +0000 (16:52 +0000)
gst-libs/gst/vaapi/Makefile.am
gst-libs/gst/vaapi/gstvaapitexture.c [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapitexture.h [new file with mode: 0644]
gst-libs/gst/vaapi/gstvaapiutils_glx.c
gst-libs/gst/vaapi/gstvaapiutils_glx.h

index 6b3990b..e650c85 100644 (file)
@@ -74,6 +74,7 @@ libgstvaapi_x11_source_priv_h =                       \
 
 libgstvaapi_glx_source_c =                     \
        gstvaapidisplay_glx.c                   \
+       gstvaapitexture.c                       \
        gstvaapiutils.c                         \
        gstvaapiutils_glx.c                     \
        gstvaapiutils_x11.c                     \
@@ -82,6 +83,7 @@ libgstvaapi_glx_source_c =                    \
 
 libgstvaapi_glx_source_h =                     \
        gstvaapidisplay_glx.h                   \
+       gstvaapitexture.h                       \
        gstvaapiwindow_glx.h                    \
        $(NULL)
 
diff --git a/gst-libs/gst/vaapi/gstvaapitexture.c b/gst-libs/gst/vaapi/gstvaapitexture.c
new file mode 100644 (file)
index 0000000..ff90056
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ *  gstvaapitexture.c - VA texture abstraction
+ *
+ *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * SECTION:gstvaapitexture
+ * @short_description: VA/GLX texture abstraction
+ */
+
+#include "config.h"
+#include <va/va_glx.h>
+#include "gstvaapitexture.h"
+#include "gstvaapiutils.h"
+#include "gstvaapiutils_glx.h"
+#include "gstvaapiobject_priv.h"
+
+#define DEBUG 1
+#include "gstvaapidebug.h"
+
+G_DEFINE_TYPE(GstVaapiTexture, gst_vaapi_texture, GST_VAAPI_TYPE_OBJECT);
+
+#define GST_VAAPI_TEXTURE_GET_PRIVATE(obj)                      \
+    (G_TYPE_INSTANCE_GET_PRIVATE((obj),                         \
+                                 GST_VAAPI_TYPE_TEXTURE,        \
+                                 GstVaapiTexturePrivate))
+
+struct _GstVaapiTexturePrivate {
+    GLenum      target;
+    GLenum      format;
+    guint       width;
+    guint       height;
+    void       *gl_surface;
+    guint       foreign_texture : 1;
+    guint       is_constructed  : 1;
+};
+
+enum {
+    PROP_0,
+
+    PROP_TARGET,
+    PROP_FORMAT,
+    PROP_WIDTH,
+    PROP_HEIGHT
+};
+
+static void
+gst_vaapi_texture_destroy(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    const GLuint texture_id = GST_VAAPI_OBJECT_ID(texture);
+    VAStatus status;
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    if (priv->gl_surface) {
+        status = vaDestroySurfaceGLX(
+            GST_VAAPI_OBJECT_VADISPLAY(texture),
+            priv->gl_surface
+        );
+        priv->gl_surface = NULL;
+    }
+
+    if (texture) {
+        if (!priv->foreign_texture)
+            glDeleteTextures(1, &texture_id);
+        GST_VAAPI_OBJECT_ID(texture) = 0;
+    }
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+}
+
+static gboolean
+gst_vaapi_texture_create(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate * const priv = texture->priv;
+    GLuint texture_id;
+    VAStatus status;
+
+    if (priv->foreign_texture)
+        texture_id = GST_VAAPI_OBJECT_ID(texture);
+    else {
+        GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+        texture_id = gl_create_texture(
+            priv->target,
+            priv->format,
+            priv->width,
+            priv->height
+        );
+        GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+        if (!texture_id)
+            return FALSE;
+        GST_VAAPI_OBJECT_ID(texture) = texture_id;
+    }
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    status = vaCreateSurfaceGLX(
+        GST_VAAPI_OBJECT_VADISPLAY(texture),
+        priv->target,
+        texture_id,
+        &priv->gl_surface
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+    if (!vaapi_check_status(status, "vaCreateSurfaceGLX()"))
+        return FALSE;
+    return TRUE;
+}
+
+static void
+gst_vaapi_texture_finalize(GObject *object)
+{
+    gst_vaapi_texture_destroy(GST_VAAPI_TEXTURE(object));
+
+    G_OBJECT_CLASS(gst_vaapi_texture_parent_class)->finalize(object);
+}
+
+static void
+gst_vaapi_texture_constructed(GObject *object)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+    GObjectClass *parent_class;
+
+    texture->priv->foreign_texture = GST_VAAPI_OBJECT_ID(texture) != 0;
+    texture->priv->is_constructed  = gst_vaapi_texture_create(texture);
+
+    parent_class = G_OBJECT_CLASS(gst_vaapi_texture_parent_class);
+    if (parent_class->constructed)
+        parent_class->constructed(object);
+}
+
+static void
+gst_vaapi_texture_set_property(
+    GObject      *object,
+    guint         prop_id,
+    const GValue *value,
+    GParamSpec   *pspec
+)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        texture->priv->target = g_value_get_uint(value);
+        break;
+    case PROP_FORMAT:
+        texture->priv->format = g_value_get_uint(value);
+        break;
+    case PROP_WIDTH:
+        texture->priv->width = g_value_get_uint(value);
+        break;
+    case PROP_HEIGHT:
+        texture->priv->height = g_value_get_uint(value);
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_texture_get_property(
+    GObject    *object,
+    guint       prop_id,
+    GValue     *value,
+    GParamSpec *pspec
+)
+{
+    GstVaapiTexture * const texture = GST_VAAPI_TEXTURE(object);
+
+    switch (prop_id) {
+    case PROP_TARGET:
+        g_value_set_uint(value, gst_vaapi_texture_get_target(texture));
+        break;
+    case PROP_FORMAT:
+        g_value_set_uint(value, gst_vaapi_texture_get_format(texture));
+        break;
+    case PROP_WIDTH:
+        g_value_set_uint(value, gst_vaapi_texture_get_width(texture));
+        break;
+    case PROP_HEIGHT:
+        g_value_set_uint(value, gst_vaapi_texture_get_height(texture));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+        break;
+    }
+}
+
+static void
+gst_vaapi_texture_class_init(GstVaapiTextureClass *klass)
+{
+    GObjectClass * const object_class = G_OBJECT_CLASS(klass);
+
+    g_type_class_add_private(klass, sizeof(GstVaapiTexturePrivate));
+
+    object_class->finalize     = gst_vaapi_texture_finalize;
+    object_class->set_property = gst_vaapi_texture_set_property;
+    object_class->get_property = gst_vaapi_texture_get_property;
+    object_class->constructed  = gst_vaapi_texture_constructed;
+
+    g_object_class_install_property
+        (object_class,
+         PROP_TARGET,
+         g_param_spec_uint("target",
+                           "Target",
+                           "The texture target",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_FORMAT,
+         g_param_spec_uint("format",
+                           "Format",
+                           "The texture format",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_WIDTH,
+         g_param_spec_uint("width",
+                           "width",
+                           "The texture width",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+        (object_class,
+         PROP_HEIGHT,
+         g_param_spec_uint("height",
+                           "height",
+                           "The texture height",
+                           0, G_MAXUINT32, 0,
+                           G_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+gst_vaapi_texture_init(GstVaapiTexture *texture)
+{
+    GstVaapiTexturePrivate *priv = GST_VAAPI_TEXTURE_GET_PRIVATE(texture);
+
+    texture->priv               = priv;
+    priv->target                = GL_NONE;
+    priv->format                = GL_NONE;
+    priv->width                 = 0;
+    priv->height                = 0;
+    priv->gl_surface            = NULL;
+    priv->foreign_texture       = FALSE;
+    priv->is_constructed        = FALSE;
+}
+
+GstVaapiTexture *
+gst_vaapi_texture_new(
+    GstVaapiDisplay *display,
+    GLenum           target,
+    GLenum           format,
+    guint            width,
+    guint            height
+)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    return g_object_new(GST_VAAPI_TYPE_TEXTURE,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(0),
+                        "target",  target,
+                        "format",  format,
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+GstVaapiTexture *
+gst_vaapi_texture_new_with_texture(
+    GstVaapiDisplay *display,
+    GLuint           texture,
+    GLenum           target,
+    GLenum           format
+)
+{
+    guint width, height, border_width;
+
+    g_return_val_if_fail(GST_VAAPI_IS_DISPLAY(display), NULL);
+
+    /* Check texture dimensions */
+    if (!gl_get_texture_param(GL_TEXTURE_WIDTH, &width))
+        return NULL;
+    if (!gl_get_texture_param(GL_TEXTURE_HEIGHT, &height))
+        return NULL;
+    if (!gl_get_texture_param(GL_TEXTURE_BORDER, &border_width))
+        return NULL;
+
+    width  -= 2 * border_width;
+    height -= 2 * border_width;
+    if (width == 0 || height == 0)
+        return NULL;
+
+    return g_object_new(GST_VAAPI_TYPE_TEXTURE,
+                        "display", display,
+                        "id",      GST_VAAPI_ID(texture),
+                        "target",  target,
+                        "format",  format,
+                        "width",   width,
+                        "height",  height,
+                        NULL);
+}
+
+/**
+ * gst_vaapi_texture_get_id:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the underlying texture id of the @texture.
+ *
+ * Return value: the underlying texture id of the @texture
+ */
+GLuint
+gst_vaapi_texture_get_id(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+
+    return GST_VAAPI_OBJECT_ID(texture);
+}
+
+/**
+ * gst_vaapi_texture_get_target:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture target type
+ *
+ * Return value: the texture target
+ */
+GLenum
+gst_vaapi_texture_get_target(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), GL_NONE);
+    g_return_val_if_fail(texture->priv->is_constructed, GL_NONE);
+
+    return texture->priv->target;
+}
+
+/**
+ * gst_vaapi_texture_get_format
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture format
+ *
+ * Return value: the texture format
+ */
+GLenum
+gst_vaapi_texture_get_format(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), GL_NONE);
+    g_return_val_if_fail(texture->priv->is_constructed, GL_NONE);
+
+    return texture->priv->format;
+}
+
+/**
+ * gst_vaapi_texture_get_width:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture width.
+ *
+ * Return value: the texture width, in pixels
+ */
+guint
+gst_vaapi_texture_get_width(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+    g_return_val_if_fail(texture->priv->is_constructed, 0);
+
+    return texture->priv->width;
+}
+
+/**
+ * gst_vaapi_texture_get_height:
+ * @texture: a #GstVaapiTexture
+ *
+ * Returns the @texture height.
+ *
+ * Return value: the texture height, in pixels.
+ */
+guint
+gst_vaapi_texture_get_height(GstVaapiTexture *texture)
+{
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), 0);
+    g_return_val_if_fail(texture->priv->is_constructed, 0);
+
+    return texture->priv->height;
+}
+
+/**
+ * gst_vaapi_texture_get_size:
+ * @texture: a #GstVaapiTexture
+ * @pwidth: return location for the width, or %NULL
+ * @pheight: return location for the height, or %NULL
+ *
+ * Retrieves the dimensions of a #GstVaapiTexture.
+ */
+void
+gst_vaapi_texture_get_size(
+    GstVaapiTexture *texture,
+    guint           *pwidth,
+    guint           *pheight
+)
+{
+    g_return_if_fail(GST_VAAPI_IS_TEXTURE(texture));
+    g_return_if_fail(texture->priv->is_constructed);
+
+    if (pwidth)
+        *pwidth = texture->priv->width;
+
+    if (pheight)
+        *pheight = texture->priv->height;
+}
+
+/**
+ * gst_vaapi_window_put_texture:
+ * @texture: a #GstVaapiTexture
+ * @surface: a #GstVaapiSurface
+ * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags
+ *
+ * Renders the @surface into the àtexture. The @flags specify how
+ * de-interlacing (if needed), color space conversion, scaling and
+ * other postprocessing transformations are performed.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gst_vaapi_texture_put_surface(
+    GstVaapiTexture *texture,
+    GstVaapiSurface *surface,
+    guint            flags
+)
+{
+    VAStatus status;
+
+    g_return_val_if_fail(GST_VAAPI_IS_TEXTURE(texture), FALSE);
+    g_return_val_if_fail(texture->priv->is_constructed, FALSE);
+    g_return_val_if_fail(GST_VAAPI_IS_SURFACE(surface), FALSE);
+
+    GST_VAAPI_OBJECT_LOCK_DISPLAY(texture);
+    status = vaCopySurfaceGLX(
+        GST_VAAPI_OBJECT_VADISPLAY(texture),
+        texture->priv->gl_surface,
+        GST_VAAPI_OBJECT_ID(surface),
+        get_PutSurface_flags_from_GstVaapiSurfaceRenderFlags(flags)
+    );
+    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(texture);
+
+    if (!vaapi_check_status(status, "vaCopySurfaceGLX()"))
+        return FALSE;
+    return TRUE;
+}
diff --git a/gst-libs/gst/vaapi/gstvaapitexture.h b/gst-libs/gst/vaapi/gstvaapitexture.h
new file mode 100644 (file)
index 0000000..5620cce
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ *  gstvaapitexture.h - VA texture abstraction
+ *
+ *  gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef GST_VAAPI_TEXTURE_H
+#define GST_VAAPI_TEXTURE_H
+
+#include <GL/gl.h>
+#include <gst/vaapi/gstvaapitypes.h>
+#include <gst/vaapi/gstvaapiobject.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+#include <gst/vaapi/gstvaapisurface.h>
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_TYPE_TEXTURE \
+    (gst_vaapi_texture_get_type())
+
+#define GST_VAAPI_TEXTURE(obj)                          \
+    (G_TYPE_CHECK_INSTANCE_CAST((obj),                  \
+                                GST_VAAPI_TYPE_TEXTURE, \
+                                GstVaapiTexture))
+
+#define GST_VAAPI_TEXTURE_CLASS(klass)                  \
+    (G_TYPE_CHECK_CLASS_CAST((klass),                   \
+                             GST_VAAPI_TYPE_TEXTURE,    \
+                             GstVaapiTextureClass))
+
+#define GST_VAAPI_IS_TEXTURE(obj) \
+    (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_VAAPI_TYPE_TEXTURE))
+
+#define GST_VAAPI_IS_TEXTURE_CLASS(klass) \
+    (G_TYPE_CHECK_CLASS_TYPE((klass), GST_VAAPI_TYPE_TEXTURE))
+
+#define GST_VAAPI_TEXTURE_GET_CLASS(obj)                \
+    (G_TYPE_INSTANCE_GET_CLASS((obj),                   \
+                               GST_VAAPI_TYPE_TEXTURE,  \
+                               GstVaapiTextureClass))
+
+typedef struct _GstVaapiTexture                 GstVaapiTexture;
+typedef struct _GstVaapiTexturePrivate          GstVaapiTexturePrivate;
+typedef struct _GstVaapiTextureClass            GstVaapiTextureClass;
+
+/**
+ * GstVaapiTexture:
+ *
+ * Base class for system-dependent textures.
+ */
+struct _GstVaapiTexture {
+    /*< private >*/
+    GstVaapiObject parent_instance;
+
+    GstVaapiTexturePrivate *priv;
+};
+
+/**
+ * GstVaapiTextureClass:
+ *
+ * Base class for system-dependent textures.
+ */
+struct _GstVaapiTextureClass {
+    /*< private >*/
+    GstVaapiObjectClass parent_class;
+};
+
+GType
+gst_vaapi_texture_get_type(void);
+
+GstVaapiTexture *
+gst_vaapi_texture_new(
+    GstVaapiDisplay *display,
+    GLenum           target,
+    GLenum           format,
+    guint            width,
+    guint            height
+);
+
+GstVaapiTexture *
+gst_vaapi_texture_new_with_texture(
+    GstVaapiDisplay *display,
+    GLuint           texture,
+    GLenum           target,
+    GLenum           format
+);
+
+GLuint
+gst_vaapi_texture_get_id(GstVaapiTexture *texture);
+
+GLenum
+gst_vaapi_texture_get_target(GstVaapiTexture *texture);
+
+GLenum
+gst_vaapi_texture_get_format(GstVaapiTexture *texture);
+
+guint
+gst_vaapi_texture_get_width(GstVaapiTexture *texture);
+
+guint
+gst_vaapi_texture_get_height(GstVaapiTexture *texture);
+
+void
+gst_vaapi_texture_get_size(
+    GstVaapiTexture *texture,
+    guint           *pwidth,
+    guint           *pheight
+);
+
+gboolean
+gst_vaapi_texture_put_surface(
+    GstVaapiTexture *texture,
+    GstVaapiSurface *surface,
+    guint            flags
+);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_TEXTURE_H */
index 61721fb..9669ab2 100644 (file)
@@ -209,3 +209,129 @@ gl_make_current(Display *dpy, Window win, GLXContext ctx, GLContextState *state)
     }
     return glXMakeCurrent(dpy, win, ctx);
 }
+
+/**
+ * gl_bind_texture:
+ * @ts: a #GLTextureState
+ * @target: the target to which the texture is bound
+ * @texture: the name of a texture
+ *
+ * Binds @texture to the specified @target, while recording the
+ * previous state in @ts.
+ *
+ * Return value: %TRUE on success
+ */
+gboolean
+gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture)
+{
+    ts->target      = target;
+    ts->old_texture = 0;
+    ts->was_bound   = 0;
+    ts->was_enabled = glIsEnabled(target);
+    if (!ts->was_enabled)
+        glEnable(target);
+
+    GLenum texture_binding;
+    switch (target) {
+    case GL_TEXTURE_1D:
+        texture_binding = GL_TEXTURE_BINDING_1D;
+        break;
+    case GL_TEXTURE_2D:
+        texture_binding = GL_TEXTURE_BINDING_2D;
+        break;
+    case GL_TEXTURE_3D:
+        texture_binding = GL_TEXTURE_BINDING_3D;
+        break;
+    case GL_TEXTURE_RECTANGLE_ARB:
+        texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
+        break;
+    default:
+        g_assert(!texture);
+        return FALSE;
+    }
+
+    if (ts->was_enabled && gl_get_param(texture_binding, &ts->old_texture) < 0)
+        return FALSE;
+
+    ts->was_bound = texture == ts->old_texture;
+    if (!ts->was_bound) {
+        gl_purge_errors();
+        glBindTexture(target, texture);
+        if (gl_check_error())
+            return FALSE;
+    }
+    return TRUE;
+}
+
+/**
+ * gl_unbind_texture:
+ * @ts: a #GLTextureState
+ *
+ * Rebinds the texture that was previously bound and recorded in @ts.
+ */
+void
+gl_unbind_texture(GLTextureState *ts)
+{
+    if (!ts->was_bound && ts->old_texture)
+        glBindTexture(ts->target, ts->old_texture);
+    if (!ts->was_enabled)
+        glDisable(ts->target);
+}
+
+/**
+ * gl_create_texture:
+ * @target: the target to which the texture is bound
+ * @format: the format of the pixel data
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Creates a texture with the specified dimensions and @format. The
+ * internal format will be automatically derived from @format.
+ *
+ * Return value: the newly created texture name
+ */
+GLuint
+gl_create_texture(GLenum target, GLenum format, guint width, guint height)
+{
+    GLuint texture;
+    GLTextureState ts;
+    guint bytes_per_component;
+
+    switch (format) {
+    case GL_LUMINANCE:
+        bytes_per_component = 1;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        bytes_per_component = 2;
+        break;
+    case GL_RGBA:
+    case GL_BGRA:
+        bytes_per_component = 4;
+        break;
+    default:
+        bytes_per_component = 0;
+        break;
+    }
+    g_assert(bytes_per_component > 0);
+
+    glGenTextures(1, &texture);
+    if (!gl_bind_texture(&ts, target, texture))
+        return 0;
+    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_component);
+    glTexImage2D(
+        target,
+        0,
+        bytes_per_component,
+        width, height,
+        0,
+        format,
+        GL_UNSIGNED_BYTE,
+        NULL
+    );
+    gl_unbind_texture(&ts);
+    return texture;
+}
index 7251e22..ca88b60 100644 (file)
@@ -64,4 +64,24 @@ gboolean
 gl_make_current(Display *dpy, Window win, GLXContext ctx, GLContextState *state)
     attribute_hidden;
 
+typedef struct _GLTextureState GLTextureState;
+struct _GLTextureState {
+    gboolean    was_enabled;
+    gboolean    was_bound;
+    GLenum      target;
+    GLuint      old_texture;
+};
+
+gboolean
+gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture)
+    attribute_hidden;
+
+void
+gl_unbind_texture(GLTextureState *ts)
+    attribute_hidden;
+
+GLuint
+gl_create_texture(GLenum target, GLenum format, guint width, guint height)
+    attribute_hidden;
+
 #endif /* GST_VAAPI_UTILS_GLX_H */