mirror the visuals of the host X at startup.

* hw/kdrive/ephyr/ephyr.c: make Xephyr mirror
	  the visuals of the host X upon startup. This
	  is important for GLX client apps.
	* hw/kdrive/ephyr/hostx.c,h: add a hostx_get_visuals_info()
	  to get the visuals of the host X.
This commit is contained in:
Dodji Seketeli 2007-08-28 15:58:55 +02:00 committed by Dodji Seketeli
parent 26da625055
commit 1dd589410c
3 changed files with 231 additions and 1 deletions

View File

@ -54,6 +54,7 @@ Bool EphyrWantGrayScale = 0;
#ifdef XEPHYR_DRI
extern void ephyrDRIExtensionInit(void) ;
static Bool EphyrMirrorHostVisuals (void) ;
#endif
Bool
@ -630,6 +631,7 @@ ephyrInitScreen (ScreenPtr pScreen)
ephyrDRIExtensionInit () ;
ephyrHijackGLXExtension () ;
ephyrProxyExtensionInit ("ATIFGLRXDRI") ;
EphyrMirrorHostVisuals () ;
#endif
return TRUE;
}
@ -1046,6 +1048,168 @@ EphyrKeyboardBell (KdKeyboardInfo *ki, int volume, int frequency, int duration)
{
}
/**
* Duplicates a visual of a_screen
* In screen a_screen, for depth a_depth, find a visual which
* bitsPerRGBValue and colormap size equal
* a_bits_per_rgb_values and a_colormap_entries.
* The ID of that duplicated visual is set to a_new_id.
* That duplicated visual is then added to the list of visuals
* of the screen.
*/
static Bool
EphyrDuplicateVisual (unsigned int a_screen,
short a_depth,
short a_class,
short a_bits_per_rgb_values,
short a_colormap_entries,
unsigned int a_red_mask,
unsigned int a_green_mask,
unsigned int a_blue_mask,
unsigned int a_new_id)
{
Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ;
ScreenPtr screen=NULL ;
VisualRec new_visual, *new_visuals=NULL ;
int i=0 ;
EPHYR_LOG ("enter\n") ;
if (a_screen > screenInfo.numScreens) {
EPHYR_LOG_ERROR ("bad screen number\n") ;
goto out;
}
memset (&new_visual, 0, sizeof (VisualRec)) ;
/*get the screen pointed to by a_screen*/
screen = screenInfo.screens[a_screen] ;
EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
/*
* In that screen, first look for an existing visual that has the
* same characteristics as those passed in parameter
* to this function and copy it.
*/
for (i=0; i < screen->numVisuals; i++) {
if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values &&
screen->visuals[i].ColormapEntries == a_colormap_entries ) {
/*copy the visual found*/
memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ;
new_visual.vid = a_new_id ;
found_visual = TRUE ;
EPHYR_LOG ("found a visual that matches visual id: %d\n",
a_new_id) ;
break;
}
}
if (!found_visual) {
EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ;
goto out ;
}
/*
* be prepare to extend screen->visuals to add new_visual to it
*/
new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ;
memmove (new_visuals,
screen->visuals,
screen->numVisuals*sizeof (VisualRec)) ;
memmove (&new_visuals[screen->numVisuals],
&new_visual,
sizeof (VisualRec)) ;
/*
* Now, in that same screen, update the screen->allowedDepths member.
* In that array, each element represents the visuals applicable to
* a given depth. So we need to add an entry matching the new visual
* that we are going to add to screen->visuals
*/
for (i=0; i<screen->numDepths; i++) {
VisualID *vids=NULL;
DepthPtr cur_depth=NULL ;
/*find the entry matching a_depth*/
if (screen->allowedDepths[i].depth != a_depth)
continue ;
cur_depth = &screen->allowedDepths[i];
/*
* extend the list of visual IDs in that entry,
* so to add a_new_id in there.
*/
vids = xrealloc (cur_depth->vids,
(cur_depth->numVids+1)*sizeof (VisualID));
if (!vids) {
EPHYR_LOG_ERROR ("failed to realloc numids\n") ;
goto out ;
}
vids[cur_depth->numVids] = a_new_id ;
/*
* Okay now commit our change.
* Do really update screen->allowedDepths[i]
*/
cur_depth->numVids++ ;
cur_depth->vids = vids ;
found_depth=TRUE;
}
if (!found_depth) {
EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n",
a_screen) ;
goto out ;
}
/*
* Commit our change to screen->visuals
*/
xfree (screen->visuals) ;
screen->visuals = new_visuals ;
screen->numVisuals++ ;
new_visuals = NULL ;
is_ok = TRUE ;
out:
if (new_visuals) {
xfree (new_visuals) ;
new_visuals = NULL ;
}
EPHYR_LOG ("leave\n") ;
return is_ok ;
}
/**
* Duplicates the visuals of the host X server.
* This is necessary to have visuals that have the same
* ID as those of the host X. It is important to have that for
* GLX.
*/
static Bool
EphyrMirrorHostVisuals (void)
{
Bool is_ok=FALSE;
EphyrHostVisualInfo *visuals=NULL;
int nb_visuals=0, i=0;
EPHYR_LOG ("enter\n") ;
if (!hostx_get_visuals_info (&visuals, &nb_visuals)) {
EPHYR_LOG_ERROR ("failed to get host visuals\n") ;
goto out ;
}
for (i=0; i<nb_visuals; i++) {
if (!EphyrDuplicateVisual (visuals[i].screen,
visuals[i].depth,
visuals[i].class,
visuals[i].bits_per_rgb,
visuals[i].colormap_size,
visuals[i].red_mask,
visuals[i].blue_mask,
visuals[i].green_mask,
visuals[i].visualid)) {
EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n",
(int)visuals[i].visualid) ;
}
}
is_ok = TRUE ;
out:
EPHYR_LOG ("leave\n") ;
return is_ok;
}
KdKeyboardDriver EphyrKeyboardDriver = {
"ephyr",
EphyrKeyboardInit,

View File

@ -40,6 +40,7 @@
#include <X11/Xatom.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#include "ephyrlog.h"
/*
* All xlib calls go here, which gets built as its own .a .
@ -987,3 +988,54 @@ hostx_get_extension_info (const char *a_ext_name,
return 1 ;
}
int
hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals,
int *a_num_entries)
{
Display *dpy=hostx_get_display () ;
Bool is_ok=False ;
XVisualInfo templ, *visuals=NULL;
EphyrHostVisualInfo *host_visuals=NULL ;
int nb_items=0, i=0;
EPHYR_RETURN_VAL_IF_FAIL (a_visuals && a_num_entries && dpy,
False) ;
EPHYR_LOG ("enter\n") ;
memset (&templ, 0, sizeof (templ)) ;
visuals = XGetVisualInfo (dpy, VisualNoMask, &templ, &nb_items) ;
if (!visuals) {
EPHYR_LOG_ERROR ("host does not advertise any visual\n") ;
goto out ;
}
EPHYR_LOG ("host advertises %d visuals\n", nb_items) ;
host_visuals = calloc (nb_items, sizeof (EphyrHostVisualInfo)) ;
for (i=0; i<nb_items; i++) {
host_visuals[i].visualid = visuals[i].visualid ;
host_visuals[i].screen = visuals[i].screen ;
host_visuals[i].depth = visuals[i].depth ;
host_visuals[i].class = visuals[i].class ;
host_visuals[i].red_mask = visuals[i].red_mask ;
host_visuals[i].green_mask = visuals[i].green_mask ;
host_visuals[i].blue_mask = visuals[i].blue_mask ;
host_visuals[i].colormap_size = visuals[i].colormap_size ;
host_visuals[i].bits_per_rgb = visuals[i].bits_per_rgb ;
}
*a_visuals = host_visuals ;
*a_num_entries = nb_items;
host_visuals=NULL;
is_ok = TRUE;
out:
if (visuals) {
XFree (visuals) ;
visuals = NULL;
}
if (host_visuals) {
free (host_visuals) ;
host_visuals = NULL;
}
EPHYR_LOG ("leave\n") ;
return is_ok ;
}

View File

@ -92,6 +92,18 @@ struct EphyrHostXEvent
int key_state;
};
typedef struct {
VisualID visualid;
int screen;
int depth;
int class;
unsigned long red_mask;
unsigned long green_mask;
unsigned long blue_mask;
int colormap_size;
int bits_per_rgb;
} EphyrHostVisualInfo;
int
hostx_want_screen_size(EphyrScreenInfo screen, int *width, int *height);
@ -183,5 +195,7 @@ hostx_get_extension_info (const char *a_ext_name,
int *a_major_opcode,
int *a_first_even,
int *a_first_error) ;
int
hostx_get_visuals_info (EphyrHostVisualInfo **a_visuals,
int *a_num_entries) ;
#endif