~ubuntu-branches/ubuntu/natty/libva/natty

« back to all changes in this revision

Viewing changes to va/glx/va_glx_impl.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Artur Rona, Reinhard Tartler
  • Date: 2011-02-13 19:01:16 UTC
  • mfrom: (3.2.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110213190116-wy9fqh71nmomiacl
Tags: 1.0.8-3
[ Artur Rona ]
* Update library dependencies to fix FTBFS properly.

[ Reinhard Tartler ]
* Disable i965 driver on hurd-i386, Closes: #613102

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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, "libva-glx error: ");
 
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((Display *)ctx->native_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_create_pixmap = (PFNGLXCREATEPIXMAPPROC)
 
226
        get_proc_address("glXCreatePixmap");
 
227
    if (!pOpenGLVTable->glx_create_pixmap)
 
228
        return 0;
 
229
    pOpenGLVTable->glx_destroy_pixmap = (PFNGLXDESTROYPIXMAPPROC)
 
230
        get_proc_address("glXDestroyPixmap");
 
231
    if (!pOpenGLVTable->glx_destroy_pixmap)
 
232
        return 0;
 
233
    pOpenGLVTable->glx_bind_tex_image = (PFNGLXBINDTEXIMAGEEXTPROC)
 
234
        get_proc_address("glXBindTexImageEXT");
 
235
    if (!pOpenGLVTable->glx_bind_tex_image)
 
236
        return 0;
 
237
    pOpenGLVTable->glx_release_tex_image = (PFNGLXRELEASETEXIMAGEEXTPROC)
 
238
        get_proc_address("glXReleaseTexImageEXT");
 
239
    if (!pOpenGLVTable->glx_release_tex_image)
 
240
        return 0;
 
241
    return 1;
 
242
}
 
243
 
 
244
static int load_fbo_extensions(VADriverContextP ctx)
 
245
{
 
246
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
247
 
 
248
    pOpenGLVTable->gl_gen_framebuffers = (PFNGLGENFRAMEBUFFERSEXTPROC)
 
249
        get_proc_address("glGenFramebuffersEXT");
 
250
    if (!pOpenGLVTable->gl_gen_framebuffers)
 
251
        return 0;
 
252
    pOpenGLVTable->gl_delete_framebuffers = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
 
253
        get_proc_address("glDeleteFramebuffersEXT");
 
254
    if (!pOpenGLVTable->gl_delete_framebuffers)
 
255
        return 0;
 
256
    pOpenGLVTable->gl_bind_framebuffer = (PFNGLBINDFRAMEBUFFEREXTPROC)
 
257
        get_proc_address("glBindFramebufferEXT");
 
258
    if (!pOpenGLVTable->gl_bind_framebuffer)
 
259
        return 0;
 
260
    pOpenGLVTable->gl_gen_renderbuffers = (PFNGLGENRENDERBUFFERSEXTPROC)
 
261
        get_proc_address("glGenRenderbuffersEXT");
 
262
    if (!pOpenGLVTable->gl_gen_renderbuffers)
 
263
        return 0;
 
264
    pOpenGLVTable->gl_delete_renderbuffers = (PFNGLDELETERENDERBUFFERSEXTPROC)
 
265
        get_proc_address("glDeleteRenderbuffersEXT");
 
266
    if (!pOpenGLVTable->gl_delete_renderbuffers)
 
267
        return 0;
 
268
    pOpenGLVTable->gl_bind_renderbuffer = (PFNGLBINDRENDERBUFFEREXTPROC)
 
269
        get_proc_address("glBindRenderbufferEXT");
 
270
    if (!pOpenGLVTable->gl_bind_renderbuffer)
 
271
        return 0;
 
272
    pOpenGLVTable->gl_renderbuffer_storage = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
 
273
        get_proc_address("glRenderbufferStorageEXT");
 
274
    if (!pOpenGLVTable->gl_renderbuffer_storage)
 
275
        return 0;
 
276
    pOpenGLVTable->gl_framebuffer_renderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
 
277
        get_proc_address("glFramebufferRenderbufferEXT");
 
278
    if (!pOpenGLVTable->gl_framebuffer_renderbuffer)
 
279
        return 0;
 
280
    pOpenGLVTable->gl_framebuffer_texture_2d = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
 
281
        get_proc_address("glFramebufferTexture2DEXT");
 
282
    if (!pOpenGLVTable->gl_framebuffer_texture_2d)
 
283
        return 0;
 
284
    pOpenGLVTable->gl_check_framebuffer_status = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
 
285
        get_proc_address("glCheckFramebufferStatusEXT");
 
286
    if (!pOpenGLVTable->gl_check_framebuffer_status)
 
287
        return 0;
 
288
    return 1;
 
289
}
 
