mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 15:58:05 +02:00
winsys/xlib: remove dependency on glx/x11 state tracker
Introduce xlib_drawable struct, pass this down to winsys instead of having it use the internal data structures from glx/x11
This commit is contained in:
parent
7f9a3959b0
commit
1675d05f91
8 changed files with 103 additions and 133 deletions
25
src/gallium/include/state_tracker/xlib_sw_winsys.h
Normal file
25
src/gallium/include/state_tracker/xlib_sw_winsys.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef XLIB_SW_WINSYS_H
|
||||
#define XLIB_SW_WINSYS_H
|
||||
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct sw_winsys *xlib_create_sw_winsys( Display *display );
|
||||
|
||||
/* This is what the xlib software winsys expects to find in the
|
||||
* "private" field of flush_frontbuffers(). Xlib-based state trackers
|
||||
* somehow need to know this.
|
||||
*/
|
||||
struct xlib_drawable {
|
||||
Visual *visual;
|
||||
int depth;
|
||||
Drawable drawable;
|
||||
GC gc; /* temporary? */
|
||||
};
|
||||
|
||||
void
|
||||
xlib_sw_display(struct xlib_drawable *xm_buffer,
|
||||
struct sw_displaytarget *dt);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -689,7 +689,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
|
|||
int desiredVisualID = -1;
|
||||
int numAux = 0;
|
||||
|
||||
xmesa_init();
|
||||
xmesa_init( dpy );
|
||||
|
||||
parselist = list;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@
|
|||
* corner of the window. Therefore, most drawing functions in this
|
||||
* file have to flip Y coordinates.
|
||||
*
|
||||
* Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
|
||||
* in support for the MIT Shared Memory extension. If enabled, when you
|
||||
* use an Ximage for the back buffer in double buffered mode, the "swap"
|
||||
* operation will be faster. You must also link with -lXext.
|
||||
*
|
||||
* Byte swapping: If the Mesa host and the X display use a different
|
||||
* byte order then there's some trickiness to be aware of when using
|
||||
|
|
@ -111,41 +107,6 @@ static int host_byte_order( void )
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the X Shared Memory extension is available.
|
||||
* Return: 0 = not available
|
||||
* 1 = shared XImage support available
|
||||
* 2 = shared Pixmap support available also
|
||||
*/
|
||||
int xmesa_check_for_xshm( Display *display )
|
||||
{
|
||||
#if defined(USE_XSHM)
|
||||
int major, minor, ignore;
|
||||
Bool pixmaps;
|
||||
|
||||
if (getenv("SP_NO_RAST"))
|
||||
return 0;
|
||||
|
||||
if (getenv("MESA_NOSHM")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
|
||||
if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
|
||||
return (pixmaps==True) ? 2 : 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* No XSHM support */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -242,7 +203,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b,
|
|||
|
||||
pipe_mutex_lock(_xmesa_lock);
|
||||
XSync(b->xm_visual->display, 0); /* added for Chromium */
|
||||
stat = get_drawable_size(dpy, b->drawable, width, height);
|
||||
stat = get_drawable_size(dpy, b->ws.drawable, width, height);
|
||||
pipe_mutex_unlock(_xmesa_lock);
|
||||
|
||||
if (!stat) {
|
||||
|
|
@ -397,7 +358,9 @@ create_xmesa_buffer(Drawable d, BufferType type,
|
|||
if (!b)
|
||||
return NULL;
|
||||
|
||||
b->drawable = d;
|
||||
b->ws.drawable = d;
|
||||
b->ws.visual = vis->visinfo->visual;
|
||||
b->ws.depth = vis->visinfo->depth;
|
||||
|
||||
b->xm_visual = vis;
|
||||
b->type = type;
|
||||
|
|
@ -422,18 +385,6 @@ create_xmesa_buffer(Drawable d, BufferType type,
|
|||
(void *) b);
|
||||
fb = &b->stfb->Base;
|
||||
|
||||
/*
|
||||
* Create scratch XImage for xmesa_display_surface()
|
||||
*/
|
||||
b->tempImage = XCreateImage(vis->display,
|
||||
vis->visinfo->visual,
|
||||
vis->visinfo->depth,
|
||||
ZPixmap, 0, /* format, offset */
|
||||
NULL, /* data */
|
||||
0, 0, /* size */
|
||||
32, /* bitmap_pad */
|
||||
0); /* bytes_per_line */
|
||||
|
||||
/* GLX_EXT_texture_from_pixmap */
|
||||
b->TextureTarget = 0;
|
||||
b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
|
||||
|
|
@ -490,15 +441,12 @@ xmesa_free_buffer(XMesaBuffer buffer)
|
|||
/* Since the X window for the XMesaBuffer is going away, we don't
|
||||
* want to dereference this pointer in the future.
|
||||
*/
|
||||
b->drawable = 0;
|
||||
|
||||
buffer->tempImage->data = NULL;
|
||||
XDestroyImage(buffer->tempImage);
|
||||
b->ws.drawable = 0;
|
||||
|
||||
/* Unreference. If count = zero we'll really delete the buffer */
|
||||
_mesa_reference_framebuffer(&fb, NULL);
|
||||
|
||||
XFreeGC(b->xm_visual->display, b->gc);
|
||||
XFreeGC(b->xm_visual->display, b->ws.gc);
|
||||
|
||||
free(buffer);
|
||||
|
||||
|
|
@ -578,17 +526,12 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
|
|||
|
||||
if (b && window) {
|
||||
/* these should have been set in create_xmesa_buffer */
|
||||
ASSERT(b->drawable == window);
|
||||
ASSERT(b->ws.drawable == window);
|
||||
|
||||
/* Setup for single/double buffering */
|
||||
if (v->mesa_visual.doubleBufferMode) {
|
||||
/* Double buffered */
|
||||
b->shm = xmesa_check_for_xshm( v->display );
|
||||
}
|
||||
|
||||
/* X11 graphics context */
|
||||
b->gc = XCreateGC( v->display, window, 0, NULL );
|
||||
XSetFunction( v->display, b->gc, GXcopy );
|
||||
b->ws.gc = XCreateGC( v->display, window, 0, NULL );
|
||||
XSetFunction( v->display, b->ws.gc, GXcopy );
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
|
|
@ -673,7 +616,7 @@ XMesaVisual XMesaCreateVisual( Display *display,
|
|||
XMesaVisual v;
|
||||
GLint red_bits, green_bits, blue_bits, alpha_bits;
|
||||
|
||||
xmesa_init();
|
||||
xmesa_init( display );
|
||||
|
||||
/* For debugging only */
|
||||
if (_mesa_getenv("MESA_XSYNC")) {
|
||||
|
|
@ -773,12 +716,12 @@ void XMesaDestroyVisual( XMesaVisual v )
|
|||
* Do one-time initializations.
|
||||
*/
|
||||
void
|
||||
xmesa_init(void)
|
||||
xmesa_init( Display *display )
|
||||
{
|
||||
static GLboolean firstTime = GL_TRUE;
|
||||
if (firstTime) {
|
||||
pipe_mutex_init(_xmesa_lock);
|
||||
_screen = driver.create_pipe_screen();
|
||||
_screen = driver.create_pipe_screen( display );
|
||||
screen = trace_screen_create( _screen );
|
||||
firstTime = GL_FALSE;
|
||||
}
|
||||
|
|
@ -800,7 +743,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
|
|||
GLcontext *mesaCtx;
|
||||
uint pf;
|
||||
|
||||
xmesa_init();
|
||||
xmesa_init( v->display );
|
||||
|
||||
/* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
|
||||
c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
|
||||
|
|
@ -1155,7 +1098,7 @@ void XMesaSwapBuffers( XMesaBuffer b )
|
|||
frontLeftSurf = surf;
|
||||
}
|
||||
|
||||
driver.display_surface(b, frontLeftSurf);
|
||||
driver.display_surface(&b->ws, frontLeftSurf);
|
||||
}
|
||||
|
||||
xmesa_check_and_update_buffer_size(NULL, b);
|
||||
|
|
@ -1203,7 +1146,7 @@ XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
|
|||
{
|
||||
XMesaBuffer b;
|
||||
for (b = XMesaBufferList; b; b = b->Next) {
|
||||
if (b->drawable == d && b->xm_visual->display == dpy) {
|
||||
if (b->ws.drawable == d && b->xm_visual->display == dpy) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
|
@ -1237,10 +1180,10 @@ void XMesaGarbageCollect( void )
|
|||
next = b->Next;
|
||||
if (b->xm_visual &&
|
||||
b->xm_visual->display &&
|
||||
b->drawable &&
|
||||
b->ws.drawable &&
|
||||
b->type == WINDOW) {
|
||||
XSync(b->xm_visual->display, False);
|
||||
if (!window_exists( b->xm_visual->display, b->drawable )) {
|
||||
if (!window_exists( b->xm_visual->display, b->ws.drawable )) {
|
||||
/* found a dead window, free the ancillary info */
|
||||
XMesaDestroyBuffer( b );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,15 +62,11 @@ and create a window, you must do the following to use the X/Mesa interface:
|
|||
#include "state_tracker/st_public.h"
|
||||
#include "os/os_thread.h"
|
||||
|
||||
#include "state_tracker/xlib_sw_winsys.h"
|
||||
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/Xlibint.h>
|
||||
# include <X11/Xutil.h>
|
||||
# ifdef USE_XSHM /* was SHM */
|
||||
# include <sys/ipc.h>
|
||||
# include <sys/shm.h>
|
||||
# include <X11/extensions/XShm.h>
|
||||
# endif
|
||||
|
||||
typedef struct xmesa_buffer *XMesaBuffer;
|
||||
typedef struct xmesa_context *XMesaContext;
|
||||
|
|
@ -316,6 +312,7 @@ typedef enum {
|
|||
*/
|
||||
struct xmesa_buffer {
|
||||
struct st_framebuffer *stfb;
|
||||
struct xlib_drawable ws;
|
||||
|
||||
GLboolean wasCurrent; /* was ever the current buffer? */
|
||||
XMesaVisual xm_visual; /* the X/Mesa visual */
|
||||
|
|
@ -329,13 +326,6 @@ struct xmesa_buffer {
|
|||
XImage *tempImage;
|
||||
unsigned long selectedEvents;/* for pbuffers only */
|
||||
|
||||
GLuint shm; /* X Shared Memory extension status: */
|
||||
/* 0 = not available */
|
||||
/* 1 = XImage support available */
|
||||
/* 2 = Pixmap support available too */
|
||||
#if defined(USE_XSHM)
|
||||
XShmSegmentInfo shminfo;
|
||||
#endif
|
||||
|
||||
GC gc; /* scratch GC for span, line, tri drawing */
|
||||
|
||||
|
|
@ -367,7 +357,7 @@ xmesa_buffer(GLframebuffer *fb)
|
|||
|
||||
|
||||
extern void
|
||||
xmesa_init(void);
|
||||
xmesa_init(Display *dpy);
|
||||
|
||||
extern void
|
||||
xmesa_delete_framebuffer(struct gl_framebuffer *fb);
|
||||
|
|
@ -397,8 +387,6 @@ xmesa_buffer_height(XMesaBuffer b)
|
|||
return b->stfb->Base.Height;
|
||||
}
|
||||
|
||||
extern int
|
||||
xmesa_check_for_xshm(Display *display);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,14 +32,15 @@
|
|||
struct pipe_context;
|
||||
struct pipe_screen;
|
||||
struct pipe_surface;
|
||||
struct xmesa_buffer;
|
||||
struct xlib_drawable;
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
struct xm_driver {
|
||||
|
||||
struct pipe_screen *(*create_pipe_screen)( void );
|
||||
struct pipe_screen *(*create_pipe_screen)( Display *display );
|
||||
|
||||
void (*display_surface)( struct xmesa_buffer *,
|
||||
void (*display_surface)( struct xlib_drawable *,
|
||||
struct pipe_surface * );
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,16 +42,16 @@
|
|||
|
||||
#include "llvmpipe/lp_texture.h"
|
||||
#include "llvmpipe/lp_screen.h"
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
#include "state_tracker/xlib_sw_winsys.h"
|
||||
#include "util/u_debug.h"
|
||||
|
||||
static struct pipe_screen *
|
||||
xlib_create_llvmpipe_screen( void )
|
||||
xlib_create_llvmpipe_screen( Display *display )
|
||||
{
|
||||
struct sw_winsys *winsys;
|
||||
struct pipe_screen *screen;
|
||||
|
||||
winsys = xlib_create_sw_winsys();
|
||||
winsys = xlib_create_sw_winsys( display );
|
||||
if (winsys == NULL)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ fail:
|
|||
|
||||
|
||||
static void
|
||||
xlib_llvmpipe_display_surface(struct xmesa_buffer *xm_buffer,
|
||||
xlib_llvmpipe_display_surface(struct xlib_drawable *xm_buffer,
|
||||
struct pipe_surface *surf)
|
||||
{
|
||||
struct llvmpipe_texture *texture = llvmpipe_texture(surf->texture);
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@
|
|||
#include "util/u_debug.h"
|
||||
|
||||
static struct pipe_screen *
|
||||
xlib_create_softpipe_screen( void )
|
||||
xlib_create_softpipe_screen( Display *display )
|
||||
{
|
||||
struct sw_winsys *winsys;
|
||||
struct pipe_screen *screen;
|
||||
|
||||
winsys = xlib_create_sw_winsys();
|
||||
winsys = xlib_create_sw_winsys( display );
|
||||
if (winsys == NULL)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,17 @@
|
|||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#include "state_tracker/sw_winsys.h"
|
||||
#include "state_tracker/xlib_sw_winsys.h"
|
||||
|
||||
#include "xlib.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlibint.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
/**
|
||||
* Subclass of pipe_buffer for Xlib winsys.
|
||||
* Low-level OS/window system memory buffer
|
||||
|
|
@ -64,21 +71,25 @@ struct xm_displaytarget
|
|||
void *data;
|
||||
void *mapped;
|
||||
|
||||
Display *display;
|
||||
Visual *visual;
|
||||
XImage *tempImage;
|
||||
#ifdef USE_XSHM
|
||||
int shm;
|
||||
|
||||
XShmSegmentInfo shminfo;
|
||||
#endif
|
||||
int shm;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subclass of sw_winsys for Xlib winsys
|
||||
*/
|
||||
struct xmesa_sw_winsys
|
||||
struct xlib_sw_winsys
|
||||
{
|
||||
struct sw_winsys base;
|
||||
/* struct xmesa_visual *xm_visual; */
|
||||
|
||||
|
||||
|
||||
Display *display;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -136,8 +147,8 @@ static char *alloc_shm(struct xm_displaytarget *buf, unsigned size)
|
|||
* Allocate a shared memory XImage back buffer for the given XMesaBuffer.
|
||||
*/
|
||||
static void
|
||||
alloc_shm_ximage(struct xm_displaytarget *xm_buffer,
|
||||
struct xmesa_buffer *xmb,
|
||||
alloc_shm_ximage(struct xm_displaytarget *xm_dt,
|
||||
struct xlib_drawable *xmb,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
/*
|
||||
|
|
@ -148,15 +159,15 @@ alloc_shm_ximage(struct xm_displaytarget *xm_buffer,
|
|||
*/
|
||||
int (*old_handler)(Display *, XErrorEvent *);
|
||||
|
||||
xm_buffer->tempImage = XShmCreateImage(xmb->xm_visual->display,
|
||||
xmb->xm_visual->visinfo->visual,
|
||||
xmb->xm_visual->visinfo->depth,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&xm_buffer->shminfo,
|
||||
width, height);
|
||||
if (xm_buffer->tempImage == NULL) {
|
||||
xm_buffer->shm = 0;
|
||||
xm_dt->tempImage = XShmCreateImage(xm_dt->display,
|
||||
xmb->visual,
|
||||
xmb->depth,
|
||||
ZPixmap,
|
||||
NULL,
|
||||
&xm_dt->shminfo,
|
||||
width, height);
|
||||
if (xm_dt->tempImage == NULL) {
|
||||
xm_dt->shm = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -164,21 +175,21 @@ alloc_shm_ximage(struct xm_displaytarget *xm_buffer,
|
|||
mesaXErrorFlag = 0;
|
||||
old_handler = XSetErrorHandler(mesaHandleXError);
|
||||
/* This may trigger the X protocol error we're ready to catch: */
|
||||
XShmAttach(xmb->xm_visual->display, &xm_buffer->shminfo);
|
||||
XSync(xmb->xm_visual->display, False);
|
||||
XShmAttach(xm_dt->display, &xm_dt->shminfo);
|
||||
XSync(xm_dt->display, False);
|
||||
|
||||
if (mesaXErrorFlag) {
|
||||
/* we are on a remote display, this error is normal, don't print it */
|
||||
XFlush(xmb->xm_visual->display);
|
||||
XFlush(xm_dt->display);
|
||||
mesaXErrorFlag = 0;
|
||||
XDestroyImage(xm_buffer->tempImage);
|
||||
xm_buffer->tempImage = NULL;
|
||||
xm_buffer->shm = 0;
|
||||
XDestroyImage(xm_dt->tempImage);
|
||||
xm_dt->tempImage = NULL;
|
||||
xm_dt->shm = 0;
|
||||
(void) XSetErrorHandler(old_handler);
|
||||
return;
|
||||
}
|
||||
|
||||
xm_buffer->shm = 1;
|
||||
xm_dt->shm = 1;
|
||||
}
|
||||
|
||||
#endif /* USE_XSHM */
|
||||
|
|
@ -239,7 +250,7 @@ xm_displaytarget_destroy(struct sw_winsys *ws,
|
|||
* by the XMesaBuffer.
|
||||
*/
|
||||
void
|
||||
xlib_sw_display(struct xmesa_buffer *xm_buffer,
|
||||
xlib_sw_display(struct xlib_drawable *xlib_drawable,
|
||||
struct sw_displaytarget *dt)
|
||||
{
|
||||
XImage *ximage;
|
||||
|
|
@ -262,7 +273,8 @@ xlib_sw_display(struct xmesa_buffer *xm_buffer,
|
|||
{
|
||||
assert(util_format_get_blockwidth(xm_dt->format) == 1);
|
||||
assert(util_format_get_blockheight(xm_dt->format) == 1);
|
||||
alloc_shm_ximage(xm_dt, xm_buffer,
|
||||
alloc_shm_ximage(xm_dt,
|
||||
xlib_drawable,
|
||||
xm_dt->stride / util_format_get_blocksize(xm_dt->format),
|
||||
xm_dt->height);
|
||||
}
|
||||
|
|
@ -271,7 +283,7 @@ xlib_sw_display(struct xmesa_buffer *xm_buffer,
|
|||
ximage->data = xm_dt->data;
|
||||
|
||||
/* _debug_printf("XSHM\n"); */
|
||||
XShmPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc,
|
||||
XShmPutImage(xm_dt->display, xlib_drawable->drawable, xlib_drawable->gc,
|
||||
ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height, False);
|
||||
}
|
||||
else
|
||||
|
|
@ -291,7 +303,7 @@ xlib_sw_display(struct xmesa_buffer *xm_buffer,
|
|||
ximage->bytes_per_line = xm_dt->stride;
|
||||
|
||||
/* _debug_printf("XPUT\n"); */
|
||||
XPutImage(xm_buffer->xm_visual->display, xm_buffer->drawable, xm_buffer->gc,
|
||||
XPutImage(xm_dt->display, xlib_drawable->drawable, xlib_drawable->gc,
|
||||
ximage, 0, 0, 0, 0, xm_dt->width, xm_dt->height);
|
||||
}
|
||||
}
|
||||
|
|
@ -305,9 +317,8 @@ xm_displaytarget_display(struct sw_winsys *ws,
|
|||
struct sw_displaytarget *dt,
|
||||
void *context_private)
|
||||
{
|
||||
XMesaContext xmctx = (XMesaContext) context_private;
|
||||
struct xmesa_buffer *xm_buffer = xmctx->xm_buffer;
|
||||
xm_sw_display(xm_buffer, dt);
|
||||
struct xlib_drawable *xlib_drawable = (struct xlib_drawable *)context_private;
|
||||
xlib_sw_display(xlib_drawable, dt);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -325,6 +336,7 @@ xm_displaytarget_create(struct sw_winsys *winsys,
|
|||
if(!xm_dt)
|
||||
goto no_xm_dt;
|
||||
|
||||
xm_dt->display = ((struct xlib_sw_winsys *)winsys)->display;
|
||||
xm_dt->format = format;
|
||||
xm_dt->width = width;
|
||||
xm_dt->height = height;
|
||||
|
|
@ -370,14 +382,15 @@ xm_destroy( struct sw_winsys *ws )
|
|||
|
||||
|
||||
struct sw_winsys *
|
||||
xlib_create_sw_winsys( void )
|
||||
xlib_create_sw_winsys( Display *display )
|
||||
{
|
||||
struct xmesa_sw_winsys *ws;
|
||||
struct xlib_sw_winsys *ws;
|
||||
|
||||
ws = CALLOC_STRUCT(xmesa_sw_winsys);
|
||||
ws = CALLOC_STRUCT(xlib_sw_winsys);
|
||||
if (!ws)
|
||||
return NULL;
|
||||
|
||||
ws->display = display;
|
||||
ws->base.destroy = xm_destroy;
|
||||
|
||||
ws->base.is_displaytarget_format_supported = xm_is_displaytarget_format_supported;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue