Logo Search packages:      
Sourcecode: beryl-core version File versions

syscheck.c

/*
 *
 * Beryl hardware/software detection system
 *
 * Copyright : (C) 2007 by Dennis Kasprzyk
 * E-mail    : onestone@beryl-project.org
 *
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/sync.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <unistd.h>
#include <sys/wait.h>

#include "syscheck.h"

#define TRUE 1
#define FALSE 0


static Bool detect_nvidia(Display *dpy)
{
      int xEvent;
      int xError;
      int xOpcode;

      if (XQueryExtension(dpy, "NV-GLX", &xOpcode, &xEvent, &xError))
      {
            return TRUE;
      }
      return FALSE;
}

static Bool detect_nvglx(void)
{
      pid_t p = fork();

      if (p)
      {
            int stat;

            waitpid(p, &stat, 0);
            if (!WIFEXITED(stat))
            {
                  fprintf(stderr,"Something went wrong with Nvidia detection.");
                  return FALSE;
            }
            else
            {
                  if (WEXITSTATUS(stat))
                  {
                        return FALSE;
                  }
                  else
                  {
                        return TRUE;
                  }
            }
      }
      else
      {
            execl("/bin/sh", "sh", "-c",
                    "xdpyinfo | grep -q -i NV-GLX", (char *)NULL);
            exit(1);
      }

}

static Bool detect_xgl(void)
{
      pid_t p = fork();

      if (p)
      {
            int stat;

            waitpid(p, &stat, 0);
            if (!WIFEXITED(stat))
            {
                  fprintf(stderr,"Something went wrong with Xgl detection.\n");
                  return FALSE;
            }
            else
            {
                  if (WEXITSTATUS(stat))
                  {
                        return FALSE;
                  }
                  else
                  {
                        return TRUE;
                  }
            }
      }
      else
      {
            execl("/bin/sh", "sh", "-c", "xvinfo | grep -q -i Xgl", (char *)NULL);
            exit(1);
      }
}


static int checkScreen(Display *dpy,int screen)
{
      printf("\nChecking Screen %d ...\n\n",screen);

      Window root = XRootWindow(dpy, screen);
    XWindowAttributes attrib;
      XVisualInfo templ;
      XVisualInfo *visinfo;
      int nvisinfo, defaultDepth, value;
      const char *glxServerExtensions, *glxExtensions, *glExtensions;
      GLXContext ctx;

      if (!XGetWindowAttributes(dpy, root, &attrib))
      {
            fprintf(stderr, "Unable to get root window attributes\n");
            return CHECK_ERROR;
      }

      templ.visualid = XVisualIDFromVisual(attrib.visual);
      visinfo = XGetVisualInfo(dpy, VisualIDMask, &templ, &nvisinfo);
      if (!nvisinfo)
      {
            fprintf(stderr,"Couldn't get visual info for default visual\n");
            return CHECK_ERROR;
      }

      defaultDepth = visinfo->depth;

      glXGetConfig(dpy, visinfo, GLX_USE_GL, &value);
      if (!value)
      {
            fprintf(stderr,"Root visual is not a GL visual\n");
            return CHECK_ERROR;
      }

      glXGetConfig(dpy, visinfo, GLX_DOUBLEBUFFER, &value);
      if (!value)
      {
            fprintf(stderr,"Root visual is not a double buffered GL visual\n");
            return CHECK_ERROR;
      }

      // indirect rendering works always
      ctx = glXCreateContext(dpy, visinfo, NULL, 0);

      if (!ctx)
      {
            fprintf(stderr, "glXCreateContext failed\n");
            return CHECK_ERROR;
      }

      XFree(visinfo);

      glxExtensions =   glXQueryExtensionsString(dpy, screen);
      glxServerExtensions =   glXQueryServerString(dpy, screen, GLX_EXTENSIONS);

      printf("Checking for GLX_SGIX_fbconfig                  : ");

      if (strstr(glxExtensions, "GLX_SGIX_fbconfig") ||
            strstr(glxServerExtensions, "GLX_SGIX_fbconfig"))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "No GLX_SGIX_fbconfig\n");
            glXDestroyContext(dpy, ctx);
            return CHECK_ERROR;
      }

      printf("Checking for GLX_EXT_texture_from_pixmap        : ");

      if (strstr(glxExtensions, "GLX_EXT_texture_from_pixmap") ||
            strstr(glxServerExtensions, "GLX_EXT_texture_from_pixmap"))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "No GLX_EXT_texture_from_pixmap\n");
            glXDestroyContext(dpy, ctx);
            return CHECK_NOTFP;
      }

      glXMakeCurrent(dpy, root, ctx);

      glExtensions = (const char *)glGetString(GL_EXTENSIONS);

      printf("Checking for non power of two texture support   : ");

      if (strstr(glExtensions, "GL_ARB_texture_non_power_of_two") ||
            strstr(glExtensions, "GL_NV_texture_rectangle") ||
            strstr(glExtensions, "GL_EXT_texture_rectangle") ||
            strstr(glExtensions, "GL_ARB_texture_rectangle"))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "Support for non power of two textures missing\n");
            glXDestroyContext(dpy, ctx);
            return CHECK_ERROR;
      }

      printf("Checking maximum texture size                   : ");

      int maxSize = 0;
      if (strstr(glExtensions, "GL_ARB_texture_non_power_of_two"))
            glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
      else
            glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &maxSize);

      if (attrib.width <= maxSize && attrib.height <= maxSize)
            printf("passed (%dx%d)\n",maxSize,maxSize);
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "Root window size (%d/%d) is bigger then maximum "
                                    "texture size (%dx%d)\n",attrib.width,attrib.height,
                                    maxSize,maxSize);
            glXDestroyContext(dpy, ctx);
      }

      glXDestroyContext(dpy, ctx);
      return CHECK_SUCCESS;
}

static int checkDisplay(Display *dpy)
{

      int xEvent;
      int xError;
      int xOpcode;

      printf("Checking for XComposite extension               : ");
      if (!XQueryExtension(dpy, COMPOSITE_NAME, &xOpcode, &xEvent, &xError))
      {
            printf("failed\n\n");
            fprintf(stderr, "No composite extension\n");
            return CHECK_ERROR;
      }


      int compositeMajor;
      int compositeMinor;
      XCompositeQueryVersion(dpy, &compositeMajor, &compositeMinor);
      if (compositeMajor == 0 && compositeMinor < 2)
      {
            printf("failed\n\n");
            fprintf(stderr, "Composite extension too old\n");
            return CHECK_ERROR;
      }
      else
            printf("passed ");
      printf("(v%d.%d)\n",compositeMajor,compositeMinor);

      printf("Checking for XDamage extension                  : ");

      if (XDamageQueryExtension(dpy, &xEvent, &xError))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "No damage extension\n");
            return CHECK_ERROR;
      }

      printf("Checking for RandR extension                    : ");

      if (XRRQueryExtension(dpy, &xEvent, &xError))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "No RandR extension\n");
            return CHECK_ERROR;
      }

      printf("Checking for XSync extension                    : ");
      if (XSyncQueryExtension(dpy, &xEvent, &xError))
            printf("passed\n");
      else
      {
            printf("failed\n\n");
            fprintf(stderr, "No sync extension\n");
            return CHECK_ERROR;
      }
      return CHECK_SUCCESS;
}

static int startCheck(char * displayName, int *mode, int *numScreens)
{
      printf("**************************************************************\n");
      printf("* Beryl system compatiblity check                            *\n");
      printf("**************************************************************\n");
      Display *dpy = XOpenDisplay(displayName);
      if (!dpy) {
            fprintf(stderr, "Error: unable to open display %s\n", displayName);
            return CHECK_ERROR;
      }

      if (mode)
      {
            *mode = MODE_AIGLX;
            if (detect_xgl())
                  *mode = MODE_XGL;
            else if (detect_nvidia(dpy))
                  *mode = MODE_NVIDIA;
            printf("\nDetected xserver                                : ");
            switch (*mode)
            {
                  case MODE_XGL:
                        printf("XGL\n");
                        break;
                  case MODE_NVIDIA:
                        printf("NVIDIA\n");
                        break;
                  default:
                        printf("AIGLX\n");
                        break;
            }
      }

      int rv = 0;

      printf("\nChecking Display %s ...\n\n",XDisplayName(displayName));
      rv = checkDisplay(dpy);
      if (rv)
            return rv;

      int nScreens = ScreenCount(dpy);
      if (numScreens)
            *numScreens = nScreens;
      int i = 0;
      for (i = 0; i < nScreens && *mode != MODE_XGL; i++)
      {
            rv = checkScreen(dpy,i);
            if (rv)
                  return rv;
      }

      printf("\n");

      XCloseDisplay(dpy);

      return CHECK_SUCCESS;
}

int syscheck(char * displayName, int *mode, int *numScreens)
{
      if (detect_xgl() || detect_nvglx())
            return startCheck(displayName,mode,numScreens);

      pid_t p = fork();

      if (p)
      {
            int stat;

            waitpid(p, &stat, 0);
            if (!WIFEXITED(stat))
            {
                  fprintf(stderr,"Something went wrong with system check.\n");
                  *mode = MODE_AIGLX;
                  *numScreens = 1;
                  return CHECK_ERROR;
            }
            else
            {
                  int rv = WEXITSTATUS(stat);
                  *mode = (rv >> 2) & 0x3;
                  *numScreens = (rv >> 4) & 0xf;
                  return rv & 0x3;
            }
      }
      else
      {
            int m = 0;
            int ns = 0;
            int rv = startCheck(displayName,&m,&ns);
            if (ns > 0xf)
                  ns = 0xf;
            if (m > 0x3)
                  m = 0;
            if (rv > 0x3)
                  rv = 0x3;
            exit(rv & (m << 2) & (ns << 4));
      }
}

Generated by  Doxygen 1.6.0   Back to index