Re: [AD] thoughts on a release

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Wed January 20 2010, Peter Wang wrote:
> On 2010-01-19, Thomas Fjellstrom <tfjellstrom@xxxxxxxxxx> wrote:
> > On Tue January 19 2010, Thomas Fjellstrom wrote:
> > > On Tue January 19 2010, Peter Wang wrote:
> > > > On 2010-01-19, Thomas Fjellstrom <tfjellstrom@xxxxxxxxxx> wrote:
> > > > > > Another thing that's arguably as important as those, is a
> > > > > > "capabilities" framework, so people can query what they can,
> > > > > > and can't do on a given computer.
> > > >
> > > > Was there a proposal somewhere?  What kind of capabilities did you
> > > > have in mind?
> > >
> > > I think there might have been a proper proposal, but at any rate its
> > > been mentioned on IRC and the list a few times in the past.
> > >
> > > What I think (and others seem to agree, SiegeLord, Elias, etc) is
> > > that there should be a list of common capabilities exported via an
> > > allegro API. So you can detect if there really is FAST hw
> > > acceleration (just having GL work is no indication), things like NPOT
> > > textures, FBO's, and other useful (but not always available) features
> > > should be advertised in a cross platform manner (yes, I'm aware "FBO"
> > > is a GL term, but D3D should have a corresponding feature).
> > >
> > > This way people can detect what features are available, and provide
> > > different code paths, before objects are even created.
> 
> I would think that many of the graphical capabilities would not be known
> until OpenGL is initialised, which means you'd want to query it on a
> specific display.  Maybe like:
> 
>     enum { ALLEGRO_CAPABILITY_NPOT_TEXTURES = 1, ... };
>     bool al_get_display_capability(ALLEGRO_DISPLAY *dpy, int cap);
> 
> Perhaps some capabilities are not boolean values, e.g. maximum texture
> size, so maybe we need multiple functions with different return types.
> 
> > I'm not the one to work on the capabilities stuff, but I do have some
> > experience working with both Xinerama and XRandR, so I will volunteer
> > to work on that should no one else want to (as a last resort).
> 
> As usual I can't find any documentation for Xrandr.h.  Do you know where
> it is, or of a good example?

I basically just looked at KDEs code, and the header. I might have some 
example code laying around some place, I wrote some for the display enum 
code in a5, but it turns out it was (a lot) easier to just use Xinerama for 
that. So the XRR code has been sitting. I've managed to find the code I 
wrote, its quite the mess, and doesn't compile, seems I was in the middle of 
reorganizing the code a bit when I stopped. But the XRandR code should be 
clear enough. Also its XRR 1.2 code, it might not be entirely correct for 
XRR 1.3+. I'll bet you can find a version that compiles fine if you look in 
the archive, or on a.cc.

The major problem is nvidia STILL doesn't implement XRR 1.2 or better. And 
Xorg in all their wisdom decided it was a good idea to fake the latest XRR 
protocol version at the server level using whatever the gfx driver provides. 
Which gives you bogus information on systems with the binary nvidia driver. 
What you get out of xrandr on a system running the binary nvidia driver is a 
single screen, regardless of how many actual screens you have, and it comes 
with a bogus refresh rate (there /was/ a good reason for that at the time it 
was implemented).

A proper implementation will have to check the number of Xinerama screens 
against the number of screens XRR says you have, and if XRandR.num_screens < 
Xinerama.num_screens, use XF86VidMode if you can.


> Peter
> 
> -------------------------------------------------------------------------
> ----- Throughout its 18-year history, RSA Conference consistently
>  attracts the world's best and brightest in the field, creating
>  opportunities for Conference attendees to learn about information
>  security's most important issues through interactions with peers,
>  luminaries and emerging and established companies.
>  http://p.sf.net/sfu/rsaconf-dev2dev
> 


-- 
Thomas Fjellstrom
tfjellstrom@xxxxxxxxxx
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/Xinerama.h>
#include <X11/extensions/xf86vmode.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRACE(a,b...) printf(a,##b)

/*

possible flow: (once we know we have xrandr 1.2)

Check if xrandr mode and X Screen size are the same
if Xinerama has more than one screen, we have a faulty Xrandr implementation,
 fallback to broken xrandr code
else
 use xrandr
endif

*/