290
 
 
291
 
 
292
/* ========================================================================= */
 
293
/* === VA/GLX helpers                                                    === */
 
294
/* ========================================================================= */
 
295
 
 
296
// OpenGL context state
 
297
typedef struct OpenGLContextState *OpenGLContextStateP;
 
298
 
 
299
struct OpenGLContextState {
 
300
    Display     *display;
 
301
    Window       window;
 
302
    GLXContext   context;
 
303
};
 
304
 
 
305
static void
 
306
gl_destroy_context(OpenGLContextStateP cs)
 
307
{
 
308
    if (!cs)
 
309
        return;
 
310
 
 
311
    if (cs->display && cs->context) {
 
312
        if (glXGetCurrentContext() == cs->context)
 
313
            glXMakeCurrent(cs->display, None, NULL);
 
314
        glXDestroyContext(cs->display, cs->context);
 
315
        cs->display = NULL;
 
316
        cs->context = NULL;
 
317
    }
 
318
    free(cs);
 
319
}
 
320
 
 
321
static OpenGLContextStateP
 
322
gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
 
323
{
 
324
    OpenGLContextStateP cs;
 
325
    GLXFBConfig *fbconfigs = NULL;
 
326
    int fbconfig_id, val, n, n_fbconfigs;
 
327
    Status status;
 
328
 
 
329
    static GLint fbconfig_attrs[] = {
 
330
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
 
331
        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
 
332
        GLX_DOUBLEBUFFER,  True,
 
333
        GLX_RED_SIZE,      8,
 
334
        GLX_GREEN_SIZE,    8, 
 
335
        GLX_BLUE_SIZE,     8,
 
336
        None
 
337
    };
 
338
 
 
339
    cs = malloc(sizeof(*cs));
 
340
    if (!cs)
 
341
        goto error;
 
342
 
 
343
    cs->display = (Display *)ctx->native_dpy;
 
344
    cs->window  = parent ? parent->window : None;
 
345
    cs->context = NULL;
 
346
 
 
347
    if (parent && parent->context) {
 
348
        status = glXQueryContext(
 
349
            parent->display,
 
350
            parent->context,
 
351
            GLX_FBCONFIG_ID, &fbconfig_id
 
352
        );
 
353
        if (status != Success)
 
354
            goto error;
 
355
 
 
356
        if (fbconfig_id == GLX_DONT_CARE)
 
357
            goto choose_fbconfig;
 
358
 
 
359
        fbconfigs = glXGetFBConfigs(
 
360
            (Display *)ctx->native_dpy,
 
361
            ctx->x11_screen,
 
362
            &n_fbconfigs
 
363
        );
 
364
        if (!fbconfigs)
 
365
            goto error;
 
366
 
 
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,
 
371
                fbconfigs[n],
 
372
                GLX_FBCONFIG_ID, &val
 
373
            );
 
374
            if (status == Success && val == fbconfig_id)
 
375
                break;
 
376
        }
 
377
        if (n == n_fbconfigs)
 
378
            goto error;
 
379
    }
 
380
    else {
 
381
    choose_fbconfig:
 
382
        fbconfigs = glXChooseFBConfig(
 
383
            (Display *)ctx->native_dpy,
 
384
            ctx->x11_screen,
 
385
            fbconfig_attrs, &n_fbconfigs
 
386
        );
 
387
        if (!fbconfigs)
 
388
            goto error;
 
389
 
 
390
        /* Select the first one */
 
391
        n = 0;
 
392
    }
 
