2 * gstvaapiutils_glx.c - GLX utilties
4 * gstreamer-vaapi (C) 2010 Splitted-Desktop Systems
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21 #define _GNU_SOURCE 1 /* RTLD_DEFAULT */
26 #include "gstvaapiutils_glx.h"
27 #include "gstvaapiutils_x11.h"
30 #include "gstvaapidebug.h"
32 /** Lookup for substring NAME in string EXT using SEP as separators */
34 find_string(const char *name, const char *ext, const char *sep)
42 end = ext + strlen(ext);
43 name_len = strlen(name);
45 n = strcspn(ext, sep);
46 if (n == name_len && strncmp(name, ext, n) == 0)
54 * gl_get_error_string:
55 * @error: an OpenGL error enumeration
57 * Retrieves the string representation the OpenGL @error.
59 * Return error: the static string representing the OpenGL @error
62 gl_get_error_string(GLenum error)
69 { GL_NO_ERROR, "no error" },
70 { GL_INVALID_ENUM, "invalid enumerant" },
71 { GL_INVALID_VALUE, "invalid value" },
72 { GL_INVALID_OPERATION, "invalid operation" },
73 { GL_STACK_OVERFLOW, "stack overflow" },
74 { GL_STACK_UNDERFLOW, "stack underflow" },
75 { GL_OUT_OF_MEMORY, "out of memory" },
76 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
77 { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
83 for (i = 0; gl_errors[i].str; i++) {
84 if (gl_errors[i].val == error)
85 return gl_errors[i].str;
93 * Purges all OpenGL errors. This function is generally useful to
94 * clear up the pending errors prior to calling gl_check_error().
99 while (glGetError() != GL_NO_ERROR)
106 * Checks whether there is any OpenGL error pending.
108 * Return value: %TRUE if an error was encountered
114 gboolean has_errors = FALSE;
116 while ((error = glGetError()) != GL_NO_ERROR) {
117 GST_DEBUG("glError: %s caught", gl_get_error_string(error));
125 * @param: the parameter name
126 * @pval: return location for the value
128 * This function is a wrapper around glGetIntegerv() that does extra
131 * Return value: %TRUE on success
134 gl_get_param(GLenum param, guint *pval)
139 glGetIntegerv(param, &val);
140 if (gl_check_error())
149 * gl_get_texture_param:
150 * @target: the target to which the texture is bound
151 * @param: the parameter name
152 * @pval: return location for the value
154 * This function is a wrapper around glGetTexLevelParameteriv() that
155 * does extra error checking.
157 * Return value: %TRUE on success
160 gl_get_texture_param(GLenum target, GLenum param, guint *pval)
165 glGetTexLevelParameteriv(target, 0, param, &val);
166 if (gl_check_error())
176 * @color: the requested RGB color
178 * Sets background color to the RGB @color. This basically is a
179 * wrapper around glClearColor().
182 gl_set_bgcolor(guint32 color)
185 ((color >> 16) & 0xff) / 255.0f,
186 ((color >> 8) & 0xff) / 255.0f,
187 ( color & 0xff) / 255.0f,
194 * @fovy: the field of view angle, in degrees, in the y direction
195 * @aspect: the aspect ratio that determines the field of view in the
196 * x direction. The aspect ratio is the ratio of x (width) to y
198 * @zNear: the distance from the viewer to the near clipping plane
200 * @zFar: the distance from the viewer to the far clipping plane
203 * Specified a viewing frustum into the world coordinate system. This
204 * basically is the Mesa implementation of gluPerspective().
207 frustum(GLdouble left, GLdouble right,
208 GLdouble bottom, GLdouble top,
209 GLdouble nearval, GLdouble farval)
211 GLdouble x, y, a, b, c, d;
214 x = (2.0 * nearval) / (right - left);
215 y = (2.0 * nearval) / (top - bottom);
216 a = (right + left) / (right - left);
217 b = (top + bottom) / (top - bottom);
218 c = -(farval + nearval) / ( farval - nearval);
219 d = -(2.0 * farval * nearval) / (farval - nearval);
221 #define M(row,col) m[col*4+row]
222 M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
223 M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
224 M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
225 M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
232 gl_perspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
234 GLdouble xmin, xmax, ymin, ymax;
236 ymax = zNear * tan(fovy * M_PI / 360.0);
238 xmin = ymin * aspect;
239 xmax = ymax * aspect;
241 /* Don't call glFrustum() because of error semantics (covglu) */
242 frustum(xmin, xmax, ymin, ymax, zNear, zFar);
247 * @width: the requested width, in pixels
248 * @height: the requested height, in pixels
250 * Resizes the OpenGL viewport to the specified dimensions, using an
251 * orthogonal projection. (0,0) represents the top-left corner of the
255 gl_resize(guint width, guint height)
261 #define Z_CAMERA 0.869f
263 glViewport(0, 0, width, height);
264 glMatrixMode(GL_PROJECTION);
266 gl_perspective(FOVY, ASPECT, Z_NEAR, Z_FAR);
267 glMatrixMode(GL_MODELVIEW);
270 glTranslatef(-0.5f, -0.5f, -Z_CAMERA);
271 glScalef(1.0f/width, -1.0f/height, 1.0f/width);
272 glTranslatef(0.0f, -1.0f*height, 0.0f);
277 * @dpy: an X11 #Display
278 * @screen: the associated screen of @dpy
279 * @parent: the parent #GLContextState, or %NULL if none is to be used
281 * Creates a GLX context sharing textures and displays lists with
282 * @parent, if not %NULL.
284 * Return value: the newly created GLX context
287 gl_create_context(Display *dpy, int screen, GLContextState *parent)
290 GLXFBConfig *fbconfigs = NULL;
291 int fbconfig_id, val, n, n_fbconfigs;
294 static GLint fbconfig_attrs[] = {
295 GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
296 GLX_RENDER_TYPE, GLX_RGBA_BIT,
297 GLX_DOUBLEBUFFER, True,
304 cs = malloc(sizeof(*cs));
309 cs->window = parent ? parent->window : None;
312 cs->swapped_buffers = FALSE;
314 if (parent && parent->context) {
315 status = glXQueryContext(
318 GLX_FBCONFIG_ID, &fbconfig_id
320 if (status != Success)
323 if (fbconfig_id == GLX_DONT_CARE)
324 goto choose_fbconfig;
326 fbconfigs = glXGetFBConfigs(dpy, screen, &n_fbconfigs);
330 /* Find out a GLXFBConfig compatible with the parent context */
331 for (n = 0; n < n_fbconfigs; n++) {
332 status = glXGetFBConfigAttrib(
335 GLX_FBCONFIG_ID, &val
337 if (status == Success && val == fbconfig_id)
340 if (n == n_fbconfigs)
345 fbconfigs = glXChooseFBConfig(
348 fbconfig_attrs, &n_fbconfigs
353 /* Select the first one */
357 cs->visual = glXGetVisualFromFBConfig(dpy, fbconfigs[n]);
358 cs->context = glXCreateNewContext(
362 parent ? parent->context : NULL,
369 gl_destroy_context(cs);
378 * gl_destroy_context:
379 * @cs: a #GLContextState
381 * Destroys the GLX context @cs
384 gl_destroy_context(GLContextState *cs)
394 if (cs->display && cs->context) {
395 if (glXGetCurrentContext() == cs->context) {
396 /* XXX: if buffers were never swapped, the application
397 will crash later with the NVIDIA driver */
398 if (!cs->swapped_buffers)
400 glXMakeCurrent(cs->display, None, NULL);
402 glXDestroyContext(cs->display, cs->context);
410 * gl_get_current_context:
411 * @cs: return location to the current #GLContextState
413 * Retrieves the current GLX context, display and drawable packed into
414 * the #GLContextState struct.
417 gl_get_current_context(GLContextState *cs)
419 cs->display = glXGetCurrentDisplay();
420 cs->window = glXGetCurrentDrawable();
421 cs->context = glXGetCurrentContext();
425 * gl_set_current_context:
426 * @new_cs: the requested new #GLContextState
427 * @old_cs: return location to the context that was previously current
429 * Makes the @new_cs GLX context the current GLX rendering context of
430 * the calling thread, replacing the previously current context if
433 * If @old_cs is non %NULL, the previously current GLX context and
434 * window are recorded.
436 * Return value: %TRUE on success
439 gl_set_current_context(GLContextState *new_cs, GLContextState *old_cs)
441 /* If display is NULL, this could be that new_cs was retrieved from
442 gl_get_current_context() with none set previously. If that case,
443 the other fields are also NULL and we don't return an error */
444 if (!new_cs->display)
445 return !new_cs->window && !new_cs->context;
448 if (old_cs == new_cs)
450 gl_get_current_context(old_cs);
451 if (old_cs->display == new_cs->display &&
452 old_cs->window == new_cs->window &&
453 old_cs->context == new_cs->context)
456 return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
461 * @cs: a #GLContextState
463 * Promotes the contents of the back buffer of the @win window to
464 * become the contents of the front buffer. This simply is wrapper
465 * around glXSwapBuffers().
468 gl_swap_buffers(GLContextState *cs)
470 glXSwapBuffers(cs->display, cs->window);
471 cs->swapped_buffers = TRUE;
476 * @ts: a #GLTextureState
477 * @target: the target to which the texture is bound
478 * @texture: the name of a texture
480 * Binds @texture to the specified @target, while recording the
481 * previous state in @ts.
483 * Return value: %TRUE on success
486 gl_bind_texture(GLTextureState *ts, GLenum target, GLuint texture)
491 ts->was_enabled = glIsEnabled(target);
492 if (!ts->was_enabled)
495 GLenum texture_binding;
498 texture_binding = GL_TEXTURE_BINDING_1D;
501 texture_binding = GL_TEXTURE_BINDING_2D;
504 texture_binding = GL_TEXTURE_BINDING_3D;
506 case GL_TEXTURE_RECTANGLE_ARB:
507 texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
514 if (!gl_get_param(texture_binding, &ts->old_texture))
517 ts->was_bound = texture == ts->old_texture;
518 if (!ts->was_bound) {
520 glBindTexture(target, texture);
521 if (gl_check_error())
529 * @ts: a #GLTextureState
531 * Rebinds the texture that was previously bound and recorded in @ts.
534 gl_unbind_texture(GLTextureState *ts)
536 if (!ts->was_bound && ts->old_texture)
537 glBindTexture(ts->target, ts->old_texture);
538 if (!ts->was_enabled)
539 glDisable(ts->target);
544 * @target: the target to which the texture is bound
545 * @format: the format of the pixel data
546 * @width: the requested width, in pixels
547 * @height: the requested height, in pixels
549 * Creates a texture with the specified dimensions and @format. The
550 * internal format will be automatically derived from @format.
552 * Return value: the newly created texture name
555 gl_create_texture(GLenum target, GLenum format, guint width, guint height)
557 GLenum internal_format;
560 guint bytes_per_component;
562 internal_format = format;
565 bytes_per_component = 1;
567 case GL_LUMINANCE_ALPHA:
568 bytes_per_component = 2;
572 internal_format = GL_RGBA;
573 bytes_per_component = 4;
576 bytes_per_component = 0;
579 g_assert(bytes_per_component > 0);
581 glGenTextures(1, &texture);
582 if (!gl_bind_texture(&ts, target, texture))
584 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
585 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
586 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
587 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
588 glPixelStorei(GL_UNPACK_ALIGNMENT, bytes_per_component);
599 gl_unbind_texture(&ts);
605 * @name: the name of the OpenGL extension function to lookup
607 * Returns the specified OpenGL extension function
609 * Return value: the OpenGL extension matching @name, or %NULL if none
612 typedef void (*GLFuncPtr)(void);
613 typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
616 get_proc_address_default(const char *name)
621 static GLXGetProcAddressProc
622 get_proc_address_func(void)
624 GLXGetProcAddressProc get_proc_func;
627 get_proc_func = (GLXGetProcAddressProc)
628 dlsym(RTLD_DEFAULT, "glXGetProcAddress");
630 return get_proc_func;
632 get_proc_func = (GLXGetProcAddressProc)
633 dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
635 return get_proc_func;
637 return get_proc_address_default;
640 static inline GLFuncPtr
641 get_proc_address(const char *name)
643 static GLXGetProcAddressProc get_proc_func = NULL;
645 get_proc_func = get_proc_address_func();
646 return get_proc_func(name);
652 * Initializes the global #GLVTable.
654 * Return value: the #GLVTable filled in with OpenGL extensions, or
657 static GLVTable gl_vtable_static;
662 GLVTable * const gl_vtable = &gl_vtable_static;
663 const gchar *gl_extensions = (const gchar *)glGetString(GL_EXTENSIONS);
664 gboolean has_extension;
666 /* GLX_EXT_texture_from_pixmap */
667 gl_vtable->glx_create_pixmap = (PFNGLXCREATEPIXMAPPROC)
668 get_proc_address("glXCreatePixmap");
669 if (!gl_vtable->glx_create_pixmap)
671 gl_vtable->glx_destroy_pixmap = (PFNGLXDESTROYPIXMAPPROC)
672 get_proc_address("glXDestroyPixmap");
673 if (!gl_vtable->glx_destroy_pixmap)
675 gl_vtable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
676 get_proc_address("glXBindTexImageEXT");
677 if (!gl_vtable->glx_bind_tex_image)
679 gl_vtable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
680 get_proc_address("glXReleaseTexImageEXT");
681 if (!gl_vtable->glx_release_tex_image)
684 /* GL_ARB_framebuffer_object */
686 find_string("GL_ARB_framebuffer_object", gl_extensions, " ") ||
687 find_string("GL_EXT_framebuffer_object", gl_extensions, " ")
690 gl_vtable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
691 get_proc_address("glGenFramebuffersEXT");
692 if (!gl_vtable->gl_gen_framebuffers)
694 gl_vtable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
695 get_proc_address("glDeleteFramebuffersEXT");
696 if (!gl_vtable->gl_delete_framebuffers)
698 gl_vtable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
699 get_proc_address("glBindFramebufferEXT");
700 if (!gl_vtable->gl_bind_framebuffer)
702 gl_vtable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
703 get_proc_address("glGenRenderbuffersEXT");
704 if (!gl_vtable->gl_gen_renderbuffers)
706 gl_vtable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
707 get_proc_address("glDeleteRenderbuffersEXT");
708 if (!gl_vtable->gl_delete_renderbuffers)
710 gl_vtable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
711 get_proc_address("glBindRenderbufferEXT");
712 if (!gl_vtable->gl_bind_renderbuffer)
714 gl_vtable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
715 get_proc_address("glRenderbufferStorageEXT");
716 if (!gl_vtable->gl_renderbuffer_storage)
718 gl_vtable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
719 get_proc_address("glFramebufferRenderbufferEXT");
720 if (!gl_vtable->gl_framebuffer_renderbuffer)
722 gl_vtable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
723 get_proc_address("glFramebufferTexture2DEXT");
724 if (!gl_vtable->gl_framebuffer_texture_2d)
726 gl_vtable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
727 get_proc_address("glCheckFramebufferStatusEXT");
728 if (!gl_vtable->gl_check_framebuffer_status)
730 gl_vtable->has_framebuffer_object = TRUE;
733 /* GL_ARB_fragment_program */
735 find_string("GL_ARB_fragment_program", gl_extensions, " ")
738 gl_vtable->gl_gen_programs = (PFNGLGENPROGRAMSARBPROC)
739 get_proc_address("glGenProgramsARB");
740 if (!gl_vtable->gl_gen_programs)
742 gl_vtable->gl_delete_programs = (PFNGLDELETEPROGRAMSARBPROC)
743 get_proc_address("glDeleteProgramsARB");
744 if (!gl_vtable->gl_delete_programs)
746 gl_vtable->gl_bind_program = (PFNGLBINDPROGRAMARBPROC)
747 get_proc_address("glBindProgramARB");
748 if (!gl_vtable->gl_bind_program)
750 gl_vtable->gl_program_string = (PFNGLPROGRAMSTRINGARBPROC)
751 get_proc_address("glProgramStringARB");
752 if (!gl_vtable->gl_program_string)
754 gl_vtable->gl_get_program_iv = (PFNGLGETPROGRAMIVARBPROC)
755 get_proc_address("glGetProgramivARB");
756 if (!gl_vtable->gl_get_program_iv)
758 gl_vtable->gl_program_local_parameter_4fv = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)
759 get_proc_address("glProgramLocalParameter4fvARB");
760 if (!gl_vtable->gl_program_local_parameter_4fv)
762 gl_vtable->has_fragment_program = TRUE;
765 /* GL_ARB_multitexture */
767 find_string("GL_ARB_multitexture", gl_extensions, " ")
770 gl_vtable->gl_active_texture = (PFNGLACTIVETEXTUREPROC)
771 get_proc_address("glActiveTextureARB");
772 if (!gl_vtable->gl_active_texture)
774 gl_vtable->gl_multi_tex_coord_2f = (PFNGLMULTITEXCOORD2FPROC)
775 get_proc_address("glMultiTexCoord2fARB");
776 if (!gl_vtable->gl_multi_tex_coord_2f)
778 gl_vtable->has_multitexture = TRUE;
786 * Retrieves a VTable for OpenGL extensions.
788 * Return value: VTable for OpenGL extensions
793 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
794 static gboolean gl_vtable_init = TRUE;
795 static GLVTable *gl_vtable = NULL;
797 g_static_mutex_lock(&mutex);
798 if (gl_vtable_init) {
799 gl_vtable_init = FALSE;
800 gl_vtable = gl_init_vtable();
802 g_static_mutex_unlock(&mutex);
807 * gl_create_pixmap_object:
808 * @dpy: an X11 #Display
809 * @width: the request width, in pixels
810 * @height: the request height, in pixels
812 * Creates a #GLPixmapObject of the specified dimensions. This
813 * requires the GLX_EXT_texture_from_pixmap extension.
815 * Return value: the newly created #GLPixmapObject object
818 gl_create_pixmap_object(Display *dpy, guint width, guint height)
820 GLVTable * const gl_vtable = gl_get_vtable();
821 GLPixmapObject *pixo;
822 GLXFBConfig *fbconfig;
825 XWindowAttributes wattr;
827 int n_fbconfig_attrs;
829 int fbconfig_attrs[32] = {
830 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
831 GLX_DOUBLEBUFFER, GL_FALSE,
832 GLX_RENDER_TYPE, GLX_RGBA_BIT,
833 GLX_X_RENDERABLE, GL_TRUE,
834 GLX_Y_INVERTED_EXT, GL_TRUE,
841 int pixmap_attrs[10] = {
842 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
843 GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
850 screen = DefaultScreen(dpy);
851 rootwin = RootWindow(dpy, screen);
853 /* XXX: this won't work for different displays */
854 if (!gl_vtable->has_texture_from_pixmap) {
855 const char *glx_extensions = glXQueryExtensionsString(dpy, screen);
858 if (!find_string("GLX_EXT_texture_from_pixmap", glx_extensions, " "))
860 gl_vtable->has_texture_from_pixmap = TRUE;
863 pixo = calloc(1, sizeof(*pixo));
869 pixo->height = height;
871 pixo->glx_pixmap = None;
872 pixo->is_bound = FALSE;
874 XGetWindowAttributes(dpy, rootwin, &wattr);
875 pixo->pixmap = XCreatePixmap(dpy, rootwin, width, height, wattr.depth);
879 /* Initialize FBConfig attributes */
880 for (attr = fbconfig_attrs; *attr != GL_NONE; attr += 2)
882 *attr++ = GLX_DEPTH_SIZE; *attr++ = wattr.depth;
883 if (wattr.depth == 32) {
884 *attr++ = GLX_ALPHA_SIZE; *attr++ = 8;
885 *attr++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attr++ = GL_TRUE;
888 *attr++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attr++ = GL_TRUE;
892 fbconfig = glXChooseFBConfig(
895 fbconfig_attrs, &n_fbconfig_attrs
900 /* Initialize GLX Pixmap attributes */
901 for (attr = pixmap_attrs; *attr != GL_NONE; attr += 2)
903 *attr++ = GLX_TEXTURE_FORMAT_EXT;
904 if (wattr.depth == 32)
905 *attr++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
907 *attr++ = GLX_TEXTURE_FORMAT_RGB_EXT;
911 pixo->glx_pixmap = gl_vtable->glx_create_pixmap(
918 if (x11_untrap_errors() != 0)
921 pixo->target = GL_TEXTURE_2D;
922 glGenTextures(1, &pixo->texture);
923 if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
925 glTexParameteri(pixo->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
926 glTexParameteri(pixo->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
927 gl_unbind_texture(&pixo->old_texture);
931 gl_destroy_pixmap_object(pixo);
936 * gl_destroy_pixmap_object:
937 * @pixo: a #GLPixmapObject
939 * Destroys the #GLPixmapObject object.
942 gl_destroy_pixmap_object(GLPixmapObject *pixo)
944 GLVTable * const gl_vtable = gl_get_vtable();
949 gl_unbind_pixmap_object(pixo);
952 glDeleteTextures(1, &pixo->texture);
956 if (pixo->glx_pixmap) {
957 gl_vtable->glx_destroy_pixmap(pixo->dpy, pixo->glx_pixmap);
958 pixo->glx_pixmap = None;
962 XFreePixmap(pixo->dpy, pixo->pixmap);
969 * gl_bind_pixmap_object:
970 * @pixo: a #GLPixmapObject
972 * Defines a two-dimensional texture image. The texture image is taken
973 * from the @pixo pixmap and need not be copied. The texture target,
974 * format and size are derived from attributes of the @pixo pixmap.
976 * Return value: %TRUE on success
979 gl_bind_pixmap_object(GLPixmapObject *pixo)
981 GLVTable * const gl_vtable = gl_get_vtable();
986 if (!gl_bind_texture(&pixo->old_texture, pixo->target, pixo->texture))
990 gl_vtable->glx_bind_tex_image(
996 XSync(pixo->dpy, False);
997 if (x11_untrap_errors() != 0) {
998 GST_DEBUG("failed to bind pixmap");
1002 pixo->is_bound = TRUE;
1007 * gl_unbind_pixmap_object:
1008 * @pixo: a #GLPixmapObject
1010 * Releases a color buffers that is being used as a texture.
1012 * Return value: %TRUE on success
1015 gl_unbind_pixmap_object(GLPixmapObject *pixo)
1017 GLVTable * const gl_vtable = gl_get_vtable();
1019 if (!pixo->is_bound)
1023 gl_vtable->glx_release_tex_image(
1028 XSync(pixo->dpy, False);
1029 if (x11_untrap_errors() != 0) {
1030 GST_DEBUG("failed to release pixmap");
1034 gl_unbind_texture(&pixo->old_texture);
1036 pixo->is_bound = FALSE;
1041 * gl_create_framebuffer_object:
1042 * @target: the target to which the texture is bound
1043 * @texture: the GL texture to hold the framebuffer
1044 * @width: the requested width, in pixels
1045 * @height: the requested height, in pixels
1047 * Creates an FBO with the specified texture and size.
1049 * Return value: the newly created #GLFramebufferObject, or %NULL if
1052 GLFramebufferObject *
1053 gl_create_framebuffer_object(
1060 GLVTable * const gl_vtable = gl_get_vtable();
1061 GLFramebufferObject *fbo;
1064 if (!gl_vtable || !gl_vtable->has_framebuffer_object)
1067 /* XXX: we only support GL_TEXTURE_2D at this time */
1068 if (target != GL_TEXTURE_2D)
1071 fbo = calloc(1, sizeof(*fbo));
1076 fbo->height = height;
1079 fbo->is_bound = FALSE;
1081 gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
1082 gl_vtable->gl_gen_framebuffers(1, &fbo->fbo);
1083 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
1084 gl_vtable->gl_framebuffer_texture_2d(
1086 GL_COLOR_ATTACHMENT0_EXT,
1091 status = gl_vtable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
1092 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
1093 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
1098 gl_destroy_framebuffer_object(fbo);
1103 * gl_destroy_framebuffer_object:
1104 * @fbo: a #GLFramebufferObject
1106 * Destroys the @fbo object.
1109 gl_destroy_framebuffer_object(GLFramebufferObject *fbo)
1111 GLVTable * const gl_vtable = gl_get_vtable();
1116 gl_unbind_framebuffer_object(fbo);
1119 gl_vtable->gl_delete_framebuffers(1, &fbo->fbo);
1126 * gl_bind_framebuffer_object:
1127 * @fbo: a #GLFramebufferObject
1129 * Binds @fbo object.
1131 * Return value: %TRUE on success
1134 gl_bind_framebuffer_object(GLFramebufferObject *fbo)
1136 GLVTable * const gl_vtable = gl_get_vtable();
1137 const guint width = fbo->width;
1138 const guint height = fbo->height;
1140 const guint attribs = (GL_VIEWPORT_BIT|
1144 GL_COLOR_BUFFER_BIT);
1149 gl_get_param(GL_FRAMEBUFFER_BINDING, &fbo->old_fbo);
1150 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->fbo);
1151 glPushAttrib(attribs);
1152 glMatrixMode(GL_PROJECTION);
1155 glMatrixMode(GL_MODELVIEW);
1158 glViewport(0, 0, width, height);
1159 glTranslatef(-1.0f, -1.0f, 0.0f);
1160 glScalef(2.0f / width, 2.0f / height, 1.0f);
1162 fbo->is_bound = TRUE;
1167 * gl_unbind_framebuffer_object:
1168 * @fbo: a #GLFramebufferObject
1170 * Releases @fbo object.
1172 * Return value: %TRUE on success
1175 gl_unbind_framebuffer_object(GLFramebufferObject *fbo)
1177 GLVTable * const gl_vtable = gl_get_vtable();
1183 glMatrixMode(GL_PROJECTION);
1185 glMatrixMode(GL_MODELVIEW);
1187 gl_vtable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo->old_fbo);
1189 fbo->is_bound = FALSE;