struct _mode_info {
	int id; // XID for XRR, index into xf86vm.modes for XF86VidMode
	int width, height;
	int rate;
};

struct _crtc_info {
	int x, y;
	int mmwidth, mmheight;
	int rotation;
	int cur_mode;
	int nmode;
	int *modes;
};

struct ALLEGRO_SYSTEM_XGLX
{
	Display *x11display;
	int nscreen;

	int xrandr_avail;
	int xinerama_avail;
	int xf86vm_avail;

	int ncrtc;
	struct _crtc_info **crtcs;

	int nmode;
	struct _mode_info *modes;

#ifdef ALLEGRO_XWINDOWS_WITH_XRANDR
	struct {
		int broken; // if xrandr claims to be 1.2 but is actually Xorg's broken wrapper over a 1.1 driver.
		XRRScreenResources *res; // need this handle to call many XRR functions.
	} xrandr;
#endif

#ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA
	struct {
		int nscreen;
		XineramaScreenInfo *screens;
	} xinerama;
#endif

#ifdef ALLEGRO_XWINDOWS_WITH_XF86VM
	struct {
		int xinerama; // if xf86vm queries xinerama screens instead of X screens
		int nmode;
		XF86VidModeModeInfo **modes;
	} xf86vm;
#endif

};

int _al_xsys_mmon_init(struct ALLEGRO_SYSTEM_XGLX *s)
{
	int i = 0;

	s->xrandr_avail = 0;
	s->xf86vm_avail = 0;
	s->xinerama_avail = 0;

	if(_al_xsys_xinerama_init(s))
		s->xinerama_avail = 1;

	if(_al_xsys_xrandr_init(s))
		s->xrandr_avail = 1;

	if(_al_xsys_xf86vm_init(s))
		s->xf86vm_avail = 1;

	if(s->xinerama_avail)
		s->xinerama_avail = _al_xsys_xinerama_query(s);

	if(s->xrandr_avail) {
		s->xrandr_avail = _al_xsys_xrandr_query(s);
	}

	s->nscreen = ScreenCount(s->x11display);

	if(s->xf86vm_avail) {
		/*
			xf86vm uses Xinerama screens when using true Xinerama,
			which is the case if its available, and XRandR isn't
		*/

		int nscr = s->xrandr_avail ? s->nscreen : s->xinerama.nscreen;

		for(i = 0; i < nscr; i++) {
			_al_xsys_xf86vm_query(s, i);
		}
	}

}

int _al_xsys_mmon_new_crtc(struct ALLEGRO_SYSTEM_XGLX *s)
{
	
}

int _al_xsys_mmon_set_crtc_nmode(struct ALLEGRO_SYSTEM_XGLX *s, int nmode)
{

}

struct _mode_info *_al_xsys_mmon_get_crtc_mode(struct ALLEGRO_SYSTEM_XGLX *s, int nmode)
{

}

int _al_xsys_xrandr_init(struct ALLEGRO_SYSTEM_XGLX *s)
{
#ifdef ALLEGRO_XWINDOWS_WITH_XRANDR
	int event_basep = 0, error_basep = 0;
	XRRScreenResources *res = NULL;

	s->xrandr.res   = NULL;
	s->xrandr.ncrtc = 0;
	s->xrandr.crtcs = NULL;
	s->xrandr.nmode = 0;
	s->xrandr.modes = NULL;

	if(XRRQueryExtension (s->x11display, &event_basep, &error_basep)) {
		int xrrv_major = 0, xrrv_minor = 0;
		Status status;

		status = XRRQueryVersion (s->x11display, &xrrv_major, &xrrv_minor);
		if(status && (xrrv_major > 1 || (xrrv_major == 1 && xrrv_minor >= 2))) {
			TRACE("xrandrtest: xrandr version: %i.%i\n", xrrv_major, xrrv_minor);
			s->xrandr.res = res = XRRGetScreenResources (s->x11display, XRootWindow(s->x11display, DefaultScreen(s->x11display)));
			if(!res)
				goto _uninit;

			if(!res->nmode) {
				fprintf(stderr, "xrandrtest: Got ScreenResources, but we're missing all the modes :o\n");
				goto _uninit;
			}
		}
		else {
			TRACE("xrandr_init: xrandr version too old, need >=1.2, have %i.%i\n", xrrv_major, xrrv_minor);
			goto _uninit;
		}
	}
	else {
		TRACE("xrandr_init: xrandr extension not available.\n");
		goto _uninit;
	}

	return 1;

_uninit:

	if(res) {
		XRRFreeScreenResources(res);
		res = s->xrandr.res = NULL;
	}

#endif /* ALLEGRO_XWINDOWS_WITH_XRANDR */

	return 0;
}

