diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-02-12 21:06:48 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-02-12 21:06:48 -0800 |
commit | 62e3914fdaac08d83e07e0ac786de4c273a3fdb5 (patch) | |
tree | d8eb142e29179b6085f70686efe36d1da794fe5a | |
parent | edd7bf5b8a4073387e4dad37269572ec4d1b6a59 (diff) |
1.0-71671.0-7167
30 files changed, 3950 insertions, 147 deletions
@@ -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 Binary files differindex 83c81c6..e981c13 100644 --- a/src/libXNVCtrl/libXNVCtrl.a +++ b/src/libXNVCtrl/libXNVCtrl.a 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 */ @@ -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() */ @@ -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"); |