393
 
 
394
    cs->context = glXCreateNewContext(
 
395
        (Display *)ctx->native_dpy,
 
396
        fbconfigs[n],
 
397
        GLX_RGBA_TYPE,
 
398
        parent ? parent->context : NULL,
 
399
        True
 
400
    );
 
401
    if (cs->context)
 
402
        goto end;
 
403
 
 
404
error:
 
405
    gl_destroy_context(cs);
 
406
    cs = NULL;
 
407
end:
 
408
    if (fbconfigs)
 
409
        XFree(fbconfigs);
 
410
    return cs;
 
411
}
 
412
 
 
413
static void gl_get_current_context(OpenGLContextStateP cs)
 
414
{
 
415
    cs->display = glXGetCurrentDisplay();
 
416
    cs->window  = glXGetCurrentDrawable();
 
417
    cs->context = glXGetCurrentContext();
 
418
}
 
419
 
 
420
static int
 
421
gl_set_current_context(OpenGLContextStateP new_cs, OpenGLContextStateP old_cs)
 
422
{
 
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;
 
428
 
 
429
    if (old_cs) {
 
430
        if (old_cs == new_cs)
 
431
            return 1;
 
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)
 
436
            return 1;
 
437
    }
 
438
    return glXMakeCurrent(new_cs->display, new_cs->window, new_cs->context);
 
439
}
 
440
 
 
441
/** Unique VASurfaceGLX identifier */
 
442
#define VA_SURFACE_GLX_MAGIC VA_FOURCC('V','A','G','L')
 
443
 
 
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
 
449
    unsigned int        width;
 
450
    unsigned int        height;
 
451
    OpenGLContextStateP gl_context;
 
452
    int                 is_bound;
 
453
    Pixmap              pixmap;
 
454
    GLuint              pix_texture;
 
455
    GLXPixmap           glx_pixmap;
 
456
    GLuint              fbo;
 
457
};
 
458
 
 
459
// Create Pixmaps for GLX texture-from-pixmap extension
 
460
static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
461
{
 
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;
 
468
    Window                root_window;
 
469
    XWindowAttributes     wattr;
 
470
    int                  *attrib;
 
471
    int                   n_fbconfig_attrs;
 
472
 
 
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)
 
476
        return 0;
 
477
    pixmap = XCreatePixmap(
 
478
        (Display *)ctx->native_dpy,
 
479
        root_window,
 
480
        width,
 
481
        height,
 
482
        wattr.depth
 
483
    );
 
484
    if (!pixmap)
 
485
        return 0;
 
486
    pSurfaceGLX->pixmap = pixmap;
 
487
 
 
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,
 
494
        GLX_RED_SIZE,           8,
 
495
        GLX_GREEN_SIZE,         8,
 
496
        GLX_BLUE_SIZE,          8,
 
497
        GL_NONE,
 
498
    };
 
499
    for (attrib = fbconfig_attrs; *attrib != GL_NONE; attrib += 2)
 
500
        ;
 
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;
 
505
    }
 
506
    else {
 
507
    *attrib++ = GLX_BIND_TO_TEXTURE_RGB_EXT;    *attrib++ = GL_TRUE;
 
508
    }
 
509
    *attrib++ = GL_NONE;
 
510
 
 
511
    fbconfig = glXChooseFBConfig(
 
512
        (Display *)ctx->native_dpy,
 
513
        ctx->x11_screen,
 
514
        fbconfig_attrs,
 
515
        &n_fbconfig_attrs
 
516
    );
 
517
    if (!fbconfig)
 
518
        return 0;
 
519
 
 
520
    int pixmap_attrs[10] = {
 
521
        GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
 
522
        GLX_MIPMAP_TEXTURE_EXT, GL_FALSE,
 
523
        GL_NONE,
 
524
    };
 
525
    for (attrib = pixmap_attrs; *attrib != GL_NONE; attrib += 2)
 
526
        ;
 
527
    *attrib++ = GLX_TEXTURE_FORMAT_EXT;
 