int _al_xsys_xrandr_query(struct ALLEGRO_SYSTEM_XGLX *s) {
	int use_xrandr = 0;
	XRRScreenResources *res = NULL;
	int ncrtc = 0, nmode = 0;
	struct _crtc_info **crtcs = NULL;
	struct _mode_info *modes = NULL;

/* comment out old init code

//#ifdef ALLEGRO_XWINDOWS_WITH_XRANDR
	int event_basep = 0, error_basep = 0;
	if(XRRQueryExtension (s->x11display, &event_basep, &error_basep)) {
		Status status;
		int xrrv_major = 0, xrrv_minor = 0;
		status = XRRQueryVersion (s->x11display, &xrrv_major, &xrrv_minor);
		if(status && (xrrv_major > 1 || (xrrv_major == 1 && xrrv_minor >= 2))) {
			int screen = DefaultScreen(s->x11display);

			fprintf(stderr, "xrandrtest: XRandR version: %i.%i\n", xrrv_major, xrrv_minor);

			res = XRRGetScreenResources (s->x11display, XRootWindow(s->x11display, screen));
			if(!res)
				goto _uninit;

			if(!res->nmode) {
				fprintf(stderr, "xrandrtest: Got ScreenResources, but we're missing all the modes :o\n");
				goto _uninit;
			}

			use_xrandr = 1;
		}
		else {
			fprintf(stderr, "xrandrtest: failed to query XRandR extension, got version %i.%i\n", xrrv_major, xrrv_minor);
		}
	}
	else {
		fprintf(stderr, "xrandrtest: XRandR extension is not available\n");
	}
*/

	if(use_xrandr) {
		int i = 0;

		printf("xrandrtest: ncrtc:%i noutput:%i nmode:%i\n", res->ncrtc, res->noutput, res->nmode);

#ifdef ALLEGRO_XWINDOWS_WITH_XINERAMA
		/* try and filter out broken xrandr information */
		if(s->xinerama_avail) {
			if(s->xinerama.nscreen > res->ncrtc) {
				/* going to assume xinerama is correct here,
					it'll make sure we'll at least beable to get current screen modes from ati and nvidia binary drivers.
					Just going to ignore xrandr for now.
				*/
				s->xrandr_avail = 0;
				return 0;
			}
		}
#endif

		nmode = res->nmode;
		modes = calloc(nmode, sizeof(struct _mode_info));
		if(!modes)
			goto _uninit;

		for(i = 0; i < nmode; i++) {
			modes[i].xid = res->modes[i].id;
			modes[i].width = res->modes[i].width;
			modes[i].height = res->modes[i].height;

	// calculate the refresh rate
			if (res->modes[i].hTotal && res->modes[i].vTotal)
				modes[i].rate = ((float) res->modes[i].dotClock / ((float) res->modes[i].hTotal * (float) res->modes[i].vTotal));
			else
				modes[i].rate = 0;

			//printf("got mode[%i]: %ix%i @ %i\n", modes[i].xid, modes[i].width, modes[i].height, modes[i].rate);
		}

		crtcs = calloc(res->ncrtc, sizeof(struct _crtc_info *));
		if(!crtcs)
			goto _uninit;

		for(i = 0; i < res->ncrtc; i++) {
			XRRCrtcInfo *crtc_info = NULL;
			XRROutputInfo *output_info = NULL;
			XRROutputInfo *possible_info = NULL;
			int j = 0, k = 0, p = 0;

			crtcs[i] = calloc(1, sizeof(struct _crtc_info));
			if(!crtcs[i])
				goto _uninit;

			crtc_info = XRRGetCrtcInfo (s->x11display, res, res->crtcs[i]);
			if(!crtc_info) {
				continue;
			}

			printf("xrandrtest: crtc[%i]: noutput:%i\n", i, crtc_info->noutput);

			crtcs[i]->x = crtc_info->x;
			crtcs[i]->y = crtc_info->y;


			for(j = 0; j < crtc_info->noutput; j++) {
				output_info = XRRGetOutputInfo (s->x11display, res, crtc_info->outputs[j]);
				if(output_info && output_info->nmode) {
					int l = 0, m = 0;
					printf("xrandrtest: crtc[%i]: output[%s]: choosing %s output\n", i, output_info->name, output_info->name);
					for(m = 0; m < output_info->nmode; m++) {
						for(l = 0; l < nmode; l++) {
							if(modes[l].xid == output_info->modes[m]) {
								printf("\toutput mode[%i]: %ix%i @ %i\n", modes[l].xid, modes[l].width, modes[l].height, modes[l].rate);
								break;
							}
						}
					}

					break;
				}
				XRRFreeOutputInfo(output_info);
			}


			//output_info = XRRGetOutputInfo (s->x11display, res, crtc_info->outputs[0]);
			if(!output_info)
				continue;

/*
			printf("xrandrtest: crtc[%i]: npossible: %i\n", i, crtc_info->npossible);
			for(p = 0; p < crtc_info->npossible; p++) {
				possible_info = XRRGetOutputInfo (s->x11display, res, crtc_info->possible[p]);
				if(possible_info) {
					printf("xrandrtest: crtc[%i]: npossible[%s] modes: %i\n", i, possible_info->name, possible_info->nmode);
					if(possible_info->nmode) {
						int l = 0, m = 0;
						for(m = 0; m < possible_info->nmode; m++) {
							for(l = 0; l < nmode; l++) {
								if(modes[l].xid == possible_info->modes[m]) {
									printf("\tpossible mode[%i]: %ix%i @ %i\n", modes[l].xid, modes[l].width, modes[l].height, modes[l].rate);
									break;
								}
							}
						}
					}
				}
				XRRFreeOutputInfo(possible_info);
			}
*/

			crtcs[i]->mmwidth  = output_info->mm_width;
			crtcs[i]->mmheight = output_info->mm_height;

			printf("xrandrtest: crtc[%i]: %ix%i (%immx%imm)\n", i, crtcs[i]->x, crtcs[i]->y, crtcs[i]->mmwidth, crtcs[i]->mmheight);

			crtcs[i]->nmode = output_info->nmode;
			if(!crtcs[i]->nmode)
				continue;

			crtcs[i]->modes = calloc(output_info->nmode, sizeof(int));
			if(!crtcs[i]->modes)
				continue;

			for(k = 0; k < output_info->nmode; k++) {
				int l = 0;
				crtcs[i]->modes[k] = output_info->modes[k];
				for(l = 0; l < nmode; l++) {
					if(modes[l].xid == output_info->modes[k]) {
						printf("\tmode[%i]: %ix%i @ %i\n", l, modes[l].width, modes[l].height, modes[l].rate);
						break;
					}
				}
			}

			XRRFreeOutputInfo(output_info);
			XRRFreeCrtcInfo(crtc_info);
		}
	}
//#endif /* ALLEGRO_XWINDOWS_WITH_XINERAMA */
	return use_xrandr;

_uninit:

	return 0;
}

