libs: texture: Make texture a standard GstMiniObject.

We store GstVaapiTextureGLX and GstVaapiTextureEGL's private data in
the qdata of miniobject and avoid extending the base texture class.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/-/merge_requests/317>
This commit is contained in:
He Junyan 2020-04-18 19:32:24 +08:00 committed by Víctor Manuel Jáquez Leal
parent 808247a963
commit f20bd8bfd1
9 changed files with 353 additions and 318 deletions

View file

@ -38,51 +38,80 @@
(GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED | \ (GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED | \
GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED) GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED)
#define GST_VAAPI_TEXTURE_PRIVATE_QUARK gst_vaapi_texture_private_quark ()
static GQuark
gst_vaapi_texture_private_quark (void)
{
static gsize g_quark;
if (g_once_init_enter (&g_quark)) {
gsize quark = (gsize) g_quark_from_static_string ("GstVaapiTexturePrivate");
g_once_init_leave (&g_quark, quark);
}
return g_quark;
}
gpointer
gst_vaapi_texture_get_private (GstVaapiTexture * texture)
{
return gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (texture),
GST_VAAPI_TEXTURE_PRIVATE_QUARK);
}
void
gst_vaapi_texture_set_private (GstVaapiTexture * texture, gpointer priv,
GDestroyNotify destroy)
{
gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (texture),
GST_VAAPI_TEXTURE_PRIVATE_QUARK, (gpointer) priv, destroy);
}
static void static void
gst_vaapi_texture_init (GstVaapiTexture * texture, GstVaapiID id, gst_vaapi_texture_init (GstVaapiTexture * texture, GstVaapiID id,
guint target, guint format, guint width, guint height) guint target, guint format, guint width, guint height)
{ {
texture->is_wrapped = id != GST_VAAPI_ID_INVALID; texture->is_wrapped = id != GST_VAAPI_ID_INVALID;
GST_VAAPI_OBJECT_ID (texture) = texture->is_wrapped ? id : 0; GST_VAAPI_TEXTURE_ID (texture) = texture->is_wrapped ? id : 0;
texture->gl_target = target; texture->gl_target = target;
texture->gl_format = format; texture->gl_format = format;
texture->width = width; texture->width = width;
texture->height = height; texture->height = height;
} }
static inline gboolean static void
gst_vaapi_texture_allocate (GstVaapiTexture * texture) gst_vaapi_texture_free (GstVaapiTexture * texture)
{ {
return GST_VAAPI_TEXTURE_GET_CLASS (texture)->allocate (texture); gst_vaapi_display_replace (&GST_VAAPI_TEXTURE_DISPLAY (texture), NULL);
g_slice_free1 (sizeof (GstVaapiTexture), texture);
} }
GST_DEFINE_MINI_OBJECT_TYPE (GstVaapiTexture, gst_vaapi_texture);
GstVaapiTexture * GstVaapiTexture *
gst_vaapi_texture_new_internal (const GstVaapiTextureClass * klass, gst_vaapi_texture_new_internal (GstVaapiDisplay * display, GstVaapiID id,
GstVaapiDisplay * display, GstVaapiID id, guint target, guint format, guint target, guint format, guint width, guint height)
guint width, guint height)
{ {
GstVaapiTexture *texture; GstVaapiTexture *texture;
g_return_val_if_fail (display, NULL);
g_return_val_if_fail (target != 0, NULL); g_return_val_if_fail (target != 0, NULL);
g_return_val_if_fail (format != 0, NULL); g_return_val_if_fail (format != 0, NULL);
g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL); g_return_val_if_fail (height > 0, NULL);
texture = gst_vaapi_object_new (GST_VAAPI_OBJECT_CLASS (klass), display); texture = g_slice_alloc (sizeof (GstVaapiTexture));
if (!texture) if (!texture)
return NULL; return NULL;
gst_vaapi_texture_init (texture, id, target, format, width, height); gst_mini_object_init (GST_MINI_OBJECT_CAST (texture), 0,
if (!gst_vaapi_texture_allocate (texture)) GST_TYPE_VAAPI_TEXTURE, NULL, NULL,
goto error; (GstMiniObjectFreeFunction) gst_vaapi_texture_free);
return texture;
/* ERRORS */ GST_VAAPI_TEXTURE_DISPLAY (texture) = gst_object_ref (display);
error:
{ gst_vaapi_texture_init (texture, id, target, format, width, height);
gst_vaapi_object_unref (texture);
return NULL; return texture;
}
} }
/** /**
@ -155,50 +184,6 @@ gst_vaapi_texture_new_wrapped (GstVaapiDisplay * display, guint id,
return dpy_class->create_texture (display, id, target, format, width, height); return dpy_class->create_texture (display, id, target, format, width, height);
} }
/**
* gst_vaapi_texture_ref:
* @texture: a #GstVaapiTexture
*
* Atomically increases the reference count of the given @texture by one.
*
* Returns: The same @texture argument
*/
GstVaapiTexture *
gst_vaapi_texture_ref (GstVaapiTexture * texture)
{
return gst_vaapi_object_ref (GST_VAAPI_OBJECT (texture));
}
/**
* gst_vaapi_texture_unref:
* @texture: a #GstVaapiTexture
*
* Atomically decreases the reference count of the @texture by one. If
* the reference count reaches zero, the texture will be free'd.
*/
void
gst_vaapi_texture_unref (GstVaapiTexture * texture)
{
gst_vaapi_object_unref (GST_VAAPI_OBJECT (texture));
}
/**
* gst_vaapi_texture_replace:
* @old_texture_ptr: a pointer to a #GstVaapiTexture
* @new_texture: a #GstVaapiTexture
*
* Atomically replaces the texture texture held in @old_texture_ptr
* with @new_texture. This means that @old_texture_ptr shall reference
* a valid texture. However, @new_texture can be NULL.
*/
void
gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr,
GstVaapiTexture * new_texture)
{
gst_vaapi_object_replace ((GstVaapiObject **) (old_texture_ptr),
GST_VAAPI_OBJECT (new_texture));
}
/** /**
* gst_vaapi_texture_get_id: * gst_vaapi_texture_get_id:
* @texture: a #GstVaapiTexture * @texture: a #GstVaapiTexture
@ -300,6 +285,21 @@ gst_vaapi_texture_get_size (GstVaapiTexture * texture,
*height_ptr = GST_VAAPI_TEXTURE_HEIGHT (texture); *height_ptr = GST_VAAPI_TEXTURE_HEIGHT (texture);
} }
/**
* gst_vaapi_texture_get_display:
* @texture: a #GstVaapiTexture
*
* Returns the #GstVaapiDisplay this @texture is bound to.
*
* Return value: the parent #GstVaapiDisplay object
*/
GstVaapiDisplay *
gst_vaapi_texture_get_display (GstVaapiTexture * texture)
{
g_return_val_if_fail (texture != NULL, NULL);
return GST_VAAPI_TEXTURE_DISPLAY (texture);
}
/** /**
* gst_vaapi_texture_get_orientation_flags: * gst_vaapi_texture_get_orientation_flags:
* @texture: a #GstVaapiTexture * @texture: a #GstVaapiTexture
@ -313,8 +313,7 @@ gst_vaapi_texture_get_orientation_flags (GstVaapiTexture * texture)
{ {
g_return_val_if_fail (texture != NULL, 0); g_return_val_if_fail (texture != NULL, 0);
return GST_VAAPI_TEXTURE_FLAGS (texture) & return GST_MINI_OBJECT_FLAGS (texture) & GST_VAAPI_TEXTURE_ORIENTATION_FLAGS;
GST_VAAPI_TEXTURE_ORIENTATION_FLAGS;
} }
/** /**
@ -333,8 +332,8 @@ gst_vaapi_texture_set_orientation_flags (GstVaapiTexture * texture, guint flags)
g_return_if_fail (texture != NULL); g_return_if_fail (texture != NULL);
g_return_if_fail ((flags & ~GST_VAAPI_TEXTURE_ORIENTATION_FLAGS) == 0); g_return_if_fail ((flags & ~GST_VAAPI_TEXTURE_ORIENTATION_FLAGS) == 0);
GST_VAAPI_TEXTURE_FLAG_UNSET (texture, GST_VAAPI_TEXTURE_ORIENTATION_FLAGS); GST_MINI_OBJECT_FLAG_UNSET (texture, GST_VAAPI_TEXTURE_ORIENTATION_FLAGS);
GST_VAAPI_TEXTURE_FLAG_SET (texture, flags); GST_MINI_OBJECT_FLAG_SET (texture, flags);
} }
/** /**
@ -343,7 +342,7 @@ gst_vaapi_texture_set_orientation_flags (GstVaapiTexture * texture, guint flags)
* @surface: a #GstVaapiSurface * @surface: a #GstVaapiSurface
* @flags: postprocessing flags. See #GstVaapiTextureRenderFlags * @flags: postprocessing flags. See #GstVaapiTextureRenderFlags
* *
* Renders the @surface into the àtexture. The @flags specify how * Renders the @surface into the @texture. The @flags specify how
* de-interlacing (if needed), color space conversion, scaling and * de-interlacing (if needed), color space conversion, scaling and
* other postprocessing transformations are performed. * other postprocessing transformations are performed.
* *
@ -353,14 +352,12 @@ gboolean
gst_vaapi_texture_put_surface (GstVaapiTexture * texture, gst_vaapi_texture_put_surface (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
{ {
const GstVaapiTextureClass *klass;
GstVaapiRectangle rect; GstVaapiRectangle rect;
g_return_val_if_fail (texture != NULL, FALSE); g_return_val_if_fail (texture != NULL, FALSE);
g_return_val_if_fail (surface != NULL, FALSE); g_return_val_if_fail (surface != NULL, FALSE);
klass = GST_VAAPI_TEXTURE_GET_CLASS (texture); if (!texture->put_surface)
if (!klass)
return FALSE; return FALSE;
if (!crop_rect) { if (!crop_rect) {
@ -369,5 +366,5 @@ gst_vaapi_texture_put_surface (GstVaapiTexture * texture,
gst_vaapi_surface_get_size (surface, &rect.width, &rect.height); gst_vaapi_surface_get_size (surface, &rect.width, &rect.height);
crop_rect = &rect; crop_rect = &rect;
} }
return klass->put_surface (texture, surface, crop_rect, flags); return texture->put_surface (texture, surface, crop_rect, flags);
} }

View file

@ -33,6 +33,17 @@ G_BEGIN_DECLS
#define GST_VAAPI_TEXTURE(obj) \ #define GST_VAAPI_TEXTURE(obj) \
((GstVaapiTexture *)(obj)) ((GstVaapiTexture *)(obj))
#define GST_TYPE_VAAPI_TEXTURE (gst_vaapi_texture_get_type ())
/**
* GST_VAAPI_TEXTURE_DISPLAY:
* @texture: a #GstVaapiTexture
*
* Macro that evaluates to the display associated with the @texture
*/
#define GST_VAAPI_TEXTURE_DISPLAY(texture) \
gst_vaapi_texture_get_display (GST_VAAPI_TEXTURE (texture))
/** /**
* GST_VAAPI_TEXTURE_ID: * GST_VAAPI_TEXTURE_ID:
* @texture: a #GstVaapiTexture * @texture: a #GstVaapiTexture
@ -94,10 +105,26 @@ typedef struct _GstVaapiTexture GstVaapiTexture;
* from the left to the right. * from the left to the right.
*/ */
typedef enum { typedef enum {
GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED = 1 << 31, GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED = (GST_MINI_OBJECT_FLAG_LAST << 1),
GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED = 1 << 30, GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED = (GST_MINI_OBJECT_FLAG_LAST << 2),
} GstVaapiTextureOrientationFlags; } GstVaapiTextureOrientationFlags;
GType
gst_vaapi_texture_get_type (void) G_GNUC_CONST;
/**
* gst_vaapi_texture_unref: (skip)
* @texture: (transfer full): a #GstVaapiTexture.
*
* Decreases the refcount of the texture. If the refcount reaches 0, the
* texture will be freed.
*/
static inline void
gst_vaapi_texture_unref (GstVaapiTexture * texture)
{
gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
}
GstVaapiTexture * GstVaapiTexture *
gst_vaapi_texture_new (GstVaapiDisplay * display, guint target, guint format, gst_vaapi_texture_new (GstVaapiDisplay * display, guint target, guint format,
guint width, guint height); guint width, guint height);
@ -106,19 +133,12 @@ GstVaapiTexture *
gst_vaapi_texture_new_wrapped (GstVaapiDisplay * display, guint id, gst_vaapi_texture_new_wrapped (GstVaapiDisplay * display, guint id,
guint target, guint format, guint width, guint height); guint target, guint format, guint width, guint height);
GstVaapiTexture *
gst_vaapi_texture_ref (GstVaapiTexture * texture);
void
gst_vaapi_texture_unref (GstVaapiTexture * texture);
void
gst_vaapi_texture_replace (GstVaapiTexture ** old_texture_ptr,
GstVaapiTexture * new_texture);
guint guint
gst_vaapi_texture_get_id (GstVaapiTexture * texture); gst_vaapi_texture_get_id (GstVaapiTexture * texture);
GstVaapiDisplay *
gst_vaapi_texture_get_display (GstVaapiTexture * texture);
guint guint
gst_vaapi_texture_get_target (GstVaapiTexture * texture); gst_vaapi_texture_get_target (GstVaapiTexture * texture);
@ -147,6 +167,8 @@ gst_vaapi_texture_put_surface (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect,
guint flags); guint flags);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiTexture, gst_vaapi_texture_unref)
G_END_DECLS G_END_DECLS
#endif /* GST_VAAPI_TEXTURE_H */ #endif /* GST_VAAPI_TEXTURE_H */

