summaryrefslogtreecommitdiffstats
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 @@
1commit 8e76000abce070da5f1c902a6290f4ccaa3eccc8
2Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
3Date: Fri Sep 18 15:51:08 2009 +0000
4
5 Add C++ guards.
6
7commit bf1ae22ef324fbb347f5369e1ba307e847553fe8
8Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
9Date: Fri Sep 18 15:49:55 2009 +0000
10
11 Fix check for GL extensions.
12
13commit df0953a951d8a2e5e4b0a28a95ae0f1ac735726e
14Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
15Date: Tue Sep 8 12:25:14 2009 +0000
16
17 Add generic VA/GLX implementation with TFP and FBO.
18
19commit f640b1cf9eab4e5d478239b608ed0d8b68f6c5f6
20Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
21Date: Tue Sep 8 12:15:35 2009 +0000
22
23 Move GLX VTable to a new file.
24
25commit 70d9cb6d1aa2fc2dde6646f3b692433e0d93d431
26Author: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
27Date: Fri Aug 28 11:15:51 2009 +0000
28
29 Add OpenGL extensions (v3).
30
31diff --git a/src/glx/Makefile.am b/src/glx/Makefile.am
32new file mode 100644
33index 0000000..7783d8c
34--- /dev/null
35+++ b/src/glx/Makefile.am
36@@ -0,0 +1,41 @@
37+# Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
38+#
39+# Permission is hereby granted, free of charge, to any person obtaining a
40+# copy of this software and associated documentation files (the
41+# "Software"), to deal in the Software without restriction, including
42+# without limitation the rights to use, copy, modify, merge, publish,
43+# distribute, sub license, and/or sell copies of the Software, and to
44+# permit persons to whom the Software is furnished to do so, subject to
45+# the following conditions:
46+#
47+# The above copyright notice and this permission notice (including the
48+# next paragraph) shall be included in all copies or substantial portions
49+# of the Software.
50+#
51+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
52+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
53+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
54+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
55+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
56+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
57+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
58+
59+AM_CFLAGS = -DLINUX -DIN_LIBVA -I$(top_srcdir)/src -I$(top_srcdir)/src/x11
60+
61+source_c = \
62+ va_glx.c \
63+ va_glx_impl.c
64+
65+source_h = \
66+ va_glx.h \
67+ va_backend_glx.h
68+
69+source_h_priv = \
70+ va_glx_impl.h \
71+ va_glx_private.h
72+
73+noinst_LTLIBRARIES = libva_glx.la
74+libva_glxincludedir = ${includedir}/va
75+libva_glxinclude_HEADERS = $(source_h)
76+libva_glx_la_SOURCES = $(source_c)
77+noinst_HEADERS = $(source_h_priv)
78diff --git a/src/glx/va_backend_glx.h b/src/glx/va_backend_glx.h
79new file mode 100644
80index 0000000..3885d30
81--- /dev/null
82+++ b/src/glx/va_backend_glx.h
83@@ -0,0 +1,87 @@
84+/*
85+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
86+ *
87+ * Permission is hereby granted, free of charge, to any person obtaining a
88+ * copy of this software and associated documentation files (the
89+ * "Software"), to deal in the Software without restriction, including
90+ * without limitation the rights to use, copy, modify, merge, publish,
91+ * distribute, sub license, and/or sell copies of the Software, and to
92+ * permit persons to whom the Software is furnished to do so, subject to
93+ * the following conditions:
94+ *
95+ * The above copyright notice and this permission notice (including the
96+ * next paragraph) shall be included in all copies or substantial portions
97+ * of the Software.
98+ *
99+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
100+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
101+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
102+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
103+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
104+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
105+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
106+ */
107+
108+#ifndef VA_BACKEND_GLX_H
109+#define VA_BACKEND_GLX_H
110+
111+struct VADriverContext;
112+
113+struct VADriverVTableGLX {
114+ /* Optional: create a surface used for display to OpenGL */
115+ VAStatus (*vaCreateSurfaceGLX)(
116+ struct VADriverContext *ctx,
117+ unsigned int gl_target,
118+ unsigned int gl_texture,
119+ void **gl_surface
120+ );
121+
122+ /* Optional: destroy a VA/GLX surface */
123+ VAStatus (*vaDestroySurfaceGLX)(
124+ struct VADriverContext *ctx,
125+ void *gl_surface
126+ );
127+
128+ /* Optional: associate a VA surface to a VA/GLX surface */
129+ VAStatus (*vaAssociateSurfaceGLX)(
130+ struct VADriverContext *ctx,
131+ void *gl_surface,
132+ VASurfaceID surface,
133+ unsigned int flags
134+ );
135+
136+ /* Optional: deassociate a VA surface from a VA/GLX surface */
137+ VAStatus (*vaDeassociateSurfaceGLX)(
138+ struct VADriverContext *ctx,
139+ void *gl_surface
140+ );
141+
142+ /* Optional: synchronize a VA/GLX surface */
143+ VAStatus (*vaSyncSurfaceGLX)(
144+ struct VADriverContext *ctx,
145+ void *gl_surface
146+ );
147+
148+ /* Optional: prepare VA/GLX surface for rendering */
149+ VAStatus (*vaBeginRenderSurfaceGLX)(
150+ struct VADriverContext *ctx,
151+ void *gl_surface
152+ );
153+
154+ /* Optional: notify the server that the VA/GLX surface is no
155+ longer used for rendering */
156+ VAStatus (*vaEndRenderSurfaceGLX)(
157+ struct VADriverContext *ctx,
158+ void *gl_surface
159+ );
160+
161+ /* Optional: copy a VA surface to a VA/GLX surface */
162+ VAStatus (*vaCopySurfaceGLX)(
163+ struct VADriverContext *ctx,
164+ void *gl_surface,
165+ VASurfaceID surface,
166+ unsigned int flags
167+ );
168+};
169+
170+#endif /* VA_BACKEND_GLX_H */
171diff --git a/src/glx/va_glx.c b/src/glx/va_glx.c
172new file mode 100644
173index 0000000..f6ec2c3
174--- /dev/null
175+++ b/src/glx/va_glx.c
176@@ -0,0 +1,295 @@
177+/*
178+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
179+ *
180+ * Permission is hereby granted, free of charge, to any person obtaining a
181+ * copy of this software and associated documentation files (the
182+ * "Software"), to deal in the Software without restriction, including
183+ * without limitation the rights to use, copy, modify, merge, publish,
184+ * distribute, sub license, and/or sell copies of the Software, and to
185+ * permit persons to whom the Software is furnished to do so, subject to
186+ * the following conditions:
187+ *
188+ * The above copyright notice and this permission notice (including the
189+ * next paragraph) shall be included in all copies or substantial portions
190+ * of the Software.
191+ *
192+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
193+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
194+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
195+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
196+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
197+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
198+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
199+ */
200+
201+#include "va_glx_private.h"
202+#include "va_glx_impl.h"
203+
204+#define INIT_CONTEXT(ctx, dpy) do { \
205+ if (!vaDisplayIsValid(dpy)) \
206+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
207+ \
208+ ctx = ((VADisplayContextP)(dpy))->pDriverContext; \
209+ if (!(ctx)) \
210+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
211+ \
212+ VAStatus status = va_glx_init_context(ctx); \
213+ if (status != VA_STATUS_SUCCESS) \
214+ return status; \
215+ } while (0)
216+
217+#define INIT_SURFACE(surface, surface_arg) do { \
218+ surface = (VASurfaceGLXP)(surface_arg); \
219+ if (!vaSurfaceIsValid(surface)) \
220+ return VA_STATUS_ERROR_INVALID_SURFACE; \
221+ } while (0)
222+
223+#define INVOKE(ctx, func, args) do { \
224+ VADriverVTableGLXP vtable; \
225+ vtable = &VA_DRIVER_CONTEXT_GLX(ctx)->vtable; \
226+ if (!vtable->va##func##GLX) \
227+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
228+ status = vtable->va##func##GLX args; \
229+ } while (0)
230+
231+// Check VADisplay is valid
232+static inline int vaDisplayIsValid(VADisplay dpy)
233+{
234+ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
235+
236+ return (pDisplayContext &&
237+ pDisplayContext->vaIsValid &&
238+ pDisplayContext->vaIsValid(pDisplayContext));
239+}
240+
241+// Check VASurfaceGLX is valid
242+static inline int vaSurfaceIsValid(VASurfaceGLXP pSurfaceGLX)
243+{
244+ return pSurfaceGLX && pSurfaceGLX->magic == VA_SURFACE_GLX_MAGIC;
245+}
246+
247+// Destroy VA/GLX display context
248+static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
249+{
250+ VADisplayContextGLXP pDisplayContextGLX;
251+ VADriverContextP pDriverContext;
252+ VADriverContextGLXP pDriverContextGLX;
253+
254+ if (!pDisplayContext)
255+ return;
256+
257+ pDriverContext = pDisplayContext->pDriverContext;
258+ pDriverContextGLX = pDriverContext->glx;
259+ if (pDriverContextGLX) {
260+ free(pDriverContextGLX);
261+ pDriverContext->glx = NULL;
262+ }
263+
264+ pDisplayContextGLX = pDisplayContext->opaque;
265+ if (pDisplayContextGLX) {
266+ if (pDisplayContextGLX->vaDestroy)
267+ pDisplayContextGLX->vaDestroy(pDisplayContext);
268+ free(pDisplayContextGLX);
269+ pDisplayContext->opaque = NULL;
270+ }
271+}
272+
273+// Return a suitable VADisplay for VA API
274+VADisplay vaGetDisplayGLX(Display *native_dpy)
275+{
276+ VADisplay dpy = NULL;
277+ VADisplayContextP pDisplayContext = NULL;
278+ VADisplayContextGLXP pDisplayContextGLX = NULL;
279+ VADriverContextP pDriverContext;
280+ VADriverContextGLXP pDriverContextGLX = NULL;
281+
282+ dpy = vaGetDisplay(native_dpy);
283+ if (!dpy)
284+ return NULL;
285+ pDisplayContext = (VADisplayContextP)dpy;
286+ pDriverContext = pDisplayContext->pDriverContext;
287+
288+ pDisplayContextGLX = calloc(1, sizeof(*pDisplayContextGLX));
289+ if (!pDisplayContextGLX)
290+ goto error;
291+
292+ pDriverContextGLX = calloc(1, sizeof(*pDriverContextGLX));
293+ if (!pDriverContextGLX)
294+ goto error;
295+
296+ pDisplayContextGLX->vaDestroy = pDisplayContext->vaDestroy;
297+ pDisplayContext->vaDestroy = va_DisplayContextDestroy;
298+ pDisplayContext->opaque = pDisplayContextGLX;
299+ pDriverContext->glx = pDriverContextGLX;
300+ return dpy;
301+
302+error:
303+ free(pDriverContextGLX);
304+ free(pDisplayContextGLX);
305+ pDisplayContext->vaDestroy(pDisplayContext);
306+ return NULL;
307+}
308+
309+// Create a surface used for display to OpenGL
310+VAStatus vaCreateSurfaceGLX(
311+ VADisplay dpy,
312+ GLenum target,
313+ GLuint texture,
314+ void **gl_surface
315+)
316+{
317+ VADriverContextP ctx;
318+ VASurfaceGLXP pSurfaceGLX;
319+ VAStatus status;
320+
321+ /* Make sure it is a valid GL texture object */
322+ if (!glIsTexture(texture))
323+ return VA_STATUS_ERROR_INVALID_PARAMETER;
324+
325+ INIT_CONTEXT(ctx, dpy);
326+
327+ pSurfaceGLX = va_glx_create_surface(ctx, target, texture);
328+ if (!pSurfaceGLX)
329+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
330+
331+ INVOKE(ctx, CreateSurface, (ctx, target, texture, &pSurfaceGLX->priv));
332+
333+ if (status != VA_STATUS_SUCCESS)
334+ va_glx_destroy_surface(ctx, &pSurfaceGLX);
335+
336+ *gl_surface = pSurfaceGLX;
337+ return status;
338+}
339+
340+// Destroy a VA/GLX surface
341+VAStatus vaDestroySurfaceGLX(
342+ VADisplay dpy,
343+ void *gl_surface
344+)
345+{
346+ VADriverContextP ctx;
347+ VASurfaceGLXP pSurfaceGLX;
348+ VAStatus status;
349+
350+ INIT_CONTEXT(ctx, dpy);
351+ INIT_SURFACE(pSurfaceGLX, gl_surface);
352+
353+ INVOKE(ctx, DestroySurface, (ctx, pSurfaceGLX));
354+
355+ free(pSurfaceGLX);
356+ return status;
357+}
358+
359+// Associate a VA surface to a VA/GLX surface
360+VAStatus vaAssociateSurfaceGLX(
361+ VADisplay dpy,
362+ void *gl_surface,
363+ VASurfaceID surface,
364+ unsigned int flags
365+)
366+{
367+ VADriverContextP ctx;
368+ VASurfaceGLXP pSurfaceGLX;
369+ VAStatus status;
370+
371+ INIT_CONTEXT(ctx, dpy);
372+ INIT_SURFACE(pSurfaceGLX, gl_surface);
373+
374+ INVOKE(ctx, AssociateSurface, (ctx, pSurfaceGLX, surface, flags));
375+
376+ if (status == VA_STATUS_SUCCESS)
377+ pSurfaceGLX->surface = surface;
378+
379+ return status;
380+}
381+
382+// Deassociate a VA surface from a VA/GLX surface
383+VAStatus vaDeassociateSurfaceGLX(
384+ VADisplay dpy,
385+ void *gl_surface
386+)
387+{
388+ VADriverContextP ctx;
389+ VASurfaceGLXP pSurfaceGLX;
390+ VAStatus status;
391+
392+ INIT_CONTEXT(ctx, dpy);
393+ INIT_SURFACE(pSurfaceGLX, gl_surface);
394+
395+ INVOKE(ctx, DeassociateSurface, (ctx, pSurfaceGLX));
396+
397+ if (status == VA_STATUS_SUCCESS)
398+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
399+
400+ return status;
401+}
402+
403+// Synchronize a VA/GLX surface
404+VAStatus vaSyncSurfaceGLX(
405+ VADisplay dpy,
406+ void *gl_surface
407+)
408+{
409+ VADriverContextP ctx;
410+ VASurfaceGLXP pSurfaceGLX;
411+ VAStatus status;
412+
413+ INIT_CONTEXT(ctx, dpy);
414+ INIT_SURFACE(pSurfaceGLX, gl_surface);
415+
416+ INVOKE(ctx, SyncSurface, (ctx, pSurfaceGLX));
417+ return status;
418+}
419+
420+// Prepare VA/GLX surface for rendering
421+VAStatus vaBeginRenderSurfaceGLX(
422+ VADisplay dpy,
423+ void *gl_surface
424+)
425+{
426+ VADriverContextP ctx;
427+ VASurfaceGLXP pSurfaceGLX;
428+ VAStatus status;
429+
430+ INIT_CONTEXT(ctx, dpy);
431+ INIT_SURFACE(pSurfaceGLX, gl_surface);
432+
433+ INVOKE(ctx, BeginRenderSurface, (ctx, pSurfaceGLX));
434+ return status;
435+}
436+
437+// Notify the server that the VA/GLX surface is no longer used for rendering
438+VAStatus vaEndRenderSurfaceGLX(
439+ VADisplay dpy,
440+ void *gl_surface
441+)
442+{
443+ VADriverContextP ctx;
444+ VASurfaceGLXP pSurfaceGLX;
445+ VAStatus status;
446+
447+ INIT_CONTEXT(ctx, dpy);
448+ INIT_SURFACE(pSurfaceGLX, gl_surface);
449+
450+ INVOKE(ctx, EndRenderSurface, (ctx, pSurfaceGLX));
451+ return status;
452+}
453+
454+// Copy a VA surface to a VA/GLX surface
455+VAStatus vaCopySurfaceGLX(
456+ VADisplay dpy,
457+ void *gl_surface,
458+ VASurfaceID surface,
459+ unsigned int flags
460+)
461+{
462+ VADriverContextP ctx;
463+ VASurfaceGLXP pSurfaceGLX;
464+ VAStatus status;
465+
466+ INIT_CONTEXT(ctx, dpy);
467+ INIT_SURFACE(pSurfaceGLX, gl_surface);
468+
469+ INVOKE(ctx, CopySurface, (ctx, pSurfaceGLX, surface, flags));
470+ return status;
471+}
472diff --git a/src/glx/va_glx.h b/src/glx/va_glx.h
473new file mode 100644
474index 0000000..183ef3a
475--- /dev/null
476+++ b/src/glx/va_glx.h
477@@ -0,0 +1,217 @@
478+/*
479+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
480+ *
481+ * Permission is hereby granted, free of charge, to any person obtaining a
482+ * copy of this software and associated documentation files (the
483+ * "Software"), to deal in the Software without restriction, including
484+ * without limitation the rights to use, copy, modify, merge, publish,
485+ * distribute, sub license, and/or sell copies of the Software, and to
486+ * permit persons to whom the Software is furnished to do so, subject to
487+ * the following conditions:
488+ *
489+ * The above copyright notice and this permission notice (including the
490+ * next paragraph) shall be included in all copies or substantial portions
491+ * of the Software.
492+ *
493+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
494+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
495+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
496+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
497+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
498+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
499+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
500+ */
501+
502+#ifndef VA_GLX_H
503+#define VA_GLX_H
504+
505+#ifdef IN_LIBVA
506+#include "va.h"
507+#else
508+#include <va/va.h>
509+#endif
510+#include <GL/glx.h>
511+
512+#ifdef __cplusplus
513+extern "C" {
514+#endif
515+
516+/**
517+ * Return a suitable VADisplay for VA API
518+ *
519+ * @param[in] dpy the X11 display
520+ * @return a VADisplay
521+ */
522+VADisplay vaGetDisplayGLX(
523+ Display *dpy
524+);
525+
526+/**
527+ * Create a surface used for display to OpenGL
528+ *
529+ * The application shall maintain the live GLX context itself.
530+ * Implementations are free to use glXGetCurrentContext() and
531+ * glXGetCurrentDrawable() functions for internal purposes.
532+ *
533+ * @param[in] dpy the VA display
534+ * @param[in] target the GL target to which the texture needs to be bound
535+ * @param[in] texture the GL texture
536+ * @param[out] gl_surface the VA/GLX surface
537+ * @return VA_STATUS_SUCCESS if successful
538+ */
539+VAStatus vaCreateSurfaceGLX(
540+ VADisplay dpy,
541+ GLenum target,
542+ GLuint texture,
543+ void **gl_surface
544+);
545+
546+/**
547+ * Destroy a VA/GLX surface
548+ *
549+ * The application shall maintain the live GLX context itself.
550+ * Implementations are free to use glXGetCurrentContext() and
551+ * glXGetCurrentDrawable() functions for internal purposes.
552+ *
553+ * @param[in] dpy the VA display
554+ * @param[in] gl_surface the VA surface
555+ * @return VA_STATUS_SUCCESS if successful
556+ */
557+VAStatus vaDestroySurfaceGLX(
558+ VADisplay dpy,
559+ void *gl_surface
560+);
561+
562+/**
563+ * Associate a VA surface to a VA/GLX surface
564+ *
565+ * The association is live until vaDeassociateSurfaceGLX(),
566+ * vaCopySurfaceGLX() or the next call to vaBeginPicture() with the
567+ * specificed VA surface.
568+ *
569+ * The application shall maintain the live GLX context itself.
570+ * Implementations are free to use glXGetCurrentContext() and
571+ * glXGetCurrentDrawable() functions for internal purposes.
572+ *
573+ * @param[in] dpy the VA display
574+ * @param[in] gl_surface the VA/GLX surface
575+ * @param[in] surface the VA surface
576+ * @param[in] flags the PutSurface flags
577+ * @return VA_STATUS_SUCCESS if successful
578+ */
579+VAStatus vaAssociateSurfaceGLX(
580+ VADisplay dpy,
581+ void *gl_surface,
582+ VASurfaceID surface,
583+ unsigned int flags
584+);
585+
586+/**
587+ * Deassociate a VA surface from a VA/GLX surface
588+ *
589+ * The application shall maintain the live GLX context itself.
590+ * Implementations are free to use glXGetCurrentContext() and
591+ * glXGetCurrentDrawable() functions for internal purposes.
592+ *
593+ * @param[in] dpy the VA display
594+ * @param[in] gl_surface the VA surface
595+ * @return VA_STATUS_SUCCESS if successful
596+ */
597+VAStatus vaDeassociateSurfaceGLX(
598+ VADisplay dpy,
599+ void *gl_surface
600+);
601+
602+/**
603+ * Synchronize a VA/GLX surface
604+ *
605+ * This function blocks until all pending operations on the VA/GLX
606+ * surface have been completed.
607+ *
608+ * The application shall maintain the live GLX context itself.
609+ * Implementations are free to use glXGetCurrentContext() and
610+ * glXGetCurrentDrawable() functions for internal purposes.
611+ *
612+ * @param[in] dpy the VA display
613+ * @param[in] gl_surface the VA surface
614+ * @return VA_STATUS_SUCCESS if successful
615+ */
616+VAStatus vaSyncSurfaceGLX(
617+ VADisplay dpy,
618+ void *gl_surface
619+);
620+
621+/**
622+ * Prepare VA/GLX surface for rendering
623+ *
624+ * This function performs an implicit vaSyncSurfaceGLX().
625+ *
626+ * Implementations using the GLX texture-from-pixmap extension will
627+ * generally call glXBindTexImage() here.
628+ *
629+ * The application shall maintain the live GLX context itself.
630+ * Implementations are free to use glXGetCurrentContext() and
631+ * glXGetCurrentDrawable() functions for internal purposes.
632+ *
633+ * @param[in] dpy the VA display
634+ * @param[in] gl_surface the VA surface
635+ * @return VA_STATUS_SUCCESS if successful
636+ */
637+VAStatus vaBeginRenderSurfaceGLX(
638+ VADisplay dpy,
639+ void *gl_surface
640+);
641+
642+/**
643+ * Notify the server that the VA/GLX surface is no longer used for
644+ * rendering
645+ *
646+ * Implementations using the GLX texture-from-pixmap extension will
647+ * generally call glXReleaseTexImage() here.
648+ *
649+ * The application shall maintain the live GLX context itself.
650+ * Implementations are free to use glXGetCurrentContext() and
651+ * glXGetCurrentDrawable() functions for internal purposes.
652+ *
653+ * @param[in] dpy the VA display
654+ * @param[in] gl_surface the VA surface
655+ * @return VA_STATUS_SUCCESS if successful
656+ */
657+VAStatus vaEndRenderSurfaceGLX(
658+ VADisplay dpy,
659+ void *gl_surface
660+);
661+
662+/**
663+ * Copy a VA surface to a VA/GLX surface
664+ *
665+ * This function kills any association that was previously made with
666+ * vaAssociateSurfaceGLX() and will not return until the copy is
667+ * completed.
668+ *
669+ * Upon successful return, the underlying GL texture will contain the
670+ * complete pixels and no call to vaBeginRenderSurfaceGLX() or
671+ * vaEndRenderSurfaceGLX() is required.
672+ *
673+ * The application shall maintain the live GLX context itself.
674+ * Implementations are free to use glXGetCurrentContext() and
675+ * glXGetCurrentDrawable() functions for internal purposes.
676+ *
677+ * @param[in] dpy the VA display
678+ * @param[in] gl_surface the VA/GLX destination surface
679+ * @param[in] surface the VA source surface
680+ * @param[in] flags the PutSurface flags
681+ * @return VA_STATUS_SUCCESS if successful
682+ */
683+VAStatus vaCopySurfaceGLX(
684+ VADisplay dpy,
685+ void *gl_surface,
686+ VASurfaceID surface,
687+ unsigned int flags
688+);
689+
690+#ifdef __cplusplus
691+}
692+#endif
693+
694+#endif /* VA_GLX_H */
695diff --git a/src/glx/va_glx_impl.c b/src/glx/va_glx_impl.c
696new file mode 100644
697index 0000000..d4f9c1d
698--- /dev/null
699+++ b/src/glx/va_glx_impl.c
700@@ -0,0 +1,1168 @@
701+/*
702+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
703+ *
704+ * Permission is hereby granted, free of charge, to any person obtaining a
705+ * copy of this software and associated documentation files (the
706+ * "Software"), to deal in the Software without restriction, including
707+ * without limitation the rights to use, copy, modify, merge, publish,
708+ * distribute, sub license, and/or sell copies of the Software, and to
709+ * permit persons to whom the Software is furnished to do so, subject to
710+ * the following conditions:
711+ *
712+ * The above copyright notice and this permission notice (including the
713+ * next paragraph) shall be included in all copies or substantial portions
714+ * of the Software.
715+ *
716+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
717+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
718+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
719+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
720+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
721+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
722+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
723+ */
724+
725+#define _GNU_SOURCE 1
726+#include "va_glx_private.h"
727+#include "va_glx_impl.h"
728+#include <stdio.h>
729+#include <stdarg.h>
730+#include <string.h>
731+#include <assert.h>
732+#include <dlfcn.h>
733+
734+static void va_glx_error_message(const char *format, ...)
735+{
736+ va_list args;
737+ va_start(args, format);
738+ fprintf(stderr, "[%s] ", PACKAGE_NAME);
739+ vfprintf(stderr, format, args);
740+ va_end(args);
741+}
742+
743+// X error trap
744+static int x11_error_code = 0;
745+static int (*old_error_handler)(Display *, XErrorEvent *);
746+
747+static int error_handler(Display *dpy, XErrorEvent *error)
748+{
749+ x11_error_code = error->error_code;
750+ return 0;
751+}
752+
753+static void x11_trap_errors(void)
754+{
755+ x11_error_code = 0;
756+ old_error_handler = XSetErrorHandler(error_handler);
757+}
758+
759+static int x11_untrap_errors(void)
760+{
761+ XSetErrorHandler(old_error_handler);
762+ return x11_error_code;
763+}
764+
765+// Returns a string representation of an OpenGL error
766+static const char *gl_get_error_string(GLenum error)
767+{
768+ static const struct {
769+ GLenum val;
770+ const char *str;
771+ }
772+ gl_errors[] = {
773+ { GL_NO_ERROR, "no error" },
774+ { GL_INVALID_ENUM, "invalid enumerant" },
775+ { GL_INVALID_VALUE, "invalid value" },
776+ { GL_INVALID_OPERATION, "invalid operation" },
777+ { GL_STACK_OVERFLOW, "stack overflow" },
778+ { GL_STACK_UNDERFLOW, "stack underflow" },
779+ { GL_OUT_OF_MEMORY, "out of memory" },
780+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
781+ { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
782+#endif
783+ { ~0, NULL }
784+ };
785+
786+ int i;
787+ for (i = 0; gl_errors[i].str; i++) {
788+ if (gl_errors[i].val == error)
789+ return gl_errors[i].str;
790+ }
791+ return "unknown";
792+}
793+
794+static inline int gl_do_check_error(int report)
795+{
796+ GLenum error;
797+ int is_error = 0;
798+ while ((error = glGetError()) != GL_NO_ERROR) {
799+ if (report)
800+ va_glx_error_message("glError: %s caught\n",
801+ gl_get_error_string(error));
802+ is_error = 1;
803+ }
804+ return is_error;
805+}
806+
807+static inline void gl_purge_errors(void)
808+{
809+ gl_do_check_error(0);
810+}
811+
812+static inline int gl_check_error(void)
813+{
814+ return gl_do_check_error(1);
815+}
816+
817+// glGetFloatv() wrapper
818+static int gl_get_current_color(float color[4])
819+{
820+ gl_purge_errors();
821+ glGetFloatv(GL_CURRENT_COLOR, color);
822+ if (gl_check_error())
823+ return -1;
824+ return 0;
825+}
826+
827+// glGetIntegerv() wrapper
828+static int gl_get_param(GLenum param, unsigned int *pval)
829+{
830+ GLint val;
831+
832+ gl_purge_errors();
833+ glGetIntegerv(param, &val);
834+ if (gl_check_error())
835+ return -1;
836+ if (pval)
837+ *pval = val;
838+ return 0;
839+}
840+
841+// glGetTexLevelParameteriv() wrapper
842+static int gl_get_texture_param(GLenum param, unsigned int *pval)
843+{
844+ GLint val;
845+
846+ gl_purge_errors();
847+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, param, &val);
848+ if (gl_check_error())
849+ return -1;
850+ if (pval)
851+ *pval = val;
852+ return 0;
853+}
854+
855+// Returns the OpenGL VTable
856+static inline VAOpenGLVTableP gl_get_vtable(VADriverContextP ctx)
857+{
858+ return &VA_DRIVER_CONTEXT_GLX(ctx)->gl_vtable;
859+}
860+
861+// Lookup for a GLX function
862+typedef void (*GLFuncPtr)(void);
863+typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
864+
865+static GLFuncPtr get_proc_address_default(const char *name)
866+{
867+ return NULL;
868+}
869+
870+static GLXGetProcAddressProc get_proc_address_func(void)
871+{
872+ GLXGetProcAddressProc get_proc_func;
873+
874+ dlerror();
875+ get_proc_func = (GLXGetProcAddressProc)
876+ dlsym(RTLD_DEFAULT, "glXGetProcAddress");
877+ if (dlerror() == NULL)
878+ return get_proc_func;
879+
880+ get_proc_func = (GLXGetProcAddressProc)
881+ dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
882+ if (dlerror() == NULL)
883+ return get_proc_func;
884+
885+ return get_proc_address_default;
886+}
887+
888+static inline GLFuncPtr get_proc_address(const char *name)
889+{
890+ static GLXGetProcAddressProc get_proc_func = NULL;
891+ if (get_proc_func == NULL)
892+ get_proc_func = get_proc_address_func();
893+ return get_proc_func(name);
894+}
895+
896+// Check for GLX extensions (TFP, FBO)
897+static int check_extension(const char *name, const char *ext)
898+{
899+ const char *end;
900+ int name_len, n;
901+
902+ if (name == NULL || ext == NULL)
903+ return 0;
904+
905+ end = ext + strlen(ext);
906+ name_len = strlen(name);
907+ while (ext < end) {
908+ n = strcspn(ext, " ");
909+ if (n == name_len && strncmp(name, ext, n) == 0)
910+ return 1;
911+ ext += (n + 1);
912+ }
913+ return 0;
914+}
915+
916+static int check_tfp_extensions(VADriverContextP ctx)
917+{
918+ const char *gl_extensions;
919+ const char *glx_extensions;
920+
921+ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
922+ if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions))
923+ return 0;
924+
925+ glx_extensions = glXQueryExtensionsString(ctx->x11_dpy, ctx->x11_screen);
926+ if (!check_extension("GLX_EXT_texture_from_pixmap", glx_extensions))
927+ return 0;
928+ return 1;
929+}
930+
931+static int check_fbo_extensions(VADriverContextP ctx)
932+{
933+ const char *gl_extensions;
934+
935+ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
936+ if (!check_extension("GL_ARB_framebuffer_object", gl_extensions))
937+ return 0;
938+ if (!check_extension("GL_EXT_framebuffer_object", gl_extensions))
939+ return 0;
940+ return 1;
941+}
942+
943+// Load GLX extensions
944+static int load_tfp_extensions(VADriverContextP ctx)
945+{
946+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
947+
948+ pOpenGLVTable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
949+ get_proc_address("glXBindTexImageEXT");
950+ if (pOpenGLVTable->glx_bind_tex_image == NULL)
951+ return 0;
952+ pOpenGLVTable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
953+ get_proc_address("glXReleaseTexImageEXT");
954+ if (pOpenGLVTable->glx_release_tex_image == NULL)
955+ return 0;
956+ return 1;
957+}
958+
959+static int load_fbo_extensions(VADriverContextP ctx)
960+{
961+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
962+
963+ pOpenGLVTable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
964+ get_proc_address("glGenFramebuffersEXT");
965+ if (pOpenGLVTable->gl_gen_framebuffers == NULL)
966+ return 0;
967+ pOpenGLVTable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
968+ get_proc_address("glDeleteFramebuffersEXT");
969+ if (pOpenGLVTable->gl_delete_framebuffers == NULL)
970+ return 0;
971+ pOpenGLVTable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
972+ get_proc_address("glBindFramebufferEXT");
973+ if (pOpenGLVTable->gl_bind_framebuffer == NULL)
974+ return 0;
975+ pOpenGLVTable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
976+ get_proc_address("glGenRenderbuffersEXT");
977+ if (pOpenGLVTable->gl_gen_renderbuffers == NULL)
978+ return 0;
979+ pOpenGLVTable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
980+ get_proc_address("glDeleteRenderbuffersEXT");
981+ if (pOpenGLVTable->gl_delete_renderbuffers == NULL)
982+ return 0;
983+ pOpenGLVTable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
984+ get_proc_address("glBindRenderbufferEXT");
985+ if (pOpenGLVTable->gl_bind_renderbuffer == NULL)
986+ return 0;
987+ pOpenGLVTable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
988+ get_proc_address("glRenderbufferStorageEXT");
989+ if (pOpenGLVTable->gl_renderbuffer_storage == NULL)
990+ return 0;
991+ pOpenGLVTable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
992+ get_proc_address("glFramebufferRenderbufferEXT");
993+ if (pOpenGLVTable->gl_framebuffer_renderbuffer == NULL)
994+ return 0;
995+ pOpenGLVTable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
996+ get_proc_address("glFramebufferTexture2DEXT");
997+ if (pOpenGLVTable->gl_framebuffer_texture_2d == NULL)
998+ return 0;
999+ pOpenGLVTable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
1000+ get_proc_address("glCheckFramebufferStatusEXT");
1001+ if (pOpenGLVTable->gl_check_framebuffer_status == NULL)
1002+ return 0;
1003+ return 1;
1004+}
1005+
1006+
1007+/* ========================================================================= */
1008+/* === VA/GLX helpers === */
1009+/* ========================================================================= */
1010+
1011+// OpenGL texture state
1012+typedef struct OpenGLTextureState *OpenGLTextureStateP;
1013+
1014+struct OpenGLTextureState {
1015+ int was_enabled;
1016+ int was_bound;
1017+ GLenum target;
1018+ GLuint old_texture;
1019+};
1020+
1021+// Bind texture, preserve previous texture state
1022+static int bind_texture(OpenGLTextureStateP ts, GLenum target, GLuint texture)
1023+{
1024+ ts->target = target;
1025+ ts->old_texture = 0;
1026+ ts->was_bound = 0;
1027+ ts->was_enabled = glIsEnabled(target);
1028+ if (!ts->was_enabled)
1029+ glEnable(target);
1030+
1031+ GLenum texture_binding;
1032+ switch (target) {
1033+ case GL_TEXTURE_1D:
1034+ texture_binding = GL_TEXTURE_BINDING_1D;
1035+ break;
1036+ case GL_TEXTURE_2D:
1037+ texture_binding = GL_TEXTURE_BINDING_2D;
1038+ break;
1039+ case GL_TEXTURE_3D:
1040+ texture_binding = GL_TEXTURE_BINDING_3D;
1041+ break;
1042+ case GL_TEXTURE_RECTANGLE_ARB:
1043+ texture_binding = GL_TEXTURE_BINDING_RECTANGLE_ARB;
1044+ break;
1045+ default:
1046+ assert(!target);
1047+ return -1;
1048+ }
1049+
1050+ if (ts->was_enabled && gl_get_param(texture_binding, &ts->old_texture) < 0)
1051+ return -1;
1052+
1053+ ts->was_bound = texture == ts->old_texture;
1054+ if (!ts->was_bound) {
1055+ gl_purge_errors();
1056+ glBindTexture(target, texture);
1057+ if (gl_check_error())
1058+ return -1;
1059+ }
1060+ return 0;
1061+}
1062+
1063+// Unbind texture, restore previous texture state
1064+static void unbind_texture(OpenGLTextureStateP ts)
1065+{
1066+ if (!ts->was_bound && ts->old_texture)
1067+ glBindTexture(ts->target, ts->old_texture);
1068+ if (!ts->was_enabled)
1069+ glDisable(ts->target);
1070+}
1071+
1072+// Create Pixmaps for GLX texture-from-pixmap extension
1073+static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1074+{
1075+ const unsigned int width = pSurfaceGLX->width;
1076+ const unsigned int height = pSurfaceGLX->height;
1077+ Pixmap pixmap = None;
1078+ GLXFBConfig *fbconfig = NULL;
1079+ GLXPixmap glx_pixmap = None;
1080+ Window root_window;
1081+ XWindowAttributes wattr;
1082+ int *attrib;
1083+ int n_fbconfig_attribs, x, y, status;
1084+ unsigned int border_width, depth, dummy;
1085+
1086+ root_window = RootWindow(ctx->x11_dpy, ctx->x11_screen);
1087+ XGetWindowAttributes(ctx->x11_dpy, root_window, &wattr);
1088+ pixmap = XCreatePixmap(ctx->x11_dpy, root_window,
1089+ width, height, wattr.depth);
1090+ if (!pixmap)
1091+ return -1;
1092+ pSurfaceGLX->pixmap = pixmap;
1093+
1094+ x11_trap_errors();
1095+ status = XGetGeometry(ctx->x11_dpy,
1096+ (Drawable)pixmap,
1097+ &root_window,
1098+ &x,
1099+ &y,
1100+ &dummy,
1101+ &dummy,
1102+ &border_width,
1103+ &depth);
1104+ if (x11_untrap_errors() != 0 || status == 0)
1105+ return -1;
1106+ if (depth != 24 && depth != 32)
1107+ return -1;
1108+
1109+ int fbconfig_attribs[32] = {
1110+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
1111+ GLX_DOUBLEBUFFER, GL_TRUE,
1112+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
1113+ GLX_X_RENDERABLE, GL_TRUE,
1114+ GLX_Y_INVERTED_EXT, GL_TRUE,
1115+ GLX_RED_SIZE, 8,
1116+ GLX_GREEN_SIZE, 8,
1117+ GLX_BLUE_SIZE, 8,
1118+ GL_NONE,
1119+ };
1120+ for (attrib = fbconfig_attribs; *attrib != GL_NONE; attrib += 2)
1121+ ;
1122+ *attrib++ = GLX_DEPTH_SIZE; *attrib++ = depth;
1123+ if (depth == 32) {
1124+ *attrib++ = GLX_ALPHA_SIZE; *attrib++ = 8;
1125+ *attrib++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attrib++ = GL_TRUE;
1126+ }
1127+ else {
1128+ *attrib++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attrib++ = GL_TRUE;
1129+ }
1130+ *attrib++ = GL_NONE;
1131+
1132+ fbconfig = glXChooseFBConfig(ctx->x11_dpy, ctx->x11_screen, fbconfig_attribs, &n_fbconfig_attribs);
1133+ if (fbconfig == NULL)
1134+ return -1;
1135+
1136+ int pixmap_attribs[10] = {
1137+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
1138+ GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
1139+ GL_NONE,
1140+ };
1141+ for (attrib = pixmap_attribs; *attrib != GL_NONE; attrib += 2)
1142+ ;
1143+ *attrib++ = GLX_TEXTURE_FORMAT_EXT;
1144+ if (depth == 32)
1145+ *attrib++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
1146+ else
1147+ *attrib++ = GLX_TEXTURE_FORMAT_RGB_EXT;
1148+ *attrib++ = GL_NONE;
1149+
1150+ x11_trap_errors();
1151+ glx_pixmap = glXCreatePixmap(ctx->x11_dpy,
1152+ fbconfig[0],
1153+ pixmap,
1154+ pixmap_attribs);
1155+ free(fbconfig);
1156+ if (x11_untrap_errors() != 0)
1157+ return -1;
1158+ pSurfaceGLX->glx_pixmap = glx_pixmap;
1159+ return 0;
1160+}
1161+
1162+// Destroy Pixmaps used for TFP
1163+static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1164+{
1165+ if (pSurfaceGLX->glx_pixmap) {
1166+ glXDestroyPixmap(ctx->x11_dpy, pSurfaceGLX->glx_pixmap);
1167+ pSurfaceGLX->glx_pixmap = None;
1168+ }
1169+
1170+ if (pSurfaceGLX->pixmap) {
1171+ XFreePixmap(ctx->x11_dpy, pSurfaceGLX->pixmap);
1172+ pSurfaceGLX->pixmap = None;
1173+ }
1174+}
1175+
1176+// Bind GLX Pixmap to texture
1177+static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1178+{
1179+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1180+
1181+ if (pSurfaceGLX->is_bound)
1182+ return 0;
1183+
1184+ x11_trap_errors();
1185+ pOpenGLVTable->glx_bind_tex_image(ctx->x11_dpy, pSurfaceGLX->glx_pixmap,
1186+ GLX_FRONT_LEFT_EXT, NULL);
1187+ XSync(ctx->x11_dpy, False);
1188+ if (x11_untrap_errors() != 0) {
1189+ va_glx_error_message("failed to bind pixmap\n");
1190+ return -1;
1191+ }
1192+
1193+ pSurfaceGLX->is_bound = 1;
1194+ return 0;
1195+}
1196+
1197+// Release GLX Pixmap from texture
1198+static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1199+{
1200+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1201+
1202+ if (!pSurfaceGLX->is_bound)
1203+ return 0;
1204+
1205+ x11_trap_errors();
1206+ pOpenGLVTable->glx_release_tex_image(ctx->x11_dpy, pSurfaceGLX->glx_pixmap,
1207+ GLX_FRONT_LEFT_EXT);
1208+ XSync(ctx->x11_dpy, False);
1209+ if (x11_untrap_errors() != 0) {
1210+ va_glx_error_message("failed to release pixmap\n");
1211+ return -1;
1212+ }
1213+
1214+ pSurfaceGLX->is_bound = 0;
1215+ return 0;
1216+}
1217+
1218+// Render GLX Pixmap to texture
1219+static void render_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1220+{
1221+ const unsigned int w = pSurfaceGLX->width;
1222+ const unsigned int h = pSurfaceGLX->height;
1223+ float old_color[4];
1224+
1225+ gl_get_current_color(old_color);
1226+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
1227+ glBegin(GL_QUADS);
1228+ {
1229+ glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
1230+ glTexCoord2f(0.0f, 1.0f); glVertex2i(0, h);
1231+ glTexCoord2f(1.0f, 1.0f); glVertex2i(w, h);
1232+ glTexCoord2f(1.0f, 0.0f); glVertex2i(w, 0);
1233+ }
1234+ glEnd();
1235+ glColor4fv(old_color);
1236+}
1237+
1238+// Create offscreen surface
1239+static int create_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1240+{
1241+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1242+ const GLenum texture = pSurfaceGLX->texture;
1243+ const unsigned int texture_width = pSurfaceGLX->width;
1244+ const unsigned int texture_height = pSurfaceGLX->height;
1245+ GLuint fbo, fbo_buffer, fbo_texture;
1246+ GLenum status;
1247+
1248+ glGenTextures(1, &fbo_texture);
1249+ glBindTexture(GL_TEXTURE_2D, fbo_texture);
1250+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1251+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1252+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1253+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1254+ glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1255+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture_width, texture_height, 0,
1256+ GL_BGRA, GL_UNSIGNED_BYTE, NULL);
1257+
1258+ pOpenGLVTable->gl_gen_framebuffers(1, &fbo);
1259+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo);
1260+ pOpenGLVTable->gl_gen_renderbuffers(1, &fbo_buffer);
1261+ pOpenGLVTable->gl_bind_renderbuffer(GL_RENDERBUFFER_EXT, fbo_buffer);
1262+
1263+ glBindTexture(GL_TEXTURE_2D, texture);
1264+ pOpenGLVTable->gl_framebuffer_texture_2d(GL_FRAMEBUFFER_EXT,
1265+ GL_COLOR_ATTACHMENT0_EXT,
1266+ GL_TEXTURE_2D, texture, 0);
1267+
1268+ status = pOpenGLVTable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
1269+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
1270+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
1271+ return -1;
1272+
1273+ pSurfaceGLX->fbo = fbo;
1274+ pSurfaceGLX->fbo_buffer = fbo_buffer;
1275+ pSurfaceGLX->fbo_texture = fbo_texture;
1276+ return 0;
1277+}
1278+
1279+// Destroy offscreen surface
1280+static void destroy_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1281+{
1282+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1283+
1284+ if (pSurfaceGLX->fbo_texture) {
1285+ glDeleteTextures(1, &pSurfaceGLX->fbo_texture);
1286+ pSurfaceGLX->fbo_texture = 0;
1287+ }
1288+
1289+ if (pSurfaceGLX->fbo_buffer) {
1290+ pOpenGLVTable->gl_delete_renderbuffers(1, &pSurfaceGLX->fbo_buffer);
1291+ pSurfaceGLX->fbo_buffer = 0;
1292+ }
1293+
1294+ if (pSurfaceGLX->fbo) {
1295+ pOpenGLVTable->gl_delete_framebuffers(1, &pSurfaceGLX->fbo);
1296+ pSurfaceGLX->fbo = 0;
1297+ }
1298+}
1299+
1300+// Setup matrices to match the FBO texture dimensions
1301+static void fbo_enter(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
1302+{
1303+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1304+ const unsigned int width = pSurfaceGLX->width;
1305+ const unsigned int height = pSurfaceGLX->height;
1306+
1307+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, pSurfaceGLX->fbo);
1308+ glPushAttrib(GL_VIEWPORT_BIT);
1309+ glMatrixMode(GL_PROJECTION);
1310+ glPushMatrix();
1311+ glLoadIdentity();
1312+ glMatrixMode(GL_MODELVIEW);
1313+ glPushMatrix();
1314+ glLoadIdentity();
1315+ glViewport(0, 0, width, height);
1316+ glTranslatef(-1.0f, -1.0f, 0.0f);
1317+ glScalef(2.0f / width, 2.0f / height, 1.0f);
1318+
1319+ glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->fbo_texture);
1320+}
1321+
1322+// Restore original OpenGL matrices
1323+static void fbo_leave(VADriverContextP ctx)
1324+{
1325+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
1326+
1327+ glPopAttrib();
1328+ glMatrixMode(GL_PROJECTION);
1329+ glPopMatrix();
1330+ glMatrixMode(GL_MODELVIEW);
1331+ glPopMatrix();
1332+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
1333+}
1334+
1335+// Create VA/GLX surface
1336+VASurfaceGLXP
1337+va_glx_create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
1338+{
1339+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1340+ VASurfaceGLXP pSurfaceGLX;
1341+ unsigned int internal_format, border_width, width, height;
1342+ int is_error = 1;
1343+
1344+ /* Make sure binding succeeds, if texture was not already bound */
1345+ struct OpenGLTextureState ts;
1346+ if (bind_texture(&ts, target, texture) < 0)
1347+ goto end;
1348+
1349+ pSurfaceGLX = malloc(sizeof(*pSurfaceGLX));
1350+ if (!pSurfaceGLX)
1351+ goto end;
1352+
1353+ pSurfaceGLX->magic = VA_SURFACE_GLX_MAGIC;
1354+ pSurfaceGLX->target = target;
1355+ pSurfaceGLX->texture = texture;
1356+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
1357+ pSurfaceGLX->is_bound = 0;
1358+ pSurfaceGLX->pixmap = None;
1359+ pSurfaceGLX->glx_pixmap = None;
1360+ pSurfaceGLX->fbo = 0;
1361+ pSurfaceGLX->fbo_buffer = 0;
1362+ pSurfaceGLX->fbo_texture = 0;
1363+ pSurfaceGLX->priv = NULL;
1364+
1365+ /* XXX: we don't support other textures than RGBA */
1366+ if (gl_get_texture_param(GL_TEXTURE_INTERNAL_FORMAT, &internal_format) < 0)
1367+ goto end;
1368+ if (internal_format != GL_RGBA)
1369+ goto end;
1370+
1371+ /* Check texture dimensions */
1372+ if (gl_get_texture_param(GL_TEXTURE_BORDER, &border_width) < 0)
1373+ goto end;
1374+ if (gl_get_texture_param(GL_TEXTURE_WIDTH, &width) < 0)
1375+ goto end;
1376+ if (gl_get_texture_param(GL_TEXTURE_HEIGHT, &height) < 0)
1377+ goto end;
1378+
1379+ width -= 2 * border_width;
1380+ height -= 2 * border_width;
1381+ if (width == 0 || height == 0)
1382+ goto end;
1383+
1384+ pSurfaceGLX->width = width;
1385+ pSurfaceGLX->height = height;
1386+
1387+ /* Create Pixmaps for TFP */
1388+ if (pDriverContextGLX->use_tfp) {
1389+ if (create_tfp_surface(ctx, pSurfaceGLX) < 0)
1390+ goto end;
1391+ }
1392+
1393+ /* Create Pixmaps for FBO */
1394+ if (pDriverContextGLX->use_fbo) {
1395+ if (create_fbo_surface(ctx, pSurfaceGLX) < 0)
1396+ goto end;
1397+ }
1398+
1399+ is_error = 0;
1400+end:
1401+ if (is_error && pSurfaceGLX)
1402+ va_glx_destroy_surface(ctx, &pSurfaceGLX);
1403+
1404+ unbind_texture(&ts);
1405+ return pSurfaceGLX;
1406+}
1407+
1408+// Destroy VA/GLX surface
1409+void va_glx_destroy_surface(VADriverContextP ctx, VASurfaceGLXP *ppSurfaceGLX)
1410+{
1411+ VASurfaceGLXP pSurfaceGLX = *ppSurfaceGLX;
1412+
1413+ unbind_pixmap(ctx, pSurfaceGLX);
1414+ destroy_fbo_surface(ctx, pSurfaceGLX);
1415+ destroy_tfp_surface(ctx, pSurfaceGLX);
1416+
1417+ free(pSurfaceGLX);
1418+ *ppSurfaceGLX = NULL;
1419+}
1420+
1421+
1422+/* ========================================================================= */
1423+/* === VA/GLX implementation from the driver (fordward calls) === */
1424+/* ========================================================================= */
1425+
1426+#define INVOKE(ctx, func, args) do { \
1427+ VADriverVTableGLXP vtable = &(ctx)->vtable.glx; \
1428+ if (!vtable->va##func##GLX) \
1429+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
1430+ \
1431+ VAStatus status = vtable->va##func##GLX args; \
1432+ if (status != VA_STATUS_SUCCESS) \
1433+ return status; \
1434+ } while (0)
1435+
1436+static VAStatus
1437+vaCreateSurfaceGLX_impl_driver(
1438+ VADriverContextP ctx,
1439+ GLenum target,
1440+ GLuint texture,
1441+ void **gl_surface
1442+)
1443+{
1444+ INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
1445+ return VA_STATUS_SUCCESS;
1446+}
1447+
1448+static VAStatus
1449+vaDestroySurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
1450+{
1451+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1452+
1453+ INVOKE(ctx, DestroySurface, (ctx, pSurfaceGLX->priv));
1454+ return VA_STATUS_SUCCESS;
1455+}
1456+
1457+static VAStatus
1458+vaAssociateSurfaceGLX_impl_driver(
1459+ VADriverContextP ctx,
1460+ void *gl_surface,
1461+ VASurfaceID surface,
1462+ unsigned int flags
1463+)
1464+{
1465+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1466+
1467+ INVOKE(ctx, AssociateSurface, (ctx, pSurfaceGLX->priv, surface, flags));
1468+ return VA_STATUS_SUCCESS;
1469+}
1470+
1471+static VAStatus
1472+vaDeassociateSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
1473+{
1474+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1475+
1476+ INVOKE(ctx, DeassociateSurface, (ctx, pSurfaceGLX->priv));
1477+ return VA_STATUS_SUCCESS;
1478+}
1479+
1480+static VAStatus
1481+vaSyncSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
1482+{
1483+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1484+
1485+ INVOKE(ctx, SyncSurface, (ctx, pSurfaceGLX->priv));
1486+ return VA_STATUS_SUCCESS;
1487+}
1488+
1489+static VAStatus
1490+vaBeginRenderSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
1491+{
1492+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1493+
1494+ INVOKE(ctx, BeginRenderSurface, (ctx, pSurfaceGLX->priv));
1495+ return VA_STATUS_SUCCESS;
1496+}
1497+
1498+static VAStatus
1499+vaEndRenderSurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
1500+{
1501+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1502+
1503+ INVOKE(ctx, EndRenderSurface, (ctx, pSurfaceGLX->priv));
1504+ return VA_STATUS_SUCCESS;
1505+}
1506+
1507+static VAStatus
1508+vaCopySurfaceGLX_impl_driver(
1509+ VADriverContextP ctx,
1510+ void *gl_surface,
1511+ VASurfaceID surface,
1512+ unsigned int flags
1513+)
1514+{
1515+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1516+
1517+ INVOKE(ctx, CopySurface, (ctx, pSurfaceGLX->priv, surface, flags));
1518+ return VA_STATUS_SUCCESS;
1519+}
1520+
1521+#undef INVOKE
1522+
1523+
1524+/* ========================================================================= */
1525+/* === VA/GLX implementation from libVA (generic and suboptimal path) === */
1526+/* ========================================================================= */
1527+
1528+static VAStatus
1529+vaCreateSurfaceGLX_impl_libva(
1530+ VADriverContextP ctx,
1531+ GLenum target,
1532+ GLuint texture,
1533+ void **gl_surface
1534+)
1535+{
1536+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1537+
1538+ if (!pDriverContextGLX->use_tfp)
1539+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1540+
1541+ *gl_surface = NULL;
1542+ return VA_STATUS_SUCCESS;
1543+}
1544+
1545+static VAStatus
1546+vaDestroySurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
1547+{
1548+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1549+
1550+ if (!pDriverContextGLX->use_tfp)
1551+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1552+
1553+ return VA_STATUS_SUCCESS;
1554+}
1555+
1556+static VAStatus
1557+vaAssociateSurfaceGLX_impl_libva(
1558+ VADriverContextP ctx,
1559+ void *gl_surface,
1560+ VASurfaceID surface,
1561+ unsigned int flags
1562+)
1563+{
1564+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1565+ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
1566+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1567+ VAStatus status;
1568+
1569+ if (!pDriverContextGLX->use_tfp)
1570+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1571+
1572+ /* XXX: only support VA_FRAME_PICTURE */
1573+ if (flags != VA_FRAME_PICTURE)
1574+ return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
1575+
1576+ /* XXX: optimise case where we are associating the same VA surface
1577+ as before an no changed occurred to it */
1578+ status = vtable->vaDeassociateSurfaceGLX(ctx, gl_surface);
1579+ if (status != VA_STATUS_SUCCESS)
1580+ return status;
1581+
1582+ x11_trap_errors();
1583+ status = ctx->vtable.vaPutSurface(ctx,
1584+ surface,
1585+ pSurfaceGLX->pixmap,
1586+ 0, 0,
1587+ pSurfaceGLX->width,
1588+ pSurfaceGLX->height,
1589+ 0, 0,
1590+ pSurfaceGLX->width,
1591+ pSurfaceGLX->height,
1592+ NULL, 0,
1593+ flags);
1594+ XSync(ctx->x11_dpy, False);
1595+ if (x11_untrap_errors() != 0)
1596+ return VA_STATUS_ERROR_OPERATION_FAILED;
1597+ if (status != VA_STATUS_SUCCESS)
1598+ return status;
1599+
1600+ pSurfaceGLX->surface = surface;
1601+ return VA_STATUS_SUCCESS;
1602+}
1603+
1604+static VAStatus
1605+vaDeassociateSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
1606+{
1607+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1608+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1609+
1610+ if (!pDriverContextGLX->use_tfp)
1611+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1612+
1613+ if (unbind_pixmap(ctx, pSurfaceGLX) < 0)
1614+ return VA_STATUS_ERROR_OPERATION_FAILED;
1615+
1616+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
1617+ return VA_STATUS_SUCCESS;
1618+}
1619+
1620+static VAStatus
1621+vaSyncSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
1622+{
1623+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1624+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1625+
1626+ if (!pDriverContextGLX->use_tfp)
1627+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1628+
1629+ if (pSurfaceGLX->surface == VA_INVALID_SURFACE)
1630+ return VA_STATUS_ERROR_INVALID_SURFACE;
1631+
1632+ return ctx->vtable.vaSyncSurface(ctx, pSurfaceGLX->surface);
1633+}
1634+
1635+static VAStatus
1636+vaBeginRenderSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
1637+{
1638+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1639+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1640+ VAStatus status;
1641+
1642+ if (!pDriverContextGLX->use_tfp)
1643+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1644+
1645+ status = vaSyncSurfaceGLX_impl_libva(ctx, gl_surface);
1646+ if (status != VA_STATUS_SUCCESS)
1647+ return status;
1648+
1649+ if (bind_pixmap(ctx, pSurfaceGLX) < 0)
1650+ return VA_STATUS_ERROR_OPERATION_FAILED;
1651+
1652+ return VA_STATUS_SUCCESS;
1653+}
1654+
1655+static VAStatus
1656+vaEndRenderSurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
1657+{
1658+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1659+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1660+ VAStatus status;
1661+
1662+ if (!pDriverContextGLX->use_tfp)
1663+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1664+
1665+ if (unbind_pixmap(ctx, pSurfaceGLX) < 0)
1666+ return VA_STATUS_ERROR_OPERATION_FAILED;
1667+
1668+ return VA_STATUS_SUCCESS;
1669+}
1670+
1671+static VAStatus
1672+vaCopySurfaceGLX_impl_libva(
1673+ VADriverContextP ctx,
1674+ void *gl_surface,
1675+ VASurfaceID surface,
1676+ unsigned int flags
1677+)
1678+{
1679+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1680+ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
1681+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1682+ VAStatus status;
1683+
1684+ if (!pDriverContextGLX->use_fbo)
1685+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1686+
1687+ /* XXX: only support VA_FRAME_PICTURE */
1688+ if (flags != VA_FRAME_PICTURE)
1689+ return VA_STATUS_ERROR_FLAG_NOT_SUPPORTED;
1690+
1691+ /* Associate VA surface */
1692+ status = vtable->vaAssociateSurfaceGLX(ctx, gl_surface, surface, flags);
1693+ if (status != VA_STATUS_SUCCESS)
1694+ return status;
1695+
1696+ /* Make sure binding succeeds, if texture was not already bound */
1697+ struct OpenGLTextureState ts;
1698+ if (bind_texture(&ts, pSurfaceGLX->target, pSurfaceGLX->texture) < 0)
1699+ return VA_STATUS_ERROR_OPERATION_FAILED;
1700+
1701+ /* Render to FBO */
1702+ fbo_enter(ctx, pSurfaceGLX);
1703+ status = vtable->vaBeginRenderSurfaceGLX(ctx, gl_surface);
1704+ if (status == VA_STATUS_SUCCESS) {
1705+ render_pixmap(ctx, pSurfaceGLX);
1706+ status = vtable->vaEndRenderSurfaceGLX(ctx, gl_surface);
1707+ }
1708+ fbo_leave(ctx);
1709+ unbind_texture(&ts);
1710+ if (status != VA_STATUS_SUCCESS)
1711+ return status;
1712+
1713+ return vtable->vaDeassociateSurfaceGLX(ctx, gl_surface);
1714+}
1715+
1716+
1717+/* ========================================================================= */
1718+/* === VA/GLX bind functions implementation with vaCopySurfaceGLX() === */
1719+/* ========================================================================= */
1720+
1721+static VAStatus
1722+vaAssociateSurfaceGLX_impl_bind(
1723+ VADriverContextP ctx,
1724+ void *gl_surface,
1725+ VASurfaceID surface,
1726+ unsigned int flags
1727+)
1728+{
1729+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1730+ VADriverVTableGLXP vtable = &pDriverContextGLX->vtable;
1731+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1732+ VAStatus status;
1733+
1734+ if (!pDriverContextGLX->has_copy)
1735+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1736+
1737+ status = vtable->vaCopySurfaceGLX(ctx, gl_surface, surface, flags);
1738+ if (status != VA_STATUS_SUCCESS)
1739+ return status;
1740+
1741+ pSurfaceGLX->surface = surface;
1742+ return VA_STATUS_SUCCESS;
1743+}
1744+
1745+static VAStatus
1746+vaDeassociateSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
1747+{
1748+ VADriverContextGLXP pDriverContextGLX = VA_DRIVER_CONTEXT_GLX(ctx);
1749+ VASurfaceGLXP pSurfaceGLX = gl_surface;
1750+
1751+ if (!pDriverContextGLX->has_copy)
1752+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1753+
1754+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
1755+ return VA_STATUS_SUCCESS;
1756+}
1757+
1758+static VAStatus
1759+vaBeginRenderSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
1760+{
1761+ /* Surface is already copied into the texture, in vaAssociateSurfaceGLX() */
1762+ return VA_STATUS_SUCCESS;
1763+}
1764+
1765+static VAStatus
1766+vaEndRenderSurfaceGLX_impl_bind(VADriverContextP ctx, void *gl_surface)
1767+{
1768+ return VA_STATUS_SUCCESS;
1769+}
1770+
1771+
1772+/* ========================================================================= */
1773+/* === Private VA/GLX vtable initialization === */
1774+/* ========================================================================= */
1775+
1776+// Initialize GLX driver context
1777+VAStatus va_glx_init_context(VADriverContextP ctx)
1778+{
1779+ VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
1780+ VADriverVTableGLXP vtable = &glx_ctx->vtable;
1781+ int needs_tfp = 0, needs_fbo = 0;
1782+
1783+ if (glx_ctx->is_initialized)
1784+ return VA_STATUS_SUCCESS;
1785+
1786+ glx_ctx->has_copy = ctx->vtable.glx.vaCopySurfaceGLX != NULL;
1787+ glx_ctx->has_bind = (ctx->vtable.glx.vaAssociateSurfaceGLX != NULL &&
1788+ ctx->vtable.glx.vaBeginRenderSurfaceGLX != NULL &&
1789+ ctx->vtable.glx.vaEndRenderSurfaceGLX != NULL &&
1790+ ctx->vtable.glx.vaDeassociateSurfaceGLX != NULL);
1791+
1792+ switch ((((unsigned int)glx_ctx->has_bind) << 1) | glx_ctx->has_copy) {
1793+ case 0:
1794+ /* Full implementation in libVA */
1795+ needs_tfp = 1;
1796+ needs_fbo = 1;
1797+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_libva;
1798+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_libva;
1799+ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_libva;
1800+ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_libva;
1801+ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_libva;
1802+ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_libva;
1803+ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_libva;
1804+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
1805+ break;
1806+ case 1:
1807+ /* Add bind functions based on vaCopySurfaceGLX() */
1808+ /* XXX: override vaSyncSurfaceGLX()? */
1809+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
1810+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
1811+ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_bind;
1812+ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_bind;
1813+ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_bind;
1814+ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_bind;
1815+ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
1816+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
1817+ break;
1818+ case 2:
1819+ /* Add copy function based on vaBeginRenderSurfaceGLX() et al. */
1820+ needs_fbo = 1;
1821+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
1822+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
1823+ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_driver;
1824+ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_driver;
1825+ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_driver;
1826+ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_driver;
1827+ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
1828+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
1829+ break;
1830+ case 3:
1831+ /* Keep driver bind & copy functions */
1832+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
1833+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
1834+ vtable->vaAssociateSurfaceGLX = vaAssociateSurfaceGLX_impl_driver;
1835+ vtable->vaDeassociateSurfaceGLX = vaDeassociateSurfaceGLX_impl_driver;
1836+ vtable->vaBeginRenderSurfaceGLX = vaBeginRenderSurfaceGLX_impl_driver;
1837+ vtable->vaEndRenderSurfaceGLX = vaEndRenderSurfaceGLX_impl_driver;
1838+ vtable->vaSyncSurfaceGLX = vaSyncSurfaceGLX_impl_driver;
1839+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
1840+ break;
1841+ default:
1842+ /* Fatal error: this cannot happen */
1843+ assert(0);
1844+ return VA_STATUS_ERROR_UNKNOWN;
1845+ }
1846+
1847+ glx_ctx->has_tfp = 0;
1848+ glx_ctx->use_tfp = 0;
1849+ glx_ctx->has_fbo = 0;
1850+ glx_ctx->use_fbo = 0;
1851+
1852+ if (needs_tfp) {
1853+ glx_ctx->has_tfp = check_tfp_extensions(ctx);
1854+ if (!glx_ctx->has_tfp || !load_tfp_extensions(ctx))
1855+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1856+ glx_ctx->use_tfp = 1;
1857+ }
1858+
1859+ if (needs_fbo) {
1860+ glx_ctx->has_fbo = check_fbo_extensions(ctx);
1861+ if (!glx_ctx->has_fbo || !load_fbo_extensions(ctx))
1862+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1863+ glx_ctx->use_fbo = 1;
1864+ }
1865+
1866+ glx_ctx->is_initialized = 1;
1867+ return VA_STATUS_SUCCESS;
1868+}
1869diff --git a/src/glx/va_glx_impl.h b/src/glx/va_glx_impl.h
1870new file mode 100644
1871index 0000000..977bfcc
1872--- /dev/null
1873+++ b/src/glx/va_glx_impl.h
1874@@ -0,0 +1,46 @@
1875+/*
1876+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
1877+ *
1878+ * Permission is hereby granted, free of charge, to any person obtaining a
1879+ * copy of this software and associated documentation files (the
1880+ * "Software"), to deal in the Software without restriction, including
1881+ * without limitation the rights to use, copy, modify, merge, publish,
1882+ * distribute, sub license, and/or sell copies of the Software, and to
1883+ * permit persons to whom the Software is furnished to do so, subject to
1884+ * the following conditions:
1885+ *
1886+ * The above copyright notice and this permission notice (including the
1887+ * next paragraph) shall be included in all copies or substantial portions
1888+ * of the Software.
1889+ *
1890+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1891+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1892+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
1893+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
1894+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1895+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1896+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1897+ */
1898+
1899+#ifndef VA_GLX_IMPL_H
1900+#define VA_GLX_IMPL_H
1901+
1902+/**
1903+ * Initialize GLX driver context
1904+ *
1905+ * @param[in] ctx the VA driver context
1906+ * @return VA_STATUS_SUCCESS if successful
1907+ */
1908+VAStatus va_glx_init_context(VADriverContextP ctx)
1909+ ATTRIBUTE_HIDDEN;
1910+
1911+/** Create VA/GLX surface */
1912+VASurfaceGLXP
1913+va_glx_create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
1914+ ATTRIBUTE_HIDDEN;
1915+
1916+/** Destroy VA/GLX surface */
1917+void va_glx_destroy_surface(VADriverContextP ctx, VASurfaceGLXP *pSurfaceGLX)
1918+ ATTRIBUTE_HIDDEN;
1919+
1920+#endif /* VA_GLX_IMPL_H */
1921diff --git a/src/glx/va_glx_private.h b/src/glx/va_glx_private.h
1922new file mode 100644
1923index 0000000..8658ad3
1924--- /dev/null
1925+++ b/src/glx/va_glx_private.h
1926@@ -0,0 +1,98 @@
1927+/*
1928+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
1929+ *
1930+ * Permission is hereby granted, free of charge, to any person obtaining a
1931+ * copy of this software and associated documentation files (the
1932+ * "Software"), to deal in the Software without restriction, including
1933+ * without limitation the rights to use, copy, modify, merge, publish,
1934+ * distribute, sub license, and/or sell copies of the Software, and to
1935+ * permit persons to whom the Software is furnished to do so, subject to
1936+ * the following conditions:
1937+ *
1938+ * The above copyright notice and this permission notice (including the
1939+ * next paragraph) shall be included in all copies or substantial portions
1940+ * of the Software.
1941+ *
1942+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1943+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1944+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
1945+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
1946+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1947+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1948+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1949+ */
1950+
1951+#ifndef VA_GLX_PRIVATE_H
1952+#define VA_GLX_PRIVATE_H
1953+
1954+#include "config.h"
1955+#include "va.h"
1956+#include "va_backend.h"
1957+#include "va_x11.h"
1958+#include "va_glx.h"
1959+
1960+#if GLX_GLXEXT_VERSION < 18
1961+typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *);
1962+typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int);
1963+#endif
1964+
1965+typedef struct VAOpenGLVTable *VAOpenGLVTableP;
1966+
1967+struct VAOpenGLVTable {
1968+ PFNGLXBINDTEXIMAGEEXTPROC glx_bind_tex_image;
1969+ PFNGLXRELEASETEXIMAGEEXTPROC glx_release_tex_image;
1970+ PFNGLGENFRAMEBUFFERSEXTPROC gl_gen_framebuffers;
1971+ PFNGLDELETEFRAMEBUFFERSEXTPROC gl_delete_framebuffers;
1972+ PFNGLBINDFRAMEBUFFEREXTPROC gl_bind_framebuffer;
1973+ PFNGLGENRENDERBUFFERSEXTPROC gl_gen_renderbuffers;
1974+ PFNGLDELETERENDERBUFFERSEXTPROC gl_delete_renderbuffers;
1975+ PFNGLBINDRENDERBUFFEREXTPROC gl_bind_renderbuffer;
1976+ PFNGLRENDERBUFFERSTORAGEEXTPROC gl_renderbuffer_storage;
1977+ PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC gl_framebuffer_renderbuffer;
1978+ PFNGLFRAMEBUFFERTEXTURE2DEXTPROC gl_framebuffer_texture_2d;
1979+ PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC gl_check_framebuffer_status;
1980+};
1981+
1982+typedef struct VADisplayContextGLX *VADisplayContextGLXP;
1983+typedef struct VADriverContextGLX *VADriverContextGLXP;
1984+typedef struct VASurfaceGLX *VASurfaceGLXP;
1985+typedef struct VADriverVTableGLX *VADriverVTableGLXP;
1986+
1987+struct VADisplayContextGLX {
1988+ void (*vaDestroy)(VADisplayContextP ctx);
1989+};
1990+
1991+#define VA_DRIVER_CONTEXT_GLX(ctx) ((VADriverContextGLXP)((ctx)->glx))
1992+
1993+struct VADriverContextGLX {
1994+ struct VADriverVTableGLX vtable;
1995+ struct VAOpenGLVTable gl_vtable;
1996+ unsigned int is_initialized : 1;
1997+ unsigned int has_copy : 1;
1998+ unsigned int has_bind : 1;
1999+ unsigned int has_tfp : 1;
2000+ unsigned int has_fbo : 1;
2001+ unsigned int use_tfp : 1;
2002+ unsigned int use_fbo : 1;
2003+};
2004+
2005+/** Unique VASurfaceGLX identifier */
2006+#define VA_SURFACE_GLX_MAGIC VA_FOURCC('V','A','G','L')
2007+
2008+struct VASurfaceGLX {
2009+ uint32_t magic; ///< Magic number identifying a VASurfaceGLX
2010+ GLenum target; ///< GL target to which the texture is bound
2011+ GLuint texture; ///< GL texture
2012+ VASurfaceID surface; ///< Associated VA surface
2013+ unsigned int width;
2014+ unsigned int height;
2015+ int is_bound;
2016+ Pixmap pixmap;
2017+ GLXPixmap glx_pixmap;
2018+ GLuint fbo;
2019+ GLuint fbo_buffer;
2020+ GLuint fbo_texture;
2021+ void *priv; ///< Private VA/GLX surface data from driver
2022+};
2023+
2024+#endif /* VA_GLX_PRIVATE_H */