diff options
author | Richard Purdie <rpurdie@linux.intel.com> | 2010-11-02 10:08:00 +0000 |
---|---|---|
committer | Richard Purdie <rpurdie@linux.intel.com> | 2010-11-02 10:08:00 +0000 |
commit | 01518ada4b0ca1571f4b4d21c884b02e9371da62 (patch) | |
tree | 25235b628ee04807ada4ef3ada76d4b534a8bb1a /meta-emenlow/recipes/libva/libva-0.31.0/322_libva_glx.patch | |
parent | c90c0ceca50fee19e683c19468110fba51da6cfe (diff) | |
download | openembedded-core-01518ada4b0ca1571f4b4d21c884b02e9371da62.tar.gz openembedded-core-01518ada4b0ca1571f4b4d21c884b02e9371da62.tar.bz2 openembedded-core-01518ada4b0ca1571f4b4d21c884b02e9371da62.tar.xz openembedded-core-01518ada4b0ca1571f4b4d21c884b02e9371da62.zip |
meta-emenlow: Rename packages to recipes in line with main repository
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'meta-emenlow/recipes/libva/libva-0.31.0/322_libva_glx.patch')
-rw-r--r-- | meta-emenlow/recipes/libva/libva-0.31.0/322_libva_glx.patch | 2024 |
1 files changed, 2024 insertions, 0 deletions
diff --git a/meta-emenlow/recipes/libva/libva-0.31.0/322_libva_glx.patch b/meta-emenlow/recipes/libva/libva-0.31.0/322_libva_glx.patch new file mode 100644 index 000000000..ccd9ae090 --- /dev/null +++ b/meta-emenlow/recipes/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 */ |