summaryrefslogtreecommitdiffstats
path: root/kcontrol/info/opengl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/info/opengl.cpp')
-rw-r--r--kcontrol/info/opengl.cpp673
1 files changed, 673 insertions, 0 deletions
diff --git a/kcontrol/info/opengl.cpp b/kcontrol/info/opengl.cpp
new file mode 100644
index 000000000..66266abdf
--- /dev/null
+++ b/kcontrol/info/opengl.cpp
@@ -0,0 +1,673 @@
+/***************************************************************************
+ * *
+ * Copyright (C) 2004 by Ilya Korniyko <[email protected]> *
+ * Adapted from Brian Paul's glxinfo from Mesa demos (http:/www.mesa3d.org)
+ * Copyright (C) 1999-2002 Brian Paul *
+ * *
+ * 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. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#if defined(INFO_OPENGL_AVAILABLE)
+
+#define KCMGL_DO_GLU
+
+#include <qregexp.h>
+#include <qlistview.h>
+#include <qfile.h>
+#include <qstring.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef KCMGL_DO_GLU
+#include <GL/glu.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GL/glx.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static bool IsDirect;
+
+static struct glinfo {
+ const char *serverVendor;
+ const char *serverVersion;
+ const char *serverExtensions;
+ const char *clientVendor;
+ const char *clientVersion;
+ const char *clientExtensions;
+ const char *glxExtensions;
+ const char *glVendor;
+ const char *glRenderer;
+ const char *glVersion;
+ const char *glExtensions;
+ const char *gluVersion;
+ const char *gluExtensions;
+ char *displayName;
+} gli;
+
+static struct {
+ QString module,
+ pci,
+ vendor,
+ device,
+ subvendor,
+ rev;
+} dri_info;
+
+static int ReadPipe(QString FileName, QStringList &list)
+{
+ FILE *pipe;
+
+ if ((pipe = popen(FileName.ascii(), "r")) == NULL) {
+ pclose(pipe);
+ return 0;
+ }
+
+ QTextStream t(pipe, IO_ReadOnly);
+
+ while (!t.atEnd()) list.append(t.readLine());
+
+ pclose(pipe);
+ return list.count();
+}
+
+#if defined(Q_OS_LINUX)
+
+#define INFO_DRI "/proc/dri/0/name"
+
+static bool get_dri_device()
+{
+ QFile file;
+ file.setName(INFO_DRI);
+ if (!file.exists() || !file.open(IO_ReadOnly))
+ return false;
+
+ QTextStream stream(&file);
+ QString line = stream.readLine();
+ if (!line.isEmpty()) {
+ dri_info.module = line.mid(0, line.find(0x20));
+
+ // possible formats, for regression testing
+ // line = " PCI:01:00:0";
+ // line = " pci:0000:01:00.0"
+ QRegExp rx = QRegExp("\\b[Pp][Cc][Ii][:]([0-9a-fA-F]+[:])?([0-9a-fA-F]+[:][0-9a-fA-F]+[:.][0-9a-fA-F]+)\\b");
+ if (rx.search(line)>0) {
+ dri_info.pci = rx.cap(2);
+ int end = dri_info.pci.findRev(':');
+ int end2 = dri_info.pci.findRev('.');
+ if (end2>end) end=end2;
+ dri_info.pci[end]='.';
+
+ QString cmd = QString("lspci -m -v -s ") + dri_info.pci;
+ QStringList pci_info;
+ int num;
+ if (((num = ReadPipe(cmd, pci_info)) ||
+ (num = ReadPipe("/sbin/"+cmd, pci_info)) ||
+ (num = ReadPipe("/usr/sbin/"+cmd, pci_info)) ||
+ (num = ReadPipe("/usr/local/sbin/"+cmd, pci_info))) && num>=7) {
+ for (int i=2; i<=6; i++) {
+ line = pci_info[i];
+ line.remove(QRegExp("[^:]*:[ ]*"));
+ switch (i){
+ case 2: dri_info.vendor = line; break;
+ case 3: dri_info.device = line; break;
+ case 4: dri_info.subvendor = line; break;
+ case 6: dri_info.rev = line; break;
+ }
+ }
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+#elif defined(Q_OS_FREEBSD)
+
+static bool get_dri_device() {
+
+ QStringList pci_info;
+ if (ReadPipe("sysctl -n hw.dri.0.name",pci_info)) {
+ dri_info.module = pci_info[0].mid(0, pci_info[0].find(0x20));
+ }
+ return false;
+}
+
+#else
+
+static bool get_dri_device() { return false; }
+
+#endif
+
+static void
+mesa_hack(Display *dpy, int scrnum)
+{
+ static int attribs[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ GLX_STENCIL_SIZE, 1,
+ GLX_ACCUM_RED_SIZE, 1,
+ GLX_ACCUM_GREEN_SIZE, 1,
+ GLX_ACCUM_BLUE_SIZE, 1,
+ GLX_ACCUM_ALPHA_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None
+ };
+ XVisualInfo *visinfo;
+
+ visinfo = glXChooseVisual(dpy, scrnum, attribs);
+ if (visinfo)
+ XFree(visinfo);
+}
+
+
+static void
+print_extension_list(const char *ext, QListViewItem *l1)
+{
+ int i, j;
+
+ if (!ext || !ext[0])
+ return;
+ QString qext = QString::fromLatin1(ext);
+ QListViewItem *l2 = NULL;
+
+ i = j = 0;
+ while (1) {
+ if (ext[j] == ' ' || ext[j] == 0) {
+ /* found end of an extension name */
+ const int len = j - i;
+ /* print the extension name between ext[i] and ext[j] */
+ if (!l2) l2 = new QListViewItem(l1, qext.mid(i, len));
+ else l2 = new QListViewItem(l1, l2, qext.mid(i, len));
+ i=j;
+ if (ext[j] == 0) {
+ break;
+ }
+ else {
+ i++;
+ j++;
+ if (ext[j] == 0)
+ break;
+ }
+ }
+ j++;
+ }
+}
+
+#if defined(GLX_ARB_get_proc_address) && defined(__GLXextFuncPtr)
+extern "C" {
+ extern __GLXextFuncPtr glXGetProcAddressARB (const GLubyte *);
+}
+#endif
+
+static void
+print_limits(QListViewItem *l1, const char * glExtensions, bool GetProcAddress)
+{
+ /* TODO
+ GL_SAMPLE_BUFFERS
+ GL_SAMPLES
+ GL_COMPRESSED_TEXTURE_FORMATS
+*/
+
+ if (!glExtensions)
+ return;
+
+ struct token_name {
+ GLuint type; // count and flags, !!! count must be <=2 for now
+ GLenum token;
+ const QString name;
+ };
+
+ struct token_group {
+ int count;
+ int type;
+ const token_name *group;
+ const QString descr;
+ const char *ext;
+ };
+
+ QListViewItem *l2 = NULL, *l3 = NULL;
+#if defined(PFNGLGETPROGRAMIVARBPROC)
+ PFNGLGETPROGRAMIVARBPROC kcm_glGetProgramivARB = NULL;
+#endif
+
+ #define KCMGL_FLOAT 128
+ #define KCMGL_PROG 256
+ #define KCMGL_COUNT_MASK(x) (x & 127)
+ #define KCMGL_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
+ const struct token_name various_limits[] = {
+ { 1, GL_MAX_LIGHTS, i18n("Max. number of light sources") },
+ { 1, GL_MAX_CLIP_PLANES, i18n("Max. number of clipping planes") },
+ { 1, GL_MAX_PIXEL_MAP_TABLE, i18n("Max. pixel map table size") },
+ { 1, GL_MAX_LIST_NESTING, i18n("Max. display list nesting level") },
+ { 1, GL_MAX_EVAL_ORDER, i18n("Max. evaluator order") },
+ { 1, GL_MAX_ELEMENTS_VERTICES, i18n("Max. recommended vertex count") },
+ { 1, GL_MAX_ELEMENTS_INDICES, i18n("Max. recommended index count") },
+#ifdef GL_QUERY_COUNTER_BITS
+ { 1, GL_QUERY_COUNTER_BITS, i18n("Occlusion query counter bits")},
+#endif
+#ifdef GL_MAX_VERTEX_UNITS_ARB
+ { 1, GL_MAX_VERTEX_UNITS_ARB, i18n("Max. vertex blend matrices") },
+#endif
+#ifdef GL_MAX_PALETTE_MATRICES_ARB
+ { 1, GL_MAX_PALETTE_MATRICES_ARB, i18n("Max. vertex blend matrix palette size") },
+#endif
+ {0,0,0}
+ };
+
+ const struct token_name texture_limits[] = {
+ { 1, GL_MAX_TEXTURE_SIZE, i18n("Max. texture size") },
+ { 1, GL_MAX_TEXTURE_UNITS_ARB, i18n("Num. of texture units") },
+ { 1, GL_MAX_3D_TEXTURE_SIZE, i18n("Max. 3D texture size") },
+#ifdef GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB
+ { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, i18n("Max. cube map texture size") },
+#endif
+#ifdef GL_MAX_RECTANGLE_TEXTURE_SIZE_NV
+ { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, i18n("Max. rectangular texture size") },
+#endif
+#ifdef GL_MAX_TEXTURE_LOD_BIAS_EXT
+ { 1 | KCMGL_FLOAT, GL_MAX_TEXTURE_LOD_BIAS_EXT, i18n("Max. texture LOD bias") },
+#endif
+#ifdef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
+ { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, i18n("Max. anisotropy filtering level") },
+#endif
+#ifdef GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB
+ { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, i18n("Num. of compressed texture formats") },
+#endif
+ {0,0,0}
+ };
+
+ const struct token_name float_limits[] = {
+ { 2 | KCMGL_FLOAT, GL_ALIASED_POINT_SIZE_RANGE, "ALIASED_POINT_SIZE_RANGE" },
+ { 2 | KCMGL_FLOAT, GL_SMOOTH_POINT_SIZE_RANGE, "SMOOTH_POINT_SIZE_RANGE" },
+ { 1 | KCMGL_FLOAT, GL_SMOOTH_POINT_SIZE_GRANULARITY,"SMOOTH_POINT_SIZE_GRANULARITY"},
+ { 2 | KCMGL_FLOAT, GL_ALIASED_LINE_WIDTH_RANGE, "ALIASED_LINE_WIDTH_RANGE" },
+ { 2 | KCMGL_FLOAT, GL_SMOOTH_LINE_WIDTH_RANGE, "SMOOTH_LINE_WIDTH_RANGE" },
+ { 1 | KCMGL_FLOAT, GL_SMOOTH_LINE_WIDTH_GRANULARITY,"SMOOTH_LINE_WIDTH_GRANULARITY"},
+ {0,0,0}
+ };
+
+ const struct token_name stack_depth[] = {
+ { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "MAX_MODELVIEW_STACK_DEPTH" },
+ { 1, GL_MAX_PROJECTION_STACK_DEPTH, "MAX_PROJECTION_STACK_DEPTH" },
+ { 1, GL_MAX_TEXTURE_STACK_DEPTH, "MAX_TEXTURE_STACK_DEPTH" },
+ { 1, GL_MAX_NAME_STACK_DEPTH, "MAX_NAME_STACK_DEPTH" },
+ { 1, GL_MAX_ATTRIB_STACK_DEPTH, "MAX_ATTRIB_STACK_DEPTH" },
+ { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "MAX_CLIENT_ATTRIB_STACK_DEPTH" },
+ { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "MAX_COLOR_MATRIX_STACK_DEPTH" },
+#ifdef GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB
+ { 1, GL_MAX_MATRIX_PALETTE_STACK_DEPTH_ARB,"MAX_MATRIX_PALETTE_STACK_DEPTH"},
+#endif
+ {0,0,0}
+ };
+
+#ifdef GL_ARB_fragment_program
+ const struct token_name arb_fp[] = {
+ { 1, GL_MAX_TEXTURE_COORDS_ARB, "MAX_TEXTURE_COORDS" },
+ { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "MAX_TEXTURE_IMAGE_UNITS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "MAX_PROGRAM_ENV_PARAMETERS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "MAX_PROGRAM_LOCAL_PARAMETERS" },
+ { 1, GL_MAX_PROGRAM_MATRICES_ARB, "MAX_PROGRAM_MATRICES" },
+ { 1, GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB, "MAX_PROGRAM_MATRIX_STACK_DEPTH" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "MAX_PROGRAM_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "MAX_PROGRAM_ALU_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "MAX_PROGRAM_TEX_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "MAX_PROGRAM_TEX_INDIRECTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEMPORARIES_ARB, "MAX_PROGRAM_TEMPORARIES" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_PARAMETERS_ARB, "MAX_PROGRAM_PARAMETERS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_ATTRIBS_ARB, "MAX_PROGRAM_ATTRIBS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "MAX_PROGRAM_NATIVE_TEMPORARIES" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "MAX_PROGRAM_NATIVE_PARAMETERS" },
+ { 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "MAX_PROGRAM_NATIVE_ATTRIBS" },
+ {0,0,0}
+ };
+#endif
+
+#ifdef GL_ARB_vertex_program
+ const struct token_name arb_vp[] = {
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB,"MAX_PROGRAM_ENV_PARAMETERS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB,"MAX_PROGRAM_LOCAL_PARAMETERS"},
+{ 1, GL_MAX_VERTEX_ATTRIBS_ARB, "MAX_VERTEX_ATTRIBS"},
+{ 1, GL_MAX_PROGRAM_MATRICES_ARB,"MAX_PROGRAM_MATRICES"},
+{ 1, GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB,"MAX_PROGRAM_MATRIX_STACK_DEPTH"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_INSTRUCTIONS_ARB,"MAX_PROGRAM_INSTRUCTIONS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_TEMPORARIES_ARB,"MAX_PROGRAM_TEMPORARIES"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_PARAMETERS_ARB,"MAX_PROGRAM_PARAMETERS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_ATTRIBS_ARB,"MAX_PROGRAM_ATTRIBS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB,"MAX_PROGRAM_ADDRESS_REGISTERS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,"MAX_PROGRAM_NATIVE_INSTRUCTIONS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,"MAX_PROGRAM_NATIVE_TEMPORARIES"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB,"MAX_PROGRAM_NATIVE_PARAMETERS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB,"MAX_PROGRAM_NATIVE_ATTRIBS"},
+{ 1 | KCMGL_PROG, GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB ,"MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS"},
+{0,0,0}
+};
+#endif
+
+#ifdef GL_ARB_vertex_shader
+ const struct token_name arb_vs[] = {
+ { 1, GL_MAX_VERTEX_ATTRIBS_ARB,"MAX_VERTEX_ATTRIBS"},
+ { 1, GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB,"MAX_VERTEX_UNIFORM_COMPONENTS"},
+ { 1, GL_MAX_VARYING_FLOATS_ARB,"MAX_VARYING_FLOATS"},
+ { 1, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB,"MAX_COMBINED_TEXTURE_IMAGE_UNITS"},
+ { 1, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB,"MAX_VERTEX_TEXTURE_IMAGE_UNITS"},
+ { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB,"MAX_TEXTURE_IMAGE_UNITS"},
+ { 1, GL_MAX_TEXTURE_COORDS_ARB,"MAX_TEXTURE_COORDS"},
+ {0,0,0}
+ };
+#endif
+
+#ifdef GL_ARB_fragment_shader
+ const struct token_name arb_fs[] = {
+ { 1, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB,"MAX_FRAGMENT_UNIFORM_COMPONENTS"},
+ { 1, GL_MAX_TEXTURE_IMAGE_UNITS_ARB,"MAX_TEXTURE_IMAGE_UNITS"},
+ { 1, GL_MAX_TEXTURE_COORDS_ARB,"MAX_TEXTURE_COORDS"},
+ {0,0,0}
+ };
+#endif
+
+ const struct token_name frame_buffer_props[] = {
+ { 2, GL_MAX_VIEWPORT_DIMS, i18n("Max. viewport dimensions") },
+ { 1, GL_SUBPIXEL_BITS, i18n("Subpixel bits") },
+ { 1, GL_AUX_BUFFERS, i18n("Aux. buffers")},
+ {0,0,0}
+ };
+
+ const struct token_group groups[] =
+ {
+ {KCMGL_SIZE(frame_buffer_props), 0, frame_buffer_props, i18n("Frame buffer properties"), NULL},
+ {KCMGL_SIZE(various_limits), 0, texture_limits, i18n("Texturing"), NULL},
+ {KCMGL_SIZE(various_limits), 0, various_limits, i18n("Various limits"), NULL},
+ {KCMGL_SIZE(float_limits), 0, float_limits, i18n("Points and lines"), NULL},
+ {KCMGL_SIZE(stack_depth), 0, stack_depth, i18n("Stack depth limits"), NULL},
+#ifdef GL_ARB_vertex_program
+ {KCMGL_SIZE(arb_vp), GL_VERTEX_PROGRAM_ARB, arb_vp, "ARB_vertex_program", "GL_ARB_vertex_program"},
+#endif
+#ifdef GL_ARB_fragment_program
+ {KCMGL_SIZE(arb_fp), GL_FRAGMENT_PROGRAM_ARB, arb_fp, "ARB_fragment_program", "GL_ARB_fragment_program"},
+#endif
+#ifdef GL_ARB_vertex_shader
+ {KCMGL_SIZE(arb_vs), 0, arb_vs, "ARB_vertex_shader", "GL_ARB_vertex_shader"},
+#endif
+#ifdef GL_ARB_fragment_shader
+ {KCMGL_SIZE(arb_fs), 0, arb_fs, "ARB_fragment_shader", "GL_ARB_fragment_shader"},
+#endif
+ };
+
+#if defined(GLX_ARB_get_proc_address) && defined(PFNGLGETPROGRAMIVARBPROC)
+ if (GetProcAddress && strstr(glExtensions, "GL_ARB_vertex_program"))
+ kcm_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) glXGetProcAddressARB((const GLubyte *)"glGetProgramivARB");
+#endif
+
+ for (uint i = 0; i<KCMGL_SIZE(groups); i++) {
+ if (groups[i].ext && !strstr(glExtensions, groups[i].ext)) continue;
+
+ if (l2) l2 = new QListViewItem(l1, l2, groups[i].descr);
+ else l2 = new QListViewItem(l1, groups[i].descr);
+ l3 = NULL;
+ const struct token_name *cur_token;
+ for (cur_token = groups[i].group; cur_token->type; cur_token++) {
+
+ bool tfloat = cur_token->type & KCMGL_FLOAT;
+ int count = KCMGL_COUNT_MASK(cur_token->type);
+ GLint max[2]={0,0};
+ GLfloat fmax[2]={0.0,0.0};
+
+#if defined(PFNGLGETPROGRAMIVARBPROC) && defined(GL_ARB_vertex_program)
+ bool tprog = cur_token->type & KCMGL_PROG;
+ if (tprog && kcm_glGetProgramivARB)
+ kcm_glGetProgramivARB(groups[i].type, cur_token->token, max);
+ else
+#endif
+ if (tfloat) glGetFloatv(cur_token->token, fmax);
+ else glGetIntegerv(cur_token->token, max);
+
+ if (glGetError() == GL_NONE) {
+ QString s;
+ if (!tfloat && count == 1) s = QString::number(max[0]); else
+ if (!tfloat && count == 2) s = QString("%1, %2").arg(max[0]).arg(max[1]); else
+ if (tfloat && count == 2) s = QString("%1 - %2").arg(fmax[0],0,'f',6).arg(fmax[1],0,'f',6); else
+ if (tfloat && count == 1) s = QString::number(fmax[0],'f',6);
+ if (l3) l3 = new QListViewItem(l2, l3, cur_token->name, s);
+ else l3 = new QListViewItem(l2, cur_token->name, s);
+
+ }
+ }
+
+ }
+}
+
+
+static QListViewItem *print_screen_info(QListViewItem *l1, QListViewItem *after)
+{
+ QListViewItem *l2 = NULL, *l3 = NULL;
+
+ if (after) l1= new QListViewItem(l1,after,IsDirect ? i18n("Direct Rendering") : i18n("Indirect Rendering"));
+ else l1= new QListViewItem(l1,IsDirect ? i18n("Direct Rendering") : i18n("Indirect Rendering"));
+ if (IsDirect)
+ if (get_dri_device()) {
+ l2 = new QListViewItem(l1, i18n("3D Accelerator"));
+ l2->setOpen(true);
+ l3 = new QListViewItem(l2, l3, i18n("Vendor"), dri_info.vendor);
+ l3 = new QListViewItem(l2, l3, i18n("Device"), dri_info.device);
+ l3 = new QListViewItem(l2, l3, i18n("Subvendor"), dri_info.subvendor);
+ l3 = new QListViewItem(l2, l3, i18n("Revision"), dri_info.rev);
+ }
+ else l2=new QListViewItem(l1, l2, i18n("3D Accelerator"),i18n("unknown"));
+ if (l2) l2 = new QListViewItem(l1, l2, i18n("Driver"));
+ else l2 = new QListViewItem(l1, i18n("Driver"));
+ l2->setOpen(true);
+
+ l3 = new QListViewItem(l2, i18n("Vendor"),gli.glVendor);
+ l3 = new QListViewItem(l2, l3, i18n("Renderer"), gli.glRenderer);
+ l3 = new QListViewItem(l2, l3, i18n("OpenGL version"), gli.glVersion);
+
+ if (IsDirect) {
+ if (!dri_info.module) dri_info.module = i18n("unknown");
+ l3 = new QListViewItem(l2, l3, i18n("Kernel module"), dri_info.module);
+ }
+
+ l3 = new QListViewItem(l2, l3, i18n("OpenGL extensions"));
+ print_extension_list(gli.glExtensions,l3);
+
+ l3 = new QListViewItem(l2, l3, i18n("Implementation specific"));
+ print_limits(l3, gli.glExtensions, strstr(gli.clientExtensions, "GLX_ARB_get_proc_address") != NULL);
+
+ return l1;
+}
+
+void print_glx_glu(QListViewItem *l1, QListViewItem *l2)
+{
+ QListViewItem *l3;
+
+ l2=new QListViewItem(l1, l2, i18n("GLX"));
+ l3 = new QListViewItem(l2, i18n("server GLX vendor"),gli.serverVendor);
+ l3 = new QListViewItem(l2, l3, i18n("server GLX version"),gli.serverVersion);
+ l3 = new QListViewItem(l2, l3, i18n("server GLX extensions"));
+ print_extension_list(gli.serverExtensions,l3);
+
+ l3 = new QListViewItem(l2, l3, i18n("client GLX vendor"),gli.clientVendor);
+ l3 = new QListViewItem(l2, l3, i18n("client GLX version"),gli.clientVersion);
+ l3 = new QListViewItem(l2, l3, i18n("client GLX extensions"));
+ print_extension_list(gli.clientExtensions,l3);
+ l3 = new QListViewItem(l2, l3, i18n("GLX extensions"));
+ print_extension_list(gli.glxExtensions,l3);
+
+#ifdef KCMGL_DO_GLU
+ l2 = new QListViewItem(l1, l2, i18n("GLU"));
+ l3 = new QListViewItem(l2, i18n("GLU version"), gli.gluVersion);
+ l3 = new QListViewItem(l2, l3, i18n("GLU extensions"));
+ print_extension_list(gli.gluExtensions,l3);
+#endif
+
+}
+
+static QListViewItem *get_gl_info(Display *dpy, int scrnum, Bool allowDirect,QListViewItem *l1, QListViewItem *after)
+{
+ Window win;
+ int attribSingle[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+ int attribDouble[] = {
+ GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER,
+ None };
+
+ XSetWindowAttributes attr;
+ unsigned long mask;
+ Window root;
+ GLXContext ctx;
+ XVisualInfo *visinfo;
+ int width = 100, height = 100;
+ QListViewItem *result = after;
+
+ root = RootWindow(dpy, scrnum);
+
+ visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
+ if (!visinfo) {
+ visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
+ if (!visinfo) {
+ kdDebug() << "Error: couldn't find RGB GLX visual\n";
+ return result;
+ }
+ }
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+ win = XCreateWindow(dpy, root, 0, 0, width, height,
+ 0, visinfo->depth, InputOutput,
+ visinfo->visual, mask, &attr);
+
+ ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
+ if (!ctx) {
+ kdDebug() << "Error: glXCreateContext failed\n";
+ XDestroyWindow(dpy, win);
+ return result;
+ }
+
+ if (glXMakeCurrent(dpy, win, ctx)) {
+ gli.serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
+ gli.serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
+ gli.serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
+ gli.clientVendor = glXGetClientString(dpy, GLX_VENDOR);
+ gli.clientVersion = glXGetClientString(dpy, GLX_VERSION);
+ gli.clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
+ gli.glxExtensions = glXQueryExtensionsString(dpy, scrnum);
+ gli.glVendor = (const char *) glGetString(GL_VENDOR);
+ gli.glRenderer = (const char *) glGetString(GL_RENDERER);
+ gli.glVersion = (const char *) glGetString(GL_VERSION);
+ gli.glExtensions = (const char *) glGetString(GL_EXTENSIONS);
+ gli.displayName = NULL;
+#ifdef KCMGL_DO_GLU
+ gli.gluVersion = (const char *) gluGetString(GLU_VERSION);
+ gli.gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS);
+#endif
+ IsDirect = glXIsDirect(dpy, ctx);
+
+ result = print_screen_info(l1, after);
+ }
+ else {
+ kdDebug() << "Error: glXMakeCurrent failed\n";
+ }
+
+ glXDestroyContext(dpy, ctx);
+ XDestroyWindow(dpy, win);
+ return result;
+
+}
+
+
+static bool GetInfo_OpenGL_Generic( QListView *lBox )
+{
+ QListViewItem *l1, *l2 = NULL;
+
+ char *displayName = NULL;
+ Display *dpy;
+ int numScreens, scrnum;
+
+ dpy = XOpenDisplay(displayName);
+ if (!dpy) {
+// kdDebug() << "Error: unable to open display " << displayName << endl;
+ return false;
+ }
+
+ lBox->addColumn(i18n("Information") );
+ lBox->addColumn(i18n("Value") );
+
+ l1 = new QListViewItem(lBox, i18n("Name of the Display"), DisplayString(dpy));
+ l1->setOpen(true);
+ l1->setSelectable(false);
+ l1->setExpandable(false);
+
+ numScreens = ScreenCount(dpy);
+
+ scrnum = 0;
+#ifdef KCMGL_MANY_SCREENS
+ for (; scrnum < numScreens; scrnum++)
+#endif
+ {
+ mesa_hack(dpy, scrnum);
+
+ l2 = get_gl_info(dpy, scrnum, true, l1, l2);
+ if (l2) l2->setOpen(true);
+
+ if (IsDirect) l2 = get_gl_info(dpy, scrnum, false, l1, l2);
+
+// TODO print_visual_info(dpy, scrnum, mode);
+ }
+ if (l2)
+ print_glx_glu(l1, l2);
+ else
+ KMessageBox::error(0, i18n("Could not initialize OpenGL"));
+
+ XCloseDisplay(dpy);
+ return true;
+ }
+
+bool GetInfo_OpenGL(QListView * lBox)
+{
+ return GetInfo_OpenGL_Generic(lBox);
+}
+
+#endif /* INFO_OPENGL_AVAILABLE */
+