528
    if (wattr.depth == 32)
 
529
    *attrib++ = GLX_TEXTURE_FORMAT_RGBA_EXT;
 
530
    else
 
531
    *attrib++ = GLX_TEXTURE_FORMAT_RGB_EXT;
 
532
    *attrib++ = GL_NONE;
 
533
 
 
534
    x11_trap_errors();
 
535
    glx_pixmap = pOpenGLVTable->glx_create_pixmap(
 
536
        (Display *)ctx->native_dpy,
 
537
        fbconfig[0],
 
538
        pixmap,
 
539
        pixmap_attrs
 
540
    );
 
541
    free(fbconfig);
 
542
    if (x11_untrap_errors() != 0)
 
543
        return 0;
 
544
    pSurfaceGLX->glx_pixmap = glx_pixmap;
 
545
 
 
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);
 
550
    return 1;
 
551
}
 
552
 
 
553
// Destroy Pixmaps used for TFP
 
554
static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
555
{
 
556
    VAOpenGLVTableP const pOpenGLVTable = gl_get_vtable(ctx);
 
557
 
 
558
    if (pSurfaceGLX->pix_texture) {
 
559
        glDeleteTextures(1, &pSurfaceGLX->pix_texture);
 
560
        pSurfaceGLX->pix_texture = 0;
 
561
    }
 
562
 
 
563
    if (pSurfaceGLX->glx_pixmap) {
 
564
        pOpenGLVTable->glx_destroy_pixmap((Display *)ctx->native_dpy, pSurfaceGLX->glx_pixmap);
 
565
        pSurfaceGLX->glx_pixmap = None;
 
566
    }
 
567
 
 
568
    if (pSurfaceGLX->pixmap) {
 
569
        XFreePixmap((Display *)ctx->native_dpy, pSurfaceGLX->pixmap);
 
570
        pSurfaceGLX->pixmap = None;
 
571
    }
 
572
}
 
573
 
 
574
// Bind GLX Pixmap to texture
 
575
static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
576
{
 
577
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
578
 
 
579
    if (pSurfaceGLX->is_bound)
 
580
        return 1;
 
581
 
 
582
    glBindTexture(GL_TEXTURE_2D, pSurfaceGLX->pix_texture);
 
583
 
 
584
    x11_trap_errors();
 
585
    pOpenGLVTable->glx_bind_tex_image(
 
586
        (Display *)ctx->native_dpy,
 
587
        pSurfaceGLX->glx_pixmap,
 
588
        GLX_FRONT_LEFT_EXT,
 
589
        NULL
 
590
    );
 
591
    XSync((Display *)ctx->native_dpy, False);
 
592
    if (x11_untrap_errors() != 0) {
 
593
        va_glx_error_message("failed to bind pixmap\n");
 
594
        return 0;
 
595
    }
 
596
 
 
597
    pSurfaceGLX->is_bound = 1;
 
598
    return 1;
 
599
}
 
600
 
 
601
// Release GLX Pixmap from texture
 
602
static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
603
{
 
604
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
605
 
 
606
    if (!pSurfaceGLX->is_bound)
 
607
        return 1;
 
608
 
 
609
    x11_trap_errors();
 
610
    pOpenGLVTable->glx_release_tex_image(
 
611
        (Display *)ctx->native_dpy,
 
612
        pSurfaceGLX->glx_pixmap,
 
613
        GLX_FRONT_LEFT_EXT
 
614
    );
 
615
    XSync((Display *)ctx->native_dpy, False);
 
616
    if (x11_untrap_errors() != 0) {
 
617
        va_glx_error_message("failed to release pixmap\n");
 
618
        return 0;
 
619
    }
 
620
 
 
621
    glBindTexture(GL_TEXTURE_2D, 0);
 
622
 
 
623
    pSurfaceGLX->is_bound = 0;
 
624
    return 1;
 
625
}
 
626
 
 
627
// Render GLX Pixmap to texture
 
628
static void render_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
629
{
 
630
    const unsigned int w = pSurfaceGLX->width;
 
631
    const unsigned int h = pSurfaceGLX->height;
 
632
 
 
633
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 
634
    glBegin(GL_QUADS);
 
635
    {
 
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);
 
640
    }
 
