• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/intel/libva


Commit MetaInfo

Revisiondeb99d31e52c1c88bda67f057f6eb6e6d32c0563 (tree)
Time2010-05-13 03:30:27
AuthorGwenole Beauchesne <gbeauchesne@spli...>
CommiterAustin Yuan

Log Message

Add OpenGL extensions (v3) and generic implementation with TFP and FBO.

Change Summary

Incremental Difference

--- /dev/null
+++ b/va/glx/Makefile.am
@@ -0,0 +1,41 @@
1+# Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
2+#
3+# Permission is hereby granted, free of charge, to any person obtaining a
4+# copy of this software and associated documentation files (the
5+# "Software"), to deal in the Software without restriction, including
6+# without limitation the rights to use, copy, modify, merge, publish,
7+# distribute, sub license, and/or sell copies of the Software, and to
8+# permit persons to whom the Software is furnished to do so, subject to
9+# the following conditions:
10+#
11+# The above copyright notice and this permission notice (including the
12+# next paragraph) shall be included in all copies or substantial portions
13+# of the Software.
14+#
15+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
18+# IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
19+# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
23+AM_CFLAGS = -DLINUX -I$(top_srcdir)/va -I$(top_srcdir)/va/x11
24+
25+source_c = \
26+ va_glx.c \
27+ va_glx_impl.c
28+
29+source_h = \
30+ va_glx.h \
31+ va_backend_glx.h
32+
33+source_h_priv = \
34+ va_glx_impl.h \
35+ va_glx_private.h
36+
37+noinst_LTLIBRARIES = libva_glx.la
38+libva_glxincludedir = ${includedir}/va
39+libva_glxinclude_HEADERS = $(source_h)
40+libva_glx_la_SOURCES = $(source_c)
41+noinst_HEADERS = $(source_h_priv)
--- /dev/null
+++ b/va/glx/va_backend_glx.h
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#ifndef VA_BACKEND_GLX_H
26+#define VA_BACKEND_GLX_H
27+
28+struct VADriverContext;
29+
30+struct VADriverVTableGLX {
31+ /* Optional: create a surface used for display to OpenGL */
32+ VAStatus (*vaCreateSurfaceGLX)(
33+ struct VADriverContext *ctx,
34+ unsigned int gl_target,
35+ unsigned int gl_texture,
36+ void **gl_surface
37+ );
38+
39+ /* Optional: destroy a VA/GLX surface */
40+ VAStatus (*vaDestroySurfaceGLX)(
41+ struct VADriverContext *ctx,
42+ void *gl_surface
43+ );
44+
45+ /* Optional: copy a VA surface to a VA/GLX surface */
46+ VAStatus (*vaCopySurfaceGLX)(
47+ struct VADriverContext *ctx,
48+ void *gl_surface,
49+ VASurfaceID surface,
50+ unsigned int flags
51+ );
52+};
53+
54+#endif /* VA_BACKEND_GLX_H */
--- /dev/null
+++ b/va/glx/va_glx.c
@@ -0,0 +1,174 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#include <stdlib.h>
26+#include "va_glx_private.h"
27+#include "va_glx_impl.h"
28+
29+#define INIT_CONTEXT(ctx, dpy) do { \
30+ if (!vaDisplayIsValid(dpy)) \
31+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
32+ \
33+ ctx = ((VADisplayContextP)(dpy))->pDriverContext; \
34+ if (!(ctx)) \
35+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
36+ \
37+ VAStatus status = va_glx_init_context(ctx); \
38+ if (status != VA_STATUS_SUCCESS) \
39+ return status; \
40+ } while (0)
41+
42+#define INVOKE(ctx, func, args) do { \
43+ VADriverVTableGLXP vtable; \
44+ vtable = &VA_DRIVER_CONTEXT_GLX(ctx)->vtable; \
45+ if (!vtable->va##func##GLX) \
46+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
47+ status = vtable->va##func##GLX args; \
48+ } while (0)
49+
50+// Check VADisplay is valid
51+static inline int vaDisplayIsValid(VADisplay dpy)
52+{
53+ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
54+
55+ return (pDisplayContext &&
56+ pDisplayContext->vaIsValid &&
57+ pDisplayContext->vaIsValid(pDisplayContext));
58+}
59+
60+// Destroy VA/GLX display context
61+static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
62+{
63+ VADisplayContextGLXP pDisplayContextGLX;
64+ VADriverContextP pDriverContext;
65+ VADriverContextGLXP pDriverContextGLX;
66+
67+ if (!pDisplayContext)
68+ return;
69+
70+ pDriverContext = pDisplayContext->pDriverContext;
71+ pDriverContextGLX = pDriverContext->glx;
72+ if (pDriverContextGLX) {
73+ free(pDriverContextGLX);
74+ pDriverContext->glx = NULL;
75+ }
76+
77+ pDisplayContextGLX = pDisplayContext->opaque;
78+ if (pDisplayContextGLX) {
79+ vaDestroyFunc vaDestroy = pDisplayContextGLX->vaDestroy;
80+ free(pDisplayContextGLX);
81+ pDisplayContext->opaque = NULL;
82+ if (vaDestroy)
83+ vaDestroy(pDisplayContext);
84+ }
85+}
86+
87+// Return a suitable VADisplay for VA API
88+VADisplay vaGetDisplayGLX(Display *native_dpy)
89+{
90+ VADisplay dpy = NULL;
91+ VADisplayContextP pDisplayContext = NULL;
92+ VADisplayContextGLXP pDisplayContextGLX = NULL;
93+ VADriverContextP pDriverContext;
94+ VADriverContextGLXP pDriverContextGLX = NULL;
95+
96+ dpy = vaGetDisplay(native_dpy);
97+ if (!dpy)
98+ return NULL;
99+ pDisplayContext = (VADisplayContextP)dpy;
100+ pDriverContext = pDisplayContext->pDriverContext;
101+
102+ pDisplayContextGLX = calloc(1, sizeof(*pDisplayContextGLX));
103+ if (!pDisplayContextGLX)
104+ goto error;
105+
106+ pDriverContextGLX = calloc(1, sizeof(*pDriverContextGLX));
107+ if (!pDriverContextGLX)
108+ goto error;
109+
110+ pDisplayContextGLX->vaDestroy = pDisplayContext->vaDestroy;
111+ pDisplayContext->vaDestroy = va_DisplayContextDestroy;
112+ pDisplayContext->opaque = pDisplayContextGLX;
113+ pDriverContext->glx = pDriverContextGLX;
114+ return dpy;
115+
116+error:
117+ free(pDriverContextGLX);
118+ free(pDisplayContextGLX);
119+ pDisplayContext->vaDestroy(pDisplayContext);
120+ return NULL;
121+}
122+
123+// Create a surface used for display to OpenGL
124+VAStatus vaCreateSurfaceGLX(
125+ VADisplay dpy,
126+ GLenum target,
127+ GLuint texture,
128+ void **gl_surface
129+)
130+{
131+ VADriverContextP ctx;
132+ VAStatus status;
133+
134+ /* Make sure it is a valid GL texture object */
135+ if (!glIsTexture(texture))
136+ return VA_STATUS_ERROR_INVALID_PARAMETER;
137+
138+ INIT_CONTEXT(ctx, dpy);
139+
140+ INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
141+ return status;
142+}
143+
144+// Destroy a VA/GLX surface
145+VAStatus vaDestroySurfaceGLX(
146+ VADisplay dpy,
147+ void *gl_surface
148+)
149+{
150+ VADriverContextP ctx;
151+ VAStatus status;
152+
153+ INIT_CONTEXT(ctx, dpy);
154+
155+ INVOKE(ctx, DestroySurface, (ctx, gl_surface));
156+ return status;
157+}
158+
159+// Copy a VA surface to a VA/GLX surface
160+VAStatus vaCopySurfaceGLX(
161+ VADisplay dpy,
162+ void *gl_surface,
163+ VASurfaceID surface,
164+ unsigned int flags
165+)
166+{
167+ VADriverContextP ctx;
168+ VAStatus status;
169+
170+ INIT_CONTEXT(ctx, dpy);
171+
172+ INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
173+ return status;
174+}
--- /dev/null
+++ b/va/glx/va_glx.h
@@ -0,0 +1,109 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#ifndef VA_GLX_H
26+#define VA_GLX_H
27+
28+#include <va/va.h>
29+#include <GL/glx.h>
30+
31+#ifdef __cplusplus
32+extern "C" {
33+#endif
34+
35+/**
36+ * Return a suitable VADisplay for VA API
37+ *
38+ * @param[in] dpy the X11 display
39+ * @return a VADisplay
40+ */
41+VADisplay vaGetDisplayGLX(
42+ Display *dpy
43+);
44+
45+/**
46+ * Create a surface used for display to OpenGL
47+ *
48+ * The application shall maintain the live GLX context itself.
49+ * Implementations are free to use glXGetCurrentContext() and
50+ * glXGetCurrentDrawable() functions for internal purposes.
51+ *
52+ * @param[in] dpy the VA display
53+ * @param[in] target the GL target to which the texture needs to be bound
54+ * @param[in] texture the GL texture
55+ * @param[out] gl_surface the VA/GLX surface
56+ * @return VA_STATUS_SUCCESS if successful
57+ */
58+VAStatus vaCreateSurfaceGLX(
59+ VADisplay dpy,
60+ GLenum target,
61+ GLuint texture,
62+ void **gl_surface
63+);
64+
65+/**
66+ * Destroy a VA/GLX surface
67+ *
68+ * The application shall maintain the live GLX context itself.
69+ * Implementations are free to use glXGetCurrentContext() and
70+ * glXGetCurrentDrawable() functions for internal purposes.
71+ *
72+ * @param[in] dpy the VA display
73+ * @param[in] gl_surface the VA surface
74+ * @return VA_STATUS_SUCCESS if successful
75+ */
76+VAStatus vaDestroySurfaceGLX(
77+ VADisplay dpy,
78+ void *gl_surface
79+);
80+
81+/**
82+ * Copy a VA surface to a VA/GLX surface
83+ *
84+ * This function will not return until the copy is completed. At this
85+ * point, the underlying GL texture will contain the surface pixels
86+ * in an RGB format defined by the user.
87+ *
88+ * The application shall maintain the live GLX context itself.
89+ * Implementations are free to use glXGetCurrentContext() and
90+ * glXGetCurrentDrawable() functions for internal purposes.
91+ *
92+ * @param[in] dpy the VA display
93+ * @param[in] gl_surface the VA/GLX destination surface
94+ * @param[in] surface the VA source surface
95+ * @param[in] flags the PutSurface flags
96+ * @return VA_STATUS_SUCCESS if successful
97+ */
98+VAStatus vaCopySurfaceGLX(
99+ VADisplay dpy,
100+ void *gl_surface,
101+ VASurfaceID surface,
102+ unsigned int flags
103+);
104+
105+#ifdef __cplusplus
106+}
107+#endif
108+
109+#endif /* VA_GLX_H */
--- /dev/null
+++ b/va/glx/va_glx_impl.c
@@ -0,0 +1,1078 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#define _GNU_SOURCE 1
26+#include "va_glx_private.h"
27+#include "va_glx_impl.h"
28+#include <stdio.h>
29+#include <stdlib.h>
30+#include <stdarg.h>
31+#include <string.h>
32+#include <assert.h>
33+#include <dlfcn.h>
34+
35+static void va_glx_error_message(const char *format, ...)
36+{
37+ va_list args;
38+ va_start(args, format);
39+ fprintf(stderr, "[%s] ", PACKAGE_NAME);
40+ vfprintf(stderr, format, args);
41+ va_end(args);
42+}
43+
44+// X error trap
45+static int x11_error_code = 0;
46+static int (*old_error_handler)(Display *, XErrorEvent *);
47+
48+static int error_handler(Display *dpy, XErrorEvent *error)
49+{
50+ x11_error_code = error->error_code;
51+ return 0;
52+}
53+
54+static void x11_trap_errors(void)
55+{
56+ x11_error_code = 0;
57+ old_error_handler = XSetErrorHandler(error_handler);
58+}
59+
60+static int x11_untrap_errors(void)
61+{
62+ XSetErrorHandler(old_error_handler);
63+ return x11_error_code;
64+}
65+
66+// Returns a string representation of an OpenGL error
67+static const char *gl_get_error_string(GLenum error)
68+{
69+ static const struct {
70+ GLenum val;
71+ const char *str;
72+ }
73+ gl_errors[] = {
74+ { GL_NO_ERROR, "no error" },
75+ { GL_INVALID_ENUM, "invalid enumerant" },
76+ { GL_INVALID_VALUE, "invalid value" },
77+ { GL_INVALID_OPERATION, "invalid operation" },
78+ { GL_STACK_OVERFLOW, "stack overflow" },
79+ { GL_STACK_UNDERFLOW, "stack underflow" },
80+ { GL_OUT_OF_MEMORY, "out of memory" },
81+#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
82+ { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "invalid framebuffer operation" },
83+#endif
84+ { ~0, NULL }
85+ };
86+
87+ int i;
88+ for (i = 0; gl_errors[i].str; i++) {
89+ if (gl_errors[i].val == error)
90+ return gl_errors[i].str;
91+ }
92+ return "unknown";
93+}
94+
95+static inline int gl_do_check_error(int report)
96+{
97+ GLenum error;
98+ int is_error = 0;
99+ while ((error = glGetError()) != GL_NO_ERROR) {
100+ if (report)
101+ va_glx_error_message("glError: %s caught\n",
102+ gl_get_error_string(error));
103+ is_error = 1;
104+ }
105+ return is_error;
106+}
107+
108+static inline void gl_purge_errors(void)
109+{
110+ gl_do_check_error(0);
111+}
112+
113+static inline int gl_check_error(void)
114+{
115+ return gl_do_check_error(1);
116+}
117+
118+// glGetTexLevelParameteriv() wrapper
119+static int gl_get_texture_param(GLenum param, unsigned int *pval)
120+{
121+ GLint val;
122+
123+ gl_purge_errors();
124+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, param, &val);
125+ if (gl_check_error())
126+ return 0;
127+ if (pval)
128+ *pval = val;
129+ return 1;
130+}
131+
132+// Returns the OpenGL VTable
133+static inline VAOpenGLVTableP gl_get_vtable(VADriverContextP ctx)
134+{
135+ return &VA_DRIVER_CONTEXT_GLX(ctx)->gl_vtable;
136+}
137+
138+// Lookup for a GLX function
139+typedef void (*GLFuncPtr)(void);
140+typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
141+
142+static GLFuncPtr get_proc_address_default(const char *name)
143+{
144+ return NULL;
145+}
146+
147+static GLXGetProcAddressProc get_proc_address_func(void)
148+{
149+ GLXGetProcAddressProc get_proc_func;
150+
151+ dlerror();
152+ get_proc_func = (GLXGetProcAddressProc)
153+ dlsym(RTLD_DEFAULT, "glXGetProcAddress");
154+ if (!dlerror())
155+ return get_proc_func;
156+
157+ get_proc_func = (GLXGetProcAddressProc)
158+ dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
159+ if (!dlerror())
160+ return get_proc_func;
161+
162+ return get_proc_address_default;
163+}
164+
165+static inline GLFuncPtr get_proc_address(const char *name)
166+{
167+ static GLXGetProcAddressProc get_proc_func = NULL;
168+ if (!get_proc_func)
169+ get_proc_func = get_proc_address_func();
170+ return get_proc_func(name);
171+}
172+
173+// Check for GLX extensions (TFP, FBO)
174+static int check_extension(const char *name, const char *ext)
175+{
176+ const char *end;
177+ int name_len, n;
178+
179+ if (!name || !ext)
180+ return 0;
181+
182+ end = ext + strlen(ext);
183+ name_len = strlen(name);
184+ while (ext < end) {
185+ n = strcspn(ext, " ");
186+ if (n == name_len && strncmp(name, ext, n) == 0)
187+ return 1;
188+ ext += (n + 1);
189+ }
190+ return 0;
191+}
192+
193+static int check_tfp_extensions(VADriverContextP ctx)
194+{
195+ const char *gl_extensions;
196+ const char *glx_extensions;
197+
198+ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
199+ if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions))
200+ return 0;
201+
202+ glx_extensions = glXQueryExtensionsString(ctx->x11_dpy, ctx->x11_screen);
203+ if (!check_extension("GLX_EXT_texture_from_pixmap", glx_extensions))
204+ return 0;
205+ return 1;
206+}
207+
208+static int check_fbo_extensions(VADriverContextP ctx)
209+{
210+ const char *gl_extensions;
211+
212+ gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
213+ if (check_extension("GL_ARB_framebuffer_object", gl_extensions))
214+ return 1;
215+ if (check_extension("GL_EXT_framebuffer_object", gl_extensions))
216+ return 1;
217+ return 0;
218+}
219+
220+// Load GLX extensions
221+static int load_tfp_extensions(VADriverContextP ctx)
222+{
223+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
224+
225+ pOpenGLVTable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
226+ get_proc_address("glXBindTexImageEXT");
227+ if (!pOpenGLVTable->glx_bind_tex_image)
228+ return 0;
229+ pOpenGLVTable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
230+ get_proc_address("glXReleaseTexImageEXT");
231+ if (!pOpenGLVTable->glx_release_tex_image)
232+ return 0;
233+ return 1;
234+}
235+
236+static int load_fbo_extensions(VADriverContextP ctx)
237+{
238+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
239+
240+ pOpenGLVTable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
241+ get_proc_address("glGenFramebuffersEXT");
242+ if (!pOpenGLVTable->gl_gen_framebuffers)
243+ return 0;
244+ pOpenGLVTable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
245+ get_proc_address("glDeleteFramebuffersEXT");
246+ if (!pOpenGLVTable->gl_delete_framebuffers)
247+ return 0;
248+ pOpenGLVTable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
249+ get_proc_address("glBindFramebufferEXT");
250+ if (!pOpenGLVTable->gl_bind_framebuffer)
251+ return 0;
252+ pOpenGLVTable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
253+ get_proc_address("glGenRenderbuffersEXT");
254+ if (!pOpenGLVTable->gl_gen_renderbuffers)
255+ return 0;
256+ pOpenGLVTable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
257+ get_proc_address("glDeleteRenderbuffersEXT");
258+ if (!pOpenGLVTable->gl_delete_renderbuffers)
259+ return 0;
260+ pOpenGLVTable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
261+ get_proc_address("glBindRenderbufferEXT");
262+ if (!pOpenGLVTable->gl_bind_renderbuffer)
263+ return 0;
264+ pOpenGLVTable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
265+ get_proc_address("glRenderbufferStorageEXT");
266+ if (!pOpenGLVTable->gl_renderbuffer_storage)
267+ return 0;
268+ pOpenGLVTable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
269+ get_proc_address("glFramebufferRenderbufferEXT");
270+ if (!pOpenGLVTable->gl_framebuffer_renderbuffer)
271+ return 0;
272+ pOpenGLVTable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
273+ get_proc_address("glFramebufferTexture2DEXT");
274+ if (!pOpenGLVTable->gl_framebuffer_texture_2d)
275+ return 0;
276+ pOpenGLVTable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
277+ get_proc_address("glCheckFramebufferStatusEXT");
278+ if (!pOpenGLVTable->gl_check_framebuffer_status)
279+ return 0;
280+ return 1;
281+}
282+
283+
284+/* ========================================================================= */
285+/* === VA/GLX helpers === */
286+/* ========================================================================= */
287+
288+// OpenGL context state
289+typedef struct OpenGLContextState *OpenGLContextStateP;
290+
291+struct OpenGLContextState {
292+ Display *display;
293+ Window window;
294+ GLXContext context;
295+};
296+
297+static void
298+gl_destroy_context(OpenGLContextStateP cs)
299+{
300+ if (!cs)
301+ return;
302+
303+ if (cs->display && cs->context) {
304+ if (glXGetCurrentContext() == cs->context)
305+ glXMakeCurrent(cs->display, None, NULL);
306+ glXDestroyContext(cs->display, cs->context);
307+ cs->display = NULL;
308+ cs->context = NULL;
309+ }
310+ free(cs);
311+}
312+
313+static OpenGLContextStateP
314+gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
315+{
316+ OpenGLContextStateP cs;
317+ GLXFBConfig *fbconfigs = NULL;
318+ int fbconfig_id, val, n, n_fbconfigs;
319+ Status status;
320+
321+ static GLint fbconfig_attrs[] = {
322+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
323+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
324+ GLX_DOUBLEBUFFER, True,
325+ GLX_RED_SIZE, 8,
326+ GLX_GREEN_SIZE, 8,
327+ GLX_BLUE_SIZE, 8,
328+ None
329+ };
330+
331+ cs = malloc(sizeof(*cs));
332+ if (!cs)
333+ goto error;
334+
335+ cs->display = ctx->x11_dpy;
336+ cs->window = parent ? parent->window : None;
337+ cs->context = NULL;
338+
339+ if (parent && parent->context) {
340+ status = glXQueryContext(
341+ parent->display,
342+ parent->context,
343+ GLX_FBCONFIG_ID, &fbconfig_id
344+ );
345+ if (status != Success)
346+ goto error;
347+
348+ if (fbconfig_id == GLX_DONT_CARE)
349+ goto choose_fbconfig;
350+
351+ fbconfigs = glXGetFBConfigs(
352+ ctx->x11_dpy,
353+ ctx->x11_screen,
354+ &n_fbconfigs
355+ );
356+ if (!fbconfigs)
357+ goto error;
358+
359+ /* Find out a GLXFBConfig compatible with the parent context */
360+ for (n = 0; n < n_fbconfigs; n++) {
361+ status = glXGetFBConfigAttrib(
362+ ctx->x11_dpy,
363+ fbconfigs[n],
364+ GLX_FBCONFIG_ID, &val
365+ );
366+ if (status == Success && val == fbconfig_id)
367+ break;
368+ }
369+ if (n == n_fbconfigs)
370+ goto error;
371+ }
372+ else {
373+ choose_fbconfig:
374+ fbconfigs = glXChooseFBConfig(
375+ ctx->x11_dpy,
376+ ctx->x11_screen,
377+ fbconfig_attrs, &n_fbconfigs
378+ );
379+ if (!fbconfigs)
380+ goto error;
381+
382+ /* Select the first one */
383+ n = 0;
384+ }
385+
386+ cs->context = glXCreateNewContext(
387+ ctx->x11_dpy,
388+ fbconfigs[n],
389+ GLX_RGBA_TYPE,
390+ parent ? parent->context : NULL,
391+ True
392+ );
393+ if (cs->context)
394+ goto end;
395+
396+error:
397+ gl_destroy_context(cs);
398+ cs = NULL;
399+end:
400+ if (fbconfigs)
401+ XFree(fbconfigs);
402+ return cs;
403+}
404+
405+static void gl_get_current_context(OpenGLContextStateP cs)
406+{
407+ cs->display = glXGetCurrentDisplay();
408+ cs->window = glXGetCurrentDrawable();
409+ cs->context = glXGetCurrentContext();
410+}
411+
412+static int
413+gl_set_current_context(OpenGLContextStateP new_cs, OpenGLContextStateP old_cs)
414+{
415+ /* If display is NULL, this could be that new_cs was retrieved from
416+ gl_get_current_context() with none set previously. If that case,
417+ the other fields are also NULL and we don't return an error */
418+ if (!new_cs->display)
419+ return !new_cs->window && !new_cs->context;
420+
421+ if (old_cs) {
422+ if (old_cs == new_cs)
423+ return 1;
424+ gl_get_current_context(old_cs);
425+ if (old_cs->display == new_cs->display &&
426+ old_cs->window == new_cs->window &&
427+ old_cs->context == new_cs->context)
428+ return 1;
429+ }
430+ return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
431+}
432+
433+/** Unique VASurfaceGLX identifier */
434+#define VA_SURFACE_GLX_MAGIC VA_FOURCC('V','A','G','L')
435+
436+struct VASurfaceGLX {
437+ uint32_t magic; ///< Magic number identifying a VASurfaceGLX
438+ GLenum target; ///< GL target to which the texture is bound
439+ GLuint texture; ///< GL texture
440+ VASurfaceID surface; ///< Associated VA surface
441+ unsigned int width;
442+ unsigned int height;
443+ OpenGLContextStateP gl_context;
444+ int is_bound;
445+ Pixmap pixmap;
446+ GLuint pix_texture;
447+ GLXPixmap glx_pixmap;
448+ GLuint fbo;
449+};
450+
451+// Create Pixmaps for GLX texture-from-pixmap extension
452+static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
453+{
454+ const unsigned int width = pSurfaceGLX->width;
455+ const unsigned int height = pSurfaceGLX->height;
456+ Pixmap pixmap = None;
457+ GLXFBConfig *fbconfig = NULL;
458+ GLXPixmap glx_pixmap = None;
459+ Window root_window;
460+ XWindowAttributes wattr;
461+ int *attrib;
462+ int n_fbconfig_attrs;
463+
464+ root_window = RootWindow(ctx->x11_dpy, ctx->x11_screen);
465+ XGetWindowAttributes(ctx->x11_dpy, root_window, &wattr);
466+ if (wattr.depth != 24 && wattr.depth != 32)
467+ return 0;
468+ pixmap = XCreatePixmap(
469+ ctx->x11_dpy,
470+ root_window,
471+ width,
472+ height,
473+ wattr.depth
474+ );
475+ if (!pixmap)
476+ return 0;
477+ pSurfaceGLX->pixmap = pixmap;
478+
479+ int fbconfig_attrs[32] = {
480+ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
481+ GLX_DOUBLEBUFFER, GL_TRUE,
482+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
483+ GLX_X_RENDERABLE, GL_TRUE,
484+ GLX_Y_INVERTED_EXT, GL_TRUE,
485+ GLX_RED_SIZE, 8,
486+ GLX_GREEN_SIZE, 8,
487+ GLX_BLUE_SIZE, 8,
488+ GL_NONE,
489+ };
490+ for (attrib = fbconfig_attrs; *attrib != GL_NONE; attrib += 2)
491+ ;
492+ *attrib++ = GLX_DEPTH_SIZE; *attrib++ = wattr.depth;
493+ if (wattr.depth == 32) {
494+ *attrib++ = GLX_ALPHA_SIZE; *attrib++ = 8;
495+ *attrib++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attrib++ = GL_TRUE;
496+ }
497+ else {
498+ *attrib++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attrib++ = GL_TRUE;
499+ }
500+ *attrib++ = GL_NONE;
501+
502+ fbconfig = glXChooseFBConfig(
503+ ctx->x11_dpy,
504+ ctx->x11_screen,
505+ fbconfig_attrs,
506+ &n_fbconfig_attrs
507+ );
508+ if (!fbconfig)
509+ return 0;
510+
511+ int pixmap_attrs[10] = {
512+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
513+ GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
514+ GL_NONE,
515+ };
516+ for (attrib = pixmap_attrs; *attrib != GL_NONE; attrib += 2)
517+ ;
518+ *attrib++ = GLX_TEXTURE_FORMAT_EXT;
519+ if (wattr.depth == 32)
520+ *attrib++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
521+ else
522+ *attrib++ = GLX_TEXTURE_FORMAT_RGB_EXT;
523+ *attrib++ = GL_NONE;
524+
525+ x11_trap_errors();
526+ glx_pixmap = glXCreatePixmap(
527+ ctx->x11_dpy,
528+ fbconfig[0],
529+ pixmap,
530+ pixmap_attrs
531+ );
532+ free(fbconfig);
533+ if (x11_untrap_errors() != 0)
534+ return 0;
535+ pSurfaceGLX->glx_pixmap = glx_pixmap;
536+
537+ glGenTextures(1, &pSurfaceGLX->pix_texture);
538+ glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->pix_texture);
539+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
540+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
541+ return 1;
542+}
543+
544+// Destroy Pixmaps used for TFP
545+static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
546+{
547+ if (pSurfaceGLX->pix_texture) {
548+ glDeleteTextures(1, &pSurfaceGLX->pix_texture);
549+ pSurfaceGLX->pix_texture = 0;
550+ }
551+
552+ if (pSurfaceGLX->glx_pixmap) {
553+ glXDestroyPixmap(ctx->x11_dpy, pSurfaceGLX->glx_pixmap);
554+ pSurfaceGLX->glx_pixmap = None;
555+ }
556+
557+ if (pSurfaceGLX->pixmap) {
558+ XFreePixmap(ctx->x11_dpy, pSurfaceGLX->pixmap);
559+ pSurfaceGLX->pixmap = None;
560+ }
561+}
562+
563+// Bind GLX Pixmap to texture
564+static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
565+{
566+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
567+
568+ if (pSurfaceGLX->is_bound)
569+ return 1;
570+
571+ glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->pix_texture);
572+
573+ x11_trap_errors();
574+ pOpenGLVTable->glx_bind_tex_image(
575+ ctx->x11_dpy,
576+ pSurfaceGLX->glx_pixmap,
577+ GLX_FRONT_LEFT_EXT,
578+ NULL
579+ );
580+ XSync(ctx->x11_dpy, False);
581+ if (x11_untrap_errors() != 0) {
582+ va_glx_error_message("failed to bind pixmap\n");
583+ return 0;
584+ }
585+
586+ pSurfaceGLX->is_bound = 1;
587+ return 1;
588+}
589+
590+// Release GLX Pixmap from texture
591+static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
592+{
593+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
594+
595+ if (!pSurfaceGLX->is_bound)
596+ return 1;
597+
598+ x11_trap_errors();
599+ pOpenGLVTable->glx_release_tex_image(
600+ ctx->x11_dpy,
601+ pSurfaceGLX->glx_pixmap,
602+ GLX_FRONT_LEFT_EXT
603+ );
604+ XSync(ctx->x11_dpy, False);
605+ if (x11_untrap_errors() != 0) {
606+ va_glx_error_message("failed to release pixmap\n");
607+ return 0;
608+ }
609+
610+ glBindTexture(GL_TEXTURE_2D, 0);
611+
612+ pSurfaceGLX->is_bound = 0;
613+ return 1;
614+}
615+
616+// Render GLX Pixmap to texture
617+static void render_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
618+{
619+ const unsigned int w = pSurfaceGLX->width;
620+ const unsigned int h = pSurfaceGLX->height;
621+
622+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
623+ glBegin(GL_QUADS);
624+ {
625+ glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
626+ glTexCoord2f(0.0f, 1.0f); glVertex2i(0, h);
627+ glTexCoord2f(1.0f, 1.0f); glVertex2i(w, h);
628+ glTexCoord2f(1.0f, 0.0f); glVertex2i(w, 0);
629+ }
630+ glEnd();
631+}
632+
633+// Create offscreen surface
634+static int create_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
635+{
636+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
637+ GLuint fbo;
638+ GLenum status;
639+
640+ pOpenGLVTable->gl_gen_framebuffers(1, &fbo);
641+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo);
642+ pOpenGLVTable->gl_framebuffer_texture_2d(
643+ GL_FRAMEBUFFER_EXT,
644+ GL_COLOR_ATTACHMENT0_EXT,
645+ GL_TEXTURE_2D,
646+ pSurfaceGLX->texture,
647+ 0
648+ );
649+
650+ status = pOpenGLVTable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
651+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
652+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
653+ return 0;
654+
655+ pSurfaceGLX->fbo = fbo;
656+ return 1;
657+}
658+
659+// Destroy offscreen surface
660+static void destroy_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
661+{
662+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
663+
664+ if (pSurfaceGLX->fbo) {
665+ pOpenGLVTable->gl_delete_framebuffers(1, &pSurfaceGLX->fbo);
666+ pSurfaceGLX->fbo = 0;
667+ }
668+}
669+
670+// Setup matrices to match the FBO texture dimensions
671+static void fbo_enter(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
672+{
673+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
674+ const unsigned int width = pSurfaceGLX->width;
675+ const unsigned int height = pSurfaceGLX->height;
676+
677+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, pSurfaceGLX->fbo);
678+ glPushAttrib(GL_VIEWPORT_BIT);
679+ glMatrixMode(GL_PROJECTION);
680+ glPushMatrix();
681+ glLoadIdentity();
682+ glMatrixMode(GL_MODELVIEW);
683+ glPushMatrix();
684+ glLoadIdentity();
685+ glViewport(0, 0, width, height);
686+ glTranslatef(-1.0f, -1.0f, 0.0f);
687+ glScalef(2.0f / width, 2.0f / height, 1.0f);
688+}
689+
690+// Restore original OpenGL matrices
691+static void fbo_leave(VADriverContextP ctx)
692+{
693+ VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
694+
695+ glPopAttrib();
696+ glMatrixMode(GL_PROJECTION);
697+ glPopMatrix();
698+ glMatrixMode(GL_MODELVIEW);
699+ glPopMatrix();
700+ pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
701+}
702+
703+// Check internal texture format is supported
704+static int is_supported_internal_format(GLenum format)
705+{
706+ /* XXX: we don't support other textures than RGBA */
707+ switch (format) {
708+ case 4:
709+ case GL_RGBA:
710+ case GL_RGBA8:
711+ return 1;
712+ }
713+ return 0;
714+}
715+
716+// Destroy VA/GLX surface
717+static void
718+destroy_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
719+{
720+ unbind_pixmap(ctx, pSurfaceGLX);
721+ destroy_fbo_surface(ctx, pSurfaceGLX);
722+ destroy_tfp_surface(ctx, pSurfaceGLX);
723+ free(pSurfaceGLX);
724+}
725+
726+// Create VA/GLX surface
727+static VASurfaceGLXP
728+create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
729+{
730+ VASurfaceGLXP pSurfaceGLX = NULL;
731+ unsigned int internal_format, border_width, width, height;
732+ int is_error = 1;
733+
734+ pSurfaceGLX = malloc(sizeof(*pSurfaceGLX));
735+ if (!pSurfaceGLX)
736+ goto end;
737+
738+ pSurfaceGLX->magic = VA_SURFACE_GLX_MAGIC;
739+ pSurfaceGLX->target = target;
740+ pSurfaceGLX->texture = texture;
741+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
742+ pSurfaceGLX->gl_context = NULL;
743+ pSurfaceGLX->is_bound = 0;
744+ pSurfaceGLX->pixmap = None;
745+ pSurfaceGLX->pix_texture = 0;
746+ pSurfaceGLX->glx_pixmap = None;
747+ pSurfaceGLX->fbo = 0;
748+
749+ glEnable(target);
750+ glBindTexture(target, texture);
751+ if (!gl_get_texture_param(GL_TEXTURE_INTERNAL_FORMAT, &internal_format))
752+ goto end;
753+ if (!is_supported_internal_format(internal_format))
754+ goto end;
755+
756+ /* Check texture dimensions */
757+ if (!gl_get_texture_param(GL_TEXTURE_BORDER, &border_width))
758+ goto end;
759+ if (!gl_get_texture_param(GL_TEXTURE_WIDTH, &width))
760+ goto end;
761+ if (!gl_get_texture_param(GL_TEXTURE_HEIGHT, &height))
762+ goto end;
763+
764+ width -= 2 * border_width;
765+ height -= 2 * border_width;
766+ if (width == 0 || height == 0)
767+ goto end;
768+
769+ pSurfaceGLX->width = width;
770+ pSurfaceGLX->height = height;
771+
772+ /* Create TFP objects */
773+ if (!create_tfp_surface(ctx, pSurfaceGLX))
774+ goto end;
775+
776+ /* Create FBO objects */
777+ if (!create_fbo_surface(ctx, pSurfaceGLX))
778+ goto end;
779+
780+ is_error = 0;
781+end:
782+ if (is_error && pSurfaceGLX) {
783+ destroy_surface(ctx, pSurfaceGLX);
784+ pSurfaceGLX = NULL;
785+ }
786+ return pSurfaceGLX;
787+}
788+
789+
790+/* ========================================================================= */
791+/* === VA/GLX implementation from the driver (fordward calls) === */
792+/* ========================================================================= */
793+
794+#define INVOKE(ctx, func, args) do { \
795+ VADriverVTableGLXP vtable = (ctx)->vtable.glx; \
796+ if (!vtable->va##func##GLX) \
797+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
798+ \
799+ VAStatus status = vtable->va##func##GLX args; \
800+ if (status != VA_STATUS_SUCCESS) \
801+ return status; \
802+ } while (0)
803+
804+static VAStatus
805+vaCreateSurfaceGLX_impl_driver(
806+ VADriverContextP ctx,
807+ GLenum target,
808+ GLuint texture,
809+ void **gl_surface
810+)
811+{
812+ INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
813+ return VA_STATUS_SUCCESS;
814+}
815+
816+static VAStatus
817+vaDestroySurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
818+{
819+ INVOKE(ctx, DestroySurface, (ctx, gl_surface));
820+ return VA_STATUS_SUCCESS;
821+}
822+
823+static VAStatus
824+vaCopySurfaceGLX_impl_driver(
825+ VADriverContextP ctx,
826+ void *gl_surface,
827+ VASurfaceID surface,
828+ unsigned int flags
829+)
830+{
831+ INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
832+ return VA_STATUS_SUCCESS;
833+}
834+
835+#undef INVOKE
836+
837+
838+/* ========================================================================= */
839+/* === VA/GLX implementation from libVA (generic and suboptimal path) === */
840+/* ========================================================================= */
841+
842+#define INIT_SURFACE(surface, surface_arg) do { \
843+ surface = (VASurfaceGLXP)(surface_arg); \
844+ if (!check_surface(surface)) \
845+ return VA_STATUS_ERROR_INVALID_SURFACE; \
846+ } while (0)
847+
848+// Check VASurfaceGLX is valid
849+static inline int check_surface(VASurfaceGLXP pSurfaceGLX)
850+{
851+ return pSurfaceGLX && pSurfaceGLX->magic == VA_SURFACE_GLX_MAGIC;
852+}
853+
854+static VAStatus
855+vaCreateSurfaceGLX_impl_libva(
856+ VADriverContextP ctx,
857+ GLenum target,
858+ GLuint texture,
859+ void **gl_surface
860+)
861+{
862+ VASurfaceGLXP pSurfaceGLX;
863+ struct OpenGLContextState old_cs, *new_cs;
864+
865+ gl_get_current_context(&old_cs);
866+ new_cs = gl_create_context(ctx, &old_cs);
867+ if (!new_cs)
868+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
869+ if (!gl_set_current_context(new_cs, NULL))
870+ return VA_STATUS_ERROR_OPERATION_FAILED;
871+
872+ pSurfaceGLX = create_surface(ctx, target, texture);
873+ if (!pSurfaceGLX)
874+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
875+
876+ pSurfaceGLX->gl_context = new_cs;
877+ *gl_surface = pSurfaceGLX;
878+
879+ gl_set_current_context(&old_cs, NULL);
880+ return VA_STATUS_SUCCESS;
881+}
882+
883+static VAStatus
884+vaDestroySurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
885+{
886+ VASurfaceGLXP pSurfaceGLX;
887+ struct OpenGLContextState old_cs, *new_cs;
888+
889+ INIT_SURFACE(pSurfaceGLX, gl_surface);
890+
891+ new_cs = pSurfaceGLX->gl_context;
892+ if (!gl_set_current_context(new_cs, &old_cs))
893+ return VA_STATUS_ERROR_OPERATION_FAILED;
894+
895+ destroy_surface(ctx, pSurfaceGLX);
896+
897+ gl_destroy_context(new_cs);
898+ gl_set_current_context(&old_cs, NULL);
899+ return VA_STATUS_SUCCESS;
900+}
901+
902+static inline VAStatus
903+deassociate_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
904+{
905+ if (!unbind_pixmap(ctx, pSurfaceGLX))
906+ return VA_STATUS_ERROR_OPERATION_FAILED;
907+
908+ pSurfaceGLX->surface = VA_INVALID_SURFACE;
909+ return VA_STATUS_SUCCESS;
910+}
911+
912+static VAStatus
913+associate_surface(
914+ VADriverContextP ctx,
915+ VASurfaceGLXP pSurfaceGLX,
916+ VASurfaceID surface,
917+ unsigned int flags
918+)
919+{
920+ VAStatus status;
921+
922+ /* XXX: optimise case where we are associating the same VA surface
923+ as before an no changed occurred to it */
924+ status = deassociate_surface(ctx, pSurfaceGLX);
925+ if (status != VA_STATUS_SUCCESS)
926+ return status;
927+
928+ x11_trap_errors();
929+ status = ctx->vtable.vaPutSurface(
930+ ctx,
931+ surface,
932+ pSurfaceGLX->pixmap,
933+ 0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
934+ 0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
935+ NULL, 0,
936+ flags
937+ );
938+ XSync(ctx->x11_dpy, False);
939+ if (x11_untrap_errors() != 0)
940+ return VA_STATUS_ERROR_OPERATION_FAILED;
941+ if (status != VA_STATUS_SUCCESS)
942+ return status;
943+
944+ pSurfaceGLX->surface = surface;
945+ return VA_STATUS_SUCCESS;
946+}
947+
948+static inline VAStatus
949+sync_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
950+{
951+ if (pSurfaceGLX->surface == VA_INVALID_SURFACE)
952+ return VA_STATUS_ERROR_INVALID_SURFACE;
953+
954+ return ctx->vtable.vaSyncSurface(ctx, pSurfaceGLX->surface);
955+}
956+
957+static inline VAStatus
958+begin_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
959+{
960+ VAStatus status;
961+
962+ status = sync_surface(ctx, pSurfaceGLX);
963+ if (status != VA_STATUS_SUCCESS)
964+ return status;
965+
966+ if (!bind_pixmap(ctx, pSurfaceGLX))
967+ return VA_STATUS_ERROR_OPERATION_FAILED;
968+
969+ return VA_STATUS_SUCCESS;
970+}
971+
972+static inline VAStatus
973+end_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
974+{
975+ if (!unbind_pixmap(ctx, pSurfaceGLX))
976+ return VA_STATUS_ERROR_OPERATION_FAILED;
977+
978+ return VA_STATUS_SUCCESS;
979+}
980+
981+static VAStatus
982+copy_surface(
983+ VADriverContextP ctx,
984+ VASurfaceGLXP pSurfaceGLX,
985+ VASurfaceID surface,
986+ unsigned int flags
987+)
988+{
989+ VAStatus status;
990+
991+ /* Associate VA surface */
992+ status = associate_surface(ctx, pSurfaceGLX, surface, flags);
993+ if (status != VA_STATUS_SUCCESS)
994+ return status;
995+
996+ /* Render to FBO */
997+ fbo_enter(ctx, pSurfaceGLX);
998+ status = begin_render_surface(ctx, pSurfaceGLX);
999+ if (status == VA_STATUS_SUCCESS) {
1000+ render_pixmap(ctx, pSurfaceGLX);
1001+ status = end_render_surface(ctx, pSurfaceGLX);
1002+ }
1003+ fbo_leave(ctx);
1004+ if (status != VA_STATUS_SUCCESS)
1005+ return status;
1006+
1007+ return deassociate_surface(ctx, pSurfaceGLX);
1008+}
1009+
1010+static VAStatus
1011+vaCopySurfaceGLX_impl_libva(
1012+ VADriverContextP ctx,
1013+ void *gl_surface,
1014+ VASurfaceID surface,
1015+ unsigned int flags
1016+)
1017+{
1018+ VASurfaceGLXP pSurfaceGLX;
1019+ VAStatus status;
1020+ struct OpenGLContextState old_cs;
1021+
1022+ INIT_SURFACE(pSurfaceGLX, gl_surface);
1023+
1024+ if (!gl_set_current_context(pSurfaceGLX->gl_context, &old_cs))
1025+ return VA_STATUS_ERROR_OPERATION_FAILED;
1026+
1027+ status = copy_surface(ctx, pSurfaceGLX, surface, flags);
1028+
1029+ gl_set_current_context(&old_cs, NULL);
1030+ return status;
1031+}
1032+
1033+#undef INIT_SURFACE
1034+
1035+
1036+/* ========================================================================= */
1037+/* === Private VA/GLX vtable initialization === */
1038+/* ========================================================================= */
1039+
1040+// Initialize GLX driver context
1041+VAStatus va_glx_init_context(VADriverContextP ctx)
1042+{
1043+ VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
1044+ VADriverVTableGLXP vtable = &glx_ctx->vtable;
1045+ int glx_major, glx_minor;
1046+
1047+ if (glx_ctx->is_initialized)
1048+ return VA_STATUS_SUCCESS;
1049+
1050+ if (ctx->vtable.glx && ctx->vtable.glx->vaCopySurfaceGLX) {
1051+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
1052+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
1053+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
1054+ }
1055+ else {
1056+ vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_libva;
1057+ vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_libva;
1058+ vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
1059+
1060+ if (!glXQueryVersion(ctx->x11_dpy, &glx_major, &glx_minor))
1061+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1062+ if (glx_major < 1 || (glx_major == 1 && glx_minor < 3)) { /* GLX 1.3 */
1063+ va_glx_error_message("GLX version 1.3 expected but only "
1064+ "version %d.%d is available\n",
1065+ glx_major, glx_minor);
1066+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1067+ }
1068+
1069+ if (!check_tfp_extensions(ctx) || !load_tfp_extensions(ctx))
1070+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1071+
1072+ if (!check_fbo_extensions(ctx) || !load_fbo_extensions(ctx))
1073+ return VA_STATUS_ERROR_UNIMPLEMENTED;
1074+ }
1075+
1076+ glx_ctx->is_initialized = 1;
1077+ return VA_STATUS_SUCCESS;
1078+}
--- /dev/null
+++ b/va/glx/va_glx_impl.h
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#ifndef VA_GLX_IMPL_H
26+#define VA_GLX_IMPL_H
27+
28+/**
29+ * Initialize GLX driver context
30+ *
31+ * @param[in] ctx the VA driver context
32+ * @return VA_STATUS_SUCCESS if successful
33+ */
34+VAStatus va_glx_init_context(VADriverContextP ctx)
35+ ATTRIBUTE_HIDDEN;
36+
37+#endif /* VA_GLX_IMPL_H */
--- /dev/null
+++ b/va/glx/va_glx_private.h
@@ -0,0 +1,76 @@
1+/*
2+ * Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
3+ *
4+ * Permission is hereby granted, free of charge, to any person obtaining a
5+ * copy of this software and associated documentation files (the
6+ * "Software"), to deal in the Software without restriction, including
7+ * without limitation the rights to use, copy, modify, merge, publish,
8+ * distribute, sub license, and/or sell copies of the Software, and to
9+ * permit persons to whom the Software is furnished to do so, subject to
10+ * the following conditions:
11+ *
12+ * The above copyright notice and this permission notice (including the
13+ * next paragraph) shall be included in all copies or substantial portions
14+ * of the Software.
15+ *
16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+ */
24+
25+#ifndef VA_GLX_PRIVATE_H
26+#define VA_GLX_PRIVATE_H
27+
28+#include "config.h"
29+#include "va.h"
30+#include "va_backend.h"
31+#include "va_x11.h"
32+#include "va_glx.h"
33+#include "va_backend_glx.h"
34+
35+#if GLX_GLXEXT_VERSION < 18
36+typedef void (*PFNGLXBINDTEXIMAGEEXTPROC)(Display *, GLXDrawable, int, const int *);
37+typedef void (*PFNGLXRELEASETEXIMAGEEXTPROC)(Display *, GLXDrawable, int);
38+#endif
39+
40+typedef struct VAOpenGLVTable *VAOpenGLVTableP;
41+
42+struct VAOpenGLVTable {
43+ PFNGLXBINDTEXIMAGEEXTPROC glx_bind_tex_image;
44+ PFNGLXRELEASETEXIMAGEEXTPROC glx_release_tex_image;
45+ PFNGLGENFRAMEBUFFERSEXTPROC gl_gen_framebuffers;
46+ PFNGLDELETEFRAMEBUFFERSEXTPROC gl_delete_framebuffers;
47+ PFNGLBINDFRAMEBUFFEREXTPROC gl_bind_framebuffer;
48+ PFNGLGENRENDERBUFFERSEXTPROC gl_gen_renderbuffers;
49+ PFNGLDELETERENDERBUFFERSEXTPROC gl_delete_renderbuffers;
50+ PFNGLBINDRENDERBUFFEREXTPROC gl_bind_renderbuffer;
51+ PFNGLRENDERBUFFERSTORAGEEXTPROC gl_renderbuffer_storage;
52+ PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC gl_framebuffer_renderbuffer;
53+ PFNGLFRAMEBUFFERTEXTURE2DEXTPROC gl_framebuffer_texture_2d;
54+ PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC gl_check_framebuffer_status;
55+};
56+
57+typedef struct VADisplayContextGLX *VADisplayContextGLXP;
58+typedef struct VADriverContextGLX *VADriverContextGLXP;
59+typedef struct VASurfaceGLX *VASurfaceGLXP;
60+typedef struct VADriverVTableGLX *VADriverVTableGLXP;
61+
62+typedef void (*vaDestroyFunc)(VADisplayContextP);
63+
64+struct VADisplayContextGLX {
65+ vaDestroyFunc vaDestroy;
66+};
67+
68+#define VA_DRIVER_CONTEXT_GLX(ctx) ((VADriverContextGLXP)((ctx)->glx))
69+
70+struct VADriverContextGLX {
71+ struct VADriverVTableGLX vtable;
72+ struct VAOpenGLVTable gl_vtable;
73+ unsigned int is_initialized : 1;
74+};
75+
76+#endif /* VA_GLX_PRIVATE_H */