View file

@ -40,48 +40,32 @@
#define DEBUG 1 #define DEBUG 1
#include "gstvaapidebug.h" #include "gstvaapidebug.h"
#define GST_VAAPI_TEXTURE_EGL(texture) \ typedef struct _GstVaapiTextureEGLPrivate GstVaapiTextureEGLPrivate;
((GstVaapiTextureEGL *) (texture))
typedef struct _GstVaapiTextureEGL GstVaapiTextureEGL;
typedef struct _GstVaapiTextureEGLClass GstVaapiTextureEGLClass;
/** /**
* GstVaapiTextureEGL: * GstVaapiTextureEGLPrivate:
* *
* Base object for EGL texture wrapper. * EGL texture specific fields.
*/ */
struct _GstVaapiTextureEGL struct _GstVaapiTextureEGLPrivate
{ {
/*< private > */ /*< private > */
GstVaapiTexture parent_instance; GstVaapiTexture *texture;
EglContext *egl_context; EglContext *egl_context;
EGLImageKHR egl_image; EGLImageKHR egl_image;
GstVaapiSurface *surface; GstVaapiSurface *surface;
GstVaapiFilter *filter; GstVaapiFilter *filter;
}; };
/**
* GstVaapiTextureEGLClass:
*
* Base class for EGL texture wrapper.
*/
struct _GstVaapiTextureEGLClass
{
/*< private > */
GstVaapiTextureClass parent_class;
};
typedef struct typedef struct
{ {
GstVaapiTextureEGL *texture; GstVaapiTexture *texture;
gboolean success; /* result */ gboolean success; /* result */
} CreateTextureArgs; } CreateTextureArgs;
typedef struct typedef struct
{ {
GstVaapiTextureEGL *texture; GstVaapiTexture *texture;
GstVaapiSurface *surface; GstVaapiSurface *surface;
const GstVaapiRectangle *crop_rect; const GstVaapiRectangle *crop_rect;
guint flags; guint flags;
@ -89,32 +73,31 @@ typedef struct
} UploadSurfaceArgs; } UploadSurfaceArgs;
static gboolean static gboolean
create_objects (GstVaapiTextureEGL * texture, GLuint texture_id) create_objects (GstVaapiTexture * texture, GLuint texture_id)
{ {
GstVaapiTexture *const base_texture = GST_VAAPI_TEXTURE (texture); GstVaapiTextureEGLPrivate *const texture_egl =
EglContext *const ctx = texture->egl_context; gst_vaapi_texture_get_private (texture);
EglContext *const ctx = texture_egl->egl_context;
EglVTable *const vtable = egl_context_get_vtable (ctx, FALSE); EglVTable *const vtable = egl_context_get_vtable (ctx, FALSE);
GLint attribs[3], *attrib; GLint attribs[3] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
attrib = attribs; texture_egl->egl_image =
*attrib++ = EGL_IMAGE_PRESERVED_KHR; vtable->eglCreateImageKHR (ctx->display->base.handle.p,
*attrib++ = EGL_TRUE;
*attrib++ = EGL_NONE;
texture->egl_image = vtable->eglCreateImageKHR (ctx->display->base.handle.p,
ctx->base.handle.p, EGL_GL_TEXTURE_2D_KHR, ctx->base.handle.p, EGL_GL_TEXTURE_2D_KHR,
(EGLClientBuffer) GSIZE_TO_POINTER (texture_id), attribs); (EGLClientBuffer) GSIZE_TO_POINTER (texture_id), attribs);
if (!texture->egl_image) if (!texture_egl->egl_image)
goto error_create_image; goto error_create_image;
texture->surface = texture_egl->surface =
gst_vaapi_surface_new_with_egl_image (GST_VAAPI_OBJECT_DISPLAY (texture), gst_vaapi_surface_new_with_egl_image (GST_VAAPI_TEXTURE_DISPLAY (texture),
texture->egl_image, GST_VIDEO_FORMAT_RGBA, base_texture->width, texture_egl->egl_image, GST_VIDEO_FORMAT_RGBA, texture->width,
base_texture->height); texture->height);
if (!texture->surface) if (!texture_egl->surface)
goto error_create_surface; goto error_create_surface;
texture->filter = gst_vaapi_filter_new (GST_VAAPI_OBJECT_DISPLAY (texture)); texture_egl->filter =
if (!texture->filter) gst_vaapi_filter_new (GST_VAAPI_TEXTURE_DISPLAY (texture));
if (!texture_egl->filter)
goto error_create_filter; goto error_create_filter;
return TRUE; return TRUE;
@ -137,17 +120,18 @@ error_create_filter:
} }
static gboolean static gboolean
do_create_texture_unlocked (GstVaapiTextureEGL * texture) do_create_texture_unlocked (GstVaapiTexture * texture)
{ {
GstVaapiTexture *const base_texture = GST_VAAPI_TEXTURE (texture);
GLuint texture_id; GLuint texture_id;
GstVaapiTextureEGLPrivate *texture_egl =
gst_vaapi_texture_get_private (texture);
if (base_texture->is_wrapped) if (texture->is_wrapped)
texture_id = GST_VAAPI_TEXTURE_ID (texture); texture_id = GST_VAAPI_TEXTURE_ID (texture);
else { else {
texture_id = egl_create_texture (texture->egl_context, texture_id = egl_create_texture (texture_egl->egl_context,
base_texture->gl_target, base_texture->gl_format, texture->gl_target, texture->gl_format,
base_texture->width, base_texture->height); texture->width, texture->height);
if (!texture_id) if (!texture_id)
return FALSE; return FALSE;
GST_VAAPI_TEXTURE_ID (texture) = texture_id; GST_VAAPI_TEXTURE_ID (texture) = texture_id;
@ -158,74 +142,78 @@ do_create_texture_unlocked (GstVaapiTextureEGL * texture)
static void static void
do_create_texture (CreateTextureArgs * args) do_create_texture (CreateTextureArgs * args)
{ {
GstVaapiTextureEGL *const texture = args->texture; GstVaapiTexture *const texture = args->texture;
GstVaapiTextureEGLPrivate *texture_egl =
gst_vaapi_texture_get_private (texture);
EglContextState old_cs; EglContextState old_cs;
args->success = FALSE; args->success = FALSE;
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
if (egl_context_set_current (texture->egl_context, TRUE, &old_cs)) { if (egl_context_set_current (texture_egl->egl_context, TRUE, &old_cs)) {
args->success = do_create_texture_unlocked (texture); args->success = do_create_texture_unlocked (texture);
egl_context_set_current (texture->egl_context, FALSE, &old_cs); egl_context_set_current (texture_egl->egl_context, FALSE, &old_cs);
} }
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
} }
static void static void
destroy_objects (GstVaapiTextureEGL * texture) destroy_objects (GstVaapiTextureEGLPrivate * texture_egl)
{ {
EglContext *const ctx = texture->egl_context; EglContext *const ctx = texture_egl->egl_context;
EglVTable *const vtable = egl_context_get_vtable (ctx, FALSE); EglVTable *const vtable = egl_context_get_vtable (ctx, FALSE);
if (texture->egl_image != EGL_NO_IMAGE_KHR) { if (texture_egl->egl_image != EGL_NO_IMAGE_KHR) {
vtable->eglDestroyImageKHR (ctx->display->base.handle.p, vtable->eglDestroyImageKHR (ctx->display->base.handle.p,
texture->egl_image); texture_egl->egl_image);
texture->egl_image = EGL_NO_IMAGE_KHR; texture_egl->egl_image = EGL_NO_IMAGE_KHR;
} }
gst_mini_object_replace ((GstMiniObject **) & texture->surface, NULL); gst_mini_object_replace ((GstMiniObject **) & texture_egl->surface, NULL);
gst_vaapi_filter_replace (&texture->filter, NULL); gst_vaapi_filter_replace (&texture_egl->filter, NULL);
} }
static void static void
do_destroy_texture_unlocked (GstVaapiTextureEGL * texture) do_destroy_texture_unlocked (GstVaapiTextureEGLPrivate * texture_egl)
{ {
GstVaapiTexture *const base_texture = GST_VAAPI_TEXTURE (texture); GstVaapiTexture *const base_texture = texture_egl->texture;
const GLuint texture_id = GST_VAAPI_TEXTURE_ID (texture); const GLuint texture_id = GST_VAAPI_TEXTURE_ID (base_texture);
destroy_objects (texture); destroy_objects (texture_egl);
if (texture_id) { if (texture_id) {
if (!base_texture->is_wrapped) if (!base_texture->is_wrapped)
egl_destroy_texture (texture->egl_context, texture_id); egl_destroy_texture (texture_egl->egl_context, texture_id);
GST_VAAPI_TEXTURE_ID (texture) = 0; GST_VAAPI_TEXTURE_ID (base_texture) = 0;
} }
} }
static void static void
do_destroy_texture (GstVaapiTextureEGL * texture) do_destroy_texture (GstVaapiTextureEGLPrivate * texture_egl)
{ {
EglContextState old_cs; EglContextState old_cs;
GstVaapiTexture *texture = texture_egl->texture;
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
if (egl_context_set_current (texture->egl_context, TRUE, &old_cs)) { if (egl_context_set_current (texture_egl->egl_context, TRUE, &old_cs)) {
do_destroy_texture_unlocked (texture); do_destroy_texture_unlocked (texture_egl);
egl_context_set_current (texture->egl_context, FALSE, &old_cs); egl_context_set_current (texture_egl->egl_context, FALSE, &old_cs);
} }
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
egl_object_replace (&texture->egl_context, NULL); egl_object_replace (&texture_egl->egl_context, NULL);
g_free (texture_egl);
} }
static gboolean static gboolean
do_upload_surface_unlocked (GstVaapiTextureEGL * texture, do_upload_surface_unlocked (GstVaapiTextureEGLPrivate * texture_egl,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
{ {
GstVaapiFilterStatus status; GstVaapiFilterStatus status;
if (!gst_vaapi_filter_set_cropping_rectangle (texture->filter, crop_rect)) if (!gst_vaapi_filter_set_cropping_rectangle (texture_egl->filter, crop_rect))
return FALSE; return FALSE;
status = gst_vaapi_filter_process (texture->filter, surface, texture->surface, status = gst_vaapi_filter_process (texture_egl->filter, surface,
flags); texture_egl->surface, flags);
if (status != GST_VAAPI_FILTER_STATUS_SUCCESS) if (status != GST_VAAPI_FILTER_STATUS_SUCCESS)
return FALSE; return FALSE;
return TRUE; return TRUE;
@ -234,74 +222,86 @@ do_upload_surface_unlocked (GstVaapiTextureEGL * texture,
static void static void
do_upload_surface (UploadSurfaceArgs * args) do_upload_surface (UploadSurfaceArgs * args)
{ {
GstVaapiTextureEGL *const texture = args->texture; GstVaapiTexture *const texture = args->texture;
GstVaapiTextureEGLPrivate *texture_egl =
gst_vaapi_texture_get_private (texture);
EglContextState old_cs; EglContextState old_cs;
args->success = FALSE; args->success = FALSE;
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
if (egl_context_set_current (texture->egl_context, TRUE, &old_cs)) { if (egl_context_set_current (texture_egl->egl_context, TRUE, &old_cs)) {
args->success = do_upload_surface_unlocked (texture, args->surface, args->success = do_upload_surface_unlocked (texture_egl, args->surface,
args->crop_rect, args->flags); args->crop_rect, args->flags);
egl_context_set_current (texture->egl_context, FALSE, &old_cs); egl_context_set_current (texture_egl->egl_context, FALSE, &old_cs);
} }
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
} }
static gboolean static gboolean
gst_vaapi_texture_egl_create (GstVaapiTextureEGL * texture) gst_vaapi_texture_egl_create (GstVaapiTexture * texture)
{ {
CreateTextureArgs args = { texture }; CreateTextureArgs args = { texture };
GstVaapiDisplayEGL *display = GstVaapiDisplayEGL *display =
GST_VAAPI_DISPLAY_EGL (GST_VAAPI_OBJECT_DISPLAY (texture)); GST_VAAPI_DISPLAY_EGL (GST_VAAPI_TEXTURE_DISPLAY (texture));
GstVaapiTextureEGLPrivate *texture_egl =
gst_vaapi_texture_get_private (texture);
if (GST_VAAPI_TEXTURE (texture)->is_wrapped) { if (GST_VAAPI_TEXTURE (texture)->is_wrapped) {
if (!gst_vaapi_display_egl_set_current_display (display)) if (!gst_vaapi_display_egl_set_current_display (display))
return FALSE; return FALSE;
} }
egl_object_replace (&texture->egl_context, egl_object_replace (&texture_egl->egl_context,
GST_VAAPI_DISPLAY_EGL_CONTEXT (display)); GST_VAAPI_DISPLAY_EGL_CONTEXT (display));
return egl_context_run (texture->egl_context, return egl_context_run (texture_egl->egl_context,
(EglContextRunFunc) do_create_texture, &args) && args.success; (EglContextRunFunc) do_create_texture, &args) && args.success;
} }
static void static void
gst_vaapi_texture_egl_destroy (GstVaapiTextureEGL * texture) gst_vaapi_texture_egl_destroy (GstVaapiTextureEGLPrivate * texture_egl)
{ {
egl_context_run (texture->egl_context, egl_context_run (texture_egl->egl_context,
(EglContextRunFunc) do_destroy_texture, texture); (EglContextRunFunc) do_destroy_texture, texture_egl);
} }
static gboolean static gboolean
gst_vaapi_texture_egl_put_surface (GstVaapiTextureEGL * texture, gst_vaapi_texture_egl_put_surface (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
{ {
UploadSurfaceArgs args = { texture, surface, crop_rect, flags }; UploadSurfaceArgs args = { texture, surface, crop_rect, flags };
GstVaapiTextureEGLPrivate *texture_egl =
gst_vaapi_texture_get_private (texture);
return egl_context_run (texture->egl_context, return egl_context_run (texture_egl->egl_context,
(EglContextRunFunc) do_upload_surface, &args) && args.success; (EglContextRunFunc) do_upload_surface, &args) && args.success;
} }
static void static GstVaapiTexture *
gst_vaapi_texture_egl_class_init (GstVaapiTextureEGLClass * klass) gst_vaapi_texture_egl_new_internal (GstVaapiTexture * texture)
{ {
GstVaapiObjectClass *const object_class = GST_VAAPI_OBJECT_CLASS (klass); GstVaapiTextureEGLPrivate *texture_egl;
GstVaapiTextureClass *const texture_class = GST_VAAPI_TEXTURE_CLASS (klass);
object_class->finalize = (GstVaapiObjectFinalizeFunc) texture->put_surface = gst_vaapi_texture_egl_put_surface;
gst_vaapi_texture_egl_destroy;
texture_class->allocate = (GstVaapiTextureAllocateFunc) texture_egl = g_malloc0 (sizeof (GstVaapiTextureEGLPrivate));
gst_vaapi_texture_egl_create; if (!texture_egl) {
texture_class->put_surface = (GstVaapiTexturePutSurfaceFunc) gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
gst_vaapi_texture_egl_put_surface; return NULL;
}
texture_egl->texture = texture;
gst_vaapi_texture_set_private (texture, texture_egl,
(GDestroyNotify) gst_vaapi_texture_egl_destroy);
if (!gst_vaapi_texture_egl_create (texture)) {
gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
return NULL;
}
return texture;
} }
#define gst_vaapi_texture_egl_finalize gst_vaapi_texture_egl_destroy
GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE (GstVaapiTextureEGL,
gst_vaapi_texture_egl, gst_vaapi_texture_egl_class_init (&g_class));
/** /**
* gst_vaapi_texture_egl_new: * gst_vaapi_texture_egl_new:
* @display: a #GstVaapiDisplay * @display: a #GstVaapiDisplay
@ -325,11 +325,16 @@ GstVaapiTexture *
gst_vaapi_texture_egl_new (GstVaapiDisplay * display, guint target, gst_vaapi_texture_egl_new (GstVaapiDisplay * display, guint target,
guint format, guint width, guint height) guint format, guint width, guint height)
{ {
GstVaapiTexture *texture;
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), NULL); g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), NULL);
return gst_vaapi_texture_new_internal (GST_VAAPI_TEXTURE_CLASS texture = gst_vaapi_texture_new_internal (display, GST_VAAPI_ID_INVALID,
(gst_vaapi_texture_egl_class ()), display, GST_VAAPI_ID_INVALID, target, target, format, width, height);
format, width, height); if (!texture)
return NULL;
return gst_vaapi_texture_egl_new_internal (texture);
} }
/** /**
@ -356,10 +361,15 @@ GstVaapiTexture *
gst_vaapi_texture_egl_new_wrapped (GstVaapiDisplay * display, gst_vaapi_texture_egl_new_wrapped (GstVaapiDisplay * display,
guint texture_id, guint target, GLenum format, guint width, guint height) guint texture_id, guint target, GLenum format, guint width, guint height)
{ {
GstVaapiTexture *texture;
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), NULL); g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), NULL);
g_return_val_if_fail (texture_id != GL_NONE, NULL); g_return_val_if_fail (texture_id != GL_NONE, NULL);
return gst_vaapi_texture_new_internal (GST_VAAPI_TEXTURE_CLASS texture = gst_vaapi_texture_new_internal (display, texture_id,
(gst_vaapi_texture_egl_class ()), display, texture_id, target, format, target, format, width, height);
width, height); if (!texture)
return texture;
return gst_vaapi_texture_egl_new_internal (texture);
} }

View file

@ -45,42 +45,29 @@
#define GST_VAAPI_TEXTURE_GLX(texture) \ #define GST_VAAPI_TEXTURE_GLX(texture) \
((GstVaapiTextureGLX *)(texture)) ((GstVaapiTextureGLX *)(texture))
typedef struct _GstVaapiTextureGLX GstVaapiTextureGLX; typedef struct _GstVaapiTextureGLXPrivate GstVaapiTextureGLXPrivate;
typedef struct _GstVaapiTextureGLXClass GstVaapiTextureGLXClass;
/** /**
* GstVaapiTextureGLX: * GstVaapiTextureGLXPrivate:
* *
* Base object for GLX texture wrapper. * GLX texture specific fields.
*/ */
struct _GstVaapiTextureGLX struct _GstVaapiTextureGLXPrivate
{ {
/*< private > */ /*< private > */
GstVaapiTexture parent_instance; GstVaapiTexture *texture;
GLContextState *gl_context; GLContextState *gl_context;
GLPixmapObject *pixo; GLPixmapObject *pixo;
GLFramebufferObject *fbo; GLFramebufferObject *fbo;
}; };
/**
* GstVaapiTextureGLXClass:
*
* Base class for GLX texture wrapper.
*/
struct _GstVaapiTextureGLXClass
{
/*< private > */
GstVaapiTextureClass parent_class;
};
static gboolean static gboolean
gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture, gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect,
guint flags); guint flags);
static void static void
destroy_objects (GstVaapiTextureGLX * texture) destroy_objects (GstVaapiTextureGLXPrivate * texture)
{ {
GLContextState old_cs; GLContextState old_cs;
@ -105,11 +92,12 @@ destroy_objects (GstVaapiTextureGLX * texture)
} }
static void static void
destroy_texture_unlocked (GstVaapiTexture * texture) destroy_texture_unlocked (GstVaapiTextureGLXPrivate * texture_glx)
{ {
GstVaapiTexture *texture = texture_glx->texture;
const guint texture_id = GST_VAAPI_TEXTURE_ID (texture); const guint texture_id = GST_VAAPI_TEXTURE_ID (texture);
destroy_objects (GST_VAAPI_TEXTURE_GLX (texture)); destroy_objects (texture_glx);
if (texture_id) { if (texture_id) {
if (!texture->is_wrapped) if (!texture->is_wrapped)
@ -119,38 +107,45 @@ destroy_texture_unlocked (GstVaapiTexture * texture)
} }
static void static void
gst_vaapi_texture_glx_destroy (GstVaapiTexture * texture) gst_vaapi_texture_glx_destroy (GstVaapiTextureGLXPrivate * texture_glx)
{ {
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GstVaapiTexture *texture = texture_glx->texture;
destroy_texture_unlocked (texture);
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
destroy_texture_unlocked (texture_glx);
GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
g_free (texture_glx);
} }
static gboolean static gboolean
create_objects (GstVaapiTextureGLX * texture, guint texture_id) create_objects (GstVaapiTexture * texture, guint texture_id)
{ {
GstVaapiTexture *const base_texture = GST_VAAPI_TEXTURE (texture); GstVaapiTextureGLXPrivate *texture_glx =
Display *const dpy = GST_VAAPI_OBJECT_NATIVE_DISPLAY (texture); gst_vaapi_texture_get_private (texture);
Display *const dpy =
GST_VAAPI_DISPLAY_NATIVE (GST_VAAPI_TEXTURE_DISPLAY (texture));
GLContextState old_cs; GLContextState old_cs;
gboolean success = FALSE; gboolean success = FALSE;
gl_get_current_context (&old_cs); gl_get_current_context (&old_cs);
texture->gl_context = gl_create_context (dpy, DefaultScreen (dpy), &old_cs); texture_glx->gl_context =
if (!texture->gl_context || gl_create_context (dpy, DefaultScreen (dpy), &old_cs);
!gl_set_current_context (texture->gl_context, NULL)) if (!texture_glx->gl_context
|| !gl_set_current_context (texture_glx->gl_context, NULL))
return FALSE; return FALSE;
texture->pixo = gl_create_pixmap_object (dpy, texture_glx->pixo = gl_create_pixmap_object (dpy,
base_texture->width, base_texture->height); texture->width, texture->height);
if (!texture->pixo) { if (!texture_glx->pixo) {
GST_ERROR ("failed to create GLX pixmap"); GST_ERROR ("failed to create GLX pixmap");
goto out_reset_context; goto out_reset_context;
} }
texture->fbo = gl_create_framebuffer_object (base_texture->gl_target, texture_glx->fbo = gl_create_framebuffer_object (texture->gl_target,
texture_id, base_texture->width, base_texture->height); texture_id, texture->width, texture->height);
if (!texture->fbo) { if (!texture_glx->fbo) {
GST_ERROR ("failed to create FBO"); GST_ERROR ("failed to create FBO");
goto out_reset_context; goto out_reset_context;
} }
@ -175,7 +170,7 @@ create_texture_unlocked (GstVaapiTexture * texture)
return FALSE; return FALSE;
GST_VAAPI_TEXTURE_ID (texture) = texture_id; GST_VAAPI_TEXTURE_ID (texture) = texture_id;
} }
return create_objects (GST_VAAPI_TEXTURE_GLX (texture), texture_id); return create_objects (texture, texture_id);
} }
static gboolean static gboolean
@ -183,29 +178,37 @@ gst_vaapi_texture_glx_create (GstVaapiTexture * texture)
{ {
gboolean success; gboolean success;
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
success = create_texture_unlocked (texture); success = create_texture_unlocked (texture);
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
return success; return success;
} }
static void
gst_vaapi_texture_glx_class_init (GstVaapiTextureGLXClass * klass) static GstVaapiTexture *
gst_vaapi_texture_glx_new_internal (GstVaapiTexture * texture)
{ {
GstVaapiObjectClass *const object_class = GST_VAAPI_OBJECT_CLASS (klass); GstVaapiTextureGLXPrivate *texture_glx;
GstVaapiTextureClass *const texture_class = GST_VAAPI_TEXTURE_CLASS (klass);
object_class->finalize = (GstVaapiObjectFinalizeFunc) texture->put_surface = gst_vaapi_texture_glx_put_surface;
gst_vaapi_texture_glx_destroy;
texture_class->allocate = gst_vaapi_texture_glx_create; texture_glx = g_malloc0 (sizeof (GstVaapiTextureGLXPrivate));
texture_class->put_surface = gst_vaapi_texture_glx_put_surface; if (!texture_glx) {
gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
return NULL;
}
texture_glx->texture = texture;
gst_vaapi_texture_set_private (texture, texture_glx,
(GDestroyNotify) gst_vaapi_texture_glx_destroy);
if (!gst_vaapi_texture_glx_create (texture)) {
gst_mini_object_unref (GST_MINI_OBJECT_CAST (texture));
return NULL;
}
return texture;
} }
#define gst_vaapi_texture_glx_finalize gst_vaapi_texture_glx_destroy
GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE (GstVaapiTextureGLX,
gst_vaapi_texture_glx, gst_vaapi_texture_glx_class_init (&g_class));
/** /**
* gst_vaapi_texture_glx_new: * gst_vaapi_texture_glx_new:
* @display: a #GstVaapiDisplay * @display: a #GstVaapiDisplay
@ -229,11 +232,16 @@ GstVaapiTexture *
gst_vaapi_texture_glx_new (GstVaapiDisplay * display, guint target, gst_vaapi_texture_glx_new (GstVaapiDisplay * display, guint target,
guint format, guint width, guint height) guint format, guint width, guint height)
{ {
GstVaapiTexture *texture;
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL);
return gst_vaapi_texture_new_internal (GST_VAAPI_TEXTURE_CLASS texture = gst_vaapi_texture_new_internal (display, GST_VAAPI_ID_INVALID,
(gst_vaapi_texture_glx_class ()), display, GST_VAAPI_ID_INVALID, target, target, format, width, height);
format, width, height); if (!texture)
return NULL;
return gst_vaapi_texture_glx_new_internal (texture);
} }
/* Can we assume that the vsink/app context API won't change ever? */ /* Can we assume that the vsink/app context API won't change ever? */
@ -278,6 +286,7 @@ gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display,
GLTextureState ts = { 0, }; GLTextureState ts = { 0, };
gboolean success; gboolean success;
GstVaapiGLApi gl_api; GstVaapiGLApi gl_api;
GstVaapiTexture *texture;
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL); g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_GLX (display), NULL);
g_return_val_if_fail (texture_id != GL_NONE, NULL); g_return_val_if_fail (texture_id != GL_NONE, NULL);
@ -312,9 +321,12 @@ gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display,
g_return_val_if_fail (width > 0, NULL); g_return_val_if_fail (width > 0, NULL);
g_return_val_if_fail (height > 0, NULL); g_return_val_if_fail (height > 0, NULL);
return gst_vaapi_texture_new_internal (GST_VAAPI_TEXTURE_CLASS texture = gst_vaapi_texture_new_internal (display, texture_id, target,
(gst_vaapi_texture_glx_class ()), display, texture_id, target, format, format, width, height);
width, height); if (!texture)
return NULL;
return gst_vaapi_texture_glx_new_internal (texture);
} }
/** /**
@ -330,10 +342,11 @@ gst_vaapi_texture_glx_new_wrapped (GstVaapiDisplay * display,
* Return value: %TRUE on success * Return value: %TRUE on success
*/ */
static gboolean static gboolean
gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * base_texture, gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags) GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags)
{ {
GstVaapiTextureGLX *const texture = GST_VAAPI_TEXTURE_GLX (base_texture); GstVaapiTextureGLXPrivate *texture_glx =
gst_vaapi_texture_get_private (texture);
VAStatus status; VAStatus status;
GLContextState old_cs; GLContextState old_cs;
gboolean success = FALSE; gboolean success = FALSE;
@ -344,19 +357,19 @@ gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * base_texture,
{1.0f, 0.0f}, {1.0f, 0.0f},
}; };
status = vaPutSurface (GST_VAAPI_OBJECT_VADISPLAY (texture), status = vaPutSurface (GST_VAAPI_DISPLAY_VADISPLAY (GST_VAAPI_TEXTURE_DISPLAY
GST_VAAPI_SURFACE_ID (surface), texture->pixo->pixmap, (texture)), GST_VAAPI_SURFACE_ID (surface), texture_glx->pixo->pixmap,
crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height, 0, 0,
0, 0, base_texture->width, base_texture->height, texture->width, texture->height, NULL, 0,
NULL, 0, from_GstVaapiSurfaceRenderFlags (flags)); from_GstVaapiSurfaceRenderFlags (flags));
if (!vaapi_check_status (status, "vaPutSurface() [TFP]")) if (!vaapi_check_status (status, "vaPutSurface() [TFP]"))
return FALSE; return FALSE;
if (texture->gl_context && if (texture_glx->gl_context &&
!gl_set_current_context (texture->gl_context, &old_cs)) !gl_set_current_context (texture_glx->gl_context, &old_cs))
return FALSE; return FALSE;
if (!gl_bind_framebuffer_object (texture->fbo)) { if (!gl_bind_framebuffer_object (texture_glx->fbo)) {
GST_ERROR ("failed to bind FBO"); GST_ERROR ("failed to bind FBO");
goto out_reset_context; goto out_reset_context;
} }
@ -366,12 +379,12 @@ gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * base_texture,
goto out_unbind_fbo; goto out_unbind_fbo;
} }
if (!gl_bind_pixmap_object (texture->pixo)) { if (!gl_bind_pixmap_object (texture_glx->pixo)) {
GST_ERROR ("could not bind GLX pixmap"); GST_ERROR ("could not bind GLX pixmap");
goto out_unbind_fbo; goto out_unbind_fbo;
} }
flags = GST_VAAPI_TEXTURE_FLAGS (texture); flags = GST_MINI_OBJECT_FLAGS (texture);
txc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED)]; txc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_X_INVERTED)];
tyc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED)]; tyc = g_texcoords[! !(flags & GST_VAAPI_TEXTURE_ORIENTATION_FLAG_Y_INVERTED)];
@ -381,25 +394,25 @@ gst_vaapi_texture_glx_put_surface_unlocked (GstVaapiTexture * base_texture,
glTexCoord2f (txc[0], tyc[0]); glTexCoord2f (txc[0], tyc[0]);
glVertex2i (0, 0); glVertex2i (0, 0);
glTexCoord2f (txc[0], tyc[1]); glTexCoord2f (txc[0], tyc[1]);
glVertex2i (0, base_texture->height); glVertex2i (0, texture->height);
glTexCoord2f (txc[1], tyc[1]); glTexCoord2f (txc[1], tyc[1]);
glVertex2i (base_texture->width, base_texture->height); glVertex2i (texture->width, texture->height);
glTexCoord2f (txc[1], tyc[0]); glTexCoord2f (txc[1], tyc[0]);
glVertex2i (base_texture->width, 0); glVertex2i (texture->width, 0);
} }
glEnd (); glEnd ();
if (!gl_unbind_pixmap_object (texture->pixo)) { if (!gl_unbind_pixmap_object (texture_glx->pixo)) {
GST_ERROR ("failed to release GLX pixmap"); GST_ERROR ("failed to release GLX pixmap");
goto out_unbind_fbo; goto out_unbind_fbo;
} }
success = TRUE; success = TRUE;
out_unbind_fbo: out_unbind_fbo:
if (!gl_unbind_framebuffer_object (texture->fbo)) if (!gl_unbind_framebuffer_object (texture_glx->fbo))
success = FALSE; success = FALSE;
out_reset_context: out_reset_context:
if (texture->gl_context && !gl_set_current_context (&old_cs, NULL)) if (texture_glx->gl_context && !gl_set_current_context (&old_cs, NULL))
success = FALSE; success = FALSE;
return success; return success;
} }
@ -410,9 +423,9 @@ gst_vaapi_texture_glx_put_surface (GstVaapiTexture * texture,
{ {
gboolean success; gboolean success;
GST_VAAPI_OBJECT_LOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_LOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
success = gst_vaapi_texture_glx_put_surface_unlocked (texture, surface, success = gst_vaapi_texture_glx_put_surface_unlocked (texture, surface,
crop_rect, flags); crop_rect, flags);
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (texture); GST_VAAPI_DISPLAY_UNLOCK (GST_VAAPI_TEXTURE_DISPLAY (texture));
return success; return success;
} }

View file

@ -26,14 +26,19 @@
#define GST_VAAPI_TEXTURE_PRIV_H #define GST_VAAPI_TEXTURE_PRIV_H
#include "gstvaapiobject_priv.h" #include "gstvaapiobject_priv.h"
#include <gst/gstminiobject.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_VAAPI_TEXTURE_CLASS(klass) \ /**
((GstVaapiTextureClass *)(klass)) * GST_VAAPI_TEXTURE_DISPLAY:
* @texture: a #GstVaapiTexture
#define GST_VAAPI_TEXTURE_GET_CLASS(obj) \ *
GST_VAAPI_TEXTURE_CLASS (GST_VAAPI_OBJECT_GET_CLASS (obj)) * Macro that evaluates to the @texture's display.
*/
#undef GST_VAAPI_TEXTURE_DISPLAY
#define GST_VAAPI_TEXTURE_DISPLAY(texture) \
(GST_VAAPI_TEXTURE (texture)->display)
/** /**
* GST_VAAPI_TEXTURE_ID: * GST_VAAPI_TEXTURE_ID:
@ -43,7 +48,7 @@ G_BEGIN_DECLS
*/ */
#undef GST_VAAPI_TEXTURE_ID #undef GST_VAAPI_TEXTURE_ID
#define GST_VAAPI_TEXTURE_ID(texture) \ #define GST_VAAPI_TEXTURE_ID(texture) \
(GST_VAAPI_OBJECT_ID (texture)) (GST_VAAPI_TEXTURE (texture)->object_id)
/** /**
* GST_VAAPI_TEXTURE_TARGET: * GST_VAAPI_TEXTURE_TARGET:
@ -85,18 +90,9 @@ G_BEGIN_DECLS
#define GST_VAAPI_TEXTURE_HEIGHT(texture) \ #define GST_VAAPI_TEXTURE_HEIGHT(texture) \
(GST_VAAPI_TEXTURE (texture)->height) (GST_VAAPI_TEXTURE (texture)->height)
#define GST_VAAPI_TEXTURE_FLAGS GST_VAAPI_MINI_OBJECT_FLAGS
#define GST_VAAPI_TEXTURE_FLAG_IS_SET GST_VAAPI_MINI_OBJECT_FLAG_IS_SET
#define GST_VAAPI_TEXTURE_FLAG_SET GST_VAAPI_MINI_OBJECT_FLAG_SET
#define GST_VAAPI_TEXTURE_FLAG_UNSET GST_VAAPI_MINI_OBJECT_FLAG_UNSET
/* GstVaapiTextureClass hooks */ /* GstVaapiTextureClass hooks */
typedef gboolean (*GstVaapiTextureAllocateFunc) (GstVaapiTexture * texture);
typedef gboolean (*GstVaapiTexturePutSurfaceFunc) (GstVaapiTexture * texture, typedef gboolean (*GstVaapiTexturePutSurfaceFunc) (GstVaapiTexture * texture,
GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, GstVaapiSurface * surface, const GstVaapiRectangle * crop_rect, guint flags);
guint flags);
typedef struct _GstVaapiTextureClass GstVaapiTextureClass;
/** /**
* GstVaapiTexture: * GstVaapiTexture:
@ -105,9 +101,12 @@ typedef struct _GstVaapiTextureClass GstVaapiTextureClass;
*/ */
struct _GstVaapiTexture { struct _GstVaapiTexture {
/*< private >*/ /*< private >*/
GstVaapiObject parent_instance; GstMiniObject mini_object;
GstVaapiDisplay *display;
GstVaapiID object_id;
/*< protected >*/ /*< protected >*/
GstVaapiTexturePutSurfaceFunc put_surface;
guint gl_target; guint gl_target;
guint gl_format; guint gl_format;
guint width; guint width;
@ -115,25 +114,16 @@ struct _GstVaapiTexture {
guint is_wrapped:1; guint is_wrapped:1;
}; };
/**
* GstVaapiTextureClass:
* @put_surface: virtual function to render a #GstVaapiSurface into a texture
*
* Base class for API-dependent textures.
*/
struct _GstVaapiTextureClass {
/*< private >*/
GstVaapiObjectClass parent_class;
/*< protected >*/
GstVaapiTextureAllocateFunc allocate;
GstVaapiTexturePutSurfaceFunc put_surface;
};
GstVaapiTexture * GstVaapiTexture *
gst_vaapi_texture_new_internal (const GstVaapiTextureClass * klass, gst_vaapi_texture_new_internal (GstVaapiDisplay * display, GstVaapiID id,
GstVaapiDisplay * display, GstVaapiID id, guint target, guint format, guint target, guint format, guint width, guint height);
guint width, guint height);
gpointer
gst_vaapi_texture_get_private (GstVaapiTexture * texture);
void
gst_vaapi_texture_set_private (GstVaapiTexture * texture, gpointer priv,
GDestroyNotify destroy);
G_END_DECLS G_END_DECLS

View file

@ -62,7 +62,7 @@ gst_vaapi_texture_map_init (GstVaapiTextureMap * map)
{ {
map->texture_map = map->texture_map =
g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
(GDestroyNotify) gst_vaapi_texture_unref); (GDestroyNotify) gst_mini_object_unref);
} }
static void static void