int _al_xsys_xf86vm_init(struct ALLEGRO_SYSTEM_XGLX *s)
{
	int x = 0, y = 0;
	if(!XF86VidModeQueryExtension(s->x11display, &x, &y)) {
		printf("xrandrtest: XF86VidMode Extension is not available: Extension Query failed.\n");
		return 0;
	}

	if(!XF86VidModeQueryVersion(s->x11display, &x, &y)) {
		printf("xrandrtest: XF86VidMode Extension is not available: Version Query failed.\n");
		return 0;
	}

   return 1;
}

int get_xfmode_lines(struct ALLEGRO_SYSTEM_XGLX *s, int screen)
{
	XF86VidModeModeInfo **mode_info = NULL;
	XF86VidModeMonitor *monitor = NULL;
	int nmode = 0;
	int i = 0, j = 0;

	if(!XF86VidModeGetAllModeLines(s->x11display, screen, &nmode, &mode_info)) {
		printf("xrandrtest: XF86VidMode: screen[%i]: GetAllModeLines failed.\n", screen);
		return 0;
	}

	monitor = calloc(1, sizeof(XF86VidModeMonitor));
	if(!monitor) {
		printf("xrandrtest: XF86VidMode: calloc failed :(\n");
		return 0;
	}

	if(!XF86VidModeGetMonitor(s->x11display, screen, monitor)) {
		printf("xrandrtest: XF86VidMode: GetMonitor failed.\n");
		free(monitor);
		return 0;
	}

	printf("xrandrtest: XF86VidMode: screen[%i]: hsync(%i): ", screen, monitor->nhsync);
	for(j = 0; j < monitor->nhsync; j++) {
		printf("[%i: %f-%f] ", j, monitor->hsync[i].lo, monitor->hsync[i].hi);
	}

	printf(" vsync(%i): ", monitor->nvsync);
	for(j = 0; j < monitor->nvsync; j++) {
		printf("[%i: %f-%f] ", j, monitor->vsync[i].lo, monitor->vsync[i].hi);
	}

	printf("\n");

	for(i = 0; i < nmode; i++) {
		float rate = 0.0f;
		if (mode_info[i]->htotal && mode_info[i]->vtotal) {
			rate = (mode_info[i]->dotclock * 1000L / ( mode_info[i]->htotal * mode_info[i]->vtotal));
		}

		printf("\tmode[%i]: %ix%i @ %f\n", i, mode_info[i]->hdisplay, mode_info[i]->vdisplay, rate);
	}
}

