mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
Add TFP and FBO helpers.
This commit is contained in:
parent
4ff830812f
commit
502dec7c1c
2 changed files with 718 additions and 0 deletions
|
@ -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 <string.h>
|
||||
#include <math.h>
|
||||
#include <dlfcn.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,20 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
#include <glib/gtypes.h>
|
||||
|
||||
#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 */
|
||||
|
|
Loading…
Reference in a new issue