View file

@ -139,8 +139,9 @@ ensure_texture (GstVaapiWindowEGL * window, guint width, guint height)
texture = gst_vaapi_texture_egl_new (GST_VAAPI_WINDOW_DISPLAY (window), texture = gst_vaapi_texture_egl_new (GST_VAAPI_WINDOW_DISPLAY (window),
GL_TEXTURE_2D, GL_RGBA, width, height); GL_TEXTURE_2D, GL_RGBA, width, height);
gst_vaapi_texture_replace (&window->texture, texture); gst_mini_object_replace ((GstMiniObject **) & window->texture,
gst_vaapi_texture_replace (&texture, NULL); (GstMiniObject *) texture);
gst_mini_object_replace ((GstMiniObject **) & texture, NULL);
return window->texture != NULL; return window->texture != NULL;
} }
@ -287,7 +288,7 @@ gst_vaapi_window_egl_finalize (GObject * object)
} }
gst_vaapi_window_replace (&window->window, NULL); gst_vaapi_window_replace (&window->window, NULL);
gst_vaapi_texture_replace (&window->texture, NULL); gst_mini_object_replace ((GstMiniObject **) & window->texture, NULL);
G_OBJECT_CLASS (gst_vaapi_window_egl_parent_class)->finalize (object); G_OBJECT_CLASS (gst_vaapi_window_egl_parent_class)->finalize (object);
} }
@ -385,7 +386,7 @@ gst_vaapi_window_egl_resize (GstVaapiWindow * window, guint width, guint height)
static gboolean static gboolean
do_render_texture (GstVaapiWindowEGL * window, const GstVaapiRectangle * rect) do_render_texture (GstVaapiWindowEGL * window, const GstVaapiRectangle * rect)
{ {
const GLuint tex_id = GST_VAAPI_OBJECT_ID (window->texture); const GLuint tex_id = GST_VAAPI_TEXTURE_ID (window->texture);
EglVTable *const vtable = window->egl_vtable; EglVTable *const vtable = window->egl_vtable;
GLfloat x0, y0, x1, y1; GLfloat x0, y0, x1, y1;
GLfloat texcoords[4][2]; GLfloat texcoords[4][2];

View file

@ -125,7 +125,7 @@ meta_texture_free (GstVaapiVideoMetaTexture * meta)
if (G_UNLIKELY (!meta)) if (G_UNLIKELY (!meta))
return; return;
gst_vaapi_texture_replace (&meta->texture, NULL); gst_mini_object_replace ((GstMiniObject **) & meta->texture, NULL);
g_slice_free (GstVaapiVideoMetaTexture, meta); g_slice_free (GstVaapiVideoMetaTexture, meta);
} }
@ -164,7 +164,9 @@ meta_texture_copy (GstVaapiVideoMetaTexture * meta)
copy->gl_format = meta->gl_format; copy->gl_format = meta->gl_format;
copy->width = meta->width; copy->width = meta->width;
copy->height = meta->height; copy->height = meta->height;
gst_vaapi_texture_replace (&copy->texture, meta->texture);
gst_mini_object_replace ((GstMiniObject **) & copy->texture,
(GstMiniObject *) meta->texture);
return copy; return copy;
} }
@ -186,8 +188,7 @@ gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta,
if (meta_texture->texture if (meta_texture->texture
/* Check whether VA display changed */ /* Check whether VA display changed */
&& gst_vaapi_object_get_display && GST_VAAPI_TEXTURE_DISPLAY (meta_texture->texture) == dpy
(GST_VAAPI_OBJECT (meta_texture->texture)) == dpy
/* Check whether texture id changed */ /* Check whether texture id changed */
&& (gst_vaapi_texture_get_id (meta_texture->texture) == texture_id[0])) { && (gst_vaapi_texture_get_id (meta_texture->texture) == texture_id[0])) {
texture = meta_texture->texture; texture = meta_texture->texture;
@ -202,7 +203,8 @@ gst_vaapi_texture_upload (GstVideoGLTextureUploadMeta * meta,
} }
if (meta_texture->texture != texture) { if (meta_texture->texture != texture) {
gst_vaapi_texture_replace (&meta_texture->texture, texture); gst_mini_object_replace ((GstMiniObject **) & meta_texture->texture,
(GstMiniObject *) texture);
} }
if (!texture) if (!texture)

View file

@ -168,8 +168,8 @@ main (int argc, char *argv[])
gst_vaapi_window_glx_swap_buffers (glx_window); gst_vaapi_window_glx_swap_buffers (glx_window);
pause (); pause ();
gst_vaapi_texture_unref (textures[0]); gst_mini_object_unref (GST_MINI_OBJECT_CAST (textures[0]));
gst_vaapi_texture_unref (textures[1]); gst_mini_object_unref (GST_MINI_OBJECT_CAST (textures[1]));
glDeleteTextures (1, &texture_id); glDeleteTextures (1, &texture_id);
gst_object_unref (window); gst_object_unref (window);