/*
int init_nvctrl(struct ALLEGRO_SYSTEM_XGLX *s)
{
	int event_base = 0, error_base = 0;
	int major = 0, minor = 0;

	if(!XNVCTRLQueryExtension (s->x11display, &event_base, &error_base))
	{
		printf("xrandrtest: NV-CONTROL extension is not available.\n");
		return 0;
	}

	if(!XNVCTRLQueryVersion (s->x11display, &major, &minor)) {
		printf("xrandrtest: NV-CONTROL Version Query failed.\n");
		return 0;
	}

	printf("xrandrtest: NV-CONTROL Version: %i.%i\n", major, minor);

	return 1;
}
*/

int nvctrl_query(struct ALLEGRO_SYSTEM_XGLX *s, int screen)
{
	if(!XNVCTRLIsNvScreen (s->x11display, screen)) {
		printf("xrandrtest: NV-CONTROL: screen[%i] is not controlled by NVidia.\n", screen);
		return 0;
	}

	// NV_CTRL_TWINVIEW, can be used to shortcircuit out of here... if no twinview, theres separate screens, and xrandr/xinerama can fill in.

	// NV_CTRL_ENABLED_DISPLAYS, get enabled displays via XNVCTRLQueryTargetAttribute())
}

int main(int argc, char **argv)
{
	int default_screen = 0, screen_count = 0, screen = 0;
	char *display_name = NULL;
	int event_base = 0, error_base = 0;
	int use_xrandr = 0;
	struct ALLEGRO_SYSTEM_XGLX *system = calloc(1, sizeof(struct ALLEGRO_SYSTEM_XGLX));

	display_name = getenv("DISPLAY");
	if(!display_name) {
		fprintf(stderr, "%s: DISPLAY not set >:(\n", argv[0]);
		exit(-1);
	}

	if ((system->x11display=XOpenDisplay(display_name)) == NULL)
	{
		fprintf(stderr,"%s: cannot connect to X server %s\n", argv[0], XDisplayName(display_name));
		exit(-1);
	}

	printf("xrandrtest: display name: %s\n", DisplayString(system->x11display));
	printf("xrandrtest: server vendor: %s\n", ServerVendor(system->x11display));
	if (strstr(ServerVendor(system->x11display), "X.Org")) {
		int vendrel = VendorRelease(system->x11display);

		printf("xrandrtest: X.Org version: ");
		printf("%d.%d.%d", vendrel / 10000000, (vendrel / 100000) % 100, (vendrel / 1000) % 100);
		if (vendrel % 1000) {
			printf(".%d", vendrel % 1000);
		}
		printf("\n");
	}
   else if (strstr(ServerVendor (system->x11display), "XFree86")) {
        int vendrel = VendorRelease(system->x11display);

        printf("XFree86 version: ");
        if (vendrel < 336) {
            /*
             * vendrel was set incorrectly for 3.3.4 and 3.3.5, so handle
             * those cases here.
             */
            printf("%d.%d.%d", vendrel / 100,
                              (vendrel / 10) % 10,
                               vendrel       % 10);
        } else if (vendrel < 3900) {
            /* 3.3.x versions, other than the exceptions handled above */
            printf("%d.%d", vendrel / 1000,
                           (vendrel /  100) % 10);
            if (((vendrel / 10) % 10) || (vendrel % 10)) {
                printf(".%d", (vendrel / 10) % 10);
                if (vendrel % 10) {
                    printf(".%d", vendrel % 10);
                }
            }
        } else if (vendrel < 40000000) {
            /* 4.0.x versions */
            printf("%d.%d", vendrel / 1000,
                           (vendrel /   10) % 10);
            if (vendrel % 10) {
                printf(".%d", vendrel % 10);
            }
        } else {
            /* post-4.0.x */
            printf("%d.%d.%d", vendrel / 10000000,
                              (vendrel /   100000) % 100,
                              (vendrel /     1000) % 100);
            if (vendrel % 1000) {
                printf(".%d", vendrel % 1000);
            }
        }
        printf("\n");
    }

	else if (strstr(ServerVendor (system->x11display), "DMX")) {
        int vendrel = VendorRelease(system->x11display);
        int major, minor, year, month, day;

        major    = vendrel / 100000000;
        vendrel -= major   * 100000000;
        minor    = vendrel /   1000000;
        vendrel -= minor   *   1000000;
        year     = vendrel /     10000;
        vendrel -= year    *     10000;
        month    = vendrel /       100;
        vendrel -= month   *       100;
        day      = vendrel;

                                /* Add other epoch tests here */
        if (major > 0 && minor > 0) year += 2000;

                                /* Do some sanity tests in case there is
                                 * another server with the same vendor
                                 * string.  That server could easily use
                                 * values < 100000000, which would have
                                 * the effect of keeping our major
                                 * number 0. */
        if (major > 0 && major <= 20
            && minor >= 0 && minor <= 99
            && year >= 2000
            && month >= 1 && month <= 12
            && day >= 1 && day <= 31)
            printf("DMX version: %d.%d.%04d%02d%02d\n",
                   major, minor, year, month, day);
    }
	else {
		printf("xrandrtest: server release: '%i'\n", VendorRelease(system->x11display));
	}

	printf("xrandrtest: proto version: %i.%i\n", ProtocolVersion(system->x11display),ProtocolRevision(system->x11display));

	screen_count = ScreenCount(system->x11display);
	default_screen = DefaultScreen(system->x11display);

	printf("xrandrtest: X Screen count: %i default screen: %i\n", screen_count, default_screen);
	for(screen = 0; screen < screen_count; screen++) {
		Screen *scr = ScreenOfDisplay(system->x11display, screen);
		printf("\tscreen[%i]: width:%i height:%i\n", screen, WidthOfScreen(scr), HeightOfScreen(scr));
	}

	if(XineramaQueryExtension(system->x11display, &event_base, &error_base)) {
		int minor_version = 0, major_version = 0;
		int status = XineramaQueryVersion(system->x11display, &major_version, &minor_version);
		printf("xrandrtest: Xinerama version: %i.%i\n", major_version, minor_version);

		if(!XineramaIsActive(system->x11display)) {
			printf("xrandrtest: Xinerama is not active\n");
		}
		else {
			int screen_num = 0;
			XineramaScreenInfo *info = XineramaQueryScreens(system->x11display, &screen_num);
			if(!info) {
				fprintf(stderr, "xrandrtest: XineramaQueryScreens failed.\n");
			}
			else {
				int i = 0;
				printf("xrandrtest: Xinerama: Got %i Screens\n", screen_num);
				for(i = 0; i < screen_num; i++) {
					printf("\tscreen[%i]: %ix%i+%i+%i (%immx%imm)\n", i, info[i].width, info[i].height, info[i].x_org, info[i].y_org, 0, 0);
				}
			}
		}
	}
	else {
		fprintf(stderr, "xrandrtest: Xinerama extension is not available.\n");
	}

	if(init_xfmode(system)) {
		int si = 0;
		for(si = 0; si < screen_count; si++) {
			get_xfmode_lines(system, si);
		}
	}

	use_xrandr = _al_xsys_xrandr_init(system);


	XCloseDisplay(system->x11display);
	return 0;
}


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/