summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-12 21:06:48 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-12 21:06:48 -0800
commit62e3914fdaac08d83e07e0ac786de4c273a3fdb5 (patch)
treed8eb142e29179b6085f70686efe36d1da794fe5a
parentedd7bf5b8a4073387e4dad37269572ec4d1b6a59 (diff)
1.0-71671.0-7167
-rw-r--r--Makefile33
-rw-r--r--src/Makefile.inc6
-rw-r--r--src/command-line.c13
-rw-r--r--src/glxinfo.c460
-rw-r--r--src/glxinfo.h43
-rw-r--r--src/gtk+-2.x/Makefile.inc8
-rw-r--r--src/gtk+-2.x/ctkdevice.c9
-rw-r--r--src/gtk+-2.x/ctkevent.c34
-rw-r--r--src/gtk+-2.x/ctkframelock.c22
-rw-r--r--src/gtk+-2.x/ctkglx.c885
-rw-r--r--src/gtk+-2.x/ctkglx.h78
-rw-r--r--src/gtk+-2.x/ctkgvo.c38
-rw-r--r--src/gtk+-2.x/ctkhelp.c20
-rw-r--r--src/gtk+-2.x/ctkrandr.c653
-rw-r--r--src/gtk+-2.x/ctkrandr.h97
-rw-r--r--src/gtk+-2.x/ctkwindow.c21
-rw-r--r--src/libXNVCtrl/NVCtrl.c88
-rw-r--r--src/libXNVCtrl/NVCtrl.h15
-rw-r--r--src/libXNVCtrl/NVCtrlLib.h45
-rw-r--r--src/libXNVCtrl/libXNVCtrl.abin5568 -> 6624 bytes
-rw-r--r--src/libXNVCtrl/nv_control.h57
-rw-r--r--src/libXNVCtrlAttributes/Makefile.inc4
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributes.c92
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributes.h128
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c664
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h116
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c329
-rw-r--r--src/msg.c91
-rw-r--r--src/msg.h43
-rw-r--r--src/query-assign.c5
30 files changed, 3950 insertions, 147 deletions
diff --git a/Makefile b/Makefile
index 57c9f7d..7380793 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,7 @@
SHELL = /bin/sh
INSTALL = install -m 755
+BUILD_OS := $(shell uname)
ifndef CC
CC = gcc
@@ -51,10 +52,13 @@ ifndef PKG_CONFIG
PKG_CONFIG = pkg-config
endif
-ifndef X11R6_DIR
- X11R6_DIR = /usr/X11R6
+ifndef X11R6_LIB_DIR
+ X11R6_LIB_DIR = /usr/X11R6/lib
endif
+ifndef X11R6_INC_DIR
+ X11R6_INC_DIR = /usr/X11R6/include
+endif
# the NVDEBUG environment variable controls whether we build debug or retail
@@ -78,15 +82,18 @@ endif
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
-X11R6_LIB_DIR = $(X11R6_DIR)/lib
-X11R6_INC_DIR = $(X11R6_DIR)/include
-
X11R6_CFLAGS = -I $(X11R6_INC_DIR)
GTK_CFLAGS := $(shell $(PKG_CONFIG) --cflags gtk+-2.0)
GTK_LDFLAGS := $(shell $(PKG_CONFIG) --libs gtk+-2.0)
-X11R6_LIBS := -L $(X11R6_LIB_DIR) -Wl,-Bstatic -lXxf86vm -lXv -Wl,-Bdynamic -lX11 -lXext
+ifeq ($(BUILD_OS),SunOS)
+LIBXV = -lXv
+else
+LIBXV = -Wl,-Bstatic -lXv -Wl,-Bdynamic
+endif
+
+X11R6_LIBS := -L $(X11R6_LIB_DIR) -Wl,-Bstatic -lXxf86vm -Wl,-Bdynamic $(LIBXV) -lX11 -lXext
XNVCTRL_LIB := src/libXNVCtrl/libXNVCtrl.a
@@ -152,6 +159,12 @@ DEPS_DIR = .deps
OBJS := $(patsubst %.c,$(OBJS_DIR)/%.o,$(ALL_SRC))
DEPS := $(patsubst %.c,$(DEPS_DIR)/%.d,$(SRC))
+# default echo within SunOS sh does not have -n option. Use /usr/ucb/echo instead.
+ifeq ($(BUILD_OS),SunOS)
+ECHO=/usr/ucb/echo
+else
+ECHO=echo
+endif
# and now, the build rules:
@@ -176,10 +189,10 @@ $(DEPS_DIR)/%.d: %.c
$(STAMP_C): $(filter-out $(OBJS_DIR)/$(STAMP_C:.c=.o), $(OBJS))
@ rm -f $@
- @ echo -n "const char NV_ID[] = \"nvidia id: " >> $@
- @ echo -n "$(NVIDIA_SETTINGS): " >> $@
- @ echo -n "version $(NVIDIA_SETTINGS_VERSION) " >> $@
- @ echo -n "($(shell whoami)@$(shell hostname)) " >> $@
+ @ $(ECHO) -n "const char NV_ID[] = \"nvidia id: " >> $@
+ @ $(ECHO) -n "$(NVIDIA_SETTINGS): " >> $@
+ @ $(ECHO) -n "version $(NVIDIA_SETTINGS_VERSION) " >> $@
+ @ $(ECHO) -n "($(shell whoami)@$(shell hostname)) " >> $@
@ echo "$(shell date)\";" >> $@
@ echo "const char *pNV_ID = NV_ID + 11;" >> $@
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 0331d91..7c3e745 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -32,7 +32,8 @@ SRC += \
nvidia-settings.c \
parse.c \
query-assign.c \
- nvgetopt.c
+ nvgetopt.c \
+ glxinfo.c
EXTRA_DIST += \
command-line.h \
@@ -40,4 +41,5 @@ EXTRA_DIST += \
msg.h \
parse.h \
query-assign.h \
- nvgetopt.h
+ nvgetopt.h \
+ glxinfo.h
diff --git a/src/command-line.c b/src/command-line.c
index 95cc14b..fe262ba 100644
--- a/src/command-line.c
+++ b/src/command-line.c
@@ -34,6 +34,9 @@
#include "query-assign.h"
#include "msg.h"
#include "nvgetopt.h"
+#include "glxinfo.h"
+
+#include "NvCtrlAttributes.h"
#define TAB " "
@@ -78,6 +81,9 @@ static void print_version(void)
* flags - bitmask; possible values are NVGETOPT_HAS_ARGUMENT and
* NVGETOPT_IS_BOOLEAN
*
+ * description function - function to call to display description
+ * through nv_msg()
+ *
* description - text for use by print_help() to describe the option
*/
@@ -107,6 +113,9 @@ static const NVGetoptOption __options[] = {
{ "assign", 'a', NVGETOPT_HAS_ARGUMENT, print_assign_help, NULL },
{ "query", 'q', NVGETOPT_HAS_ARGUMENT, print_query_help, NULL },
+
+ { "glxinfo", 'g', 0, NULL,
+ "Print GLX Information for the X display and exit." },
{ NULL, 0, 0, 0 },
};
@@ -216,9 +225,6 @@ void print_help(void)
} /* print_help() */
-
-
-
/*
* parse_command_line() - malloc an Options structure, initialize it
* with defaults, and fill in any pertinent data from the commandline
@@ -272,6 +278,7 @@ Options *parse_command_line(int argc, char *argv[], char *dpy)
op->num_queries++;
break;
case CONFIG_FILE_OPTION: op->config = strval; break;
+ case 'g': print_glxinfo(NULL); exit(0); break;
default:
nv_error_msg("Invalid commandline, please run `%s --help` "
"for usage information.\n", argv[0]);
diff --git a/src/glxinfo.c b/src/glxinfo.c
new file mode 100644
index 0000000..c252d25
--- /dev/null
+++ b/src/glxinfo.c
@@ -0,0 +1,460 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "NvCtrlAttributes.h"
+#include "query-assign.h" /* CtrlHandles */
+#include "msg.h"
+
+#include <GL/glx.h> /* GLX #defines */
+
+
+/*
+ * print_extension_list() - Formats OpenGL/GLX extension strings
+ * to contain commas and returns a pointer to the formated string.
+ * The user is responsible for freeing this buffer.
+ *
+ * If there is an error or there is not enough memory to create
+ * the buffer, NULL is returned.
+ *
+ */
+
+static char *
+format_extension_list(const char *ext)
+{
+ int i;
+ char * extTmp = NULL; /* Actual string to print */
+
+
+ if ( !ext || !ext[0] )
+ return NULL;
+
+ /* Count number of extensions (to get number of commas needed) */
+ i = 0;
+ extTmp = (char *)ext;
+ while ( *extTmp != '\0' ) {
+ if ( *extTmp == ' ' ) {
+ i++;
+ }
+ extTmp++;
+ }
+
+ /*
+ * Allocate buffer that will hold the extension string with
+ * commas in it
+ */
+ extTmp = (char *) malloc( (strlen(ext) +i +1) *sizeof(char) );
+ if ( extTmp == NULL ) {
+ return NULL;
+ }
+
+ /* Copy extension string to buffer, adding commas */
+ i = 0;
+ while ( *ext != '\0' && *ext != '\n' ) {
+ if ( *ext == ' ' ) {
+ extTmp[i++] = ',';
+ }
+ extTmp[i++] = *ext;
+ ext++;
+ }
+ extTmp[i] = '\0';
+
+ /* Remove any trailing whitespace and commas */
+ while ( extTmp[ strlen(extTmp)-1 ] == ' ' ||
+ extTmp[ strlen(extTmp)-1 ] == ',' ) {
+ extTmp[ strlen(extTmp)-1 ] = '\0';
+ }
+
+ return extTmp;
+} /* format_extension_list() */
+
+
+/*
+ * print_fbconfig_attribs() & helper functions -
+ * Prints a table of fbconfig attributes
+ *
+ * NOTE: Only support FBconfig for GLX v1.3+
+ *
+ */
+
+#ifdef GLX_VERSION_1_3
+
+const char *
+render_type_abbrev(int rend_type)
+{
+ switch (rend_type) {
+ case GLX_RGBA_BIT:
+ return "rgb";
+ case GLX_COLOR_INDEX_BIT:
+ return "ci";
+ case (GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT):
+ return "any";
+ default:
+ return ".";
+ }
+}
+
+
+const char *
+transparent_type_abbrev(int trans_type)
+{
+ switch (trans_type) {
+ case GLX_NONE:
+ return ".";
+ case GLX_TRANSPARENT_RGB:
+ return "rg";
+ case GLX_TRANSPARENT_INDEX:
+ return "ci";
+ default:
+ return ".";
+ }
+}
+
+
+const char *
+caveat_abbrev(int caveat)
+{
+ if (caveat == GLX_NONE_EXT || caveat == 0)
+ return(".");
+ else if (caveat == GLX_SLOW_VISUAL_EXT)
+ return("slo");
+ else if (caveat == GLX_NON_CONFORMANT_VISUAL_EXT)
+ return("NoC");
+ else
+ return(".");
+}
+
+
+static void
+print_fbconfig_attribs(GLXFBConfigAttr *fbca)
+{
+ int i; /* Iterator */
+
+
+ if ( fbca == NULL ) {
+ return;
+ }
+
+ printf("-fc- -vi- buf lv rgb d s colorbuffer ax dp st "
+ "accumbuffer -ms- cav -----pbuffer----- ---transparent----\n");
+ printf(" id id siz l ci b t r g b a bf th en "
+ "r g b a ns b eat widt hght max-pxs typ r g b a i\n");
+ printf("----------------------------------------------"
+ "---------------------------------------------------------\n");
+
+ i = 0;
+ while ( fbca[i].fbconfig_id != 0 ) {
+
+ printf("0x%2.2x ", fbca[i].fbconfig_id);
+ if ( fbca[i].visual_id ) {
+ printf("0x%2.2x ", fbca[i].visual_id);
+ } else {
+ printf(" . ");
+ }
+ printf("%3d %2d %3.3s %1c %1c ",
+ fbca[i].buffer_size,
+ fbca[i].level,
+ render_type_abbrev(fbca[i].render_type),
+ fbca[i].doublebuffer ? 'y' : '.',
+ fbca[i].stereo ? 'y' : '.'
+ );
+ printf("%2d %2d %2d %2d %2d %2d %2d ",
+ fbca[i].red_size,
+ fbca[i].green_size,
+ fbca[i].blue_size,
+ fbca[i].alpha_size,
+ fbca[i].aux_buffers,
+ fbca[i].depth_size,
+ fbca[i].stencil_size
+ );
+ printf("%2d %2d %2d %2d ",
+ fbca[i].accum_red_size,
+ fbca[i].accum_green_size,
+ fbca[i].accum_blue_size,
+ fbca[i].accum_alpha_size
+ );
+ if ( fbca[i].multi_sample_valid == 1 ) {
+ printf("%2d %1d ",
+ fbca[i].multi_samples,
+ fbca[i].multi_sample_buffers
+ );
+ } else {
+ printf(" . . ");
+ }
+ printf("%3.3s %4x %4x %7x %3.3s %2d %2d %2d %2d %2d\n",
+ caveat_abbrev(fbca[i].config_caveat),
+ fbca[i].pbuffer_width,
+ fbca[i].pbuffer_height,
+ fbca[i].pbuffer_max,
+ transparent_type_abbrev(fbca[i].transparent_type),
+ fbca[i].transparent_red_value,
+ fbca[i].transparent_green_value,
+ fbca[i].transparent_blue_value,
+ fbca[i].transparent_alpha_value,
+ fbca[i].transparent_index_value
+ );
+
+ i++;
+ } /* Done printing FBConfig attributes for FBConfig */
+
+} /* print_fbconfig_attribs() */
+
+#endif /* GLX_VERSION_1_3 */
+
+
+/*
+ * print_glxinfo() - prints information about glx
+ *
+ */
+
+#define TAB " "
+
+#define SAFE_FREE(m) \
+if ( (m) != NULL ) { \
+ free( m ); \
+ m = NULL; \
+}
+
+#define NULL_TO_EMPTY(s) \
+((s)!=NULL)?(s):""
+
+void print_glxinfo(const char *display_name)
+{
+ int screen;
+ CtrlHandles *h;
+ ReturnStatus status = NvCtrlSuccess;
+
+ char *direct_rendering = NULL;
+ char *glx_extensions = NULL;
+ char *server_vendor = NULL;
+ char *server_version = NULL;
+ char *server_extensions = NULL;
+ char *client_vendor = NULL;
+ char *client_version = NULL;
+ char *client_extensions = NULL;
+ char *opengl_vendor = NULL;
+ char *opengl_renderer = NULL;
+ char *opengl_version = NULL;
+ char *opengl_extensions = NULL;
+
+ GLXFBConfigAttr *fbconfig_attribs = NULL;
+
+ char *formated_ext_str = NULL;
+
+
+ h = nv_alloc_ctrl_handles(display_name);
+ if ( h == NULL ) {
+ return;
+ }
+
+ /* Print information for each screen */
+ for (screen = 0; screen < h->num_screens; screen++) {
+
+ /* No screen, move on */
+ if ( !h->h[screen] ) continue;
+
+ nv_msg(NULL, "GLX Information for %s:", h->screen_names[screen]);
+
+ /* Get GLX information */
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_DIRECT_RENDERING,
+ &direct_rendering);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_GLX_EXTENSIONS,
+ &glx_extensions);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ if ( glx_extensions != NULL ) {
+ formated_ext_str = format_extension_list(glx_extensions);
+ if ( formated_ext_str != NULL ) {
+ free(glx_extensions);
+ glx_extensions = formated_ext_str;
+ }
+ }
+ /* Get server GLX information */
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_SERVER_VENDOR,
+ &server_vendor);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_SERVER_VERSION,
+ &server_version);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_SERVER_EXTENSIONS,
+ &server_extensions);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ if ( server_extensions != NULL ) {
+ formated_ext_str = format_extension_list(server_extensions);
+ if ( formated_ext_str != NULL ) {
+ free(server_extensions);
+ server_extensions = formated_ext_str;
+ }
+ }
+ /* Get client GLX information */
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_CLIENT_VENDOR,
+ &client_vendor);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_CLIENT_VERSION,
+ &client_version);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_CLIENT_EXTENSIONS,
+ &client_extensions);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ if ( client_extensions != NULL ) {
+ formated_ext_str = format_extension_list(client_extensions);
+ if ( formated_ext_str != NULL ) {
+ free(client_extensions);
+ client_extensions = formated_ext_str;
+ }
+ }
+ /* Get OpenGL information */
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_OPENGL_VENDOR,
+ &opengl_vendor);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_OPENGL_RENDERER,
+ &opengl_renderer);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_OPENGL_VERSION,
+ &opengl_version);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ status = NvCtrlGetStringAttribute(h->h[screen],
+ NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS,
+ &opengl_extensions);
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+ if ( opengl_extensions != NULL ) {
+ formated_ext_str = format_extension_list(opengl_extensions);
+ if ( formated_ext_str != NULL ) {
+ free(opengl_extensions);
+ opengl_extensions = formated_ext_str;
+ }
+ }
+
+ /* Get FBConfig information */
+ status = NvCtrlGetVoidAttribute(h->h[screen],
+ NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS,
+ (void *)(&fbconfig_attribs));
+ if ( status != NvCtrlSuccess &&
+ status != NvCtrlNoAttribute ) { goto finish; }
+
+ /* Print results */
+ nv_msg(TAB, "direct rendering: %s", NULL_TO_EMPTY(direct_rendering));
+ nv_msg(TAB, "GLX extensions:");
+ nv_msg(" ", NULL_TO_EMPTY(glx_extensions));
+ nv_msg(" ", "\n");
+ nv_msg(TAB, "server glx vendor string: %s",
+ NULL_TO_EMPTY(server_vendor));
+ nv_msg(TAB, "server glx version string: %s",
+ NULL_TO_EMPTY(server_version));
+ nv_msg(TAB, "server glx extensions:");
+ nv_msg(" ", NULL_TO_EMPTY(server_extensions));
+ nv_msg(" ", "\n");
+ nv_msg(TAB, "client glx vendor string: %s",
+ NULL_TO_EMPTY(client_vendor));
+ nv_msg(TAB, "client glx version string: %s",
+ NULL_TO_EMPTY(client_version));
+ nv_msg(TAB, "client glx extensions:");
+ nv_msg(" ", NULL_TO_EMPTY(client_extensions));
+ nv_msg(" ", "\n");
+ nv_msg(TAB, "OpenGL vendor string: %s",
+ NULL_TO_EMPTY(opengl_vendor));
+ nv_msg(TAB, "OpenGL renderer string: %s",
+ NULL_TO_EMPTY(opengl_renderer));
+ nv_msg(TAB, "OpenGL version string: %s",
+ NULL_TO_EMPTY(opengl_version));
+ nv_msg(TAB, "OpenGL extensions:");
+ nv_msg(" ", NULL_TO_EMPTY(opengl_extensions));
+#ifdef GLX_VERSION_1_3
+ if ( fbconfig_attribs != NULL ) {
+ nv_msg(" ", "\n");
+ print_fbconfig_attribs(fbconfig_attribs);
+ }
+#endif
+ fflush(stdout);
+
+ /* Free memory used */
+ SAFE_FREE(server_vendor);
+ SAFE_FREE(server_version);
+ SAFE_FREE(server_extensions);
+ SAFE_FREE(client_vendor);
+ SAFE_FREE(client_version);
+ SAFE_FREE(client_extensions);
+ SAFE_FREE(direct_rendering);
+ SAFE_FREE(glx_extensions);
+ SAFE_FREE(opengl_vendor);
+ SAFE_FREE(opengl_renderer);
+ SAFE_FREE(opengl_version);
+ SAFE_FREE(opengl_extensions);
+ SAFE_FREE(fbconfig_attribs);
+
+ } /* Done looking at all screens */
+
+
+ /* Fall through */
+ finish:
+ if ( status == NvCtrlError ) {
+ nv_error_msg("Error fetching GLX Information: %s",
+ NvCtrlAttributesStrError(status) );
+ }
+
+ /* Free any leftover memory used */
+ SAFE_FREE(server_vendor);
+ SAFE_FREE(server_version);
+ SAFE_FREE(server_extensions);
+ SAFE_FREE(client_vendor);
+ SAFE_FREE(client_version);
+ SAFE_FREE(client_extensions);
+ SAFE_FREE(direct_rendering);
+ SAFE_FREE(glx_extensions);
+ SAFE_FREE(opengl_vendor);
+ SAFE_FREE(opengl_renderer);
+ SAFE_FREE(opengl_version);
+ SAFE_FREE(opengl_extensions);
+ SAFE_FREE(fbconfig_attribs);
+
+ nv_free_ctrl_handles(h);
+
+} /* print_glxinfo() */
diff --git a/src/glxinfo.h b/src/glxinfo.h
new file mode 100644
index 0000000..fd8bca2
--- /dev/null
+++ b/src/glxinfo.h
@@ -0,0 +1,43 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __GLXINFO_H__
+#define __GLXINFO_H__
+
+#include <GL/glx.h>
+
+
+#ifndef GLX_VERSION_1_3
+#warning GLX version 1.3 not defined, will not show FBConfig table!
+#else
+const char * render_type_abbrev(int rend_type);
+const char * transparent_type_abbrev(int trans_type);
+const char * caveat_abbrev(int caveat);
+#endif
+
+
+void print_glxinfo(const char *display_name);
+
+
+#endif /* __GLXINFO_H__ */
diff --git a/src/gtk+-2.x/Makefile.inc b/src/gtk+-2.x/Makefile.inc
index c649a4c..0501eb3 100644
--- a/src/gtk+-2.x/Makefile.inc
+++ b/src/gtk+-2.x/Makefile.inc
@@ -39,6 +39,7 @@ SRC += \
ctkevent.c \
ctkwindow.c \
ctkopengl.c \
+ ctkglx.c \
ctkdevice.c \
ctkhelp.c \
ctkimagesliders.c \
@@ -48,7 +49,8 @@ SRC += \
ctkdisplaydevice-dfp.c \
ctkthermal.c \
ctkgvo.c \
- ctkdropdownmenu.c
+ ctkdropdownmenu.c \
+ ctkrandr.c
EXTRA_DIST += \
@@ -65,6 +67,7 @@ EXTRA_DIST += \
ctkevent.h \
ctkwindow.h \
ctkopengl.h \
+ ctkglx.h \
ctkdevice.h \
ctkhelp.h \
ctkimagesliders.h \
@@ -75,5 +78,6 @@ EXTRA_DIST += \
ctkconstants.h \
ctkthermal.h \
ctkgvo.h \
- ctkdropdownmenu.h
+ ctkdropdownmenu.h \
+ ctkrandr.h
diff --git a/src/gtk+-2.x/ctkdevice.c b/src/gtk+-2.x/ctkdevice.c
index d87cb3e..ec0bb03 100644
--- a/src/gtk+-2.x/ctkdevice.c
+++ b/src/gtk+-2.x/ctkdevice.c
@@ -148,7 +148,8 @@ GtkWidget* ctk_device_new(
os = NULL;
if (ret == NvCtrlSuccess) {
if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) os = "Linux";
- if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD";
+ else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD";
+ else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) os = "SunOS";
}
if (!os) os = __unknown;
@@ -198,8 +199,12 @@ GtkWidget* ctk_device_new(
if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) {
img = &big_banner_penguin_image;
- } else {
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) {
img = &big_banner_bsd_image;
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) {
+ img = &big_banner_penguin_image; /* XXX To be replaced with Sun Logo */
+ } else {
+ img = &big_banner_penguin_image; /* Should never get here */
}
image_buffer = decompress_image_data(img);
diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c
index f64ecdb..5eb49e5 100644
--- a/src/gtk+-2.x/ctkevent.c
+++ b/src/gtk+-2.x/ctkevent.c
@@ -30,6 +30,10 @@
*/
#include <gtk/gtk.h>
+
+#include <X11/Xlib.h> /* Xrandr */
+#include <X11/extensions/Xrandr.h> /* Xrandr */
+
#include "ctkevent.h"
#include "NVCtrlLib.h"
@@ -45,11 +49,13 @@ typedef struct {
Display *dpy;
GPollFD event_poll_fd;
int event_base;
+ int randr_event_base;
CtkEvent *ctk_event;
} CtkEventSource;
static guint signals[NV_CTRL_LAST_ATTRIBUTE + 1];
+static guint signal_RRScreenChangeNotify;
@@ -76,7 +82,7 @@ GType ctk_event_get_type(void)
return ctk_event_type;
-} /* ctk_window_get_type() */
+} /* ctk_event_get_type() */
static void ctk_event_class_init(CtkEventClass *ctk_event_class)
@@ -195,6 +201,16 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
#warning "There are attributes that do not emit signals!"
#endif
+
+ /* Make XRandR signal */
+ signal_RRScreenChangeNotify =
+ g_signal_new("CTK_EVENT_RRScreenChangeNotify",
+ G_OBJECT_CLASS_TYPE(ctk_event_class),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE, 1, G_TYPE_POINTER);
+
+
} /* ctk_event_class_init */
@@ -234,6 +250,7 @@ GtkObject *ctk_event_new (NvCtrlAttributeHandle *handle)
event_source->event_poll_fd.fd = ConnectionNumber(dpy);
event_source->event_poll_fd.events = G_IO_IN;
event_source->event_base = NvCtrlGetEventBase(handle);
+ event_source->randr_event_base = NvCtrlGetXrandrEventBase(handle);
event_source->ctk_event = ctk_event;
/* add the input source to the glib main loop */
@@ -242,7 +259,8 @@ GtkObject *ctk_event_new (NvCtrlAttributeHandle *handle)
g_source_attach(source, NULL);
return GTK_OBJECT(ctk_event);
-}
+
+} /* ctk_event_new() */
static gboolean ctk_event_prepare(GSource *source, gint *timeout)
@@ -312,6 +330,16 @@ static gboolean ctk_event_dispatch(GSource *source,
0, &event_struct);
}
}
+
+ /*
+ * Also handle XRandR events.
+ */
+ if (event.type ==
+ (event_source->randr_event_base + RRScreenChangeNotify)) {
+ g_signal_emit(event_source->ctk_event, signal_RRScreenChangeNotify,
+ 0, &event);
+ }
return TRUE;
-}
+
+} /* ctk_event_dispatch() */
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index 6a0b9ca..1b336fb 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -1330,13 +1330,19 @@ static void polarity_toggled(GtkCellRendererToggle *cell,
enabled ^= 1;
- /* don't allow the user to turn off the rising edge */
-
- if (mask == NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE) enabled = TRUE;
-
if (enabled) polarity |= mask;
else polarity &= ~mask;
+
+ /* if the last bit was turned off, turn back on the other bit */
+
+ if (!polarity) {
+ if (mask == NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE)
+ polarity = NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE;
+ if (mask == NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE)
+ polarity = NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE;
+ }
+
gtk_list_store_set(ctk_framelock->list_store, &iter,
COLUMN_POLARITY, polarity, -1);
@@ -1348,6 +1354,9 @@ static void polarity_toggled(GtkCellRendererToggle *cell,
case NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE:
polarity_str = "rising";
break;
+ case NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE:
+ polarity_str = "falling";
+ break;
case NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES:
polarity_str = "rising and falling";
break;
@@ -2224,12 +2233,9 @@ static GtkWidget *create_error_msg_dialog(CtkFramelock *ctk_framelock)
static void error_msg(CtkFramelock *ctk_framelock, const gchar *fmt, ...)
{
- va_list ap;
gchar *msg;
- va_start(ap, fmt);
- msg = nv_build_vararg_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(msg, fmt);
gtk_label_set_line_wrap(GTK_LABEL(ctk_framelock->error_msg_label), TRUE);
gtk_label_set_use_markup(GTK_LABEL(ctk_framelock->error_msg_label), TRUE);
diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c
new file mode 100644
index 0000000..ebd2754
--- /dev/null
+++ b/src/gtk+-2.x/ctkglx.c
@@ -0,0 +1,885 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <gtk/gtk.h>
+#include <NvCtrlAttributes.h>
+
+#include "glx_banner.h"
+#include "ctkglx.h"
+#include "ctkconfig.h"
+#include "ctkhelp.h"
+
+#include <GL/glx.h> /* GLX #defines */
+
+
+
+/* Prototypes */
+
+static void ctk_glx_probe_info(GtkWidget *widget,
+ GtkObject *old_parent,
+ gpointer data);
+
+
+
+/* Number of FBConfigs attributes reported in gui */
+#define NUM_FBCONFIG_ATTRIBS 30
+
+
+/* FBConfig tooltips */
+static const char * __fid_help =
+ "fid (Frame buffer ID) - Frame Buffer Configuration ID.";
+static const char * __vid_help =
+ "vid (XVisual ID) - ID of the associated X Visual.";
+static const char * __bfs_help =
+ "bfs (buffer size) - Number of bits per color in the color buffer.";
+static const char * __lvl_help =
+ "lvl (level) - Frame buffer level. Level zero is the default frame "
+ "buffer. Positive levels are the overlay frame buffers (on top of the "
+ "default frame buffer). Negative levels are the underlay frame buffers "
+ "(under the default frame buffer).";
+static const char * __bf_help =
+ "bf (Buffer format) - Color buffer format. 'rgb' means each element of the "
+ "pixel buffer holds red, green, blue, and alpha values. 'ci' means each "
+ "element of the pixel buffer holds a color index value, where the actual "
+ "color is defined by a color map.";
+static const char * __db_help =
+ "db (Double buffer) - 'y' if the configuration has front and back color "
+ "buffers that are swappable. '-' if this is not supported.";
+static const char * __st_help =
+ "st (Stereo buffer) - 'y' if the configuration has left and right color "
+ "buffers that are rendered to in stereo. '-' if this is not supported";
+static const char * __rs_help =
+ "rs (Red size) - Number of bits used for ammount of red per color. "
+ "(Undefined for configurations that use color indexing.)";
+static const char * __gs_help =
+ "gs (Green size - Number of bits used for ammount of green per color. "
+ "(Undefined for configurations that use color indexing.)";
+static const char * __bs_help =
+ "bs (Blue size - Number of bits used for ammount of blue per color. "
+ "(Undefined for configurations that use color indexing.)";
+static const char * __as_help =
+ "as (Alpha size - Number of bits used for ammount of alpha per color. "
+ "(Undefined for configurations that use color indexing.)";
+static const char * __aux_help =
+ "aux (Auxillary buffers) - Number of available auxiliary color butters.";
+static const char * __dpt_help =
+ "dpt (Depth buffer size) - Number of bits per color in the depth buffer.";
+static const char * __stn_help =
+ "stn (Stencil size) - Number of bits per element in the stencil buffer.";
+static const char * __acr_help =
+ "acr (Accumulator red size) - Number of bits used for ammount of red per "
+ "color in the accumulator buffer.";
+static const char * __acg_help =
+ "acg (Accumulator green size) - Number of bits used for ammount of green "
+ "per color in the accumulator buffer.";
+static const char * __acb_help =
+ "acb (Accumulator blue size) - Number of bits used for ammount of blue per "
+ "color in the accumulator buffer.";
+static const char * __aca_help =
+ "aca (Accumulator alpha size) - Number of bits used for ammount of alpha "
+ "per color in the accumulator buffer.";
+static const char * __ms_help =
+ "ms (Multisample samples) - Number of samples per multisample.";
+static const char * __mb_help =
+ "mb (Multisample buffer count) - Number of multisample buffers.";
+static const char * __cav_help =
+ "cav (Caveats) - Caveats for this configuration. A frame buffer "
+ "configuration may have the following caveats: 'NonC' if it supports "
+ "any non-conformant visual extension. 'Slow' if it has reduced "
+ "preformance. '-' if it has no caveats.";
+static const char * __pbw_help =
+ "pbw (Pbuffer width) - Width of pbuffer (in hexadecimal).";
+static const char * __pbh_help =
+ "pbh (Pbuffer height) - Height of pbuffer (in hexadecimal).";
+static const char * __pbp_help =
+ "pbp (Pbuffer max pixels) - Max number of pixels in pbuffer (in "
+ "hexadecimal).";
+static const char * __trt_help =
+ "trt (Transparency type) - Type of transparency (RGBA or Index).";
+static const char * __trr_help =
+ "trr (Transparency red value) - Red value consided transparent.";
+static const char * __trg_help =
+ "trg (Transparency green value) - Green value consided transparent.";
+static const char * __trb_help =
+ "trb (Transparency blue value) - Blue value consided transparent.";
+static const char * __tra_help =
+ "tra (Transparency alpha value) - Alpha value consided transparent.";
+static const char * __tri_help =
+ "tri (Transparency index value) - Color index value consided transparent.";
+
+
+GType ctk_glx_get_type(void)
+{
+ static GType ctk_glx_type = 0;
+
+ if (!ctk_glx_type) {
+ static const GTypeInfo ctk_glx_info = {
+ sizeof (CtkGLXClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init, */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CtkGLX),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_glx_type = g_type_register_static (GTK_TYPE_VBOX,
+ "CtkGLX", &ctk_glx_info, 0);
+ }
+
+ return ctk_glx_type;
+} /* ctk_glx_get_type() */
+
+
+static void add_table_row(GtkWidget *table,
+ const gint row,
+ const gint value_alignment,
+ const gchar *name,
+ const gchar *value)
+{
+ GtkWidget *label;
+
+
+ label = gtk_label_new(name);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+
+ gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+
+ label = gtk_label_new(value);
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), value_alignment, 0.0f);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+
+ gtk_table_attach(GTK_TABLE(table), label, 1, 2, row, row + 1,
+ GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
+} /* add_table_row() */
+
+
+static void dummy_button_signal(GtkWidget *widget,
+ gpointer user_data)
+{
+ /* This is a dummy function so tooltips are enabled
+ * for the fbconfig table column titles
+ */
+}
+
+
+/* Creates the GLX information widget
+ *
+ * NOTE: The GLX information other than the FBConfigs will
+ * be setup when this page is hooked up and the "parent-set"
+ * signal is thrown. This will result in calling the
+ * ctk_glx_probe_info() function.
+ */
+GtkWidget* ctk_glx_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config, CtkEvent *ctk_event)
+{
+ GObject *object;
+ CtkGLX *ctk_glx;
+ GtkWidget *label;
+ GtkWidget *image;
+ GtkWidget *frame;
+ GtkWidget *hseparator;
+ GtkWidget *hbox, *hbox2;
+ GtkWidget *vbox, *vbox2;
+ GtkWidget *alignment;
+ GtkWidget *table;
+ GtkWidget *scrollWin;
+ GtkWidget *event; /* For setting the background color to white */
+ GdkColor color;
+
+ ReturnStatus ret;
+
+ guint8 *image_buffer = NULL;
+ const nv_image_t *img;
+
+ char * glx_info_str = NULL; /* Test if GLX supported */
+ GLXFBConfigAttr *fbconfig_attribs = NULL; /* FBConfig data */
+ int i; /* Iterator */
+
+ gchar *fbconfig_titles[NUM_FBCONFIG_ATTRIBS] = {
+ "fid", "vid", "bfs", "lvl",
+ "bf", "db", "st",
+ "rs", "gs", "bs", "as",
+ "aux", "dpt", "stn",
+ "acr", "acg", "acb", "aca",
+ "ms", "mb",
+ "cav",
+ "pbw", "pbh", "pbp",
+ "trt", "trr", "trg", "trb", "tra", "tri"
+ };
+
+ const char *fbconfig_tooltips[NUM_FBCONFIG_ATTRIBS] = {
+ __fid_help, __vid_help, __bfs_help, __lvl_help,
+ __bf_help, __db_help, __st_help,
+ __rs_help, __gs_help, __bs_help, __as_help,
+ __aux_help, __dpt_help, __stn_help,
+ __acr_help, __acg_help, __acb_help, __aca_help,
+ __ms_help, __mb_help,
+ __cav_help,
+ __pbw_help, __pbh_help, __pbp_help,
+ __trt_help, __trr_help, __trg_help,
+ __trb_help, __tra_help, __tri_help
+ };
+
+
+ /* Parse a white color (for background) */
+ gdk_color_parse ("white", &color);
+
+
+ /* Create the ctk glx object */
+ object = g_object_new(CTK_TYPE_GLX, NULL);
+ ctk_glx = CTK_GLX(object);
+
+
+ /* Cache the attribute handle */
+ ctk_glx->handle = handle;
+
+ /* Set container properties of the object */
+ ctk_glx->ctk_config = ctk_config;
+ gtk_box_set_spacing(GTK_BOX(ctk_glx), 10);
+
+ /* Image banner */
+ alignment = gtk_alignment_new(0, 0, 0, 0);
+ frame = gtk_frame_new(NULL);
+ img = &glx_banner_image;
+ image_buffer = decompress_image_data(img);
+ image = gtk_image_new_from_pixbuf
+ (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
+ FALSE, 8, img->width, img->height,
+ img->width * img->bytes_per_pixel,
+ free_decompressed_image, NULL));
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(frame), image);
+ gtk_container_add(GTK_CONTAINER(alignment), frame);
+ gtk_box_pack_start(GTK_BOX(ctk_glx), alignment, FALSE, FALSE, 0);
+
+
+ /* Determine if GLX is supported */
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_SERVER_VENDOR,
+ &glx_info_str );
+ free(glx_info_str);
+ if ( ret != NvCtrlSuccess ) {
+ goto fail_glx_not_supported;
+ }
+
+
+ /* Information Scroll Box */
+ scrollWin = gtk_scrolled_window_new(NULL, NULL);
+ hbox = gtk_hbox_new(FALSE, 0);
+ vbox = gtk_vbox_new(FALSE, 5);
+ event = gtk_event_box_new();
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollWin),
+ GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
+ gtk_box_pack_start(GTK_BOX(ctk_glx), scrollWin, TRUE, TRUE, 0);
+ gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &color);
+ gtk_container_add(GTK_CONTAINER(event), hbox);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin),
+ event);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
+ ctk_glx->glxinfo_vpane = vbox;
+
+
+ /* GLX 1.3 supports frame buffer configurations */
+#ifdef GLX_VERSION_1_3
+
+ /* Grab the FBConfigs */
+ ret = NvCtrlGetVoidAttribute(handle, NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS,
+ (void *)(&fbconfig_attribs));
+ if ( ret != NvCtrlSuccess ) {
+ goto fail_glx_not_supported;
+ }
+
+ /* Create clist in a scroll box */
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new("Frame Buffer Configurations");
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(ctk_glx), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ vbox = gtk_vbox_new(FALSE, 10);
+ vbox2 = gtk_vbox_new(FALSE, 10);
+ scrollWin = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrollWin),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ gtk_box_pack_start(GTK_BOX(ctk_glx), GTK_WIDGET(vbox), TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), scrollWin, TRUE, TRUE, 0);
+
+ /*
+ * NODE: Because clists have a hard time displaying tooltips in their
+ * column labels/buttons, we make the fbconfig table using a
+ * table widget.
+ */
+
+ /* Count number of rows */
+ i = 1;
+ if ( fbconfig_attribs ) {
+ while ( fbconfig_attribs[i].fbconfig_id != 0 ) { i++; }
+ }
+
+ table = gtk_table_new(i, NUM_FBCONFIG_ATTRIBS, FALSE);
+ event = gtk_event_box_new();
+ gtk_widget_modify_bg (table, GTK_STATE_NORMAL, &color);
+ gtk_container_add (GTK_CONTAINER(event), table);
+ gtk_widget_modify_bg(event, GTK_STATE_NORMAL, &color);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollWin),
+ event);
+
+ /* Generate table headings */
+ for ( i = 0; i < NUM_FBCONFIG_ATTRIBS; i++ ) {
+ GtkWidget * btn = gtk_button_new_with_label(fbconfig_titles[i]);
+ g_signal_connect(G_OBJECT(btn), "clicked",
+ G_CALLBACK(dummy_button_signal),
+ (gpointer) ctk_glx);
+ ctk_config_set_tooltip(ctk_config, btn, fbconfig_tooltips[i]);
+ gtk_table_attach(GTK_TABLE(table), btn, i, i+1, 0, 1,
+ GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
+ }
+
+ if ( fbconfig_attribs ) {
+
+ /* Populate FBConfig table */
+ i = 0;
+ while ( fbconfig_attribs[i].fbconfig_id != 0 ) {
+ char str[NUM_FBCONFIG_ATTRIBS + 1][16];
+ int cell = 0; /* Used for putting information into cells */
+
+ if ( fbconfig_attribs[i].fbconfig_id ) {
+ snprintf((char *) (&(str[cell++])), 16, "0x%02X",
+ fbconfig_attribs[i].fbconfig_id);
+ } else {
+ sprintf((char *) (&(str[cell++])),".");
+ }
+
+ if ( fbconfig_attribs[i].visual_id ) {
+ snprintf((char *) (&(str[cell++])), 16, "0x%02X",
+ fbconfig_attribs[i].visual_id);
+ } else {
+ sprintf((char *) (&(str[cell++])),".");
+ }
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].buffer_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].level);
+ snprintf((char *) (&(str[cell++])), 16, "%s",
+ render_type_abbrev(fbconfig_attribs[i].render_type) );
+ snprintf((char *) (&(str[cell++])), 16, "%c",
+ fbconfig_attribs[i].doublebuffer ? 'y' : '.');
+ snprintf((char *) (&(str[cell++])), 16, "%c",
+ fbconfig_attribs[i].stereo ? 'y' : '.');
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].red_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].green_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].blue_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].alpha_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].aux_buffers);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].depth_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].stencil_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].accum_red_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].accum_green_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].accum_blue_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].accum_alpha_size);
+ snprintf((char *) (&(str[cell++])), 16, "%2d",
+ fbconfig_attribs[i].multi_samples);
+ snprintf((char *) (&(str[cell++])), 16, "%1d",
+ fbconfig_attribs[i].multi_sample_buffers);
+ snprintf((char *) (&(str[cell++])), 16, "%s",
+ caveat_abbrev( fbconfig_attribs[i].config_caveat) );
+ snprintf((char *) (&(str[cell++])), 16, "0x%04X",
+ fbconfig_attribs[i].pbuffer_width);
+ snprintf((char *) (&(str[cell++])), 16, "0x%04X",
+ fbconfig_attribs[i].pbuffer_height);
+ snprintf((char *) (&(str[cell++])), 16, "0x%07X",
+ fbconfig_attribs[i].pbuffer_max);
+ snprintf((char *) (&(str[cell++])), 16, "%s",
+ transparent_type_abbrev(fbconfig_attribs[i].transparent_type));
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].transparent_red_value);
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].transparent_green_value);
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].transparent_blue_value);
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].transparent_alpha_value);
+ snprintf((char *) (&(str[cell++])), 16, "%3d",
+ fbconfig_attribs[i].transparent_index_value);
+ str[NUM_FBCONFIG_ATTRIBS][0] = '\0';
+
+ /* Populate row cells */
+ for ( cell = 0; cell < NUM_FBCONFIG_ATTRIBS ; cell++) {
+ GtkWidget * label = gtk_label_new( str[cell] );
+ gtk_table_attach(GTK_TABLE(table), label,
+ cell, cell+1,
+ i+1, i+2,
+ GTK_EXPAND, GTK_EXPAND, 3, 2);
+ }
+ i++;
+
+ } /* Done - Populating FBconfig table */
+
+
+ free(fbconfig_attribs);
+
+ } /* Done - FBConfigs exist */
+
+#endif /* GLX_VERSION_1_3 */
+
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+
+ /* Set to probe for GLX info when widget is swapped in */
+ ctk_glx->probe_handler_id =
+ g_signal_connect(G_OBJECT(ctk_glx), "parent-set",
+ G_CALLBACK(ctk_glx_probe_info),
+ (gpointer) ctk_glx);
+
+ return GTK_WIDGET(object);
+
+
+ /* Failure (no GLX) */
+ fail_glx_not_supported:
+ label = gtk_label_new("The OpenGL extension 'GLX' is not supported by\n"
+ "the X server or there was a problem retrieving\n"
+ "GLX information from the X server."
+ );
+ gdk_color_parse ("#FF0000", &color);
+ gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &color);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+
+ gtk_container_add(GTK_CONTAINER(ctk_glx), label);
+
+ /* Free memory that may have been allocated */
+ free(fbconfig_attribs);
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+ return GTK_WIDGET(object);
+
+} /* ctk_glx_new */
+
+
+
+
+/* Probes for GLX information and sets up the results
+ * in the GLX widget.
+ */
+static void ctk_glx_probe_info(GtkWidget *widget,
+ GtkObject *old_parent,
+ gpointer data)
+{
+ CtkGLX *ctk_glx = (CtkGLX *) data;
+
+ ReturnStatus ret;
+
+ char *direct_rendering = NULL;
+ char *glx_extensions = NULL;
+ char *server_vendor = NULL;
+ char *server_version = NULL;
+ char *server_extensions = NULL;
+ char *client_vendor = NULL;
+ char *client_version = NULL;
+ char *client_extensions = NULL;
+ char *opengl_vendor = NULL;
+ char *opengl_renderer = NULL;
+ char *opengl_version = NULL;
+ char *opengl_extensions = NULL;
+ char *ptr;
+
+ GtkWidget *hseparator;
+ GtkWidget *hbox, *hbox2;
+ GtkWidget *vbox, *vbox2;
+ GtkWidget *label;
+ GtkWidget *table;
+
+
+ /* Make sure the widget was initialized */
+ if ( !ctk_glx || !ctk_glx->glxinfo_vpane || !ctk_glx->probe_handler_id ) {
+ return;
+ }
+
+
+ /* Disconnect the handler */
+ g_signal_handler_disconnect(G_OBJECT(ctk_glx),
+ ctk_glx->probe_handler_id);
+ ctk_glx->probe_handler_id = 0;
+
+
+ /* Get GLX information */
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_DIRECT_RENDERING,
+ &direct_rendering);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_GLX_EXTENSIONS,
+ &glx_extensions);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+
+
+ /* Get Server GLX information */
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_SERVER_VENDOR,
+ &server_vendor);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_SERVER_VERSION,
+ &server_version);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_SERVER_EXTENSIONS,
+ &server_extensions);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+
+
+ /* Get Client GLX information */
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_CLIENT_VENDOR,
+ &client_vendor);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_CLIENT_VERSION,
+ &client_version);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_CLIENT_EXTENSIONS,
+ &client_extensions);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+
+
+ /* Get OpenGL information */
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_OPENGL_VENDOR,
+ &opengl_vendor);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_OPENGL_RENDERER,
+ &opengl_renderer);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_OPENGL_VERSION,
+ &opengl_version);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+ ret = NvCtrlGetStringAttribute(ctk_glx->handle,
+ NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS,
+ &opengl_extensions);
+ if ( ret != NvCtrlSuccess ) { goto done; }
+
+
+ /* Modify extension lists so they show only one name per line */
+ for ( ptr = glx_extensions; ptr != NULL && ptr[0] != '\0'; ptr++ ) {
+ if ( ptr[0] == ' ' ) ptr[0] = '\n';
+ }
+ for ( ptr = server_extensions; ptr != NULL && ptr[0] != '\0'; ptr++ ) {
+ if ( ptr[0] == ' ' ) ptr[0] = '\n';
+ }
+ for ( ptr = client_extensions; ptr != NULL && ptr[0] != '\0'; ptr++ ) {
+ if ( ptr[0] == ' ' ) ptr[0] = '\n';
+ }
+ for ( ptr = opengl_extensions; ptr != NULL && ptr[0] != '\0'; ptr++ ) {
+ if ( ptr[0] == ' ' ) ptr[0] = '\n';
+ }
+
+
+ /* Add (Shared) GLX information to widget */
+ vbox = ctk_glx->glxinfo_vpane;
+ vbox2 = gtk_vbox_new(FALSE, 0);
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new("GLX Information");
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 2);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 0);
+ table = gtk_table_new(2, 2, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ add_table_row(table, 0, 0, "Direct Rendering:", direct_rendering);
+ add_table_row(table, 1, 0, "GLX Extensions:",
+ glx_extensions?glx_extensions:"");
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
+
+
+ /* Add server GLX information to widget */
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new("Server GLX Information");
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 0);
+ table = gtk_table_new(3, 2, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ add_table_row(table, 0, 0, "Vendor:",
+ server_vendor?server_vendor:"");
+ add_table_row(table, 1, 0, "Version:",
+ server_version?server_version:"");
+ add_table_row(table, 2, 0, "Extensions:",
+ server_extensions?server_extensions:"");
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
+
+
+ /* Add client GLX information to widget */
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new("Client GLX Information");
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 0);
+ table = gtk_table_new(3, 2, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ add_table_row(table, 0, 0, "Vendor:",
+ client_vendor?client_vendor:"");
+ add_table_row(table, 1, 0, "Version:",
+ client_version?client_version:"");
+ add_table_row(table, 2, 0, "Extensions:",
+ client_extensions?client_extensions:"");
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
+
+
+ /* Add OpenGL information to widget */
+ hbox = gtk_hbox_new(FALSE, 0);
+ label = gtk_label_new("OpenGL Information");
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 0);
+ table = gtk_table_new(4, 2, FALSE);
+ vbox2 = gtk_vbox_new(FALSE, 0);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ add_table_row(table, 0, 0, "Vendor:", opengl_vendor);
+ add_table_row(table, 1, 0, "Renderer:", opengl_renderer);
+ add_table_row(table, 2, 0, "Version:", opengl_version);
+ add_table_row(table, 3, 0, "Extensions:", opengl_extensions);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), vbox2, TRUE, TRUE, 2);
+
+
+ /* Show the information */
+ gtk_widget_show_all(GTK_WIDGET(ctk_glx));
+
+
+
+ /* Fall through */
+ done:
+
+ /* Free temp strings */
+ free(direct_rendering);
+ free(glx_extensions);
+ free(server_vendor);
+ free(server_version);
+ free(server_extensions);
+ free(client_vendor);
+ free(client_version);
+ free(client_extensions);
+ free(opengl_vendor);
+ free(opengl_renderer);
+ free(opengl_version);
+ free(opengl_extensions);
+
+} /* ctk_glx_probe_info() */
+
+
+
+GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *table,
+ CtkGLX *ctk_glx)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "GLX Help");
+ ctk_help_para(b, &i,
+ "This page in the NVIDIA X Server Control Panel describes "
+ "information about the OpenGL extension to the X Server "
+ "(GLX)."
+ );
+
+ ctk_help_heading(b, &i, "Direct Rendering");
+ ctk_help_para(b, &i,
+ "This will tell you if direct rendering is available. If "
+ "direct rendering is available, then a program running on "
+ "the same computer that the control pannel is running on "
+ "will be able to bypass the X Server and take advantage of "
+ "faster rendering. If direct rendering is not available, "
+ "then indirect rendering will be used and all rendering "
+ "will happen through the X Server."
+ );
+ ctk_help_heading(b, &i, "GLX Extensions");
+ ctk_help_para(b, &i,
+ "This is the list of GLX extensions that are supported by "
+ "both the client (libraries) and server (GLX extension to "
+ "the X Server.)"
+ );
+
+ ctk_help_heading(b, &i, "Server GLX Vendor String");
+ ctk_help_para(b, &i,
+ "This is the vendor supplying the GLX extension running on "
+ "the X Server."
+ );
+ ctk_help_heading(b, &i, "Server GLX Version String");
+ ctk_help_para(b, &i,
+ "This is the version of the GLX extension running on the X "
+ "Server."
+ );
+ ctk_help_heading(b, &i, "Server GLX Extensions");
+ ctk_help_para(b, &i,
+ "This is the list of extensions supported by the GLX "
+ "extension running on the X Server."
+ );
+
+ ctk_help_heading(b, &i, "Client GLX Vendor String");
+ ctk_help_para(b, &i,
+ "This is the vendor supplying the GLX libraries."
+ );
+ ctk_help_heading(b, &i, "Client GLX Version String");
+ ctk_help_para(b, &i,
+ "This is the version of the GLX libraries."
+ );
+ ctk_help_heading(b, &i, "Client GLX Extensions");
+ ctk_help_para(b, &i,
+ "This is the list of extensions supported by the GLX "
+ "libraries."
+ );
+
+ ctk_help_heading(b, &i, "Frame Buffer Configurations");
+ ctk_help_para(b, &i, "This table lists the supported frame buffer "
+ "configurations for the display.");
+ ctk_help_para(b, &i,
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n"
+ "\t%s\n\n",
+
+ __fid_help,
+ __vid_help,
+ __bfs_help,
+ __lvl_help,
+ __bf_help,
+ __db_help,
+ __st_help,
+ __rs_help,
+ __gs_help,
+ __bs_help,
+
+ __as_help,
+ __aux_help,
+ __dpt_help,
+ __stn_help,
+ __acr_help,
+ __acg_help,
+ __acb_help,
+ __aca_help,
+ __ms_help,
+ __mb_help,
+
+ __cav_help,
+ __pbw_help,
+ __pbh_help,
+ __pbp_help,
+ __trt_help,
+ __trr_help,
+ __trg_help,
+ __trb_help,
+ __tra_help,
+ __tri_help
+ );
+
+ ctk_help_finish(b);
+
+ return b;
+
+} /* ctk_glx_create_help() */
+
+
diff --git a/src/gtk+-2.x/ctkglx.h b/src/gtk+-2.x/ctkglx.h
new file mode 100644
index 0000000..56a47ae
--- /dev/null
+++ b/src/gtk+-2.x/ctkglx.h
@@ -0,0 +1,78 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_GLX_H__
+#define __CTK_GLX_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_GLX (ctk_glx_get_type())
+
+#define CTK_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_GLX, CtkGLX))
+
+#define CTK_GLX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_GLX, CtkGLXClass))
+
+#define CTK_IS_GLX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_GLX))
+
+#define CTK_IS_GLX_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_GLX))
+
+#define CTK_GLX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_GLX, CtkGLXClass))
+
+
+typedef struct _CtkGLX CtkGLX;
+typedef struct _CtkGLXClass CtkGLXClass;
+
+struct _CtkGLX
+{
+ GtkVBox parent;
+
+ NvCtrlAttributeHandle *handle;
+ CtkConfig *ctk_config;
+
+ GtkWidget *glxinfo_vpane;
+ int probe_handler_id; /* Signal handler ID */
+};
+
+struct _CtkGLXClass
+{
+ GtkVBoxClass parent_class;
+};
+
+GType ctk_glx_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_glx_new (NvCtrlAttributeHandle *,
+ CtkConfig *, CtkEvent *);
+
+GtkTextBuffer *ctk_glx_create_help(GtkTextTagTable *, CtkGLX *);
+
+G_END_DECLS
+
+#endif /* __CTK_GLX_H__ */
diff --git a/src/gtk+-2.x/ctkgvo.c b/src/gtk+-2.x/ctkgvo.c
index 9276886..ee0eff1 100644
--- a/src/gtk+-2.x/ctkgvo.c
+++ b/src/gtk+-2.x/ctkgvo.c
@@ -148,21 +148,29 @@ typedef struct {
} FormatName;
static const FormatName videoFormatNames[] = {
- { NV_CTRL_GVO_VIDEO_FORMAT_480I_59_94_SMPTE259_NTSC, "480i 59.94 Hz (SMPTE259) NTSC" },
- { NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, "576i 50.00 Hz (SMPTE259) PAL" },
- { NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296, "720p 59.94 Hz (SMPTE296)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296, "720p 60.00 Hz (SMPTE296)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260, "1035i 59.94 Hz (SMPTE260)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260, "1035i 60.00 Hz (SMPTE260)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295, "1080i 50.00 Hz (SMPTE295)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274, "1080i 50.00 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274, "1080i 59.94 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274, "1080i 60.00 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274, "1080p 23.976 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274, "1080p 24.00 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274, "1080p 25.00 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274, "1080p 29.97 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274, "1080p 30.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_480I_59_94_SMPTE259_NTSC, "480i 59.94 Hz (SMPTE259) NTSC"},
+ { NV_CTRL_GVO_VIDEO_FORMAT_576I_50_00_SMPTE259_PAL, "576i 50.00 Hz (SMPTE259) PAL"},
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296, "720p 23.98 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296, "720p 24.00 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296, "720p 25.00 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296, "720p 29.97 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296, "720p 30.00 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296, "720p 50.00 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_59_94_SMPTE296, "720p 59.94 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_720P_60_00_SMPTE296, "720p 60.00 Hz (SMPTE296)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1035I_59_94_SMPTE260, "1035i 59.94 Hz (SMPTE260)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1035I_60_00_SMPTE260, "1035i 60.00 Hz (SMPTE260)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE295, "1080i 50.00 Hz (SMPTE295)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_50_00_SMPTE274, "1080i 50.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_59_94_SMPTE274, "1080i 59.94 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_60_00_SMPTE274, "1080i 60.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_976_SMPTE274, "1080p 23.976 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE274, "1080p 24.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274, "1080p 25.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274, "1080p 29.97 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274, "1080p 30.00 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE274, "1080PsF 23.98 Hz (SMPTE274)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE274, "1080PsF 24.00 Hz (SMPTE274)" },
{ -1, NULL },
};
diff --git a/src/gtk+-2.x/ctkhelp.c b/src/gtk+-2.x/ctkhelp.c
index 213eb4a..042f67b 100644
--- a/src/gtk+-2.x/ctkhelp.c
+++ b/src/gtk+-2.x/ctkhelp.c
@@ -352,12 +352,9 @@ static gboolean window_destroy(GtkWidget *widget, GdkEvent *event,
void ctk_help_title(GtkTextBuffer *buffer, GtkTextIter *iter,
const gchar *fmt, ...)
{
- va_list ap;
gchar *a, *b;
- va_start(ap, fmt);
- a = nv_build_vararg_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(a, fmt);
b = g_strconcat("\n", a, "\n", NULL);
@@ -370,12 +367,9 @@ void ctk_help_title(GtkTextBuffer *buffer, GtkTextIter *iter,
void ctk_help_para(GtkTextBuffer *buffer, GtkTextIter *iter,
const gchar *fmt, ...)
{
- va_list ap;
gchar *a, *b;
- va_start(ap, fmt);
- a = nv_build_vararg_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(a, fmt);
b = g_strconcat("\n", a, "\n", NULL);
@@ -388,12 +382,9 @@ void ctk_help_para(GtkTextBuffer *buffer, GtkTextIter *iter,
void ctk_help_heading(GtkTextBuffer *buffer, GtkTextIter *iter,
const gchar *fmt, ...)
{
- va_list ap;
gchar *a, *b;
- va_start(ap, fmt);
- a = nv_build_vararg_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(a, fmt);
b = g_strconcat("\n", a, "\n", NULL);
@@ -406,12 +397,9 @@ void ctk_help_heading(GtkTextBuffer *buffer, GtkTextIter *iter,
void ctk_help_term(GtkTextBuffer *buffer, GtkTextIter *iter,
const gchar *fmt, ...)
{
- va_list ap;
gchar *a, *b;
- va_start(ap, fmt);
- a = nv_build_vararg_string(fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(a, fmt);
b = g_strconcat("\n", a, NULL);
diff --git a/src/gtk+-2.x/ctkrandr.c b/src/gtk+-2.x/ctkrandr.c
new file mode 100644
index 0000000..12f712c
--- /dev/null
+++ b/src/gtk+-2.x/ctkrandr.c
@@ -0,0 +1,653 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
+#include "rotation_banner.h" /* Images */
+#include "rotation_orientation_horiz.h"
+#include "rotation_orientation_horiz_flipped.h"
+#include "rotation_orientation_vert.h"
+#include "rotation_orientation_vert_flipped.h"
+#include "rotate_left_on.h"
+#include "rotate_left_off.h"
+#include "rotate_right_on.h"
+#include "rotate_right_off.h"
+
+#include "ctkevent.h"
+#include "ctkrandr.h"
+
+
+GType ctk_randr_get_type(void)
+{
+ static GType ctk_randr_type = 0;
+
+ if (!ctk_randr_type) {
+ static const GTypeInfo ctk_randr_info = {
+ sizeof (CtkRandRClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(CtkRandR),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_randr_type = g_type_register_static
+ (GTK_TYPE_VBOX, "CtkRandR", &ctk_randr_info, 0);
+ }
+
+ return ctk_randr_type;
+}
+
+
+
+/*
+ * Human readable rotation settings
+ */
+static char *get_rotation_string(int rotation)
+{
+ switch ( rotation ) {
+ case RR_Rotate_0:
+ return "Normal (0 degree rotation)";
+ break;
+ case RR_Rotate_90:
+ return "Rotated left (90 degree rotation)";
+ break;
+ case RR_Rotate_180:
+ return "Inverted (180 degree rotation)";
+ break;
+ case RR_Rotate_270:
+ return "Rotated right (270 degree rotation)";
+ break;
+ default:
+ return "Unknown rotation";
+ break;
+ }
+}
+
+
+
+/*
+ * Helper function used to load a pixbuf from an nv_image dump
+ */
+static GdkPixbuf * load_pixbuf_from_nvimage(const nv_image_t *img)
+{
+ guint8 *image_buffer = decompress_image_data(img);
+ if ( !image_buffer )
+ return NULL;
+
+ return gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
+ FALSE, 8, img->width, img->height,
+ img->width * img->bytes_per_pixel,
+ free_decompressed_image, NULL);
+}
+
+
+
+/*
+ * Helper function to load the correctly oriented pixbuf
+ * orientation image from the nv_image dump repository
+ */
+static GdkPixbuf *load_orientation_image_pixbuf(Rotation rotation)
+{
+ const nv_image_t *img_data;
+ int rotate_img_data;
+ guint8 *img_buffer;
+ guint8 *img_buffer_tmp;
+ GdkPixbuf *pixbuf;
+
+
+ /* Figure out which image and rotation to use */
+ switch ( rotation ) {
+ case RR_Rotate_0: /* Normal */
+ img_data = &rotation_orientation_horiz_image;
+ rotate_img_data = 0;
+ break;
+ case RR_Rotate_90: /* Left */
+ img_data = &rotation_orientation_vert_flipped_image;
+ rotate_img_data = 1;
+ break;
+ case RR_Rotate_180: /* Inverted */
+ img_data = &rotation_orientation_horiz_flipped_image;
+ rotate_img_data = 1;
+ break;
+ case RR_Rotate_270: /* Right */
+ img_data = &rotation_orientation_vert_image;
+ rotate_img_data = 0;
+ break;
+ default: /* Unknown */
+ img_data = &rotation_orientation_horiz_image;
+ rotate_img_data = 0;
+ break;
+ }
+
+ /* Load image */
+ img_buffer = decompress_image_data(img_data);
+ if ( !img_buffer ) {
+ return NULL;
+ }
+
+ /* Image data needs to be rotated */
+ if ( rotate_img_data ) {
+ unsigned char *src;
+ unsigned char *dst;
+ unsigned int bppt, w, h; /* Used to rotate image */
+
+
+ img_buffer_tmp = img_buffer;
+
+ img_buffer = (guint8 *) malloc( img_data->width * img_data->height *
+ img_data->bytes_per_pixel );
+ if ( !img_buffer ) {
+ free(img_buffer_tmp);
+ return NULL;
+ }
+
+ /* GTK 2.2 doesn't support this, so we do it ourselves. */
+ dst = (unsigned char *)img_buffer;
+ src = (unsigned char *)img_buffer_tmp;
+ src += (img_data->width * img_data->height -1) *
+ img_data->bytes_per_pixel;
+
+ for (h = 0; h < img_data->height; h++ ) {
+ for (w = 0; w < img_data->width; w++ ) {
+ for (bppt = 0; bppt < img_data->bytes_per_pixel; bppt++ ) {
+ dst[bppt] = src[bppt];
+ }
+ dst += img_data->bytes_per_pixel;
+ src -= img_data->bytes_per_pixel;
+ }
+ }
+
+ free(img_buffer_tmp);
+ } /* Done - rotating image */
+
+ pixbuf = gdk_pixbuf_new_from_data(img_buffer, GDK_COLORSPACE_RGB, FALSE,
+ 8, img_data->width, img_data->height,
+ img_data->width * img_data->bytes_per_pixel,
+ free_decompressed_image, NULL);
+ return pixbuf;
+
+} /* load_orientation_image_pixbuf() */
+
+
+
+/*
+ * Makes widgets associated with rotation reflect the given
+ * rotation setting.
+ */
+static void update_rotation(CtkRandR *ctk_randr, Rotation rotation)
+{
+ /* Update screen image */
+ gtk_image_set_from_pixbuf(ctk_randr->orientation_image,
+ ctk_randr->orientation_image_pixbufs[rotation]);
+
+ /* Update label */
+ gtk_label_set_text(ctk_randr->label,
+ get_rotation_string(rotation));
+
+
+ /* Update the status bar */
+ ctk_config_statusbar_message(ctk_randr->ctk_config,
+ "Screen rotation set to %s.",
+ get_rotation_string(rotation));
+
+} /* update_rotation() */
+
+
+
+/*
+ * When XRandR events happens outside of the control panel,
+ * they are trapped by this function so the gui can be updated
+ * with the new rotation setting.
+ */
+void ctk_randr_event_handler(GtkWidget *widget,
+ XRRScreenChangeNotifyEvent *ev,
+ gpointer data)
+{
+ update_rotation((CtkRandR *)data, ev->rotation);
+} /* ctk_randr_event_handler() */
+
+
+
+/*
+ * Rotate left button event handlers
+ */
+static void do_button_rotate_left_clicked(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+ int orig_rotation;
+ int rotation;
+ int rotations;
+ ReturnStatus status;
+
+
+ /* Get current rotation */
+ NvCtrlGetAttribute(ctk_randr->handle, NV_CTRL_ATTR_XRANDR_ROTATION,
+ &orig_rotation);
+
+ /* Get available rotations */
+ NvCtrlGetAttribute(ctk_randr->handle, NV_CTRL_ATTR_XRANDR_ROTATIONS,
+ &rotations);
+
+ /* Find next available rotation to the left */
+ rotation = orig_rotation;
+ do {
+ rotation <<= 1;
+ if ( rotation > 8 ) {
+ rotation = 1;
+ }
+ } while ( !(rotation & rotations) && (rotation != orig_rotation) );
+
+ /* Set rotation */
+ status = NvCtrlSetAttribute(ctk_randr->handle,
+ NV_CTRL_ATTR_XRANDR_ROTATION,
+ rotation);
+
+ /* Update widgets */
+ update_rotation(ctk_randr, rotation);
+}
+
+static void do_button_rotate_left_press(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ ctk_randr->rotate_left_button_pressed = True;
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_left_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_ON]);
+}
+
+static void do_button_rotate_left_release(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ ctk_randr->rotate_left_button_pressed = False;
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_left_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_OFF]);
+}
+
+static void do_button_rotate_left_enter(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ if ( ctk_randr->rotate_left_button_pressed ) {
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_left_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_ON]);
+ }
+}
+
+static void do_button_rotate_left_leave(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ if ( ctk_randr->rotate_left_button_pressed ) {
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_left_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_OFF]);
+ }
+}
+
+
+
+/*
+ * Rotate right button event handlers
+ */
+static void do_button_rotate_right_clicked(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+ int orig_rotation;
+ int rotation;
+ int rotations;
+ ReturnStatus status;
+
+
+ /* Get current rotation */
+ NvCtrlGetAttribute(ctk_randr->handle, NV_CTRL_ATTR_XRANDR_ROTATION,
+ &orig_rotation);
+
+ /* Get available rotations */
+ NvCtrlGetAttribute(ctk_randr->handle, NV_CTRL_ATTR_XRANDR_ROTATIONS,
+ &rotations);
+
+ /* Find next available rotation to the left */
+ rotation = orig_rotation;
+ do {
+ rotation >>= 1;
+ if ( rotation == 0 ) {
+ rotation = 8;
+ }
+ } while ( !(rotation & rotations) && (rotation != orig_rotation) );
+
+
+ /* Set rotation */
+ status = NvCtrlSetAttribute(ctk_randr->handle,
+ NV_CTRL_ATTR_XRANDR_ROTATION,
+ rotation);
+
+ /* Update widgets */
+ update_rotation(ctk_randr, rotation);
+}
+
+static void do_button_rotate_right_press(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ ctk_randr->rotate_right_button_pressed = True;
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_right_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_ON]);
+}
+
+
+static void do_button_rotate_right_release(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ ctk_randr->rotate_right_button_pressed = False;
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_right_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_OFF]);
+}
+
+static void do_button_rotate_right_enter(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ if ( ctk_randr->rotate_right_button_pressed ) {
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_right_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_ON]);
+ }
+}
+
+static void do_button_rotate_right_leave(GtkWidget *widget, gpointer data)
+{
+ CtkRandR *ctk_randr = (CtkRandR *)data;
+
+ if ( ctk_randr->rotate_right_button_pressed ) {
+ gtk_image_set_from_pixbuf(ctk_randr->rotate_right_button_image,
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_OFF]);
+ }
+}
+
+
+
+/*
+ * CTK RandR widget creation
+ *
+ */
+GtkWidget* ctk_randr_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config,
+ CtkEvent *ctk_event)
+{
+ GObject *object;
+ CtkRandR *ctk_randr;
+ GtkWidget *alignment;
+ GtkWidget *button;
+
+ Bool ret; /* NvCtrlxxx function return value */
+ int rotation_supported;
+ int rotation;
+
+
+
+ /* Make sure we have a handle */
+ g_return_val_if_fail(handle != NULL, NULL);
+
+
+ /* Check if this screen supports rotation */
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED,
+ &rotation_supported);
+ if ((ret != NvCtrlSuccess) || (!rotation_supported)) {
+ /* Rotation not available */
+ return NULL;
+ }
+
+
+ /* Get the initial state of rotation */
+ NvCtrlGetAttribute(handle, NV_CTRL_ATTR_XRANDR_ROTATION, &rotation);
+
+
+ /* Create the ctk object */
+ object = g_object_new(CTK_TYPE_RANDR, NULL);
+ ctk_randr = CTK_RANDR(object);
+
+
+ /* Cache the attribute handle */
+ ctk_randr->handle = handle;
+
+
+ /* Set container properties of the object */
+ ctk_randr->ctk_config = ctk_config;
+ gtk_box_set_spacing(GTK_BOX(ctk_randr), 10);
+
+
+ /* Preload orientated screens pixbufs & image */
+ ctk_randr->orientation_image_pixbufs[CTKRANDR_IMG_ROTATION_NORMAL] =
+ load_orientation_image_pixbuf(RR_Rotate_0);
+
+ ctk_randr->orientation_image_pixbufs[CTKRANDR_IMG_ROTATION_LEFT] =
+ load_orientation_image_pixbuf(RR_Rotate_90);
+
+ ctk_randr->orientation_image_pixbufs[CTKRANDR_IMG_ROTATION_INVERTED] =
+ load_orientation_image_pixbuf(RR_Rotate_180);
+
+ ctk_randr->orientation_image_pixbufs[CTKRANDR_IMG_ROTATION_RIGHT] =
+ load_orientation_image_pixbuf(RR_Rotate_270);
+
+ ctk_randr->orientation_image =
+ GTK_IMAGE(gtk_image_new_from_pixbuf(ctk_randr->orientation_image_pixbufs[rotation]) );
+
+
+ /* Preload button pixbufs & images */
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_OFF] =
+ load_pixbuf_from_nvimage(&rotate_left_off_image);
+
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_ON] =
+ load_pixbuf_from_nvimage(&rotate_left_on_image);
+
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_OFF] =
+ load_pixbuf_from_nvimage(&rotate_right_off_image);
+
+ ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_ON] =
+ load_pixbuf_from_nvimage(&rotate_right_on_image);
+
+ ctk_randr->rotate_left_button_image =
+ GTK_IMAGE(gtk_image_new_from_pixbuf(ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_LEFT_OFF]) );
+
+ ctk_randr->rotate_right_button_image =
+ GTK_IMAGE(gtk_image_new_from_pixbuf(ctk_randr->button_pixbufs[CTKRANDR_BTN_ROTATE_RIGHT_OFF]) );
+
+
+
+ { /* Banner image */
+ GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
+ GtkWidget *frame = gtk_frame_new(NULL);
+
+ const nv_image_t *image_data = &rotation_banner_image;
+ guint8 *image_buffer = decompress_image_data(image_data);
+ GdkPixbuf *image_pixbuf =
+ gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
+ FALSE, 8, image_data->width,
+ image_data->height,
+ image_data->width * image_data->bytes_per_pixel,
+ free_decompressed_image, NULL);
+ GtkWidget *image = gtk_image_new_from_pixbuf(image_pixbuf);
+
+
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
+
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+ gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(frame), image);
+ }
+
+
+ { /* Rotation control pane */
+ GtkWidget *vRotationPane = gtk_vbox_new(FALSE, 0);
+ GtkWidget *hStrechedControlBox = gtk_hbox_new(TRUE, 0);
+ GtkWidget *hControlBox = gtk_hbox_new(FALSE, 10);
+
+ gtk_box_pack_start(GTK_BOX(object), vRotationPane, TRUE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(vRotationPane), hStrechedControlBox,
+ FALSE, FALSE,
+ 0);
+
+ gtk_box_pack_start(GTK_BOX(hStrechedControlBox), hControlBox,
+ FALSE, FALSE, 0);
+
+
+ { /* Rotate left button */
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
+ GtkWidget *btn_box = gtk_hbox_new(FALSE, 0);
+ GtkWidget *button = gtk_button_new();
+
+ gtk_box_pack_start(GTK_BOX(hControlBox), vbox, TRUE, FALSE, 0);
+
+ gtk_widget_set_size_request(button, 26, 26);
+ ctk_config_set_tooltip(ctk_config, button, "Rotate left");
+ g_signal_connect(G_OBJECT(button), "pressed",
+ G_CALLBACK(do_button_rotate_left_press),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "released",
+ G_CALLBACK(do_button_rotate_left_release),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "enter",
+ G_CALLBACK(do_button_rotate_left_enter),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "leave",
+ G_CALLBACK(do_button_rotate_left_leave),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(do_button_rotate_left_clicked),
+ (gpointer) (ctk_randr));
+
+ gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(button), btn_box);
+
+ gtk_container_add(GTK_CONTAINER(btn_box),
+ GTK_WIDGET(ctk_randr->rotate_left_button_image));
+ }
+
+ { /* Rotation orientation image */
+ GtkWidget *img_box = gtk_hbox_new(TRUE, 0);
+
+ gtk_widget_set_size_request(img_box, 120, 120);
+
+ gtk_box_pack_start(GTK_BOX(img_box),
+ GTK_WIDGET(ctk_randr->orientation_image),
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(hControlBox), img_box, FALSE, FALSE, 0);
+ }
+
+ { /* Rotate right button */
+ GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
+ GtkWidget *btn_box = gtk_hbox_new(FALSE, 0);
+ GtkWidget *button = gtk_button_new();
+
+ gtk_box_pack_start(GTK_BOX(hControlBox), vbox, TRUE, FALSE, 0);
+
+ gtk_widget_set_size_request(button, 26, 26);
+ ctk_config_set_tooltip(ctk_config, button, "Rotate right");
+ g_signal_connect(G_OBJECT(button), "pressed",
+ G_CALLBACK(do_button_rotate_right_press),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "released",
+ G_CALLBACK(do_button_rotate_right_release),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "enter",
+ G_CALLBACK(do_button_rotate_right_enter),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "leave",
+ G_CALLBACK(do_button_rotate_right_leave),
+ (gpointer) ctk_randr);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(do_button_rotate_right_clicked),
+ (gpointer) (ctk_randr));
+
+ gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(button), btn_box);
+
+ gtk_container_add(GTK_CONTAINER(btn_box),
+ GTK_WIDGET(ctk_randr->rotate_right_button_image));
+ }
+
+ { /* Rotation label */
+ ctk_randr->label =
+ GTK_LABEL( gtk_label_new(get_rotation_string(rotation)));
+ gtk_box_pack_start(GTK_BOX(vRotationPane),
+ GTK_WIDGET(ctk_randr->label),
+ TRUE, TRUE, 10);
+ }
+
+ } /* Rotation control pane */
+
+
+
+ /* Show the widget */
+ gtk_widget_show_all(GTK_WIDGET(ctk_randr));
+
+
+ /* Link widget to XRandR events */
+ g_signal_connect(ctk_event, "CTK_EVENT_RRScreenChangeNotify",
+ G_CALLBACK(ctk_randr_event_handler),
+ (gpointer) ctk_randr);
+
+
+ return GTK_WIDGET(ctk_randr);
+}
+
+
+
+/*
+ * RandR help screen
+ */
+GtkTextBuffer *ctk_randr_create_help(GtkTextTagTable *table,
+ CtkRandR *ctk_randr)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "Rotation Help");
+ ctk_help_para(b, &i,
+ "This page in the NVIDIA X Server Control Panel allows "
+ "you to select the desired screen orientation through "
+ "the XRandR extension."
+ );
+
+ ctk_help_finish(b);
+
+ return b;
+}
diff --git a/src/gtk+-2.x/ctkrandr.h b/src/gtk+-2.x/ctkrandr.h
new file mode 100644
index 0000000..86c21e2
--- /dev/null
+++ b/src/gtk+-2.x/ctkrandr.h
@@ -0,0 +1,97 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_RANDR_H__
+#define __CTK_RANDR_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_RANDR (ctk_randr_get_type())
+
+#define CTK_RANDR(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_RANDR, CtkRandR))
+
+#define CTK_RANDR_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_RANDR, CtkRandRClass))
+
+#define CTK_IS_RANDR(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_RANDR))
+
+#define CTK_IS_RANDR_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_RANDR))
+
+#define CTK_RANDR_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_RANDR, CtkRandRClass))
+
+
+/* Image pixbuf indices */
+#define CTKRANDR_IMG_ROTATION_NORMAL RR_Rotate_0
+#define CTKRANDR_IMG_ROTATION_LEFT RR_Rotate_90
+#define CTKRANDR_IMG_ROTATION_INVERTED RR_Rotate_180
+#define CTKRANDR_IMG_ROTATION_RIGHT RR_Rotate_270
+
+/* Button pixbuf indices */
+#define CTKRANDR_BTN_ROTATE_LEFT_OFF 0
+#define CTKRANDR_BTN_ROTATE_LEFT_ON 1
+#define CTKRANDR_BTN_ROTATE_RIGHT_OFF 2
+#define CTKRANDR_BTN_ROTATE_RIGHT_ON 3
+
+
+typedef struct _CtkRandR
+{
+ GtkVBox parent;
+
+ NvCtrlAttributeHandle *handle;
+ CtkConfig *ctk_config;
+
+ GtkLabel *label;
+
+ GtkImage *orientation_image;
+ GdkPixbuf *orientation_image_pixbufs[9];
+
+ GtkImage *rotate_left_button_image;
+ Bool rotate_left_button_pressed;
+ GtkImage *rotate_right_button_image;
+ Bool rotate_right_button_pressed;
+ GdkPixbuf *button_pixbufs[4];
+
+} CtkRandR;
+
+typedef struct _CtkRandRClass
+{
+ GtkVBoxClass parent_class;
+} CtkRandRClass;
+
+GType ctk_randr_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_randr_new (NvCtrlAttributeHandle *, CtkConfig *,
+ CtkEvent *);
+
+GtkTextBuffer *ctk_randr_create_help(GtkTextTagTable *, CtkRandR *);
+
+G_END_DECLS
+
+#endif /* __CTK_RANDR_H__ */
diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c
index c148537..badeddc 100644
--- a/src/gtk+-2.x/ctkwindow.c
+++ b/src/gtk+-2.x/ctkwindow.c
@@ -42,8 +42,10 @@
#include "ctkdevice.h"
#include "ctkcolorcorrection.h"
#include "ctkxvideo.h"
+#include "ctkrandr.h"
#include "ctkcursorshadow.h"
#include "ctkopengl.h"
+#include "ctkglx.h"
#include "ctkmultisample.h"
#include "ctkthermal.h"
@@ -526,6 +528,15 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
"X Server XVideo Settings", NULL);
}
+ /* randr settings */
+
+ child = ctk_randr_new(handles[i], ctk_config, ctk_event);
+ if (child) {
+ help = ctk_randr_create_help(tag_table, CTK_RANDR(child));
+ add_page(child, help, ctk_window, &iter,
+ "Rotation Settings", NULL);
+ }
+
/* cursor shadow */
child = ctk_cursor_shadow_new(handles[i], ctk_config, ctk_event);
@@ -543,6 +554,16 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
add_page(child, help, ctk_window, &iter, "OpenGL Settings", NULL);
}
+
+ /* GLX Information */
+
+ child = ctk_glx_new(handles[i], ctk_config, ctk_event);
+ if (child) {
+ help = ctk_glx_create_help(tag_table, CTK_GLX(child));
+ add_page(child, help, ctk_window, &iter, "OpenGL/GLX Information", NULL);
+ }
+
+
/* multisample settings */
child = ctk_multisample_new(handles[i], ctk_config, ctk_event);
diff --git a/src/libXNVCtrl/NVCtrl.c b/src/libXNVCtrl/NVCtrl.c
index 56446d1..2f8b352 100644
--- a/src/libXNVCtrl/NVCtrl.c
+++ b/src/libXNVCtrl/NVCtrl.c
@@ -10,6 +10,7 @@
#define NEED_EVENTS
#define NEED_REPLIES
+#include <stdlib.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
#include "Xext.h"
@@ -288,6 +289,93 @@ Bool XNVCTRLQueryValidAttributeValues (
return exists;
}
+
+
+void XNVCTRLSetGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3]
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlSetGvoColorConversionReq *req;
+
+ XNVCTRLSimpleCheckExtension (dpy, info);
+
+ LockDisplay (dpy);
+ GetReq (nvCtrlSetGvoColorConversion, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlSetGvoColorConversion;
+ req->screen = screen;
+ req->row1_col1 = colorMatrix[0][0];
+ req->row1_col2 = colorMatrix[0][1];
+ req->row1_col3 = colorMatrix[0][2];
+ req->row1_col4 = colorOffset[0];
+ req->row2_col1 = colorMatrix[1][0];
+ req->row2_col2 = colorMatrix[1][1];
+ req->row2_col3 = colorMatrix[1][2];
+ req->row2_col4 = colorOffset[1];
+ req->row3_col1 = colorMatrix[2][0];
+ req->row3_col2 = colorMatrix[2][1];
+ req->row3_col3 = colorMatrix[2][2];
+ req->row3_col4 = colorOffset[2];
+ UnlockDisplay (dpy);
+ SyncHandle ();
+}
+
+
+Bool XNVCTRLQueryGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3]
+){
+ XExtDisplayInfo *info = find_display (dpy);
+ xnvCtrlQueryGvoColorConversionReply rep;
+ xnvCtrlQueryGvoColorConversionReq *req;
+ float buf[3][4];
+
+ if(!XextHasExtension(info))
+ return False;
+
+ XNVCTRLCheckExtension (dpy, info, False);
+
+ LockDisplay (dpy);
+
+ GetReq (nvCtrlQueryGvoColorConversion, req);
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlQueryGvoColorConversion;
+ req->screen = screen;
+
+ if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
+ UnlockDisplay (dpy);
+ SyncHandle ();
+ return False;
+ }
+
+ _XRead(dpy, (char *)(&buf), 48);
+
+ colorMatrix[0][0] = buf[0][0];
+ colorMatrix[0][1] = buf[0][1];
+ colorMatrix[0][2] = buf[0][2];
+ colorMatrix[1][0] = buf[1][0];
+ colorMatrix[1][1] = buf[1][1];
+ colorMatrix[1][2] = buf[1][2];
+ colorMatrix[2][0] = buf[2][0];
+ colorMatrix[2][1] = buf[2][1];
+ colorMatrix[2][2] = buf[2][2];
+
+ colorOffset[0] = buf[0][3];
+ colorOffset[1] = buf[1][3];
+ colorOffset[2] = buf[2][3];
+
+ UnlockDisplay (dpy);
+ SyncHandle ();
+
+ return True;
+}
+
+
Bool XNVCtrlSelectNotify (
Display *dpy,
int screen,
diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h
index 9470ec9..caea219 100644
--- a/src/libXNVCtrl/NVCtrl.h
+++ b/src/libXNVCtrl/NVCtrl.h
@@ -111,6 +111,7 @@
#define NV_CTRL_OPERATING_SYSTEM 8 /* R-- */
#define NV_CTRL_OPERATING_SYSTEM_LINUX 0
#define NV_CTRL_OPERATING_SYSTEM_FREEBSD 1
+#define NV_CTRL_OPERATING_SYSTEM_SUNOS 2
/*
@@ -283,6 +284,7 @@
#define NV_CTRL_FRAMELOCK_POLARITY 23 /* RW- */
#define NV_CTRL_FRAMELOCK_POLARITY_RISING_EDGE 0x1
+#define NV_CTRL_FRAMELOCK_POLARITY_FALLING_EDGE 0x2
#define NV_CTRL_FRAMELOCK_POLARITY_BOTH_EDGES 0x3
@@ -652,6 +654,11 @@
*
* if this screen does not support PBUFFER_SCANOUT, then all other
* PBUFFER_SCANOUT attributes are unavailable.
+ *
+ * PBUFFER_SCANOUT is supported if and only if:
+ * - Twinview is configured with clone mode. The secondary screen is used to
+ * scanout the pbuffer.
+ * - The desktop is running in with 16 bits per pixel.
*/
#define NV_CTRL_PBUFFER_SCANOUT_SUPPORTED 65 /* R-- */
#define NV_CTRL_PBUFFER_SCANOUT_FALSE 0
@@ -796,6 +803,14 @@
#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE274 13
#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE274 14
#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE274 15
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_50_00_SMPTE296 16
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE274 17
+#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE274 18
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_30_00_SMPTE296 19
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_29_97_SMPTE296 20
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_25_00_SMPTE296 21
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_24_00_SMPTE296 22
+#define NV_CTRL_GVO_VIDEO_FORMAT_720P_23_98_SMPTE296 23
/*
diff --git a/src/libXNVCtrl/NVCtrlLib.h b/src/libXNVCtrl/NVCtrlLib.h
index ee8810f..372247c 100644
--- a/src/libXNVCtrl/NVCtrlLib.h
+++ b/src/libXNVCtrl/NVCtrlLib.h
@@ -18,6 +18,7 @@ Bool XNVCTRLQueryExtension (
int *error_basep
);
+
/*
* XNVCTRLQueryVersion -
*
@@ -45,6 +46,7 @@ Bool XNVCTRLIsNvScreen (
int screen
);
+
/*
* XNVCTRLSetAttribute -
*
@@ -67,6 +69,7 @@ void XNVCTRLSetAttribute (
int value
);
+
/*
* XNVCTRLQueryAttribute -
*
@@ -82,7 +85,6 @@ void XNVCTRLSetAttribute (
* BadMatch - The NVIDIA driver is not present on that screen.
*/
-
Bool XNVCTRLQueryAttribute (
Display *dpy,
int screen,
@@ -91,6 +93,7 @@ Bool XNVCTRLQueryAttribute (
int *value
);
+
/*
* XNVCTRLQueryStringAttribute -
*
@@ -113,6 +116,7 @@ Bool XNVCTRLQueryStringAttribute (
char **ptr
);
+
/*
* XNVCTRLQueryValidAttributeValues -
*
@@ -130,6 +134,45 @@ Bool XNVCTRLQueryValidAttributeValues (
NVCTRLAttributeValidValuesRec *values
);
+
+/*
+ * XNVCTRLSetGvoColorConversion -
+ *
+ * Sets the color conversion matrix and color offset
+ * that should be used for GVO (Graphic to Video Out).
+ *
+ * Possible errors:
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadImplementation - GVO is not available on that screen.
+ */
+
+void XNVCTRLSetGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3]
+);
+
+
+/*
+ * XNVCTRLQueryGvoColorConversion -
+ *
+ * Retrieves the color conversion matrix and color offset
+ * that are currently being used for GVO (Graphic to Video Out).
+ *
+ * Possible errors:
+ * BadMatch - The NVIDIA driver is not present on that screen.
+ * BadImplementation - GVO is not available on that screen.
+ */
+
+Bool XNVCTRLQueryGvoColorConversion (
+ Display *dpy,
+ int screen,
+ float colorMatrix[3][3],
+ float colorOffset[3]
+);
+
+
/*
* XNVCtrlSelectNotify -
*
diff --git a/src/libXNVCtrl/libXNVCtrl.a b/src/libXNVCtrl/libXNVCtrl.a
index 83c81c6..e981c13 100644
--- a/src/libXNVCtrl/libXNVCtrl.a
+++ b/src/libXNVCtrl/libXNVCtrl.a
Binary files differ
diff --git a/src/libXNVCtrl/nv_control.h b/src/libXNVCtrl/nv_control.h
index fcd26cf..e82b0f4 100644
--- a/src/libXNVCtrl/nv_control.h
+++ b/src/libXNVCtrl/nv_control.h
@@ -15,7 +15,17 @@
#define X_nvCtrlQueryStringAttribute 4
#define X_nvCtrlQueryValidAttributeValues 5
#define X_nvCtrlSelectNotify 6
-#define X_nvCtrlLastRequest (X_nvCtrlSelectNotify + 1)
+#define X_nvCtrlSetGvoColorConversion 7
+#define X_nvCtrlQueryGvoColorConversion 8
+#define X_nvCtrlLastRequest (X_nvCtrlQueryGvoColorConversion + 1)
+
+
+/* Define 32 bit floats */
+typedef float FLOAT32;
+#ifndef F32
+#define F32
+#endif
+
typedef struct {
CARD8 reqType;
@@ -148,6 +158,51 @@ typedef struct {
} xnvCtrlQueryValidAttributeValuesReply;
#define sz_xnvCtrlQueryValidAttributeValuesReply 32
+/* Set GVO Color Conversion request */
+typedef struct {
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+ FLOAT32 row1_col1 F32;
+ FLOAT32 row1_col2 F32;
+ FLOAT32 row1_col3 F32;
+ FLOAT32 row1_col4 F32;
+ FLOAT32 row2_col1 F32;
+ FLOAT32 row2_col2 F32;
+ FLOAT32 row2_col3 F32;
+ FLOAT32 row2_col4 F32;
+ FLOAT32 row3_col1 F32;
+ FLOAT32 row3_col2 F32;
+ FLOAT32 row3_col3 F32;
+ FLOAT32 row3_col4 F32;
+} xnvCtrlSetGvoColorConversionReq;
+#define sz_xnvCtrlSetGvoColorConversionReq 56
+
+/* Query GVO Color Conversion request */
+typedef struct {
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+} xnvCtrlQueryGvoColorConversionReq;
+#define sz_xnvCtrlQueryGvoColorConversionReq 8
+
+/* Query GVO Color Conversion reply */
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+ CARD32 pad8 B32;
+} xnvCtrlQueryGvoColorConversionReply;
+#define sz_xnvCtrlQueryGvoColorConversionReply 32
+
typedef struct {
CARD8 reqType;
CARD8 nvReqType;
diff --git a/src/libXNVCtrlAttributes/Makefile.inc b/src/libXNVCtrlAttributes/Makefile.inc
index 943d44d..257cc7f 100644
--- a/src/libXNVCtrlAttributes/Makefile.inc
+++ b/src/libXNVCtrlAttributes/Makefile.inc
@@ -29,7 +29,9 @@ SRC += \
NvCtrlAttributes.c \
NvCtrlAttributesNvControl.c \
NvCtrlAttributesVidMode.c \
- NvCtrlAttributesXv.c
+ NvCtrlAttributesXv.c \
+ NvCtrlAttributesGlx.c \
+ NvCtrlAttributesXrandr.c
EXTRA_DIST += \
NvCtrlAttributes.h \
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.c b/src/libXNVCtrlAttributes/NvCtrlAttributes.c
index 3d70024..4ffc302 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributes.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.c
@@ -85,7 +85,25 @@ NvCtrlAttributeHandle *NvCtrlAttributeInit(Display *dpy, int screen,
if (subsystems & NV_CTRL_ATTRIBUTES_XVIDEO_SUBSYSTEM) {
NvCtrlInitXvOverlayAttributes(h);
}
-
+
+ /*
+ * initialize the GLX extension and attributes; it is OK if
+ * this fails
+ */
+
+ if (subsystems & NV_CTRL_ATTRIBUTES_GLX_SUBSYSTEM) {
+ h->glx = NvCtrlInitGlxAttributes(h);
+ }
+
+ /*
+ * initialize the XRandR extension and attributes; it is OK if
+ * this fails
+ */
+
+ if (subsystems & NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM) {
+ h->xrandr = NvCtrlInitXrandrAttributes(h);
+ }
+
return (NvCtrlAttributeHandle *) h;
failed:
@@ -209,6 +227,20 @@ int NvCtrlGetEventBase(NvCtrlAttributeHandle *handle)
} /* NvCtrlGetEventBase() */
+int NvCtrlGetXrandrEventBase(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return 0;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->xrandr) return 0;
+ return (h->xrandr->event_base);
+
+} /* NvCtrlGetXrandrEventBase() */
+
+
ReturnStatus NvCtrlGetAttribute(NvCtrlAttributeHandle *handle,
int attr, int *val)
{
@@ -227,6 +259,15 @@ ReturnStatus NvCtrlSetAttribute(NvCtrlAttributeHandle *handle,
} /* NvCtrlSetAttribute() */
+ReturnStatus NvCtrlGetVoidAttribute(NvCtrlAttributeHandle *handle,
+ int attr, void **ptr)
+{
+ if (!handle) return NvCtrlBadArgument;
+ return NvCtrlGetVoidDisplayAttribute(handle, 0, attr, ptr);
+
+} /* NvCtrlGetVoidAttribute() */
+
+
ReturnStatus NvCtrlGetValidAttributeValues(NvCtrlAttributeHandle *handle,
int attr,
NVCTRLAttributeValidValuesRec *val)
@@ -283,6 +324,14 @@ NvCtrlGetDisplayAttribute(NvCtrlAttributeHandle *handle,
return NvCtrlXvGetAttribute(h, attr, val);
}
+
+ if ((attr >= NV_CTRL_ATTR_XRANDR_BASE) &&
+ (attr <= NV_CTRL_ATTR_XRANDR_LAST_ATTRIBUTE)) {
+
+ return NvCtrlXrandrGetAttribute(h, attr, val);
+ }
+
+
return NvCtrlNoAttribute;
} /* NvCtrlGetDisplayAttribute() */
@@ -307,12 +356,37 @@ NvCtrlSetDisplayAttribute(NvCtrlAttributeHandle *handle,
return NvCtrlXvSetAttribute(h, attr, val);
}
+ if ((attr >= NV_CTRL_ATTR_XRANDR_BASE) &&
+ (attr <= NV_CTRL_ATTR_XRANDR_LAST_ATTRIBUTE)) {
+
+ return NvCtrlXrandrSetAttribute(h, attr, val);
+ }
+
return NvCtrlNoAttribute;
} /* NvCtrlSetDisplayAttribute() */
ReturnStatus
+NvCtrlGetVoidDisplayAttribute(NvCtrlAttributeHandle *handle,
+ unsigned int display_mask, int attr, void **ptr)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if ( attr >= NV_CTRL_ATTR_GLX_BASE &&
+ attr >= NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE ) {
+ if ( !(h->glx) ) return NvCtrlMissingExtension;
+ return NvCtrlGlxGetVoidAttribute(h, display_mask, attr, ptr);
+ }
+
+ return NvCtrlNoAttribute;
+
+} /* NvCtrlGetVoidDisplayAttribute() */
+
+
+ReturnStatus
NvCtrlGetValidDisplayAttributeValues(NvCtrlAttributeHandle *handle,
unsigned int display_mask, int attr,
NVCTRLAttributeValidValuesRec *val)
@@ -347,11 +421,17 @@ NvCtrlGetStringDisplayAttribute(NvCtrlAttributeHandle *handle,
h = (NvCtrlAttributePrivateHandle *) handle;
- if ((attr >= 0) && (attr <= NV_CTRL_LAST_ATTRIBUTE)) {
+ if ((attr >= 0) && (attr <= NV_CTRL_STRING_LAST_ATTRIBUTE)) {
if (!h->nv) return NvCtrlMissingExtension;
return NvCtrlNvControlGetStringAttribute(h, display_mask, attr, ptr);
}
+ if ((attr >= NV_CTRL_STRING_GLX_BASE) &&
+ (attr <= NV_CTRL_STRING_GLX_LAST_ATTRIBUTE)) {
+ if (!h->glx) return NvCtrlMissingExtension;
+ return NvCtrlGlxGetStringAttribute(h, display_mask, attr, ptr);
+ }
+
return NvCtrlNoAttribute;
} /* NvCtrlGetStringDisplayAttribute() */
@@ -396,6 +476,12 @@ void NvCtrlAttributeClose(NvCtrlAttributeHandle *handle)
* subsystem
*/
- free(h);
+ if ( h->glx ) {
+ NvCtrlGlxAttributesClose(h);
+ }
+ if ( h->xrandr ) {
+ NvCtrlXrandrAttributesClose(h);
+ }
+ free(h);
} /* NvCtrlAttributeClose() */
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.h b/src/libXNVCtrlAttributes/NvCtrlAttributes.h
index b1b6be8..27da5d1 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributes.h
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.h
@@ -111,7 +111,30 @@ typedef void NvCtrlAttributeHandle;
#define NV_CTRL_ATTR_XV_NUM \
(NV_CTRL_ATTR_XV_LAST_ATTRIBUTE - NV_CTRL_ATTR_XV_BASE + 1)
-#define NV_CTRL_ATTR_LAST_ATTRIBUTE (NV_CTRL_ATTR_XV_LAST_ATTRIBUTE)
+/* GLX */
+
+#define NV_CTRL_ATTR_GLX_BASE \
+ (NV_CTRL_ATTR_XV_LAST_ATTRIBUTE + 1)
+
+#define NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS (NV_CTRL_ATTR_GLX_BASE + 0)
+
+#define NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE \
+ (NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS)
+
+/* XRandR */
+
+#define NV_CTRL_ATTR_XRANDR_BASE \
+ (NV_CTRL_ATTR_GLX_LAST_ATTRIBUTE + 1)
+
+#define NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED (NV_CTRL_ATTR_XRANDR_BASE + 0)
+#define NV_CTRL_ATTR_XRANDR_ROTATIONS (NV_CTRL_ATTR_XRANDR_BASE + 1)
+#define NV_CTRL_ATTR_XRANDR_ROTATION (NV_CTRL_ATTR_XRANDR_BASE + 2)
+
+#define NV_CTRL_ATTR_XRANDR_LAST_ATTRIBUTE \
+ (NV_CTRL_ATTR_XRANDR_ROTATION)
+
+
+#define NV_CTRL_ATTR_LAST_ATTRIBUTE (NV_CTRL_ATTR_XRANDR_LAST_ATTRIBUTE)
typedef enum {
@@ -127,6 +150,83 @@ typedef enum {
} ReturnStatus;
+/* GLX FBConfig attribute structure */
+
+typedef struct GLXFBConfigAttrRec {
+ int fbconfig_id;
+ int visual_id;
+
+ int buffer_size;
+ int level;
+ int doublebuffer;
+ int stereo;
+ int aux_buffers;
+
+ int red_size;
+ int green_size;
+ int blue_size;
+ int alpha_size;
+ int depth_size;
+ int stencil_size;
+
+ int accum_red_size;
+ int accum_green_size;
+ int accum_blue_size;
+ int accum_alpha_size;
+
+ int render_type;
+ int drawable_type;
+ int x_renderable;
+ int x_visual_type;
+ int config_caveat;
+
+ int transparent_type;
+ int transparent_index_value;
+ int transparent_red_value;
+ int transparent_green_value;
+ int transparent_blue_value;
+ int transparent_alpha_value;
+
+ int pbuffer_width;
+ int pbuffer_height;
+ int pbuffer_max;
+
+ int multi_sample_valid;
+ int multi_samples;
+ int multi_sample_buffers;
+
+} GLXFBConfigAttr;
+
+
+
+/*
+ * Valid string attributes for NvCtrlGetStringAttribute(); these are
+ * in addition to the ones in NVCtrl.h
+ */
+
+#define NV_CTRL_STRING_GLX_BASE \
+ (NV_CTRL_STRING_LAST_ATTRIBUTE + 1)
+
+#define NV_CTRL_STRING_GLX_DIRECT_RENDERING (NV_CTRL_STRING_GLX_BASE + 0)
+#define NV_CTRL_STRING_GLX_GLX_EXTENSIONS (NV_CTRL_STRING_GLX_BASE + 1)
+
+#define NV_CTRL_STRING_GLX_SERVER_VENDOR (NV_CTRL_STRING_GLX_BASE + 2)
+#define NV_CTRL_STRING_GLX_SERVER_VERSION (NV_CTRL_STRING_GLX_BASE + 3)
+#define NV_CTRL_STRING_GLX_SERVER_EXTENSIONS (NV_CTRL_STRING_GLX_BASE + 4)
+
+#define NV_CTRL_STRING_GLX_CLIENT_VENDOR (NV_CTRL_STRING_GLX_BASE + 5)
+#define NV_CTRL_STRING_GLX_CLIENT_VERSION (NV_CTRL_STRING_GLX_BASE + 6)
+#define NV_CTRL_STRING_GLX_CLIENT_EXTENSIONS (NV_CTRL_STRING_GLX_BASE + 7)
+
+#define NV_CTRL_STRING_GLX_OPENGL_VENDOR (NV_CTRL_STRING_GLX_BASE + 8)
+#define NV_CTRL_STRING_GLX_OPENGL_RENDERER (NV_CTRL_STRING_GLX_BASE + 9)
+#define NV_CTRL_STRING_GLX_OPENGL_VERSION (NV_CTRL_STRING_GLX_BASE + 10)
+#define NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS (NV_CTRL_STRING_GLX_BASE + 11)
+
+#define NV_CTRL_STRING_GLX_LAST_ATTRIBUTE \
+ (NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS)
+
+
/*
* NvCtrlAttributeInit() - intializes the control panel backend; this
@@ -140,10 +240,14 @@ typedef enum {
#define NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM 0x1
#define NV_CTRL_ATTRIBUTES_XF86VIDMODE_SUBSYSTEM 0x2
#define NV_CTRL_ATTRIBUTES_XVIDEO_SUBSYSTEM 0x4
+#define NV_CTRL_ATTRIBUTES_GLX_SUBSYSTEM 0x8
+#define NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM 0x10
#define NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS \
(NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM | \
NV_CTRL_ATTRIBUTES_XF86VIDMODE_SUBSYSTEM | \
- NV_CTRL_ATTRIBUTES_XVIDEO_SUBSYSTEM)
+ NV_CTRL_ATTRIBUTES_XVIDEO_SUBSYSTEM | \
+ NV_CTRL_ATTRIBUTES_GLX_SUBSYSTEM | \
+ NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM)
@@ -157,6 +261,7 @@ int NvCtrlGetScreen(NvCtrlAttributeHandle *handle);
int NvCtrlGetScreenWidth(NvCtrlAttributeHandle *handle);
int NvCtrlGetScreenHeight(NvCtrlAttributeHandle *handle);
int NvCtrlGetEventBase(NvCtrlAttributeHandle *handle);
+int NvCtrlGetXrandrEventBase(NvCtrlAttributeHandle *handle);
ReturnStatus NvCtrlGetColorAttributes (NvCtrlAttributeHandle *handle,
float contrast[3],
@@ -198,6 +303,17 @@ ReturnStatus NvCtrlSetAttribute (NvCtrlAttributeHandle *handle,
int attr, int val);
/*
+ * NvCtrlGetVoidAttribute() - this function works like the
+ * Get and GetString only it returns a void pointer. The
+ * data type pointed to is dependent on which attribute you
+ * are requesting.
+ */
+
+ReturnStatus NvCtrlGetVoidAttribute (NvCtrlAttributeHandle *handle,
+ int attr, void **ptr);
+
+
+/*
* NvCtrlGetValidAttributeValues() - get the valid settable values for
* the specified attribute. See the description of
* NVCTRLAttributeValidValuesRec in NVCtrl.h.
@@ -218,7 +334,7 @@ ReturnStatus NvCtrlGetStringAttribute (NvCtrlAttributeHandle *handle,
int attr, char **ptr);
/*
- * The following four functions are identical to the above four,
+ * The following four functions are identical to the above five,
* except that they specify a particular display mask.
*/
@@ -228,6 +344,12 @@ NvCtrlGetDisplayAttribute (NvCtrlAttributeHandle *handle,
ReturnStatus
NvCtrlSetDisplayAttribute (NvCtrlAttributeHandle *handle,
unsigned int display_mask, int attr, int val);
+
+ReturnStatus
+NvCtrlGetVoidDisplayAttribute (NvCtrlAttributeHandle *handle,
+ unsigned int display_mask,
+ int attr, void **val);
+
ReturnStatus
NvCtrlGetValidDisplayAttributeValues (NvCtrlAttributeHandle *handle,
unsigned int display_mask, int attr,
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c b/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c
new file mode 100644
index 0000000..2175da8
--- /dev/null
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c
@@ -0,0 +1,664 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include "NvCtrlAttributes.h"
+#include "NvCtrlAttributesPrivate.h"
+
+#include "NVCtrlLib.h"
+
+#include "msg.h"
+
+#include "parse.h"
+
+#include <X11/extensions/xf86vmode.h>
+#include <X11/extensions/Xvlib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <sys/utsname.h>
+
+#include <dlfcn.h> /* To dynamically load libGL.so */
+#include <GL/glx.h> /* GLX #defines */
+
+/****
+ *
+ * Provides a way to communicate GLX settings.
+ *
+ *
+ * Currently available attributes:
+ *
+ * GLX Information -----------------
+ *
+ * direct_rendering - STR
+ * glx_extensions - STR
+ *
+ *
+ * OpenGL --------------------------
+ *
+ * opengl_vendor_str - STR
+ * opengl_renderer_str - STR
+ * opengl_version_str - STR
+ * opengl_extensions - STR
+ *
+ *
+ * Server GLX Information ----------
+ *
+ * server_vendor_str - STR
+ * server_version_str - STR
+ * server_extensions - STR
+ *
+ *
+ * Client GLX Information ----------
+ *
+ * client_vendor_str - STR
+ * client_version_str - STR
+ * client_extensions - STR
+ *
+ *
+ * GLX Frame Buffer Information ----
+ *
+ * fbconfigs_attrib - ARRAY of GLXFBConfigAttr
+ *
+ ****/
+
+
+
+/******************************************************************************
+ *
+ * NvCtrlInitGlxAttributes()
+ *
+ * Initializes the NvCtrlGlxAttributes Extension by linking the libGL.so.1 and
+ * resolving functions used to retrieve GLX information.
+ *
+ * NOTE: A private dpy is kept due to a libGL.so.1 bug where closing the library
+ * before closing the dpy will cause XCloseDisplay to segfault.
+ *
+ ****/
+
+NvCtrlGlxAttributes *
+NvCtrlInitGlxAttributes (NvCtrlAttributePrivateHandle *h)
+{
+ NvCtrlGlxAttributes * glx = NULL;
+ const char * error = NULL; /* libGL error string */
+
+ /* For querying server about glx extension */
+ int errorBase;
+ int eventBase;
+ Bool (* glXQueryExtension) (Display *, int *, int *);
+
+
+
+ /* Check parameter */
+ if ( h == NULL || h->dpy == NULL ) {
+ goto fail;
+ }
+
+
+ /* Allocate for the GlxAttributes struct */
+ glx = (NvCtrlGlxAttributes *)
+ calloc(1, sizeof (NvCtrlGlxAttributes));
+ if ( glx == NULL ) {
+ error = "Out of memory.";
+ goto fail;
+ }
+
+
+ /* Link the libGL lib */
+ glx->libGL = dlopen("libGL.so.1", RTLD_LAZY);
+ if ( glx->libGL == NULL ) {
+ /* Silently fail */
+ goto fail;
+ }
+
+ /* Make sure GLX is supported by the server */
+ glXQueryExtension = dlsym(glx->libGL, "glXQueryExtension");
+ glx->dpy = XOpenDisplay( XDisplayString(h->dpy) );
+ if ( glx->dpy == NULL ) {
+ goto fail;
+ }
+ if ( !glXQueryExtension(glx->dpy, &errorBase, &eventBase) ) {
+ goto fail;
+ }
+
+
+ /* Resolve GLX functions */
+ glx->glGetString = dlsym(glx->libGL,
+ "glGetString");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXQueryExtensionsString = dlsym(glx->libGL,
+ "glXQueryExtensionsString");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXQueryServerString = dlsym(glx->libGL,
+ "glXQueryServerString");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXGetClientString = dlsym(glx->libGL,
+ "glXGetClientString");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXIsDirect = dlsym(glx->libGL,
+ "glXIsDirect");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXMakeCurrent = dlsym(glx->libGL,
+ "glXMakeCurrent");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXCreateContext = dlsym(glx->libGL,
+ "glXCreateContext");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXDestroyContext = dlsym(glx->libGL,
+ "glXDestroyContext");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXChooseVisual = dlsym(glx->libGL,
+ "glXChooseVisual");
+ if ((error = dlerror()) != NULL) goto fail;
+#ifdef GLX_VERSION_1_3
+ glx->glXGetFBConfigs = dlsym(glx->libGL,
+ "glXGetFBConfigs");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXGetFBConfigAttrib = dlsym(glx->libGL,
+ "glXGetFBConfigAttrib");
+ if ((error = dlerror()) != NULL) goto fail;
+ glx->glXGetVisualFromFBConfig = dlsym(glx->libGL,
+ "glXGetVisualFromFBConfig");
+ if ((error = dlerror()) != NULL) goto fail;
+#endif /* GLX_VERSION_1_3 */
+
+
+ return glx;
+
+
+ /* Handle failures */
+ fail:
+ if ( error != NULL ) {
+ nv_error_msg("libGL setup error : %s\n", error);
+ }
+ if ( glx != NULL ) {
+ if ( glx->dpy != NULL ) {
+ XCloseDisplay(glx->dpy);
+ }
+ if ( glx->libGL != NULL ) {
+ dlclose(glx->libGL);
+ }
+ free(glx);
+ }
+ return NULL;
+} /* NvCtrlInitGlxAttributes() */
+
+
+
+/******************************************************************************
+ *
+ * NvCtrlGlxAttributesClose()
+ *
+ * Frees and relinquishes any resource used by the NvCtrlGlxAttributes
+ * extension.
+ *
+ ****/
+
+void
+NvCtrlGlxAttributesClose (NvCtrlAttributePrivateHandle *h)
+{
+ if ( h == NULL || h->glx == NULL ) {
+ return;
+ }
+
+ if ( h->glx->dpy != NULL ) {
+ XCloseDisplay( h->glx->dpy );
+ }
+
+ if ( h->glx->libGL != NULL ) {
+ dlclose( h->glx->libGL );
+ }
+
+ free(h->glx);
+ h->glx = NULL;
+
+} /* NvCtrlGlxAttributesClose() */
+
+
+
+/******************************************************************************
+ *
+ * get_fbconfig_attribs()
+ *
+ *
+ * Returns an array of GLX Frame Buffer Configuration Attributes for the
+ * given Display/Screen.
+ *
+ * NOTE: A seperate display connection is used to avoid the dependence on
+ * libGL when an XCloseDisplay is issued. If we did not, calling
+ * XCloseDisplay AFTER the libGL library has been dlclose'ed (after
+ * having made at least one GLX call) would cause a segfault.
+ *
+ ****/
+
+#ifdef GLX_VERSION_1_3
+
+static GLXFBConfigAttr *
+get_fbconfig_attribs(NvCtrlAttributePrivateHandle *h)
+{
+ XVisualInfo * visinfo;
+
+ GLXFBConfigAttr * fbcas = NULL;
+ GLXFBConfig * fbconfigs = NULL;
+
+ int nfbconfigs;
+ int i; /* Used for indexing */
+ int ret; /* Return value of glXGetFBConfigAttr */
+
+
+
+ /* Some sanity */
+ if ( h == NULL || h->dpy == NULL || h->glx == NULL ) {
+ goto fail;
+ }
+
+ /* Get all fbconfigs for the display/screen */
+ fbconfigs = (* (h->glx->glXGetFBConfigs))( h->glx->dpy, h->screen,
+ &nfbconfigs);
+ if ( fbconfigs == NULL || nfbconfigs == 0 ) {
+ goto fail;
+ }
+
+ /* Allocate to hold the fbconfig attributes */
+ fbcas = calloc(nfbconfigs + 1, sizeof (GLXFBConfigAttr));
+ if ( fbcas == NULL ) {
+ goto fail;
+ }
+
+ /* Query each fbconfig's attributes and populate the attrib array */
+ for ( i = 0; i < nfbconfigs; i++ ) {
+
+ /* Get related visual id if any */
+ visinfo = (* (h->glx->glXGetVisualFromFBConfig)) (h->glx->dpy,
+ fbconfigs[i]);
+ if ( visinfo ) {
+ fbcas[i].visual_id = visinfo->visualid;
+ XFree(visinfo);
+ } else {
+ fbcas[i].visual_id = 0;
+ }
+
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy,
+ fbconfigs[i],
+ GLX_FBCONFIG_ID,
+ &(fbcas[i].fbconfig_id));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_BUFFER_SIZE,
+ &(fbcas[i].buffer_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_LEVEL,
+ &(fbcas[i].level));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_DOUBLEBUFFER,
+ &(fbcas[i].doublebuffer));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_STEREO,
+ &(fbcas[i].stereo));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_AUX_BUFFERS,
+ &(fbcas[i].aux_buffers));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_RED_SIZE,
+ &(fbcas[i].red_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_GREEN_SIZE,
+ &(fbcas[i].green_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_BLUE_SIZE,
+ &(fbcas[i].blue_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_ALPHA_SIZE,
+ &(fbcas[i].alpha_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_DEPTH_SIZE,
+ &(fbcas[i].depth_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_STENCIL_SIZE,
+ &(fbcas[i].stencil_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_ACCUM_RED_SIZE,
+ &(fbcas[i].accum_red_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_ACCUM_GREEN_SIZE,
+ &(fbcas[i].accum_green_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_ACCUM_BLUE_SIZE,
+ &(fbcas[i].accum_blue_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_ACCUM_ALPHA_SIZE,
+ &(fbcas[i].accum_alpha_size));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_RENDER_TYPE,
+ &(fbcas[i].render_type));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_DRAWABLE_TYPE,
+ &(fbcas[i].drawable_type));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_X_RENDERABLE,
+ &(fbcas[i].x_renderable));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_X_VISUAL_TYPE,
+ &(fbcas[i].x_visual_type));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_CONFIG_CAVEAT,
+ &(fbcas[i].config_caveat));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_TYPE,
+ &(fbcas[i].transparent_type));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_INDEX_VALUE,
+ &(fbcas[i].transparent_index_value));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_RED_VALUE,
+ &(fbcas[i].transparent_red_value));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_GREEN_VALUE,
+ &(fbcas[i].transparent_green_value));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_BLUE_VALUE,
+ &(fbcas[i].transparent_blue_value));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_TRANSPARENT_ALPHA_VALUE,
+ &(fbcas[i].transparent_alpha_value));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_MAX_PBUFFER_WIDTH,
+ &(fbcas[i].pbuffer_width));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_MAX_PBUFFER_HEIGHT,
+ &(fbcas[i].pbuffer_height));
+ if ( ret != Success ) goto fail;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_MAX_PBUFFER_PIXELS,
+ &(fbcas[i].pbuffer_max));
+ if ( ret != Success ) goto fail;
+
+#if defined(GLX_SAMPLES_ARB) && defined (GLX_SAMPLE_BUFFERS_ARB)
+ fbcas[i].multi_sample_valid = 1;
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy, fbconfigs[i],
+ GLX_SAMPLES_ARB,
+ &(fbcas[i].multi_samples));
+ if ( ret != Success ) {
+ fbcas[i].multi_sample_valid = 0;
+ } else {
+ ret = (* (h->glx->glXGetFBConfigAttrib)) (h->glx->dpy,
+ fbconfigs[i],
+ GLX_SAMPLE_BUFFERS_ARB,
+ &(fbcas[i].multi_sample_buffers));
+ if ( ret != Success ) {
+ fbcas[i].multi_sample_valid = 0;
+ }
+ }
+#else
+#warning Multisample extension not found, will not print multisample information!
+ fbcas[i].multi_sample_valid = 0;
+#endif /* Multisample extension */
+
+ } /* Done reading fbconfig information */
+
+
+ XFree(fbconfigs);
+ return fbcas;
+
+
+ /* Handle failures */
+ fail:
+ if ( fbcas != NULL ) {
+ free(fbcas);
+ }
+ if ( fbconfigs != NULL ) {
+ XFree(fbconfigs);
+ }
+
+ return NULL;
+} /* get_fbconfig_attribs() */
+
+#endif /* GLX_VERSION_1_3 */
+
+
+
+/******************************************************************************
+ *
+ * NvCtrlGlxGetVoidAttribute()
+ *
+ * Retrieves various GLX attributes (other than strings and ints)
+ *
+ ****/
+
+ReturnStatus
+NvCtrlGlxGetVoidAttribute (NvCtrlAttributePrivateHandle *h,
+ unsigned int display_mask,
+ int attr, void **ptr)
+{
+ GLXFBConfigAttr * fbconfig_attribs = NULL;
+
+
+ /* Validate Arguments */
+ if (h == NULL || ptr == NULL) {
+ return NvCtrlBadArgument;
+ }
+
+
+ /* Fetch the right attribute */
+ switch ( attr ) {
+
+#ifdef GLX_VERSION_1_3
+ case NV_CTRL_ATTR_GLX_FBCONFIG_ATTRIBS:
+ fbconfig_attribs = get_fbconfig_attribs(h);
+ *ptr = fbconfig_attribs;
+ break;
+#endif
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done fetching attribute */
+
+
+ if ( *ptr == NULL ) {
+ return NvCtrlError;
+ }
+ return NvCtrlSuccess;
+
+} /* NvCtrlGlxGetAttribute */
+
+
+
+
+/******************************************************************************
+ *
+ * NvCtrlGlxGetStringAttribute()
+ *
+ *
+ * Retrieves a particular GLX information string by calling the appropreate
+ * OpenGL/GLX function.
+ *
+ *
+ * But first, the following macros are used to setup a rendering context
+ * such that valid information may be retrieved. (Having a context is
+ * required for getting OpenGL and 'Direct rendering' information.)
+ *
+ * NOTE: A seperate display connection is used to avoid the dependence on
+ * libGL when an XCloseDisplay is issued. If we did not, calling
+ * XCloseDisplay AFTER the libGL library has been dlclose'ed (after
+ * having made at least one GLX call) would cause a segfault.
+ *
+ ****/
+
+/* Macros to set up/tear down a rendering context */
+
+#define GET_CONTEXT() \
+ \
+ root = RootWindow(h->glx->dpy, h->screen); \
+ visinfo = h->glx->glXChooseVisual(h->glx->dpy, h->screen, \
+ &(attribListSgl[0])); \
+ win_attr.background_pixel = 0; \
+ win_attr.border_pixel = 0; \
+ win_attr.colormap = XCreateColormap(h->glx->dpy, root, \
+ visinfo->visual, AllocNone); \
+ win_attr.event_mask = StructureNotifyMask | ExposureMask; \
+ mask = CWBackPixel | CWBorderPixel | CWColormap | \
+ CWEventMask; \
+ win = XCreateWindow(h->glx->dpy, root, 0, 0, width, height, \
+ 0, visinfo->depth, InputOutput, \
+ visinfo->visual, mask, &win_attr); \
+ ctx = h->glx->glXCreateContext(h->glx->dpy, visinfo, NULL, True ); \
+ if ( ctx ) { h->glx->glXMakeCurrent(h->glx->dpy, win, ctx); }
+
+#define CLEAN_CONTEXT() \
+ \
+ if ( visinfo ) { XFree(visinfo); } \
+ if ( ctx ) { h->glx->glXDestroyContext(h->glx->dpy, ctx); } \
+ if ( win ) { XDestroyWindow(h->glx->dpy, win); }
+
+
+ReturnStatus
+NvCtrlGlxGetStringAttribute (NvCtrlAttributePrivateHandle *h,
+ unsigned int display_mask,
+ int attr, char **ptr)
+{
+ const char *str = NULL;
+
+ /* These variables are required for getting some OpenGL/GLX Information */
+ Window win;
+ Window root;
+ GLXContext ctx;
+ XVisualInfo *visinfo;
+ XSetWindowAttributes win_attr; /* Used for creating a gc */
+ unsigned long mask;
+ int width = 100;
+ int height = 100;
+
+ static int attribListSgl[] = { GLX_RGBA,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None };
+
+
+ /* Validate Arguments */
+ if (h == NULL || ptr == NULL) {
+ return NvCtrlBadArgument;
+ }
+
+ /* Make sure extension was initialized */
+ if ( h->glx == NULL ) {
+ return NvCtrlError;
+ }
+
+ /* Get the right string */
+ switch (attr) {
+
+ case NV_CTRL_STRING_GLX_DIRECT_RENDERING:
+ GET_CONTEXT();
+ str = ( (* (h->glx->glXIsDirect))(h->glx->dpy, ctx) ) ? "Yes" : "No";
+ CLEAN_CONTEXT();
+ break;
+ case NV_CTRL_STRING_GLX_GLX_EXTENSIONS:
+ str = (* (h->glx->glXQueryExtensionsString))(h->glx->dpy, h->screen);
+ break;
+ case NV_CTRL_STRING_GLX_SERVER_VENDOR:
+ str = (* (h->glx->glXQueryServerString))(h->glx->dpy, h->screen,
+ GLX_VENDOR);
+ break;
+ case NV_CTRL_STRING_GLX_SERVER_VERSION:
+ str = (* (h->glx->glXQueryServerString))(h->glx->dpy, h->screen,
+ GLX_VERSION);
+ break;
+ case NV_CTRL_STRING_GLX_SERVER_EXTENSIONS:
+ str = (* (h->glx->glXQueryServerString))(h->glx->dpy, h->screen,
+ GLX_EXTENSIONS);
+ break;
+ case NV_CTRL_STRING_GLX_CLIENT_VENDOR:
+ str = (* (h->glx->glXGetClientString))(h->glx->dpy, GLX_VENDOR);
+ break;
+ case NV_CTRL_STRING_GLX_CLIENT_VERSION:
+ str = (* (h->glx->glXGetClientString))(h->glx->dpy, GLX_VERSION);
+ break;
+ case NV_CTRL_STRING_GLX_CLIENT_EXTENSIONS:
+ str = (* (h->glx->glXGetClientString))(h->glx->dpy, GLX_EXTENSIONS);
+ break;
+ case NV_CTRL_STRING_GLX_OPENGL_VENDOR:
+ GET_CONTEXT();
+ str = (const char *) (* (h->glx->glGetString))(GL_VENDOR);
+ CLEAN_CONTEXT();
+ break;
+ case NV_CTRL_STRING_GLX_OPENGL_RENDERER:
+ GET_CONTEXT();
+ str = (const char *) (* (h->glx->glGetString))(GL_RENDERER);
+ CLEAN_CONTEXT();
+ break;
+ case NV_CTRL_STRING_GLX_OPENGL_VERSION:
+ GET_CONTEXT();
+ str = (const char *) (* (h->glx->glGetString))(GL_VERSION);
+ CLEAN_CONTEXT();
+ break;
+ case NV_CTRL_STRING_GLX_OPENGL_EXTENSIONS:
+ GET_CONTEXT();
+ str = (const char *) (* (h->glx->glGetString))(GL_EXTENSIONS);
+ CLEAN_CONTEXT();
+ break;
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done - Fetching corresponding string attribute */
+
+
+ /* Copy the string and return it */
+ if ( str == NULL ||
+ (*ptr = strdup(str)) == NULL ) {
+ return NvCtrlError;
+ }
+
+ return NvCtrlSuccess;
+
+} /* NvCtrlGlxGetStringAttribute() */
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
index bea6a49..294cad2 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
@@ -27,10 +27,15 @@
#include "NvCtrlAttributes.h"
#include "NVCtrl.h"
+#include <GL/glx.h> /* GLX #defines */
+#include <X11/extensions/Xrandr.h> /* Xrandr */
+
#define EXTENSION_NV_CONTROL 0x1
#define EXTENSION_XF86VIDMODE 0x2
#define EXTENSION_XVIDEO 0x4
+#define EXTENSION_GLX 0x8
+#define EXTENSION_XRANDR 0x10
/* caps bits */
@@ -73,6 +78,8 @@ typedef struct __NvCtrlXvOverlayAttributes NvCtrlXvOverlayAttributes;
typedef struct __NvCtrlXvTextureAttributes NvCtrlXvTextureAttributes;
typedef struct __NvCtrlXvBlitterAttributes NvCtrlXvBlitterAttributes;
typedef struct __NvCtrlXvAttribute NvCtrlXvAttribute;
+typedef struct __NvCtrlGlxAttributes NvCtrlGlxAttributes;
+typedef struct __NvCtrlXrandrAttributes NvCtrlXrandrAttributes;
struct __NvCtrlNvControlAttributes {
int event_base;
@@ -114,6 +121,74 @@ struct __NvCtrlXvBlitterAttributes {
NvCtrlXvAttribute *defaults;
};
+struct __NvCtrlGlxAttributes {
+
+ /* Private display connection for the GLX information ext. */
+ Display *dpy;
+
+ /* libGL.so library handle */
+ void *libGL;
+
+ /* OpenGL functions used */
+ const GLubyte * (* glGetString) (GLenum);
+
+ /* GLX functions used */
+ const char * (* glXQueryServerString) (Display *, int, int);
+ const char * (* glXGetClientString) (Display *, int);
+ const char * (* glXQueryExtensionsString) (Display *, int);
+
+ Bool (* glXIsDirect) (Display *, GLXContext);
+ Bool (* glXMakeCurrent) (Display *, GLXDrawable,
+ GLXContext);
+ GLXContext (* glXCreateContext) (Display *, XVisualInfo *,
+ GLXContext, Bool);
+ void (* glXDestroyContext) (Display *, GLXContext);
+ XVisualInfo * (* glXChooseVisual) (Display *, int, int *);
+#ifdef GLX_VERSION_1_3
+ GLXFBConfig * (* glXGetFBConfigs) (Display *, int, int *);
+ int (* glXGetFBConfigAttrib) (Display *, GLXFBConfig,
+ int, int *);
+ XVisualInfo * (* glXGetVisualFromFBConfig) (Display *, GLXFBConfig);
+#endif /* GLX_VERSION_1_3 */
+};
+
+struct __NvCtrlXrandrAttributes {
+
+ /* libXrandr.so library handle */
+ void *libXrandr;
+ int event_base; /* XRandR extension event base */
+ int error_base;
+ Rotation rotations; /* Valid rotations */
+ int nsizes; /* Valid sizes */
+
+ /* XRandR functions used */
+ Bool (* XRRQueryExtension) (Display *dpy,
+ int *event_base,
+ int *error_base);
+ void (* XRRSelectInput) (Display *dpy, Window window,
+ int mask);
+
+ SizeID (* XRRConfigCurrentConfiguration) (XRRScreenConfiguration *config,
+ Rotation *rotation);
+
+ XRRScreenConfiguration * (* XRRGetScreenInfo) (Display *dpy, Drawable draw);
+
+ Rotation (* XRRConfigRotations) (XRRScreenConfiguration *config,
+ Rotation *rotation);
+
+ void (* XRRFreeScreenConfigInfo) (XRRScreenConfiguration *);
+
+ Rotation (* XRRRotations) (Display *dpy, int screen, Rotation *current_rotation);
+ XRRScreenSize *(* XRRSizes) (Display *dpy, int screen, int *nsizes);
+
+ Status (* XRRSetScreenConfig) (Display *dpy,
+ XRRScreenConfiguration *config,
+ Drawable draw,
+ int size_index,
+ Rotation rotation,
+ Time timestamp);
+};
+
struct __NvCtrlAttributePrivateHandle {
Display *dpy; /* display connection */
int screen; /* the screen that this handle controls */
@@ -122,6 +197,8 @@ struct __NvCtrlAttributePrivateHandle {
NvCtrlXvOverlayAttributes *xv_overlay; /* XVideo info (overlay) */
NvCtrlXvTextureAttributes *xv_texture; /* XVideo info (texture) */
NvCtrlXvBlitterAttributes *xv_blitter; /* XVideo info (blitter) */
+ NvCtrlGlxAttributes *glx; /* GLX extension info */
+ NvCtrlXrandrAttributes *xrandr; /* XRandR extension info */
};
NvCtrlNvControlAttributes *
@@ -132,6 +209,45 @@ NvCtrlInitVidModeAttributes (NvCtrlAttributePrivateHandle *);
void NvCtrlInitXvOverlayAttributes (NvCtrlAttributePrivateHandle *);
+
+/* GLX extension attribute functions */
+
+NvCtrlGlxAttributes *
+NvCtrlInitGlxAttributes (NvCtrlAttributePrivateHandle *h);
+
+void
+NvCtrlGlxAttributesClose (NvCtrlAttributePrivateHandle *h);
+
+ReturnStatus
+NvCtrlGlxGetVoidAttribute (NvCtrlAttributePrivateHandle *,
+ unsigned int,
+ int, void **);
+
+ReturnStatus
+NvCtrlGlxGetStringAttribute (NvCtrlAttributePrivateHandle *,
+ unsigned int,
+ int, char **);
+
+
+/* XRandR extension attribute functions */
+
+NvCtrlXrandrAttributes *
+NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h);
+
+void
+NvCtrlXrandrAttributesClose (NvCtrlAttributePrivateHandle *h);
+
+ReturnStatus
+NvCtrlXrandrGetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int *val);
+
+ReturnStatus
+NvCtrlXrandrSetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int val);
+
+
+/* Generic attribute functions */
+
ReturnStatus
NvCtrlNvControlGetAttribute (NvCtrlAttributePrivateHandle *, unsigned int,
int, int *);
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
new file mode 100644
index 0000000..829c439
--- /dev/null
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
@@ -0,0 +1,329 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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 Version 2
+ * of 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.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+/*
+ * XRandR backend
+ *
+ * Currently only rotation is supported.
+ *
+ */
+
+#include <sys/utsname.h>
+
+#include <stdlib.h> /* 64 bit malloc */
+
+#include <dlfcn.h> /* To dynamically load libXrandr.so.2 */
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h> /* Xrandr */
+
+#include "NvCtrlAttributes.h"
+#include "NvCtrlAttributesPrivate.h"
+#include "NVCtrlLib.h"
+
+#include "msg.h"
+#include "parse.h"
+
+
+
+/******************************************************************************
+ *
+ * Sets the requested rotation orientation.
+ *
+ ****/
+
+static ReturnStatus
+set_rotation(NvCtrlAttributePrivateHandle *h, Rotation rotation)
+{
+ XRRScreenConfiguration *sc;
+ Rotation cur_rotation;
+ SizeID cur_size;
+ Status status;
+
+
+ /* Check orientation is supported */
+ if ( !( h->xrandr->rotations & rotation ) ) {
+ return NvCtrlBadArgument;
+ }
+
+ /* Get current size & orientation */
+ sc = h->xrandr->XRRGetScreenInfo(h->dpy, DefaultRootWindow(h->dpy));
+ if ( !sc ) {
+ return NvCtrlError;
+ }
+ cur_size = h->xrandr->XRRConfigCurrentConfiguration(sc, &cur_rotation);
+
+ status = h->xrandr->XRRSetScreenConfig (h->dpy, sc,
+ DefaultRootWindow(h->dpy),
+ cur_size, rotation, CurrentTime);
+ h->xrandr->XRRFreeScreenConfigInfo(sc);
+
+ if ( status != Success ) {
+ return NvCtrlError;
+ }
+
+ return NvCtrlSuccess;
+
+} /* set_rotation() */
+
+
+
+/******************************************************************************
+ *
+ * Initializes the NvCtrlXrandrAttributes Extension by linking the
+ * libXrandr.so.2 library and resolving functions used.
+ *
+ ****/
+
+NvCtrlXrandrAttributes *
+NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h)
+{
+ NvCtrlXrandrAttributes *xrandr = NULL;
+ const char *error = NULL; /* libXrandr error string */
+ Bool ret;
+ Rotation rotation;
+ XRRScreenSize *sizes;
+
+
+ /* Check parameter */
+ if ( h == NULL || h->dpy == NULL ) {
+ goto fail;
+ }
+
+
+ /* Allocate attributes structure */
+ xrandr = (NvCtrlXrandrAttributes *)
+ calloc(1, sizeof (NvCtrlXrandrAttributes));
+ if ( xrandr == NULL ) {
+ error = "Out of memory.";
+ goto fail;
+ }
+
+
+ /* Link the libXrandr lib */
+ xrandr->libXrandr = dlopen("libXrandr.so.2", RTLD_LAZY);
+ if ( xrandr->libXrandr == NULL ) {
+ /* Silently fail */
+ goto fail;
+ }
+
+
+ /* Resolve XRandR functions */
+ xrandr->XRRQueryExtension = dlsym(xrandr->libXrandr,
+ "XRRQueryExtension");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSelectInput = dlsym(xrandr->libXrandr, "XRRSelectInput");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRConfigCurrentConfiguration = dlsym(xrandr->libXrandr,
+ "XRRConfigCurrentConfiguration");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRGetScreenInfo = dlsym(xrandr->libXrandr,
+ "XRRGetScreenInfo");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRConfigRotations = dlsym(xrandr->libXrandr, "XRRConfigRotations");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRFreeScreenConfigInfo = dlsym(xrandr->libXrandr,
+ "XRRFreeScreenConfigInfo");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSetScreenConfig = dlsym(xrandr->libXrandr,
+ "XRRSetScreenConfig");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRRotations = dlsym(xrandr->libXrandr, "XRRRotations");
+ if ((error = dlerror()) != NULL) goto fail;
+
+ xrandr->XRRSizes = dlsym(xrandr->libXrandr, "XRRSizes");
+ if ((error = dlerror()) != NULL) goto fail;
+
+
+ /* Verify rotation is supported */
+ ret = xrandr->XRRQueryExtension(h->dpy, &xrandr->event_base,
+ &xrandr->error_base);
+ if ( !ret ) goto fail;
+
+ xrandr->rotations = xrandr->XRRRotations(h->dpy, h->screen, &rotation);
+ sizes = xrandr->XRRSizes(h->dpy, h->screen, &(xrandr->nsizes));
+
+ /* Must support more than one rotation orientation */
+ if ( (xrandr->rotations == 1) || (xrandr->rotations == 2) ||
+ (xrandr->rotations == 4) || (xrandr->rotations == 8) ) {
+ goto fail;
+ }
+
+
+ /* Register to recieve XRandR events */
+ xrandr->XRRSelectInput(h->dpy, DefaultRootWindow(h->dpy),
+ RRScreenChangeNotifyMask);
+
+ // xrandr->rotations = 1;
+
+ return xrandr;
+
+
+ /* Handle failures */
+ fail:
+ if ( error != NULL ) {
+ nv_error_msg("libXrandr setup error : %s\n", error);
+ }
+ if ( xrandr != NULL ) {
+ if ( xrandr->libXrandr != NULL ) {
+ dlclose(xrandr->libXrandr);
+ }
+ free(xrandr);
+ }
+
+ return NULL;
+
+} /* NvCtrlInitXrandrAttributes() */
+
+
+
+/******************************************************************************
+ *
+ * Frees and relinquishes any resource used by the NvCtrlXrandrAttributes
+ * extension.
+ *
+ ****/
+
+void
+NvCtrlXrandrAttributesClose (NvCtrlAttributePrivateHandle *h)
+{
+ if ( h == NULL || h->xrandr == NULL ) {
+ return;
+ }
+
+ if ( h->xrandr->libXrandr != NULL ) {
+ dlclose( h->xrandr->libXrandr );
+ }
+
+ free(h->xrandr);
+ h->xrandr = NULL;
+
+} /* NvCtrlXrandrAttributesClose() */
+
+
+
+/******************************************************************************
+ *
+ * Retrieves XRandR integer attributes
+ *
+ ****/
+
+ReturnStatus
+NvCtrlXrandrGetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int *val)
+{
+ XRRScreenConfiguration *sc;
+ Rotation rotation;
+
+
+ /* Validate Arguments */
+ if ( h == NULL ) {
+ return NvCtrlBadHandle;
+ }
+ if ( h->xrandr == NULL ) {
+ return NvCtrlMissingExtension;
+ }
+ if ( val == NULL ) {
+ return NvCtrlBadArgument;
+ }
+
+
+ /* Fetch right attribute */
+ switch ( attr ) {
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED:
+ *val = ( (h->xrandr!=NULL)?1:0 );
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATIONS:
+ *val = h->xrandr->rotations;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION:
+ sc = h->xrandr->XRRGetScreenInfo(h->dpy, DefaultRootWindow(h->dpy));
+ h->xrandr->XRRConfigRotations(sc, &rotation);
+ h->xrandr->XRRFreeScreenConfigInfo(sc);
+
+ *val = (int)rotation;
+ break;
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done fetching attribute */
+
+ return NvCtrlSuccess;
+
+} /* NvCtrlXrandrGetAttribute */
+
+
+
+/******************************************************************************
+ *
+ * Sets XRandR integer attributes
+ *
+ ****/
+
+ReturnStatus
+NvCtrlXrandrSetAttribute (NvCtrlAttributePrivateHandle *h,
+ int attr, int val)
+{
+ /* Validate Arguments */
+ if ( h == NULL ) {
+ return NvCtrlBadHandle;
+ }
+ if ( h->xrandr == NULL ) {
+ return NvCtrlMissingExtension;
+ }
+
+
+ /* Set right attribute */
+ switch ( attr ) {
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION_SUPPORTED:
+ return NvCtrlReadOnlyAttribute;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATIONS:
+ return NvCtrlReadOnlyAttribute;
+ break;
+
+ case NV_CTRL_ATTR_XRANDR_ROTATION:
+ return set_rotation(h, (Rotation) val);
+ break;
+
+ default:
+ return NvCtrlNoAttribute;
+ break;
+ } /* Done setting attribute */
+
+ return NvCtrlSuccess;
+
+} /* NvCtrlXrandrSetAttribute */
diff --git a/src/msg.c b/src/msg.c
index 0642a65..002f2b4 100644
--- a/src/msg.c
+++ b/src/msg.c
@@ -31,10 +31,21 @@
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
+#if defined(__sun)
+#include <sys/termios.h>
+#endif
-static void format(FILE*, const char*, const char *, va_list);
+static void format(FILE*, const char*, char *);
static int get_terminal_width(void);
+#define NV_FORMAT(stream, prefix, fmt) \
+do { \
+ char *buf; \
+ NV_VSNPRINTF(buf, fmt); \
+ format(stream, prefix, buf); \
+ free (buf); \
+} while(0)
+
/*
* nv_error_msg() - print an error message, nicely formatted using the
* format() function.
@@ -42,13 +53,9 @@ static int get_terminal_width(void);
void nv_error_msg(const char *fmt, ...)
{
- va_list ap;
-
fprintf(stderr, "\n");
- va_start(ap, fmt);
- format(stderr, "ERROR: ", fmt, ap);
- va_end(ap);
+ NV_FORMAT(stderr, "ERROR: ", fmt);
fprintf(stderr, "\n");
@@ -63,13 +70,9 @@ void nv_error_msg(const char *fmt, ...)
void nv_warning_msg(const char *fmt, ...)
{
- va_list ap;
-
fprintf(stdout, "\n");
- va_start(ap, fmt);
- format(stdout, "WARNING: ", fmt, ap);
- va_end(ap);
+ NV_FORMAT(stdout, "WARNING: ", fmt);
fprintf(stdout, "\n");
@@ -84,10 +87,7 @@ void nv_warning_msg(const char *fmt, ...)
void nv_msg(const char *prefix, const char *fmt, ...)
{
- va_list ap;
- va_start(ap, fmt);
- format(stdout, prefix, fmt, ap);
- va_end(ap);
+ NV_FORMAT(stdout, prefix, fmt);
} /* nv_msg() */
@@ -105,69 +105,17 @@ int vsnprintf(char *str, size_t size, const char *format,
-#define FMT_BUF_LEN 256
-
/*
- * nv_build_vararg_string() - return an alloced string, assembled
- * using vsnprintf().
- */
-
-char *nv_build_vararg_string(const char *fmt, va_list ap)
-{
- int len, finished, current_len;
- char *buf;
-
- finished = 0;
- current_len = FMT_BUF_LEN;
- buf = malloc(current_len);
- do {
- len = vsnprintf(buf, current_len, fmt, ap);
- if ((len == -1) || len > current_len) {
-
- /*
- * if we get in here we know that vsnprintf had to truncate the
- * string to make it fit in the buffer... we need to extend the
- * buffer to encompass the string. Unfortunately, we have to deal
- * with two different semantics of the return value from
- * (v)snprintf:
- *
- * -1 when the buffer is not long enough (glibc < 2.1)
- *
- * or
- *
- * the length the string would have been if the buffer had been
- * large enough (glibc >= 2.1)
- */
-
- if (len == -1) current_len += FMT_BUF_LEN;
- else current_len = len+1;
- buf = realloc(buf, current_len);
- }
- else finished = 1;
-
- } while (!finished);
-
- return buf;
-
-} /* nv_build_vararg_string() */
-
-
-
-/*
- * format() - this takes a printf-style format string and a variable
- * list of args. We use sprintf to generate the desired string, and
- * then format the string so that not more than 80 characters are
- * printed across.
+ * format() - formats and prints the string buf so that no more than
+ * 80 characters are printed across.
*/
static void format(FILE *stream, const char *prefix,
- const char *fmt, va_list ap)
+ char *buf)
{
int len, prefix_len, z, w, i, max_width;
- char *buf, *line, *local_prefix, *a, *b, *c;
+ char *line, *local_prefix, *a, *b, *c;
- buf = nv_build_vararg_string(fmt, ap);
-
max_width = get_terminal_width();
/* loop until we've printed the entire string */
@@ -255,7 +203,6 @@ static void format(FILE *stream, const char *prefix,
} while (z > 0);
- free (buf);
if (local_prefix) free (local_prefix);
} /* format() */
diff --git a/src/msg.h b/src/msg.h
index 3c85dcd..ea90486 100644
--- a/src/msg.h
+++ b/src/msg.h
@@ -30,6 +30,47 @@
void nv_error_msg(const char*, ...);
void nv_warning_msg(const char*, ...);
void nv_msg(const char*, const char*, ...);
-char *nv_build_vararg_string(const char *fmt, va_list ap);
+
+/*
+ * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is
+ * correct for differing semantics of vsnprintf() in different
+ * versions of glibc:
+ *
+ * different semantics of the return value from (v)snprintf:
+ *
+ * -1 when the buffer is not long enough (glibc < 2.1)
+ *
+ * or
+ *
+ * the length the string would have been if the buffer had been large
+ * enough (glibc >= 2.1)
+ *
+ * This macro allocates memory for buf; the caller should use free()
+ * when done.
+ */
+#define NV_FMT_BUF_LEN 256
+#define NV_VSNPRINTF(buf, fmt) \
+do { \
+ va_list ap; \
+ int len, current_len = NV_FMT_BUF_LEN; \
+ \
+ (buf) = malloc(current_len); \
+ \
+ while (1) { \
+ va_start(ap, fmt); \
+ len = vsnprintf((buf), current_len, (fmt), ap); \
+ va_end(ap); \
+ \
+ if ((len > -1) && (len < current_len)) { \
+ break; \
+ } else if (len > -1) { \
+ current_len = len + 1; \
+ } else { \
+ current_len += NV_FMT_BUF_LEN; \
+ } \
+ \
+ (buf) = realloc(buf, current_len); \
+ } \
+} while (0)
#endif /* __MSG_H__ */
diff --git a/src/query-assign.c b/src/query-assign.c
index b9674e6..f8637b1 100644
--- a/src/query-assign.c
+++ b/src/query-assign.c
@@ -753,7 +753,6 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
int screen, start_screen, end_screen, bit, ret, val;
char *whence, *tmp_d_str0, *tmp_d_str1;
uint32 display_devices, mask;
- va_list ap;
ReturnStatus status;
NVCTRLAttributeValidValuesRec valid;
@@ -761,9 +760,7 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
/* build the description */
- va_start(ap, whence_fmt);
- whence = nv_build_vararg_string(whence_fmt, ap);
- va_end(ap);
+ NV_VSNPRINTF(whence, whence_fmt);
if (!whence) whence = strdup("\0");