From 502dec7c1cd6533dec99452a7422a3dc2f351259 Mon Sep 17 00:00:00 2001 From: gb Date: Tue, 30 Mar 2010 12:59:15 +0000 Subject: [PATCH] Add TFP and FBO helpers. --- gst-libs/gst/vaapi/gstvaapiutils_glx.c | 616 +++++++++++++++++++++++++++++++++ gst-libs/gst/vaapi/gstvaapiutils_glx.h | 102 ++++++ 2 files changed, 718 insertions(+) diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.c b/gst-libs/gst/vaapi/gstvaapiutils_glx.c index 5947ed7..93e8465 100644 --- a/gst-libs/gst/vaapi/gstvaapiutils_glx.c +++ b/gst-libs/gst/vaapi/gstvaapiutils_glx.c @@ -18,13 +18,38 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#define _GNU_SOURCE 1 /* RTLD_DEFAULT */ #include "config.h" +#include #include +#include #include "gstvaapiutils_glx.h" +#include "gstvaapiutils_x11.h" #define DEBUG 1 #include "gstvaapidebug.h" +/** Lookup for substring NAME in string EXT using SEP as separators */ +static gboolean +find_string(const char *name, const char *ext, const char *sep) +{ + const char *end; + int name_len, n; + + if (!name || !ext) + return FALSE; + + end = ext + strlen(ext); + name_len = strlen(name); + while (ext < end) { + n = strcspn(ext, sep); + if (n == name_len && strncmp(name, ext, n) == 0) + return TRUE; + ext += (n + 1); + } + return FALSE; +} + /** * gl_get_error_string: * @error: an OpenGL error enumeration @@ -415,3 +440,594 @@ gl_create_texture(GLenum target, GLenum format, guint width, guint height) gl_unbind_texture(&ts); return texture; } + +/** + * get_proc_address: + * @name: the name of the OpenGL extension function to lookup + * + * Returns the specified OpenGL extension function + * + * Return value: the OpenGL extension matching @name, or %NULL if none + * was found + */ +typedef void (*GLFuncPtr)(void); +typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *); + +static GLFuncPtr +get_proc_address_default(const char *name) +{ + return NULL; +} + +static GLXGetProcAddressProc +get_proc_address_func(void) +{ + GLXGetProcAddressProc get_proc_func; + + dlerror(); + get_proc_func = (GLXGetProcAddressProc) + dlsym(RTLD_DEFAULT, "glXGetProcAddress"); + if (!dlerror()) + return get_proc_func; + + get_proc_func = (GLXGetProcAddressProc) + dlsym(RTLD_DEFAULT, "glXGetProcAddressARB"); + if (!dlerror()) + return get_proc_func; + + return get_proc_address_default; +} + +static inline GLFuncPtr +get_proc_address(const char *name) +{ + static GLXGetProcAddressProc get_proc_func = NULL; + if (!get_proc_func) + get_proc_func = get_proc_address_func(); + return get_proc_func(name); +} + +/** + * gl_init_vtable: + * + * Initializes the global #GLVTable. + * + * Return value: the #GLVTable filled in with OpenGL extensions, or + * %NULL on error. + */ +static GLVTable gl_vtable_static; + +static GLVTable * +gl_init_vtable(void) +{ + GLVTable * const gl_vtable = &gl_vtable_static; + const gchar *gl_extensions = (const gchar *)glGetString(GL_EXTENSIONS); + gboolean has_extension; + + /* GLX_EXT_texture_from_pixmap */ + gl_vtable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC) + get_proc_address("glXBindTexImageEXT"); + if (!gl_vtable->glx_bind_tex_image) + return NULL; + gl_vtable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC) + get_proc_address("glXReleaseTexImageEXT"); + if (!gl_vtable->glx_release_tex_image) + return NULL; + + /* GL_ARB_framebuffer_object */ + has_extension = ( + find_string("GL_ARB_framebuffer_object", gl_extensions, " ") || + find_string("GL_EXT_framebuffer_object", gl_extensions, " ") + ); + if (has_extension) { + gl_vtable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC) + get_proc_address("glGenFramebuffersEXT"); + if (!gl_vtable->gl_gen_framebuffers) + return NULL; + gl_vtable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC) + get_proc_address("glDeleteFramebuffersEXT"); + if (!gl_vtable->gl_delete_framebuffers) + return NULL; + gl_vtable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC) + get_proc_address("glBindFramebufferEXT"); + if (!gl_vtable->gl_bind_framebuffer) + return NULL; + gl_vtable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC) + get_proc_address("glGenRenderbuffersEXT"); + if (!gl_vtable->gl_gen_renderbuffers) + return NULL; + gl_vtable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC) + get_proc_address("glDeleteRenderbuffersEXT"); + if (!gl_vtable->gl_delete_renderbuffers) + return NULL; + gl_vtable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC) + get_proc_address("glBindRenderbufferEXT"); + if (!gl_vtable->gl_bind_renderbuffer) + return NULL; + gl_vtable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC) + get_proc_address("glRenderbufferStorageEXT"); + if (!gl_vtable->gl_renderbuffer_storage) + return NULL; + gl_vtable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) + get_proc_address("glFramebufferRenderbufferEXT"); + if (!gl_vtable->gl_framebuffer_renderbuffer) + return NULL; + gl_vtable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) + get_proc_address("glFramebufferTexture2DEXT"); + if (!gl_vtable->gl_framebuffer_texture_2d) + return NULL; + gl_vtable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) + get_proc_address("glCheckFramebufferStatusEXT"); + if (!gl_vtable->gl_check_framebuffer_status) + return NULL; + gl_vtable->has_framebuffer_object = TRUE; + } + + /* GL_ARB_fragment_program */ + has_extension = ( + find_string("GL_ARB_fragment_program", gl_extensions, " ") + ); + if (has_extension) { + gl_vtable->gl_gen_programs = (PFNGLGENPROGRAMSARBPROC) + get_proc_address("glGenProgramsARB"); + if (!gl_vtable->gl_gen_programs) + return NULL; + gl_vtable->gl_delete_programs = (PFNGLDELETEPROGRAMSARBPROC) + get_proc_address("glDeleteProgramsARB"); + if (!gl_vtable->gl_delete_programs) + return NULL; + gl_vtable->gl_bind_program = (PFNGLBINDPROGRAMARBPROC) + get_proc_address("glBindProgramARB"); + if (!gl_vtable->gl_bind_program) + return NULL; + gl_vtable->gl_program_string = (PFNGLPROGRAMSTRINGARBPROC) + get_proc_address("glProgramStringARB"); + if (!gl_vtable->gl_program_string) + return NULL; + gl_vtable->gl_get_program_iv = (PFNGLGETPROGRAMIVARBPROC) + get_proc_address("glGetProgramivARB"); + if (!gl_vtable->gl_get_program_iv) + return NULL; + gl_vtable->gl_program_local_parameter_4fv = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) + get_proc_address("glProgramLocalParameter4fvARB"); + if (!gl_vtable->gl_program_local_parameter_4fv) + return NULL; + gl_vtable->has_fragment_program = TRUE; + } + + /* GL_ARB_multitexture */ + has_extension = ( + find_string("GL_ARB_multitexture", gl_extensions, " ") + ); + if (has_extension) { + gl_vtable->gl_active_texture = (PFNGLACTIVETEXTUREPROC) + get_proc_address("glActiveTextureARB"); + if (!gl_vtable->gl_active_texture) + return NULL; + gl_vtable->gl_multi_tex_coord_2f = (PFNGLMULTITEXCOORD2FPROC) + get_proc_address("glMultiTexCoord2fARB"); + if (!gl_vtable->gl_multi_tex_coord_2f) + return NULL; + gl_vtable->has_multitexture = TRUE; + } + return gl_vtable; +} + +/** + * gl_get_vtable: + * + * Retrieves a VTable for OpenGL extensions. + * + * Return value: VTable for OpenGL extensions + */ +GLVTable * +gl_get_vtable(void) +{ + static GStaticMutex mutex = G_STATIC_MUTEX_INIT; + static gboolean gl_vtable_init = TRUE; + static GLVTable *gl_vtable = NULL; + + g_static_mutex_lock(&mutex); + if (gl_vtable_init) { + gl_vtable_init = FALSE; + gl_vtable = gl_init_vtable(); + } + g_static_mutex_unlock(&mutex); + return gl_vtable; +} + +/** + * gl_create_pixmap_object: + * @dpy: an X11 #Display + * @width: the request width, in pixels + * @height: the request height, in pixels + * + * Creates a #GLPixmapObject of the specified dimensions. This + * requires the GLX_EXT_texture_from_pixmap extension. + * + * Return value: the newly created #GLPixmapObject object + */ +GLPixmapObject * +gl_create_pixmap_object(Display *dpy, guint width, guint height) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + GLPixmapObject *pixo; + GLXFBConfig *fbconfig; + int screen; + Window rootwin; + XWindowAttributes wattr; + int *attr; + int n_fbconfig_attrs; + + int fbconfig_attrs[32] = { + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_DOUBLEBUFFER, GL_TRUE, + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_RENDERABLE, GL_TRUE, + GLX_Y_INVERTED_EXT, GL_TRUE, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + GL_NONE, + }; + + int pixmap_attrs[10] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_MIPMAP_TEXTURE_EXT, GL_FALSE, + GL_NONE, + }; + + if (!gl_vtable) + return NULL; + + screen = DefaultScreen(dpy); + rootwin = RootWindow(dpy, screen); + + /* XXX: this won't work for different displays */ + if (!gl_vtable->has_texture_from_pixmap) { + const char *glx_extensions; + int glx_major, glx_minor; + glx_extensions = glXQueryExtensionsString(dpy, screen); + if (!glx_extensions) + return NULL; + if (!find_string("GLX_EXT_texture_from_pixmap", glx_extensions, " ")) + return NULL; + if (!glXQueryVersion(dpy, &glx_major, &glx_minor)) + return NULL; + if (glx_major < 0 || (glx_major == 1 && glx_minor < 3)) /* 1.3 */ + return NULL; + gl_vtable->has_texture_from_pixmap = TRUE; + } + + pixo = calloc(1, sizeof(*pixo)); + if (!pixo) + return NULL; + + pixo->dpy = dpy; + pixo->width = width; + pixo->height = height; + pixo->pixmap = None; + pixo->glx_pixmap = None; + pixo->is_bound = FALSE; + + XGetWindowAttributes(dpy, rootwin, &wattr); + pixo->pixmap = XCreatePixmap(dpy, rootwin, width, height, wattr.depth); + if (!pixo->pixmap) + goto error; + + /* Initialize FBConfig attributes */ + for (attr = fbconfig_attrs; *attr != GL_NONE; attr += 2) + ; + *attr++ = GLX_DEPTH_SIZE; *attr++ = wattr.depth; + if (wattr.depth == 32) { + *attr++ = GLX_ALPHA_SIZE; *attr++ = 8; + *attr++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attr++ = GL_TRUE; + } + else { + *attr++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attr++ = GL_TRUE; + } + *attr++ = GL_NONE; + + fbconfig = glXChooseFBConfig( + dpy, + screen, + fbconfig_attrs, &n_fbconfig_attrs + ); + if (!fbconfig) + goto error; + + /* Initialize GLX Pixmap attrutes */ + for (attr = pixmap_attrs; *attr != GL_NONE; attr += 2) + ; + *attr++ = GLX_TEXTURE_FORMAT_EXT; + if (wattr.depth == 32) + *attr++ = GLX_TEXTURE_FORMAT_RGBA_EXT; + else + *attr++ = GLX_TEXTURE_FORMAT_RGB_EXT; + *attr++ = GL_NONE; + + x11_trap_errors(); + pixo->glx_pixmap = glXCreatePixmap(dpy, fbconfig[0], pixo->pixmap, pixmap_attrs); + free(fbconfig); + if (x11_untrap_errors() != 0) + goto error; + return pixo; + +error: + gl_destroy_pixmap_object(pixo); + return NULL; +} + +/** + * gl_destroy_pixmap_object: + * @pixo: a #GLPixmapObject + * + * Destroys the #GLPixmapObject object. + */ +void +gl_destroy_pixmap_object(GLPixmapObject *pixo) +{ + if (!pixo) + return; + + gl_unbind_pixmap_object(pixo); + + if (pixo->glx_pixmap) { + glXDestroyPixmap(pixo->dpy, pixo->glx_pixmap); + pixo->glx_pixmap = None; + } + + if (pixo->pixmap) { + XFreePixmap(pixo->dpy, pixo->pixmap); + pixo->pixmap = None; + } + free(pixo); +} + +/** + * gl_bind_pixmap_object: + * @pixo: a #GLPixmapObject + * + * Defines a two-dimensional texture image. The texture image is taken + * from the @pixo pixmap and need not be copied. The texture target, + * format and size are derived from attributes of the @pixo pixmap. + * + * Return value: %TRUE on success + */ +gboolean +gl_bind_pixmap_object(GLPixmapObject *pixo) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + + if (pixo->is_bound) + return TRUE; + + x11_trap_errors(); + gl_vtable->glx_bind_tex_image( + pixo->dpy, + pixo->glx_pixmap, + GLX_FRONT_LEFT_EXT, + NULL + ); + XSync(pixo->dpy, False); + if (x11_untrap_errors() != 0) { + GST_DEBUG("failed to bind pixmap"); + return FALSE; + } + + pixo->is_bound = TRUE; + return TRUE; +} + +/** + * gl_unbind_pixmap_object: + * @pixo: a #GLPixmapObject + * + * Releases a color buffers that is being used as a texture. + * + * Return value: %TRUE on success + */ +gboolean +gl_unbind_pixmap_object(GLPixmapObject *pixo) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + + if (!pixo->is_bound) + return TRUE; + + x11_trap_errors(); + gl_vtable->glx_release_tex_image( + pixo->dpy, + pixo->glx_pixmap, + GLX_FRONT_LEFT_EXT + ); + XSync(pixo->dpy, False); + if (x11_untrap_errors() != 0) { + GST_DEBUG("failed to release pixmap"); + return FALSE; + } + + pixo->is_bound = FALSE; + return TRUE; +} + +/** + * gl_create_framebuffer_object: + * @target: the target to which the texture is bound + * @texture: the GL texture to hold the framebuffer + * @width: the requested width, in pixels + * @height: the requested height, in pixels + * + * Creates an FBO with the specified texture and size. + * + * Return value: the newly created #GLFramebufferObject, or %NULL if + * an error occurred + */ +GLFramebufferObject * +gl_create_framebuffer_object( + GLenum target, + GLuint texture, + guint width, + guint height +) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + GLFramebufferObject *fbo; + GLTextureState ts; + GLenum status; + gboolean texture_was_bound; + + if (!gl_vtable || !gl_vtable->has_framebuffer_object) + return NULL; + + /* XXX: we only support GL_TEXTURE_2D at this time */ + if (target != GL_TEXTURE_2D) + return NULL; + + fbo = calloc(1, sizeof(*fbo)); + if (!fbo) + return NULL; + + fbo->width = width; + fbo->height = height; + fbo->fbo = 0; + fbo->fbo_buffer = 0; + fbo->fbo_target = target; + fbo->fbo_texture = 0; + fbo->old_fbo = 0; + fbo->is_bound = FALSE; + + fbo->fbo_texture = gl_create_texture(target, GL_BGRA, width, height); + if (!fbo->fbo_texture) + goto error; + + gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo); + gl_vtable->gl_gen_framebuffers(1, &fbo->fbo); + gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo); + gl_vtable->gl_gen_renderbuffers(1, &fbo->fbo_buffer); + gl_vtable->gl_bind_renderbuffer(GL_RENDERBUFFER_EXT, fbo->fbo_buffer); + + texture_was_bound = gl_bind_texture(&ts, target, texture); + if (texture_was_bound) { + gl_vtable->gl_framebuffer_texture_2d( + GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + target, texture, + 0 + ); + gl_unbind_texture(&ts); + } + status = gl_vtable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT); + gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo); + if (!texture_was_bound || status != GL_FRAMEBUFFER_COMPLETE_EXT) + goto error; + return fbo; + +error: + gl_destroy_framebuffer_object(fbo); + return NULL; +} + +/** + * gl_destroy_framebuffer_object: + * @fbo: a #GLFramebufferObject + * + * Destroys the @fbo object. + */ +void +gl_destroy_framebuffer_object(GLFramebufferObject *fbo) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + + if (!fbo) + return; + + gl_unbind_framebuffer_object(fbo); + + if (fbo->fbo_texture) { + glDeleteTextures(1, &fbo->fbo_texture); + fbo->fbo_texture = 0; + } + + if (fbo->fbo_buffer) { + gl_vtable->gl_delete_renderbuffers(1, &fbo->fbo_buffer); + fbo->fbo_buffer = 0; + } + + if (fbo->fbo) { + gl_vtable->gl_delete_framebuffers(1, &fbo->fbo); + fbo->fbo = 0; + } + free(fbo); +} + +/** + * gl_bind_framebuffer_object: + * @fbo: a #GLFramebufferObject + * + * Binds @fbo object. + * + * Return value: %TRUE on success + */ +gboolean +gl_bind_framebuffer_object(GLFramebufferObject *fbo) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + const guint width = fbo->width; + const guint height = fbo->height; + + const guint attribs = (GL_VIEWPORT_BIT| + GL_CURRENT_BIT| + GL_ENABLE_BIT| + GL_TEXTURE_BIT| + GL_COLOR_BUFFER_BIT); + + if (fbo->is_bound) + return TRUE; + + gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo); + gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo); + glPushAttrib(attribs); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glViewport(0, 0, width, height); + glTranslatef(-1.0f, -1.0f, 0.0f); + glScalef(2.0f / width, 2.0f / height, 1.0f); + + if (!gl_bind_texture(&fbo->old_texture, fbo->fbo_target, fbo->fbo_texture)) + return FALSE; + + fbo->is_bound = TRUE; + return TRUE; +} + +/** + * gl_unbind_framebuffer_object: + * @fbo: a #GLFramebufferObject + * + * Releases @fbo object. + * + * Return value: %TRUE on success + */ +gboolean +gl_unbind_framebuffer_object(GLFramebufferObject *fbo) +{ + GLVTable * const gl_vtable = gl_get_vtable(); + + if (!fbo->is_bound) + return TRUE; + + glPopAttrib(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo); + + fbo->is_bound = FALSE; + return TRUE; +} diff --git a/gst-libs/gst/vaapi/gstvaapiutils_glx.h b/gst-libs/gst/vaapi/gstvaapiutils_glx.h index 69d0048..3c83da2 100644 --- a/gst-libs/gst/vaapi/gstvaapiutils_glx.h +++ b/gst-libs/gst/vaapi/gstvaapiutils_glx.h @@ -23,9 +23,20 @@ #include "config.h" #include +#include #include +#include #include +#if GLX_GLXEXT_VERSION < 18 +typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *); +typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int); +#endif + +#ifndef GL_FRAMEBUFFER_BINDING +#define GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT +#endif + const char * gl_get_error_string(GLenum error) attribute_hidden; @@ -88,4 +99,95 @@ GLuint gl_create_texture(GLenum target, GLenum format, guint width, guint height) attribute_hidden; +typedef struct _GLVTable GLVTable; +struct _GLVTable { + PFNGLXBINDTEXIMAGEEXTPROC glx_bind_tex_image; + PFNGLXRELEASETEXIMAGEEXTPROC glx_release_tex_image; + PFNGLGENFRAMEBUFFERSEXTPROC gl_gen_framebuffers; + PFNGLDELETEFRAMEBUFFERSEXTPROC gl_delete_framebuffers; + PFNGLBINDFRAMEBUFFEREXTPROC gl_bind_framebuffer; + PFNGLGENRENDERBUFFERSEXTPROC gl_gen_renderbuffers; + PFNGLDELETERENDERBUFFERSEXTPROC gl_delete_renderbuffers; + PFNGLBINDRENDERBUFFEREXTPROC gl_bind_renderbuffer; + PFNGLRENDERBUFFERSTORAGEEXTPROC gl_renderbuffer_storage; + PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC gl_framebuffer_renderbuffer; + PFNGLFRAMEBUFFERTEXTURE2DEXTPROC gl_framebuffer_texture_2d; + PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC gl_check_framebuffer_status; + PFNGLGENPROGRAMSARBPROC gl_gen_programs; + PFNGLDELETEPROGRAMSARBPROC gl_delete_programs; + PFNGLBINDPROGRAMARBPROC gl_bind_program; + PFNGLPROGRAMSTRINGARBPROC gl_program_string; + PFNGLGETPROGRAMIVARBPROC gl_get_program_iv; + PFNGLPROGRAMLOCALPARAMETER4FVARBPROC gl_program_local_parameter_4fv; + PFNGLACTIVETEXTUREPROC gl_active_texture; + PFNGLMULTITEXCOORD2FPROC gl_multi_tex_coord_2f; + guint has_texture_from_pixmap : 1; + guint has_framebuffer_object : 1; + guint has_fragment_program : 1; + guint has_multitexture : 1; +}; + +GLVTable * +gl_get_vtable(void) + attribute_hidden; + +typedef struct _GLPixmapObject GLPixmapObject; +struct _GLPixmapObject { + Display *dpy; + guint width; + guint height; + Pixmap pixmap; + GLXPixmap glx_pixmap; + guint is_bound : 1; +}; + +GLPixmapObject * +gl_create_pixmap_object(Display *dpy, guint width, guint height) + attribute_hidden; + +void +gl_destroy_pixmap_object(GLPixmapObject *pixo) + attribute_hidden; + +gboolean +gl_bind_pixmap_object(GLPixmapObject *pixo) + attribute_hidden; + +gboolean +gl_unbind_pixmap_object(GLPixmapObject *pixo) + attribute_hidden; + +typedef struct _GLFramebufferObject GLFramebufferObject; +struct _GLFramebufferObject { + guint width; + guint height; + GLuint fbo; + GLuint fbo_buffer; + GLenum fbo_target; + GLuint fbo_texture; + GLuint old_fbo; + GLTextureState old_texture; + guint is_bound : 1; +}; + +GLFramebufferObject * +gl_create_framebuffer_object( + GLenum target, + GLuint texture, + guint width, + guint height +) attribute_hidden; + +void +gl_destroy_framebuffer_object(GLFramebufferObject *fbo) + attribute_hidden; + +gboolean +gl_bind_framebuffer_object(GLFramebufferObject *fbo) + attribute_hidden; + +gboolean +gl_unbind_framebuffer_object(GLFramebufferObject *fbo) + attribute_hidden; + #endif /* GST_VAAPI_UTILS_GLX_H */ -- 2.7.4