mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 19:31:12 +00:00
aabb8c99c2
This provides for some basic EGL window abstraction.
565 lines
17 KiB
C
565 lines
17 KiB
C
/*
|
|
* gstvaapiwindow_egl.c - VA/EGL window abstraction
|
|
*
|
|
* Copyright (C) 2014 Intel Corporation
|
|
* Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation; either version 2.1
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* SECTION:gstvaapiwindow_egl
|
|
* @short_description: VA/EGL window abstraction
|
|
*/
|
|
|
|
#include "sysdeps.h"
|
|
#include "gstvaapiwindow_egl.h"
|
|
#include "gstvaapiwindow_priv.h"
|
|
#include "gstvaapitexture_egl.h"
|
|
#include "gstvaapitexture_priv.h"
|
|
#include "gstvaapidisplay_egl_priv.h"
|
|
|
|
#define GST_VAAPI_WINDOW_EGL(obj) \
|
|
((GstVaapiWindowEGL *)(obj))
|
|
|
|
#define GST_VAAPI_WINDOW_EGL_CLASS(klass) \
|
|
((GstVaapiWindowEGLClass *)(klass))
|
|
|
|
#define GST_VAAPI_WINDOW_EGL_GET_CLASS(obj) \
|
|
GST_VAAPI_WINDOW_EGL_CLASS (GST_VAAPI_WINDOW_GET_CLASS (obj))
|
|
|
|
typedef struct _GstVaapiWindowEGL GstVaapiWindowEGL;
|
|
typedef struct _GstVaapiWindowEGLClass GstVaapiWindowEGLClass;
|
|
|
|
enum
|
|
{
|
|
RENDER_PROGRAM_VAR_PROJ = 0,
|
|
RENDER_PROGRAM_VAR_TEX0,
|
|
RENDER_PROGRAM_VAR_TEX1,
|
|
RENDER_PROGRAM_VAR_TEX2,
|
|
};
|
|
|
|
struct _GstVaapiWindowEGL
|
|
{
|
|
GstVaapiWindow parent_instance;
|
|
|
|
GstVaapiWindow *window;
|
|
GstVaapiTexture *texture;
|
|
EglWindow *egl_window;
|
|
EglVTable *egl_vtable;
|
|
EglProgram *render_program;
|
|
gfloat render_projection[16];
|
|
};
|
|
|
|
struct _GstVaapiWindowEGLClass
|
|
{
|
|
GstVaapiWindowClass parent_class;
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
GstVaapiWindowEGL *window;
|
|
guint width;
|
|
guint height;
|
|
EglContext *egl_context;
|
|
gboolean success; /* result */
|
|
} CreateObjectsArgs;
|
|
|
|
typedef struct
|
|
{
|
|
GstVaapiWindowEGL *window;
|
|
guint width;
|
|
guint height;
|
|
gboolean success; /* result */
|
|
} ResizeWindowArgs;
|
|
|
|
typedef struct
|
|
{
|
|
GstVaapiWindowEGL *window;
|
|
GstVaapiSurface *surface;
|
|
const GstVaapiRectangle *src_rect;
|
|
const GstVaapiRectangle *dst_rect;
|
|
guint flags;
|
|
gboolean success; /* result */
|
|
} UploadSurfaceArgs;
|
|
|
|
static const gchar *vert_shader_text =
|
|
"#ifdef GL_ES\n"
|
|
"precision mediump float;\n"
|
|
"#endif\n"
|
|
"\n"
|
|
"uniform mat4 proj;\n"
|
|
"\n"
|
|
"attribute vec2 position;\n"
|
|
"attribute vec2 texcoord;\n"
|
|
"varying vec2 v_texcoord;\n"
|
|
"\n"
|
|
"void main () {\n"
|
|
" gl_Position = proj * vec4 (position, 0.0, 1.0);\n"
|
|
" v_texcoord = texcoord;\n"
|
|
"}\n";
|
|
|
|
static const gchar *frag_shader_text_rgba =
|
|
"#ifdef GL_ES\n"
|
|
"precision mediump float;\n"
|
|
"#endif\n"
|
|
"\n"
|
|
"uniform sampler2D tex0;\n"
|
|
"\n"
|
|
"varying vec2 v_texcoord;\n"
|
|
"\n"
|
|
"void main () {\n"
|
|
" gl_FragColor = texture2D (tex0, v_texcoord);\n"
|
|
"}\n";
|
|
|
|
static gboolean
|
|
ensure_texture (GstVaapiWindowEGL * window, guint width, guint height)
|
|
{
|
|
GstVaapiTexture *texture;
|
|
|
|
if (window->texture &&
|
|
GST_VAAPI_TEXTURE_WIDTH (window->texture) == width &&
|
|
GST_VAAPI_TEXTURE_HEIGHT (window->texture) == height)
|
|
return TRUE;
|
|
|
|
texture = gst_vaapi_texture_egl_new (GST_VAAPI_OBJECT_DISPLAY (window),
|
|
GL_TEXTURE_2D, GL_RGBA, width, height);
|
|
gst_vaapi_texture_replace (&window->texture, texture);
|
|
gst_vaapi_texture_replace (&texture, NULL);
|
|
return window->texture != NULL;
|
|
}
|
|
|
|
static gboolean
|
|
ensure_shaders (GstVaapiWindowEGL * window)
|
|
{
|
|
EglVTable *const vtable = window->egl_vtable;
|
|
EglProgram *program;
|
|
GLuint prog_id;
|
|
|
|
g_return_val_if_fail (window->texture != NULL, FALSE);
|
|
g_return_val_if_fail (GST_VAAPI_TEXTURE_FORMAT (window->texture) == GL_RGBA,
|
|
FALSE);
|
|
|
|
if (window->render_program)
|
|
return TRUE;
|
|
|
|
program = egl_program_new (window->egl_window->context,
|
|
frag_shader_text_rgba, vert_shader_text);
|
|
if (!program)
|
|
return FALSE;
|
|
|
|
prog_id = program->base.handle.u;
|
|
|
|
vtable->glUseProgram (prog_id);
|
|
program->uniforms[RENDER_PROGRAM_VAR_PROJ] =
|
|
vtable->glGetUniformLocation (prog_id, "proj");
|
|
program->uniforms[RENDER_PROGRAM_VAR_TEX0] =
|
|
vtable->glGetUniformLocation (prog_id, "tex0");
|
|
program->uniforms[RENDER_PROGRAM_VAR_TEX1] =
|
|
vtable->glGetUniformLocation (prog_id, "tex1");
|
|
program->uniforms[RENDER_PROGRAM_VAR_TEX2] =
|
|
vtable->glGetUniformLocation (prog_id, "tex2");
|
|
vtable->glUseProgram (0);
|
|
|
|
egl_matrix_set_identity (window->render_projection);
|
|
|
|
egl_object_replace (&window->render_program, program);
|
|
egl_object_replace (&program, NULL);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
do_create_objects_unlocked (GstVaapiWindowEGL * window, guint width,
|
|
guint height, EglContext * egl_context)
|
|
{
|
|
EglWindow *egl_window;
|
|
EglVTable *egl_vtable;
|
|
|
|
egl_window = egl_window_new (egl_context,
|
|
GSIZE_TO_POINTER (GST_VAAPI_OBJECT_ID (window->window)));
|
|
if (!egl_window)
|
|
return FALSE;
|
|
window->egl_window = egl_window;
|
|
|
|
egl_vtable = egl_context_get_vtable (egl_window->context, TRUE);
|
|
if (!egl_vtable)
|
|
return FALSE;
|
|
window->egl_vtable = egl_object_ref (egl_vtable);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
do_create_objects (CreateObjectsArgs * args)
|
|
{
|
|
GstVaapiWindowEGL *const window = args->window;
|
|
EglContextState old_cs;
|
|
|
|
args->success = FALSE;
|
|
|
|
GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
|
|
if (egl_context_set_current (args->egl_context, TRUE, &old_cs)) {
|
|
args->success = do_create_objects_unlocked (window, args->width,
|
|
args->height, args->egl_context);
|
|
egl_context_set_current (args->egl_context, FALSE, &old_cs);
|
|
}
|
|
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_create (GstVaapiWindowEGL * window,
|
|
guint * width, guint * height)
|
|
{
|
|
GstVaapiDisplayEGL *const display =
|
|
GST_VAAPI_DISPLAY_EGL (GST_VAAPI_OBJECT_DISPLAY (window));
|
|
const GstVaapiDisplayClass *const native_dpy_class =
|
|
GST_VAAPI_DISPLAY_GET_CLASS (display->display);
|
|
CreateObjectsArgs args;
|
|
|
|
g_return_val_if_fail (native_dpy_class != NULL, FALSE);
|
|
|
|
window->window = native_dpy_class->create_window (GST_VAAPI_DISPLAY (display),
|
|
GST_VAAPI_ID_INVALID, *width, *height);
|
|
if (!window->window)
|
|
return FALSE;
|
|
|
|
gst_vaapi_window_get_size (window->window, width, height);
|
|
|
|
args.window = window;
|
|
args.width = *width;
|
|
args.height = *height;
|
|
args.egl_context = GST_VAAPI_DISPLAY_EGL_CONTEXT (display);
|
|
return egl_context_run (args.egl_context,
|
|
(EglContextRunFunc) do_create_objects, &args) && args.success;
|
|
}
|
|
|
|
static void
|
|
do_destroy_objects_unlocked (GstVaapiWindowEGL * window)
|
|
{
|
|
egl_object_replace (&window->render_program, NULL);
|
|
egl_object_replace (&window->egl_vtable, NULL);
|
|
egl_object_replace (&window->egl_window, NULL);
|
|
}
|
|
|
|
static void
|
|
do_destroy_objects (GstVaapiWindowEGL * window)
|
|
{
|
|
EglContext *const egl_context =
|
|
GST_VAAPI_DISPLAY_EGL_CONTEXT (GST_VAAPI_OBJECT_DISPLAY (window));
|
|
EglContextState old_cs;
|
|
|
|
if (!window->egl_window)
|
|
return;
|
|
|
|
GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
|
|
if (egl_context_set_current (egl_context, TRUE, &old_cs)) {
|
|
do_destroy_objects_unlocked (window);
|
|
egl_context_set_current (egl_context, FALSE, &old_cs);
|
|
}
|
|
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
|
|
}
|
|
|
|
static void
|
|
gst_vaapi_window_egl_destroy (GstVaapiWindowEGL * window)
|
|
{
|
|
egl_context_run (window->egl_window->context,
|
|
(EglContextRunFunc) do_destroy_objects, window);
|
|
gst_vaapi_window_replace (&window->window, NULL);
|
|
gst_vaapi_texture_replace (&window->texture, NULL);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_show (GstVaapiWindowEGL * window)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
|
|
g_return_val_if_fail (klass->show, FALSE);
|
|
|
|
return klass->show (window->window);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_hide (GstVaapiWindowEGL * window)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
|
|
g_return_val_if_fail (klass->hide, FALSE);
|
|
|
|
return klass->hide (window->window);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_get_geometry (GstVaapiWindowEGL * window,
|
|
gint * x_ptr, gint * y_ptr, guint * width_ptr, guint * height_ptr)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
|
|
return klass->get_geometry ? klass->get_geometry (window->window,
|
|
x_ptr, y_ptr, width_ptr, height_ptr) : FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_set_fullscreen (GstVaapiWindowEGL * window,
|
|
gboolean fullscreen)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
|
|
return klass->set_fullscreen ? klass->set_fullscreen (window->window,
|
|
fullscreen) : FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
do_resize_window_unlocked (GstVaapiWindowEGL * window, guint width,
|
|
guint height)
|
|
{
|
|
EglVTable *const vtable = window->egl_vtable;
|
|
|
|
vtable->glViewport (0, 0, width, height);
|
|
vtable->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
|
|
vtable->glClear (GL_COLOR_BUFFER_BIT);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
do_resize_window (ResizeWindowArgs * args)
|
|
{
|
|
GstVaapiWindowEGL *const window = args->window;
|
|
EglContextState old_cs;
|
|
|
|
GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
|
|
if (egl_context_set_current (window->egl_window->context, TRUE, &old_cs)) {
|
|
args->success = do_resize_window_unlocked (window, args->width,
|
|
args->height);
|
|
egl_context_set_current (window->egl_window->context, FALSE, &old_cs);
|
|
}
|
|
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_resize (GstVaapiWindowEGL * window, guint width,
|
|
guint height)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
ResizeWindowArgs args = { window, width, height };
|
|
|
|
g_return_val_if_fail (klass->resize, FALSE);
|
|
|
|
if (!klass->resize (window->window, width, height))
|
|
return FALSE;
|
|
|
|
return egl_context_run (window->egl_window->context,
|
|
(EglContextRunFunc) do_resize_window, &args) && args.success;
|
|
}
|
|
|
|
static gboolean
|
|
do_render_texture (GstVaapiWindowEGL * window, const GstVaapiRectangle * rect)
|
|
{
|
|
const GLuint tex_id = GST_VAAPI_OBJECT_ID (window->texture);
|
|
EglVTable *const vtable = window->egl_vtable;
|
|
GLfloat x0, y0, x1, y1;
|
|
GLfloat texcoords[4][2];
|
|
GLfloat positions[4][2];
|
|
guint tex_width, tex_height;
|
|
|
|
if (!ensure_shaders (window))
|
|
return FALSE;
|
|
|
|
tex_width = GST_VAAPI_TEXTURE_WIDTH (window->texture);
|
|
tex_height = GST_VAAPI_TEXTURE_HEIGHT (window->texture);
|
|
|
|
// Source coords in VA surface
|
|
x0 = 0.0f;
|
|
y0 = 0.0f;
|
|
x1 = 1.0f;
|
|
y1 = 1.0f;
|
|
texcoords[0][0] = x0;
|
|
texcoords[0][1] = y1;
|
|
texcoords[1][0] = x1;
|
|
texcoords[1][1] = y1;
|
|
texcoords[2][0] = x1;
|
|
texcoords[2][1] = y0;
|
|
texcoords[3][0] = x0;
|
|
texcoords[3][1] = y0;
|
|
|
|
// Target coords in EGL surface
|
|
x0 = 2.0f * ((GLfloat) rect->x / tex_width) - 1.0f;
|
|
y1 = -2.0f * ((GLfloat) rect->y / tex_height) + 1.0f;
|
|
x1 = 2.0f * ((GLfloat) (rect->x + rect->width) / tex_width) - 1.0f;
|
|
y0 = -2.0f * ((GLfloat) (rect->y + rect->height) / tex_height) + 1.0f;
|
|
positions[0][0] = x0;
|
|
positions[0][1] = y0;
|
|
positions[1][0] = x1;
|
|
positions[1][1] = y0;
|
|
positions[2][0] = x1;
|
|
positions[2][1] = y1;
|
|
positions[3][0] = x0;
|
|
positions[3][1] = y1;
|
|
|
|
vtable->glClear (GL_COLOR_BUFFER_BIT);
|
|
|
|
if (G_UNLIKELY (window->egl_window->context->config->gles_version == 1)) {
|
|
vtable->glBindTexture (GST_VAAPI_TEXTURE_TARGET (window->texture), tex_id);
|
|
vtable->glEnableClientState (GL_VERTEX_ARRAY);
|
|
vtable->glVertexPointer (2, GL_FLOAT, 0, positions);
|
|
vtable->glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
|
vtable->glTexCoordPointer (2, GL_FLOAT, 0, texcoords);
|
|
|
|
vtable->glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
vtable->glDisableClientState (GL_VERTEX_ARRAY);
|
|
vtable->glDisableClientState (GL_TEXTURE_COORD_ARRAY);
|
|
} else {
|
|
EglProgram *const program = window->render_program;
|
|
|
|
vtable->glUseProgram (program->base.handle.u);
|
|
vtable->glUniformMatrix4fv (program->uniforms[RENDER_PROGRAM_VAR_PROJ],
|
|
1, GL_FALSE, window->render_projection);
|
|
vtable->glEnableVertexAttribArray (0);
|
|
vtable->glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, positions);
|
|
vtable->glEnableVertexAttribArray (1);
|
|
vtable->glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, texcoords);
|
|
|
|
vtable->glBindTexture (GST_VAAPI_TEXTURE_TARGET (window->texture), tex_id);
|
|
vtable->glUniform1i (program->uniforms[RENDER_PROGRAM_VAR_TEX0], 0);
|
|
vtable->glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
|
|
|
|
vtable->glDisableVertexAttribArray (1);
|
|
vtable->glDisableVertexAttribArray (0);
|
|
vtable->glUseProgram (0);
|
|
}
|
|
|
|
eglSwapBuffers (window->egl_window->context->display->base.handle.p,
|
|
window->egl_window->base.handle.p);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
do_upload_surface_unlocked (GstVaapiWindowEGL * window,
|
|
GstVaapiSurface * surface, const GstVaapiRectangle * src_rect,
|
|
const GstVaapiRectangle * dst_rect, guint flags)
|
|
{
|
|
if (!ensure_texture (window, dst_rect->width, dst_rect->height))
|
|
return FALSE;
|
|
if (!gst_vaapi_texture_put_surface (window->texture, surface, src_rect,
|
|
flags))
|
|
return FALSE;
|
|
if (!do_render_texture (window, dst_rect))
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
do_upload_surface (UploadSurfaceArgs * args)
|
|
{
|
|
GstVaapiWindowEGL *const window = args->window;
|
|
EglContextState old_cs;
|
|
|
|
args->success = FALSE;
|
|
|
|
GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
|
|
if (egl_context_set_current (window->egl_window->context, TRUE, &old_cs)) {
|
|
args->success = do_upload_surface_unlocked (window, args->surface,
|
|
args->src_rect, args->dst_rect, args->flags);
|
|
egl_context_set_current (window->egl_window->context, FALSE, &old_cs);
|
|
}
|
|
GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_render (GstVaapiWindowEGL * window,
|
|
GstVaapiSurface * surface, const GstVaapiRectangle * src_rect,
|
|
const GstVaapiRectangle * dst_rect, guint flags)
|
|
{
|
|
UploadSurfaceArgs args = { window, surface, src_rect, dst_rect, flags };
|
|
|
|
return egl_context_run (window->egl_window->context,
|
|
(EglContextRunFunc) do_upload_surface, &args) && args.success;
|
|
}
|
|
|
|
static gboolean
|
|
gst_vaapi_window_egl_render_pixmap (GstVaapiWindowEGL * window,
|
|
GstVaapiPixmap * pixmap,
|
|
const GstVaapiRectangle * src_rect, const GstVaapiRectangle * dst_rect)
|
|
{
|
|
const GstVaapiWindowClass *const klass =
|
|
GST_VAAPI_WINDOW_GET_CLASS (window->window);
|
|
|
|
if (!klass->render_pixmap)
|
|
return FALSE;
|
|
return klass->render_pixmap (window->window, pixmap, src_rect, dst_rect);
|
|
}
|
|
|
|
void
|
|
gst_vaapi_window_egl_class_init (GstVaapiWindowEGLClass * klass)
|
|
{
|
|
GstVaapiObjectClass *const object_class = GST_VAAPI_OBJECT_CLASS (klass);
|
|
GstVaapiWindowClass *const window_class = GST_VAAPI_WINDOW_CLASS (klass);
|
|
|
|
object_class->finalize = (GstVaapiObjectFinalizeFunc)
|
|
gst_vaapi_window_egl_destroy;
|
|
|
|
window_class->create = (GstVaapiWindowCreateFunc)
|
|
gst_vaapi_window_egl_create;
|
|
window_class->show = (GstVaapiWindowShowFunc)
|
|
gst_vaapi_window_egl_show;
|
|
window_class->hide = (GstVaapiWindowHideFunc)
|
|
gst_vaapi_window_egl_hide;
|
|
window_class->get_geometry = (GstVaapiWindowGetGeometryFunc)
|
|
gst_vaapi_window_egl_get_geometry;
|
|
window_class->set_fullscreen = (GstVaapiWindowSetFullscreenFunc)
|
|
gst_vaapi_window_egl_set_fullscreen;
|
|
window_class->resize = (GstVaapiWindowResizeFunc)
|
|
gst_vaapi_window_egl_resize;
|
|
window_class->render = (GstVaapiWindowRenderFunc)
|
|
gst_vaapi_window_egl_render;
|
|
window_class->render_pixmap = (GstVaapiWindowRenderPixmapFunc)
|
|
gst_vaapi_window_egl_render_pixmap;
|
|
}
|
|
|
|
#define gst_vaapi_window_egl_finalize \
|
|
gst_vaapi_window_egl_destroy
|
|
|
|
GST_VAAPI_OBJECT_DEFINE_CLASS_WITH_CODE (GstVaapiWindowEGL,
|
|
gst_vaapi_window_egl, gst_vaapi_window_egl_class_init (&g_class));
|
|
|
|
/**
|
|
* gst_vaapi_window_egl_new:
|
|
* @display: a #GstVaapiDisplay
|
|
* @width: the requested window width, in pixels
|
|
* @height: the requested windo height, in pixels
|
|
*
|
|
* Creates a window with the specified @width and @height. The window
|
|
* will be attached to the @display and remains invisible to the user
|
|
* until gst_vaapi_window_show() is called.
|
|
*
|
|
* Return value: the newly allocated #GstVaapiWindow object
|
|
*/
|
|
GstVaapiWindow *
|
|
gst_vaapi_window_egl_new (GstVaapiDisplay * display, guint width, guint height)
|
|
{
|
|
GST_DEBUG ("new window, size %ux%u", width, height);
|
|
|
|
g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), NULL);
|
|
|
|
return
|
|
gst_vaapi_window_new_internal (GST_VAAPI_WINDOW_CLASS
|
|
(gst_vaapi_window_egl_class ()), display, GST_VAAPI_ID_INVALID, width,
|
|
height);
|
|
}
|