641
    glEnd();
 
642
}
 
643
 
 
644
// Create offscreen surface
 
645
static int create_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
646
{
 
647
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
648
    GLuint fbo;
 
649
    GLenum status;
 
650
 
 
651
    pOpenGLVTable->gl_gen_framebuffers(1, &fbo);
 
652
    pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, fbo);
 
653
    pOpenGLVTable->gl_framebuffer_texture_2d(
 
654
        GL_FRAMEBUFFER_EXT,
 
655
        GL_COLOR_ATTACHMENT0_EXT,
 
656
        GL_TEXTURE_2D,
 
657
        pSurfaceGLX->texture,
 
658
        0
 
659
    );
 
660
 
 
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)
 
664
        return 0;
 
665
 
 
666
    pSurfaceGLX->fbo = fbo;
 
667
    return 1;
 
668
}
 
669
 
 
670
// Destroy offscreen surface
 
671
static void destroy_fbo_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
672
{
 
673
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
674
 
 
675
    if (pSurfaceGLX->fbo) {
 
676
        pOpenGLVTable->gl_delete_framebuffers(1, &pSurfaceGLX->fbo);
 
677
        pSurfaceGLX->fbo = 0;
 
678
    }
 
679
}
 
680
 
 
681
// Setup matrices to match the FBO texture dimensions
 
682
static void fbo_enter(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
683
{
 
684
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
685
    const unsigned int width  = pSurfaceGLX->width;
 
686
    const unsigned int height = pSurfaceGLX->height;
 
687
 
 
688
    pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, pSurfaceGLX->fbo);
 
689
    glPushAttrib(GL_VIEWPORT_BIT);
 
690
    glMatrixMode(GL_PROJECTION);
 
691
    glPushMatrix();
 
692
    glLoadIdentity();
 
693
    glMatrixMode(GL_MODELVIEW);
 
694
    glPushMatrix();
 
695
    glLoadIdentity();
 
696
    glViewport(0, 0, width, height);
 
697
    glTranslatef(-1.0f, -1.0f, 0.0f);
 
698
    glScalef(2.0f / width, 2.0f / height, 1.0f);
 
699
}
 
700
 
 
701
// Restore original OpenGL matrices
 
702
static void fbo_leave(VADriverContextP ctx)
 
703
{
 
704
    VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
 
705
 
 
706
    glPopAttrib();
 
707
    glMatrixMode(GL_PROJECTION);
 
708
    glPopMatrix();
 
709
    glMatrixMode(GL_MODELVIEW);
 
710
    glPopMatrix();
 
711
    pOpenGLVTable->gl_bind_framebuffer(GL_FRAMEBUFFER_EXT, 0);
 
712
}
 
713
 
 
714
// Check internal texture format is supported
 
715
static int is_supported_internal_format(GLenum format)
 
716
{
 
717
    /* XXX: we don't support other textures than RGBA */
 
718
    switch (format) {
 
719
    case 4:
 
720
    case GL_RGBA:
 
721
    case GL_RGBA8:
 
722
        return 1;
 
723
    }
 
724
    return 0;
 
725
}
 
726
 
 
727
// Destroy VA/GLX surface
 
728
static void
 
729
destroy_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
730
{
 
731
    unbind_pixmap(ctx, pSurfaceGLX);
 
732
    destroy_fbo_surface(ctx, pSurfaceGLX);
 
733
    destroy_tfp_surface(ctx, pSurfaceGLX);
 
734
    free(pSurfaceGLX);
 
735
}
 
736
 
 
737
// Create VA/GLX surface
 
738
static VASurfaceGLXP
 
739
create_surface(VADriverContextP ctx, GLenum target, GLuint texture)
 
