2 * gstvaapiutils_glx.c - GLX utilties
4 * Copyright (C) 2010-2011 Splitted-Desktop Systems
5 * Copyright (C) 2011-2012 Intel Corporation
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either version 2.1
10 * of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301 USA
23 #define _GNU_SOURCE 1 /* RTLD_DEFAULT */
28 #include "gstvaapiutils_glx.h"
29 #include "gstvaapiutils_x11.h"
32 #include "gstvaapidebug.h"
34 /** Lookup for substring NAME in string EXT using SEP as separators */
36 find_string(const char *name, const char *ext, const char *sep)
44 end = ext + strlen(ext);
45 name_len = strlen(name);
47 n = strcspn(ext, sep);
48 if (n == name_len && strncmp(name, ext, n) == 0)
56 * gl_get_error_string:
57 * @error: an OpenGL error enumeration
59 * Retrieves the string representation the OpenGL @error.
61 * Return error: the static string representing the OpenGL @error
64 gl_get_error_string(GLenum error)
67 #define MAP(id, str) \
68 case id: return str " (" #id ")"
69 MAP(GL_NO_ERROR, "no error");
70 MAP(GL_INVALID_ENUM, "invalid enumerant");
71 MAP(GL_INVALID_VALUE, "invalid value");
72 MAP(GL_INVALID_OPERATION, "invalid operation");
73 MAP(GL_STACK_OVERFLOW, "stack overflow");
74 MAP(GL_STACK_UNDERFLOW, "stack underflow");
75 MAP(GL_OUT_OF_MEMORY, "out of memory");
76 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
77 MAP(GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
78 "invalid framebuffer operation");
89 * Purges all OpenGL errors. This function is generally useful to
90 * clear up the pending errors prior to calling gl_check_error().
95 while (glGetError() != GL_NO_ERROR)
102 * Checks whether there is any OpenGL error pending.
104 * Return value: %TRUE if an error was encountered
110 gboolean has_errors = FALSE;
112 while ((error = glGetError()) != GL_NO_ERROR) {
113 GST_DEBUG("glError: %s caught", gl_get_error_string(error));
121 * @param: the parameter name
122 * @pval: return location for the value
124 * This function is a wrapper around glGetIntegerv() that does extra
127 * Return value: %TRUE on success
130 gl_get_param(GLenum param, guint *pval)
135 glGetIntegerv(param, &val);
136 if (gl_check_error())
145 * gl_get_texture_param:
146 * @target: the target to which the texture is bound
147 * @param: the parameter name
148 * @pval: return location for the value
150 * This function is a wrapper around glGetTexLevelParameteriv() that
151 * does extra error checking.
153 * Return value: %TRUE on success
156 gl_get_texture_param(GLenum target, GLenum param, guint *pval)
161 glGetTexLevelParameteriv(target, 0, param, &val);
162 if (gl_check_error())
171 * gl_get_texture_binding:
172 * @target: a texture target
174 * Determines the texture binding type for the specified target.
176 * Return value: texture binding type for @target
179 gl_get_texture_binding(GLenum target)
185 binding = GL_TEXTURE_BINDING_1D;
188 binding = GL_TEXTURE_BINDING_2D;
191 binding = GL_TEXTURE_BINDING_3D;
193 case GL_TEXTURE_RECTANGLE_ARB:
194 binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
205 * @color: the requested RGB color
207 * Sets background color to the RGB @color. This basically is a
208 * wrapper around glClearColor().
211 gl_set_bgcolor(guint32 color)
214 ((color >> 16) & 0xff) / 255.0f,
215 ((color >> 8) & 0xff) / 255.0f,
216 ( color & 0xff) / 255.0f,
223 * @fovy: the field of view angle, in degrees, in the y direction
224 * @aspect: the aspect ratio that determines the field of view in the
225 * x direction. The aspect ratio is the ratio of x (width) to y
227 * @zNear: the distance from the viewer to the near clipping plane
229 * @zFar: the distance from the viewer to the far clipping plane
232 * Specified a viewing frustum into the world coordinate system. This
233 * basically is the Mesa implementation of gluPerspective().
236 gl_perspective(GLdouble fovy, GLdouble aspect, GLdouble near_val, GLdouble far_val)
238 GLdouble left, right, top, bottom;
241 <http://www.opengl.org/resources/faq/technical/transformations.htm> */
242 top = tan(fovy * M_PI / 360.0) * near_val;
244 left = aspect * bottom;
245 right = aspect * top;
246 glFrustum(left, right, bottom, top, near_val, far_val);
251 * @width: the requested width, in pixels
252 * @height: the requested height, in pixels
254 * Resizes the OpenGL viewport to the specified dimensions, using an
255 * orthogonal projection. (0,0) represents the top-left corner of the
259 gl_resize(guint width, guint height)
265 #define Z_CAMERA 0.869f
267 glViewport(0, 0, width, height);
268 glMatrixMode(GL_PROJECTION);
270 gl_perspective(FOVY, ASPECT, Z_NEAR, Z_FAR);
271 glMatrixMode(GL_MODELVIEW);
274 glTranslatef(-0.5f, -0.5f, -Z_CAMERA);
275 glScalef(1.0f/width, -1.0f/height, 1.0f/width);
276 glTranslatef(0.0f, -1.0f*height, 0.0f);
281 * @dpy: an X11 #Display
282 * @screen: the associated screen of @dpy
283 * @parent: the parent #GLContextState, or %NULL if none is to be used
285 * Creates a GLX context sharing textures and displays lists with
286 * @parent, if not %NULL.
288 * Return value: the newly created GLX context
291 gl_create_context(Display *dpy, int screen, GLContextState *parent)
294 GLXFBConfig *fbconfigs = NULL;
295 int fbconfig_id, val, n, n_fbconfigs;
298 static GLint fbconfig_attrs[] = {
299 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
300 GLX_RENDER_TYPE, GLX_RGBA_BIT,
301 GLX_DOUBLEBUFFER, True,
308 cs = malloc(sizeof(*cs));
313 cs->display = parent->display;
314 cs->window = parent->window;
315 screen = DefaultScreen(parent->display);
323 cs->swapped_buffers = FALSE;
325 if (parent && parent->context) {
326 status = glXQueryContext(
329 GLX_FBCONFIG_ID, &fbconfig_id
331 if (status != Success)
334 if (fbconfig_id == GLX_DONT_CARE)
335 goto choose_fbconfig;
337 fbconfigs = glXGetFBConfigs(parent->display, screen, &n_fbconfigs);
341 /* Find out a GLXFBConfig compatible with the parent context */
342 for (n = 0; n < n_fbconfigs; n++) {
343 status = glXGetFBConfigAttrib(
346 GLX_FBCONFIG_ID, &val
348 if (status == Success && val == fbconfig_id)
351 if (n == n_fbconfigs)
356 fbconfigs = glXChooseFBConfig(
359 fbconfig_attrs, &n_fbconfigs
364 /* Select the first one */
368 cs->visual = glXGetVisualFromFBConfig(cs->display, fbconfigs[n]);
369 cs->context = glXCreateNewContext(
373 parent ? parent->context : NULL,
380 gl_destroy_context(cs);
389 * gl_destroy_context:
390 * @cs: a #GLContextState
392 * Destroys the GLX context @cs
395 gl_destroy_context(GLContextState *cs)
405 if (cs->display && cs->context) {
406 if (glXGetCurrentContext() == cs->context) {
407 /* XXX: if buffers were never swapped, the application
408 will crash later with the NVIDIA driver */
409 if (!cs->swapped_buffers)
411 glXMakeCurrent(cs->display, None, NULL);
413 glXDestroyContext(cs->display, cs->context);
421 * gl_get_current_context:
422 * @cs: return location to the current #GLContextState
424 * Retrieves the current GLX context, display and drawable packed into
425 * the #GLContextState struct.
428 gl_get_current_context(GLContextState *cs)
430 cs->display = glXGetCurrentDisplay();
431 cs->window = glXGetCurrentDrawable();
432 cs->context = glXGetCurrentContext();
436 * gl_set_current_context:
437 * @new_cs: the requested new #GLContextState
438 * @old_cs: return location to the context that was previously current
440 * Makes the @new_cs GLX context the current GLX rendering context of
441 * the calling thread, replacing the previously current context if
444 * If @old_cs is non %NULL, the previously current GLX context and
445 * window are recorded.
447 * Return value: %TRUE on success
450 gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs)
452 /* If display is NULL, this could be that new_cs was retrieved from
453 gl_get_current_context() with none set previously. If that case,
454 the other fields are also NULL and we don't return an error */
455 if (!new_cs->display)
456 return !new_cs->window && !new_cs->context;
459 if (old_cs == new_cs)
461 gl_get_current_context(old_cs);
462 if (old_cs->display == new_cs->display &&
463 old_cs->window == new_cs->window &&
464 old_cs->context == new_cs->context)
467 return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
472 * @cs: a #GLContextState
474 * Promotes the contents of the back buffer of the @win window to
475 * become the contents of the front buffer. This simply is wrapper
476 * around glXSwapBuffers().
479 gl_swap_buffers(GLContextState *cs)
481 glXSwapBuffers(cs->display, cs->window);
482 cs->swapped_buffers = TRUE;
487 * @ts: a #GLTextureState
488 * @target: the target to which the texture is bound
489 * @texture: the name of a texture
491 * Binds @texture to the specified @target, while recording the
492 * previous state in @ts.
494 * Return value: %TRUE on success
497 gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture)
503 if (glIsEnabled(target)) {
504 binding = gl_get_texture_binding(target);
507 if (!gl_get_param(binding, &ts->old_texture))
509 ts->was_enabled = TRUE;
510 ts->was_bound = texture == ts->old_texture;
517 ts->was_enabled = FALSE;
518 ts->was_bound = FALSE;
522 glBindTexture(target, texture);
523 if (gl_check_error())
530 * @ts: a #GLTextureState
532 * Rebinds the texture that was previously bound and recorded in @ts.
535 gl_unbind_texture(GLTextureState *ts)
537 if (!ts->was_bound && ts->old_texture)
538 glBindTexture(ts->target, ts->old_texture);
539 if (!ts->was_enabled)
540 glDisable(ts->target);
545 * @target: the target to which the texture is bound
546 * @format: the format of the pixel data
547 * @width: the requested width, in pixels
548 * @height: the requested height, in pixels
550 * Creates a texture with the specified dimensions and @format. The
551 * internal format will be automatically derived from @format.
553 * Return value: the newly created texture name
556 gl_create_texture(GLenum target, GLenum format, guint width, guint height)
558 GLenum internal_format;
561 guint bytes_per_component;
563 internal_format = format;
566 bytes_per_component = 1;
568 case GL_LUMINANCE_ALPHA:
569 bytes_per_component = 2;
573 internal_format = GL_RGBA;
574 bytes_per_component = 4;
577 bytes_per_component = 0;
580 g_assert(bytes_per_component > 0);
582 glGenTextures(1, &texture);
583 if (!gl_bind_texture(&ts, target, texture))
585 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
586 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
587 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
588 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
589 glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_component);
600 gl_unbind_texture(&ts);
606 * @name: the name of the OpenGL extension function to lookup
608 * Returns the specified OpenGL extension function
610 * Return value: the OpenGL extension matching @name, or %NULL if none
613 typedef void (*GLFuncPtr)(void);
614 typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
617 get_proc_address_default(const char *name)
622 static GLXGetProcAddressProc
623 get_proc_address_func(void)
625 GLXGetProcAddressProc get_proc_func;
628 get_proc_func = (GLXGetProcAddressProc)
629 dlsym(RTLD_DEFAULT, "glXGetProcAddress");
631 return get_proc_func;
633 get_proc_func = (GLXGetProcAddressProc)
634 dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
636 return get_proc_func;
638 return get_proc_address_default;
641 static inline GLFuncPtr
642 get_proc_address(const char *name)
644 static GLXGetProcAddressProc get_proc_func = NULL;
646 get_proc_func = get_proc_address_func();
647 return get_proc_func(name);
653 * Initializes the global #GLVTable.
655 * Return value: the #GLVTable filled in with OpenGL extensions, or
658 static GLVTable gl_vtable_static;
663 GLVTable * const gl_vtable = &gl_vtable_static;
664 const gchar *gl_extensions = (const gchar *)glGetString(GL_EXTENSIONS);
665 gboolean has_extension;
667 /* GLX_EXT_texture_from_pixmap */
668 gl_vtable->glx_create_pixmap = (PFNGLXCREATEPIXMAPPROC)
669 get_proc_address("glXCreatePixmap");
670 if (!gl_vtable->glx_create_pixmap)
672 gl_vtable->glx_destroy_pixmap = (PFNGLXDESTROYPIXMAPPROC)
673 get_proc_address("glXDestroyPixmap");
674 if (!gl_vtable->glx_destroy_pixmap)
676 gl_vtable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
677 get_proc_address("glXBindTexImageEXT");
678 if (!gl_vtable->glx_bind_tex_image)
680 gl_vtable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
681 get_proc_address("glXReleaseTexImageEXT");
682 if (!gl_vtable->glx_release_tex_image)
685 /* GL_ARB_framebuffer_object */
687 find_string("GL_ARB_framebuffer_object", gl_extensions, " ") ||
688 find_string("GL_EXT_framebuffer_object", gl_extensions, " ")
691 gl_vtable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
692 get_proc_address("glGenFramebuffersEXT");
693 if (!gl_vtable->gl_gen_framebuffers)
695 gl_vtable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
696 get_proc_address("glDeleteFramebuffersEXT");
697 if (!gl_vtable->gl_delete_framebuffers)
699 gl_vtable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
700 get_proc_address("glBindFramebufferEXT");
701 if (!gl_vtable->gl_bind_framebuffer)
703 gl_vtable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
704 get_proc_address("glGenRenderbuffersEXT");
705 if (!gl_vtable->gl_gen_renderbuffers)
707 gl_vtable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
708 get_proc_address("glDeleteRenderbuffersEXT");
709 if (!gl_vtable->gl_delete_renderbuffers)
711 gl_vtable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
712 get_proc_address("glBindRenderbufferEXT");
713 if (!gl_vtable->gl_bind_renderbuffer)
715 gl_vtable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
716 get_proc_address("glRenderbufferStorageEXT");
717 if (!gl_vtable->gl_renderbuffer_storage)
719 gl_vtable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
720 get_proc_address("glFramebufferRenderbufferEXT");
721 if (!gl_vtable->gl_framebuffer_renderbuffer)
723 gl_vtable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
724 get_proc_address("glFramebufferTexture2DEXT");
725 if (!gl_vtable->gl_framebuffer_texture_2d)
727 gl_vtable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
728 get_proc_address("glCheckFramebufferStatusEXT");
729 if (!gl_vtable->gl_check_framebuffer_status)
731 gl_vtable->has_framebuffer_object = TRUE;
734 /* GL_ARB_fragment_program */
736 find_string("GL_ARB_fragment_program", gl_extensions, " ")
739 gl_vtable->gl_gen_programs = (PFNGLGENPROGRAMSARBPROC)
740 get_proc_address("glGenProgramsARB");
741 if (!gl_vtable->gl_gen_programs)
743 gl_vtable->gl_delete_programs = (PFNGLDELETEPROGRAMSARBPROC)
744 get_proc_address("glDeleteProgramsARB");
745 if (!gl_vtable->gl_delete_programs)
747 gl_vtable->gl_bind_program = (PFNGLBINDPROGRAMARBPROC)
748 get_proc_address("glBindProgramARB");
749 if (!gl_vtable->gl_bind_program)
751 gl_vtable->gl_program_string = (PFNGLPROGRAMSTRINGARBPROC)
752 get_proc_address("glProgramStringARB");
753 if (!gl_vtable->gl_program_string)
755 gl_vtable->gl_get_program_iv = (PFNGLGETPROGRAMIVARBPROC)
756 get_proc_address("glGetProgramivARB");
757 if (!gl_vtable->gl_get_program_iv)
759 gl_vtable->gl_program_local_parameter_4fv = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)
760 get_proc_address("glProgramLocalParameter4fvARB");
761 if (!gl_vtable->gl_program_local_parameter_4fv)
763 gl_vtable->has_fragment_program = TRUE;
766 /* GL_ARB_multitexture */
768 find_string("GL_ARB_multitexture", gl_extensions, " ")
771 gl_vtable->gl_active_texture = (PFNGLACTIVETEXTUREPROC)
772 get_proc_address("glActiveTextureARB");
773 if (!gl_vtable->gl_active_texture)
775 gl_vtable->gl_multi_tex_coord_2f = (PFNGLMULTITEXCOORD2FPROC)
776 get_proc_address("glMultiTexCoord2fARB");
777 if (!gl_vtable->gl_multi_tex_coord_2f)
779 gl_vtable->has_multitexture = TRUE;
787 * Retrieves a VTable for OpenGL extensions.
789 * Return value: VTable for OpenGL extensions
794 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
795 static gboolean gl_vtable_init = TRUE;
796 static GLVTable *gl_vtable = NULL;
798 g_static_mutex_lock(&mutex);
799 if (gl_vtable_init) {
800 gl_vtable_init = FALSE;
801 gl_vtable = gl_init_vtable();
803 g_static_mutex_unlock(&mutex);
808 * gl_create_pixmap_object:
809 * @dpy: an X11 #Display
810 * @width: the request width, in pixels
811 * @height: the request height, in pixels
813 * Creates a #GLPixmapObject of the specified dimensions. This
814 * requires the GLX_EXT_texture_from_pixmap extension.
816 * Return value: the newly created #GLPixmapObject object
819 gl_create_pixmap_object(Display *dpy, guint width, guint height)
821 GLVTable * const gl_vtable = gl_get_vtable();
822 GLPixmapObject *pixo;
823 GLXFBConfig *fbconfig;
826 XWindowAttributes wattr;
828 int n_fbconfig_attrs;
830 int fbconfig_attrs[32] = {
831 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
832 GLX_DOUBLEBUFFER, GL_FALSE,
833 GLX_RENDER_TYPE, GLX_RGBA_BIT,
834 GLX_X_RENDERABLE, GL_TRUE,
835 GLX_Y_INVERTED_EXT, GL_TRUE,
842 int pixmap_attrs[10] = {
843 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
844 GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
851 screen = DefaultScreen(dpy);
852 rootwin = RootWindow(dpy, screen);
854 /* XXX: this won't work for different displays */
855 if (!gl_vtable->has_texture_from_pixmap) {
856 const char *glx_extensions = glXQueryExtensionsString(dpy, screen);
859 if (!find_string("GLX_EXT_texture_from_pixmap", glx_extensions, " "))
861 gl_vtable->has_texture_from_pixmap = TRUE;
864 pixo = calloc(1, sizeof(*pixo));
870 pixo->height = height;
872 pixo->glx_pixmap = None;
873 pixo->is_bound = FALSE;
875 XGetWindowAttributes(dpy, rootwin, &wattr);
876 pixo->pixmap = XCreatePixmap(dpy, rootwin, width, height, wattr.depth);
880 /* Initialize FBConfig attributes */
881 for (attr = fbconfig_attrs; *attr != GL_NONE; attr += 2)
883 *attr++ = GLX_DEPTH_SIZE; *attr++ = wattr.depth;
884 if (wattr.depth == 32) {
885 *attr++ = GLX_ALPHA_SIZE; *attr++ = 8;
886 *attr++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attr++ = GL_TRUE;
889 *attr++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attr++ = GL_TRUE;
893 fbconfig = glXChooseFBConfig(
896 fbconfig_attrs, &n_fbconfig_attrs
901 /* Initialize GLX Pixmap attributes */
902 for (attr = pixmap_attrs; *attr != GL_NONE; attr += 2)
904 *attr++ = GLX_TEXTURE_FORMAT_EXT;
905 if (wattr.depth == 32)
906 *attr++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
908 *attr++ = GLX_TEXTURE_FORMAT_RGB_EXT;
912 pixo->glx_pixmap = gl_vtable->glx_create_pixmap(
919 if (x11_untrap_errors() != 0)
922 pixo->target = GL_TEXTURE_2D;
923 glGenTextures(1, &pixo->texture);
924 if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
926 glTexParameteri(pixo->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
927 glTexParameteri(pixo->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
928 gl_unbind_texture(&pixo->old_texture);
932 gl_destroy_pixmap_object(pixo);
937 * gl_destroy_pixmap_object:
938 * @pixo: a #GLPixmapObject
940 * Destroys the #GLPixmapObject object.
943 gl_destroy_pixmap_object(GLPixmapObject *pixo)
945 GLVTable * const gl_vtable = gl_get_vtable();
950 gl_unbind_pixmap_object(pixo);
953 glDeleteTextures(1, &pixo->texture);
957 if (pixo->glx_pixmap) {
958 gl_vtable->glx_destroy_pixmap(pixo->dpy, pixo->glx_pixmap);
959 pixo->glx_pixmap = None;
963 XFreePixmap(pixo->dpy, pixo->pixmap);
970 * gl_bind_pixmap_object:
971 * @pixo: a #GLPixmapObject
973 * Defines a two-dimensional texture image. The texture image is taken
974 * from the @pixo pixmap and need not be copied. The texture target,
975 * format and size are derived from attributes of the @pixo pixmap.
977 * Return value: %TRUE on success
980 gl_bind_pixmap_object(GLPixmapObject *pixo)
982 GLVTable * const gl_vtable = gl_get_vtable();
987 if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
991 gl_vtable->glx_bind_tex_image(
997 XSync(pixo->dpy, False);
998 if (x11_untrap_errors() != 0) {
999 GST_DEBUG("failed to bind pixmap");
1003 pixo->is_bound = TRUE;
1008 * gl_unbind_pixmap_object:
1009 * @pixo: a #GLPixmapObject
1011 * Releases a color buffers that is being used as a texture.
1013 * Return value: %TRUE on success
1016 gl_unbind_pixmap_object(GLPixmapObject *pixo)
1018 GLVTable * const gl_vtable = gl_get_vtable();
1020 if (!pixo->is_bound)
1024 gl_vtable->glx_release_tex_image(
1029 XSync(pixo->dpy, False);
1030 if (x11_untrap_errors() != 0) {
1031 GST_DEBUG("failed to release pixmap");
1035 gl_unbind_texture(&pixo->old_texture);
1037 pixo->is_bound = FALSE;
1042 * gl_create_framebuffer_object:
1043 * @target: the target to which the texture is bound
1044 * @texture: the GL texture to hold the framebuffer
1045 * @width: the requested width, in pixels
1046 * @height: the requested height, in pixels
1048 * Creates an FBO with the specified texture and size.
1050 * Return value: the newly created #GLFramebufferObject, or %NULL if
1053 GLFramebufferObject *
1054 gl_create_framebuffer_object(
1061 GLVTable * const gl_vtable = gl_get_vtable();
1062 GLFramebufferObject *fbo;
1065 if (!gl_vtable || !gl_vtable->has_framebuffer_object)
1068 /* XXX: we only support GL_TEXTURE_2D at this time */
1069 if (target != GL_TEXTURE_2D)
1072 fbo = calloc(1, sizeof(*fbo));
1077 fbo->height = height;
1080 fbo->is_bound = FALSE;
1082 gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
1083 gl_vtable->gl_gen_framebuffers(1, &fbo->fbo);
1084 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
1085 gl_vtable->gl_framebuffer_texture_2d(
1087 GL_COLOR_ATTACHMENT0_EXT,
1092 status = gl_vtable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
1093 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
1094 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
1099 gl_destroy_framebuffer_object(fbo);
1104 * gl_destroy_framebuffer_object:
1105 * @fbo: a #GLFramebufferObject
1107 * Destroys the @fbo object.
1110 gl_destroy_framebuffer_object(GLFramebufferObject *fbo)
1112 GLVTable * const gl_vtable = gl_get_vtable();
1117 gl_unbind_framebuffer_object(fbo);
1120 gl_vtable->gl_delete_framebuffers(1, &fbo->fbo);
1127 * gl_bind_framebuffer_object:
1128 * @fbo: a #GLFramebufferObject
1130 * Binds @fbo object.
1132 * Return value: %TRUE on success
1135 gl_bind_framebuffer_object(GLFramebufferObject *fbo)
1137 GLVTable * const gl_vtable = gl_get_vtable();
1138 const guint width = fbo->width;
1139 const guint height = fbo->height;
1141 const guint attribs = (GL_VIEWPORT_BIT|
1145 GL_COLOR_BUFFER_BIT);
1150 gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
1151 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
1152 glPushAttrib(attribs);
1153 glMatrixMode(GL_PROJECTION);
1156 glMatrixMode(GL_MODELVIEW);
1159 glViewport(0, 0, width, height);
1160 glTranslatef(-1.0f, -1.0f, 0.0f);
1161 glScalef(2.0f / width, 2.0f / height, 1.0f);
1163 fbo->is_bound = TRUE;
1168 * gl_unbind_framebuffer_object:
1169 * @fbo: a #GLFramebufferObject
1171 * Releases @fbo object.
1173 * Return value: %TRUE on success
1176 gl_unbind_framebuffer_object(GLFramebufferObject *fbo)
1178 GLVTable * const gl_vtable = gl_get_vtable();
1184 glMatrixMode(GL_PROJECTION);
1186 glMatrixMode(GL_MODELVIEW);
1188 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
1190 fbo->is_bound = FALSE;