aboutsummaryrefslogtreecommitdiffstats
path: root/meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch')
-rw-r--r--meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch2024
1 files changed, 2024 insertions, 0 deletions
diff --git a/meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch b/meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch
new file mode 100644
index 00000000..ccd9ae09
--- /dev/null
+++ b/meta-emenlow/recipes-graphics/libva/libva-0.31.0/322_libva_glx.patch
@@ -0,0 +1,2024 @@
+commit 8e76000abce070da5f1c902a6290f4ccaa3eccc8
+Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
+Date: Fri Sep 18 15:51:08 2009 +0000
+
+ Add C++ guards.
+
+commit bf1ae22ef324fbb347f5369e1ba307e847553fe8
+Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
+Date: Fri Sep 18 15:49:55 2009 +0000
+
+ Fix check for GL extensions.
+
+commit df0953a951d8a2e5e4b0a28a95ae0f1ac735726e
+Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
+Date: Tue Sep 8 12:25:14 2009 +0000
+
+ Add generic VA/GLX implementation with TFP and FBO.
+
+commit f640b1cf9eab4e5d478239b608ed0d8b68f6c5f6
+Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
+Date: Tue Sep 8 12:15:35 2009 +0000
+
+ Move GLX VTable to a new file.
+
+commit 70d9cb6d1aa2fc2dde6646f3b692433e0d93d431
+Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
+Date: Fri Aug 28 11:15:51 2009 +0000
+
+ Add OpenGL extensions (v3).
+
+diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am
+new file mode 100644
+index 0000000..7783d8c
+--- /dev/null
++++ b/src/glx/Makefile.am
+@@ -0,0 +1,41 @@
++# Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++#
++# Permission is hereby granted, free of charge, to any person obtaining a
++# copy of this software and associated documentation files (the
++# "Software"), to deal in the Software without restriction, including
++# without limitation the rights to use, copy, modify, merge, publish,
++# distribute, sub license, and/or sell copies of the Software, and to
++# permit persons to whom the Software is furnished to do so, subject to
++# the following conditions:
++#
++# The above copyright notice and this permission notice (including the
++# next paragraph) shall be included in all copies or substantial portions
++# of the Software.
++#
++# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++
++AM_CFLAGS = -DLINUX -DIN_LIBVA -I$(top_srcdir)/src -I$(top_srcdir)/src/x11
++
++source_c = \
++ va_glx.c \
++ va_glx_impl.c
++
++source_h = \
++ va_glx.h \
++ va_backend_glx.h
++
++source_h_priv = \
++ va_glx_impl.h \
++ va_glx_private.h
++
++noinst_LTLIBRARIES = libva_glx.la
++libva_glxincludedir = ${includedir}/va
++libva_glxinclude_HEADERS = $(source_h)
++libva_glx_la_SOURCES = $(source_c)
++noinst_HEADERS = $(source_h_priv)
+diff --git a/src/glx/va_backend_glx.h b/src/glx/va_backend_glx.h
+new file mode 100644
+index 0000000..3885d30
+--- /dev/null
++++ b/src/glx/va_backend_glx.h
+@@ -0,0 +1,87 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef VA_BACKEND_GLX_H
++#define VA_BACKEND_GLX_H
++
++struct VADriverContext;
++
++struct VADriverVTableGLX {
++ /* Optional: create a surface used for display to OpenGL */
++ VAStatus (*vaCreateSurfaceGLX)(
++ struct VADriverContext *ctx,
++ unsigned int gl_target,
++ unsigned int gl_texture,
++ void **gl_surface
++ );
++
++ /* Optional: destroy a VA/GLX surface */
++ VAStatus (*vaDestroySurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface
++ );
++
++ /* Optional: associate a VA surface to a VA/GLX surface */
++ VAStatus (*vaAssociateSurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++ );
++
++ /* Optional: deassociate a VA surface from a VA/GLX surface */
++ VAStatus (*vaDeassociateSurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface
++ );
++
++ /* Optional: synchronize a VA/GLX surface */
++ VAStatus (*vaSyncSurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface
++ );
++
++ /* Optional: prepare VA/GLX surface for rendering */
++ VAStatus (*vaBeginRenderSurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface
++ );
++
++ /* Optional: notify the server that the VA/GLX surface is no
++ longer used for rendering */
++ VAStatus (*vaEndRenderSurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface
++ );
++
++ /* Optional: copy a VA surface to a VA/GLX surface */
++ VAStatus (*vaCopySurfaceGLX)(
++ struct VADriverContext *ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++ );
++};
++
++#endif /* VA_BACKEND_GLX_H */
+diff --git a/src/glx/va_glx.c b/src/glx/va_glx.c
+new file mode 100644
+index 0000000..f6ec2c3
+--- /dev/null
++++ b/src/glx/va_glx.c
+@@ -0,0 +1,295 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#include "va_glx_private.h"
++#include "va_glx_impl.h"
++
++#define INIT_CONTEXT(ctx, dpy) do { \
++ if (!vaDisplayIsValid(dpy)) \
++ return VA_STATUS_ERROR_INVALID_DISPLAY; \
++ \
++ ctx = ((VADisplayContextP)(dpy))->pDriverContext; \
++ if (!(ctx)) \
++ return VA_STATUS_ERROR_INVALID_DISPLAY; \
++ \
++ VAStatus status = va_glx_init_context(ctx); \
++ if (status != VA_STATUS_SUCCESS) \
++ return status; \
++ } while (0)
++
++#define INIT_SURFACE(surface, surface_arg) do { \
++ surface = (VASurfaceGLXP)(surface_arg); \
++ if (!vaSurfaceIsValid(surface)) \
++ return VA_STATUS_ERROR_INVALID_SURFACE; \
++ } while (0)
++
++#define INVOKE(ctx, func, args) do { \
++ VADriverVTableGLXP vtable; \
++ vtable = &VA_DRIVER_CONTEXT_GLX(ctx)->vtable; \
++ if (!vtable->va##func##GLX) \
++ return VA_STATUS_ERROR_UNIMPLEMENTED; \
++ status = vtable->va##func##GLX args; \
++ } while (0)
++
++// Check VADisplay is valid
++static inline int vaDisplayIsValid(VADisplay dpy)
++{
++ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
++
++ return (pDisplayContext &&
++ pDisplayContext->vaIsValid &&
++ pDisplayContext->vaIsValid(pDisplayContext));
++}
++
++// Check VASurfaceGLX is valid
++static inline int vaSurfaceIsValid(VASurfaceGLXP pSurfaceGLX)
++{
++ return pSurfaceGLX && pSurfaceGLX->magic == VA_SURFACE_GLX_MAGIC;
++}
++
++// Destroy VA/GLX display context
++static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
++{
++ VADisplayContextGLXP pDisplayContextGLX;
++ VADriverContextP pDriverContext;
++ VADriverContextGLXP pDriverContextGLX;
++
++ if (!pDisplayContext)
++ return;
++
++ pDriverContext = pDisplayContext->pDriverContext;
++ pDriverContextGLX = pDriverContext->glx;
++ if (pDriverContextGLX) {
++ free(pDriverContextGLX);
++ pDriverContext->glx = NULL;
++ }
++
++ pDisplayContextGLX = pDisplayContext->opaque;
++ if (pDisplayContextGLX) {
++ if (pDisplayContextGLX->vaDestroy)
++ pDisplayContextGLX->vaDestroy(pDisplayContext);
++ free(pDisplayContextGLX);
++ pDisplayContext->opaque = NULL;
++ }
++}
++
++// Return a suitable VADisplay for VA API
++VADisplay vaGetDisplayGLX(Display *native_dpy)
++{
++ VADisplay dpy = NULL;
++ VADisplayContextP pDisplayContext = NULL;
++ VADisplayContextGLXP pDisplayContextGLX = NULL;
++ VADriverContextP pDriverContext;
++ VADriverContextGLXP pDriverContextGLX = NULL;
++
++ dpy = vaGetDisplay(native_dpy);
++ if (!dpy)
++ return NULL;
++ pDisplayContext = (VADisplayContextP)dpy;
++ pDriverContext = pDisplayContext->pDriverContext;
++
++ pDisplayContextGLX = calloc(1, sizeof(*pDisplayContextGLX));
++ if (!pDisplayContextGLX)
++ goto error;
++
++ pDriverContextGLX = calloc(1, sizeof(*pDriverContextGLX));
++ if (!pDriverContextGLX)
++ goto error;
++
++ pDisplayContextGLX->vaDestroy = pDisplayContext->vaDestroy;
++ pDisplayContext->vaDestroy = va_DisplayContextDestroy;
++ pDisplayContext->opaque = pDisplayContextGLX;
++ pDriverContext->glx = pDriverContextGLX;
++ return dpy;
++
++error:
++ free(pDriverContextGLX);
++ free(pDisplayContextGLX);
++ pDisplayContext->vaDestroy(pDisplayContext);
++ return NULL;
++}
++
++// Create a surface used for display to OpenGL
++VAStatus vaCreateSurfaceGLX(
++ VADisplay dpy,
++ GLenum target,
++ GLuint texture,
++ void **gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ /* Make sure it is a valid GL texture object */
++ if (!glIsTexture(texture))
++ return VA_STATUS_ERROR_INVALID_PARAMETER;
++
++ INIT_CONTEXT(ctx, dpy);
++
++ pSurfaceGLX = va_glx_create_surface(ctx, target, texture);
++ if (!pSurfaceGLX)
++ return VA_STATUS_ERROR_ALLOCATION_FAILED;
++
++ INVOKE(ctx, CreateSurface, (ctx, target, texture, &pSurfaceGLX->priv));
++
++ if (status != VA_STATUS_SUCCESS)
++ va_glx_destroy_surface(ctx, &pSurfaceGLX);
++
++ *gl_surface = pSurfaceGLX;
++ return status;
++}
++
++// Destroy a VA/GLX surface
++VAStatus vaDestroySurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, DestroySurface, (ctx, pSurfaceGLX));
++
++ free(pSurfaceGLX);
++ return status;
++}
++
++// Associate a VA surface to a VA/GLX surface
++VAStatus vaAssociateSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, AssociateSurface, (ctx, pSurfaceGLX, surface, flags));
++
++ if (status == VA_STATUS_SUCCESS)
++ pSurfaceGLX->surface = surface;
++
++ return status;
++}
++
++// Deassociate a VA surface from a VA/GLX surface
++VAStatus vaDeassociateSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, DeassociateSurface, (ctx, pSurfaceGLX));
++
++ if (status == VA_STATUS_SUCCESS)
++ pSurfaceGLX->surface = VA_INVALID_SURFACE;
++
++ return status;
++}
++
++// Synchronize a VA/GLX surface
++VAStatus vaSyncSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, SyncSurface, (ctx, pSurfaceGLX));
++ return status;
++}
++
++// Prepare VA/GLX surface for rendering
++VAStatus vaBeginRenderSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, BeginRenderSurface, (ctx, pSurfaceGLX));
++ return status;
++}
++
++// Notify the server that the VA/GLX surface is no longer used for rendering
++VAStatus vaEndRenderSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, EndRenderSurface, (ctx, pSurfaceGLX));
++ return status;
++}
++
++// Copy a VA surface to a VA/GLX surface
++VAStatus vaCopySurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VADriverContextP ctx;
++ VASurfaceGLXP pSurfaceGLX;
++ VAStatus status;
++
++ INIT_CONTEXT(ctx, dpy);
++ INIT_SURFACE(pSurfaceGLX, gl_surface);
++
++ INVOKE(ctx, CopySurface, (ctx, pSurfaceGLX, surface, flags));
++ return status;
++}
+diff --git a/src/glx/va_glx.h b/src/glx/va_glx.h
+new file mode 100644
+index 0000000..183ef3a
+--- /dev/null
++++ b/src/glx/va_glx.h
+@@ -0,0 +1,217 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef VA_GLX_H
++#define VA_GLX_H
++
++#ifdef IN_LIBVA
++#include "va.h"
++#else
++#include <va/va.h>
++#endif
++#include <GL/glx.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Return a suitable VADisplay for VA API
++ *
++ * @param[in] dpy the X11 display
++ * @return a VADisplay
++ */
++VADisplay vaGetDisplayGLX(
++ Display *dpy
++);
++
++/**
++ * Create a surface used for display to OpenGL
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] target the GL target to which the texture needs to be bound
++ * @param[in] texture the GL texture
++ * @param[out] gl_surface the VA/GLX surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaCreateSurfaceGLX(
++ VADisplay dpy,
++ GLenum target,
++ GLuint texture,
++ void **gl_surface
++);
++
++/**
++ * Destroy a VA/GLX surface
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaDestroySurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++);
++
++/**
++ * Associate a VA surface to a VA/GLX surface
++ *
++ * The association is live until vaDeassociateSurfaceGLX(),
++ * vaCopySurfaceGLX() or the next call to vaBeginPicture() with the
++ * specificed VA surface.
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA/GLX surface
++ * @param[in] surface the VA surface
++ * @param[in] flags the PutSurface flags
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaAssociateSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++);
++
++/**
++ * Deassociate a VA surface from a VA/GLX surface
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaDeassociateSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++);
++
++/**
++ * Synchronize a VA/GLX surface
++ *
++ * This function blocks until all pending operations on the VA/GLX
++ * surface have been completed.
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaSyncSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++);
++
++/**
++ * Prepare VA/GLX surface for rendering
++ *
++ * This function performs an implicit vaSyncSurfaceGLX().
++ *
++ * Implementations using the GLX texture-from-pixmap extension will
++ * generally call glXBindTexImage() here.
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaBeginRenderSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++);
++
++/**
++ * Notify the server that the VA/GLX surface is no longer used for
++ * rendering
++ *
++ * Implementations using the GLX texture-from-pixmap extension will
++ * generally call glXReleaseTexImage() here.
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA surface
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaEndRenderSurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface
++);
++
++/**
++ * Copy a VA surface to a VA/GLX surface
++ *
++ * This function kills any association that was previously made with
++ * vaAssociateSurfaceGLX() and will not return until the copy is
++ * completed.
++ *
++ * Upon successful return, the underlying GL texture will contain the
++ * complete pixels and no call to vaBeginRenderSurfaceGLX() or
++ * vaEndRenderSurfaceGLX() is required.
++ *
++ * The application shall maintain the live GLX context itself.
++ * Implementations are free to use glXGetCurrentContext() and
++ * glXGetCurrentDrawable() functions for internal purposes.
++ *
++ * @param[in] dpy the VA display
++ * @param[in] gl_surface the VA/GLX destination surface
++ * @param[in] surface the VA source surface
++ * @param[in] flags the PutSurface flags
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus vaCopySurfaceGLX(
++ VADisplay dpy,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* VA_GLX_H */
+diff --git a/src/glx/va_glx_impl.c b/src/glx/va_glx_impl.c
+new file mode 100644
+index 0000000..d4f9c1d
+--- /dev/null
++++ b/src/glx/va_glx_impl.c
+@@ -0,0 +1,1168 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#define _GNU_SOURCE 1
++#include "va_glx_private.h"
++#include "va_glx_impl.h"
++#include <stdio.h>
++#include <stdarg.h>
++#include <string.h>
++#include <assert.h>
++#include <dlfcn.h>
++
++static void va_glx_error_message(const char *format, ...)
++{
++ va_list args;
++ va_start(args, format);
++ fprintf(stderr, "[%s] ", PACKAGE_NAME);
++ vfprintf(stderr, format, args);
++ va_end(args);
++}
++
++// X error trap
++static int x11_error_code = 0;
++static int (*old_error_handler)(Display *, XErrorEvent *);
++
++static int error_handler(Display *dpy, XErrorEvent *error)
++{
++ x11_error_code = error->error_code;
++ return 0;
++}
++
++static void x11_trap_errors(void)
++{
++ x11_error_code = 0;
++ old_error_handler = XSetErrorHandler(error_handler);
++}
++
++static int x11_untrap_errors(void)
++{
++ XSetErrorHandler(old_error_handler);
++ return x11_error_code;
++}
++
++// Returns a string representation of an OpenGL error
++static const char *gl_get_error_string(GLenum error)
++{
++ static const struct {
++ GLenum val;
++ const char *str;
++ }
++ gl_errors[] = {
++ { GL_NO_ERROR, "no error" },
++ { GL_INVALID_ENUM, "invalid enumerant" },
++ { GL_INVALID_VALUE, "invalid value" },
++ { GL_INVALID_OPERATION, "invalid operation" },
++ { GL_STACK_OVERFLOW, "stack overflow" },
++ { GL_STACK_UNDERFLOW, "stack underflow" },
++ { GL_OUT_OF_MEMORY, "out of memory" },
++#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
++ { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
++#endif
++ { ~0, NULL }
++ };
++
++ int i;
++ for (i = 0; gl_errors[i].str; i++) {
++ if (gl_errors[i].val == error)
++ return gl_errors[i].str;
++ }
++ return "unknown";
++}
++
++static inline int gl_do_check_error(int report)
++{
++ GLenum error;
++ int is_error = 0;
++ while ((error = glGetError()) != GL_NO_ERROR) {
++ if (report)
++ va_glx_error_message("glError: %s caught\n",
++ gl_get_error_string(error));
++ is_error = 1;
++ }
++ return is_error;
++}
++
++static inline void gl_purge_errors(void)
++{
++ gl_do_check_error(0);
++}
++
++static inline int gl_check_error(void)
++{
++ return gl_do_check_error(1);
++}
++
++// glGetFloatv() wrapper
++static int gl_get_current_color(float color[4])
++{
++ gl_purge_errors();
++ glGetFloatv(GL_CURRENT_COLOR, color);
++ if (gl_check_error())
++ return -1;
++ return 0;
++}
++
++// glGetIntegerv() wrapper
++static int gl_get_param(GLenum param, unsigned int *pval)
++{
++ GLint val;
++
++ gl_purge_errors();
++ glGetIntegerv(param, &val);
++ if (gl_check_error())
++ return -1;
++ if (pval)
++ *pval = val;
++ return 0;
++}
++
++// glGetTexLevelParameteriv() wrapper
++static int gl_get_texture_param(GLenum param, unsigned int *pval)
++{
++ GLint val;
++
++ gl_purge_errors();
++ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, param, &val);
++ if (gl_check_error())
++ return -1;
++ if (pval)
++ *pval = val;
++ return 0;
++}
++
++// Returns the OpenGL VTable
++static inline VAOpenGLVTableP gl_get_vtable(VADriverContextP ctx)
++{
++ return &VA_DRIVER_CONTEXT_GLX(ctx)->gl_vtable;
++}
++
++// Lookup for a GLX function
++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() == NULL)
++ return get_proc_func;
++
++ get_proc_func = (GLXGetProcAddressProc)
++ dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
++ if (dlerror() == NULL)
++ 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 == NULL)
++ get_proc_func = get_proc_address_func();
++ return get_proc_func(name);
++}
++
++// Check for GLX extensions (TFP, FBO)
++static int check_extension(const char *name, const char *ext)
++{
++ const char *end;
++ int name_len, n;
++
++ if (name == NULL || ext == NULL)
++ return 0;
++
++ end = ext + strlen(ext);
++ name_len = strlen(name);
++ while (ext < end) {
++ n = strcspn(ext, " ");
++ if (n == name_len && strncmp(name, ext, n) == 0)
++ return 1;
++ ext += (n + 1);
++ }
++ return 0;
++}
++
++static int check_tfp_extensions(VADriverContextP ctx)
++{
++ const char *gl_extensions;
++ const char *glx_extensions;
++
++ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
++ if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions))
++ return 0;
++
++ glx_extensions = glXQueryExtensionsString(ctx->x11_dpy, ctx->x11_screen);
++ if (!check_extension("GLX_EXT_texture_from_pixmap", glx_extensions))
++ return 0;
++ return 1;
++}
++
++static int check_fbo_extensions(VADriverContextP ctx)
++{
++ const char *gl_extensions;
++
++ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
++ if (!check_extension("GL_ARB_framebuffer_object", gl_extensions))
++ return 0;
++ if (!check_extension("GL_EXT_framebuffer_object", gl_extensions))
++ return 0;
++ return 1;
++}
++
++// Load GLX extensions
++static int load_tfp_extensions(VADriverContextP ctx)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ pOpenGLVTable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
++ get_proc_address("glXBindTexImageEXT");
++ if (pOpenGLVTable->glx_bind_tex_image == NULL)
++ return 0;
++ pOpenGLVTable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
++ get_proc_address("glXReleaseTexImageEXT");
++ if (pOpenGLVTable->glx_release_tex_image == NULL)
++ return 0;
++ return 1;
++}
++
++static int load_fbo_extensions(VADriverContextP ctx)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ pOpenGLVTable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
++ get_proc_address("glGenFramebuffersEXT");
++ if (pOpenGLVTable->gl_gen_framebuffers == NULL)
++ return 0;
++ pOpenGLVTable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
++ get_proc_address("glDeleteFramebuffersEXT");
++ if (pOpenGLVTable->gl_delete_framebuffers == NULL)
++ return 0;
++ pOpenGLVTable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
++ get_proc_address("glBindFramebufferEXT");
++ if (pOpenGLVTable->gl_bind_framebuffer == NULL)
++ return 0;
++ pOpenGLVTable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
++ get_proc_address("glGenRenderbuffersEXT");
++ if (pOpenGLVTable->gl_gen_renderbuffers == NULL)
++ return 0;
++ pOpenGLVTable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
++ get_proc_address("glDeleteRenderbuffersEXT");
++ if (pOpenGLVTable->gl_delete_renderbuffers == NULL)
++ return 0;
++ pOpenGLVTable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
++ get_proc_address("glBindRenderbufferEXT");
++ if (pOpenGLVTable->gl_bind_renderbuffer == NULL)
++ return 0;
++ pOpenGLVTable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
++ get_proc_address("glRenderbufferStorageEXT");
++ if (pOpenGLVTable->gl_renderbuffer_storage == NULL)
++ return 0;
++ pOpenGLVTable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
++ get_proc_address("glFramebufferRenderbufferEXT");
++ if (pOpenGLVTable->gl_framebuffer_renderbuffer == NULL)
++ return 0;
++ pOpenGLVTable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
++ get_proc_address("glFramebufferTexture2DEXT");
++ if (pOpenGLVTable->gl_framebuffer_texture_2d == NULL)
++ return 0;
++ pOpenGLVTable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
++ get_proc_address("glCheckFramebufferStatusEXT");
++ if (pOpenGLVTable->gl_check_framebuffer_status == NULL)
++ return 0;
++ return 1;
++}
++
++
++/* ========================================================================= */
++/* === VA/GLX helpers === */
++/* ========================================================================= */
++
++// OpenGL texture state
++typedef struct OpenGLTextureState *OpenGLTextureStateP;
++
++struct OpenGLTextureState {
++ int was_enabled;
++ int was_bound;
++ GLenum target;
++ GLuint old_texture;
++};
++
++// Bind texture, preserve previous texture state
++static int bind_texture(OpenGLTextureStateP ts, GLenum target, GLuint texture)
++{
++ ts->target = target;
++ ts->old_texture = 0;
++ ts->was_bound = 0;
++ ts->was_enabled = glIsEnabled(target);
++ if (!ts->was_enabled)
++ glEnable(target);
++
++ GLenum texture_binding;
++ switch (target) {
++ case GL_TEXTURE_1D:
++ texture_binding = GL_TEXTURE_BINDING_1D;
++ break;
++ case GL_TEXTURE_2D:
++ texture_binding = GL_TEXTURE_BINDING_2D;
++ break;
++ case GL_TEXTURE_3D:
++ texture_binding = GL_TEXTURE_BINDING_3D;
++ break;
++ case GL_TEXTURE_RECTANGLE_ARB:
++ texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
++ break;
++ default:
++ assert(!target);
++ return -1;
++ }
++
++ if (ts->was_enabled && gl_get_param(texture_binding, &ts->old_texture) < 0)
++ return -1;
++
++ ts->was_bound = texture == ts->old_texture;
++ if (!ts->was_bound) {
++ gl_purge_errors();
++ glBindTexture(target, texture);
++ if (gl_check_error())
++ return -1;
++ }
++ return 0;
++}
++
++// Unbind texture, restore previous texture state
++static void unbind_texture(OpenGLTextureStateP ts)
++{
++ if (!ts->was_bound && ts->old_texture)
++ glBindTexture(ts->target, ts->old_texture);
++ if (!ts->was_enabled)
++ glDisable(ts->target);
++}
++
++// Create Pixmaps for GLX texture-from-pixmap extension
++static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ const unsigned int width = pSurfaceGLX->width;
++ const unsigned int height = pSurfaceGLX->height;
++ Pixmap pixmap = None;
++ GLXFBConfig *fbconfig = NULL;
++ GLXPixmap glx_pixmap = None;
++ Window root_window;
++ XWindowAttributes wattr;
++ int *attrib;
++ int n_fbconfig_attribs, x, y, status;
++ unsigned int border_width, depth, dummy;
++
++ root_window = RootWindow(ctx->x11_dpy, ctx->x11_screen);
++ XGetWindowAttributes(ctx->x11_dpy, root_window, &wattr);
++ pixmap = XCreatePixmap(ctx->x11_dpy, root_window,
++ width, height, wattr.depth);
++ if (!pixmap)
++ return -1;
++ pSurfaceGLX->pixmap = pixmap;
++
++ x11_trap_errors();
++ status = XGetGeometry(ctx->x11_dpy,
++ (Drawable)pixmap,
++ &root_window,
++ &x,
++ &y,
++ &dummy,
++ &dummy,
++ &border_width,
++ &depth);
++ if (x11_untrap_errors() != 0 || status == 0)
++ return -1;
++ if (depth != 24 && depth != 32)
++ return -1;
++
++ int fbconfig_attribs[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,
++ };
++ for (attrib = fbconfig_attribs; *attrib != GL_NONE; attrib += 2)
++ ;
++ *attrib++ = GLX_DEPTH_SIZE; *attrib++ = depth;
++ if (depth == 32) {
++ *attrib++ = GLX_ALPHA_SIZE; *attrib++ = 8;
++ *attrib++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attrib++ = GL_TRUE;
++ }
++ else {
++ *attrib++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attrib++ = GL_TRUE;
++ }
++ *attrib++ = GL_NONE;
++
++ fbconfig = glXChooseFBConfig(ctx->x11_dpy, ctx->x11_screen, fbconfig_attribs, &n_fbconfig_attribs);
++ if (fbconfig == NULL)
++ return -1;
++
++ int pixmap_attribs[10] = {
++ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
++ GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
++ GL_NONE,
++ };
++ for (attrib = pixmap_attribs; *attrib != GL_NONE; attrib += 2)
++ ;
++ *attrib++ = GLX_TEXTURE_FORMAT_EXT;
++ if (depth == 32)
++ *attrib++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
++ else
++ *attrib++ = GLX_TEXTURE_FORMAT_RGB_EXT;
++ *attrib++ = GL_NONE;
++
++ x11_trap_errors();
++ glx_pixmap = glXCreatePixmap(ctx->x11_dpy,
++ fbconfig[0],
++ pixmap,
++ pixmap_attribs);
++ free(fbconfig);
++ if (x11_untrap_errors() != 0)
++ return -1;
++ pSurfaceGLX->glx_pixmap = glx_pixmap;
++ return 0;
++}
++
++// Destroy Pixmaps used for TFP
++static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ if (pSurfaceGLX->glx_pixmap) {
++ glXDestroyPixmap(ctx->x11_dpy, pSurfaceGLX->glx_pixmap);
++ pSurfaceGLX->glx_pixmap = None;
++ }
++
++ if (pSurfaceGLX->pixmap) {
++ XFreePixmap(ctx->x11_dpy, pSurfaceGLX->pixmap);
++ pSurfaceGLX->pixmap = None;
++ }
++}
++
++// Bind GLX Pixmap to texture
++static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ if (pSurfaceGLX->is_bound)
++ return 0;
++
++ x11_trap_errors();
++ pOpenGLVTable->glx_bind_tex_image(ctx->x11_dpy, pSurfaceGLX->glx_pixmap,
++ GLX_FRONT_LEFT_EXT, NULL);
++ XSync(ctx->x11_dpy, False);
++ if (x11_untrap_errors() != 0) {
++ va_glx_error_message("failed to bind pixmap\n");
++ return -1;
++ }
++
++ pSurfaceGLX->is_bound = 1;
++ return 0;
++}
++
++// Release GLX Pixmap from texture
++static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ if (!pSurfaceGLX->is_bound)
++ return 0;
++
++ x11_trap_errors();
++ pOpenGLVTable->glx_release_tex_image(ctx->x11_dpy, pSurfaceGLX->glx_pixmap,
++ GLX_FRONT_LEFT_EXT);
++ XSync(ctx->x11_dpy, False);
++ if (x11_untrap_errors() != 0) {
++ va_glx_error_message("failed to release pixmap\n");
++ return -1;
++ }
++
++ pSurfaceGLX->is_bound = 0;
++ return 0;
++}
++
++// Render GLX Pixmap to texture
++static void render_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ const unsigned int w = pSurfaceGLX->width;
++ const unsigned int h = pSurfaceGLX->height;
++ float old_color[4];
++
++ gl_get_current_color(old_color);
++ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
++ glBegin(GL_QUADS);
++ {
++ glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
++ glTexCoord2f(0.0f, 1.0f); glVertex2i(0, h);
++ glTexCoord2f(1.0f, 1.0f); glVertex2i(w, h);
++ glTexCoord2f(1.0f, 0.0f); glVertex2i(w, 0);
++ }
++ glEnd();
++ glColor4fv(old_color);
++}
++
++// Create offscreen surface
++static int create_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++ const GLenum texture = pSurfaceGLX->texture;
++ const unsigned int texture_width = pSurfaceGLX->width;
++ const unsigned int texture_height = pSurfaceGLX->height;
++ GLuint fbo, fbo_buffer, fbo_texture;
++ GLenum status;
++
++ glGenTextures(1, &fbo_texture);
++ glBindTexture(GL_TEXTURE_2D, fbo_texture);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0,
++ GL_BGRA, GL_UNSIGNED_BYTE, NULL);
++
++ pOpenGLVTable->gl_gen_framebuffers(1, &fbo);
++ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo);
++ pOpenGLVTable->gl_gen_renderbuffers(1, &fbo_buffer);
++ pOpenGLVTable->gl_bind_renderbuffer(GL_RENDERBUFFER_EXT, fbo_buffer);
++
++ glBindTexture(GL_TEXTURE_2D, texture);
++ pOpenGLVTable->gl_framebuffer_texture_2d(GL_FRAMEBUFFER_EXT,
++ GL_COLOR_ATTACHMENT0_EXT,
++ GL_TEXTURE_2D, texture, 0);
++
++ status = pOpenGLVTable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
++ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
++ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
++ return -1;
++
++ pSurfaceGLX->fbo = fbo;
++ pSurfaceGLX->fbo_buffer = fbo_buffer;
++ pSurfaceGLX->fbo_texture = fbo_texture;
++ return 0;
++}
++
++// Destroy offscreen surface
++static void destroy_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ if (pSurfaceGLX->fbo_texture) {
++ glDeleteTextures(1, &pSurfaceGLX->fbo_texture);
++ pSurfaceGLX->fbo_texture = 0;
++ }
++
++ if (pSurfaceGLX->fbo_buffer) {
++ pOpenGLVTable->gl_delete_renderbuffers(1, &pSurfaceGLX->fbo_buffer);
++ pSurfaceGLX->fbo_buffer = 0;
++ }
++
++ if (pSurfaceGLX->fbo) {
++ pOpenGLVTable->gl_delete_framebuffers(1, &pSurfaceGLX->fbo);
++ pSurfaceGLX->fbo = 0;
++ }
++}
++
++// Setup matrices to match the FBO texture dimensions
++static void fbo_enter(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++ const unsigned int width = pSurfaceGLX->width;
++ const unsigned int height = pSurfaceGLX->height;
++
++ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, pSurfaceGLX->fbo);
++ glPushAttrib(GL_VIEWPORT_BIT);
++ 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);
++
++ glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->fbo_texture);
++}
++
++// Restore original OpenGL matrices
++static void fbo_leave(VADriverContextP ctx)
++{
++ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
++
++ glPopAttrib();
++ glMatrixMode(GL_PROJECTION);
++ glPopMatrix();
++ glMatrixMode(GL_MODELVIEW);
++ glPopMatrix();
++ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
++}
++
++// Create VA/GLX surface
++VASurfaceGLXP
++va_glx_create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX;
++ unsigned int internal_format, border_width, width, height;
++ int is_error = 1;
++
++ /* Make sure binding succeeds, if texture was not already bound */
++ struct OpenGLTextureState ts;
++ if (bind_texture(&ts, target, texture) < 0)
++ goto end;
++
++ pSurfaceGLX = malloc(sizeof(*pSurfaceGLX));
++ if (!pSurfaceGLX)
++ goto end;
++
++ pSurfaceGLX->magic = VA_SURFACE_GLX_MAGIC;
++ pSurfaceGLX->target = target;
++ pSurfaceGLX->texture = texture;
++ pSurfaceGLX->surface = VA_INVALID_SURFACE;
++ pSurfaceGLX->is_bound = 0;
++ pSurfaceGLX->pixmap = None;
++ pSurfaceGLX->glx_pixmap = None;
++ pSurfaceGLX->fbo = 0;
++ pSurfaceGLX->fbo_buffer = 0;
++ pSurfaceGLX->fbo_texture = 0;
++ pSurfaceGLX->priv = NULL;
++
++ /* XXX: we don't support other textures than RGBA */
++ if (gl_get_texture_param(GL_TEXTURE_INTERNAL_FORMAT, &internal_format) < 0)
++ goto end;
++ if (internal_format != GL_RGBA)
++ goto end;
++
++ /* Check texture dimensions */
++ if (gl_get_texture_param(GL_TEXTURE_BORDER, &border_width) < 0)
++ goto end;
++ if (gl_get_texture_param(GL_TEXTURE_WIDTH, &width) < 0)
++ goto end;
++ if (gl_get_texture_param(GL_TEXTURE_HEIGHT, &height) < 0)
++ goto end;
++
++ width -= 2 * border_width;
++ height -= 2 * border_width;
++ if (width == 0 || height == 0)
++ goto end;
++
++ pSurfaceGLX->width = width;
++ pSurfaceGLX->height = height;
++
++ /* Create Pixmaps for TFP */
++ if (pDriverContextGLX->use_tfp) {
++ if (create_tfp_surface(ctx, pSurfaceGLX) < 0)
++ goto end;
++ }
++
++ /* Create Pixmaps for FBO */
++ if (pDriverContextGLX->use_fbo) {
++ if (create_fbo_surface(ctx, pSurfaceGLX) < 0)
++ goto end;
++ }
++
++ is_error = 0;
++end:
++ if (is_error && pSurfaceGLX)
++ va_glx_destroy_surface(ctx, &pSurfaceGLX);
++
++ unbind_texture(&ts);
++ return pSurfaceGLX;
++}
++
++// Destroy VA/GLX surface
++void va_glx_destroy_surface(VADriverContextP ctx, VASurfaceGLXP *ppSurfaceGLX)
++{
++ VASurfaceGLXP pSurfaceGLX = *ppSurfaceGLX;
++
++ unbind_pixmap(ctx, pSurfaceGLX);
++ destroy_fbo_surface(ctx, pSurfaceGLX);
++ destroy_tfp_surface(ctx, pSurfaceGLX);
++
++ free(pSurfaceGLX);
++ *ppSurfaceGLX = NULL;
++}
++
++
++/* ========================================================================= */
++/* === VA/GLX implementation from the driver (fordward calls) === */
++/* ========================================================================= */
++
++#define INVOKE(ctx, func, args) do { \
++ VADriverVTableGLXP vtable = &(ctx)->vtable.glx; \
++ if (!vtable->va##func##GLX) \
++ return VA_STATUS_ERROR_UNIMPLEMENTED; \
++ \
++ VAStatus status = vtable->va##func##GLX args; \
++ if (status != VA_STATUS_SUCCESS) \
++ return status; \
++ } while (0)
++
++static VAStatus
++vaCreateSurfaceGLX_impl_driver(
++ VADriverContextP ctx,
++ GLenum target,
++ GLuint texture,
++ void **gl_surface
++)
++{
++ INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaDestroySurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, DestroySurface, (ctx, pSurfaceGLX->priv));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaAssociateSurfaceGLX_impl_driver(
++ VADriverContextP ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, AssociateSurface, (ctx, pSurfaceGLX->priv, surface, flags));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaDeassociateSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, DeassociateSurface, (ctx, pSurfaceGLX->priv));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaSyncSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, SyncSurface, (ctx, pSurfaceGLX->priv));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaBeginRenderSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, BeginRenderSurface, (ctx, pSurfaceGLX->priv));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaEndRenderSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, EndRenderSurface, (ctx, pSurfaceGLX->priv));
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaCopySurfaceGLX_impl_driver(
++ VADriverContextP ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ INVOKE(ctx, CopySurface, (ctx, pSurfaceGLX->priv, surface, flags));
++ return VA_STATUS_SUCCESS;
++}
++
++#undef INVOKE
++
++
++/* ========================================================================= */
++/* === VA/GLX implementation from libVA (generic and suboptimal path) === */
++/* ========================================================================= */
++
++static VAStatus
++vaCreateSurfaceGLX_impl_libva(
++ VADriverContextP ctx,
++ GLenum target,
++ GLuint texture,
++ void **gl_surface
++)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ *gl_surface = NULL;
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaDestroySurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaAssociateSurfaceGLX_impl_libva(
++ VADriverContextP ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++ VAStatus status;
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ /* XXX: only support VA_FRAME_PICTURE */
++ if (flags != VA_FRAME_PICTURE)
++ return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
++
++ /* XXX: optimise case where we are associating the same VA surface
++ as before an no changed occurred to it */
++ status = vtable->vaDeassociateSurfaceGLX(ctx, gl_surface);
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ x11_trap_errors();
++ status = ctx->vtable.vaPutSurface(ctx,
++ surface,
++ pSurfaceGLX->pixmap,
++ 0, 0,
++ pSurfaceGLX->width,
++ pSurfaceGLX->height,
++ 0, 0,
++ pSurfaceGLX->width,
++ pSurfaceGLX->height,
++ NULL, 0,
++ flags);
++ XSync(ctx->x11_dpy, False);
++ if (x11_untrap_errors() != 0)
++ return VA_STATUS_ERROR_OPERATION_FAILED;
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ pSurfaceGLX->surface = surface;
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaDeassociateSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ if (unbind_pixmap(ctx, pSurfaceGLX) < 0)
++ return VA_STATUS_ERROR_OPERATION_FAILED;
++
++ pSurfaceGLX->surface = VA_INVALID_SURFACE;
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaSyncSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ if (pSurfaceGLX->surface == VA_INVALID_SURFACE)
++ return VA_STATUS_ERROR_INVALID_SURFACE;
++
++ return ctx->vtable.vaSyncSurface(ctx, pSurfaceGLX->surface);
++}
++
++static VAStatus
++vaBeginRenderSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++ VAStatus status;
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ status = vaSyncSurfaceGLX_impl_libva(ctx, gl_surface);
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ if (bind_pixmap(ctx, pSurfaceGLX) < 0)
++ return VA_STATUS_ERROR_OPERATION_FAILED;
++
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaEndRenderSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++ VAStatus status;
++
++ if (!pDriverContextGLX->use_tfp)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ if (unbind_pixmap(ctx, pSurfaceGLX) < 0)
++ return VA_STATUS_ERROR_OPERATION_FAILED;
++
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaCopySurfaceGLX_impl_libva(
++ VADriverContextP ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++ VAStatus status;
++
++ if (!pDriverContextGLX->use_fbo)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ /* XXX: only support VA_FRAME_PICTURE */
++ if (flags != VA_FRAME_PICTURE)
++ return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
++
++ /* Associate VA surface */
++ status = vtable->vaAssociateSurfaceGLX(ctx, gl_surface, surface, flags);
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ /* Make sure binding succeeds, if texture was not already bound */
++ struct OpenGLTextureState ts;
++ if (bind_texture(&ts, pSurfaceGLX->target, pSurfaceGLX->texture) < 0)
++ return VA_STATUS_ERROR_OPERATION_FAILED;
++
++ /* Render to FBO */
++ fbo_enter(ctx, pSurfaceGLX);
++ status = vtable->vaBeginRenderSurfaceGLX(ctx, gl_surface);
++ if (status == VA_STATUS_SUCCESS) {
++ render_pixmap(ctx, pSurfaceGLX);
++ status = vtable->vaEndRenderSurfaceGLX(ctx, gl_surface);
++ }
++ fbo_leave(ctx);
++ unbind_texture(&ts);
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ return vtable->vaDeassociateSurfaceGLX(ctx, gl_surface);
++}
++
++
++/* ========================================================================= */
++/* === VA/GLX bind functions implementation with vaCopySurfaceGLX() === */
++/* ========================================================================= */
++
++static VAStatus
++vaAssociateSurfaceGLX_impl_bind(
++ VADriverContextP ctx,
++ void *gl_surface,
++ VASurfaceID surface,
++ unsigned int flags
++)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++ VAStatus status;
++
++ if (!pDriverContextGLX->has_copy)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ status = vtable->vaCopySurfaceGLX(ctx, gl_surface, surface, flags);
++ if (status != VA_STATUS_SUCCESS)
++ return status;
++
++ pSurfaceGLX->surface = surface;
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaDeassociateSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
++{
++ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
++ VASurfaceGLXP pSurfaceGLX = gl_surface;
++
++ if (!pDriverContextGLX->has_copy)
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++
++ pSurfaceGLX->surface = VA_INVALID_SURFACE;
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaBeginRenderSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
++{
++ /* Surface is already copied into the texture, in vaAssociateSurfaceGLX() */
++ return VA_STATUS_SUCCESS;
++}
++
++static VAStatus
++vaEndRenderSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
++{
++ return VA_STATUS_SUCCESS;
++}
++
++
++/* ========================================================================= */
++/* === Private VA/GLX vtable initialization === */
++/* ========================================================================= */
++
++// Initialize GLX driver context
++VAStatus va_glx_init_context(VADriverContextP ctx)
++{
++ VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
++ VADriverVTableGLXP vtable = &glx_ctx->vtable;
++ int needs_tfp = 0, needs_fbo = 0;
++
++ if (glx_ctx->is_initialized)
++ return VA_STATUS_SUCCESS;
++
++ glx_ctx->has_copy = ctx->vtable.glx.vaCopySurfaceGLX != NULL;
++ glx_ctx->has_bind = (ctx->vtable.glx.vaAssociateSurfaceGLX != NULL &&
++ ctx->vtable.glx.vaBeginRenderSurfaceGLX != NULL &&
++ ctx->vtable.glx.vaEndRenderSurfaceGLX != NULL &&
++ ctx->vtable.glx.vaDeassociateSurfaceGLX != NULL);
++
++ switch ((((unsigned int)glx_ctx->has_bind) << 1) | glx_ctx->has_copy) {
++ case 0:
++ /* Full implementation in libVA */
++ needs_tfp = 1;
++ needs_fbo = 1;
++ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_libva;
++ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_libva;
++ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_libva;
++ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_libva;
++ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_libva;
++ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_libva;
++ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_libva;
++ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
++ break;
++ case 1:
++ /* Add bind functions based on vaCopySurfaceGLX() */
++ /* XXX: override vaSyncSurfaceGLX()? */
++ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
++ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
++ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_bind;
++ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_bind;
++ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_bind;
++ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_bind;
++ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
++ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
++ break;
++ case 2:
++ /* Add copy function based on vaBeginRenderSurfaceGLX() et al. */
++ needs_fbo = 1;
++ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
++ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
++ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_driver;
++ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_driver;
++ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_driver;
++ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_driver;
++ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
++ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
++ break;
++ case 3:
++ /* Keep driver bind & copy functions */
++ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
++ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
++ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_driver;
++ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_driver;
++ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_driver;
++ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_driver;
++ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
++ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
++ break;
++ default:
++ /* Fatal error: this cannot happen */
++ assert(0);
++ return VA_STATUS_ERROR_UNKNOWN;
++ }
++
++ glx_ctx->has_tfp = 0;
++ glx_ctx->use_tfp = 0;
++ glx_ctx->has_fbo = 0;
++ glx_ctx->use_fbo = 0;
++
++ if (needs_tfp) {
++ glx_ctx->has_tfp = check_tfp_extensions(ctx);
++ if (!glx_ctx->has_tfp || !load_tfp_extensions(ctx))
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++ glx_ctx->use_tfp = 1;
++ }
++
++ if (needs_fbo) {
++ glx_ctx->has_fbo = check_fbo_extensions(ctx);
++ if (!glx_ctx->has_fbo || !load_fbo_extensions(ctx))
++ return VA_STATUS_ERROR_UNIMPLEMENTED;
++ glx_ctx->use_fbo = 1;
++ }
++
++ glx_ctx->is_initialized = 1;
++ return VA_STATUS_SUCCESS;
++}
+diff --git a/src/glx/va_glx_impl.h b/src/glx/va_glx_impl.h
+new file mode 100644
+index 0000000..977bfcc
+--- /dev/null
++++ b/src/glx/va_glx_impl.h
+@@ -0,0 +1,46 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef VA_GLX_IMPL_H
++#define VA_GLX_IMPL_H
++
++/**
++ * Initialize GLX driver context
++ *
++ * @param[in] ctx the VA driver context
++ * @return VA_STATUS_SUCCESS if successful
++ */
++VAStatus va_glx_init_context(VADriverContextP ctx)
++ ATTRIBUTE_HIDDEN;
++
++/** Create VA/GLX surface */
++VASurfaceGLXP
++va_glx_create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
++ ATTRIBUTE_HIDDEN;
++
++/** Destroy VA/GLX surface */
++void va_glx_destroy_surface(VADriverContextP ctx, VASurfaceGLXP *pSurfaceGLX)
++ ATTRIBUTE_HIDDEN;
++
++#endif /* VA_GLX_IMPL_H */
+diff --git a/src/glx/va_glx_private.h b/src/glx/va_glx_private.h
+new file mode 100644
+index 0000000..8658ad3
+--- /dev/null
++++ b/src/glx/va_glx_private.h
+@@ -0,0 +1,98 @@
++/*
++ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sub license, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial portions
++ * of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
++ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
++ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
++ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
++ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef VA_GLX_PRIVATE_H
++#define VA_GLX_PRIVATE_H
++
++#include "config.h"
++#include "va.h"
++#include "va_backend.h"
++#include "va_x11.h"
++#include "va_glx.h"
++
++#if GLX_GLXEXT_VERSION < 18
++typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *);
++typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int);
++#endif
++
++typedef struct VAOpenGLVTable *VAOpenGLVTableP;
++
++struct VAOpenGLVTable {
++ 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;
++};
++
++typedef struct VADisplayContextGLX *VADisplayContextGLXP;
++typedef struct VADriverContextGLX *VADriverContextGLXP;
++typedef struct VASurfaceGLX *VASurfaceGLXP;
++typedef struct VADriverVTableGLX *VADriverVTableGLXP;
++
++struct VADisplayContextGLX {
++ void (*vaDestroy)(VADisplayContextP ctx);
++};
++
++#define VA_DRIVER_CONTEXT_GLX(ctx) ((VADriverContextGLXP)((ctx)->glx))
++
++struct VADriverContextGLX {
++ struct VADriverVTableGLX vtable;
++ struct VAOpenGLVTable gl_vtable;
++ unsigned int is_initialized : 1;
++ unsigned int has_copy : 1;
++ unsigned int has_bind : 1;
++ unsigned int has_tfp : 1;
++ unsigned int has_fbo : 1;
++ unsigned int use_tfp : 1;
++ unsigned int use_fbo : 1;
++};
++
++/** Unique VASurfaceGLX identifier */
++#define VA_SURFACE_GLX_MAGIC VA_FOURCC('V','A','G','L')
++
++struct VASurfaceGLX {
++ uint32_t magic; ///< Magic number identifying a VASurfaceGLX
++ GLenum target; ///< GL target to which the texture is bound
++ GLuint texture; ///< GL texture
++ VASurfaceID surface; ///< Associated VA surface
++ unsigned int width;
++ unsigned int height;
++ int is_bound;
++ Pixmap pixmap;
++ GLXPixmap glx_pixmap;
++ GLuint fbo;
++ GLuint fbo_buffer;
++ GLuint fbo_texture;
++ void *priv; ///< Private VA/GLX surface data from driver
++};
++
++#endif /* VA_GLX_PRIVATE_H */