740
{
 
741
    VASurfaceGLXP pSurfaceGLX = NULL;
 
742
    unsigned int internal_format, border_width, width, height;
 
743
    int is_error = 1;
 
744
 
 
745
    pSurfaceGLX = malloc(sizeof(*pSurfaceGLX));
 
746
    if (!pSurfaceGLX)
 
747
        goto end;
 
748
 
 
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;
 
759
 
 
760
    glEnable(target);
 
761
    glBindTexture(target, texture);
 
762
    if (!gl_get_texture_param(GL_TEXTURE_INTERNAL_FORMAT, &internal_format))
 
763
        goto end;
 
764
    if (!is_supported_internal_format(internal_format))
 
765
        goto end;
 
766
 
 
767
    /* Check texture dimensions */
 
768
    if (!gl_get_texture_param(GL_TEXTURE_BORDER, &border_width))
 
769
        goto end;
 
770
    if (!gl_get_texture_param(GL_TEXTURE_WIDTH, &width))
 
771
        goto end;
 
772
    if (!gl_get_texture_param(GL_TEXTURE_HEIGHT, &height))
 
773
        goto end;
 
774
 
 
775
    width  -= 2 * border_width;
 
776
    height -= 2 * border_width;
 
777
    if (width == 0 || height == 0)
 
778
        goto end;
 
779
 
 
780
    pSurfaceGLX->width  = width;
 
781
    pSurfaceGLX->height = height;
 
782
 
 
783
    /* Create TFP objects */
 
784
    if (!create_tfp_surface(ctx, pSurfaceGLX))
 
785
        goto end;
 
786
 
 
787
    /* Create FBO objects */
 
788
    if (!create_fbo_surface(ctx, pSurfaceGLX))
 
789
        goto end;
 
790
 
 
791
    is_error = 0;
 
792
end:
 
793
    if (is_error && pSurfaceGLX) {
 
794
        destroy_surface(ctx, pSurfaceGLX);
 
795
        pSurfaceGLX = NULL;
 
796
    }
 
797
    return pSurfaceGLX;
 
798
}
 
799
 
 
800
 
 
801
/* ========================================================================= */
 
802
/* === VA/GLX implementation from the driver (fordward calls)            === */
 
803
/* ========================================================================= */
 
804
 
 
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;       \
 
809
                                                        \
 
810
        VAStatus status = vtable->va##func##GLX args;   \
 
811
        if (status != VA_STATUS_SUCCESS)                \
 
812
            return status;                              \
 
813
    } while (0)
 
814
 
 
815
static VAStatus
 
816
vaCreateSurfaceGLX_impl_driver(
 
817
    VADriverContextP    ctx,
 
818
    GLenum              target,
 
819
    GLuint              texture,
 
820
    void              **gl_surface
 
821
)
 
822
{
 
823
    INVOKE(ctx, CreateSurface, (ctx, target, texture, gl_surface));
 
824
    return VA_STATUS_SUCCESS;
 
825
}
 
826
 
 
827
static VAStatus
 
828
vaDestroySurfaceGLX_impl_driver(VADriverContextP ctx, void *gl_surface)
 
829
{
 
830
    INVOKE(ctx, DestroySurface, (ctx, gl_surface));
 
831
    return VA_STATUS_SUCCESS;
 
832
}
 
833
 
 
834
static VAStatus
 
835
vaCopySurfaceGLX_impl_driver(
 
836
    VADriverContextP    ctx,
 
837
    void               *gl_surface,
 
838
    VASurfaceID         surface,
 
839
    unsigned int        flags
 
840
)
 
841
{
 
842
    INVOKE(ctx, CopySurface, (ctx, gl_surface, surface, flags));
 
843
    return VA_STATUS_SUCCESS;
 
844
}
 
845
 
 
846
#undef INVOKE
 
847
 
 
848
 
 
849
/* ========================================================================= */
 
850
/* === VA/GLX implementation from libVA (generic and suboptimal path)    === */
 
851
/* ========================================================================= */
 
852
 
 
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;     \
 
857
    } while (0)
 
858
 
 
859
// Check VASurfaceGLX is valid
 
860
static inline int check_surface(VASurfaceGLXP pSurfaceGLX)
 
861
{
 
862
    return pSurfaceGLX && pSurfaceGLX->magic == VA_SURFACE_GLX_MAGIC;
 
863
}
 
