Commit 451428c4 authored by Gwenole Beauchesne's avatar Gwenole Beauchesne Committed by Jean-Paul Saman

x11: create alternate X connections (MT-safe).

Make sure VA/X11 and VA/GLX backends can be used independently from
the user-provided master X display. Create alternate thread-local X
connections for VA-specific purposes.

This allows for async VA initialization without the need for the
program to explicitly call XInitThreads() beforehand.
Signed-off-by: default avatarGwenole Beauchesne <gwenole.beauchesne@intel.com>
parent b1bc8cf8
......@@ -25,6 +25,7 @@
#define _GNU_SOURCE 1
#include "va_glx_private.h"
#include "va_glx_impl.h"
#include "va_backend_x11.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
......@@ -192,6 +193,7 @@ static int check_extension(const char *name, const char *ext)
static int check_tfp_extensions(VADriverContextP ctx)
{
Display * const x11_dpy = va_x11_get_display(ctx);
const char *gl_extensions;
const char *glx_extensions;
......@@ -199,7 +201,7 @@ static int check_tfp_extensions(VADriverContextP ctx)
if (!check_extension("GL_ARB_texture_non_power_of_two", gl_extensions))
return 0;
glx_extensions = glXQueryExtensionsString(ctx->native_dpy, ctx->x11_screen);
glx_extensions = glXQueryExtensionsString(x11_dpy, ctx->x11_screen);
if (!check_extension("GLX_EXT_texture_from_pixmap", glx_extensions))
return 0;
return 1;
......@@ -321,6 +323,7 @@ gl_destroy_context(OpenGLContextStateP cs)
static OpenGLContextStateP
gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
{
Display * const x11_dpy = va_x11_get_display(ctx);
OpenGLContextStateP cs;
GLXFBConfig *fbconfigs = NULL;
int fbconfig_id, val, n, n_fbconfigs;
......@@ -340,7 +343,7 @@ gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
if (!cs)
goto error;
cs->display = ctx->native_dpy;
cs->display = x11_dpy;
cs->window = parent ? parent->window : None;
cs->context = NULL;
......@@ -357,7 +360,7 @@ gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
goto choose_fbconfig;
fbconfigs = glXGetFBConfigs(
ctx->native_dpy,
x11_dpy,
ctx->x11_screen,
&n_fbconfigs
);
......@@ -367,7 +370,7 @@ gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
/* Find out a GLXFBConfig compatible with the parent context */
for (n = 0; n < n_fbconfigs; n++) {
status = glXGetFBConfigAttrib(
ctx->native_dpy,
x11_dpy,
fbconfigs[n],
GLX_FBCONFIG_ID, &val
);
......@@ -380,7 +383,7 @@ gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
else {
choose_fbconfig:
fbconfigs = glXChooseFBConfig(
ctx->native_dpy,
x11_dpy,
ctx->x11_screen,
fbconfig_attrs, &n_fbconfigs
);
......@@ -392,7 +395,7 @@ gl_create_context(VADriverContextP ctx, OpenGLContextStateP parent)
}
cs->context = glXCreateNewContext(
ctx->native_dpy,
x11_dpy,
fbconfigs[n],
GLX_RGBA_TYPE,
parent ? parent->context : NULL,
......@@ -459,6 +462,7 @@ struct VASurfaceGLX {
// Create Pixmaps for GLX texture-from-pixmap extension
static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VAOpenGLVTableP const pOpenGLVTable = gl_get_vtable(ctx);
const unsigned int width = pSurfaceGLX->width;
const unsigned int height = pSurfaceGLX->height;
......@@ -470,12 +474,12 @@ static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
int *attrib;
int n_fbconfig_attrs;
root_window = RootWindow(ctx->native_dpy, ctx->x11_screen);
XGetWindowAttributes(ctx->native_dpy, root_window, &wattr);
root_window = RootWindow(x11_dpy, ctx->x11_screen);
XGetWindowAttributes(x11_dpy, root_window, &wattr);
if (wattr.depth != 24 && wattr.depth != 32)
return 0;
pixmap = XCreatePixmap(
ctx->native_dpy,
x11_dpy,
root_window,
width,
height,
......@@ -509,7 +513,7 @@ static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
*attrib++ = GL_NONE;
fbconfig = glXChooseFBConfig(
ctx->native_dpy,
x11_dpy,
ctx->x11_screen,
fbconfig_attrs,
&n_fbconfig_attrs
......@@ -533,7 +537,7 @@ static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
x11_trap_errors();
glx_pixmap = pOpenGLVTable->glx_create_pixmap(
ctx->native_dpy,
x11_dpy,
fbconfig[0],
pixmap,
pixmap_attrs
......@@ -553,6 +557,7 @@ static int create_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
// Destroy Pixmaps used for TFP
static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VAOpenGLVTableP const pOpenGLVTable = gl_get_vtable(ctx);
if (pSurfaceGLX->pix_texture) {
......@@ -561,12 +566,12 @@ static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
}
if (pSurfaceGLX->glx_pixmap) {
pOpenGLVTable->glx_destroy_pixmap(ctx->native_dpy, pSurfaceGLX->glx_pixmap);
pOpenGLVTable->glx_destroy_pixmap(x11_dpy, pSurfaceGLX->glx_pixmap);
pSurfaceGLX->glx_pixmap = None;
}
if (pSurfaceGLX->pixmap) {
XFreePixmap(ctx->native_dpy, pSurfaceGLX->pixmap);
XFreePixmap(x11_dpy, pSurfaceGLX->pixmap);
pSurfaceGLX->pixmap = None;
}
}
......@@ -574,6 +579,7 @@ static void destroy_tfp_surface(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
// Bind GLX Pixmap to texture
static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
if (pSurfaceGLX->is_bound)
......@@ -583,12 +589,12 @@ static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
x11_trap_errors();
pOpenGLVTable->glx_bind_tex_image(
ctx->native_dpy,
x11_dpy,
pSurfaceGLX->glx_pixmap,
GLX_FRONT_LEFT_EXT,
NULL
);
XSync(ctx->native_dpy, False);
XSync(x11_dpy, False);
if (x11_untrap_errors() != 0) {
va_glx_error_message("failed to bind pixmap\n");
return 0;
......@@ -601,6 +607,7 @@ static int bind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
// Release GLX Pixmap from texture
static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VAOpenGLVTableP pOpenGLVTable = gl_get_vtable(ctx);
if (!pSurfaceGLX->is_bound)
......@@ -608,11 +615,11 @@ static int unbind_pixmap(VADriverContextP ctx, VASurfaceGLXP pSurfaceGLX)
x11_trap_errors();
pOpenGLVTable->glx_release_tex_image(
ctx->native_dpy,
x11_dpy,
pSurfaceGLX->glx_pixmap,
GLX_FRONT_LEFT_EXT
);
XSync(ctx->native_dpy, False);
XSync(x11_dpy, False);
if (x11_untrap_errors() != 0) {
va_glx_error_message("failed to release pixmap\n");
return 0;
......@@ -928,6 +935,7 @@ associate_surface(
unsigned int flags
)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VAStatus status;
/* XXX: optimise case where we are associating the same VA surface
......@@ -946,7 +954,7 @@ associate_surface(
NULL, 0,
flags
);
XSync(ctx->native_dpy, False);
XSync(x11_dpy, False);
if (x11_untrap_errors() != 0)
return VA_STATUS_ERROR_OPERATION_FAILED;
if (status != VA_STATUS_SUCCESS)
......@@ -1051,6 +1059,7 @@ vaCopySurfaceGLX_impl_libva(
// Initialize GLX driver context
VAStatus va_glx_init_context(VADriverContextP ctx)
{
Display * const x11_dpy = va_x11_get_display(ctx);
VADriverContextGLXP glx_ctx = VA_DRIVER_CONTEXT_GLX(ctx);
VADriverVTableGLXP vtable = &glx_ctx->vtable;
int glx_major, glx_minor;
......@@ -1068,7 +1077,7 @@ VAStatus va_glx_init_context(VADriverContextP ctx)
vtable->vaDestroySurfaceGLX = vaDestroySurfaceGLX_impl_libva;
vtable->vaCopySurfaceGLX = vaCopySurfaceGLX_impl_libva;
if (!glXQueryVersion(ctx->native_dpy, &glx_major, &glx_minor))
if (!glXQueryVersion(x11_dpy, &glx_major, &glx_minor))
return VA_STATUS_ERROR_UNIMPLEMENTED;
if (!check_tfp_extensions(ctx) || !load_tfp_extensions(ctx))
......
......@@ -433,8 +433,9 @@ struct VADriverContext
void *dri_state;
void *glx; /* opaque for GLX code */
void *tls_state; /* opaque for thread-local data */
unsigned long reserved[45]; /* reserve for future add-ins, decrease the subscript accordingly */
unsigned long reserved[44]; /* reserve for future add-ins, decrease the subscript accordingly */
};
#define VA_DISPLAY_MAGIC 0x56414430 /* VAD0 */
......
......@@ -34,6 +34,7 @@ source_c = \
$(NULL)
source_h = \
va_backend_x11.h \
va_dri.h \
va_dri2.h \
va_dricommon.h \
......
......@@ -9,6 +9,7 @@
#include "X11/Xlib.h"
#include "va.h"
#include "va_backend.h"
#include "va_backend_x11.h"
#include "va_dri.h"
#include "va_dricommon.h"
......@@ -60,19 +61,21 @@ static void
dri1Close(VADriverContextP ctx)
{
struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
Display * const x11_dpy = va_x11_get_display(ctx);
free_drawable_hashtable(ctx);
VA_DRIDestroyContext(ctx->native_dpy, ctx->x11_screen, dri_state->hwContextID);
VA_DRIDestroyContext(x11_dpy, ctx->x11_screen, dri_state->hwContextID);
assert(dri_state->pSAREA != MAP_FAILED);
drmUnmap(dri_state->pSAREA, SAREA_MAX);
assert(dri_state->fd >= 0);
drmCloseOnce(dri_state->fd);
VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
VA_DRICloseConnection(x11_dpy, ctx->x11_screen);
}
Bool
isDRI1Connected(VADriverContextP ctx, char **driver_name)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
int direct_capable;
int driver_major;
......@@ -87,7 +90,7 @@ isDRI1Connected(VADriverContextP ctx, char **driver_name)
dri_state->pSAREA = MAP_FAILED;
dri_state->driConnectedFlag = VA_NONE;
if (!VA_DRIQueryDirectRenderingCapable(ctx->native_dpy,
if (!VA_DRIQueryDirectRenderingCapable(x11_dpy,
ctx->x11_screen,
&direct_capable))
goto err_out0;
......@@ -95,12 +98,12 @@ isDRI1Connected(VADriverContextP ctx, char **driver_name)
if (!direct_capable)
goto err_out0;
if (!VA_DRIGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
if (!VA_DRIGetClientDriverName(x11_dpy, ctx->x11_screen,
&driver_major, &driver_minor,
&driver_patch, driver_name))
goto err_out0;
if (!VA_DRIOpenConnection(ctx->native_dpy, ctx->x11_screen,
if (!VA_DRIOpenConnection(x11_dpy, ctx->x11_screen,
&dri_state->hSAREA, &BusID))
goto err_out0;
......@@ -115,14 +118,14 @@ isDRI1Connected(VADriverContextP ctx, char **driver_name)
if (drmGetMagic(dri_state->fd, &magic))
goto err_out1;
if (newlyopened && !VA_DRIAuthConnection(ctx->native_dpy, ctx->x11_screen, magic))
if (newlyopened && !VA_DRIAuthConnection(x11_dpy, ctx->x11_screen, magic))
goto err_out1;
if (drmMap(dri_state->fd, dri_state->hSAREA, SAREA_MAX, &dri_state->pSAREA))
goto err_out1;
if (!VA_DRICreateContext(ctx->native_dpy, ctx->x11_screen,
DefaultVisual(ctx->native_dpy, ctx->x11_screen),
if (!VA_DRICreateContext(x11_dpy, ctx->x11_screen,
DefaultVisual(x11_dpy, ctx->x11_screen),
&dri_state->hwContextID, &dri_state->hwContext))
goto err_out1;
......@@ -142,7 +145,7 @@ err_out1:
if (dri_state->fd >= 0)
drmCloseOnce(dri_state->fd);
VA_DRICloseConnection(ctx->native_dpy, ctx->x11_screen);
VA_DRICloseConnection(x11_dpy, ctx->x11_screen);
err_out0:
if (*driver_name)
......
......@@ -9,6 +9,7 @@
#include <X11/Xlib.h>
#include "va.h"
#include "va_backend.h"
#include "va_backend_x11.h"
#include "va_dri2.h"
#include "va_dri2tokens.h"
......@@ -40,6 +41,7 @@ static int gsDRI2SwapAvailable;
static struct dri_drawable *
dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri2_drawable *dri2_drawable;
dri2_drawable = calloc(1, sizeof(*dri2_drawable));
......@@ -50,7 +52,7 @@ dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
dri2_drawable->base.x_drawable = x_drawable;
dri2_drawable->base.x = 0;
dri2_drawable->base.y = 0;
VA_DRI2CreateDrawable(ctx->native_dpy, x_drawable);
VA_DRI2CreateDrawable(x11_dpy, x_drawable);
return &dri2_drawable->base;
}
......@@ -58,13 +60,16 @@ dri2CreateDrawable(VADriverContextP ctx, XID x_drawable)
static void
dri2DestroyDrawable(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
VA_DRI2DestroyDrawable(ctx->native_dpy, dri_drawable->x_drawable);
Display * const x11_dpy = va_x11_get_display(ctx);
VA_DRI2DestroyDrawable(x11_dpy, dri_drawable->x_drawable);
free(dri_drawable);
}
static void
dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
XRectangle xrect;
XserverRegion region;
......@@ -72,7 +77,7 @@ dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
if (dri2_drawable->has_backbuffer) {
if (gsDRI2SwapAvailable) {
CARD64 ret;
VA_DRI2SwapBuffers(ctx->native_dpy, dri_drawable->x_drawable, 0, 0,
VA_DRI2SwapBuffers(x11_dpy, dri_drawable->x_drawable, 0, 0,
0, &ret);
} else {
xrect.x = 0;
......@@ -80,10 +85,10 @@ dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
xrect.width = dri2_drawable->width;
xrect.height = dri2_drawable->height;
region = XFixesCreateRegion(ctx->native_dpy, &xrect, 1);
VA_DRI2CopyRegion(ctx->native_dpy, dri_drawable->x_drawable, region,
region = XFixesCreateRegion(x11_dpy, &xrect, 1);
VA_DRI2CopyRegion(x11_dpy, dri_drawable->x_drawable, region,
DRI2BufferFrontLeft, DRI2BufferBackLeft);
XFixesDestroyRegion(ctx->native_dpy, region);
XFixesDestroyRegion(x11_dpy, region);
}
}
}
......@@ -91,6 +96,7 @@ dri2SwapBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
static union dri_buffer *
dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri2_drawable *dri2_drawable = (struct dri2_drawable *)dri_drawable;
int i;
int count;
......@@ -103,7 +109,7 @@ dri2GetRenderingBuffer(VADriverContextP ctx, struct dri_drawable *dri_drawable)
else
attachments[i++] = __DRI_BUFFER_FRONT_LEFT;
buffers = VA_DRI2GetBuffers(ctx->native_dpy, dri_drawable->x_drawable,
buffers = VA_DRI2GetBuffers(x11_dpy, dri_drawable->x_drawable,
&dri2_drawable->width, &dri2_drawable->height,
attachments, i, &count);
assert(buffers);
......@@ -152,6 +158,7 @@ dri2Close(VADriverContextP ctx)
Bool
isDRI2Connected(VADriverContextP ctx, char **driver_name)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
int major, minor;
int error_base;
......@@ -161,14 +168,14 @@ isDRI2Connected(VADriverContextP ctx, char **driver_name)
*driver_name = NULL;
dri_state->fd = -1;
dri_state->driConnectedFlag = VA_NONE;
if (!VA_DRI2QueryExtension(ctx->native_dpy, &event_base, &error_base))
if (!VA_DRI2QueryExtension(x11_dpy, &event_base, &error_base))
goto err_out;
if (!VA_DRI2QueryVersion(ctx->native_dpy, &major, &minor))
if (!VA_DRI2QueryVersion(x11_dpy, &major, &minor))
goto err_out;
if (!VA_DRI2Connect(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
if (!VA_DRI2Connect(x11_dpy, RootWindow(x11_dpy, ctx->x11_screen),
driver_name, &device_name))
goto err_out;
......@@ -181,7 +188,7 @@ isDRI2Connected(VADriverContextP ctx, char **driver_name)
if (drmGetMagic(dri_state->fd, &magic))
goto err_out;
if (!VA_DRI2Authenticate(ctx->native_dpy, RootWindow(ctx->native_dpy, ctx->x11_screen),
if (!VA_DRI2Authenticate(x11_dpy, RootWindow(x11_dpy, ctx->x11_screen),
magic))
goto err_out;
......
/*
* Copyright (C) 2011 Intel Corporation. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef VA_BACKEND_X11_H
#define VA_BACKEND_X11_H
/**
* Return thread-local X11 display
*
* @param[in] ctx the VA driver context
* @return X11 Display if successful, or NULL if none was found
*/
Display *
va_x11_get_display(VADriverContextP ctx);
#endif /* VA_BACKEND_X11_H */
#include "va_dricommon.h"
#include "va_backend_x11.h"
// X error trap
static int x11_error_code = 0;
......@@ -38,6 +39,7 @@ is_window(Display *dpy, Drawable drawable)
static struct dri_drawable *
do_drawable_hash(VADriverContextP ctx, XID drawable)
{
Display * const x11_dpy = va_x11_get_display(ctx);
struct dri_state *dri_state = (struct dri_state *)ctx->dri_state;
int index = drawable % DRAWABLE_HASH_SZ;
struct dri_drawable *dri_drawable = dri_state->drawable_hash[index];
......@@ -50,7 +52,7 @@ do_drawable_hash(VADriverContextP ctx, XID drawable)
dri_drawable = dri_state->createDrawable(ctx, drawable);
dri_drawable->x_drawable = drawable;
dri_drawable->is_window = is_window(ctx->native_dpy, drawable);
dri_drawable->is_window = is_window(x11_dpy, drawable);
dri_drawable->next = dri_state->drawable_hash[index];
dri_state->drawable_hash[index] = dri_drawable;
......
......@@ -26,6 +26,7 @@
#include "sysdeps.h"
#include "va.h"
#include "va_backend.h"
#include "va_backend_x11.h"
#include "va_trace.h"
#include "va_fool.h"
#include "va_x11.h"
......@@ -39,11 +40,124 @@
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
typedef struct {
pthread_key_t tls_key;
} ThreadLocalState;
typedef struct {
Display *dpy;
} ThreadLocalStateX11;
#define USE_TLS_DATA_AS_KEY \
(sizeof(pthread_key_t) <= sizeof(((VADriverContextP)0)->tls_state))
static void
destroy_tls_state_x11(void *arg)
{
ThreadLocalStateX11 * const state = arg;
if (!state)
return;
if (state->dpy) {
XCloseDisplay(state->dpy);
state->dpy = NULL;
}
free(state);
}
ThreadLocalStateX11 *
create_tls_state_x11(Display *dpy)
{
ThreadLocalStateX11 *tls_state;
tls_state = calloc(1, sizeof(*tls_state));
if (!tls_state)
return NULL;
tls_state->dpy = XOpenDisplay(DisplayString(dpy));
if (!tls_state->dpy)
goto error;
return tls_state;
error:
destroy_tls_state_x11(tls_state);
return NULL;
}
static void
destroy_tls_state(void **tls_state_ptr)
{
ThreadLocalState *tls_state = *tls_state_ptr;
ThreadLocalStateX11 *tls_state_x11;
pthread_key_t tls_key;
tls_key = USE_TLS_DATA_AS_KEY ? (uintptr_t)tls_state : tls_state->tls_key;
/* XXX: it seems the destructor is not implicitly called */
tls_state_x11 = pthread_getspecific(tls_key);
if (tls_state_x11) {
destroy_tls_state_x11(tls_state_x11);
pthread_setspecific(tls_key, NULL);
}
pthread_key_delete(tls_key);
if (!USE_TLS_DATA_AS_KEY)
free(tls_state);
*tls_state_ptr = NULL;
}
static Bool
create_tls_state(void **tls_state_ptr, Display *dpy)
{
ThreadLocalState *tls_state = NULL;
pthread_key_t tls_key;
if (pthread_key_create(&tls_key, destroy_tls_state_x11) != 0)
return False;
if (USE_TLS_DATA_AS_KEY)
tls_state = (void *)(uintptr_t)tls_key;
else {
tls_state = malloc(sizeof(*tls_state));
if (!tls_state)
goto error;
tls_state->tls_key = tls_key;
}
*tls_state_ptr = tls_state;
return True;
error:
destroy_tls_state((void **)&tls_state);
*tls_state_ptr = NULL;
return False;
}
Display *
va_x11_get_display(VADriverContextP ctx)
{
ThreadLocalState * const tls_state = ctx->tls_state;
ThreadLocalStateX11 *tls_state_x11;
pthread_key_t tls_key;
tls_key = USE_TLS_DATA_AS_KEY ? (uintptr_t)tls_state : tls_state->tls_key;
tls_state_x11 = pthread_getspecific(tls_key);
if (!tls_state_x11) {
tls_state_x11 = create_tls_state_x11(ctx->native_dpy);
if (!tls_state_x11)
return NULL;
pthread_setspecific(tls_key, tls_state_x11);
}
return tls_state_x11->dpy;
}
static int va_DisplayContextIsValid (
VADisplayContextP pDisplayContext
)
......@@ -68,6 +182,7 @@ static void va_DisplayContextDestroy (
if (dri_state && dri_state->close)
dri_state->close(ctx);
destroy_tls_state(&pDisplayContext->pDriverContext->tls_state);
free(pDisplayContext->pDriverContext->dri_state);
free(pDisplayContext->pDriverContext);
free(pDisplayContext);
......@@ -106,15 +221,16 @@ static VAStatus va_NVCTRL_GetDriverName (
)
{
VADriverContextP ctx = pDisplayContext->pDriverContext;
Display * const x11_dpy = va_x11_get_display(ctx);
int direct_capable, driver_major, driver_minor, driver_patch;
Bool result;
result = VA_NVCTRLQueryDirectRenderingCapable(ctx->native_dpy, ctx->x11_screen,
result = VA_NVCTRLQueryDirectRenderingCapable(x11_dpy, ctx->x11_screen,
&direct_capable);
if (!result || !direct_capable)
return VA_STATUS_ERROR_UNKNOWN;
result = VA_NVCTRLGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
result = VA_NVCTRLGetClientDriverName(x11_dpy, ctx->x11_screen,
&driver_major, &driver_minor,
&driver_patch, driver_name);
if (!result)
......@@ -129,10 +245,11 @@ static VAStatus va_FGLRX_GetDriverName (
)
{
VADriverContextP ctx = pDisplayContext->pDriverContext;
Display * const x11_dpy = va_x11_get_display(ctx);
int driver_major, driver_minor, driver_patch;
Bool result;
result = VA_FGLRXGetClientDriverName(ctx->native_dpy, ctx->x11_screen,
result = VA_FGLRXGetClientDriverName(x11_dpy, ctx->x11_screen,
&driver_major, &driver_minor,
&driver_patch, driver_name);
if (!result)
......@@ -177,20 +294,24 @@ VADisplay vaGetDisplay (
/* create new entry */
VADriverContextP pDriverContext;
struct dri_state *dri_state;
void *tls_state;
Bool tls_state_ok;
pDisplayContext = calloc(1, sizeof(*pDisplayContext));
pDriverContext = calloc(1, sizeof(*pDriverContext));
dri_state = calloc(1, sizeof(*dri_state));
if (pDisplayContext && pDriverContext && dri_state)
tls_state_ok = create_tls_state(&tls_state, native_dpy);
if (pDisplayContext && pDriverContext && dri_state && tls_state_ok)
{
pDisplayContext->vadpy_magic = VA_DISPLAY_MAGIC;
pDriverContext->native_dpy = (void *)native_dpy;
pDriverContext->native_dpy = native_dpy;
pDisplayContext->pDriverContext = pDriverContext;
pDisplayContext->vaIsValid = va_DisplayContextIsValid;
pDisplayContext->vaDestroy = va_DisplayContextDestroy;
pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName;
pDisplayContext->opaque = NULL;
pDriverContext->dri_state = dri_state;
pDriverContext->tls_state = tls_state;
dpy = (VADisplay)pDisplayContext;
}
else
......@@ -201,6 +322,8 @@ VADisplay vaGetDisplay (
free(pDriverContext);
if (dri_state)
free(dri_state);
if (tls_state_ok)
destroy_tls_state(&tls_state);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment