2
* Copyright (C) 2009 Splitted-Desktop Systems. All Rights Reserved.
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:
12
* The above copyright notice and this permission notice (including the
13
* next paragraph) shall be included in all copies or substantial portions
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.
26
#include "va_glx_private.h"
27
#include "va_glx_impl.h"
35
static void va_glx_error_message(const char *format, ...)
38
va_start(args, format);
39
fprintf(stderr, "libva-glx error: ");
40
vfprintf(stderr, format, args);
45
static int x11_error_code = 0;
46
static int (*old_error_handler)(Display *, XErrorEvent *);
48
static int error_handler(Display *dpy, XErrorEvent *error)
50
x11_error_code = error->error_code;
54
static void x11_trap_errors(void)
57
old_error_handler = XSetErrorHandler(error_handler);
60
static int x11_untrap_errors(void)
62
XSetErrorHandler(old_error_handler);
63
return x11_error_code;
66
// Returns a string representation of an OpenGL error
67
static const char *gl_get_error_string(GLenum error)
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" },
88
for (i = 0; gl_errors[i].str; i++) {
89
if (gl_errors[i].val == error)
90
return gl_errors[i].str;
95
static inline int gl_do_check_error(int report)
99
while ((error = glGetError()) != GL_NO_ERROR) {
101
va_glx_error_message("glError: %s caught\n",
102
gl_get_error_string(error));
108
static inline void gl_purge_errors(void)
110
gl_do_check_error(0);
113
static inline int gl_check_error(void)
115
return gl_do_check_error(1);
118
// glGetTexLevelParameteriv() wrapper
119
static int gl_get_texture_param(GLenum param, unsigned int *pval)
124
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, param, &val);
125
if (gl_check_error())
132
// Returns the OpenGL VTable
133
static inline VAOpenGLVTableP gl_get_vtable(VADriverContextP ctx)
135
return &VA_DRIVER_CONTEXT_GLX(ctx)->gl_vtable;
138
// Lookup for a GLX function
139
typedef void (*GLFuncPtr)(void);
140
typedef GLFuncPtr (*GLXGetProcAddressProc)(const char *);
142
static GLFuncPtr get_proc_address_default(const char *name)
147
static GLXGetProcAddressProc get_proc_address_func(void)
149
GLXGetProcAddressProc get_proc_func;
152
get_proc_func = (GLXGetProcAddressProc)
153
dlsym(RTLD_DEFAULT, "glXGetProcAddress");
155
return get_proc_func;
157
get_proc_func = (GLXGetProcAddressProc)
158
dlsym(RTLD_DEFAULT, "glXGetProcAddressARB");
160
return get_proc_func;
162
return get_proc_address_default;
165
static inline GLFuncPtr get_proc_address(const char *name)
167
static GLXGetProcAddressProc get_proc_func = NULL;
169
get_proc_func = get_proc_address_func();
170
return get_proc_func(name);
173
// Check for GLX extensions (TFP, FBO)
174
static int check_extension(const char *name, const char *ext)
182
end = ext + strlen(ext);
183
name_len = strlen(name);
185
n = strcspn(ext, " ");
186
if (n == name_len && strncmp(name, ext, n) == 0)
193
static int check_tfp_extensions(VADriverContextP ctx)
195
const char *gl_extensions;
196
const char *glx_extensions;
198
gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
199
if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions))
202
glx_extensions = glXQueryExtensionsString((Display *)ctx->native_dpy, ctx->x11_screen);
203
if (!check_extension("GLX_EXT_texture_from_pixmap", glx_extensions))
208
static int check_fbo_extensions(VADriverContextP ctx)
210
const char *gl_extensions;
212
gl_extensions = (const char *)glGetString(GL_EXTENSIONS);
213
if (check_extension("GL_ARB_framebuffer_object", gl_extensions))
215
if (check_extension("GL_EXT_framebuffer_object", gl_extensions))
220
// Load GLX extensions
221
static int load_tfp_extensions(VADriverContextP ctx)
223
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
225
pOpenGLVTable->glx_create_pixmap = (PFNGLXCREATEPIXMAPPROC)
226
get_proc_address("glXCreatePixmap");
227
if (!pOpenGLVTable->glx_create_pixmap)
229
pOpenGLVTable->glx_destroy_pixmap = (PFNGLXDESTROYPIXMAPPROC)
230
get_proc_address("glXDestroyPixmap");
231
if (!pOpenGLVTable->glx_destroy_pixmap)
233
pOpenGLVTable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
234
get_proc_address("glXBindTexImageEXT");
235
if (!pOpenGLVTable->glx_bind_tex_image)
237
pOpenGLVTable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
238
get_proc_address("glXReleaseTexImageEXT");
239
if (!pOpenGLVTable->glx_release_tex_image)
244
static int load_fbo_extensions(VADriverContextP ctx)
246
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
248
pOpenGLVTable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
249
get_proc_address("glGenFramebuffersEXT");
250
if (!pOpenGLVTable->gl_gen_framebuffers)
252
pOpenGLVTable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
253
get_proc_address("glDeleteFramebuffersEXT");
254
if (!pOpenGLVTable->gl_delete_framebuffers)
256
pOpenGLVTable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
257
get_proc_address("glBindFramebufferEXT");
258
if (!pOpenGLVTable->gl_bind_framebuffer)
260
pOpenGLVTable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
261
get_proc_address("glGenRenderbuffersEXT");
262
if (!pOpenGLVTable->gl_gen_renderbuffers)
264
pOpenGLVTable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
265
get_proc_address("glDeleteRenderbuffersEXT");
266
if (!pOpenGLVTable->gl_delete_renderbuffers)
268
pOpenGLVTable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
269
get_proc_address("glBindRenderbufferEXT");
270
if (!pOpenGLVTable->gl_bind_renderbuffer)
272
pOpenGLVTable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
273
get_proc_address("glRenderbufferStorageEXT");
274
if (!pOpenGLVTable->gl_renderbuffer_storage)
276
pOpenGLVTable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
277
get_proc_address("glFramebufferRenderbufferEXT");
278
if (!pOpenGLVTable->gl_framebuffer_renderbuffer)
280
pOpenGLVTable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
281
get_proc_address("glFramebufferTexture2DEXT");
282
if (!pOpenGLVTable->gl_framebuffer_texture_2d)
284
pOpenGLVTable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
285
get_proc_address("glCheckFramebufferStatusEXT");
286
if (!pOpenGLVTable->gl_check_framebuffer_status)
292
/* ========================================================================= */
293
/* === VA/GLX helpers === */
294
/* ========================================================================= */
296
// OpenGL context state
297
typedef struct OpenGLContextState *OpenGLContextStateP;
299
struct OpenGLContextState {
306
gl_destroy_context(OpenGLContextStateP cs)
311
if (cs->display && cs->context) {
312
if (glXGetCurrentContext() == cs->context)
313
glXMakeCurrent(cs->display, None, NULL);
314
glXDestroyContext(cs->display, cs->context);
321
static OpenGLContextStateP
322
gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
324
OpenGLContextStateP cs;
325
GLXFBConfig *fbconfigs = NULL;
326
int fbconfig_id, val, n, n_fbconfigs;
329
static GLint fbconfig_attrs[] = {
330
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
331
GLX_RENDER_TYPE, GLX_RGBA_BIT,
332
GLX_DOUBLEBUFFER, True,
339
cs = malloc(sizeof(*cs));
343
cs->display = (Display *)ctx->native_dpy;
344
cs->window = parent ? parent->window : None;
347
if (parent && parent->context) {
348
status = glXQueryContext(
351
GLX_FBCONFIG_ID, &fbconfig_id
353
if (status != Success)
356
if (fbconfig_id == GLX_DONT_CARE)
357
goto choose_fbconfig;
359
fbconfigs = glXGetFBConfigs(
360
(Display *)ctx->native_dpy,
367
/* Find out a GLXFBConfig compatible with the parent context */
368
for (n = 0; n < n_fbconfigs; n++) {
369
status = glXGetFBConfigAttrib(
370
(Display *)ctx->native_dpy,
372
GLX_FBCONFIG_ID, &val
374
if (status == Success && val == fbconfig_id)
377
if (n == n_fbconfigs)
382
fbconfigs = glXChooseFBConfig(
383
(Display *)ctx->native_dpy,
385
fbconfig_attrs, &n_fbconfigs
390
/* Select the first one */
394
cs->context = glXCreateNewContext(
395
(Display *)ctx->native_dpy,
398
parent ? parent->context : NULL,
405
gl_destroy_context(cs);
413
static void gl_get_current_context(OpenGLContextStateP cs)
415
cs->display = glXGetCurrentDisplay();
416
cs->window = glXGetCurrentDrawable();
417
cs->context = glXGetCurrentContext();
421
gl_set_current_context(OpenGLContextStateP new_cs, OpenGLContextStateP old_cs)
423
/* If display is NULL, this could be that new_cs was retrieved from
424
gl_get_current_context() with none set previously. If that case,
425
the other fields are also NULL and we don't return an error */
426
if (!new_cs->display)
427
return !new_cs->window && !new_cs->context;
430
if (old_cs == new_cs)
432
gl_get_current_context(old_cs);
433
if (old_cs->display == new_cs->display &&
434
old_cs->window == new_cs->window &&
435
old_cs->context == new_cs->context)
438
return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
441
/** Unique VASurfaceGLX identifier */
442
#define VA_SURFACE_GLX_MAGIC VA_FOURCC('V','A','G','L')
444
struct VASurfaceGLX {
445
uint32_t magic; ///< Magic number identifying a VASurfaceGLX
446
GLenum target; ///< GL target to which the texture is bound
447
GLuint texture; ///< GL texture
448
VASurfaceID surface; ///< Associated VA surface
451
OpenGLContextStateP gl_context;
455
GLXPixmap glx_pixmap;
459
// Create Pixmaps for GLX texture-from-pixmap extension
460
static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
462
VAOpenGLVTableP const pOpenGLVTable = gl_get_vtable(ctx);
463
const unsigned int width = pSurfaceGLX->width;
464
const unsigned int height = pSurfaceGLX->height;
465
Pixmap pixmap = None;
466
GLXFBConfig *fbconfig = NULL;
467
GLXPixmap glx_pixmap = None;
469
XWindowAttributes wattr;
471
int n_fbconfig_attrs;
473
root_window = RootWindow((Display *)ctx->native_dpy, ctx->x11_screen);
474
XGetWindowAttributes((Display *)ctx->native_dpy, root_window, &wattr);
475
if (wattr.depth != 24 && wattr.depth != 32)
477
pixmap = XCreatePixmap(
478
(Display *)ctx->native_dpy,
486
pSurfaceGLX->pixmap = pixmap;
488
int fbconfig_attrs[32] = {
489
GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
490
GLX_DOUBLEBUFFER, GL_TRUE,
491
GLX_RENDER_TYPE, GLX_RGBA_BIT,
492
GLX_X_RENDERABLE, GL_TRUE,
493
GLX_Y_INVERTED_EXT, GL_TRUE,
499
for (attrib = fbconfig_attrs; *attrib != GL_NONE; attrib += 2)
501
*attrib++ = GLX_DEPTH_SIZE; *attrib++ = wattr.depth;
502
if (wattr.depth == 32) {
503
*attrib++ = GLX_ALPHA_SIZE; *attrib++ = 8;
504
*attrib++ = GLX_BIND_TO_TEXTURE_RGBA_EXT; *attrib++ = GL_TRUE;
507
*attrib++ = GLX_BIND_TO_TEXTURE_RGB_EXT; *attrib++ = GL_TRUE;
511
fbconfig = glXChooseFBConfig(
512
(Display *)ctx->native_dpy,
520
int pixmap_attrs[10] = {
521
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
522
GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
525
for (attrib = pixmap_attrs; *attrib != GL_NONE; attrib += 2)
527
*attrib++ = GLX_TEXTURE_FORMAT_EXT;
528
if (wattr.depth == 32)
529
*attrib++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
531
*attrib++ = GLX_TEXTURE_FORMAT_RGB_EXT;
535
glx_pixmap = pOpenGLVTable->glx_create_pixmap(
536
(Display *)ctx->native_dpy,
542
if (x11_untrap_errors() != 0)
544
pSurfaceGLX->glx_pixmap = glx_pixmap;
546
glGenTextures(1, &pSurfaceGLX->pix_texture);
547
glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->pix_texture);
548
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
549
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
553
// Destroy Pixmaps used for TFP
554
static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
556
VAOpenGLVTableP const pOpenGLVTable = gl_get_vtable(ctx);
558
if (pSurfaceGLX->pix_texture) {
559
glDeleteTextures(1, &pSurfaceGLX->pix_texture);
560
pSurfaceGLX->pix_texture = 0;
563
if (pSurfaceGLX->glx_pixmap) {
564
pOpenGLVTable->glx_destroy_pixmap((Display *)ctx->native_dpy, pSurfaceGLX->glx_pixmap);
565
pSurfaceGLX->glx_pixmap = None;
568
if (pSurfaceGLX->pixmap) {
569
XFreePixmap((Display *)ctx->native_dpy, pSurfaceGLX->pixmap);
570
pSurfaceGLX->pixmap = None;
574
// Bind GLX Pixmap to texture
575
static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
577
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
579
if (pSurfaceGLX->is_bound)
582
glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->pix_texture);
585
pOpenGLVTable->glx_bind_tex_image(
586
(Display *)ctx->native_dpy,
587
pSurfaceGLX->glx_pixmap,
591
XSync((Display *)ctx->native_dpy, False);
592
if (x11_untrap_errors() != 0) {
593
va_glx_error_message("failed to bind pixmap\n");
597
pSurfaceGLX->is_bound = 1;
601
// Release GLX Pixmap from texture
602
static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
604
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
606
if (!pSurfaceGLX->is_bound)
610
pOpenGLVTable->glx_release_tex_image(
611
(Display *)ctx->native_dpy,
612
pSurfaceGLX->glx_pixmap,
615
XSync((Display *)ctx->native_dpy, False);
616
if (x11_untrap_errors() != 0) {
617
va_glx_error_message("failed to release pixmap\n");
621
glBindTexture(GL_TEXTURE_2D, 0);
623
pSurfaceGLX->is_bound = 0;
627
// Render GLX Pixmap to texture
628
static void render_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
630
const unsigned int w = pSurfaceGLX->width;
631
const unsigned int h = pSurfaceGLX->height;
633
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
636
glTexCoord2f(0.0f, 0.0f); glVertex2i(0, 0);
637
glTexCoord2f(0.0f, 1.0f); glVertex2i(0, h);
638
glTexCoord2f(1.0f, 1.0f); glVertex2i(w, h);
639
glTexCoord2f(1.0f, 0.0f); glVertex2i(w, 0);
644
// Create offscreen surface
645
static int create_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
647
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
651
pOpenGLVTable->gl_gen_framebuffers(1, &fbo);
652
pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo);
653
pOpenGLVTable->gl_framebuffer_texture_2d(
655
GL_COLOR_ATTACHMENT0_EXT,
657
pSurfaceGLX->texture,
661
status = pOpenGLVTable->gl_check_framebuffer_status(GL_DRAW_FRAMEBUFFER_EXT);
662
pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
663
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
666
pSurfaceGLX->fbo = fbo;
670
// Destroy offscreen surface
671
static void destroy_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
673
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
675
if (pSurfaceGLX->fbo) {
676
pOpenGLVTable->gl_delete_framebuffers(1, &pSurfaceGLX->fbo);
677
pSurfaceGLX->fbo = 0;
681
// Setup matrices to match the FBO texture dimensions
682
static void fbo_enter(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
684
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
685
const unsigned int width = pSurfaceGLX->width;
686
const unsigned int height = pSurfaceGLX->height;
688
pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, pSurfaceGLX->fbo);
689
glPushAttrib(GL_VIEWPORT_BIT);
690
glMatrixMode(GL_PROJECTION);
693
glMatrixMode(GL_MODELVIEW);
696
glViewport(0, 0, width, height);
697
glTranslatef(-1.0f, -1.0f, 0.0f);
698
glScalef(2.0f / width, 2.0f / height, 1.0f);
701
// Restore original OpenGL matrices
702
static void fbo_leave(VADriverContextP ctx)
704
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
707
glMatrixMode(GL_PROJECTION);
709
glMatrixMode(GL_MODELVIEW);
711
pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
714
// Check internal texture format is supported
715
static int is_supported_internal_format(GLenum format)
717
/* XXX: we don't support other textures than RGBA */
727
// Destroy VA/GLX surface
729
destroy_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
731
unbind_pixmap(ctx, pSurfaceGLX);
732
destroy_fbo_surface(ctx, pSurfaceGLX);
733
destroy_tfp_surface(ctx, pSurfaceGLX);
737
// Create VA/GLX surface
739
create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
741
VASurfaceGLXP pSurfaceGLX = NULL;
742
unsigned int internal_format, border_width, width, height;
745
pSurfaceGLX = malloc(sizeof(*pSurfaceGLX));
749
pSurfaceGLX->magic = VA_SURFACE_GLX_MAGIC;
750
pSurfaceGLX->target = target;
751
pSurfaceGLX->texture = texture;
752
pSurfaceGLX->surface = VA_INVALID_SURFACE;
753
pSurfaceGLX->gl_context = NULL;
754
pSurfaceGLX->is_bound = 0;
755
pSurfaceGLX->pixmap = None;
756
pSurfaceGLX->pix_texture = 0;
757
pSurfaceGLX->glx_pixmap = None;
758
pSurfaceGLX->fbo = 0;
761
glBindTexture(target, texture);
762
if (!gl_get_texture_param(GL_TEXTURE_INTERNAL_FORMAT, &internal_format))
764
if (!is_supported_internal_format(internal_format))
767
/* Check texture dimensions */
768
if (!gl_get_texture_param(GL_TEXTURE_BORDER, &border_width))
770
if (!gl_get_texture_param(GL_TEXTURE_WIDTH, &width))
772
if (!gl_get_texture_param(GL_TEXTURE_HEIGHT, &height))
775
width -= 2 * border_width;
776
height -= 2 * border_width;
777
if (width == 0 || height == 0)
780
pSurfaceGLX->width = width;
781
pSurfaceGLX->height = height;
783
/* Create TFP objects */
784
if (!create_tfp_surface(ctx, pSurfaceGLX))
787
/* Create FBO objects */
788
if (!create_fbo_surface(ctx, pSurfaceGLX))
793
if (is_error && pSurfaceGLX) {
794
destroy_surface(ctx, pSurfaceGLX);
801
/* ========================================================================= */
802
/* === VA/GLX implementation from the driver (fordward calls) === */
803
/* ========================================================================= */
805
#define INVOKE(ctx, func, args) do { \
806
VADriverVTableGLXP vtable = (ctx)->vtable.glx; \
807
if (!vtable->va##func##GLX) \
808
return VA_STATUS_ERROR_UNIMPLEMENTED; \
810
VAStatus status = vtable->va##func##GLX args; \
811
if (status != VA_STATUS_SUCCESS) \
816
vaCreateSurfaceGLX_impl_driver(
817
VADriverContextP ctx,
823
INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
824
return VA_STATUS_SUCCESS;
828
vaDestroySurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
830
INVOKE(ctx, DestroySurface, (ctx, gl_surface));
831
return VA_STATUS_SUCCESS;
835
vaCopySurfaceGLX_impl_driver(
836
VADriverContextP ctx,
842
INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
843
return VA_STATUS_SUCCESS;
849
/* ========================================================================= */
850
/* === VA/GLX implementation from libVA (generic and suboptimal path) === */
851
/* ========================================================================= */
853
#define INIT_SURFACE(surface, surface_arg) do { \
854
surface = (VASurfaceGLXP)(surface_arg); \
855
if (!check_surface(surface)) \
856
return VA_STATUS_ERROR_INVALID_SURFACE; \
859
// Check VASurfaceGLX is valid
860
static inline int check_surface(VASurfaceGLXP pSurfaceGLX)
862
return pSurfaceGLX && pSurfaceGLX->magic == VA_SURFACE_GLX_MAGIC;
866
vaCreateSurfaceGLX_impl_libva(
867
VADriverContextP ctx,
873
VASurfaceGLXP pSurfaceGLX;
874
struct OpenGLContextState old_cs, *new_cs;
876
gl_get_current_context(&old_cs);
877
new_cs = gl_create_context(ctx, &old_cs);
879
return VA_STATUS_ERROR_ALLOCATION_FAILED;
880
if (!gl_set_current_context(new_cs, NULL))
881
return VA_STATUS_ERROR_OPERATION_FAILED;
883
pSurfaceGLX = create_surface(ctx, target, texture);
885
return VA_STATUS_ERROR_ALLOCATION_FAILED;
887
pSurfaceGLX->gl_context = new_cs;
888
*gl_surface = pSurfaceGLX;
890
gl_set_current_context(&old_cs, NULL);
891
return VA_STATUS_SUCCESS;
895
vaDestroySurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
897
VASurfaceGLXP pSurfaceGLX;
898
struct OpenGLContextState old_cs, *new_cs;
900
INIT_SURFACE(pSurfaceGLX, gl_surface);
902
new_cs = pSurfaceGLX->gl_context;
903
if (!gl_set_current_context(new_cs, &old_cs))
904
return VA_STATUS_ERROR_OPERATION_FAILED;
906
destroy_surface(ctx, pSurfaceGLX);
908
gl_destroy_context(new_cs);
909
gl_set_current_context(&old_cs, NULL);
910
return VA_STATUS_SUCCESS;
913
static inline VAStatus
914
deassociate_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
916
if (!unbind_pixmap(ctx, pSurfaceGLX))
917
return VA_STATUS_ERROR_OPERATION_FAILED;
919
pSurfaceGLX->surface = VA_INVALID_SURFACE;
920
return VA_STATUS_SUCCESS;
925
VADriverContextP ctx,
926
VASurfaceGLXP pSurfaceGLX,
933
/* XXX: optimise case where we are associating the same VA surface
934
as before an no changed occurred to it */
935
status = deassociate_surface(ctx, pSurfaceGLX);
936
if (status != VA_STATUS_SUCCESS)
940
status = ctx->vtable.vaPutSurface(
943
(void *)pSurfaceGLX->pixmap,
944
0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
945
0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
949
XSync((Display *)ctx->native_dpy, False);
950
if (x11_untrap_errors() != 0)
951
return VA_STATUS_ERROR_OPERATION_FAILED;
952
if (status != VA_STATUS_SUCCESS)
955
pSurfaceGLX->surface = surface;
956
return VA_STATUS_SUCCESS;
959
static inline VAStatus
960
sync_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
962
if (pSurfaceGLX->surface == VA_INVALID_SURFACE)
963
return VA_STATUS_ERROR_INVALID_SURFACE;
965
return ctx->vtable.vaSyncSurface(ctx, pSurfaceGLX->surface);
968
static inline VAStatus
969
begin_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
973
status = sync_surface(ctx, pSurfaceGLX);
974
if (status != VA_STATUS_SUCCESS)
977
if (!bind_pixmap(ctx, pSurfaceGLX))
978
return VA_STATUS_ERROR_OPERATION_FAILED;
980
return VA_STATUS_SUCCESS;
983
static inline VAStatus
984
end_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
986
if (!unbind_pixmap(ctx, pSurfaceGLX))
987
return VA_STATUS_ERROR_OPERATION_FAILED;
989
return VA_STATUS_SUCCESS;
994
VADriverContextP ctx,
995
VASurfaceGLXP pSurfaceGLX,
1002
/* Associate VA surface */
1003
status = associate_surface(ctx, pSurfaceGLX, surface, flags);
1004
if (status != VA_STATUS_SUCCESS)
1008
fbo_enter(ctx, pSurfaceGLX);
1009
status = begin_render_surface(ctx, pSurfaceGLX);
1010
if (status == VA_STATUS_SUCCESS) {
1011
render_pixmap(ctx, pSurfaceGLX);
1012
status = end_render_surface(ctx, pSurfaceGLX);
1015
if (status != VA_STATUS_SUCCESS)
1018
return deassociate_surface(ctx, pSurfaceGLX);
1022
vaCopySurfaceGLX_impl_libva(
1023
VADriverContextP ctx,
1025
VASurfaceID surface,
1029
VASurfaceGLXP pSurfaceGLX;
1031
struct OpenGLContextState old_cs;
1033
INIT_SURFACE(pSurfaceGLX, gl_surface);
1035
if (!gl_set_current_context(pSurfaceGLX->gl_context, &old_cs))
1036
return VA_STATUS_ERROR_OPERATION_FAILED;
1038
status = copy_surface(ctx, pSurfaceGLX, surface, flags);
1040
gl_set_current_context(&old_cs, NULL);
1047
/* ========================================================================= */
1048
/* === Private VA/GLX vtable initialization === */
1049
/* ========================================================================= */
1051
// Initialize GLX driver context
1052
VAStatus va_glx_init_context(VADriverContextP ctx)
1054
VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
1055
VADriverVTableGLXP vtable = &glx_ctx->vtable;
1056
int glx_major, glx_minor;
1058
if (glx_ctx->is_initialized)
1059
return VA_STATUS_SUCCESS;
1061
if (ctx->vtable.glx && ctx->vtable.glx->vaCopySurfaceGLX) {
1062
vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_driver;
1063
vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_driver;
1064
vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_driver;
1067
vtable->vaCreateSurfaceGLX = vaCreateSurfaceGLX_impl_libva;
1068
vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_libva;
1069
vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
1071
if (!glXQueryVersion((Display *)ctx->native_dpy, &glx_major, &glx_minor))
1072
return VA_STATUS_ERROR_UNIMPLEMENTED;
1074
if (!check_tfp_extensions(ctx) || !load_tfp_extensions(ctx))
1075
return VA_STATUS_ERROR_UNIMPLEMENTED;
1077
if (!check_fbo_extensions(ctx) || !load_fbo_extensions(ctx))
1078
return VA_STATUS_ERROR_UNIMPLEMENTED;
1081
glx_ctx->is_initialized = 1;
1082
return VA_STATUS_SUCCESS;