864
 
 
865
static VAStatus
 
866
vaCreateSurfaceGLX_impl_libva(
 
867
    VADriverContextP    ctx,
 
868
    GLenum              target,
 
869
    GLuint              texture,
 
870
    void              **gl_surface
 
871
)
 
872
{
 
873
    VASurfaceGLXP pSurfaceGLX;
 
874
    struct OpenGLContextState old_cs, *new_cs;
 
875
 
 
876
    gl_get_current_context(&old_cs);
 
877
    new_cs = gl_create_context(ctx, &old_cs);
 
878
    if (!new_cs)
 
879
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
880
    if (!gl_set_current_context(new_cs, NULL))
 
881
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
882
 
 
883
    pSurfaceGLX = create_surface(ctx, target, texture);
 
884
    if (!pSurfaceGLX)
 
885
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
886
 
 
887
    pSurfaceGLX->gl_context = new_cs;
 
888
    *gl_surface = pSurfaceGLX;
 
889
 
 
890
    gl_set_current_context(&old_cs, NULL);
 
891
    return VA_STATUS_SUCCESS;
 
892
}
 
893
 
 
894
static VAStatus
 
895
vaDestroySurfaceGLX_impl_libva(VADriverContextP ctx, void *gl_surface)
 
896
{
 
897
    VASurfaceGLXP pSurfaceGLX;
 
898
    struct OpenGLContextState old_cs, *new_cs;
 
899
 
 
900
    INIT_SURFACE(pSurfaceGLX, gl_surface);
 
901
 
 
902
    new_cs = pSurfaceGLX->gl_context;
 
903
    if (!gl_set_current_context(new_cs, &old_cs))
 
904
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
905
 
 
906
    destroy_surface(ctx, pSurfaceGLX);
 
907
 
 
908
    gl_destroy_context(new_cs);
 
909
    gl_set_current_context(&old_cs, NULL);
 
910
    return VA_STATUS_SUCCESS;
 
911
}
 
912
 
 
913
static inline VAStatus
 
914
deassociate_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
915
{
 
916
    if (!unbind_pixmap(ctx, pSurfaceGLX))
 
917
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
918
 
 
919
    pSurfaceGLX->surface = VA_INVALID_SURFACE;
 
920
    return VA_STATUS_SUCCESS;
 
921
}
 
922
 
 
923
static VAStatus
 
924
associate_surface(
 
925
    VADriverContextP    ctx,
 
926
    VASurfaceGLXP       pSurfaceGLX,
 
927
    VASurfaceID         surface,
 
928
    unsigned int        flags
 
929
)
 
930
{
 
931
    VAStatus status;
 
932
 
 
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)
 
937
        return status;
 
938
 
 
939
    x11_trap_errors();
 
940
    status = ctx->vtable.vaPutSurface(
 
941
        ctx,
 
942
        surface,
 
943
        (void *)pSurfaceGLX->pixmap,
 
944
        0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
 
945
        0, 0, pSurfaceGLX->width, pSurfaceGLX->height,
 
946
        NULL, 0,
 
947
        flags
 
948
    );
 
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)
 
953
        return status;
 
954
 
 
955
    pSurfaceGLX->surface = surface;
 
956
    return VA_STATUS_SUCCESS;
 
957
}
 
958
 
 
959
static inline VAStatus
 
960
sync_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
961
{
 
962
    if (pSurfaceGLX->surface == VA_INVALID_SURFACE)
 
963
        return VA_STATUS_ERROR_INVALID_SURFACE;
 
964
 
 
965
    return ctx->vtable.vaSyncSurface(ctx, pSurfaceGLX->surface);
 
966
}
 
967
 
 
968
static inline VAStatus
 
969
begin_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
970
{
 
971
    VAStatus status;
 
972
 
 
973
    status = sync_surface(ctx, pSurfaceGLX);
 
974
    if (status != VA_STATUS_SUCCESS)
 
975
        return status;
 
976
 
 
977
    if (!bind_pixmap(ctx, pSurfaceGLX))
 
978
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
979
 
 
980
    return VA_STATUS_SUCCESS;
 
981
}
 
982
 
 
983
static inline VAStatus
 
984
end_render_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
 
985
{
 
986
    if (!unbind_pixmap(ctx, pSurfaceGLX))
 
987
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
988
 
 
989
    return VA_STATUS_SUCCESS;
 
990
}
 
991
 
 
992
static VAStatus
 
993
copy_surface(
 
994
    VADriverContextP    ctx,
 
995
    VASurfaceGLXP       pSurfaceGLX,
 
996
    VASurfaceID         surface,
 
997
    unsigned int        flags
 
998
)
 
999
{
 
1000
    VAStatus status;
 
1001
 
 
1002
    /* Associate VA surface */
 
1003
    status = associate_surface(ctx, pSurfaceGLX, surface, flags);
 
1004
    if (status != VA_STATUS_SUCCESS)
 
1005
        return status;
 
1006
 
 
1007
    /* Render to FBO */
 
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);
 
1013
    }
 
1014
    fbo_leave(ctx);
 
1015
    if (status != VA_STATUS_SUCCESS)
 
1016
        return status;
 
1017
 
 
1018
    return deassociate_surface(ctx, pSurfaceGLX);
 
1019
}
 
1020
 
 
1021
static VAStatus
 
1022
vaCopySurfaceGLX_impl_libva(
 
1023
    VADriverContextP    ctx,
 
1024
    void               *gl_surface,
 
1025
    VASurfaceID         surface,
 
1026
    unsigned int        flags
 
1027
)
 
1028
{
 
1029
    VASurfaceGLXP pSurfaceGLX;
 
1030
    VAStatus status;
 
1031
    struct OpenGLContextState old_cs;
 
1032
 
 
1033
    INIT_SURFACE(pSurfaceGLX, gl_surface);
 
1034
 
 
1035
    if (!gl_set_current_context(pSurfaceGLX->gl_context, &old_cs))
 
1036
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
1037
 
 
1038
    status = copy_surface(ctx, pSurfaceGLX, surface, flags);
 
1039
 
 
1040
    gl_set_current_context(&old_cs, NULL);
 
1041
    return status;
 
1042
}
 
1043
 
 
1044
#undef INIT_SURFACE
 
1045
 
 
1046
 
 
1047
/* ========================================================================= */
 
1048
/* === Private VA/GLX vtable initialization                              === */
 
1049
/* ========================================================================= */
 
1050
 
 
1051
// Initialize GLX driver context
 
1052
VAStatus va_glx_init_context(VADriverContextP ctx)
 
1053
{
 
1054
    VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
 
1055
    VADriverVTableGLXP  vtable  = &glx_ctx->vtable;
 
1056
    int glx_major, glx_minor;
 
1057
 
 
1058
    if (glx_ctx->is_initialized)
 
1059
        return VA_STATUS_SUCCESS;
 
1060
 
 
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;
 
1065
    }
 
1066
    else {
 
1067
        vtable->vaCreateSurfaceGLX      = vaCreateSurfaceGLX_impl_libva;
 
1068
        vtable->vaDestroySurfaceGLX     = vaDestroySurfaceGLX_impl_libva;
 
1069
        vtable->vaCopySurfaceGLX        = vaCopySurfaceGLX_impl_libva;
 
1070
 
 
1071
        if (!glXQueryVersion((Display *)ctx->native_dpy, &glx_major, &glx_minor))
 
1072
            return VA_STATUS_ERROR_UNIMPLEMENTED;
 
1073
 
 
1074
        if (!check_tfp_extensions(ctx) || !load_tfp_extensions(ctx))
 
1075
            return VA_STATUS_ERROR_UNIMPLEMENTED;
 
1076
 
 
1077
        if (!check_fbo_extensions(ctx) || !load_fbo_extensions(ctx))
 
1078
            return VA_STATUS_ERROR_UNIMPLEMENTED;
 
1079
    }
 
1080
 
 
1081
    glx_ctx->is_initialized = 1;
 
1082
    return VA_STATUS_SUCCESS;
 
1083
}