summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2013-10-04 08:47:45 -0700
committerAaron Plattner <aplattner@nvidia.com>2013-10-04 08:47:45 -0700
commitdb3b5f655464386838d0c5859cddaf6c4f812979 (patch)
treed0b3a4e3f065eea69098c1f9e931914cdecdaf67
parent2e80e4fdc20e051090289e4b32d713a7c4f7e14c (diff)
331.13331.13
-rw-r--r--doc/version.mk2
-rw-r--r--samples/nv-control-dpy.c175
-rw-r--r--samples/nv-control-events.c25
-rw-r--r--samples/nv-control-info.c7
-rw-r--r--samples/nv-control-targets.c179
-rw-r--r--samples/nv-control-warpblend.h4
-rw-r--r--samples/version.mk2
-rw-r--r--src/XF86Config-parser/Flags.c85
-rw-r--r--src/XF86Config-parser/xf86Parser.h9
-rw-r--r--src/app-profiles.c104
-rw-r--r--src/app-profiles.h6
-rw-r--r--src/command-line.c42
-rw-r--r--src/common-utils/common-utils.c24
-rw-r--r--src/common-utils/common-utils.h17
-rw-r--r--src/common-utils/gen-manpage-opts-helper.c2
-rw-r--r--src/common-utils/nvgetopt.h4
-rw-r--r--src/config-file.c117
-rw-r--r--src/gtk+-2.x/ctkappprofile.c33
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.c205
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig-utils.h2
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.c387
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice.c35
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.c147
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.h10
-rw-r--r--src/gtk+-2.x/ctkevent.c7
-rw-r--r--src/gtk+-2.x/ctkframelock.c1341
-rw-r--r--src/gtk+-2.x/ctkgpu.c226
-rw-r--r--src/gtk+-2.x/ctkgpu.h8
-rw-r--r--src/gtk+-2.x/ctkgvi.c2
-rw-r--r--src/gtk+-2.x/ctklicense.c10
-rw-r--r--src/gtk+-2.x/ctkpowermizer.c348
-rw-r--r--src/gtk+-2.x/ctkpowermizer.h6
-rw-r--r--src/gtk+-2.x/ctkscreen.c26
-rw-r--r--src/gtk+-2.x/ctkscreen.h5
-rw-r--r--src/gtk+-2.x/ctkslimm.c122
-rw-r--r--src/gtk+-2.x/ctkthermal.c47
-rw-r--r--src/gtk+-2.x/ctkwindow.c82
-rw-r--r--src/gtk+-2.x/ctkxvideo.c648
-rw-r--r--src/gtk+-2.x/ctkxvideo.h7
-rw-r--r--src/libXNVCtrl/NVCtrl.h82
-rw-r--r--src/nvidia-settings.c11
-rw-r--r--src/option-table.h10
-rw-r--r--src/parse.c37
-rw-r--r--src/parse.h4
-rw-r--r--src/query-assign.c865
-rw-r--r--src/query-assign.h10
-rw-r--r--src/version.mk2
-rw-r--r--utils.mk2
-rw-r--r--version.mk2
49 files changed, 3123 insertions, 2410 deletions
diff --git a/doc/version.mk b/doc/version.mk
index 8a89afe..2abb57a 100644
--- a/doc/version.mk
+++ b/doc/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 325.15
+NVIDIA_VERSION = 331.13
diff --git a/samples/nv-control-dpy.c b/samples/nv-control-dpy.c
index 4371270..437cea1 100644
--- a/samples/nv-control-dpy.c
+++ b/samples/nv-control-dpy.c
@@ -45,7 +45,6 @@
static char *display_device_name(int mask);
static unsigned int display_device_mask(char *str);
static char *remove_whitespace(char *str);
-static int count_bits(unsigned int mask);
static void parse_mode_string(char *modeString, char **modeName,
unsigned int *mask);
static char *find_modeline(char *modeString, char *pModeLines,
@@ -1096,158 +1095,6 @@ int main(int argc, char *argv[])
}
}
}
-
-
- /*
- * demonstrate how to programmatically transition into TwinView
- * using NV-CONTROL and XRandR; the process is roughly:
- *
- * - probe for new display devices
- *
- * - if we found any new display devices, create a mode pool for
- * the new display devices
- *
- * - associate any new display devices to the X screen, so that
- * they are available for MetaMode assignment.
- *
- * - add a new MetaMode
- *
- * We have skipped error checking, and checking for things like if
- * we are already using multiple display devices, but this gives
- * the general idea.
- */
-
- else if (strcmp(argv[1], "--dynamic-twinview") == 0) {
-
- char *pOut;
- int id;
-
- /*
- * first, probe for new display devices; while
- * NV_CTRL_CONNECTED_DISPLAYS reports what the NVIDIA X driver
- * believes is currently connected to the GPU,
- * NV_CTRL_PROBE_DISPLAYS forces the driver to redetect what
- * is connected.
- */
-
- XNVCTRLQueryAttribute(dpy,
- screen,
- 0,
- NV_CTRL_PROBE_DISPLAYS,
- &display_devices);
-
- /*
- * if we don't have atleast two display devices, there is
- * nothing to do
- */
-
- printf("probed display device mask: 0x%08x\n\n", display_devices);
-
- if (count_bits(display_devices) < 2) {
- printf("only one display device found; cannot enable "
- "TwinView.\n\n");
- return 1;
- }
-
-
- /*
- * next, make sure all display devices have a modepool; a more
- * sophisticated client could use
- * NV_CTRL_BINARY_DATA_MODELINES to query if a pool of
- * modelines already exist on each display device we care
- * about.
- */
-
- for (mask = 1; mask < (1 << 24); mask <<= 1) {
-
- if (!(display_devices & mask)) continue;
-
- XNVCTRLStringOperation(dpy,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen,
- mask,
- NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL,
- NULL,
- NULL);
- }
-
- printf("all display devices should now have a mode pool.\n\n");
-
-
- /*
- * associate all the probed display devices to the X screen;
- * this makes the display devices available for MetaMode
- * assignment
- */
-
- ret =
- XNVCTRLSetAttributeAndGetStatus(dpy,
- screen,
- 0,
- NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
- display_devices);
-
- if (!ret) {
- printf("unable to assign the associated display devices to "
- "0x%08x.\n\n", display_devices);
- return 1;
- }
-
- printf("associated display devices 0x%08x.\n\n", display_devices);
-
-
- /*
- * next, we add a new MetaMode; a more sophisticated client
- * would actually select a modeline from
- * NV_CTRL_BINARY_DATA_MODELINES on each display device, but
- * for demonstration purposes, we assume that
- * "nvidia-auto-select" is a valid mode on each display
- * device.
- */
-
- pOut = NULL;
-
- ret = XNVCTRLStringOperation(dpy,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen,
- 0,
- NV_CTRL_STRING_OPERATION_ADD_METAMODE,
- "nvidia-auto-select, nvidia-auto-select",
- &pOut);
-
- if (!ret || !pOut) {
- printf("failed to add MetaMode; this may be because the MetaMode "
- "already exists for this X screen.\n\n");
- return 1;
- }
-
- /*
- * retrieve the id of the added MetaMode from the return
- * string; a more sophisticated client should do actual
- * parsing of the returned string, which is defined to be a
- * comma-separated list of "token=value" pairs as output.
- * Currently, the only output token is "id", which indicates
- * the id that was assigned to the MetaMode.
- */
-
- sscanf(pOut, "id=%d", &id);
-
- XFree(pOut);
-
-
- /*
- * we have added a new MetaMode for this X screen, and we know
- * its id. The last step is to use the XRandR extension to
- * switch to this mode; see the Xrandr(3) manpage for details.
- *
- * For demonstration purposes, just use the xrandr commandline
- * utility to switch to the mode with the refreshrate that
- * matches the id.
- */
-
- printf("The id of the new MetaMode is %d; use xrandr to "
- "switch to it.\n\n", id);
- }
/* Display all names each display device goes by
@@ -1382,9 +1229,6 @@ int main(int argc, char *argv[])
printf(" --print-used-modelines: print the modeline for each display "
"device for each MetaMode on the X screen.\n\n");
- printf(" --dynamic-twinview: demonstrates the process of "
- "dynamically transitioning into TwinView.\n\n");
-
printf(" --print-display-names: print all the names associated with "
"each display device on the server\n\n");
}
@@ -1511,25 +1355,6 @@ static char *remove_whitespace(char *str)
/*
- * count the number of bits set in the specified mask
- */
-
-static int count_bits(unsigned int mask)
-{
- int n = 0;
-
- while (mask) {
- n++;
- mask &= (mask - 1) ;
- }
-
- return n;
-
-} /* count_bits() */
-
-
-
-/*
* parse_mode_string() - extract the modeName and the display device
* mask for the per-display device MetaMode string in 'modeString'
*/
diff --git a/samples/nv-control-events.c b/samples/nv-control-events.c
index 1b34b44..b9711a0 100644
--- a/samples/nv-control-events.c
+++ b/samples/nv-control-events.c
@@ -606,13 +606,6 @@ static AttrEntry attr_table[] = {
MAKE_ENTRY(NV_CTRL_MAX_DISPLAYS),
MAKE_ENTRY(NV_CTRL_DYNAMIC_TWINVIEW),
MAKE_ENTRY(NV_CTRL_MULTIGPU_DISPLAY_OWNER),
- MAKE_ENTRY(NV_CTRL_GPU_SCALING),
- MAKE_ENTRY(NV_CTRL_FRONTEND_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_BACKEND_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_FLATPANEL_NATIVE_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_GPU_SCALING_ACTIVE),
- MAKE_ENTRY(NV_CTRL_DFP_SCALING_ACTIVE),
MAKE_ENTRY(NV_CTRL_FSAA_APPLICATION_ENHANCED),
MAKE_ENTRY(NV_CTRL_FRAMELOCK_SYNC_RATE_4),
MAKE_ENTRY(NV_CTRL_GVO_LOCK_OWNER),
@@ -731,5 +724,23 @@ static AttrEntry attr_table[] = {
MAKE_ENTRY(NV_CTRL_GVO_ANC_PARITY_COMPUTATION),
MAKE_ENTRY(NV_CTRL_3D_VISION_PRO_GLASSES_PAIR_EVENT),
MAKE_ENTRY(NV_CTRL_3D_VISION_PRO_GLASSES_UNPAIR_EVENT),
+ MAKE_ENTRY(NV_CTRL_GPU_PCIE_CURRENT_LINK_WIDTH),
+ MAKE_ENTRY(NV_CTRL_GPU_PCIE_CURRENT_LINK_SPEED),
+ MAKE_ENTRY(NV_CTRL_GVO_AUDIO_BLANKING),
+ MAKE_ENTRY(NV_CTRL_CURRENT_METAMODE_ID),
+ MAKE_ENTRY(NV_CTRL_DISPLAY_ENABLED),
+ MAKE_ENTRY(NV_CTRL_FRAMELOCK_INCOMING_HOUSE_SYNC_RATE),
+ MAKE_ENTRY(NV_CTRL_FXAA),
+ MAKE_ENTRY(NV_CTRL_DISPLAY_RANDR_OUTPUT_ID),
+ MAKE_ENTRY(NV_CTRL_FRAMELOCK_DISPLAY_CONFIG),
+ MAKE_ENTRY(NV_CTRL_TOTAL_DEDICATED_GPU_MEMORY),
+ MAKE_ENTRY(NV_CTRL_USED_DEDICATED_GPU_MEMORY),
+ MAKE_ENTRY(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_IMMEDIATE),
+ MAKE_ENTRY(NV_CTRL_GPU_DOUBLE_PRECISION_BOOST_REBOOT),
+ MAKE_ENTRY(NV_CTRL_DPY_HDMI_3D),
+ MAKE_ENTRY(NV_CTRL_BASE_MOSAIC),
+ MAKE_ENTRY(NV_CTRL_MULTIGPU_MASTER_POSSIBLE),
+ MAKE_ENTRY(NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE),
+ MAKE_ENTRY(NV_CTRL_XV_SYNC_TO_DISPLAY_ID),
{ -1, NULL, NULL }
};
diff --git a/samples/nv-control-info.c b/samples/nv-control-info.c
index 913c246..ae92d18 100644
--- a/samples/nv-control-info.c
+++ b/samples/nv-control-info.c
@@ -189,13 +189,6 @@ static AttrEntry attr_int_table[] = {
MAKE_ENTRY(NV_CTRL_MAX_DISPLAYS),
MAKE_ENTRY(NV_CTRL_DYNAMIC_TWINVIEW),
MAKE_ENTRY(NV_CTRL_MULTIGPU_DISPLAY_OWNER),
- MAKE_ENTRY(NV_CTRL_GPU_SCALING),
- MAKE_ENTRY(NV_CTRL_FRONTEND_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_BACKEND_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_FLATPANEL_NATIVE_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_FLATPANEL_BEST_FIT_RESOLUTION),
- MAKE_ENTRY(NV_CTRL_GPU_SCALING_ACTIVE),
- MAKE_ENTRY(NV_CTRL_DFP_SCALING_ACTIVE),
MAKE_ENTRY(NV_CTRL_FSAA_APPLICATION_ENHANCED),
MAKE_ENTRY(NV_CTRL_FRAMELOCK_SYNC_RATE_4),
MAKE_ENTRY(NV_CTRL_GVO_LOCK_OWNER),
diff --git a/samples/nv-control-targets.c b/samples/nv-control-targets.c
index 3d24fb4..9d3bc6a 100644
--- a/samples/nv-control-targets.c
+++ b/samples/nv-control-targets.c
@@ -41,44 +41,18 @@
-/*
- * display_device_name() - return the display device name corresponding
- * to the display device mask.
- */
-
-static char *display_device_name(int mask)
+static void print_display_device_target_indices(const int *pData)
{
- switch (mask) {
- case (1 << 0): return "CRT-0"; break;
- case (1 << 1): return "CRT-1"; break;
- case (1 << 2): return "CRT-2"; break;
- case (1 << 3): return "CRT-3"; break;
- case (1 << 4): return "CRT-4"; break;
- case (1 << 5): return "CRT-5"; break;
- case (1 << 6): return "CRT-6"; break;
- case (1 << 7): return "CRT-7"; break;
-
- case (1 << 8): return "TV-0"; break;
- case (1 << 9): return "TV-1"; break;
- case (1 << 10): return "TV-2"; break;
- case (1 << 11): return "TV-3"; break;
- case (1 << 12): return "TV-4"; break;
- case (1 << 13): return "TV-5"; break;
- case (1 << 14): return "TV-6"; break;
- case (1 << 15): return "TV-7"; break;
-
- case (1 << 16): return "DFP-0"; break;
- case (1 << 17): return "DFP-1"; break;
- case (1 << 18): return "DFP-2"; break;
- case (1 << 19): return "DFP-3"; break;
- case (1 << 20): return "DFP-4"; break;
- case (1 << 21): return "DFP-5"; break;
- case (1 << 22): return "DFP-6"; break;
- case (1 << 23): return "DFP-7"; break;
- default: return "Unknown";
- }
-} /* display_device_name() */
+ int i, first = 1;
+ for (i = 1; i <= pData[0]; i++) {
+ if (!first) {
+ printf(", ");
+ }
+ first = 0;
+ printf("DPY-%d", pData[i]);
+ }
+}
int main(int argc, char *argv[])
@@ -94,7 +68,6 @@ int main(int argc, char *argv[])
int num_coolers;
int num_thermal_sensors;
int gpu, screen;
- int display_devices, mask;
int *pData;
int len, j;
char *str;
@@ -156,6 +129,26 @@ int main(int argc, char *argv[])
printf(" number of X Screens: %d\n", num_screens);
+ /* Get the number of display devices in the system */
+
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ 0, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_DISPLAY_TARGETS,
+ (unsigned char **) &pData,
+ &len);
+ if (!ret) {
+ fprintf(stderr, "Failed to query number of display devices\n");
+ return 1;
+ }
+ printf(" number of display devices: %d (", pData[0]);
+ print_display_device_target_indices(pData);
+ printf(")\n");
+ XFree(pData);
+
+
/* Get the number of Frame Lock devices in the system */
ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK,
@@ -221,6 +214,8 @@ int main(int argc, char *argv[])
for (gpu = 0; gpu < num_gpus; gpu++) {
+ int *pDisplayData;
+
printf("\n\n");
printf("GPU %d information:\n", gpu);
@@ -256,35 +251,22 @@ int main(int argc, char *argv[])
/* Connected Display Devices on GPU */
- ret = XNVCTRLQueryTargetAttribute(dpy,
- NV_CTRL_TARGET_TYPE_GPU,
- gpu, // target_id
- 0, // display_mask
- NV_CTRL_CONNECTED_DISPLAYS,
- &display_devices);
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU,
+ (unsigned char **) &pDisplayData,
+ &len);
if (!ret) {
fprintf(stderr, "Failed to query connected displays\n");
return 1;
}
- printf(" Display Device Mask (Connected) : 0x%08x\n",
- display_devices);
-
-
- /* Enabled Display Devices on GPU */
-
- ret = XNVCTRLQueryTargetAttribute(dpy,
- NV_CTRL_TARGET_TYPE_GPU,
- gpu, // target_id
- 0, // display_mask
- NV_CTRL_ENABLED_DISPLAYS,
- &display_devices);
- if (!ret) {
- fprintf(stderr, "Failed to query enabled displays\n");
- return 1;
- }
- printf(" Display Device Mask (Enabled) : 0x%08x\n",
- display_devices);
-
+ printf(" Connected Display Devices : ");
+ print_display_device_target_indices(pDisplayData);
+ XFree(pDisplayData);
+ printf("\n");
/* X Screens driven by this GPU */
@@ -307,64 +289,47 @@ int main(int argc, char *argv[])
for (j = 1; j <= pData[0]; j++) {
screen = pData[j];
-
+
printf("\n");
printf(" X Screen %d information:\n", screen);
+ /* Assigned Display Devices on X Screen */
- /* Connected Display Devices on X Screen */
-
- ret = XNVCTRLQueryTargetAttribute(dpy,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen, // target_id
- 0, // display_mask
- NV_CTRL_CONNECTED_DISPLAYS,
- &display_devices);
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN,
+ (unsigned char **) &pDisplayData,
+ &len);
if (!ret) {
- fprintf(stderr, "Failed to query connected displays\n");
- XFree(pData);
+ fprintf(stderr, "Failed to query assigned displays\n");
return 1;
}
- printf(" Display Device Mask (Connected) : 0x%08x\n",
- display_devices);
-
+ printf(" Assigned Display Devices : ");
+ print_display_device_target_indices(pDisplayData);
+ XFree(pDisplayData);
+ printf("\n");
/* Enabled Display Devices on X Screen */
- ret = XNVCTRLQueryTargetAttribute(dpy,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen, // target_id
- 0, // display_mask
- NV_CTRL_ENABLED_DISPLAYS,
- &display_devices);
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN,
+ (unsigned char **) &pDisplayData,
+ &len);
if (!ret) {
- fprintf(stderr, "Failed to query enabled displays\n");
- XFree(pData);
+ fprintf(stderr, "Failed to query assigned displays\n");
return 1;
}
- printf(" Display Device Mask (Enabled) : 0x%08x\n",
- display_devices);
-
-
- /* List all display devices on this X Screen */
-
- for (mask = 1; mask < (1 << 24); mask <<= 1) {
- if (!(display_devices & mask)) {
- continue;
- }
-
- ret = XNVCTRLQueryTargetStringAttribute
- (dpy,
- NV_CTRL_TARGET_TYPE_X_SCREEN,
- screen, // target_id
- mask, // display_mask
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &str);
- printf(" Display Device (0x%08x) : %s - '%s'\n",
- mask,
- display_device_name(mask),
- str);
- }
+ printf(" Enabled Display Devices : ");
+ print_display_device_target_indices(pDisplayData);
+ XFree(pDisplayData);
+ printf("\n");
}
XFree(pData);
}
diff --git a/samples/nv-control-warpblend.h b/samples/nv-control-warpblend.h
index 36d36dc..4550e06 100644
--- a/samples/nv-control-warpblend.h
+++ b/samples/nv-control-warpblend.h
@@ -78,7 +78,7 @@
* XNVCTRLSetScanoutWarping
*
* xDpy: valid X display connection
- * screenId: X protocol screen number; typically 0 in "TwinView" or "Mosaic"
+ * screenId: X protocol screen number
* nvDpyId: NV-CONTROL display target index; can be enumerated with the
* NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN request.
* warpDatatype: NV_CTRL_WARP_DATA_TYPE_MESH_TRIANGLESTRIP_XYUVRQ or
@@ -107,7 +107,7 @@ XNVCTRLSetScanoutWarping(
* XNVCTRLSetScanout[Intensity/Offset]
*
* xDpy: valid X display connection
- * screenId: X protocol screen number; typically 0 in "TwinView" or "Mosaic"
+ * screenId: X protocol screen number
* nvDpyId: NV-CONTROL display target index; can be enumerated with the
* NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN request.
* pixmap: XID naming a valid Pixmap to be used as Intensity/Offset data.
diff --git a/samples/version.mk b/samples/version.mk
index 8a89afe..2abb57a 100644
--- a/samples/version.mk
+++ b/samples/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 325.15
+NVIDIA_VERSION = 331.13
diff --git a/src/XF86Config-parser/Flags.c b/src/XF86Config-parser/Flags.c
index 6eadae2..55720e0 100644
--- a/src/XF86Config-parser/Flags.c
+++ b/src/XF86Config-parser/Flags.c
@@ -59,6 +59,7 @@
#include "xf86tokens.h"
#include "Configint.h"
#include <math.h>
+#include "common-utils.h"
extern LexRec val;
@@ -504,3 +505,87 @@ xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs)
list = list->next;
}
}
+
+/*
+ * Determines if the Composite extension should be disabled or not.
+ *
+ * - If the extension can be enabled, this function returns NULL.
+ *
+ * - If the extension should be disabled, this function returns a
+ * string that lists the conflicting options that are enabled.
+ */
+
+const char *xconfigValidateComposite(XConfigPtr config,
+ GenerateOptions *gop,
+ int composite_specified,
+ int xinerama_enabled,
+ int depth,
+ int overlay_enabled,
+ int cioverlay_enabled,
+ int ubb_enabled,
+ int stereo_enabled)
+{
+ int i, n, disable_composite;
+ static char err_str[256];
+ int size = 256;
+ char *s;
+
+ const struct {
+ const char *name;
+ int value;
+
+ } composite_incompatible_options[] = {
+ { "Xinerama", xinerama_enabled },
+ { "Overlay", overlay_enabled },
+ { "CIOverlay", cioverlay_enabled },
+ { "UBB", ubb_enabled },
+ { "Stereo", stereo_enabled },
+ };
+
+ /*
+ * We need to be careful to only set the option value if the X
+ * server is going to recognize the Extension section and the
+ * composite option. We guess whether the server will recognize
+ * the option: if get_xserver_in_use() thinks the X server
+ * supports the "Composite" extension, or the current config
+ * already has an extension section, or the user specified the
+ * composite option.
+ */
+ if (!gop->supports_extension_section &&
+ !config->extensions &&
+ !composite_specified) {
+ /* Composite can't be set in X config, so bail */
+ return NULL;
+ }
+
+ disable_composite = FALSE;
+ s = err_str;
+ n = 0;
+ err_str[0] = '\0';
+
+ for (i = 0; i < ARRAY_LEN(composite_incompatible_options); i++) {
+ int value = composite_incompatible_options[i].value;
+ const char *name = composite_incompatible_options[i].name;
+ int wrote;
+
+ if (value) {
+ disable_composite = TRUE;
+ n++;
+
+ wrote = snprintf(s, size, "%s%s", (n > 1) ? " or " : "", name);
+ if (wrote <= 0) {
+ break;
+ }
+ size -= wrote;
+ s += wrote;
+ }
+ }
+
+ /* Special case checking for depth 8 */
+
+ if (depth <= 8) {
+ snprintf(s, size, "%sdepth=8", (n > 1) ? " or " : "");
+ }
+
+ return disable_composite ? err_str : NULL;
+}
diff --git a/src/XF86Config-parser/xf86Parser.h b/src/XF86Config-parser/xf86Parser.h
index 09fccad..1135ffd 100644
--- a/src/XF86Config-parser/xf86Parser.h
+++ b/src/XF86Config-parser/xf86Parser.h
@@ -762,6 +762,15 @@ void xconfigGenerateLoadDefaultOptions(GenerateOptions *gop);
void xconfigGetXServerInUse(GenerateOptions *gop);
+const char *xconfigValidateComposite(XConfigPtr config,
+ GenerateOptions *gop,
+ int composite_enabled,
+ int xinerama_enabled,
+ int depth,
+ int overlay_enabled,
+ int cioverlay_enabled,
+ int ubb_enabled,
+ int stereo);
/*
* check (and update, if necessary) the inputs in the specified layout
diff --git a/src/app-profiles.c b/src/app-profiles.c
index b6f98cc..a56bcbc 100644
--- a/src/app-profiles.c
+++ b/src/app-profiles.c
@@ -866,10 +866,19 @@ static int file_in_search_path(AppProfileConfig *config, const char *filename)
return FALSE;
}
+// Print an error message and optionally capture the error string for later use
+// Note: this assumes fmt is a string literal!
+#define LOG_ERROR(error_str, fmt, ...) do { \
+ if (error_str) { \
+ nv_append_sprintf(error_str, fmt "\n", __VA_ARGS__); \
+ } \
+ nv_error_msg(fmt, __VA_ARGS__); \
+} while (0)
+
/*
* Creates parent directories as needed, similarly to "mkdir -p"
*/
-static int nv_mkdirp(const char *dirname)
+static int nv_mkdirp(const char *dirname, char **error_str)
{
int ret = 0;
char *parent_name;
@@ -881,8 +890,10 @@ static int nv_mkdirp(const char *dirname)
parent_name = nvstrndup(dirname, next - dirname);
ret = mkdir(parent_name, 0777);
if ((ret < 0) && (errno != EEXIST)) {
- nv_error_msg("Could not create parent directory \"%s\" for full path \"%s\" (%s)",
- parent_name, dirname, strerror(errno));
+ LOG_ERROR(error_str,
+ "Could not create parent directory \"%s\" "
+ "for full path \"%s\" (%s)",
+ parent_name, dirname, strerror(errno));
free(parent_name);
return ret;
}
@@ -893,15 +904,15 @@ static int nv_mkdirp(const char *dirname)
ret = mkdir(dirname, 0777);
if (ret < 0) {
if (errno != EEXIST) {
- nv_error_msg("Could not create directory \"%s\" (%s)",
- dirname, strerror(errno));
+ LOG_ERROR(error_str, "Could not create directory \"%s\" (%s)",
+ dirname, strerror(errno));
} else {
ret = stat(dirname, &stat_buf);
if (ret == 0) {
if (!S_ISDIR(stat_buf.st_mode)) {
- nv_error_msg("Could not create directory \"%s\" (file "
- "exists, but not as a directory)",
- dirname);
+ LOG_ERROR(error_str, "Could not create directory \"%s\" "
+ "(file exists, but not as a directory)",
+ dirname);
ret = -1;
}
}
@@ -941,16 +952,17 @@ char *nv_app_profile_config_get_backup_filename(AppProfileConfig *config, const
}
static int app_profile_config_backup_file(AppProfileConfig *config,
- const char *filename)
+ const char *filename,
+ char **error_str)
{
int ret;
char *backup_name = nv_app_profile_config_get_backup_filename(config, filename);
char *backup_dirname = nv_dirname(backup_name);
- ret = nv_mkdirp(backup_dirname);
+ ret = nv_mkdirp(backup_dirname, error_str);
if (ret < 0) {
- nv_error_msg("Could not create backup directory \"%s\" (%s)",
- backup_name, strerror(errno));
+ LOG_ERROR(error_str, "Could not create backup directory \"%s\" (%s)",
+ backup_name, strerror(errno));
goto done;
}
@@ -960,8 +972,8 @@ static int app_profile_config_backup_file(AppProfileConfig *config,
// Clear the error; the file does not exist
ret = 0;
} else {
- nv_error_msg("Could not rename file \"%s\" to \"%s\" for backup (%s)",
- filename, backup_name, strerror(errno));
+ LOG_ERROR(error_str, "Could not rename file \"%s\" to \"%s\" for backup (%s)",
+ filename, backup_name, strerror(errno));
}
}
@@ -973,10 +985,12 @@ done:
return ret;
}
+
static int app_profile_config_save_updates_to_file(AppProfileConfig *config,
const char *filename,
const char *update_text,
- int backup)
+ int backup,
+ char **error_str)
{
int file_is_new = FALSE;
struct stat stat_buf;
@@ -987,7 +1001,8 @@ static int app_profile_config_save_updates_to_file(AppProfileConfig *config,
ret = stat(filename, &stat_buf);
if ((ret < 0) && (errno != ENOENT)) {
- nv_error_msg("Could not stat file \"%s\" (%s)", filename, strerror(errno));
+ LOG_ERROR(error_str, "Could not stat file \"%s\" (%s)",
+ filename, strerror(errno));
goto done;
} else if ((ret < 0) && (errno == ENOENT)) {
file_is_new = TRUE;
@@ -998,11 +1013,12 @@ static int app_profile_config_save_updates_to_file(AppProfileConfig *config,
// This file is in a directory in the search path
ret = stat(dirname, &stat_buf);
if ((ret < 0) && (errno != ENOENT)) {
- nv_error_msg("Could not stat file \"%s\" (%s)", dirname, strerror(errno));
+ LOG_ERROR(error_str, "Could not stat file \"%s\" (%s)",
+ dirname, strerror(errno));
goto done;
} else if ((ret < 0) && errno == ENOENT) {
// Attempt to create the directory in the search path
- ret = nv_mkdirp(dirname);
+ ret = nv_mkdirp(dirname, error_str);
if (ret < 0) {
goto done;
}
@@ -1010,24 +1026,27 @@ static int app_profile_config_save_updates_to_file(AppProfileConfig *config,
// If the search path entry is currently a regular file,
// unlink it and create a directory instead
if (backup) {
- ret = app_profile_config_backup_file(config, dirname);
+ ret = app_profile_config_backup_file(config, dirname,
+ error_str);
if (ret < 0) {
goto done;
}
}
ret = unlink(dirname);
if (ret < 0) {
- nv_error_msg("Could not remove the file \"%s\" (%s)", dirname, strerror(errno));
+ LOG_ERROR(error_str,
+ "Could not remove the file \"%s\" (%s)",
+ dirname, strerror(errno));
goto done;
}
- ret = nv_mkdirp(dirname);
+ ret = nv_mkdirp(dirname, error_str);
if (ret < 0) {
goto done;
}
}
} else {
// Attempt to create parent directories for this file
- ret = nv_mkdirp(dirname);
+ ret = nv_mkdirp(dirname, error_str);
if (ret < 0) {
goto done;
}
@@ -1037,18 +1056,23 @@ static int app_profile_config_save_updates_to_file(AppProfileConfig *config,
// but that seems a little dangerous. Instead, complain and bail out
// here.
ret = -1;
- nv_error_msg("Refusing to write to file \"%s\" since it is not a regular file", filename);
+ LOG_ERROR(error_str,
+ "Refusing to write to file \"%s\" "
+ "since it is not a regular file", filename);
+ goto done;
}
if (!file_is_new && backup) {
- ret = app_profile_config_backup_file(config, filename);
+ ret = app_profile_config_backup_file(config, filename,
+ error_str);
if (ret < 0) {
goto done;
}
}
ret = open_and_stat(filename, "w", &fp, &stat_buf);
if (ret < 0) {
- nv_error_msg("Could not write to the file \"%s\" (%s)", filename, strerror(errno));
+ LOG_ERROR(error_str, "Could not write to the file \"%s\" (%s)",
+ filename, strerror(errno));
goto done;
}
nv_info_msg("", "Writing to configuration file \"%s\"\n", filename);
@@ -1060,24 +1084,44 @@ done:
return ret;
}
-int nv_app_profile_config_save_updates(AppProfileConfig *config, json_t *updates, int backup)
+int nv_app_profile_config_save_updates(AppProfileConfig *config,
+ json_t *updates,
+ int backup,
+ char **error_str)
{
json_t *update;
const char *filename;
const char *update_text;
size_t i, size;
int ret = 0;
+ int all_ret = 0;
+
+ if (error_str) {
+ *error_str = NULL;
+ }
- for (i = 0, size = json_array_size(updates); (ret == 0) && (i < size); i++) {
+ for (i = 0, size = json_array_size(updates); i < size; i++) {
update = json_array_get(updates, i);
filename = json_string_value(json_object_get(update, "filename"));
update_text = json_string_value(json_object_get(update, "text"));
- ret = app_profile_config_save_updates_to_file(config, filename, update_text, backup);
+ ret = app_profile_config_save_updates_to_file(config,
+ filename,
+ update_text,
+ backup,
+ error_str);
+ if (ret < 0) {
+ all_ret = -1;
+ }
}
- assert(ret <= 0);
+ assert(all_ret <= 0);
- return ret;
+ // This asserts an error string is set iff we are returning an error
+ assert(!error_str ||
+ (!(*error_str) && (all_ret == 0)) ||
+ ((*error_str) && (all_ret < 0)));
+
+ return all_ret;
}
AppProfileConfig *nv_app_profile_config_dup(AppProfileConfig *config)
diff --git a/src/app-profiles.h b/src/app-profiles.h
index fa74e58..6aa9de3 100644
--- a/src/app-profiles.h
+++ b/src/app-profiles.h
@@ -122,8 +122,12 @@ typedef struct AppProfileConfigRec {
* backup indicates whether this should also make backups of the original files
* before saving.
* Returns 0 if successful, or a negative integer if an error was encountered.
+ * If error_str is non-NULL, *error_str is set to NULL on success, or a
+ * dynamically-allocated string if an error occurred.
*/
-int nv_app_profile_config_save_updates(AppProfileConfig *config, json_t *updates, int backup);
+int nv_app_profile_config_save_updates(AppProfileConfig *config,
+ json_t *updates, int backup,
+ char **error_str);
/*
* Load an application profile configuration from disk, using a list of files specified by search_path.
diff --git a/src/command-line.c b/src/command-line.c
index 5638965..d884617 100644
--- a/src/command-line.c
+++ b/src/command-line.c
@@ -49,6 +49,7 @@ int __verbosity = VERBOSITY_DEFAULT;
int __terse = NV_FALSE;
int __display_device_string = NV_FALSE;
int __verbosity_level_changed = NV_FALSE;
+int __list_targets = NV_FALSE;
/*
* print_version() - print version information
@@ -101,31 +102,45 @@ static void print_attribute_help(char *attr)
if (show_desc) {
nv_msg(NULL, "Attribute '%s':", entry->name);
- if (entry->flags & NV_PARSER_TYPE_FRAMELOCK)
+ if (entry->flags & NV_PARSER_TYPE_FRAMELOCK) {
nv_msg(NULL, " - Is Frame Lock attribute.");
- if (entry->flags & NV_PARSER_TYPE_NO_CONFIG_WRITE)
+ }
+ if (entry->flags & NV_PARSER_TYPE_NO_CONFIG_WRITE) {
nv_msg(NULL, " - Attribute is not written to the rc file.");
- if (entry->flags & NV_PARSER_TYPE_GUI_ATTRIBUTE)
+ }
+ if (entry->flags & NV_PARSER_TYPE_GUI_ATTRIBUTE) {
nv_msg(NULL, " - Is GUI attribute.");
- if (entry->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE)
+ }
+ if (entry->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
nv_msg(NULL, " - Attribute value is packed integer.");
- if (entry->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY)
+ }
+ if (entry->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY) {
nv_msg(NULL, " - Attribute value is a display mask.");
- if (entry->flags & NV_PARSER_TYPE_NO_QUERY_ALL)
+ }
+ if (entry->flags & NV_PARSER_TYPE_NO_QUERY_ALL) {
nv_msg(NULL, " - Attribute not queried in 'query all'.");
- if (entry->flags & NV_PARSER_TYPE_NO_ZERO_VALUE)
+ }
+ if (entry->flags & NV_PARSER_TYPE_NO_ZERO_VALUE) {
nv_msg(NULL, " - Attribute cannot be zero.");
- if (entry->flags & NV_PARSER_TYPE_100Hz)
+ }
+ if (entry->flags & NV_PARSER_TYPE_100Hz) {
nv_msg(NULL, " - Attribute value is in units of Centihertz (1/100Hz).");
- if (entry->flags & NV_PARSER_TYPE_1000Hz)
+ }
+ if (entry->flags & NV_PARSER_TYPE_1000Hz) {
nv_msg(NULL, " - Attribute value is in units of Milihertz (1/1000 Hz).");
- if (entry->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE)
+ }
+ if (entry->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
nv_msg(NULL, " - Attribute value is string.");
- if (entry->flags & NV_PARSER_TYPE_SDI)
+ }
+ if (entry->flags & NV_PARSER_TYPE_SDI) {
nv_msg(NULL, " - Is SDI attribute.");
- if (entry->flags & NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY)
+ }
+ if (entry->flags & NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY) {
nv_msg(NULL, " - Attribute value is switch display.");
-
+ }
+ if (entry->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID) {
+ nv_msg(NULL, " - Attribute value is a display id.");
+ }
nv_msg(TAB, "%s", entry->desc);
nv_msg(NULL, "");
} else {
@@ -253,6 +268,7 @@ Options *parse_command_line(int argc, char *argv[], char *dpy,
case 't': __terse = NV_TRUE; break;
case 'd': __display_device_string = NV_TRUE; break;
case 'e': print_attribute_help(strval); exit(0); break;
+ case 'L': __list_targets = NV_TRUE; break;
default:
nv_error_msg("Invalid commandline, please run `%s --help` "
"for usage information.\n", argv[0]);
diff --git a/src/common-utils/common-utils.c b/src/common-utils/common-utils.c
index b2958a7..9bd349e 100644
--- a/src/common-utils/common-utils.c
+++ b/src/common-utils/common-utils.c
@@ -235,6 +235,28 @@ char *nvasprintf(const char *fmt, ...)
} /* nvasprintf() */
+/*
+ * nv_append_sprintf() - similar to glib's g_string_append_printf(), except
+ * instead of operating on a GString it operates on a (char **). Appends a
+ * formatted string to the end of the dynamically-allocated string pointed to by
+ * *buf (or the empty string if *buf is NULL), potentially reallocating the
+ * string in the process. This function only returns on succcess.
+ */
+void nv_append_sprintf(char **buf, const char *fmt, ...)
+{
+ char *prefix, *suffix;
+
+ prefix = *buf;
+ NV_VSNPRINTF(suffix, fmt);
+
+ if (!prefix) {
+ *buf = suffix;
+ } else {
+ *buf = nvstrcat(prefix, suffix, NULL);
+ free(prefix);
+ free(suffix);
+ }
+}
/*
@@ -413,7 +435,7 @@ TextRows *nv_format_text_rows(const char *prefix,
}
}
- /* look for any newline inbetween a and b, and move b to it */
+ /* look for any newline between a and b, and move b to it */
for (c = a; c < b; c++) if (*c == '\n') { b = c; break; }
diff --git a/src/common-utils/common-utils.h b/src/common-utils/common-utils.h
index 92c57dd..3bc934f 100644
--- a/src/common-utils/common-utils.h
+++ b/src/common-utils/common-utils.h
@@ -72,6 +72,7 @@ char *nvstrtolower(char *s);
char *nvstrtoupper(char *s);
char *nvstrchrnul(char *s, int c);
char *nvasprintf(const char *fmt, ...) NV_ATTRIBUTE_PRINTF(1, 2);
+void nv_append_sprintf(char **buf, const char *fmt, ...) NV_ATTRIBUTE_PRINTF(2, 3);
void nvfree(void *s);
char *tilde_expansion(const char *str);
@@ -184,4 +185,20 @@ static NV_INLINE uint64_t nv_encode_version(unsigned int major,
#define NV_VERSION4(major, minor, micro, nano) \
nv_encode_version(major, minor, micro, nano)
+/*
+ * Helper enum that can be used for boolean values that might or might not be
+ * set. Care should be taken to avoid simple boolean testing, as a value of
+ * NV_OPTIONAL_BOOL_DEFAULT would evaluate as true.
+ *
+ * The user is responsible for unconditionally initializing the default value of
+ * any such booleans to NV_OPTIONAL_BOOL_DEFAULT, before any code path that
+ * might optionally set their values is executed.
+ */
+
+typedef enum {
+ NV_OPTIONAL_BOOL_DEFAULT = -1,
+ NV_OPTIONAL_BOOL_FALSE = FALSE,
+ NV_OPTIONAL_BOOL_TRUE = TRUE
+} NVOptionalBool;
+
#endif /* __COMMON_UTILS_H__ */
diff --git a/src/common-utils/gen-manpage-opts-helper.c b/src/common-utils/gen-manpage-opts-helper.c
index d2abb1c..532015d 100644
--- a/src/common-utils/gen-manpage-opts-helper.c
+++ b/src/common-utils/gen-manpage-opts-helper.c
@@ -89,7 +89,7 @@ static void print_option(const NVGetoptOption *o)
* '^' : toggles bold on and off
* '-' : is backslashified: "\-"
*
- * Whitespace is omited when italics or bold is on
+ * Whitespace is omitted when italics or bold is on
*/
italics = 0;
diff --git a/src/common-utils/nvgetopt.h b/src/common-utils/nvgetopt.h
index 5847546..fc735ee 100644
--- a/src/common-utils/nvgetopt.h
+++ b/src/common-utils/nvgetopt.h
@@ -34,8 +34,8 @@
/*
* indicates that the option is a boolean value; the presence of the
- * option will be interpretted as a TRUE value; if the option is
- * prepended with '--no-', the option will be interpretted as a FALSE
+ * option will be interpreted as a TRUE value; if the option is
+ * prepended with '--no-', the option will be interpreted as a FALSE
* value. On success, nvgetopt will return the parsed boolean value
* through 'boolval'.
*/
diff --git a/src/config-file.c b/src/config-file.c
index bb0b691..9478467 100644
--- a/src/config-file.c
+++ b/src/config-file.c
@@ -217,14 +217,14 @@ int nv_read_config_file(const char *file, const char *display_name,
int nv_write_config_file(const char *filename, CtrlHandles *h,
ParsedAttribute *p, ConfigProperties *conf)
{
- int screen, ret, entry, bit, val, display, randr_gamma_available;
+ int screen, ret, entry, val, display, randr_gamma_available;
FILE *stream;
time_t now;
ReturnStatus status;
+ NVCTRLAttributePermissionsRec perms;
NVCTRLAttributeValidValuesRec valid;
- uint32 mask;
CtrlHandleTarget *t;
- char *tmp_d_str, *prefix, scratch[4];
+ char *prefix, scratch[4];
const char *tmp;
char *locale = "C";
@@ -337,59 +337,43 @@ int nv_write_config_file(const char *filename, CtrlHandles *h,
get_color_value(a->attr, c, b, g));
continue;
}
-
- for (bit = 0; bit < 24; bit++) {
-
- mask = 1 << bit;
-
- /*
- * if this bit is not present in the screen's enabled
- * display device mask (and the X screen has enabled
- * display devices), skip to the next bit
- */
-
- if (((t->d & mask) == 0x0) && (t->d)) continue;
- status = NvCtrlGetValidDisplayAttributeValues
- (t->h, mask, a->attr, &valid);
+ /* Ignore display attributes, they are written later on */
- if (status != NvCtrlSuccess) goto exit_bit_loop;
-
- if ((valid.permissions & ATTRIBUTE_TYPE_WRITE) == 0x0)
- goto exit_bit_loop;
-
- status = NvCtrlGetDisplayAttribute(t->h, mask, a->attr, &val);
-
- if (status != NvCtrlSuccess) goto exit_bit_loop;
-
- if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
+ ret = nv_get_attribute_perms(h, a->attr, a->flags, &perms);
+ if (!ret || (perms.permissions & ATTRIBUTE_TYPE_DISPLAY)) {
+ continue;
+ }
- tmp_d_str =
- display_device_mask_to_display_device_name(mask);
+ /* Only write attributes that can be written */
- fprintf(stream, "%s%c%s[%s]=%d\n", prefix,
- DISPLAY_NAME_SEPARATOR, a->name, tmp_d_str, val);
-
- free(tmp_d_str);
-
- continue;
-
- } else {
+ status = NvCtrlGetValidAttributeValues(t->h, a->attr, &valid);
+ if (status != NvCtrlSuccess ||
+ !(valid.permissions & ATTRIBUTE_TYPE_WRITE) ||
+ (valid.permissions & ATTRIBUTE_TYPE_DISPLAY)) {;
+ continue;
+ }
- fprintf(stream, "%s%c%s=%d\n", prefix,
- DISPLAY_NAME_SEPARATOR, a->name, val);
+ status = NvCtrlGetAttribute(t->h, a->attr, &val);
+ if (status != NvCtrlSuccess) {
+ continue;
+ }
- /* fall through to exit_bit_loop */
+ if (a->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID) {
+ const char *name =
+ nv_get_display_target_config_name(h, val);
+ if (name) {
+ fprintf(stream, "%s%c%s=%s\n", prefix,
+ DISPLAY_NAME_SEPARATOR, a->name, name);
}
-
- exit_bit_loop:
+ continue;
+ }
+
+ fprintf(stream, "%s%c%s=%d\n", prefix,
+ DISPLAY_NAME_SEPARATOR, a->name, val);
- bit = 25; /* XXX force us out of the display device loop */
-
- } /* bit */
-
} /* entry */
-
+
} /* screen */
/*
@@ -447,7 +431,28 @@ int nv_write_config_file(const char *filename, CtrlHandles *h,
fprintf(stream, "%s%c%s=%f\n",
prefix, DISPLAY_NAME_SEPARATOR, a->name,
get_color_value(a->attr, c, b, g));
- }
+ continue;
+ }
+
+ /* Make sure this is a display attribute */
+
+ ret = nv_get_attribute_perms(h, a->attr, a->flags, &perms);
+ if (!ret || !(perms.permissions & ATTRIBUTE_TYPE_DISPLAY)) {
+ continue;
+ }
+
+ status = NvCtrlGetValidAttributeValues(t->h, a->attr, &valid);
+ if (status != NvCtrlSuccess ||
+ !(valid.permissions & ATTRIBUTE_TYPE_WRITE) ||
+ !(valid.permissions & ATTRIBUTE_TYPE_DISPLAY)) {
+ continue;
+ }
+
+ status = NvCtrlGetAttribute(t->h, a->attr, &val);
+ if (status == NvCtrlSuccess) {
+ fprintf(stream, "%s%c%s=%d\n", prefix,
+ DISPLAY_NAME_SEPARATOR, a->name, val);
+ }
}
free(prefix);
@@ -499,22 +504,16 @@ int nv_write_config_file(const char *filename, CtrlHandles *h,
}
}
- if (p->display_device_mask) {
-
- tmp_d_str = display_device_mask_to_display_device_name
- (p->display_device_mask);
-
- fprintf(stream, "%s%s%c%s[%s]=%d\n", p->display, target_str,
- DISPLAY_NAME_SEPARATOR, tmp, tmp_d_str, p->val.i);
-
- free(tmp_d_str);
-
+ if (p->flags & NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE) {
+ fprintf(stream, "%s%s%c%s[0x%08x]=%d\n", p->display, target_str,
+ DISPLAY_NAME_SEPARATOR, tmp, p->display_device_mask,
+ p->val.i);
} else {
-
fprintf(stream, "%s%s%c%s=%d\n", p->display, target_str,
DISPLAY_NAME_SEPARATOR, tmp, p->val.i);
}
+
p = p->next;
}
diff --git a/src/gtk+-2.x/ctkappprofile.c b/src/gtk+-2.x/ctkappprofile.c
index 65e84d9..939634b 100644
--- a/src/gtk+-2.x/ctkappprofile.c
+++ b/src/gtk+-2.x/ctkappprofile.c
@@ -3583,13 +3583,15 @@ static void save_app_profile_changes_dialog_save_changes(GtkWidget *widget, gpoi
GtkWidget *error_dialog;
SaveAppProfileChangesDialog *dialog = (SaveAppProfileChangesDialog *)user_data;
CtkAppProfile *ctk_app_profile = CTK_APP_PROFILE(dialog->parent);
+ char *write_errors = NULL;
static const char config_files_changed_string[] =
"nvidia-settings has detected that configuration files have changed "
"since the configuration was last loaded. Saving the configuration "
"may cause these changes to be permanently lost. Continue anyway?\n";
- static const char write_errors_occurred_string[] =
- "nvidia-settings encountered errors when writing to the configuration. "
- "Some changes may not have been saved. Reload the configuration anyway?\n";
+ static const char write_errors_occurred_prefix[] =
+ "nvidia-settings encountered errors when writing to the configuration:\n";
+ static const char write_errors_occurred_suffix[] =
+ "\nSome changes may not have been saved. Reload the configuration anyway?\n";
// First check for possible conflicts
if (nv_app_profile_config_check_backing_files(ctk_app_profile->cur_config)) {
@@ -3608,14 +3610,23 @@ static void save_app_profile_changes_dialog_save_changes(GtkWidget *widget, gpoi
do_backup = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dialog->backup_check_button));
if (do_save) {
- ret = nv_app_profile_config_save_updates(ctk_app_profile->cur_config, dialog->updates,
- do_backup);
+ ret = nv_app_profile_config_save_updates(ctk_app_profile->cur_config,
+ dialog->updates,
+ do_backup, &write_errors);
if (ret < 0) {
- error_dialog = gtk_message_dialog_new(GTK_WINDOW(dialog->top_window),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_YES_NO,
- "%s", write_errors_occurred_string);
+ if (!write_errors) {
+ write_errors = strdup("Unknown error.");
+ }
+ error_dialog =
+ gtk_message_dialog_new(GTK_WINDOW(dialog->top_window),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_YES_NO,
+ "%s%s%s",
+ write_errors_occurred_prefix,
+ write_errors,
+ write_errors_occurred_suffix);
result = gtk_dialog_run(GTK_DIALOG(error_dialog));
if (result != GTK_RESPONSE_YES) {
do_reload = FALSE;
@@ -3623,6 +3634,8 @@ static void save_app_profile_changes_dialog_save_changes(GtkWidget *widget, gpoi
gtk_widget_destroy(error_dialog);
}
+ free(write_errors);
+
if (do_reload) {
app_profile_reload(CTK_APP_PROFILE(dialog->parent));
}
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.c b/src/gtk+-2.x/ctkdisplayconfig-utils.c
index 050dc03..d3a7107 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.c
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.c
@@ -1976,12 +1976,39 @@ gchar *screen_get_metamode_str(nvScreenPtr screen, int metamode_idx,
}
}
+ if (!metamode_str) {
+ metamode_str = strdup("NULL");
+ }
+
return metamode_str;
} /* screen_get_metamode_str() */
+/** cleanup_metamode() ***********************************************
+ *
+ * Frees any internal memory used by the metamode.
+ *
+ **/
+
+void cleanup_metamode(nvMetaModePtr metamode)
+{
+ if (metamode->cpl_str) {
+ free(metamode->cpl_str);
+ metamode->cpl_str = NULL;
+ }
+
+ if (metamode->x_str) {
+ XFree(metamode->x_str);
+ metamode->x_str = NULL;
+ }
+
+ metamode->x_str_entry = NULL;
+}
+
+
+
/** screen_remove_metamodes() ****************************************
*
* Removes all metamodes currently referenced by this screen, also
@@ -2006,7 +2033,7 @@ static void screen_remove_metamodes(nvScreenPtr screen)
while (screen->metamodes) {
metamode = screen->metamodes;
screen->metamodes = metamode->next;
- free(metamode->string);
+ cleanup_metamode(metamode);
free(metamode);
}
screen->num_metamodes = 0;
@@ -2070,7 +2097,6 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str,
char *mode_str_itr;
const char *tokens_end;
const char *metamode_modes;
- char *metamode_copy = NULL;
nvMetaModePtr metamode = NULL;
int mode_count = 0;
@@ -2105,82 +2131,82 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str,
}
}
- /* Process each mode in the metamode string */
- metamode_copy = strdup(metamode_modes);
- if (!metamode_copy) goto fail;
+ metamode_modes = parse_skip_whitespace(metamode_modes);
- for (mode_str_itr = mode_strtok(metamode_copy);
- mode_str_itr;
- mode_str_itr = mode_strtok(NULL)) {
+ if (strcmp(metamode_modes, "NULL")) {
+ /* Process each mode in the metamode string */
+ char *metamode_copy = strdup(metamode_modes);
+ if (!metamode_copy) goto fail;
- nvModePtr mode;
- nvDisplayPtr display;
- unsigned int display_id;
- const char *orig_mode_str = parse_skip_whitespace(mode_str_itr);
- const char *mode_str;
+ for (mode_str_itr = mode_strtok(metamode_copy);
+ mode_str_itr;
+ mode_str_itr = mode_strtok(NULL)) {
- /* Parse the display device (NV-CONTROL target) id from the name */
- mode_str = parse_read_display_id(mode_str_itr, &display_id);
- if (!mode_str) {
- nv_warning_msg("Failed to read a display device name on screen %d "
- "while parsing metamode:\n\n'%s'",
- screen->scrnum,
+ nvModePtr mode;
+ nvDisplayPtr display;
+ unsigned int display_id;
+ const char *orig_mode_str = parse_skip_whitespace(mode_str_itr);
+ const char *mode_str;
- orig_mode_str);
- continue;
- }
-
- /* Match device id to an existing display */
- display = layout_get_display(screen->layout, display_id);
- if (!display) {
- nv_warning_msg("Failed to find display device %d on screen %d "
- "while parsing metamode:\n\n'%s'",
- display_id,
- screen->scrnum,
+ /* Parse the display device (NV-CONTROL target) id from the name */
+ mode_str = parse_read_display_id(mode_str_itr, &display_id);
+ if (!mode_str) {
+ nv_warning_msg("Failed to read a display device name on screen "
+ "%d while parsing metamode:\n\n'%s'",
+ screen->scrnum, orig_mode_str);
+ continue;
+ }
- orig_mode_str);
- continue;
- }
+ /* Match device id to an existing display */
+ display = layout_get_display(screen->layout, display_id);
+ if (!display) {
+ nv_warning_msg("Failed to find display device %d on screen %d "
+ "while parsing metamode:\n\n'%s'",
+ display_id,
+ screen->scrnum,
+ orig_mode_str);
+ continue;
+ }
- /* Parse the mode */
- mode = mode_parse(display, mode_str);
- if (!mode) {
- nv_warning_msg("Failed to parse mode '%s'\non screen %d\n"
- "from metamode:\n\n'%s'",
- mode_str,
- screen->scrnum,
- orig_mode_str);
- continue;
- }
+ /* Parse the mode */
+ mode = mode_parse(display, mode_str);
+ if (!mode) {
+ nv_warning_msg("Failed to parse mode '%s'\non screen %d\n"
+ "from metamode:\n\n'%s'",
+ mode_str,
+ screen->scrnum,
+ orig_mode_str);
+ continue;
+ }
- /* Make the mode part of the metamode */
- mode->metamode = metamode;
+ /* Make the mode part of the metamode */
+ mode->metamode = metamode;
- /* On older X driver NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN
- * attribute is Not Available so we are unable to link displays to
- * the screen implicitly.
- * To avoid display->cur_mode = NULL link displays explicitly.
- */
- screen_link_display(screen, display);
- /* Make sure each display has the right number of (NULL) modes */
- screen_check_metamodes(screen);
+ /* On older X driver NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN
+ * attribute is Not Available so we are unable to link displays to
+ * the screen implicitly.
+ * To avoid display->cur_mode = NULL link displays explicitly.
+ */
+ screen_link_display(screen, display);
+ /* Make sure each display has the right number of (NULL) modes */
+ screen_check_metamodes(screen);
- /* Add the mode at the end of the display's mode list */
- xconfigAddListItem((GenericListPtr *)(&display->modes),
- (GenericListPtr)mode);
- display->num_modes++;
- mode_count++;
- }
+ /* Add the mode at the end of the display's mode list */
+ xconfigAddListItem((GenericListPtr *)(&display->modes),
+ (GenericListPtr)mode);
+ display->num_modes++;
+ mode_count++;
+ }
- free(metamode_copy);
- metamode_copy = NULL;
+ free(metamode_copy);
- /* Make sure something was added */
- if (mode_count == 0) {
- nv_warning_msg("Failed to find any display on screen %d\n"
- "while parsing metamode:\n\n'%s'",
- screen->scrnum, metamode_str);
- goto fail;
+ /* Make sure something was added */
+ if (mode_count == 0) {
+ nv_warning_msg("Failed to find any display on screen %d\n"
+ "while parsing metamode:\n\n'%s'",
+ screen->scrnum, metamode_str);
+ goto fail;
+ }
}
/* Add the metamode to the end of the screen's metamode list */
@@ -2195,9 +2221,6 @@ static Bool screen_add_metamode(nvScreenPtr screen, const char *metamode_str,
if (metamode) {
free(metamode);
}
- if (metamode_copy) {
- free(metamode_copy);
- }
return FALSE;
@@ -3197,7 +3220,7 @@ static Bool layout_add_gpu_from_server(nvLayoutPtr layout, unsigned int gpu_id,
gpu->uuid = NULL;
}
- get_bus_id_str(gpu->handle, &(gpu->pci_bus_id));
+ gpu->pci_bus_id = get_bus_id_str(gpu->handle);
ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_WIDTH,
(int *)&(gpu->max_width));
@@ -3507,13 +3530,6 @@ static Bool layout_add_screen_from_server(nvLayoutPtr layout,
if (ret == NvCtrlSuccess) {
screen->stereo_supported = TRUE;
screen->stereo = val;
-
- /* XXX For now, if stereo is off, don't show configuration options
- * until we work out interactions with composite.
- */
- if (val == NV_CTRL_STEREO_OFF) {
- screen->stereo_supported = FALSE;
- }
} else {
screen->stereo_supported = FALSE;
}
@@ -3526,17 +3542,20 @@ static Bool layout_add_screen_from_server(nvLayoutPtr layout,
screen->overlay = NV_CTRL_OVERLAY_OFF;
}
- /* See if the screen supports dynamic twinview */
- ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW, &val);
- if (ret != NvCtrlSuccess) {
- *err_str = g_strdup_printf("Failed to query Dynamic TwinView for "
- "screen %d.",
- screen_id);
- nv_warning_msg("%s", *err_str);
- goto fail;
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_HWOVERLAY, &val);
+ if (ret == NvCtrlSuccess) {
+ screen->hw_overlay = val;
+ } else {
+ screen->hw_overlay = NV_CTRL_HWOVERLAY_FALSE;
}
- screen->dynamic_twinview = !!val;
+ /* Query the current UBB state */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_UBB, &val);
+ if (ret == NvCtrlSuccess) {
+ screen->ubb = val;
+ } else {
+ screen->ubb = NV_CTRL_UBB_OFF;
+ }
/* See if the screen is set to not scanout */
ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_NO_SCANOUT, &val);
@@ -3557,18 +3576,6 @@ static Bool layout_add_screen_from_server(nvLayoutPtr layout,
screen->no_scanout = (val == NV_CTRL_NO_SCANOUT_ENABLED);
- /* XXX Currently there is no support for screens that are scanning
- * out but have TwinView disabled.
- */
- if (!screen->dynamic_twinview && !screen->no_scanout) {
- *err_str = g_strdup_printf("nvidia-settings currently does not "
- "support scanout screens (%d) that have "
- "dynamic twinview disabled.",
- screen_id);
- nv_warning_msg("%s", *err_str);
- goto fail;
- }
-
/* Link screen to the GPUs driving it */
if (!link_screen_to_gpus(layout, screen)) {
*err_str = g_strdup_printf("Failed to find GPU that drives screen %d.",
diff --git a/src/gtk+-2.x/ctkdisplayconfig-utils.h b/src/gtk+-2.x/ctkdisplayconfig-utils.h
index e903377..0e74a62 100644
--- a/src/gtk+-2.x/ctkdisplayconfig-utils.h
+++ b/src/gtk+-2.x/ctkdisplayconfig-utils.h
@@ -87,6 +87,8 @@ Bool display_set_modes_rotation(nvDisplayPtr display, Rotation rotation);
/* Metamode functions */
+void cleanup_metamode(nvMetaModePtr metamode);
+
/* Screen functions */
diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c
index 8cb0638..ee2e25e 100644
--- a/src/gtk+-2.x/ctkdisplayconfig.c
+++ b/src/gtk+-2.x/ctkdisplayconfig.c
@@ -2171,7 +2171,11 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
{
GtkTextIter i;
GtkTextBuffer *b;
+ nvGpuPtr gpu = NULL;
+ if (ctk_object->layout) {
+ gpu = ctk_object->layout->gpus;
+ }
b = gtk_text_buffer_new(table);
@@ -2196,6 +2200,26 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
"be moved by holding CONTROL-Click and dragging.");
ctk_help_heading(b, &i, "Layout Hidden Label");
ctk_help_para(b, &i, "%s", __layout_hidden_label_help);
+
+ if (gpu) {
+ switch (gpu->mosaic_type) {
+ case MOSAIC_TYPE_SLI_MOSAIC:
+ ctk_help_heading(b, &i, "Enable SLI Mosaic");
+ ctk_help_para(b, &i, "%s", __layout_sli_mosaic_button_help);
+ break;
+ case MOSAIC_TYPE_BASE_MOSAIC:
+ ctk_help_heading(b, &i, "Enable Base Mosaic");
+ ctk_help_para(b, &i, "%s", __layout_base_mosaic_full_button_help);
+ break;
+ case MOSAIC_TYPE_BASE_MOSAIC_LIMITED:
+ ctk_help_heading(b, &i, "Enable Base Mosaic (Surround)");
+ ctk_help_para(b, &i, "%s", __layout_base_mosaic_surround_button_help);
+ break;
+ default:
+ break;
+ }
+ }
+
ctk_help_heading(b, &i, "Enable Xinerama");
ctk_help_para(b, &i, "%s This setting is only available when multiple "
"X screens are present.", __layout_xinerama_button_help);
@@ -2207,6 +2231,13 @@ GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
ctk_help_para(b, &i, "The following options are available when a display "
"device is selected in the Selection drop-down to configure "
"the settings for that display device.");
+ ctk_help_heading(b, &i, "Configuration");
+ ctk_help_para(b, &i, "%s \"Disabled\" disables the selected display "
+ "device. \"X screen <number>\" associates the selected "
+ "display device with the specified X Screen. \"New X screen "
+ "(requires X restart)\" creates a new X Screen and "
+ "associates the selected display device with it.",
+ __dpy_configuration_mnu_help);
ctk_help_heading(b, &i, "Resolution");
ctk_help_para(b, &i, "%s", __dpy_resolution_mnu_help);
ctk_help_heading(b, &i, "Refresh");
@@ -7064,11 +7095,11 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
modified_current_metamode = FALSE;
} else {
nv_info_msg(TAB, "Modifying current MetaMode to: %s...",
- metamode->string);
+ metamode->cpl_str);
ret = NvCtrlSetStringAttribute(screen->handle,
NV_CTRL_STRING_CURRENT_METAMODE,
- metamode->string,
+ metamode->cpl_str,
NULL);
if (ret == NvCtrlSuccess) {
metamode->id = old_rate;
@@ -7080,7 +7111,8 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
nv_warning_msg("Failed to set MetaMode (%d) '%s' "
"(Mode: %dx%d, id: %d) on X screen %d!",
- screen->cur_metamode_idx+1, metamode->string, new_width,
+ screen->cur_metamode_idx+1, metamode->cpl_str,
+ new_width,
new_height, new_rate,
NvCtrlGetTargetId(screen->handle));
@@ -7088,7 +7120,8 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
msg = g_strdup_printf("Failed to set MetaMode (%d) '%s' "
"(Mode %dx%d, id: %d) on X screen %d\n\n"
"Would you like to remove this MetaMode?",
- screen->cur_metamode_idx+1, metamode->string,
+ screen->cur_metamode_idx+1,
+ metamode->cpl_str,
new_width, new_height, new_rate,
NvCtrlGetTargetId(screen->handle));
dlg = gtk_message_dialog_new
@@ -7100,7 +7133,8 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
} else {
msg = g_strdup_printf("Failed to set MetaMode (%d) '%s' "
"(Mode %dx%d, id: %d) on X screen %d.",
- screen->cur_metamode_idx+1, metamode->string,
+ screen->cur_metamode_idx+1,
+ metamode->cpl_str,
new_width, new_height, new_rate,
NvCtrlGetTargetId(screen->handle));
dlg = gtk_message_dialog_new
@@ -7206,18 +7240,18 @@ static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
-/** find_metamode_string_by_id() *************************************
+/** link_metamode_string_by_id() *************************************
*
* Looks in the list of strings (metamode_strs) for a metamode with
- * the given id (defined by string 'id_str') and returns the pointer
- * to it, or NULL if not found.
+ * the given id (defined by string 'id_str'). If found, sets the metamode
+ * id and x_id appropriately.
*
**/
-static char *find_metamode_string_by_id(char *metamode_strs, int match_id,
- int *match_idx)
+static void link_metamode_string_by_id(char *metamode_strs, int match_id,
+ nvMetaModePtr metamode)
{
- int idx = 0;
+ int x_idx = 0;
char *m;
for (m = metamode_strs; m && strlen(m); m += strlen(m) +1) {
@@ -7225,16 +7259,14 @@ static char *find_metamode_string_by_id(char *metamode_strs, int match_id,
if (str) {
int id = atoi(str+3);
if (id && (id == match_id)) {
- if (match_idx) {
- *match_idx = idx;
- }
- return m;
+ metamode->id = id;
+ metamode->x_idx = x_idx;
+ metamode->x_str_entry = m;
+ return;
}
}
- idx++;
+ x_idx++;
}
-
- return NULL;
}
@@ -7253,13 +7285,13 @@ static Bool add_cpl_metamode_to_X(nvScreenPtr screen, nvMetaModePtr metamode,
ret = NvCtrlStringOperation(screen->handle, 0,
NV_CTRL_STRING_OPERATION_ADD_METAMODE,
- metamode->string, &tokens);
+ metamode->cpl_str, &tokens);
/* Grab the metamode ID from the returned tokens */
if ((ret != NvCtrlSuccess) || !tokens) {
nv_error_msg("Failed to add MetaMode '%s' to X for "
"screen %d",
- metamode->string, screen->scrnum);
+ metamode->cpl_str, screen->scrnum);
return FALSE;
}
@@ -7272,7 +7304,7 @@ static Bool add_cpl_metamode_to_X(nvScreenPtr screen, nvMetaModePtr metamode,
nv_info_msg(TAB, "Added MetaMode (# %d, ID: %d) > [%s]",
metamode_idx,
metamode->id,
- metamode->string);
+ metamode->cpl_str);
return TRUE;
}
@@ -7296,31 +7328,17 @@ static void stub_metamode_str(char *str)
}
-
-/** preprocess_metamodes() *******************************************
- *
- * Does preprocess work to the metamode strings:
- *
- * - Generates the metamode strings for the screen's metamodes
- * that will be used for creating the metamode list on the X
- * Server.
- *
- * - Stubs out each string in the metamode_strs list that should
- * not be deleted (it has a matching metamode in "screen".)
+/** setup_metamodes_for_apply() **************************************
*
- * - Adds new metamodes to the X server screen that are specified
- * in "screen" but not found in metamode_strs.
+ * Prepares the list of CPL metamodes to be applied to the X server.
*
**/
-static void preprocess_metamodes(nvScreenPtr screen, char *metamode_strs,
- char *cur_metamode_str,
- int num_metamodes_in_X,
- int cur_metamode_idx)
+static void setup_metamodes_for_apply(nvScreenPtr screen,
+ char *metamode_strs)
{
nvMetaModePtr metamode;
ReturnStatus ret;
- char *str;
char *tmp;
int metamode_idx;
@@ -7329,95 +7347,210 @@ static void preprocess_metamodes(nvScreenPtr screen, char *metamode_strs,
metamode;
metamode = metamode->next, metamode_idx++) {
- /* Generate the metamode's string */
- free(metamode->string);
metamode->id = -1;
metamode->x_idx = -1;
- metamode->string = screen_get_metamode_str(screen, metamode_idx, 1);
- if (!metamode->string) continue;
- /* See if the metamode already exists and if so, get its ID */
+ /* Get metamode string from CPL */
+ metamode->cpl_str = screen_get_metamode_str(screen, metamode_idx, 1);
+ if (!metamode->cpl_str) {
+ continue;
+ }
+
+ /* Parse CPL string into X metamode string */
ret = NvCtrlStringOperation(screen->handle, 0,
NV_CTRL_STRING_OPERATION_PARSE_METAMODE,
- metamode->string, &str);
- if (ret != NvCtrlSuccess) {
- /* XXX Something's wrong with the metamode, ignore it for now. */
+ metamode->cpl_str, &metamode->x_str);
+ if ((ret != NvCtrlSuccess) ||
+ !metamode->x_str) {
continue;
}
- /* XXX Later, we'll ask X to parse this metamode on updates
- * and already have an ID so we'll know already which metamodes
- * need to be deleted/added/moved.
- */
-
- tmp = strstr(str, "id=");
+ /* Identify metamode id and position in X */
+ tmp = strstr(metamode->x_str, "id=");
if (tmp) {
int id = atoi(tmp+3);
- tmp = find_metamode_string_by_id(metamode_strs, id,
- &(metamode->x_idx));
- if (tmp) {
- metamode->id = id;
+ link_metamode_string_by_id(metamode_strs, id, metamode);
+ }
+ }
+}
- /* We matched a CPL metamode with an X metamode, so stub the
- * metamode from the X list so we don't delete it later.
- */
- stub_metamode_str(tmp);
- /*
- nv_info_msg(TAB, "%3d - Matched MetaMode (ID:%3d, X idx:%3d) > [%s]",
- metamode_idx,
- metamode->id,
- metamode->x_idx,
- metamode->string);
- */
- /* Process the next metamode */
+/** cleanup_metamodes_for_apply() ************************************
+ *
+ * Releases memory used for applying metamodes to X.
+ *
+ **/
+
+static void cleanup_metamodes_for_apply(nvScreenPtr screen)
+{
+ nvMetaModePtr metamode;
+
+ for (metamode = screen->metamodes;
+ metamode;
+ metamode = metamode->next) {
+
+ cleanup_metamode(metamode);
+ }
+}
+
+
+
+/** remove_duplicate_cpl_metamodes() *********************************
+ *
+ * Removes duplicate metamodes in the CPL
+ *
+ **/
+
+static void remove_duplicate_cpl_metamodes(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ nvMetaModePtr m1;
+ nvMetaModePtr m2;
+ int m1_idx;
+ int m1_old_idx;
+ int m2_idx;
+
+ m1 = screen->metamodes;
+ m1_idx = 0;
+ m1_old_idx = 0;
+ while (m1) {
+ Bool found = FALSE;
+
+ if (!m1->x_str) {
+ m1 = m1->next;
+ m1_idx++;
+ m1_old_idx++;
+ continue;
+ }
+
+ for (m2 = screen->metamodes, m2_idx = 0;
+ m2 != m1;
+ m2 = m2->next, m2_idx++) {
+
+ if (!m2->x_str) {
+ continue;
+ }
+
+ if (strcmp(m1->x_str, m2->x_str)) {
continue;
}
+
+ /* m1 and m2 are the same, delete m1 (since it comes after) */
+ if (m1 == screen->cur_metamode) {
+ ctk_display_layout_set_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, m2_idx);
+ }
+
+ m1 = m1->next;
+
+ ctk_display_layout_delete_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, m1_idx, FALSE);
+
+ nv_info_msg(TAB, "Removed MetaMode %d on Screen %d (is "
+ "duplicate of MetaMode %d)\n", m1_old_idx+1,
+ screen->scrnum,
+ m2_idx+1);
+
+ found = TRUE;
+ break;
}
- /* If the CPL metamode did not match any of the metamodes in X, we
- * should add it. Note, however, that since we have not yet gone
- * through the whole list of CPL MetaModes (the currently active
- * MetaMode in X may match a CPL MetaMode we have not yet encountered),
- * we don't yet know if the current metamode should be modified via
- * NV_CTRL_STRING_CURRENT_METAMODE, or added then swapped to, so ignore
- * it for now and handle it once we've gone through all the CPL
- * MetaModes.
+ if (!found) {
+ m1 = m1->next;
+ m1_idx++;
+ }
+ m1_old_idx++;
+ }
+}
+
+
+
+/** preprocess_metamodes() *******************************************
+ *
+ * Does preprocess work to the metamode strings:
+ *
+ * - Generates the metamode strings for the screen's metamodes
+ * that will be used for creating the metamode list on the X
+ * Server.
+ *
+ * - Stubs out each string in the metamode_strs list that should
+ * not be deleted (it has a matching metamode in "screen".)
+ *
+ * - Adds new metamodes to the X server screen that are specified
+ * in "screen" but not found in metamode_strs.
+ *
+ **/
+
+static void preprocess_metamodes(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen,
+ char *x_metamode_strs,
+ char *cur_x_metamode_str,
+ int num_x_metamodes,
+ int cur_x_metamode_idx)
+{
+ nvMetaModePtr metamode;
+ Bool cur_x_metamode_matched = FALSE;
+
+
+ /* Generate metamode strings and match CPL metamodes to X */
+ setup_metamodes_for_apply(screen, x_metamode_strs);
+
+ /* Remove duplicate metamodes in CPL based on parsed string */
+ remove_duplicate_cpl_metamodes(ctk_object, screen);
+
+ /* Add metamodes from the CPL that aren't in X */
+ for (metamode = screen->metamodes;
+ metamode;
+ metamode = metamode->next) {
+
+ /* CPL metamode was found in X, stub out the string entry in the X
+ * metamodes list so we don't delete it later.
+ */
+ if (metamode->x_str_entry) {
+ stub_metamode_str(metamode->x_str_entry);
+ /* Track if the current X metamode matched a CPL metamode */
+ if (metamode->x_str_entry == cur_x_metamode_str) {
+ cur_x_metamode_matched = TRUE;
+ }
+ continue;
+ }
+
+ /* CPL metamode was not found in X, so we should add it. */
+
+ /* Don't add the current metamode (yet). If the current X metamode
+ * string does not get stubbed out (i.e. it does not match to another
+ * CPL metamode), then it can be modify via
+ * NV_CTRL_STRING_CURRENT_METAMODE instead of adding a new metamode,
+ * switching to it and deleting the old one.
*/
if (metamode == screen->cur_metamode) {
continue;
}
- /* The metamode was not found, so add it to the X screen's list */
- if (add_cpl_metamode_to_X(screen, metamode, num_metamodes_in_X)) {
- num_metamodes_in_X++;
+ if (add_cpl_metamode_to_X(screen, metamode, num_x_metamodes)) {
+ num_x_metamodes++;
}
}
- /* If the currently selected MetaMode in the CPL did not match any metamode
- * in X, and the current active MetaMode (in X) was linked to another CPL
- * MetaMode, then we will need to add the CPL's current MetaMode so we can
- * switch to it later.
- *
- * Note: if a mode was matched above, then the current metamode pointer
- * should now point to a stubbed out entry, and this is what we check for
- * here.
+ /* If the currently selected CPL metamode did not match any X metamode, and
+ * the current active X metamode matched to another CPL metamode, then the
+ * currently selected CPL metamode will need to be added and switched to.
*/
- if ((screen->cur_metamode->id < 0)) {
- const char *ctmp = parse_skip_whitespace(cur_metamode_str);
-
- if (!*ctmp) {
+ if (screen->cur_metamode->id < 0) {
+ if (cur_x_metamode_matched) {
if (add_cpl_metamode_to_X(screen, screen->cur_metamode,
- num_metamodes_in_X)) {
- num_metamodes_in_X++;
+ num_x_metamodes)) {
+ num_x_metamodes++;
}
} else {
/* Current metamode will be overridden, so stub it here so that it
* does not get deleted later.
*/
- stub_metamode_str(cur_metamode_str);
- screen->cur_metamode->x_idx = cur_metamode_idx;
+ stub_metamode_str(cur_x_metamode_str);
+ screen->cur_metamode->x_idx = cur_x_metamode_idx;
}
}
@@ -7439,15 +7572,15 @@ static Bool screen_move_metamode(nvScreenPtr screen, nvMetaModePtr metamode,
int len;
ReturnStatus ret;
- if (!metamode->string) {
+ if (!metamode->cpl_str) {
goto fail;
}
/* Append the index we want */
- len = 24 + strlen(metamode->string);
+ len = 24 + strlen(metamode->cpl_str);
update_str = malloc(len);
snprintf(update_str, len, "index=%d :: %s", metamode_idx,
- metamode->string);
+ metamode->cpl_str);
ret = NvCtrlSetStringAttribute(screen->handle,
NV_CTRL_STRING_MOVE_METAMODE,
@@ -7460,7 +7593,7 @@ static Bool screen_move_metamode(nvScreenPtr screen, nvMetaModePtr metamode,
metamode->id,
metamode->x_idx,
metamode_idx,
- metamode->string);
+ metamode->cpl_str);
/* We moved the metamode to position metamode_idx, so bump the
* index of all metamodes from the new position to the old one.
@@ -7490,11 +7623,12 @@ static Bool screen_move_metamode(nvScreenPtr screen, nvMetaModePtr metamode,
metamode->id,
metamode->x_idx,
metamode_idx,
- metamode->string ? metamode->string : "NULL");
+ metamode->cpl_str ? metamode->cpl_str : "NULL");
return FALSE;
}
+
/** order_metamodes() ************************************************
*
* Makes sure the metamodes are ordered properly by moving each
@@ -7580,7 +7714,9 @@ static void postprocess_metamodes(nvScreenPtr screen, char *metamode_strs)
/* Reorder the list of metamodes */
order_metamodes(screen);
-} /* postprocess_metamodes() */
+ /* Cleanup */
+ cleanup_metamodes_for_apply(screen);
+}
@@ -7696,7 +7832,7 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object,
/* Add new metamodes and relate MetaModes from CPL to X */
- preprocess_metamodes(screen, metamode_strs, cur_metamode_ptr,
+ preprocess_metamodes(ctk_object, screen, metamode_strs, cur_metamode_ptr,
num_metamodes_in_X,
cur_metamode_idx);
@@ -7731,7 +7867,7 @@ static int update_screen_metamodes(CtkDisplayConfig *ctk_object,
screen->cur_metamode->edim.width,
screen->cur_metamode->edim.height);
- nv_info_msg(TAB, "Using > %s", screen->cur_metamode->string);
+ nv_info_msg(TAB, "Using > %s", screen->cur_metamode->cpl_str);
clear_apply = 1;
}
@@ -7830,6 +7966,8 @@ static void apply_clicked(GtkWidget *widget, gpointer user_data)
/* re-register to receive events */
register_layout_events(ctk_object);
+ update_gui(ctk_object);
+
} /* apply_clicked() */
@@ -8610,21 +8748,42 @@ static int generateXConfig(CtkDisplayConfig *ctk_object, XConfigPtr *pConfig)
goto fail;
}
- if (go.supports_extension_section && layout->xinerama_enabled) {
+ /* Check if composite should be disabled */
+ {
+ const char *composite_disabled_str = NULL;
+ nvScreenPtr screen;
- if (!config->extensions) {
- config->extensions = calloc(1, sizeof(XConfigExtensionsRec));
+ /* See if any X screens have overlay, cioverlay, ubb or stereo enabled,
+ * or depth 8.
+ */
+ for (screen = layout->screens; screen; screen = screen->next_in_layout) {
+
+ composite_disabled_str =
+ xconfigValidateComposite(config,
+ &go,
+ 1, // composite_specified
+ layout->xinerama_enabled,
+ screen->depth,
+ screen->overlay && screen->hw_overlay,
+ screen->overlay && !screen->hw_overlay,
+ screen->ubb,
+ screen->stereo
+ );
+ if (composite_disabled_str) {
+ break;
+ }
}
- /* remove any existing composite extension option and then add the option*/
- xconfigRemoveNamedOption(&(config->extensions->options), "Composite",
- NULL);
- xconfigAddNewOption(&config->extensions->options, "Composite", "Disable");
-
+ if (composite_disabled_str) {
+ if (!config->extensions) {
+ config->extensions = nvalloc(sizeof(XConfigExtensionsRec));
+ }
+ xconfigRemoveNamedOption(&(config->extensions->options), "Composite",
+ NULL);
+ xconfigAddNewOption(&config->extensions->options, "Composite", "Disable");
+ }
}
-
-
*pConfig = config;
return XCONFIG_GEN_OK;
diff --git a/src/gtk+-2.x/ctkdisplaydevice.c b/src/gtk+-2.x/ctkdisplaydevice.c
index f979e6d..e8900ae 100644
--- a/src/gtk+-2.x/ctkdisplaydevice.c
+++ b/src/gtk+-2.x/ctkdisplaydevice.c
@@ -58,7 +58,6 @@ static gboolean update_tv_encoder_info(InfoEntry *entry);
static gboolean update_chip_info(InfoEntry *entry);
static gboolean update_signal_info(InfoEntry *entry);
static gboolean update_link_info(InfoEntry *entry);
-static gboolean update_native_resolution(InfoEntry *entry);
static gboolean update_refresh_rate(InfoEntry *entry);
static gboolean register_link_events(InfoEntry *entry);
@@ -95,11 +94,6 @@ static const char *__info_signal_help =
"Report whether the flat panel is driven by an LVDS, TMDS, or DisplayPort "
"signal.";
-static const char * __native_res_help =
-"The Native Resolution is the width and height in pixels that the display "
-"device uses to display the image. All other resolutions must be scaled "
-"to this resolution by the GPU and/or the device's built-in scaler.";
-
static const char * __refresh_rate_help =
"The refresh rate displays the rate at which the screen is currently "
"refreshing the image.";
@@ -144,13 +138,6 @@ static InfoEntryData __info_entry_data[] = {
unregister_link_events,
},
{
- "Native Resolution",
- &__native_res_help,
- update_native_resolution,
- NULL,
- NULL,
- },
- {
"Refresh Rate",
&__refresh_rate_help,
update_refresh_rate,
@@ -695,28 +682,6 @@ static gboolean update_link_info(InfoEntry *entry)
-static gboolean update_native_resolution(InfoEntry *entry)
-{
- CtkDisplayDevice *ctk_object = entry->ctk_object;
- ReturnStatus ret;
- gint val;
- char *str;
-
- ret = NvCtrlGetAttribute(ctk_object->handle,
- NV_CTRL_FLATPANEL_NATIVE_RESOLUTION, &val);
- if (ret != NvCtrlSuccess) {
- return FALSE;
- }
-
- str = g_strdup_printf("%dx%d", (val >> 16), (val & 0xFFFF));
- gtk_label_set_text(GTK_LABEL(entry->txt), str);
- g_free(str);
-
- return TRUE;
-}
-
-
-
static gboolean update_refresh_rate(InfoEntry *entry)
{
CtkDisplayDevice *ctk_object = entry->ctk_object;
diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c
index d426a5b..8cdc438 100644
--- a/src/gtk+-2.x/ctkdisplaylayout.c
+++ b/src/gtk+-2.x/ctkdisplaylayout.c
@@ -61,61 +61,82 @@
#define NUM_COLORS_PER_PALETTE 4 /* Number of colors in a device's palette */
#define NUM_COLORS ((NUM_COLOR_PALETTES) * (NUM_COLORS_PER_PALETTE))
-#if MAX_DEVICES != 8
+#define COLOR_PALETTE_STEP_VALUE 0x181818
+
+#if MAX_DEVICES != 64
#warning "Each GPU needs a color palette!"
#endif
/* Each device will need a unique color palette */
-char *__palettes_color_names[NUM_COLORS] = {
-
- /* Blue */
- "#D9DBF4", /* View - Has modeline set */
- "#C9CBE4", /* Panning - Has modeline set */
- "#BABCD5", /* View - Off/Disabled */
- "#A3A5BE", /* Panning - OFf/Disabled */
-
- /* Orange */
- "#FFDB94",
- "#E8C47D",
- "#C9A55E",
- "#A6823B",
-
- /* Purple */
- "#E2D4F0",
- "#CFC1DD",
- "#B7A9C5",
- "#9D8FAB",
-
- /* Beige */
- "#EAF1C9",
- "#CBD2AA",
- "#ADB48C",
- "#838A62",
-
- /* Green */
- "#96E562",
- "#70BF3C",
- "#5BAA27",
- "#3C8B08",
-
- /* Pink */
- "#FFD6E9",
- "#E1B8CB",
- "#C79EB1",
- "#A87F92",
-
- /* Yellow */
- "#EEEE7E",
- "#E0E070",
- "#D5D565",
- "#C4C454",
-
- /* Teal */
- "#C9EAF1",
- "#A2C3CA",
- "#8DAEB5",
- "#76979E"
- };
+int __palettes_color_names[NUM_COLORS] = {
+ 0xD9DBF4, /* Blue */
+ 0xFFDB94, /* Orange */
+ 0xE2D4F0, /* Purple */
+ 0xEAF1C9, /* Beige */
+ 0x96E562, /* Green */
+ 0xFFD6E9, /* Pink */
+ 0xEEEE7E, /* Yellow */
+ 0xC9EAF1, /* Teal */
+
+ 0xB9F282,
+ 0xB298FE,
+ 0x84FAE3,
+ 0xE1928D,
+ 0xFF8FE6,
+ 0xB2F9BF,
+ 0xA2E0FC,
+ 0xFEBBAF,
+
+ 0xF5B2FA,
+ 0xA2B4F7,
+ 0x96FA94,
+ 0xE0F7A8,
+ 0xFFFE9E,
+ 0xF096BA,
+ 0xB0FFE9,
+ 0xFD8B9E,
+ 0xB996DA,
+ 0x83F3B0,
+ 0xFFAF8C,
+ 0xE086FE,
+ 0xC4E1CB,
+ 0xCDA3F7,
+ 0xF1CEBE,
+ 0xC0CFFF,
+
+ 0x8A8AFA,
+ 0xE8D399,
+ 0xE381B6,
+ 0xABB7A3,
+ 0xDFE4E0,
+ 0xA6FCD2,
+ 0xFD85CC,
+ 0x98E387,
+ 0xF1E8AF,
+ 0x82C2FF,
+ 0xCCF599,
+ 0xAA83F9,
+ 0xD3FCC4,
+ 0xFCB4CE,
+ 0x8FECF8,
+ 0xA8F4A5,
+ 0xB0F1FF,
+ 0x91A5FA,
+ 0xB3C6EF,
+ 0xE1B6EC,
+ 0xD3C1FB,
+ 0xDEE4BD,
+ 0xD9F982,
+ 0xFEE5C4,
+ 0xEAB6B9,
+ 0xB6E5E7,
+ 0x81DCF2,
+ 0x81F08F,
+ 0xDCAACC,
+ 0xCCF0D7,
+ 0xF49FD4,
+ 0xC0B7C2
+};
@@ -2570,7 +2591,7 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle,
CtkDisplayLayout *ctk_object;
GtkWidget *tmp;
PangoFontDescription *font_description;
- int i;
+ int i, j;
/* Make sure we have a handle */
@@ -2619,9 +2640,24 @@ GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle,
/* Parse the device color palettes */
ctk_object->color_palettes = calloc(NUM_COLORS, sizeof(GdkColor));
- for (i = 0; i < NUM_COLORS; i++) {
- gdk_color_parse(__palettes_color_names[i],
- &(ctk_object->color_palettes[i]));
+ for (i = 0; i < NUM_COLOR_PALETTES; i++) {
+ for (j = 0; j < NUM_COLORS_PER_PALETTE; j++) {
+
+ int color = __palettes_color_names[i] -
+ (j * COLOR_PALETTE_STEP_VALUE);
+ int index = i * NUM_COLORS_PER_PALETTE + j;
+
+ /*
+ * Convert the reference 24 bit 0xRRGGBB hex value to the GdkColor
+ * struct that uses 16 bit ints for each color value. We also need
+ * to shift the color values to the most significant end of these
+ * fields.
+ */
+
+ ctk_object->color_palettes[index].red = (color & 0xff0000) >> 8;
+ ctk_object->color_palettes[index].green = (color & 0xff00);
+ ctk_object->color_palettes[index].blue = (color & 0xff) << 8;
+ }
}
@@ -3426,6 +3462,7 @@ void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object,
screen->cur_metamode_idx = screen->num_metamodes -1;
}
+ cleanup_metamode(metamode);
free(metamode);
diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h
index a5c7c74..34a7b44 100644
--- a/src/gtk+-2.x/ctkdisplaylayout.h
+++ b/src/gtk+-2.x/ctkdisplaylayout.h
@@ -54,7 +54,7 @@ G_BEGIN_DECLS
/* Maximums */
-#define MAX_DEVICES 8 /* Max number of GPUs */
+#define MAX_DEVICES 64 /* Max number of GPUs */
/* XF86VIDMODE */
@@ -271,7 +271,10 @@ typedef struct nvMetaModeRec {
// Used for applying and generating metamodes (effective dimensions)
GdkRectangle edim; /* Bounding box of all non-NULL modes */
- char *string; /* Temp string used for modifying the metamode list */
+ /* Used to apply the metamode to the running X server */
+ char *cpl_str; /* metamode string from CPL */
+ char *x_str; /* parsed CPL string from X */
+ char *x_str_entry; /* Points to string in metamode strings buffer */
} nvMetaMode, *nvMetaModePtr;
@@ -311,6 +314,8 @@ typedef struct nvScreenRec {
int depth; /* Depth of the screen */
int stereo; /* Stereo mode enabled on this screen */
int overlay; /* Overlay enabled on this screen */
+ int hw_overlay;
+ int ubb;
nvDisplayPtr displays; /* List of displays using this screen */
int num_displays; /* # of displays using this screen */
@@ -331,7 +336,6 @@ typedef struct nvScreenRec {
Bool sli;
char *sli_mode;
char *multigpu_mode;
- Bool dynamic_twinview; /* This screen supports dynamic twinview */
Bool no_scanout; /* This screen has no display devices */
Bool stereo_supported; /* Can stereo be configured on this screen */
diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c
index 72fb330..a8497dc 100644
--- a/src/gtk+-2.x/ctkevent.c
+++ b/src/gtk+-2.x/ctkevent.c
@@ -218,7 +218,6 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
MAKE_SIGNAL(NV_CTRL_MAX_SCREEN_WIDTH);
MAKE_SIGNAL(NV_CTRL_MAX_SCREEN_HEIGHT);
MAKE_SIGNAL(NV_CTRL_MAX_DISPLAYS);
- MAKE_SIGNAL(NV_CTRL_DYNAMIC_TWINVIEW);
MAKE_SIGNAL(NV_CTRL_MULTIGPU_DISPLAY_OWNER);
MAKE_SIGNAL(NV_CTRL_GPU_SCALING);
MAKE_SIGNAL(NV_CTRL_GPU_SCALING_DEFAULT_TARGET);
@@ -329,6 +328,9 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
MAKE_SIGNAL(NV_CTRL_BASE_MOSAIC);
MAKE_SIGNAL(NV_CTRL_MULTIGPU_MASTER_POSSIBLE);
MAKE_SIGNAL(NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE);
+ MAKE_SIGNAL(NV_CTRL_XV_SYNC_TO_DISPLAY_ID);
+ MAKE_SIGNAL(NV_CTRL_BACKLIGHT_BRIGHTNESS);
+ MAKE_SIGNAL(NV_CTRL_THERMAL_COOLER_SPEED);
#undef MAKE_SIGNAL
/*
@@ -338,7 +340,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
* knows about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_THERMAL_COOLER_SPEED
#warning "There are attributes that do not emit signals!"
#endif
@@ -390,6 +392,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_NAME_TARGET_INDEX);
MAKE_STRING_SIGNAL(NV_CTRL_STRING_DISPLAY_NAME_RANDR);
MAKE_STRING_SIGNAL(NV_CTRL_STRING_GPU_UUID);
+ MAKE_STRING_SIGNAL(NV_CTRL_STRING_GPU_UTILIZATION);
MAKE_STRING_SIGNAL(NV_CTRL_STRING_MULTIGPU_MODE);
#undef MAKE_STRING_SIGNAL
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index 5454646..fe43a31 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -20,7 +20,9 @@
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixdata.h>
-#include <NvCtrlAttributes.h>
+#include "NvCtrlAttributes.h"
+#include "NVCtrlLib.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -73,6 +75,19 @@ enum
};
/*
+ * These signals get hooked up (to the display_state_received() function)
+ * for all frame lock display devices that are included in the list. When the
+ * entry is removed, these signals also get removed.
+ */
+
+const char *__DisplaySignals[] =
+ {
+ CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE),
+ CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE_3),
+ CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_DISPLAY_CONFIG),
+ };
+
+/*
* These signals get hooked up (to the gpu_state_received() function)
* for all frame lock devices that are included in the list. When the
* frame lock device entry is removed, these signals also get removed for
@@ -81,13 +96,8 @@ enum
const char *__GPUSignals[] =
{
- CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_MASTER),
- CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_SLAVES),
CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_SYNC),
CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_TEST_SIGNAL),
- CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE),
- CTK_EVENT_NAME(NV_CTRL_REFRESH_RATE_3),
- CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_SLAVEABLE)
};
/*
@@ -102,7 +112,7 @@ const char *__FrameLockSignals[] =
CTK_EVENT_NAME(NV_CTRL_USE_HOUSE_SYNC),
CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_SYNC_INTERVAL),
CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_POLARITY),
- CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_VIDEO_MODE)
+ CTK_EVENT_NAME(NV_CTRL_FRAMELOCK_VIDEO_MODE),
};
typedef struct _nvListTreeRec nvListTreeRec, *nvListTreePtr;
@@ -161,8 +171,11 @@ struct _nvListTreeRec {
struct _nvDisplayDataRec {
-
- gpointer handle; /* NV-CONTROL GPU Target */
+
+ gpointer handle; /* NV-CONTROL Display Target */
+
+ gboolean serverable;
+ gboolean clientable;
GtkWidget *label;
@@ -191,8 +204,6 @@ struct _nvGPUDataRec {
gpointer handle; /* NV-CONTROL GPU Target */
- guint server_mask;
- guint clients_mask;
gboolean enabled; /* Sync enabled */
GtkWidget *timing_label;
@@ -821,30 +832,37 @@ static gchar *get_display_name(nvDisplayDataPtr data, gboolean simple)
{
ReturnStatus ret;
char *display_name;
- char *display_type;
+ char *display_type = NULL;
char *name;
-
- ret = NvCtrlGetStringDisplayAttribute(data->handle,
- data->device_mask,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &display_name);
+
+ ret = NvCtrlGetStringAttribute(data->handle,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
+ &display_name);
if (ret != NvCtrlSuccess) {
display_name = NULL;
}
- display_type =
- display_device_mask_to_display_device_name(data->device_mask);
+ if (!simple) {
+ ret =
+ NvCtrlGetStringAttribute(data->handle,
+ NV_CTRL_STRING_DISPLAY_NAME_RANDR,
+ &display_type);
+ if (ret != NvCtrlSuccess) {
+ display_type = NULL;
+ }
+ }
- if (simple) {
- name = g_strconcat(display_name?display_name:"Unknown Display",
- NULL);
- } else {
- name = g_strconcat(display_name?display_name:"Unknown Display",
+ if (display_type) {
+ name = g_strconcat((display_name ? display_name : "Unknown Display"),
" (", display_type, ")", NULL);
+ XFree(display_type);
+ } else {
+ name = g_strconcat((display_name ? display_name : "Unknown Display"),
+ NULL);
}
if (display_name) {
- free(display_name);
+ XFree(display_name);
}
return name;
@@ -1123,6 +1141,24 @@ static nvListEntryPtr get_display_server_entry(nvListTreePtr tree)
+/** get_display_server_data() ****************************************
+ *
+ * Retrieves the display list entry'sdata that is the currently
+ * selected server.
+ *
+ */
+static nvDisplayDataPtr get_display_server_data(nvListTreePtr tree)
+{
+ nvListEntryPtr entry = get_display_server_entry(tree);
+ if (!entry) {
+ return NULL;
+ }
+
+ return (nvDisplayDataPtr)entry->data;
+}
+
+
+
/** list_entry_update_framelock_controls() ***************************
*
* Updates a Quadro Sync list entry's GUI controls based on the current
@@ -1166,27 +1202,7 @@ static void list_entry_update_framelock_controls(CtkFramelock *ctk_framelock,
static void list_entry_update_gpu_controls(CtkFramelock *ctk_framelock,
nvListEntryPtr entry)
{
- nvGPUDataPtr data = (nvGPUDataPtr)(entry->data);
- int slaveables;
- nvDisplayDataPtr display_data;
- nvListEntryPtr child;
- ReturnStatus ret;
-
-
- ret = NvCtrlGetDisplayAttribute(data->handle,
- ~0, /* Query all displays */
- NV_CTRL_FRAMELOCK_SLAVEABLE,
- &slaveables);
-
- /* Update the slaveable flag of the GPU's display devices */
- child = entry->children;
- while (child) {
- display_data = (nvDisplayDataPtr)(child->data);
- /* Assume device is slaveable if slaveable query fails. */
- display_data->slaveable = ((ret != NvCtrlSuccess) ||
- (display_data->device_mask & slaveables));
- child = child->next_sibling;
- }
+ /* No controls to update */
}
static gboolean framelock_refresh_rates_compatible(int server, int client)
@@ -1215,64 +1231,52 @@ static gboolean framelock_refresh_rates_compatible(int server, int client)
static void list_entry_update_display_controls(CtkFramelock *ctk_framelock,
nvListEntryPtr entry)
{
- nvDisplayDataPtr data = (nvDisplayDataPtr)(entry->data);
+ nvDisplayDataPtr display_data = (nvDisplayDataPtr)(entry->data);
gboolean framelock_enabled = ctk_framelock->framelock_enabled;
gboolean sensitive;
-
- nvListTreePtr tree = (nvListTreePtr)(ctk_framelock->tree);
- nvListEntryPtr server_entry = get_display_server_entry(tree);
- nvDisplayDataPtr server_data = NULL;
-
+ nvDisplayDataPtr server_data = get_display_server_data(entry->tree);
- if (server_entry) {
- server_data = (nvDisplayDataPtr)(server_entry->data);
- if (!server_data) {
- return; /* Oops */
- }
- }
- /* Server Checkbox is unavailable when framelock is enabled,
- * this display cannot be master
- * (display is driven by GPU that is connected through a
- * secondary connector.).
+ /* Display can be set as the server if Framelock is disabled and the
+ * display is serverable.
*/
- sensitive = (!framelock_enabled && data->masterable);
- gtk_widget_set_sensitive(data->server_label, sensitive);
- gtk_widget_set_sensitive(data->server_checkbox, sensitive);
-
- /* When a server is selected, this display can only become a
- * client if the X server reports that it can frame lock this
- * client correctly.
+ sensitive = (!framelock_enabled && display_data->serverable);
+ gtk_widget_set_sensitive(display_data->server_label, sensitive);
+ gtk_widget_set_sensitive(display_data->server_checkbox, sensitive);
+
+ /* Display can be set as a client if Framelock is disabled and the
+ * display is clientable. Noce that if a server is currently selected,
+ * and this display does not match the refresh rate, we still allow users
+ * to select this display as a client - at which point we'll implicitly
+ * disable the server.
*/
- sensitive = (!framelock_enabled && data->slaveable);
- gtk_widget_set_sensitive(data->client_label, sensitive);
- gtk_widget_set_sensitive(data->client_checkbox, sensitive);
+ sensitive = (!framelock_enabled && display_data->clientable);
+ gtk_widget_set_sensitive(display_data->client_label, sensitive);
+ gtk_widget_set_sensitive(display_data->client_checkbox, sensitive);
- /* Gray out the display device's refresh rate when it is not
- * the same as the current server's, or the X server tells us
- * the client cannot be frame locked.
+ /* Gray out the display device's refresh rate when it is not the same as
+ * the current server's, or the X server tells us the client cannot be
+ * framelocked.
*/
- sensitive = (data->slaveable &&
- (!server_data ||
- framelock_refresh_rates_compatible(server_data->rate_mHz,
- data->rate_mHz)));
- gtk_widget_set_sensitive(data->rate_label, sensitive);
- gtk_widget_set_sensitive(data->rate_text, sensitive);
- gtk_widget_set_sensitive(data->label, sensitive);
-
- ctk_config_set_tooltip(entry->tree->ctk_framelock->ctk_config, entry->ebox,
+ sensitive = (display_data->clientable &&
+ (!server_data ||
+ framelock_refresh_rates_compatible(server_data->rate_mHz,
+ display_data->rate_mHz)));
+ gtk_widget_set_sensitive(display_data->rate_label, sensitive);
+ gtk_widget_set_sensitive(display_data->rate_text, sensitive);
+ gtk_widget_set_sensitive(display_data->label, sensitive);
+
+
+ ctk_config_set_tooltip(ctk_framelock->ctk_config, entry->ebox,
sensitive ? NULL : "This display device cannot be "
"included in the frame lock group since it has a "
"different refresh rate than that of the server.");
- /* Remove display device from the GPU's clients list */
+ /* If display cannot be a client, make sure it is not set as such */
if (!sensitive && gtk_toggle_button_get_active
- (GTK_TOGGLE_BUTTON(data->client_checkbox))) {
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox))) {
gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(data->client_checkbox),
- FALSE);
- ((nvGPUDataPtr)(entry->parent->data))->clients_mask &=
- data->device_mask;
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox), FALSE);
}
}
@@ -1315,30 +1319,84 @@ static void list_entry_update_controls(CtkFramelock *ctk_framelock,
-/** any_gpu_has_selection() ******************************************
+/** has_client_selected() ********************************************
*
- * Returns TRUE if any of the gpus have a server/client selected
+ * Returns TRUE if any of the displays in the tree are configured as
+ * clients.
*
*/
-static gboolean any_gpu_has_selection(nvListEntryPtr entry)
+static gboolean has_client_selected(nvListEntryPtr entry)
{
if (!entry) return FALSE;
- if (entry->data_type == ENTRY_DATA_GPU &&
- (((nvGPUDataPtr)(entry->data))->server_mask ||
- ((nvGPUDataPtr)(entry->data))->clients_mask)) {
+ if (entry->data_type == ENTRY_DATA_DISPLAY) {
+ nvDisplayDataPtr data = (nvDisplayDataPtr) entry->data;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->client_checkbox))) {
+ return TRUE;
+ }
+ }
+
+ if (has_client_selected(entry->children)) {
return TRUE;
}
- if (any_gpu_has_selection(entry->children)) {
+ return has_client_selected(entry->next_sibling);
+}
+
+
+
+/** has_server_selected() ********************************************
+ *
+ * Returns TRUE if any of the displays in the tree are configured as
+ * the server.
+ *
+ */
+static gboolean has_server_selected(nvListEntryPtr entry)
+{
+ if (!entry) return FALSE;
+
+ if (entry->data_type == ENTRY_DATA_DISPLAY) {
+ nvDisplayDataPtr data = (nvDisplayDataPtr) entry->data;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->server_checkbox))) {
+ return TRUE;
+ }
+ }
+
+ if (has_server_selected(entry->children)) {
return TRUE;
}
- if (any_gpu_has_selection(entry->next_sibling)) {
+ return has_server_selected(entry->next_sibling);
+}
+
+
+
+/** has_display_selected() *******************************************
+ *
+ * Returns TRUE if any of the displays are selected as a server or
+ * client.
+ *
+ */
+static gboolean has_display_selected(nvListEntryPtr entry)
+{
+ if (!entry) return FALSE;
+
+ if (entry->data_type == ENTRY_DATA_DISPLAY) {
+ nvDisplayDataPtr data = (nvDisplayDataPtr) entry->data;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->client_checkbox)) ||
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->server_checkbox))) {
+ return TRUE;
+ }
+ }
+
+ if (has_display_selected(entry->children)) {
return TRUE;
}
- return FALSE;
+ return has_display_selected(entry->next_sibling);
}
@@ -1354,12 +1412,12 @@ static gboolean any_gpu_has_selection(nvListEntryPtr entry)
static void update_framelock_controls(CtkFramelock *ctk_framelock)
{
nvListTreePtr tree;
- gboolean enabled;
+ gboolean framelock_enabled;
gboolean something_selected;
tree = (nvListTreePtr)(ctk_framelock->tree);
- enabled = ctk_framelock->framelock_enabled;
+ framelock_enabled = ctk_framelock->framelock_enabled;
/* Quadro Sync Buttons */
gtk_widget_set_sensitive(ctk_framelock->remove_devices_button,
@@ -1372,18 +1430,17 @@ static void update_framelock_controls(CtkFramelock *ctk_framelock)
(G_OBJECT(ctk_framelock->sync_state_button),
G_CALLBACK(toggle_sync_enable),
(gpointer) ctk_framelock);
-
- something_selected =
- any_gpu_has_selection(((nvListTreePtr)ctk_framelock->tree)->entries);
+
+ something_selected = has_display_selected(tree->entries);
gtk_widget_set_sensitive(ctk_framelock->sync_state_button,
- tree->nentries && something_selected);
+ something_selected);
gtk_container_remove
(GTK_CONTAINER(ctk_framelock->sync_state_button),
ctk_framelock->selected_syncing_label);
- if (tree->nentries && enabled) {
+ if (tree->nentries && framelock_enabled) {
ctk_framelock->selected_syncing_label =
ctk_framelock->disable_syncing_label;
gtk_toggle_button_set_active
@@ -1407,7 +1464,7 @@ static void update_framelock_controls(CtkFramelock *ctk_framelock)
/* Test link */
gtk_widget_set_sensitive(ctk_framelock->test_link_button,
- (enabled && tree->server_entry));
+ (framelock_enabled && tree->server_entry));
/* Update the frame lock Quadro Sync frame */
list_entry_update_controls(ctk_framelock, tree->entries);
@@ -1421,41 +1478,6 @@ static void update_framelock_controls(CtkFramelock *ctk_framelock)
-/** get_display_on_gpu() *********************************************
- *
- * Returns the display list entry that matches the device mask and
- * is connected to the gpu list entry.
- *
- */
-static nvListEntryPtr get_display_on_gpu(nvListEntryPtr gpu_entry,
- guint device_mask)
-{
- nvListEntryPtr display_entry;
- nvDisplayDataPtr display_data;
-
- if (!device_mask) {
- return NULL;
- }
-
- /* Gather bitmask of server/clients */
- display_entry = gpu_entry->children;
- for (display_entry = gpu_entry->children; display_entry;
- display_entry = display_entry->next_sibling) {
-
- if (display_entry->data_type != ENTRY_DATA_DISPLAY) {
- continue;
- }
-
- display_data = (nvDisplayDataPtr)(display_entry->data);
- if (display_data->device_mask & device_mask) {
- return display_entry;
- }
- }
- return NULL;
-}
-
-
-
/** any_gpu_enabled() ************************************************
*
* Returns TRUE if any of the gpus have frame lock enabled.
@@ -1743,7 +1765,7 @@ static void list_entry_remove_expander_button(nvListEntryPtr entry)
* a tree keep their parent-child relationship.
*
*/
-static nvListEntryPtr list_entry_new(void)
+static nvListEntryPtr list_entry_new(nvListTreePtr tree)
{
nvListEntryPtr entry;
@@ -1752,6 +1774,8 @@ static nvListEntryPtr list_entry_new(void)
return NULL;
}
+ entry->tree = tree;
+
/* Create the vertical box that holds this entry and its children */
entry->vbox = gtk_vbox_new(FALSE, 0);
@@ -2057,7 +2081,8 @@ static void list_entry_remove_children(nvListEntryPtr entry)
* data.
*
*/
-static nvListEntryPtr list_entry_new_with_framelock(nvFrameLockDataPtr data)
+static nvListEntryPtr list_entry_new_with_framelock(nvFrameLockDataPtr data,
+ nvListTreePtr tree)
{
nvListEntryPtr entry;
@@ -2067,7 +2092,7 @@ static nvListEntryPtr list_entry_new_with_framelock(nvFrameLockDataPtr data)
GtkWidget *padding;
- entry = list_entry_new();
+ entry = list_entry_new(tree);
if (!entry) {
return NULL;
}
@@ -2160,7 +2185,8 @@ static nvListEntryPtr list_entry_new_with_framelock(nvFrameLockDataPtr data)
* - Creates a new list entry that will hold the given gpu data.
*
*/
-static nvListEntryPtr list_entry_new_with_gpu(nvGPUDataPtr data)
+static nvListEntryPtr list_entry_new_with_gpu(nvGPUDataPtr data,
+ nvListTreePtr tree)
{
nvListEntryPtr entry;
@@ -2169,7 +2195,7 @@ static nvListEntryPtr list_entry_new_with_gpu(nvGPUDataPtr data)
GtkWidget *padding;
- entry = list_entry_new();
+ entry = list_entry_new(tree);
if (!entry) {
return NULL;
}
@@ -2206,7 +2232,8 @@ static nvListEntryPtr list_entry_new_with_gpu(nvGPUDataPtr data)
* - Creates a new list entry that will hold the given display data.
*
*/
-static nvListEntryPtr list_entry_new_with_display(nvDisplayDataPtr data)
+static nvListEntryPtr list_entry_new_with_display(nvDisplayDataPtr data,
+ nvListTreePtr tree)
{
nvListEntryPtr entry;
@@ -2216,12 +2243,13 @@ static nvListEntryPtr list_entry_new_with_display(nvDisplayDataPtr data)
GtkWidget *padding;
- entry = list_entry_new();
+ entry = list_entry_new(tree);
if (!entry) {
return NULL;
}
entry->data = (gpointer)(data);
entry->data_type = ENTRY_DATA_DISPLAY;
+ entry->ctk_event = CTK_EVENT(ctk_event_new(data->handle));
/* Pack the data's widgets into the list entry data hbox */
@@ -2303,7 +2331,7 @@ static void list_tree_add_entry(nvListTreePtr tree, nvListEntryPtr entry)
{
nvListEntryPtr e;
- if (!tree || !entry || entry->tree) {
+ if (!tree || !entry) {
return;
}
entry->tree = tree;
@@ -2763,18 +2791,28 @@ static void expand_all_clicked(GtkWidget *widget, gpointer data)
*/
static void toggle_server(GtkWidget *widget, gpointer data)
{
- nvListEntryPtr entry = (nvListEntryPtr)data;
- nvListEntryPtr server_entry = NULL;
- nvDisplayDataPtr display_data = (nvDisplayDataPtr)(entry->data);
- nvDisplayDataPtr server_entry_display_data = NULL;
- nvListTreePtr tree = (nvListTreePtr)(entry->tree);
- nvGPUDataPtr gpu_data = (nvGPUDataPtr)(entry->parent->data);
+ nvListEntryPtr display_entry = (nvListEntryPtr)data;
+ nvDisplayDataPtr display_data;
+ nvGPUDataPtr gpu_data;
+ nvListTreePtr tree;
+ CtkFramelock *ctk_framelock;
gboolean server_checked;
- if (entry->data_type != ENTRY_DATA_DISPLAY) {
+ if (display_entry->data_type != ENTRY_DATA_DISPLAY) {
return;
}
+ display_data = (nvDisplayDataPtr)(display_entry->data);
+ gpu_data = (nvGPUDataPtr)(display_entry->parent->data);
+ tree = (nvListTreePtr)(display_entry->tree);
+ ctk_framelock = tree->ctk_framelock;
+
+ /* Make sure FrameLock is disabled on the GPU */
+ NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
+ NV_CTRL_FRAMELOCK_SYNC_DISABLE);
+ gpu_data->enabled = FALSE;
+ ctk_framelock->framelock_enabled = any_gpu_enabled(tree->entries);
+
server_checked = gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON(display_data->server_checkbox));
@@ -2784,35 +2822,35 @@ static void toggle_server(GtkWidget *widget, gpointer data)
* it was selected as server before.
*/
if (server_checked) {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->client_checkbox), FALSE);
- server_entry = get_display_server_entry(tree);
- if (server_entry) {
- server_entry_display_data = (nvDisplayDataPtr)server_entry->data;
+ nvDisplayDataPtr server_data =
+ get_display_server_data(display_entry->tree);
+ if (server_data &&
+ (server_data != display_data)) {
gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(server_entry_display_data->server_checkbox),
- FALSE);
+ (GTK_TOGGLE_BUTTON(server_data->server_checkbox), FALSE);
}
- }
-
- entry->tree->server_entry = (server_checked ? entry : NULL);
- gpu_data->server_mask = (server_checked ? display_data->device_mask : 0);
+ tree->server_entry = display_entry;
- /* Update X server state, making sure FrameLock sync is disabled */
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
- NV_CTRL_FRAMELOCK_SYNC_DISABLE);
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox), FALSE);
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_MASTER,
- gpu_data->server_mask);
+ NvCtrlSetAttribute(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER);
+ } else {
+ if (tree->server_entry == display_entry) {
+ tree->server_entry = NULL;
+ }
- gpu_data->enabled = FALSE;
- entry->tree->ctk_framelock->framelock_enabled =
- any_gpu_enabled(entry->tree->entries);
+ NvCtrlSetAttribute(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED);
+ }
/* Update GUI state */
- update_framelock_controls(entry->tree->ctk_framelock);
+ update_framelock_controls(ctk_framelock);
- ctk_config_statusbar_message(entry->tree->ctk_framelock->ctk_config,
+ ctk_config_statusbar_message(ctk_framelock->ctk_config,
"%s frame lock server device.",
(server_checked ? "Selected" : "Unselected"));
}
@@ -2827,47 +2865,53 @@ static void toggle_server(GtkWidget *widget, gpointer data)
*/
static void toggle_client(GtkWidget *widget, gpointer data)
{
- nvListEntryPtr entry = (nvListEntryPtr)data;
- nvDisplayDataPtr display_data = (nvDisplayDataPtr)(entry->data);
- nvGPUDataPtr gpu_data = (nvGPUDataPtr)(entry->parent->data);
+ nvListEntryPtr display_entry = (nvListEntryPtr)data;
+ nvDisplayDataPtr display_data;
+ nvGPUDataPtr gpu_data;
+ nvListTreePtr tree;
+ CtkFramelock *ctk_framelock;
gboolean client_checked;
- if (entry->data_type != ENTRY_DATA_DISPLAY) {
+ if (display_entry->data_type != ENTRY_DATA_DISPLAY) {
return;
}
+ display_data = (nvDisplayDataPtr)(display_entry->data);
+ gpu_data = (nvGPUDataPtr)(display_entry->parent->data);
+ tree = (nvListTreePtr)(display_entry->tree);
+ ctk_framelock = tree->ctk_framelock;
+
+ /* Make sure FrameLock is disabled on the GPU */
+ NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
+ NV_CTRL_FRAMELOCK_SYNC_DISABLE);
+ gpu_data->enabled = FALSE;
+ ctk_framelock->framelock_enabled = any_gpu_enabled(tree->entries);
+
client_checked = gtk_toggle_button_get_active
(GTK_TOGGLE_BUTTON(display_data->client_checkbox));
-
- if (client_checked) {
- gpu_data->clients_mask |= display_data->device_mask;
- /*
- * if the device is selected as client, uncheck the server box
- * for the same.
- */
+ /*
+ * if the device is selected as client, uncheck the server box
+ * for the same.
+ */
+ if (client_checked) {
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON(display_data->server_checkbox), FALSE);
+
+ NvCtrlSetAttribute(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT);
} else {
- gpu_data->clients_mask &= ~(display_data->device_mask);
+ NvCtrlSetAttribute(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED);
}
- /* Update X server state, make sure FrameLock Sync is disabled */
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
- NV_CTRL_FRAMELOCK_SYNC_DISABLE);
-
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SLAVES,
- gpu_data->clients_mask);
-
- gpu_data->enabled = FALSE;
- entry->tree->ctk_framelock->framelock_enabled =
- any_gpu_enabled(entry->tree->entries);
-
/* Update GUI state */
- update_framelock_controls(entry->tree->ctk_framelock);
+ update_framelock_controls(ctk_framelock);
- ctk_config_statusbar_message(entry->tree->ctk_framelock->ctk_config,
+ ctk_config_statusbar_message(ctk_framelock->ctk_config,
"%s frame lock client device.",
(client_checked ? "Selected" : "Unselected"));
}
@@ -2932,7 +2976,7 @@ static gboolean set_enable_sync_clients(nvListEntryPtr entry_list,
/* Go through all entries and activate/disable all entries that
* aren't the server.
*/
-
+
for (entry = entry_list; entry; entry = entry->next_sibling) {
nvGPUDataPtr data;
@@ -2941,19 +2985,20 @@ static gboolean set_enable_sync_clients(nvListEntryPtr entry_list,
enable);
framelock_enabled = (framelock_enabled || something_enabled);
}
-
+
if (entry == server_gpu_entry || entry->data_type != ENTRY_DATA_GPU) {
continue;
}
data = (nvGPUDataPtr)(entry->data);
-
+
/* Only send protocol if there is something to enable */
- if (!data->clients_mask) continue;
+ if (!has_client_selected(entry)) continue;
ret = NvCtrlSetAttribute(data->handle, NV_CTRL_FRAMELOCK_SYNC, enable);
if (ret != NvCtrlSuccess) continue;
+ /* Verify state w/ the server */
ret = NvCtrlGetAttribute(data->handle, NV_CTRL_FRAMELOCK_SYNC,
&(something_enabled));
if (ret != NvCtrlSuccess) continue;
@@ -3534,7 +3579,7 @@ static void toggle_detect_video_mode(GtkToggleButton *button,
/** list_entry_update_framelock_status() *****************************
*
- * Updates the state of the GUI for a frame lock list entry by
+ * Updates the dynamic state of the GUI for a frame lock list entry by
* querying the current state of the X Server.
*
*/
@@ -3642,8 +3687,8 @@ static void list_entry_update_framelock_status(CtkFramelock *ctk_framelock,
/** list_entry_update_gpu_status() ***********************************
*
- * Updates the state of the GUI for a gpu list entry by querying the
- * current state of the X Server.
+ * Updates the dynamic state of the GUI for a gpu list entry by
+ * querying the current state of the X Server.
*
*/
static void list_entry_update_gpu_status(CtkFramelock *ctk_framelock,
@@ -3670,8 +3715,8 @@ static void list_entry_update_gpu_status(CtkFramelock *ctk_framelock,
&house);
}
- has_client = data->clients_mask;
- has_server = data->server_mask;
+ has_client = has_client_selected(entry);
+ has_server = has_server_selected(entry);
/* Update the Timing LED:
*
@@ -3702,8 +3747,8 @@ static void list_entry_update_gpu_status(CtkFramelock *ctk_framelock,
/** list_entry_update_display_status() *******************************
*
- * Updates the state of the GUI for a display list entry by querying
- * the current state of the X Server.
+ * Updates the dynamic state of the GUI for a display list entry by
+ * querying the current state of the X Server.
*
*/
static void list_entry_update_display_status(CtkFramelock *ctk_framelock,
@@ -3741,28 +3786,30 @@ static void list_entry_update_display_status(CtkFramelock *ctk_framelock,
gtk_widget_set_sensitive(data->stereo_label, FALSE);
update_image(data->stereo_hbox, ctk_framelock->led_grey_pixbuf);
} else {
- nvGPUDataPtr gpu_data;
- gint timing = TRUE;
- gint stereo_sync;
-
/* If the display's GPU is not receiving timing, activate the
* stereo label but make sure to gray out the LED.
*/
gtk_widget_set_sensitive(data->stereo_label, TRUE);
if (entry->parent) {
- gpu_data = (nvGPUDataPtr)(entry->parent->data);
- NvCtrlGetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_TIMING,
- &timing);
- }
- if (!timing) {
- update_image(data->stereo_hbox, ctk_framelock->led_grey_pixbuf);
- } else {
- NvCtrlGetAttribute(data->handle, NV_CTRL_FRAMELOCK_STEREO_SYNC,
- &stereo_sync);
- update_image(data->stereo_hbox,
- (stereo_sync ? ctk_framelock->led_green_pixbuf :
- ctk_framelock->led_red_pixbuf));
+ GdkPixbuf *pixbuf = ctk_framelock->led_grey_pixbuf;
+ nvGPUDataPtr gpu_data = (nvGPUDataPtr)(entry->parent->data);
+ ReturnStatus ret;
+ int val;
+
+ ret = NvCtrlGetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_TIMING,
+ &val);
+ if ((ret == NvCtrlSuccess) &&
+ (val == NV_CTRL_FRAMELOCK_TIMING_TRUE)) {
+ ret = NvCtrlGetAttribute(gpu_data->handle,
+ NV_CTRL_FRAMELOCK_STEREO_SYNC, &val);
+ if (ret == NvCtrlSuccess) {
+ pixbuf = (val == NV_CTRL_FRAMELOCK_STEREO_SYNC_TRUE) ?
+ ctk_framelock->led_green_pixbuf :
+ ctk_framelock->led_red_pixbuf;
+ }
+ }
+ update_image(data->stereo_hbox, pixbuf);
}
}
}
@@ -4034,176 +4081,262 @@ static void update_display_rate_txt(nvDisplayDataPtr data,
-/** gpu_state_received() *********************************************
+/** validate_clients_against_server() ********************************
*
- * Signal handler for gpu target events.
+ * Validates that the given client entries (siblings and any children
+ * of 'entry') match the server display's refresh rate, and disables
+ * any client entries that don't.
*
*/
-static void gpu_state_received(GtkObject *object,
- gpointer arg1, gpointer user_data)
+
+static void validate_clients_against_server(nvListEntryPtr entry,
+ nvDisplayDataPtr server_display_data)
{
- CtkEventStruct *event = (CtkEventStruct *) arg1;
- nvListEntryPtr gpu_entry = (nvListEntryPtr) user_data;
- nvGPUDataPtr gpu_data = (nvGPUDataPtr) gpu_entry->data;
+ nvDisplayDataPtr display_data;
- nvListEntryPtr display_entry = NULL;
- nvDisplayDataPtr display_data = NULL;
+ if (!entry || !server_display_data) return;
- CtkFramelock *ctk_framelock = gpu_entry->tree->ctk_framelock;
- gboolean sensitive;
- gboolean checked;
- int rateMultiplier = 1;
- int precision = 3;
+ if (entry->data_type == ENTRY_DATA_DISPLAY) {
+ display_data = (nvDisplayDataPtr)entry->data;
- switch (event->attribute) {
- case NV_CTRL_FRAMELOCK_MASTER:
-
- /* Unset the previous master */
- display_entry = get_display_server_entry(gpu_entry->tree);
- if (display_entry) {
- display_data = (nvDisplayDataPtr)(display_entry->data);
-
- /* Clear the server checkbox */
- g_signal_handlers_block_by_func
- (G_OBJECT(display_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
-
+ if ((display_data != server_display_data) &&
+ (!framelock_refresh_rates_compatible(server_display_data->rate_mHz,
+ display_data->rate_mHz))) {
gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->server_checkbox), 0);
-
- g_signal_handlers_unblock_by_func
- (G_OBJECT(display_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
-
- /* If the server display device is on another gpu, tell the
- * X Server we are unsetting it.
- */
- if (display_entry->parent != gpu_entry) {
- nvGPUDataPtr gpu_data =
- (nvGPUDataPtr)(display_entry->parent->data);
-
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
- NV_CTRL_FRAMELOCK_SYNC_DISABLE);
- gpu_data->enabled = FALSE;
-
- NvCtrlSetAttribute(display_data->handle,
- NV_CTRL_FRAMELOCK_MASTER, 0);
- }
- ((nvGPUDataPtr)(display_entry->parent->data))->server_mask = 0;
- gpu_entry->tree->server_entry = NULL;
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox), FALSE);
}
+ }
- /* Set the new master */
- display_entry = get_display_on_gpu(gpu_entry, event->value);
- if (display_entry) {
- display_data = (nvDisplayDataPtr)(display_entry->data);
+ validate_clients_against_server(entry->children,
+ server_display_data);
- /* Set the server checkbox */
- g_signal_handlers_block_by_func
- (G_OBJECT(display_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
-
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->server_checkbox), 1);
-
- g_signal_handlers_unblock_by_func
- (G_OBJECT(display_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
-
- gpu_entry->tree->server_entry = display_entry;
+ validate_clients_against_server(entry->next_sibling,
+ server_display_data);
+}
+
+
+
+/** update_display_config() ******************************************
+ *
+ * Updates the UI to reflect the current configuration of a display
+ * device. This function is meant to be used as a handler for
+ * NV_CTRL_FRAMELOCK_DISPLAY_CONFIG events, as well as initialization.
+ *
+ * As a side effect, calling this function may possibly disable the
+ * currently selected server, incompatible clients, and/or framelock sync.
+ * This occurs if a new framelock server is being configured, or a client is
+ * selected that does not properly match the currently selected server's
+ * refresh rate.
+ *
+ */
+
+static void update_display_config(nvListEntryPtr display_entry, int config)
+{
+ nvDisplayDataPtr display_data = (nvDisplayDataPtr)display_entry->data;
+ ReturnStatus ret;
+ NVCTRLAttributeValidValuesRec valid_config;
+ gboolean serverable = FALSE;
+ gboolean clientable = FALSE;
+
+ nvDisplayDataPtr old_server_display_data;
+
+
+ /* Get what is possible */
+ ret = NvCtrlGetValidAttributeValues(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ &valid_config);
+
+ if (ret == NvCtrlSuccess &&
+ (valid_config.type == ATTRIBUTE_TYPE_INT_BITS)) {
+ if (valid_config.u.bits.ints &
+ (1<<NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT)) {
+ clientable = TRUE;
}
-
- gpu_data->server_mask = event->value;
+ if (valid_config.u.bits.ints &
+ (1<<NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER)) {
+ serverable = TRUE;
+ }
+ }
- /* See if anything was disabled */
- ctk_framelock->framelock_enabled =
- any_gpu_enabled(gpu_entry->tree->entries);
+ display_data->serverable = serverable;
+ display_data->clientable = clientable;
- update_framelock_controls(gpu_entry->tree->ctk_framelock);
- break;
+ if (!clientable && config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT) {
+ config = NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED;
+ }
+ if (!serverable && config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER) {
+ config = NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED;
+ }
- case NV_CTRL_FRAMELOCK_SLAVES:
-
- /* Set all client devices on this GPU. If a client is found
- * to not match the selected server's refresh rate, unselect
- * the server. The user will have to reselect the server.
+ gtk_widget_set_sensitive(display_data->client_label, clientable);
+ gtk_widget_set_sensitive(display_data->client_checkbox, clientable);
+
+ gtk_widget_set_sensitive(display_data->server_label, serverable);
+ gtk_widget_set_sensitive(display_data->server_checkbox, serverable);
+
+
+ /* Ensure we'll end up in a valid configuration.
+ *
+ * If a client is being enabled:
+ * - Disable the server if its refresh rate does not match. (It will be
+ * up to the client to re-select a propper server.)
+ *
+ * If a (new) server is being enabled:
+ * - Disable any previous server.
+ * - Disable any configured clients that do not match the new server's
+ * refresh rate.
+ *
+ */
+
+ old_server_display_data = get_display_server_data(display_entry->tree);
+
+ if (config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT) {
+ /* Disable existing server if the rates don't match, and make user re-
+ * select the server.
*/
- for (display_entry = gpu_entry->children; display_entry;
- display_entry = display_entry->next_sibling) {
- display_data =
- (nvDisplayDataPtr)(display_entry->data);
-
- sensitive =
- GTK_WIDGET_IS_SENSITIVE(display_data->client_checkbox);
- checked = ((display_data->device_mask) & event->value);
-
- /* Update the display list entry gui */
-
- g_signal_handlers_block_by_func
- (G_OBJECT(display_data->client_checkbox),
- G_CALLBACK(toggle_client),
- (gpointer) display_entry);
-
+ if (old_server_display_data &&
+ (display_data != old_server_display_data) &&
+ (!framelock_refresh_rates_compatible(old_server_display_data->rate_mHz,
+ display_data->rate_mHz))) {
gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->client_checkbox), checked);
-
- g_signal_handlers_unblock_by_func
- (G_OBJECT(display_data->client_checkbox),
- G_CALLBACK(toggle_client),
- (gpointer) display_entry);
-
- /* If there is an inconsistency, unselect the server */
-
- if (checked && !sensitive && gpu_entry->tree->server_entry) {
-
- nvListEntryPtr server_entry =
- get_display_server_entry(gpu_entry->tree);
- nvDisplayDataPtr server_data =
- (nvDisplayDataPtr)(server_entry->data);
-
- /* Clear the server checkbox */
- g_signal_handlers_block_by_func
- (G_OBJECT(server_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
-
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(server_data->server_checkbox), 0);
-
- g_signal_handlers_unblock_by_func
- (G_OBJECT(server_data->server_checkbox),
- G_CALLBACK(toggle_server),
- (gpointer) display_entry);
+ (GTK_TOGGLE_BUTTON(old_server_display_data->server_checkbox),
+ FALSE);
+ }
- NvCtrlSetAttribute(server_data->handle,
- NV_CTRL_FRAMELOCK_MASTER, 0);
- ((nvGPUDataPtr)(server_entry->parent->data))->server_mask = 0;
- gpu_entry->tree->server_entry = NULL;
- }
+ } else if (config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER) {
+ /* Disable any previous servers */
+ if (old_server_display_data &&
+ (display_data != old_server_display_data)) {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(old_server_display_data->server_checkbox),
+ FALSE);
}
- /* Save the client state */
- gpu_data->clients_mask = event->value;
+ /* Disable any configured clients that don't match the new refresh
+ * rate.
+ */
+ validate_clients_against_server(display_entry->tree->entries,
+ display_data);
+ }
+
- /* See if anything was disabled */
- ctk_framelock->framelock_enabled =
- any_gpu_enabled(gpu_entry->tree->entries);
+ /* Apply the setting to the display device */
+
+ g_signal_handlers_block_matched(G_OBJECT(display_entry->ctk_event),
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ (gpointer)display_entry);
+
+ if (config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_CLIENT) {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox), TRUE);
+ } else {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(display_data->client_checkbox), FALSE);
+ }
+
+ if (config == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER) {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(display_data->server_checkbox), TRUE);
+ } else {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(display_data->server_checkbox), FALSE);
+ }
+
+ g_signal_handlers_unblock_matched(G_OBJECT(display_entry->ctk_event),
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ (gpointer)display_entry);
+}
+
+
+
+/** display_state_received() *****************************************
+ *
+ * Signal handler for display target events.
+ *
+ */
+static void display_state_received(GtkObject *object,
+ gpointer arg1, gpointer user_data)
+{
+ CtkEventStruct *event = (CtkEventStruct *) arg1;
+ nvListEntryPtr display_entry = (nvListEntryPtr) user_data;
+ nvDisplayDataPtr display_data;
+ nvListTreePtr tree;
+ CtkFramelock *ctk_framelock;
+
+ int rateMultiplier = 1;
+ int precision = 3;
+
+ if (!display_entry ||
+ !display_entry->data ||
+ !display_entry->data_type != ENTRY_DATA_DISPLAY) {
+ return;
+ }
- update_framelock_controls(gpu_entry->tree->ctk_framelock);
+ display_data = (nvDisplayDataPtr) display_entry->data;
+ tree = display_entry->tree;
+ ctk_framelock = tree->ctk_framelock;
+
+ switch (event->attribute) {
+
+ case NV_CTRL_REFRESH_RATE:
+ rateMultiplier = 10;
+ precision = 2;
+ /* fallthrough */
+ case NV_CTRL_REFRESH_RATE_3:
+ update_display_rate_txt(display_data,
+ event->value * rateMultiplier, /* rate_mHz */
+ precision);
+
+ /* Update the UI */
+ update_framelock_controls(ctk_framelock);
break;
-
+
+ case NV_CTRL_FRAMELOCK_DISPLAY_CONFIG:
+ update_display_config(display_entry, event->value);
+
+ /* Update the UI */
+ update_framelock_controls(ctk_framelock);
+ break;
+ }
+}
+
+
+
+/** gpu_state_received() *********************************************
+ *
+ * Signal handler for gpu target events.
+ *
+ */
+static void gpu_state_received(GtkObject *object,
+ gpointer arg1, gpointer user_data)
+{
+ CtkEventStruct *event = (CtkEventStruct *) arg1;
+ nvListEntryPtr gpu_entry = (nvListEntryPtr) user_data;
+ nvGPUDataPtr gpu_data;
+ nvListTreePtr tree;
+ CtkFramelock *ctk_framelock;
+
+ if (!gpu_entry ||
+ !gpu_entry->data ||
+ !gpu_entry->data_type != ENTRY_DATA_GPU) {
+ return;
+ }
+
+ gpu_data = (nvGPUDataPtr) gpu_entry->data;
+ tree = gpu_entry->tree;
+ ctk_framelock = tree->ctk_framelock;
+
+ switch (event->attribute) {
case NV_CTRL_FRAMELOCK_SYNC:
/* Cache the enable/disable state of the gpu sync */
gpu_data->enabled = event->value;
-
+
/* Look to see if any gpu is enabled/disabled */
ctk_framelock->framelock_enabled =
- any_gpu_enabled(gpu_entry->tree->entries);
+ any_gpu_enabled(tree->entries);
g_signal_handlers_block_by_func
(G_OBJECT(ctk_framelock->sync_state_button),
@@ -4219,10 +4352,9 @@ static void gpu_state_received(GtkObject *object,
G_CALLBACK(toggle_sync_enable),
(gpointer) ctk_framelock);
- update_framelock_controls(gpu_entry->tree->ctk_framelock);
+ update_framelock_controls(ctk_framelock);
break;
-
case NV_CTRL_FRAMELOCK_TEST_SIGNAL:
switch (event->value) {
case NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE:
@@ -4248,11 +4380,11 @@ static void gpu_state_received(GtkObject *object,
(G_OBJECT(ctk_framelock->test_link_button),
G_CALLBACK(toggle_test_link),
(gpointer) ctk_framelock);
-
+
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON(ctk_framelock->test_link_button),
ctk_framelock->test_link_enabled);
-
+
g_signal_handlers_unblock_by_func
(G_OBJECT(ctk_framelock->test_link_button),
G_CALLBACK(toggle_test_link),
@@ -4264,39 +4396,11 @@ static void gpu_state_received(GtkObject *object,
"Test link complete."));
break;
-
- case NV_CTRL_REFRESH_RATE:
- rateMultiplier = 10;
- precision = 2;
- /* fallthrough */
- case NV_CTRL_REFRESH_RATE_3:
- /* Update the display device's refresh rate */
- display_entry = get_display_on_gpu(gpu_entry, event->display_mask);
- if (display_entry && display_entry->data) {
- display_data =
- (nvDisplayDataPtr)(display_entry->data);
-
- update_display_rate_txt(display_data,
- event->value * rateMultiplier,
- precision);
- }
-
- /* Make sure the framelock controls are in a consistent state */
- update_framelock_controls(ctk_framelock);
- break;
-
-
- case NV_CTRL_FRAMELOCK_SLAVEABLE:
- /* Update slaveable relationships in the GUI */
- update_framelock_controls(ctk_framelock);
- break;
-
-
default:
/* Oops */
break;
}
-
+
} /* gpu_state_received() */
@@ -5088,238 +5192,203 @@ static void remove_devices_response(GtkWidget *button, gint response,
-/** add_display_devices() ********************************************
+/** add_display_device() *********************************************
*
- * Adds (as children list entries) all enabled display devices that
- * are bound to the given GPU List Entry.
+ * Adds an display device to the give GPU entry.
*
*/
-static void add_display_devices(CtkFramelock *ctk_framelock,
- nvListEntryPtr gpu_entry)
+static gboolean add_display_device(CtkFramelock *ctk_framelock,
+ nvListEntryPtr gpu_entry,
+ int display_id)
{
- nvDisplayDataPtr display_data = NULL;
-
- nvGPUDataPtr gpu_data;
- nvListEntryPtr entry;
- ReturnStatus ret;
-
- unsigned int enabled_displays;
- unsigned int display_mask;
+ nvGPUDataPtr gpu_data = (nvGPUDataPtr)(gpu_entry->data);
+ nvDisplayDataPtr display_data = NULL;
+ nvListEntryPtr entry = NULL;
+ nvListTreePtr tree = (nvListTreePtr)(ctk_framelock->tree);
- unsigned int master_mask;
- unsigned int slaves_mask;
+ ReturnStatus ret;
+ int val;
+ int rate;
+ int precision;
+ gboolean hdmi3D;
+ int i;
- nvListEntryPtr server_entry = NULL;
+ display_data = (nvDisplayDataPtr) calloc(1, sizeof(nvDisplayDataRec));
+ if (!display_data) {
+ goto fail;
+ }
- if (!gpu_entry || gpu_entry->data_type != ENTRY_DATA_GPU) {
+ display_data->handle =
+ NvCtrlAttributeInit(NvCtrlGetDisplayPtr(gpu_data->handle),
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ display_id,
+ NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
+ if (!display_data->handle) {
goto fail;
}
- server_entry =
- get_display_server_entry((nvListTreePtr)(ctk_framelock->tree));
- gpu_data = (nvGPUDataPtr)(gpu_entry->data);
+ /* Create, pack and link the display device UI widgets */
- /* Query list of devices on this GPU. */
- ret = NvCtrlGetAttribute(gpu_data->handle,
- NV_CTRL_ENABLED_DISPLAYS,
- (int *)&enabled_displays);
- if (ret != NvCtrlSuccess || !enabled_displays) {
- goto fail;
- }
+ display_data->label = gtk_label_new("");
- /* Query master device */
- ret = NvCtrlGetAttribute(gpu_data->handle,
- NV_CTRL_FRAMELOCK_MASTER,
- (int *)&master_mask);
- if (ret != NvCtrlSuccess) {
- goto fail;
- }
+ display_data->server_label = gtk_label_new("Server");
+ display_data->server_checkbox = gtk_check_button_new();
+ ctk_config_set_tooltip(ctk_framelock->ctk_config,
+ display_data->server_checkbox,
+ __server_checkbox_help);
- /* Query slave devices */
- ret = NvCtrlGetAttribute(gpu_data->handle,
- NV_CTRL_FRAMELOCK_SLAVES,
- (int *)&slaves_mask);
- if (ret != NvCtrlSuccess) {
+ display_data->client_label = gtk_label_new("Client");
+ display_data->client_checkbox = gtk_check_button_new();
+ ctk_config_set_tooltip(ctk_framelock->ctk_config,
+ display_data->client_checkbox,
+ __client_checkbox_help);
+
+ display_data->rate_label = gtk_label_new("Refresh:");
+ display_data->rate_text = gtk_label_new("");
+
+ display_data->stereo_label = gtk_label_new("Stereo");
+ display_data->stereo_hbox = gtk_hbox_new(FALSE, 0);
+
+ entry = list_entry_new_with_display(display_data, tree);
+ if (!entry) {
goto fail;
}
-
- /* If the tree already has a master and this display is also set
- * as master, unset this entry and make it a slave. */
- if (server_entry && master_mask) {
- /* Ensure FrameLock sync is disabled before setting server/clients */
- NvCtrlSetAttribute(gpu_data->handle, NV_CTRL_FRAMELOCK_SYNC,
- NV_CTRL_FRAMELOCK_SYNC_DISABLE);
- gpu_data->enabled = FALSE;
+ list_entry_add_child(gpu_entry, entry);
- ret = NvCtrlSetAttribute(gpu_data->handle,
- NV_CTRL_FRAMELOCK_MASTER, 0);
- if (ret != NvCtrlSuccess) {
- goto fail;
- }
- slaves_mask |= master_mask;
- master_mask = 0;
- ret = NvCtrlSetAttribute(gpu_data->handle,
- NV_CTRL_FRAMELOCK_SLAVES, slaves_mask);
+
+ /* Query current configuration */
+
+ /* Name */
+ update_entry_label(ctk_framelock, entry);
+
+ /* Refresh rate */
+ ret = NvCtrlGetAttribute(display_data->handle, NV_CTRL_REFRESH_RATE_3,
+ &rate);
+ if (ret != NvCtrlSuccess) {
+ ret = NvCtrlGetAttribute(display_data->handle, NV_CTRL_REFRESH_RATE,
+ &rate);
if (ret != NvCtrlSuccess) {
- goto fail;
+ rate = 0;
+ precision = 0;
+ } else {
+ rate = rate * 10;
+ precision = 2;
}
+ } else {
+ precision = 3;
}
+ update_display_rate_txt(display_data, rate, precision);
+
+ /* HDMI 3D */
+ ret = NvCtrlGetDisplayAttribute(display_data->handle,
+ display_data->device_mask,
+ NV_CTRL_DPY_HDMI_3D, &hdmi3D);
+ display_data->hdmi3D = hdmi3D;
- /* Cache the server/clients masks */
- gpu_data->server_mask = master_mask;
- gpu_data->clients_mask = slaves_mask;
+ /* Configuration */
+ ret = NvCtrlGetAttribute(display_data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ &val);
+ if (ret != NvCtrlSuccess) {
+ val = NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED;
+ }
+ if (val == NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_SERVER) {
+ tree->server_entry = entry;
+ }
- /* Add all enabled displays found on the GPU */
- display_mask = 1;
- while (display_mask) {
- int rate;
- int precision;
- gboolean hdmi3D;
+ update_display_config(entry, val);
- if (display_mask & enabled_displays) {
- /* Create the display structure */
- display_data =
- (nvDisplayDataPtr) calloc(1, sizeof(nvDisplayDataRec));
- if (!display_data) {
- goto fail;
- }
+ /* Update status (LEDs) based on current state */
- /* Setup the display information */
- display_data->handle = gpu_data->handle;
- display_data->device_mask = display_mask;
+ list_entry_update_status(ctk_framelock, entry);
- ret = NvCtrlGetDisplayAttribute(gpu_data->handle,
- display_mask,
- NV_CTRL_FRAMELOCK_MASTERABLE,
- &(display_data->masterable));
- if (ret != NvCtrlSuccess) {
- goto fail;
- }
- display_data->label = gtk_label_new("");
-
- display_data->server_label = gtk_label_new("Server");
- display_data->server_checkbox = gtk_check_button_new();
- ctk_config_set_tooltip(ctk_framelock->ctk_config,
- display_data->server_checkbox,
- __server_checkbox_help);
-
- display_data->client_label = gtk_label_new("Client");
- display_data->client_checkbox = gtk_check_button_new();
- ctk_config_set_tooltip(ctk_framelock->ctk_config,
- display_data->client_checkbox,
- __client_checkbox_help);
-
-
- display_data->rate_label = gtk_label_new("Refresh:");
- display_data->rate_text = gtk_label_new("");
-
- display_data->stereo_label = gtk_label_new("Stereo");
- display_data->stereo_hbox = gtk_hbox_new(FALSE, 0);
-
- /* Create the display entry */
- entry = list_entry_new_with_display(display_data);
-
- update_entry_label(ctk_framelock, entry);
- list_entry_update_status(ctk_framelock, entry);
-
- /* Add display to GPU entry */
- list_entry_add_child(gpu_entry, entry);
-
- /* Determine if display is HDMI 3D */
- ret = NvCtrlGetDisplayAttribute(display_data->handle,
- display_data->device_mask,
- NV_CTRL_DPY_HDMI_3D, &hdmi3D);
-
- display_data->hdmi3D = hdmi3D;
-
- /* Refresh Rate */
- ret = NvCtrlGetDisplayAttribute(display_data->handle,
- display_data->device_mask,
- NV_CTRL_REFRESH_RATE_3, &rate);
- if (ret != NvCtrlSuccess) {
- ret = NvCtrlGetDisplayAttribute(display_data->handle,
- display_data->device_mask,
- NV_CTRL_REFRESH_RATE, &rate);
- if (ret != NvCtrlSuccess) {
- rate = 0;
- precision = 0;
- } else {
- rate = rate * 10;
- precision = 2;
- }
- } else {
- precision = 3;
- }
- update_display_rate_txt(display_data, rate, precision);
-
- /* Setup state */
- if (!display_data->masterable) {
- gtk_widget_set_sensitive(display_data->server_label, FALSE);
- gtk_widget_set_sensitive(display_data->server_checkbox, FALSE);
-
- } else if (master_mask & display_mask) {
-
- /* If this entry is the new master, make the tree point
- * point to it so other displays that may have the master
- * mask aren't added as masters too by mistake.
- *
- * NOTE: At this point the entry will not actually
- * be in the tree. This gets resolved since
- * by adding this display device the parent
- * GPU and frame lock devices will also be
- * added. If this changes (display device
- * gets added but for some reason the GPU/
- * frame lock device get thrown out), then
- * more code will be required to make sure
- * the tree->selected_entry is set to NULL
- * (if it was NULL before.)
- */
- ((nvListTreePtr)(ctk_framelock->tree))->server_entry =
- entry;
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->server_checkbox), TRUE);
- gtk_widget_set_sensitive(display_data->client_label, FALSE);
- gtk_widget_set_sensitive(display_data->client_checkbox, FALSE);
- }
+ /* Listen to events */
- /* Set display device as slave */
- if (slaves_mask & display_mask) {
- gtk_toggle_button_set_active
- (GTK_TOGGLE_BUTTON(display_data->client_checkbox), TRUE);
- gtk_widget_set_sensitive(display_data->server_label, FALSE);
- gtk_widget_set_sensitive(display_data->server_checkbox, FALSE);
- }
-
- /* Connect signals */
- g_signal_connect(G_OBJECT(display_data->server_checkbox),
- "toggled",
- G_CALLBACK(toggle_server),
- (gpointer) entry);
-
- g_signal_connect(G_OBJECT(display_data->client_checkbox),
- "toggled",
- G_CALLBACK(toggle_client),
- (gpointer) entry);
- }
- display_mask <<= 1;
+ for (i = 0; i < ARRAY_LEN(__DisplaySignals); i++) {
+ g_signal_connect(G_OBJECT(entry->ctk_event),
+ __DisplaySignals[i],
+ G_CALLBACK(display_state_received),
+ (gpointer) entry);
}
- return;
+ g_signal_connect(G_OBJECT(display_data->server_checkbox),
+ "toggled",
+ G_CALLBACK(toggle_server),
+ (gpointer) entry);
+ g_signal_connect(G_OBJECT(display_data->client_checkbox),
+ "toggled",
+ G_CALLBACK(toggle_client),
+ (gpointer) entry);
+ return TRUE;
- /* Handle failures */
fail:
- display_data_free(display_data);
+ if (entry) {
+ list_entry_free(entry);
+ } else if (display_data) {
+ display_data_free(display_data);
+ }
+ return FALSE;
+}
+
+
+
+/** add_display_devices() ********************************************
+ *
+ * Adds (as children list entries) all enabled display devices that
+ * are bound to the given GPU entry.
+ *
+ */
+static void add_display_devices(CtkFramelock *ctk_framelock,
+ nvListEntryPtr gpu_entry)
+{
+ nvGPUDataPtr gpu_data;
+ ReturnStatus ret;
+ int *pData;
+
+ if (!gpu_entry || gpu_entry->data_type != ENTRY_DATA_GPU) {
+ return;
+ }
+
+ gpu_data = (nvGPUDataPtr)(gpu_entry->data);
+ ret =
+ NvCtrlGetBinaryAttribute(gpu_data->handle, 0,
+ NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU,
+ (unsigned char **)(&pData),
+ NULL);
+ if (ret == NvCtrlSuccess) {
+ int i;
+
+ for (i = 0; i < pData[0]; i++) {
+ int display_id = pData[1+i];
+ Bool valid;
+ int enabled;
+
+ /* Only add enabled display devices */
+ valid =
+ XNVCTRLQueryTargetAttribute(NvCtrlGetDisplayPtr(gpu_data->handle),
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ display_id,
+ 0,
+ NV_CTRL_DISPLAY_ENABLED,
+ &enabled);
+ if (valid && enabled) {
+ add_display_device(ctk_framelock, gpu_entry, display_id);
+ }
+ }
+ XFree(pData);
+ }
}
+
/** add_gpu_devices() ************************************************
*
* Adds (as children list entries) all GPU devices that are bound to
@@ -5381,8 +5450,9 @@ static void add_gpu_devices(CtkFramelock *ctk_framelock,
gpu_data->timing_hbox = gtk_hbox_new(FALSE, 0);
/* Create the GPU list entry */
- entry = list_entry_new_with_gpu(gpu_data);
-
+ entry = list_entry_new_with_gpu(gpu_data,
+ (nvListTreePtr)(ctk_framelock->tree));
+
update_entry_label(ctk_framelock, entry);
list_entry_update_status(ctk_framelock, entry);
@@ -5527,7 +5597,8 @@ static void add_framelock_devices(CtkFramelock *ctk_framelock,
framelock_data->server_id = server_id;
/* Create the frame lock list entry */
- entry = list_entry_new_with_framelock(framelock_data);
+ entry = list_entry_new_with_framelock(framelock_data,
+ (nvListTreePtr)(ctk_framelock->tree));
update_entry_label(ctk_framelock, entry);
list_entry_update_status(ctk_framelock, entry);
@@ -5711,13 +5782,13 @@ static void add_devices(CtkFramelock *ctk_framelock,
* to the parsed attribute list.
*
*/
-#define __ADD_ATTR(x,y,z) \
+#define __ADD_ATTR(ATTR,VAL) \
a.display = display_name; \
a.target_type = target_type; \
a.target_id = target_id; \
- a.attr = (x); \
- a.val.i = (y); \
- a.display_device_mask = (z); \
+ a.attr = (ATTR); \
+ a.val.i = (VAL); \
+ a.display_device_mask = 0; \
a.flags |= NV_PARSER_HAS_TARGET; \
nv_parsed_attribute_add(head, &a);
@@ -5744,18 +5815,18 @@ static void add_entry_to_parsed_attributes(nvListEntryPtr entry,
display_name = NvCtrlGetDisplayName(data->handle);
target_type = NV_CTRL_TARGET_TYPE_FRAMELOCK;
target_id = NvCtrlGetTargetId(data->handle);
-
+
NvCtrlGetAttribute(data->handle, NV_CTRL_USE_HOUSE_SYNC,
&use_house_sync);
- __ADD_ATTR(NV_CTRL_USE_HOUSE_SYNC, use_house_sync, 0);
+ __ADD_ATTR(NV_CTRL_USE_HOUSE_SYNC, use_house_sync);
/* If use house sync is enabled, also save other house sync info */
if (use_house_sync) {
int sync_interval;
int sync_edge;
int video_mode;
-
+
NvCtrlGetAttribute(data->handle,
NV_CTRL_FRAMELOCK_SYNC_INTERVAL,
&sync_interval);
@@ -5766,35 +5837,40 @@ static void add_entry_to_parsed_attributes(nvListEntryPtr entry,
NV_CTRL_FRAMELOCK_VIDEO_MODE,
&video_mode);
- __ADD_ATTR(NV_CTRL_FRAMELOCK_SYNC_INTERVAL, sync_interval, 0);
- __ADD_ATTR(NV_CTRL_FRAMELOCK_POLARITY, sync_edge, 0);
- __ADD_ATTR(NV_CTRL_FRAMELOCK_VIDEO_MODE, video_mode, 0);
+ __ADD_ATTR(NV_CTRL_FRAMELOCK_SYNC_INTERVAL, sync_interval);
+ __ADD_ATTR(NV_CTRL_FRAMELOCK_POLARITY, sync_edge);
+ __ADD_ATTR(NV_CTRL_FRAMELOCK_VIDEO_MODE, video_mode);
}
if (display_name) {
free(display_name);
}
- }
+ }
break;
case ENTRY_DATA_GPU:
+ /* Nothing to save for GPU targets */
+ break;
+
+ case ENTRY_DATA_DISPLAY:
{
- nvGPUDataPtr data = (nvGPUDataPtr)(entry->data);
- display_name = NvCtrlGetDisplayName(data->handle);
- target_type = NV_CTRL_TARGET_TYPE_GPU;
- target_id = NvCtrlGetTargetId(data->handle);
+ nvDisplayDataPtr data = (nvDisplayDataPtr)(entry->data);
+ int config;
+ ReturnStatus ret;
- __ADD_ATTR(NV_CTRL_FRAMELOCK_MASTER, data->server_mask, 0);
- __ADD_ATTR(NV_CTRL_FRAMELOCK_SLAVES, data->clients_mask, 0);
+ display_name = NvCtrlGetDisplayName(data->handle);
- if (display_name) {
- free(display_name);
- }
- }
- break;
+ ret = NvCtrlGetAttribute(data->handle,
+ NV_CTRL_FRAMELOCK_DISPLAY_CONFIG,
+ &config);
+ if (ret != NvCtrlSuccess) {
+ config = NV_CTRL_FRAMELOCK_DISPLAY_CONFIG_DISABLED;
+ }
+ target_type = NV_CTRL_TARGET_TYPE_DISPLAY;
+ target_id = NvCtrlGetTargetId(data->handle);
- case ENTRY_DATA_DISPLAY:
- /* Nothing to save */
+ __ADD_ATTR(NV_CTRL_FRAMELOCK_DISPLAY_CONFIG, config);
+ }
break;
default:
@@ -5816,17 +5892,13 @@ static void add_entry_to_parsed_attributes(nvListEntryPtr entry,
static void add_entries_to_parsed_attributes(nvListEntryPtr entry,
ParsedAttribute *head)
{
- if (!entry) return;
-
- /* Add GPU entries to parsed attributes list */
- if (entry->data_type == ENTRY_DATA_GPU) {
- add_entry_to_parsed_attributes(entry, head);
+ if (!entry) {
+ return;
}
-
- /* add children */
- add_entries_to_parsed_attributes(entry->children, head);
- /* add siblings */
+ add_entry_to_parsed_attributes(entry, head);
+
+ add_entries_to_parsed_attributes(entry->children, head);
add_entries_to_parsed_attributes(entry->next_sibling, head);
}
@@ -5837,8 +5909,9 @@ static void add_entries_to_parsed_attributes(nvListEntryPtr entry,
* Add to the ParsedAttribute list any attributes that we want saved
* in the config file.
*
- * This includes all the clients/server bitmasks for all GPUs and
- * the house sync settings of the selected master frame lock device.
+ * This includes all the clients/server display configurations for all
+ * GPUs and the house sync settings of the selected master frame lock
+ * device.
*
*/
void ctk_framelock_config_file_attributes(GtkWidget *w,
diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c
index 2f9d7d2..e681c86 100644
--- a/src/gtk+-2.x/ctkgpu.c
+++ b/src/gtk+-2.x/ctkgpu.c
@@ -22,7 +22,9 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include "msg.h"
#include "parse.h"
#include "ctkbanner.h"
@@ -35,11 +37,17 @@
static void probe_displays_received(GtkObject *object, gpointer arg1,
gpointer user_data);
-static gboolean update_gpu_memory_used(gpointer);
+static gboolean update_gpu_usage(gpointer);
#define ARRAY_ELEMENTS 16
#define DEFAULT_UPDATE_GPU_INFO_TIME_INTERVAL 3000
+typedef struct {
+ gint graphics;
+ gint video;
+ gint pcie;
+} utilizationEntry, * utilizationEntryPtr;
+
GType ctk_gpu_get_type(
void
)
@@ -133,44 +141,43 @@ void get_bus_type_str(NvCtrlAttributeHandle *handle,
}
}
-void get_bus_id_str(NvCtrlAttributeHandle *handle,
- gchar **pci_bus_id)
+gchar *get_bus_id_str(NvCtrlAttributeHandle *handle)
{
int ret;
int pci_domain, pci_bus, pci_device, pci_func;
gchar *bus_id;
- const gchar *__pci_bus_id_unknown = "?@?:?:?";
/* NV_CTRL_PCI_DOMAIN & NV_CTRL_PCI_BUS &
* NV_CTRL_PCI_DEVICE & NV__CTRL_PCI_FUNCTION
*/
- bus_id = NULL;
ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_DOMAIN, &pci_domain);
- if (ret != NvCtrlSuccess) goto bus_id_fallback;
+ if (ret != NvCtrlSuccess) {
+ return NULL;
+ }
ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_BUS, &pci_bus);
- if (ret != NvCtrlSuccess) goto bus_id_fallback;
+ if (ret != NvCtrlSuccess) {
+ return NULL;
+ }
ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_DEVICE, &pci_device);
- if (ret != NvCtrlSuccess) goto bus_id_fallback;
+ if (ret != NvCtrlSuccess) {
+ return NULL;
+ }
ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_FUNCTION, &pci_func);
- if (ret != NvCtrlSuccess) goto bus_id_fallback;
-
- bus_id = malloc(32);
- if (bus_id) {
- xconfigFormatPciBusString(bus_id, 32, pci_domain, pci_bus,
- pci_device, pci_func);
+ if (ret != NvCtrlSuccess) {
+ return NULL;
}
- bus_id_fallback:
-
+ bus_id = g_malloc(32);
if (!bus_id) {
- bus_id = g_strdup(__pci_bus_id_unknown);
+ return NULL;
}
-
- *pci_bus_id = bus_id;
+ xconfigFormatPciBusString(bus_id, 32, pci_domain, pci_bus,
+ pci_device, pci_func);
+ return bus_id;
}
@@ -249,20 +256,17 @@ GtkWidget* ctk_gpu_new(
}
/* Get Bus related information */
-
- get_bus_id_str(handle, &pci_bus_id);
-
+
+ pci_bus_id = get_bus_id_str(handle);
+
/* NV_CTRL_PCI_ID */
- pci_device_id[ARRAY_ELEMENTS-1] = '\0';
- pci_vendor_id[ARRAY_ELEMENTS-1] = '\0';
+ memset(&pci_device_id, 0, sizeof(pci_device_id));
+ memset(&pci_vendor_id, 0, sizeof(pci_vendor_id));
ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_ID, &pci_id);
- if (ret != NvCtrlSuccess) {
- snprintf(pci_device_id, ARRAY_ELEMENTS, "Unknown");
- snprintf(pci_vendor_id, ARRAY_ELEMENTS, "Unknown");
- } else {
+ if (ret == NvCtrlSuccess) {
snprintf(pci_device_id, ARRAY_ELEMENTS, "0x%04x", (pci_id & 0xFFFF));
snprintf(pci_vendor_id, ARRAY_ELEMENTS, "0x%04x", (pci_id >> 16));
}
@@ -382,6 +386,7 @@ GtkWidget* ctk_gpu_new(
ctk_gpu->handle = handle;
ctk_gpu->gpu_cores = (gpu_cores != NULL) ? 1 : 0;
+ ctk_gpu->gpu_uuid = (gpu_uuid != NULL) ? 1 : 0;
ctk_gpu->memory_interface = (memory_interface != NULL) ? 1 : 0;
ctk_gpu->ctk_config = ctk_config;
ctk_gpu->ctk_event = ctk_event;
@@ -438,18 +443,22 @@ GtkWidget* ctk_gpu_new(
add_table_row(table, row++,
0, 0.5, "Graphics Processor:",
0, 0.5, product_name);
- add_table_row(table, row++,
- 0, 0.5, "GPU UUID:",
- 0, 0.5, gpu_uuid);
+ if ( ctk_gpu->gpu_uuid ) {
+ add_table_row(table, row++,
+ 0, 0.5, "GPU UUID:",
+ 0, 0.5, gpu_uuid);
+ }
if ( ctk_gpu->gpu_cores ) {
gtk_table_resize(GTK_TABLE(table), ++total_rows, 2);
add_table_row(table, row++,
0, 0.5, "CUDA Cores:",
0, 0.5, gpu_cores);
}
- add_table_row(table, row++,
- 0, 0.5, "VBIOS Version:",
- 0, 0.5, vbios_version);
+ if ( vbios_version ) {
+ add_table_row(table, row++,
+ 0, 0.5, "VBIOS Version:",
+ 0, 0.5, vbios_version);
+ }
add_table_row(table, row++,
0, 0.5, "Total Memory:",
0, 0.5, video_ram);
@@ -460,30 +469,45 @@ GtkWidget* ctk_gpu_new(
add_table_row(table, row++,
0, 0.5, "Used Dedicated Memory:",
0, 0.5, NULL);
- update_gpu_memory_used(ctk_gpu);
if ( ctk_gpu->memory_interface ) {
gtk_table_resize(GTK_TABLE(table), ++total_rows, 2);
add_table_row(table, row++,
0, 0.5, "Memory Interface:",
0, 0.5, memory_interface);
}
+ ctk_gpu->gpu_utilization_label =
+ add_table_row(table, row++,
+ 0, 0.5, "GPU Utilization:",
+ 0, 0.5, NULL);
+ ctk_gpu->video_utilization_label =
+ add_table_row(table, row++,
+ 0, 0.5, "Video Engine Utilization:",
+ 0, 0.5, NULL);
/* spacing */
row += 3;
add_table_row(table, row++,
0, 0.5, "Bus Type:",
0, 0.5, bus);
- add_table_row(table, row++,
- 0, 0.5, "Bus ID:",
- 0, 0.5, pci_bus_id);
- add_table_row(table, row++,
- 0, 0.5, "PCI Device ID:",
- 0, 0.5, pci_device_id);
- add_table_row(table, row++,
- 0, 0.5, "PCI Vendor ID:",
- 0, 0.5, pci_vendor_id);
- add_table_row(table, row++,
- 0, 0.5, "IRQ:",
- 0, 0.5, irq);
+ if ( pci_bus_id ) {
+ add_table_row(table, row++,
+ 0, 0.5, "Bus ID:",
+ 0, 0.5, pci_bus_id);
+ }
+ if ( pci_device_id[0] ) {
+ add_table_row(table, row++,
+ 0, 0.5, "PCI Device ID:",
+ 0, 0.5, pci_device_id);
+ }
+ if (pci_vendor_id[0] ) {
+ add_table_row(table, row++,
+ 0, 0.5, "PCI Vendor ID:",
+ 0, 0.5, pci_vendor_id);
+ }
+ if ( irq ) {
+ add_table_row(table, row++,
+ 0, 0.5, "IRQ:",
+ 0, 0.5, irq);
+ }
if (ctk_gpu->pcie_gen_queriable) {
/* spacing */
row += 3;
@@ -496,12 +520,18 @@ GtkWidget* ctk_gpu_new(
add_table_row(table, row++,
0, 0.5, "Maximum PCIe Link Speed:",
0, 0.5, link_speed_str);
+ ctk_gpu->pcie_utilization_label =
+ add_table_row(table, row++,
+ 0, 0.5, "PCIe Bandwidth Utilization:",
+ 0, 0.5, NULL);
+
g_free(link_speed_str);
g_free(link_width_str);
g_free(pcie_gen_str);
row++;
}
+ update_gpu_usage(ctk_gpu);
/* spacing */
row += 3;
add_table_row(table, row++,
@@ -543,7 +573,7 @@ GtkWidget* ctk_gpu_new(
ctk_config_add_timer(ctk_gpu->ctk_config,
DEFAULT_UPDATE_GPU_INFO_TIME_INTERVAL,
tmp_str,
- (GSourceFunc) update_gpu_memory_used,
+ (GSourceFunc) update_gpu_usage,
(gpointer) ctk_gpu);
g_free(tmp_str);
@@ -571,6 +601,12 @@ GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table,
ctk_help_heading(b, &i, "Graphics Processor");
ctk_help_para(b, &i, "This is the product name of the GPU.");
+ if (ctk_gpu->gpu_uuid) {
+ ctk_help_heading(b, &i, "GPU UUID");
+ ctk_help_para(b, &i, "This is the global unique identifier "
+ "of the GPU.");
+ }
+
if (ctk_gpu->gpu_cores) {
ctk_help_heading(b, &i, "CUDA Cores");
ctk_help_para(b, &i, "This is the number of CUDA cores supported by "
@@ -603,6 +639,12 @@ GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table,
"memory interface.");
}
+ ctk_help_heading(b, &i, "GPU Utilization");
+ ctk_help_para(b, &i, "This is the percentage usage of graphics engine.");
+
+ ctk_help_heading(b, &i, "Video Engine Utilization");
+ ctk_help_para(b, &i, "This is the percentage usage of video engine");
+
ctk_help_heading(b, &i, "Bus Type");
ctk_help_para(b, &i, "This is the bus type which is "
"used to connect the NVIDIA GPU to the rest of "
@@ -646,7 +688,12 @@ GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table,
"This is expressed in gigatransfers per second "
"(GT/s). The link may be dynamically trained to a "
"slower speed, based on the GPU's utilization and "
- "performance settings.");
+ "performance settings.");
+
+ ctk_help_heading(b, &i, "PCIe Bandwidth Utilization");
+ ctk_help_para(b, &i, "This is the percentage usage of "
+ "PCIe bandwidth.");
+
}
ctk_help_heading(b, &i, "X Screens");
@@ -676,13 +723,35 @@ static void probe_displays_received(GtkObject *object, gpointer arg1,
g_free(str);
}
-static gboolean update_gpu_memory_used(gpointer user_data)
+
+
+static void apply_gpu_utilization_token(char *token, char *value, void *data)
+{
+ utilizationEntryPtr pEntry = (utilizationEntryPtr) data;
+
+ if (!strcasecmp("graphics", token)) {
+ pEntry->graphics = atoi(value);
+ } else if (!strcasecmp("video", token)) {
+ pEntry->video = atoi(value);
+ } else if (!strcasecmp("pcie", token)) {
+ pEntry->pcie = atoi(value);
+ } else {
+ nv_warning_msg("Unknown GPU utilization token value pair: %s=%s",
+ token, value);
+ }
+}
+
+
+
+static gboolean update_gpu_usage(gpointer user_data)
{
CtkGpu *ctk_gpu;
gchar *memory_text;
+ gchar *utilization_text = NULL;
ReturnStatus ret;
- int value;
- static int num_failures = 0;
+ gchar *utilizationStr = NULL;
+ gint value = 0;
+ utilizationEntry entry;
ctk_gpu = CTK_GPU(user_data);
@@ -691,9 +760,7 @@ static gboolean update_gpu_memory_used(gpointer user_data)
&value);
if (ret != NvCtrlSuccess || value > ctk_gpu->gpu_memory || value < 0) {
gtk_label_set_text(GTK_LABEL(ctk_gpu->gpu_memory_used_label), "Unknown");
- if(num_failures++ >= 10) {
- return FALSE;
- }
+ return FALSE;
} else {
if (ctk_gpu->gpu_memory > 0) {
memory_text = g_strdup_printf("%d MB (%.0f%%)",
@@ -708,6 +775,47 @@ static gboolean update_gpu_memory_used(gpointer user_data)
g_free(memory_text);
}
+ /* GPU utilization */
+ ret = NvCtrlGetStringAttribute(ctk_gpu->handle,
+ NV_CTRL_STRING_GPU_UTILIZATION,
+ &utilizationStr);
+ if (ret != NvCtrlSuccess) {
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->gpu_utilization_label), "Unknown");
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->video_utilization_label),
+ "Unknown");
+ if (ctk_gpu->pcie_utilization_label) {
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->pcie_utilization_label),
+ "Unknown");
+ }
+ return FALSE;
+ } else {
+ memset(&entry, -1, sizeof(&entry));
+ parse_token_value_pairs(utilizationStr, apply_gpu_utilization_token,
+ &entry);
+ if (entry.graphics != -1) {
+ utilization_text = g_strdup_printf("%d %%",
+ entry.graphics);
+
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->gpu_utilization_label),
+ utilization_text);
+ }
+ if (entry.video != -1) {
+ utilization_text = g_strdup_printf("%d %%",
+ entry.video);
+
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->video_utilization_label),
+ utilization_text);
+ }
+ if ((entry.pcie != -1) &&
+ (ctk_gpu->pcie_utilization_label)) {
+ utilization_text = g_strdup_printf("%d %%",
+ entry.pcie);
+
+ gtk_label_set_text(GTK_LABEL(ctk_gpu->pcie_utilization_label),
+ utilization_text);
+ }
+ g_free(utilization_text);
+ }
return TRUE;
}
@@ -715,10 +823,14 @@ void ctk_gpu_page_select(GtkWidget *widget)
{
CtkGpu *ctk_gpu = CTK_GPU(widget);
+ /* Update GPU usage */
+
+ update_gpu_usage(ctk_gpu);
+
/* Start the gpu timer */
ctk_config_start_timer(ctk_gpu->ctk_config,
- (GSourceFunc) update_gpu_memory_used,
+ (GSourceFunc) update_gpu_usage,
(gpointer) ctk_gpu);
}
@@ -729,7 +841,7 @@ void ctk_gpu_page_unselect(GtkWidget *widget)
/* Stop the gpu timer */
ctk_config_stop_timer(ctk_gpu->ctk_config,
- (GSourceFunc) update_gpu_memory_used,
+ (GSourceFunc) update_gpu_usage,
(gpointer) ctk_gpu);
}
diff --git a/src/gtk+-2.x/ctkgpu.h b/src/gtk+-2.x/ctkgpu.h
index eb95a0d..38d96e0 100644
--- a/src/gtk+-2.x/ctkgpu.h
+++ b/src/gtk+-2.x/ctkgpu.h
@@ -61,8 +61,13 @@ struct _CtkGpu
GtkWidget *displays;
GtkWidget *gpu_memory_used_label;
+ GtkWidget *gpu_utilization_label;
+ GtkWidget *video_utilization_label;
+ GtkWidget *pcie_utilization_label;
gint gpu_memory;
+ gint gpu_utilization;
gint gpu_cores;
+ gint gpu_uuid;
gint memory_interface;
gboolean pcie_gen_queriable;
};
@@ -80,8 +85,7 @@ GtkWidget* ctk_gpu_new (NvCtrlAttributeHandle *handle,
void get_bus_type_str(NvCtrlAttributeHandle *handle,
gchar **bus);
-void get_bus_id_str(NvCtrlAttributeHandle *handle,
- gchar **pci_bus_id);
+gchar *get_bus_id_str(NvCtrlAttributeHandle *handle);
GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *,
CtkGpu *);
diff --git a/src/gtk+-2.x/ctkgvi.c b/src/gtk+-2.x/ctkgvi.c
index d0fd5db..f44a51c 100644
--- a/src/gtk+-2.x/ctkgvi.c
+++ b/src/gtk+-2.x/ctkgvi.c
@@ -538,7 +538,7 @@ GtkWidget* ctk_gvi_new(NvCtrlAttributeHandle *handle,
/* Get Bus related information */
get_bus_type_str(handle, &bus);
- get_bus_id_str(handle, &pci_bus_id);
+ pci_bus_id = get_bus_id_str(handle);
/* NV_CTRL_IRQ */
diff --git a/src/gtk+-2.x/ctklicense.c b/src/gtk+-2.x/ctklicense.c
index a28edf3..233cdcd 100644
--- a/src/gtk+-2.x/ctklicense.c
+++ b/src/gtk+-2.x/ctklicense.c
@@ -29,11 +29,6 @@
#include "ctkhelp.h"
#include "ctkbanner.h"
-static const char * __enable_confirm_msg =
-"To use the features on the %s panel you\n"
-"must agree to the terms of the preceding license agreement.\n"
-"Do you accept this agreement?";
-
static const char * __license_pre_msg =
"Please read and accept the following license agreement:";
@@ -284,7 +279,10 @@ GtkWidget* ctk_license_dialog_new(GtkWidget *parent, gchar *panel_name)
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(ctk_license_dialog->dialog)->vbox),
hbox, TRUE, TRUE, 10);
hbox = gtk_hbox_new(FALSE, 10);
- enable_message = g_strdup_printf(__enable_confirm_msg, panel_name);
+ enable_message = g_strdup_printf("To use the features on the %s panel you\n"
+ "must agree to the terms of the preceding "
+ "license agreement.\nDo you accept this "
+ "agreement?", panel_name);
label = gtk_label_new(enable_message);
g_free(enable_message);
diff --git a/src/gtk+-2.x/ctkpowermizer.c b/src/gtk+-2.x/ctkpowermizer.c
index 9c326e1..3bdf176 100644
--- a/src/gtk+-2.x/ctkpowermizer.c
+++ b/src/gtk+-2.x/ctkpowermizer.c
@@ -38,6 +38,8 @@
static gboolean update_powermizer_info(gpointer);
static void update_powermizer_menu_info(CtkPowermizer *ctk_powermizer);
+static void set_powermizer_menu_label_txt(CtkPowermizer *ctk_powermizer,
+ gint powerMizerMode);
static void powermizer_menu_changed(GtkWidget*, gpointer);
static void update_powermizer_menu_event(GtkObject *object,
gpointer arg1,
@@ -70,8 +72,8 @@ static const char *__performance_level_help =
static const char *__gpu_clock_freq_help =
"This indicates the current Graphics Clock frequency.";
-static const char *__memory_clock_freq_help =
-"This indicates the current Memory Clock frequency.";
+static const char *__memory_transfer_rate_freq_help =
+"This indicates the current Memory transfer rate.";
static const char *__processor_clock_freq_help =
"This indicates the current Processor Clock frequency.";
@@ -144,12 +146,12 @@ GType ctk_powermizer_get_type(void)
typedef struct {
gint perf_level;
gint nvclock;
- gint memclock;
gint processorclock;
gint nvclockmin;
gint nvclockmax;
- gint memclockmin;
- gint memclockmax;
+ gint memtransferrate;
+ gint memtransferratemin;
+ gint memtransferratemax;
gint processorclockmin;
gint processorclockmax;
} perfModeEntry, * perfModeEntryPtr;
@@ -167,12 +169,12 @@ static void apply_perf_mode_token(char *token, char *value, void *data)
pEntry->nvclockmin = atoi(value);
} else if (!strcasecmp("nvclockmax", token)) {
pEntry->nvclockmax = atoi(value);
- } else if (!strcasecmp("memclock", token)) {
- pEntry->memclock = atoi(value);
- } else if (!strcasecmp("memclockmin", token)) {
- pEntry->memclockmin = atoi(value);
- } else if (!strcasecmp("memclockmax", token)) {
- pEntry->memclockmax = atoi(value);
+ } else if (!strcasecmp("memtransferrate", token)) {
+ pEntry->memtransferrate = atoi(value);
+ } else if (!strcasecmp("memtransferratemin", token)) {
+ pEntry->memtransferratemin = atoi(value);
+ } else if (!strcasecmp("memtransferratemax", token)) {
+ pEntry->memtransferratemax = atoi(value);
} else if (!strcasecmp("processorclock", token)) {
pEntry->processorclock = atoi(value);
} else if (!strcasecmp("processorclockmin", token)) {
@@ -197,6 +199,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
char tmp_str[24];
gint ret;
gint row_idx = 0; /* Where to insert into the perf mode table */
+ gint col_idx = 0; /* Column index adjustment factor */
gboolean active;
GtkWidget *vsep;
perfModeEntryPtr pEntry = NULL;
@@ -237,14 +240,14 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
/* Only add complete perf mode entries */
if ((pEntry[index].perf_level != -1) &&
- (pEntry[index].nvclockmax != -1) &&
- (pEntry[index].memclockmax != -1)) {
+ (pEntry[index].nvclockmax != -1)) {
/* Set hasDecoupledClocks flag to decide new/old clock
* interface to show.
*/
if (!ctk_powermizer->hasDecoupledClock &&
((pEntry[index].nvclockmax != pEntry[index].nvclockmin) ||
- (pEntry[index].memclockmax != pEntry[index].memclockmin) ||
+ (pEntry[index].memtransferratemax !=
+ pEntry[index].memtransferratemin) ||
(pEntry[index].processorclockmax !=
pEntry[index].processorclockmin))) {
ctk_powermizer->hasDecoupledClock = TRUE;
@@ -268,6 +271,7 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
if (ctk_powermizer->hasDecoupledClock) {
table = gtk_table_new(2, 15, FALSE);
row_idx = row_idx + 3;
+ col_idx = 0;
gtk_table_set_row_spacings(GTK_TABLE(table), 3);
gtk_table_set_col_spacings(GTK_TABLE(table), 15);
gtk_container_set_border_width(GTK_CONTAINER(table), 5);
@@ -287,75 +291,71 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0);
}
- if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) {
+ if (ctk_powermizer->gpu_clock) {
/* Graphics clock */
label = gtk_label_new("Graphics Clock");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 5, 0, 1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- label = gtk_label_new("Current");
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 3, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+4, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Min");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 3, 4, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Max");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 4, 5, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+3, col_idx+4, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
/* Vertical separator */
vsep = gtk_vseparator_new();
- gtk_table_attach(GTK_TABLE(table), vsep, 5, 6, 0, row_idx,
+ gtk_table_attach(GTK_TABLE(table), vsep, col_idx+4, col_idx+5, 0,
+ row_idx,
GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0);
-
- /* Memory clock */
- label = gtk_label_new("Memory Clock");
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 6, 9, 0, 1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- label = gtk_label_new("Current");
+ col_idx += 4;
+ }
+
+ /* Memory transfer rate */
+ if (ctk_powermizer->memory_transfer_rate &&
+ pEntry[i].memtransferrate != -1) {
+ label = gtk_label_new("Memory Transfer Rate");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 6, 7, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+3, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Min");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 7, 8, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Max");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 8, 9, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
-
+
/* Vertical separator */
vsep = gtk_vseparator_new();
- gtk_table_attach(GTK_TABLE(table), vsep, 9, 10, 0, row_idx,
+ gtk_table_attach(GTK_TABLE(table), vsep, col_idx+3, col_idx+4,
+ 0, row_idx,
GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0);
+ col_idx += 4;
}
if (ctk_powermizer->processor_clock) {
/* Processor clock */
label = gtk_label_new("Processor Clock");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 10, 11, 0, 1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- label = gtk_label_new("Current");
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 11, 12, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+3, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Min");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 12, 13, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
label = gtk_label_new("Max");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 13, 14, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3, 1, 2,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
/* Vertical separator */
vsep = gtk_vseparator_new();
- gtk_table_attach(GTK_TABLE(table), vsep, 14, 15, 0, row_idx,
+ gtk_table_attach(GTK_TABLE(table), vsep, col_idx+3, col_idx+4,
+ 0, row_idx,
GTK_FILL, GTK_FILL | GTK_EXPAND, 0, 0);
}
} else {
@@ -375,23 +375,27 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
}
- if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) {
+ if (ctk_powermizer->gpu_clock) {
label = gtk_label_new("Graphics Clock");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx++;
+ }
-
- label = gtk_label_new("Memory Clock");
+ if (pEntry[i].memtransferrate != -1 &&
+ ctk_powermizer->memory_transfer_rate) {
+ label = gtk_label_new("Memory Transfer Rate");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 3, 0, 1,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx++;
}
if (ctk_powermizer->processor_clock) {
label = gtk_label_new("Processor Clock");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
}
}
@@ -400,11 +404,11 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
row_idx = 0; //reset value used to calculate vseparator.
row_idx = 3;
for (i = 0; i < index; i++) {
+ col_idx = 0;
/* Only add complete perf mode entries */
if (ctk_powermizer->hasDecoupledClock &&
(pEntry[i].perf_level != -1) &&
- (pEntry[i].nvclockmax != -1) &&
- (pEntry[i].memclockmax != -1)) {
+ (pEntry[i].nvclockmax != -1)) {
active = (pEntry[i].perf_level == perf_level);
@@ -420,85 +424,63 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
gtk_table_attach(GTK_TABLE(table), label, 0, 1,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx +=1;
}
- if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) {
- if (active) {
- g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->nvclock);
- label = gtk_label_new(tmp_str);
- gtk_widget_set_sensitive(label, active);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 3,
- row_idx, row_idx+1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- }
+ if (ctk_powermizer->gpu_clock) {
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmin);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 3, 4,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclockmax);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 4, 5,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
-
- if (active) {
- g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->memclock);
- label = gtk_label_new(tmp_str);
- gtk_widget_set_sensitive(label, active);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 6, 7,
- row_idx, row_idx+1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- }
- g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmin);
+ col_idx +=3;
+ }
+ if (ctk_powermizer->memory_transfer_rate &&
+ pEntry[i].memtransferrate != -1) {
+ g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memtransferratemin);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 7, 8,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclockmax);
+ g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memtransferratemax);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 8, 9,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx +=3;
}
if (ctk_powermizer->processor_clock) {
- if (active) {
- g_snprintf(tmp_str, 24, "%d MHz", ctk_powermizer->processorclock);
- label = gtk_label_new(tmp_str);
- gtk_widget_set_sensitive(label, active);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 11, 12, row_idx, row_idx+1,
- GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
- }
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmin);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 12, 13,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+1, col_idx+2,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclockmax);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 13, 14,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx+2, col_idx+3,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
}
row_idx++;
} else if ((pEntry[i].perf_level != -1) &&
- (pEntry[i].nvclock != -1) &&
- (pEntry[i].memclock != -1)) {
+ (pEntry[i].nvclock != -1)) {
active = (pEntry[i].perf_level == perf_level);
@@ -514,39 +496,46 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
gtk_table_attach(GTK_TABLE(table), label, 0, 1,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx++;
}
- if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) {
+ if (ctk_powermizer->gpu_clock) {
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].nvclock);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 1, 2,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx, col_idx+1,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx++;
+ }
+ if (ctk_powermizer->memory_transfer_rate &&
+ pEntry[i].memtransferrate != -1) {
- g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memclock);
+ g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].memtransferrate);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 3,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx, col_idx+1,
row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ col_idx++;
}
if (ctk_powermizer->processor_clock) {
g_snprintf(tmp_str, 24, "%d MHz", pEntry[i].processorclock);
label = gtk_label_new(tmp_str);
gtk_widget_set_sensitive(label, active);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1,
+ gtk_table_attach(GTK_TABLE(table), label, col_idx, col_idx+1,
+ row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
}
row_idx++;
} else {
nv_warning_msg("Incomplete Perf Mode (perf=%d, nvclock=%d,"
- " memclock=%d)",
+ " memtransferrate=%d)",
pEntry[i].perf_level, pEntry[i].nvclock,
- pEntry[i].memclock);
+ pEntry[i].memtransferrate);
}
}
@@ -562,12 +551,14 @@ static void update_perf_mode_table(CtkPowermizer *ctk_powermizer,
static gboolean update_powermizer_info(gpointer user_data)
{
gint power_source, adaptive_clock, perf_level;
- gint clockret, gpu_clock, memory_clock, processor_clock;
+ gint gpu_clock, memory_transfer_rate;
CtkPowermizer *ctk_powermizer;
NvCtrlAttributeHandle *handle;
gint ret;
gchar *s;
+ char *clock_string = NULL;
+ perfModeEntry pEntry;
ctk_powermizer = CTK_POWERMIZER(user_data);
handle = ctk_powermizer->attribute_handle;
@@ -589,36 +580,44 @@ static gboolean update_powermizer_info(gpointer user_data)
gtk_label_set_text(GTK_LABEL(ctk_powermizer->adaptive_clock_status), s);
g_free(s);
}
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_CURRENT_CLOCK_FREQS,
- &clockret);
- if (ret == NvCtrlSuccess && ctk_powermizer->gpu_clock &&
- ctk_powermizer->memory_clock) {
- memory_clock = clockret & 0x0000FFFF;
- gpu_clock = (clockret >> 16);
+ /* Get the current values of clocks */
- ctk_powermizer->nvclock = gpu_clock;
- ctk_powermizer->memclock = memory_clock;
+ ret = NvCtrlGetStringAttribute(ctk_powermizer->attribute_handle,
+ NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS,
+ &clock_string);
- s = g_strdup_printf("%d Mhz", gpu_clock);
- gtk_label_set_text(GTK_LABEL(ctk_powermizer->gpu_clock), s);
- g_free(s);
+ if (ret == NvCtrlSuccess && ctk_powermizer->gpu_clock) {
- s = g_strdup_printf("%d Mhz", memory_clock);
- gtk_label_set_text(GTK_LABEL(ctk_powermizer->memory_clock), s);
- g_free(s);
- }
+ /* Invalidate the entries */
+ memset(&pEntry, -1, sizeof(pEntry));
- ret = NvCtrlGetAttribute(handle,
- NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS,
- &processor_clock);
- if (ret == NvCtrlSuccess && ctk_powermizer->processor_clock) {
- ctk_powermizer->processorclock = processor_clock;
- s = g_strdup_printf("%d Mhz", processor_clock);
- gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s);
- g_free(s);
+ parse_token_value_pairs(clock_string, apply_perf_mode_token,
+ &pEntry);
+
+ if (pEntry.nvclock != -1) {
+ gpu_clock = pEntry.nvclock;
+ s = g_strdup_printf("%d Mhz", gpu_clock);
+ gtk_label_set_text(GTK_LABEL(ctk_powermizer->gpu_clock), s);
+ g_free(s);
+
+ }
+
+ if (ctk_powermizer->memory_transfer_rate &&
+ pEntry.memtransferrate != -1) {
+ memory_transfer_rate = pEntry.memtransferrate;
+ s = g_strdup_printf("%d Mhz", memory_transfer_rate);
+ gtk_label_set_text(GTK_LABEL(ctk_powermizer->memory_transfer_rate), s);
+ g_free(s);
+ }
+
+ if (ctk_powermizer->processor_clock && pEntry.processorclock != -1) {
+ s = g_strdup_printf("%d Mhz", pEntry.processorclock);
+ gtk_label_set_text(GTK_LABEL(ctk_powermizer->processor_clock), s);
+ g_free(s);
+ }
}
+ XFree(clock_string);
ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_POWER_SOURCE, &power_source);
if (ret == NvCtrlSuccess && ctk_powermizer->power_source) {
@@ -659,8 +658,7 @@ static gboolean update_powermizer_info(gpointer user_data)
g_free(s);
}
- if (ctk_powermizer->performance_level && ctk_powermizer->gpu_clock &&
- ctk_powermizer->memory_clock) {
+ if (ctk_powermizer->performance_level && ctk_powermizer->gpu_clock) {
/* update the perf table */
update_perf_mode_table(ctk_powermizer, perf_level);
@@ -758,14 +756,17 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
gint row = 0;
gchar *s = NULL;
gint tmp;
+ gboolean gpu_clock_available = FALSE;
+ gboolean mem_transfer_rate_available = FALSE;
gboolean processor_clock_available = FALSE;
gboolean power_source_available = FALSE;
gboolean perf_level_available = FALSE;
gboolean adaptive_clock_state_available = FALSE;
- gboolean clock_freqs_available = FALSE;
gboolean cuda_dp_ui = FALSE;
gboolean pcie_gen_queriable = FALSE;
NVCTRLAttributeValidValuesRec valid_modes;
+ char *clock_string = NULL;
+ perfModeEntry pEntry;
/* make sure we have a handle */
@@ -790,17 +791,31 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
adaptive_clock_state_available = TRUE;
}
- ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_CURRENT_CLOCK_FREQS,
- &val);
- if (ret == NvCtrlSuccess) {
- clock_freqs_available = TRUE;
- }
+ /* Check if reporting value of the clock supported */
+
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_GPU_CURRENT_CLOCK_FREQS,
+ &clock_string);
- ret = NvCtrlGetAttribute(handle, NV_CTRL_GPU_CURRENT_PROCESSOR_CLOCK_FREQS,
- &val);
if (ret == NvCtrlSuccess) {
- processor_clock_available = TRUE;
+
+ /* Invalidate the entries */
+ memset(&pEntry, -1, sizeof(pEntry));
+
+ parse_token_value_pairs(clock_string, apply_perf_mode_token,
+ &pEntry);
+
+ if (pEntry.nvclock != -1) {
+ gpu_clock_available = TRUE;
+ }
+ if (pEntry.memtransferrate != -1) {
+ mem_transfer_rate_available = TRUE;
+ }
+ if (pEntry.processorclock != -1) {
+ processor_clock_available = TRUE;
+ }
}
+ XFree(clock_string);
/* NV_CTRL_GPU_PCIE_GENERATION */
@@ -811,7 +826,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
/* return early if query to attributes fail */
if (!power_source_available && !perf_level_available &&
- !adaptive_clock_state_available && clock_freqs_available &&
+ !adaptive_clock_state_available && !gpu_clock_available &&
!processor_clock_available && !pcie_gen_queriable) {
return NULL;
}
@@ -871,7 +886,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
/* Clock Frequencies */
- if (clock_freqs_available) {
+ if (gpu_clock_available) {
/* spacing */
row += 3;
ctk_powermizer->gpu_clock =
@@ -885,21 +900,23 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
0.0,
0.5,
NULL);
-
- ctk_powermizer->memory_clock =
+ } else {
+ ctk_powermizer->gpu_clock = NULL;
+ }
+ if (mem_transfer_rate_available) {
+ ctk_powermizer->memory_transfer_rate =
add_table_row_with_help_text(table, ctk_config,
- __memory_clock_freq_help,
+ __memory_transfer_rate_freq_help,
row++, //row
0, // column
0.0f,
0.5,
- "Memory Clock:",
+ "Memory Transfer Rate:",
0.0,
0.5,
NULL);
} else {
- ctk_powermizer->gpu_clock = NULL;
- ctk_powermizer->memory_clock = NULL;
+ ctk_powermizer->memory_transfer_rate = NULL;
}
/* Processor clock */
if (processor_clock_available) {
@@ -992,7 +1009,7 @@ GtkWidget* ctk_powermizer_new(NvCtrlAttributeHandle *handle,
/* Available Performance Level Title */
- if (perf_level_available && clock_freqs_available) {
+ if (perf_level_available && gpu_clock_available) {
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
@@ -1264,13 +1281,35 @@ static void update_powermizer_menu_event(GtkObject *object,
+static void set_powermizer_menu_label_txt(CtkPowermizer *ctk_powermizer,
+ gint powerMizerMode)
+{
+ gint actualPowerMizerMode;
+ gchar *label;
+
+ if (powerMizerMode == NV_CTRL_GPU_POWER_MIZER_MODE_AUTO) {
+ actualPowerMizerMode = ctk_powermizer->powermizer_default_mode;
+ } else {
+ actualPowerMizerMode = powerMizerMode;
+ }
+
+ label = get_powermizer_menu_label(actualPowerMizerMode);
+ gtk_label_set_text(GTK_LABEL(ctk_powermizer->powermizer_txt), label);
+ g_free(label);
+}
+
+
+
static void update_powermizer_menu_info(CtkPowermizer *ctk_powermizer)
{
- gint powerMizerMode, defaultPowerMizerMode, actualPowerMizerMode;
- gchar* label;
+ gint powerMizerMode, defaultPowerMizerMode;
ReturnStatus ret1, ret2;
CtkDropDownMenu *menu;
+ if (!ctk_powermizer->powermizer_menu) {
+ return;
+ }
+
menu = CTK_DROP_DOWN_MENU(ctk_powermizer->powermizer_menu);
ret1 = NvCtrlGetAttribute(ctk_powermizer->attribute_handle,
@@ -1288,17 +1327,11 @@ static void update_powermizer_menu_info(CtkPowermizer *ctk_powermizer)
G_CALLBACK(powermizer_menu_changed),
(gpointer) ctk_powermizer);
- if (powerMizerMode == NV_CTRL_GPU_POWER_MIZER_MODE_AUTO) {
- actualPowerMizerMode = defaultPowerMizerMode;
- } else {
- actualPowerMizerMode = powerMizerMode;
- }
+ ctk_powermizer->powermizer_default_mode = defaultPowerMizerMode;
ctk_drop_down_menu_set_current_value(menu, powerMizerMode);
- label = get_powermizer_menu_label(actualPowerMizerMode);
- gtk_label_set_text(GTK_LABEL(ctk_powermizer->powermizer_txt), label);
- g_free(label);
+ set_powermizer_menu_label_txt(ctk_powermizer, powerMizerMode);
g_signal_handlers_unblock_by_func(G_OBJECT(ctk_powermizer->powermizer_menu),
G_CALLBACK(powermizer_menu_changed),
@@ -1332,7 +1365,7 @@ static void powermizer_menu_changed(GtkWidget *widget,
return;
}
- update_powermizer_menu_info(user_data);
+ set_powermizer_menu_label_txt(ctk_powermizer, powerMizerMode);
post_powermizer_menu_update(ctk_powermizer);
}
@@ -1519,14 +1552,17 @@ GtkTextBuffer *ctk_powermizer_create_help(GtkTextTagTable *table,
ctk_help_para(b, &i, "%s", __adaptive_clock_help);
}
- if (ctk_powermizer->gpu_clock && ctk_powermizer->memory_clock) {
+ if (ctk_powermizer->gpu_clock) {
ctk_help_heading(b, &i, "Clock Frequencies");
- if (ctk_powermizer->processor_clock) {
+ if (ctk_powermizer->memory_transfer_rate &&
+ ctk_powermizer->processor_clock) {
s = "This indicates the GPU's current Graphics Clock, "
- "Memory Clock and Processor Clock frequencies.";
- } else {
+ "Memory transfer rate and Processor Clock frequencies.";
+ } else if (ctk_powermizer->memory_transfer_rate) {
s = "This indicates the GPU's current Graphics Clock and "
- "Memory Clock frequencies.";
+ "Memory transfer rate.";
+ } else {
+ s = "This indicates the GPU's current Graphics Clock ferquencies.";
}
ctk_help_para(b, &i, "%s", s);
}
diff --git a/src/gtk+-2.x/ctkpowermizer.h b/src/gtk+-2.x/ctkpowermizer.h
index e1919e8..fc0f971 100644
--- a/src/gtk+-2.x/ctkpowermizer.h
+++ b/src/gtk+-2.x/ctkpowermizer.h
@@ -56,7 +56,7 @@ struct _CtkPowermizer
GtkWidget *adaptive_clock_status;
GtkWidget *gpu_clock;
- GtkWidget *memory_clock;
+ GtkWidget *memory_transfer_rate;
GtkWidget *processor_clock;
GtkWidget *power_source;
GtkWidget *performance_level;
@@ -72,9 +72,7 @@ struct _CtkPowermizer
gboolean dp_toggle_warning_dlg_shown;
gboolean hasDecoupledClock;
gint attribute;
- gint nvclock;
- gint memclock;
- gint processorclock;
+ gint powermizer_default_mode;
GtkWidget *status;
GtkWidget *link_width;
diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c
index 56bce3f..421fe21 100644
--- a/src/gtk+-2.x/ctkscreen.c
+++ b/src/gtk+-2.x/ctkscreen.c
@@ -48,7 +48,6 @@ static const _CtkStereoMode stereoMode[] = {
{ NV_CTRL_STEREO_3D_VISION, "NVIDIA 3D Vision Stereo" },
{ NV_CTRL_STEREO_3D_VISION_PRO, "NVIDIA 3D Vision Pro Stereo" },
{ NV_CTRL_STEREO_HDMI_3D, "HDMI 3D Stereo" },
- { -1, NULL},
};
void ctk_screen_event_handler(GtkWidget *widget,
@@ -64,7 +63,7 @@ static void info_update_gpu_error(GtkObject *object, gpointer arg1,
static const char *get_stereo_mode_string(int stereo_mode)
{
int i;
- for (i = 0; stereoMode[i].name; i++) {
+ for (i = 0; i < ARRAY_LEN(stereoMode); i++) {
if (stereoMode[i].stereo_mode == stereo_mode) {
return stereoMode[i].name;
}
@@ -273,12 +272,6 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle,
snprintf(tmp, 16, "%d", gpu_errors);
- /* get the stereo mode set for this X screen */
- ret = NvCtrlGetAttribute(handle, NV_CTRL_STEREO, (int *)&stereo_mode);
- if (ret != NvCtrlSuccess) {
- stereo_mode = -1;
- }
-
/* now, create the object */
object = g_object_new(CTK_TYPE_SCREEN, NULL);
@@ -288,6 +281,10 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle,
ctk_screen->handle = handle;
+ /* get the stereo mode set for this X screen */
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_STEREO, (int *)&stereo_mode);
+ ctk_screen->stereo_available = (ret == NvCtrlSuccess);
+
/* set container properties of the object */
gtk_box_set_spacing(GTK_BOX(ctk_screen), 10);
@@ -340,8 +337,10 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle,
/* gpu errors */
ctk_screen->gpu_errors =
add_table_row(table, 19, 0, 0, "Recovered GPU Errors:", 0, 0, tmp);
- add_table_row(table, 20, 0, 0, "Stereo Mode:", 0, 0,
- get_stereo_mode_string(stereo_mode));
+ if (ctk_screen->stereo_available) {
+ add_table_row(table, 20, 0, 0, "Stereo Mode:", 0, 0,
+ get_stereo_mode_string(stereo_mode));
+ }
g_free(screen_number);
free(display_name);
@@ -376,6 +375,7 @@ GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle,
GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *table,
+ CtkScreen *ctk_screen,
const gchar *screen_name)
{
GtkTextIter i;
@@ -428,8 +428,10 @@ GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *table,
"GPU received and the NVIDIA X driver successfully recovered "
"from.");
- ctk_help_heading(b, &i, "Stereo Mode");
- ctk_help_para(b, &i, "This is the stereo mode set for the X screen.");
+ if (ctk_screen->stereo_available) {
+ ctk_help_heading(b, &i, "Stereo Mode");
+ ctk_help_para(b, &i, "This is the stereo mode set for the X screen.");
+ }
ctk_help_finish(b);
diff --git a/src/gtk+-2.x/ctkscreen.h b/src/gtk+-2.x/ctkscreen.h
index 6ea0b18..13bc003 100644
--- a/src/gtk+-2.x/ctkscreen.h
+++ b/src/gtk+-2.x/ctkscreen.h
@@ -57,6 +57,8 @@ struct _CtkScreen
GtkWidget *dimensions;
GtkWidget *displays;
GtkWidget *gpu_errors;
+
+ int stereo_available;
};
struct _CtkScreenClass
@@ -73,7 +75,8 @@ GType ctk_screen_get_type (void) G_GNUC_CONST;
GtkWidget* ctk_screen_new (NvCtrlAttributeHandle *handle,
CtkEvent *ctk_event);
-GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *, const gchar *);
+GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *, CtkScreen *,
+ const gchar *);
G_END_DECLS
diff --git a/src/gtk+-2.x/ctkslimm.c b/src/gtk+-2.x/ctkslimm.c
index 85f4f7a..bfbc638 100644
--- a/src/gtk+-2.x/ctkslimm.c
+++ b/src/gtk+-2.x/ctkslimm.c
@@ -1259,6 +1259,19 @@ static nvDisplayPtr intersect_modelines(nvLayoutPtr layout)
return display;
}
+#define STEREO_IS_3D_VISION(stereo) \
+ (((stereo) == NV_CTRL_STEREO_3D_VISION) || \
+ ((stereo) == NV_CTRL_STEREO_3D_VISION_PRO))
+
+static int get_display_stereo_mode(nvDisplayPtr display)
+{
+ if ((display->screen == NULL) ||
+ (display->screen->stereo_supported == FALSE)) {
+ return NV_CTRL_STEREO_OFF;
+ } else {
+ return display->screen->stereo;
+ }
+}
GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
CtkEvent *ctk_event, CtkConfig *ctk_config)
@@ -1279,6 +1292,7 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
CtkDropDownMenu *menu;
gchar *err_str = NULL;
+ gchar *str;
gchar *tmp;
gchar *sli_mode = NULL;
ReturnStatus ret;
@@ -1415,41 +1429,66 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
/* If we failed to load, tell the user why */
if (err_str || !layout) {
- gchar *str;
+ goto slimm_fail;
+ }
- if (!err_str) {
- str = g_strdup("Unable to load SLI Mosaic Mode Settings page.");
- } else {
- str = g_strdup_printf("Unable to load SLI Mosaic Mode Settings "
- "page:\n\n%s", err_str);
- g_free(err_str);
- }
+ display = intersect_modelines(layout);
- label = gtk_label_new(str);
- g_free(str);
- gtk_label_set_selectable(GTK_LABEL(label), TRUE);
- gtk_container_add(GTK_CONTAINER(object), label);
+ if (display == NULL) {
+ err_str = g_strdup("Unable to find active display with "
+ "intersected modelines.");
+ goto slimm_fail;
+ } else if ((display->modelines == NULL) &&
+ (display->cur_mode->modeline == NULL)) {
+ /* The modepool for the active display did not have any modes in
+ * its modepool matching any of the modes on the modepool of any
+ * other display in the layout, causing intersect_modelines to
+ * remove every mode from the list of available modes for SLI mosaic
+ * mode.
+ *
+ * This can happen if one display had its modepool trimmed and modified
+ * to support 3D vision, while other displays (either on X screens
+ * without stereo currently enabled, or on screenless GPUs) did not.
+ * Find if that is the case, and display an informative message if so.
+ */
+ nvGpuPtr gpu;
+ nvDisplayPtr d;
+ int stereo = get_display_stereo_mode(display);
- /* Show the GUI */
- gtk_widget_show_all(GTK_WIDGET(ctk_object));
+ for (gpu = layout->gpus; gpu; gpu = gpu->next_in_layout) {
+ for (d = gpu->displays; d; d = d->next_on_gpu) {
+ int other_stereo;
- return GTK_WIDGET(ctk_object);
- }
+ if (display == d) {
+ continue;
+ }
- display = intersect_modelines(layout);
+ other_stereo = get_display_stereo_mode(d);
- if (display == NULL) {
- gchar *str = g_strdup("Unable to find active display with "
- "intersected modelines.");
- label = gtk_label_new(str);
- g_free(str);
- gtk_label_set_selectable(GTK_LABEL(label), TRUE);
- gtk_container_add(GTK_CONTAINER(object), label);
+ if ((STEREO_IS_3D_VISION(stereo) &&
+ !STEREO_IS_3D_VISION(other_stereo)) ||
+ (!STEREO_IS_3D_VISION(stereo) &&
+ STEREO_IS_3D_VISION(other_stereo))) {
- /* Show the GUI */
- gtk_widget_show_all(GTK_WIDGET(ctk_object));
+ err_str = g_strdup("Unable to find common modelines between\n"
+ "all connected displays due to 3D vision\n"
+ "being enabled on some displays and not\n"
+ "others. Please make sure that 3D vision\n"
+ "is enabled on all connected displays\n"
+ "before enabling SLI mosaic mode.");
- return GTK_WIDGET(ctk_object);
+ goto slimm_fail;
+ }
+ }
+ }
+
+ /* The intersected modepool was empty, but not because of a mismatch
+ * in 3D Vision settings.
+ */
+ err_str = g_strdup("Unable to find find common modelines between "
+ "all connected displays.");
+
+ goto slimm_fail;
}
@@ -1457,11 +1496,8 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
ctk_object->modelines = display->modelines;
if (display->cur_mode->modeline) {
ctk_object->cur_modeline = display->cur_mode->modeline;
- } else if (ctk_object->modelines) {
- ctk_object->cur_modeline = ctk_object->modelines;
} else {
- /* This is an error. */
- return NULL;
+ ctk_object->cur_modeline = ctk_object->modelines;
}
ctk_object->num_modelines = display->num_modelines;
@@ -1737,6 +1773,30 @@ GtkWidget* ctk_slimm_new(NvCtrlAttributeHandle *handle,
gtk_widget_show_all(GTK_WIDGET(object));
return GTK_WIDGET(object);
+
+slimm_fail:
+
+ if (layout) {
+ layout_free(layout);
+ }
+
+ if (!err_str) {
+ str = g_strdup("Unable to load SLI Mosaic Mode Settings page.");
+ } else {
+ str = g_strdup_printf("Unable to load SLI Mosaic Mode Settings "
+ "page:\n\n%s", err_str);
+ g_free(err_str);
+ }
+
+ label = gtk_label_new(str);
+ g_free(str);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+ gtk_container_add(GTK_CONTAINER(object), label);
+
+ /* Show the GUI */
+ gtk_widget_show_all(GTK_WIDGET(ctk_object));
+
+ return GTK_WIDGET(ctk_object);
}
diff --git a/src/gtk+-2.x/ctkthermal.c b/src/gtk+-2.x/ctkthermal.c
index a3c4ac7..d5f2947 100644
--- a/src/gtk+-2.x/ctkthermal.c
+++ b/src/gtk+-2.x/ctkthermal.c
@@ -97,8 +97,11 @@ static const char * __enable_button_help =
static const char * __fan_id_help =
"This shows the GPU Fan's index.";
+static const char * __fan_rpm_help =
+"This shows the current GPU Fan Speed in rotations per minute (RPM).";
+
static const char * __fan_speed_help =
-"This shows the current GPU Fan Speed.";
+"This shows the current GPU Fan Speed level as a percentage.";
static const char * __fan_control_type_help =
"Fan Type indicates if and how this fan may be controlled. Possible "
@@ -155,7 +158,7 @@ GType ctk_thermal_get_type(void)
*/
static gboolean update_cooler_info(gpointer user_data)
{
- int i, level, cooler_type, cooler_target;
+ int i, speed, level, cooler_type, cooler_target;
gchar *tmp_str;
CtkThermal *ctk_thermal;
GtkWidget *table, *label, *eventbox;
@@ -190,18 +193,26 @@ static gboolean update_cooler_info(gpointer user_data)
gtk_container_add(GTK_CONTAINER(eventbox), label);
ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_id_help);
- label = gtk_label_new("Speed (%)");
+ label = gtk_label_new("Speed (RPM)");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
eventbox = gtk_event_box_new();
gtk_table_attach(GTK_TABLE(table), eventbox, 1, 2, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
gtk_container_add(GTK_CONTAINER(eventbox), label);
+ ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_rpm_help);
+
+ label = gtk_label_new("Speed (%)");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ eventbox = gtk_event_box_new();
+ gtk_table_attach(GTK_TABLE(table), eventbox, 2, 3, 0, 1,
+ GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ gtk_container_add(GTK_CONTAINER(eventbox), label);
ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox, __fan_speed_help);
label = gtk_label_new("Control Type");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
eventbox = gtk_event_box_new();
- gtk_table_attach(GTK_TABLE(table), eventbox, 2, 3, 0, 1,
+ gtk_table_attach(GTK_TABLE(table), eventbox, 3, 4, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
gtk_container_add(GTK_CONTAINER(eventbox), label);
ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox,
@@ -210,7 +221,7 @@ static gboolean update_cooler_info(gpointer user_data)
label = gtk_label_new("Cooling Target");
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
eventbox = gtk_event_box_new();
- gtk_table_attach(GTK_TABLE(table), eventbox, 3, 4, 0, 1,
+ gtk_table_attach(GTK_TABLE(table), eventbox, 4, 5, 0, 1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
gtk_container_add(GTK_CONTAINER(eventbox), label);
ctk_config_set_tooltip(ctk_thermal->ctk_config, eventbox,
@@ -220,7 +231,7 @@ static gboolean update_cooler_info(gpointer user_data)
for (i = 0; i < ctk_thermal->cooler_count; i++) {
row_idx = i+1;
- gtk_table_resize(GTK_TABLE(table), row_idx+1, 4);
+ gtk_table_resize(GTK_TABLE(table), row_idx+1, 5);
tmp_str = g_strdup_printf("%d", i);
label = gtk_label_new(tmp_str);
@@ -230,6 +241,21 @@ static gboolean update_cooler_info(gpointer user_data)
free(tmp_str);
ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].handle,
+ NV_CTRL_THERMAL_COOLER_SPEED,
+ &speed);
+ if (ret == NvCtrlSuccess) {
+ tmp_str = g_strdup_printf("%d", speed);
+ }
+ else {
+ tmp_str = g_strdup_printf("Unsupported");
+ }
+ label = gtk_label_new(tmp_str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_table_attach(GTK_TABLE(table), label, 1, 2, row_idx, row_idx+1,
+ GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
+ free(tmp_str);
+
+ ret = NvCtrlGetAttribute(ctk_thermal->cooler_control[i].handle,
NV_CTRL_THERMAL_COOLER_LEVEL,
&level);
if (ret != NvCtrlSuccess) {
@@ -239,7 +265,7 @@ static gboolean update_cooler_info(gpointer user_data)
tmp_str = g_strdup_printf("%d", level);
label = gtk_label_new(tmp_str);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 1, 2, row_idx, row_idx+1,
+ gtk_table_attach(GTK_TABLE(table), label, 2, 3, row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
free(tmp_str);
@@ -259,7 +285,7 @@ static gboolean update_cooler_info(gpointer user_data)
}
label = gtk_label_new(tmp_str);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 2, 3, row_idx, row_idx+1,
+ gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
free(tmp_str);
@@ -288,7 +314,7 @@ static gboolean update_cooler_info(gpointer user_data)
}
label = gtk_label_new(tmp_str);
gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
- gtk_table_attach(GTK_TABLE(table), label, 3, 4, row_idx, row_idx+1,
+ gtk_table_attach(GTK_TABLE(table), label, 4, 5, row_idx, row_idx+1,
GTK_FILL, GTK_FILL | GTK_EXPAND, 5, 0);
free(tmp_str);
}
@@ -1661,6 +1687,9 @@ next_help:
ctk_help_heading(b, &i, "ID");
ctk_help_para(b, &i, "%s", __fan_id_help);
+ ctk_help_heading(b, &i, "Speed (RPM)");
+ ctk_help_para(b, &i,"%s", __fan_rpm_help);
+
ctk_help_heading(b, &i, "Speed (%%)");
ctk_help_para(b, &i, "%s", __fan_speed_help);
diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c
index b92c076..7ade747 100644
--- a/src/gtk+-2.x/ctkwindow.c
+++ b/src/gtk+-2.x/ctkwindow.c
@@ -341,47 +341,27 @@ static void tree_selection_changed(GtkTreeSelection *selection,
-/*
- * tree_view_key_event() - callback for additional keyboard events we
- * want to track (space and Return) to expand and collapse collapsible
- * categories in the treeview.
+/*
+ * row_activated_event() - callback for row-activated event
+ * - handles key presses automatically
+ * - allows the mouse to collapse/expand the menu even when the
+ * expand button/triangle is not working.
*/
-static gboolean tree_view_key_event(GtkWidget *tree_view, GdkEvent *event,
- gpointer user_data)
+static void row_activated_event(GtkTreeView *view,
+ GtkTreePath *path,
+ GtkTreeViewColumn *col,
+ gpointer user_data)
{
- GdkEventKey *key_event = (GdkEventKey *) event;
CtkWindow *ctk_window = CTK_WINDOW(user_data);
-
- if ((key_event->keyval == GDK_space) ||
- (key_event->keyval == GDK_Return)) {
-
- GtkTreeSelection* selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath* path;
-
- selection = gtk_tree_view_get_selection(ctk_window->treeview);
-
- if (!gtk_tree_selection_get_selected(selection, &model, &iter))
- return FALSE;
-
- path = gtk_tree_model_get_path(model, &iter);
-
- if (gtk_tree_view_row_expanded(ctk_window->treeview, path)) {
- gtk_tree_view_collapse_row(ctk_window->treeview, path);
- } else {
- gtk_tree_view_expand_row(ctk_window->treeview, path, FALSE);
- }
-
- gtk_tree_path_free(path);
-
- return TRUE;
- }
-
- return FALSE;
-} /* tree_view_key_event() */
+ if (gtk_tree_view_row_expanded(ctk_window->treeview, path)) {
+ gtk_tree_view_collapse_row(ctk_window->treeview, path);
+ } else {
+ gtk_tree_view_expand_row(ctk_window->treeview, path, FALSE);
+ }
+}
+
static gboolean has_randr_gamma(NvCtrlAttributeHandle *handle)
@@ -544,10 +524,10 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf,
ctk_window->treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
g_object_unref(ctk_window->tree_store);
- /* catch keyboard events to the tree view */
+ /* Added row activated event to the tree view */
- g_signal_connect(ctk_window->treeview, "key_press_event",
- G_CALLBACK(tree_view_key_event), GTK_OBJECT(ctk_window));
+ g_signal_connect(ctk_window->treeview, "row_activated",
+ G_CALLBACK(row_activated_event), GTK_OBJECT(ctk_window));
selection = gtk_tree_view_get_selection(ctk_window->treeview);
@@ -660,8 +640,10 @@ GtkWidget *ctk_window_new(ParsedAttribute *p, ConfigProperties *conf,
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_WIDGET_COLUMN, child, -1);
gtk_tree_store_set(ctk_window->tree_store, &iter,
- CTK_WINDOW_HELP_COLUMN,
- ctk_screen_create_help(tag_table, screen_name), -1);
+ CTK_WINDOW_HELP_COLUMN,
+ ctk_screen_create_help(tag_table, CTK_SCREEN(child),
+ screen_name),
+ -1);
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN,
NULL, -1);
@@ -1438,16 +1420,18 @@ static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter,
* saved to the RC file when the UI is closed.
*/
- if (handles) {
- display_handle = nv_get_target_handle(handles,
- NV_CTRL_TARGET_TYPE_DISPLAY,
- display_id);
- } else {
- display_handle = NULL;
- }
+ display_handle = nv_get_target_handle(handles,
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ display_id);
if (!display_handle) {
- continue;
+ display_handle =
+ nv_add_target(handles, NvCtrlGetDisplayPtr(gpu_handle),
+ NV_CTRL_TARGET_TYPE_DISPLAY, display_id);
+
+ if (!display_handle) {
+ continue;
+ }
}
/*
diff --git a/src/gtk+-2.x/ctkxvideo.c b/src/gtk+-2.x/ctkxvideo.c
index 32bcf7c..8d33c5c 100644
--- a/src/gtk+-2.x/ctkxvideo.c
+++ b/src/gtk+-2.x/ctkxvideo.c
@@ -21,12 +21,13 @@
#include <stdio.h>
#include <gtk/gtk.h>
#include "NvCtrlAttributes.h"
+#include "NVCtrlLib.h"
-#include "ctkbanner.h"
+#include "msg.h"
+#include "ctkbanner.h"
#include "ctkxvideo.h"
-#include "ctkscale.h"
-
+#include "ctkutils.h"
#include "ctkhelp.h"
@@ -34,35 +35,9 @@ static const char *__xv_sync_to_display_help =
"This controls which display device will be synched to when "
"XVideo Sync To VBlank is enabled.";
-static void xv_sync_to_display_changed(GtkWidget *widget, gpointer user_data);
-
-static GtkWidget *xv_sync_to_display_radio_button_add(CtkXVideo *ctk_xvideo,
- GtkWidget *prev_radio,
- char *label,
- gint value,
- int index);
-
-static void
-xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo, gint value,
- gboolean update_status);
-
-static void xv_sync_to_display_changed(GtkWidget *widget, gpointer user_data);
-
-static void xv_sync_to_display_update_received(GtkObject *object, gpointer arg1,
- gpointer user_data);
-
-static void post_xv_sync_to_display_changed(CtkXVideo *ctk_xvideo,
- GtkWidget *widget);
-static void nv_ctrl_enabled_displays(GtkObject *object, gpointer arg1,
- gpointer user_data);
-static void xv_sync_to_display_radio_button_remove(CtkXVideo *ctk_xvideo,
- gint value);
-static void xv_sync_to_display_radio_button_enabled_add(CtkXVideo *ctk_xvideo,
- gint add_device_mask);
#define FRAME_PADDING 5
-
#define __XV_SYNC_TO_DISPLAY 1
@@ -93,298 +68,285 @@ GType ctk_xvideo_get_type(
return ctk_xvideo_type;
}
+
+
/*
- * xv_sync_to_display_radio_button_add() - create a radio button and plug it
- * into the xv_sync_display radio group.
+ * Updates the status bar for when a change occured.
*/
-
-static GtkWidget *xv_sync_to_display_radio_button_add(CtkXVideo *ctk_xvideo,
- GtkWidget *prev_radio,
- char *label,
- gint value,
- int index)
+static void post_xv_sync_to_display_update(CtkXVideo *ctk_xvideo,
+ GtkWidget *active_button)
{
- GtkWidget *radio;
-
- if (prev_radio) {
- radio = gtk_radio_button_new_with_label_from_widget
- (GTK_RADIO_BUTTON(prev_radio), label);
- } else {
- radio = gtk_radio_button_new_with_label(NULL, label);
- }
-
- gtk_box_pack_start(GTK_BOX(ctk_xvideo->xv_sync_to_display_button_box),
- radio, FALSE, FALSE, 0);
+ const gchar *label;
- g_object_set_data(G_OBJECT(radio), "xv_sync_to_display",
- GINT_TO_POINTER(value));
-
- g_signal_connect(G_OBJECT(radio), "toggled",
- G_CALLBACK(xv_sync_to_display_changed),
- (gpointer) ctk_xvideo);
+ label = gtk_button_get_label(GTK_BUTTON(active_button));
- ctk_xvideo->xv_sync_to_display_buttons[index] = radio;
+ ctk_config_statusbar_message(ctk_xvideo->ctk_config,
+ "XVideo application syncing to %s.",
+ label);
+}
- return radio;
-
-} /* xv_sync_to_display_radio_button_add() */
-static void
-xv_sync_to_display_update_radio_buttons(CtkXVideo *ctk_xvideo,
- gint value, gboolean update_status)
+/*
+ * xv_sync_to_display_id_toggled() - callback function for changes to the
+ * sync_to_display radio button group; if the specified radio button is
+ * active, send xv_sync_to_display state to the server
+ */
+static void xv_sync_to_display_id_toggled(GtkWidget *widget,
+ gpointer user_data)
{
- GtkWidget *b, *button = NULL;
- int i;
+ CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data);
+ gboolean enabled;
+ gint device_id;
+
+ enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+ if (!enabled) {
+ /* Ignore 'disable' events. */
+ return;
+ }
- button = ctk_xvideo->xv_sync_to_display_buttons[value];
-
- if (!button) return;
+ user_data = g_object_get_data(G_OBJECT(widget), "display_id");
- /* turn off signal handling for all the sync buttons */
+ device_id = GPOINTER_TO_INT(user_data);
- for (i = 0; i < 24; i++) {
- b = ctk_xvideo->xv_sync_to_display_buttons[i];
- if (!b) continue;
+ NvCtrlSetAttribute(ctk_xvideo->handle, NV_CTRL_XV_SYNC_TO_DISPLAY_ID,
+ device_id);
- g_signal_handlers_block_by_func
- (G_OBJECT(b), G_CALLBACK(xv_sync_to_display_changed),
- (gpointer) ctk_xvideo);
- }
-
- /* set the appropriate button active */
+ post_xv_sync_to_display_update(ctk_xvideo, widget);
+}
+
+
+
+/*
+ * Sets the radio button at the given index as enabled.
+ */
+static void xv_sync_to_display_set_enabled(CtkXVideo *ctk_xvideo,
+ GtkWidget *button,
+ gboolean update_status)
+{
+ /* turn off signal handling. Note that we only disable events
+ * for the button being enabled since we ignore disable events.
+ */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(button), G_CALLBACK(xv_sync_to_display_id_toggled),
+ (gpointer) ctk_xvideo);
+
+ /* set the button as active */
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
-
- /* turn on signal handling for all the sync buttons */
- for (i = 0; i < 24; i++) {
- b = ctk_xvideo->xv_sync_to_display_buttons[i];
- if (!b) continue;
+ /* turn on signal handling */
- g_signal_handlers_unblock_by_func
- (G_OBJECT(b), G_CALLBACK(xv_sync_to_display_changed),
- (gpointer) ctk_xvideo);
- }
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(button), G_CALLBACK(xv_sync_to_display_id_toggled),
+ (gpointer) ctk_xvideo);
if (update_status) {
- post_xv_sync_to_display_changed(ctk_xvideo, button);
+ post_xv_sync_to_display_update(ctk_xvideo, button);
}
+}
-} /* xv_sync_to_display_update_radio_buttons() */
/*
- * xv_sync_to_display_changed() - callback function for changes to the
- * sync_to_display radio button group; if the specified radio button is
- * active, send xv_sync_to_display state to the server
+ * xv_sync_to_display_radio_button_add() - create a radio button and plug it
+ * into the xv_sync_display_buttons radio group.
*/
-
-static void xv_sync_to_display_changed(GtkWidget *widget, gpointer user_data)
+static GtkWidget *xv_sync_to_display_radio_button_add(CtkXVideo *ctk_xvideo,
+ GtkWidget *last_button,
+ gint display_id)
{
- CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data);
- gboolean enabled;
- gint device_mask;
-
- enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+ Bool valid;
+ char *name;
+ char *randr;
+ gchar *label;
+ GtkWidget *button;
+ GSList *slist;
+
+
+ valid =
+ XNVCTRLQueryTargetStringAttribute(NvCtrlGetDisplayPtr(ctk_xvideo->handle),
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ display_id,
+ 0,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
+ &name);
+ if (!valid) {
+ name = NULL;
+ }
- if (!enabled) {
- /* Ignore 'disable' events. */
- return;
+ valid =
+ XNVCTRLQueryTargetStringAttribute(NvCtrlGetDisplayPtr(ctk_xvideo->handle),
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ display_id,
+ 0,
+ NV_CTRL_STRING_DISPLAY_NAME_RANDR,
+ &randr);
+ if (!valid) {
+ randr = NULL;
}
- user_data = g_object_get_data(G_OBJECT(widget), "xv_sync_to_display");
+ if (name && randr) {
+ label = g_strdup_printf("%s (%s)", name, randr);
+ } else {
+ label = g_strdup_printf("%s",
+ name ? name : (randr ? randr : "Unknown"));
+ }
- device_mask = GPOINTER_TO_INT(user_data);
+ XFree(name);
+ XFree(randr);
- NvCtrlSetAttribute(ctk_xvideo->handle,
- NV_CTRL_XV_SYNC_TO_DISPLAY, device_mask);
+ if (last_button) {
+ slist = gtk_radio_button_get_group(GTK_RADIO_BUTTON(last_button));
+ } else {
+ slist = NULL;
+ }
+ button = gtk_radio_button_new_with_label(slist, label);
+ g_free(label);
- post_xv_sync_to_display_changed(ctk_xvideo, widget);
+ gtk_box_pack_start(GTK_BOX(ctk_xvideo->xv_sync_to_display_button_box),
+ button, FALSE, FALSE, 0);
-}/* xv_sync_to_display_changed() */
+ g_object_set_data(G_OBJECT(button), "display_id",
+ GINT_TO_POINTER(display_id));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
-static void post_xv_sync_to_display_changed(CtkXVideo *ctk_xvideo,
- GtkWidget *active_button)
-{
- const gchar *label;
+ g_signal_connect(G_OBJECT(button), "toggled",
+ G_CALLBACK(xv_sync_to_display_id_toggled),
+ (gpointer) ctk_xvideo);
- label = gtk_button_get_label(GTK_BUTTON(active_button));
+ ctk_config_set_tooltip(ctk_xvideo->ctk_config, button,
+ __xv_sync_to_display_help);
- ctk_config_statusbar_message(ctk_xvideo->ctk_config,
- "XVideo application syncing to %s.",
- label);
+ return button;
}
+
+
/*
- * xv_sync_to_display_radio_button_remove()
+ * Rebuilds the list of display devices available for syncing.
*/
-static void xv_sync_to_display_radio_button_remove(CtkXVideo *ctk_xvideo,
- gint value)
+static void xv_sync_to_display_rebuild_buttons(CtkXVideo *ctk_xvideo,
+ gboolean update_status)
{
- int j;
- GtkWidget *b;
- gpointer user_data;
- for (j = 0; j < 24; j++) {
- b = ctk_xvideo->xv_sync_to_display_buttons[j];
- if (b != NULL) {
- user_data = g_object_get_data(G_OBJECT(b), "xv_sync_to_display");
- if (GPOINTER_TO_INT(user_data) == value) {
- g_object_set_data(G_OBJECT(b), "xv_sync_to_display",
- GINT_TO_POINTER(0));
- gtk_container_remove(GTK_CONTAINER(ctk_xvideo->xv_sync_to_display_button_box), b);
- ctk_xvideo->xv_sync_to_display_buttons[j] = NULL;
- break;
- }
+ ReturnStatus ret;
+ int enabled_display_id;
+ int *pData;
+ int len;
+ int i;
+
+ GtkWidget *last_button;
+
+
+ /* Remove all buttons */
+
+ ctk_empty_container(ctk_xvideo->xv_sync_to_display_button_box);
+
+
+ /* Rebuild the list based on the curren configuration */
+
+ ret = NvCtrlGetAttribute(ctk_xvideo->handle,
+ NV_CTRL_XV_SYNC_TO_DISPLAY_ID,
+ &enabled_display_id);
+ if (ret != NvCtrlSuccess) {
+ nv_warning_msg("Failed to query XV Sync display ID on X screen %d.",
+ NvCtrlGetTargetId(ctk_xvideo->handle));
+ return;
+ }
+
+ ret = NvCtrlGetBinaryAttribute(ctk_xvideo->handle, 0,
+ NV_CTRL_BINARY_DATA_DISPLAYS_ENABLED_ON_XSCREEN,
+ (unsigned char **)(&pData), &len);
+ if (ret != NvCtrlSuccess) {
+ nv_warning_msg("Failed to query list of displays assigned to X screen "
+ " %d.",
+ NvCtrlGetTargetId(ctk_xvideo->handle));
+ return;
+ }
+
+
+ /* Add a button for each display device */
+
+ last_button = NULL;
+ for (i = 0; i < pData[0]; i++) {
+ GtkWidget *button;
+ int display_id = pData[1+i];
+
+ button = xv_sync_to_display_radio_button_add(ctk_xvideo,
+ last_button,
+ display_id);
+ if (!button) {
+ continue;
+ }
+
+ /* Make sure the enabled display is marked as so */
+ if (display_id == enabled_display_id) {
+ xv_sync_to_display_set_enabled(ctk_xvideo, button,
+ update_status);
}
+
+ /* Track the first button */
+ if (!last_button) {
+ ctk_xvideo->xv_sync_to_display_buttons = button;
+ }
+
+ last_button = button;
}
-} /* xv_sync_to_display_radio_button_remove() */
+
+ gtk_widget_show_all(ctk_xvideo->xv_sync_to_display_button_box);
+}
+
+
/*
- * nv_ctrl_enabled_displays()
+ * Handles NV_CTRL_ENABLED_DISPLAYS events and updates
+ * the list of displays in the UI.
*/
-static void nv_ctrl_enabled_displays(GtkObject *object, gpointer arg1,
+static void enabled_displays_handler(GtkObject *object, gpointer arg1,
gpointer user_data)
{
CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data);
- int i, enabled, prev_enabled = 0;
- int remove_devices_mask, add_devices_mask;
- unsigned int mask;
- gpointer udata;
- GtkWidget *b;
- ReturnStatus ret;
-
- /*
- * The event data passed in gives us the enabled displays mask
- * for all displays on all X Screens on this GPU. Since we can
- * only sync to a display on this X Screen, we need to have the
- * correct enabled displays.
- */
- ret = NvCtrlGetAttribute(ctk_xvideo->handle,
- NV_CTRL_ENABLED_DISPLAYS,
- &enabled);
- if (ret != NvCtrlSuccess) {
- enabled = 0;
- }
-
- /* Extract the previous value. */
- for ( i = 0; i < 24; i++) {
- b = ctk_xvideo->xv_sync_to_display_buttons[i];
- if (b == NULL) continue;
- udata = g_object_get_data(G_OBJECT(b),
- "xv_sync_to_display");
-
- prev_enabled |= GPOINTER_TO_INT(udata);
- }
-
- /* Remove devices that were previously enabled but are no
- * longer enabled. */
- remove_devices_mask = (prev_enabled & (~enabled));
-
- /* Add devices that were not previously enabled */
- add_devices_mask = (enabled & (~prev_enabled));
- prev_enabled = enabled;
- for (mask = 1; mask; mask <<= 1) {
- if (mask & add_devices_mask)
- xv_sync_to_display_radio_button_enabled_add(ctk_xvideo, mask);
-
- if (mask & remove_devices_mask)
- xv_sync_to_display_radio_button_remove(ctk_xvideo, mask);
- }
- gtk_widget_show_all(ctk_xvideo->xv_sync_to_display_button_box);
-} /* nv_ctrl_enabled_displays() */
-
-/*
- * xv_sync_to_display_radio_button_enabled_add()
- */
-static void xv_sync_to_display_radio_button_enabled_add(CtkXVideo *ctk_xvideo,
- gint add_device_mask)
-{
- GtkWidget *radio[24], *prev_radio = NULL, *b1, *b2;
- int n;
- ReturnStatus ret;
- char *name, *type;
- gchar *name_str;
-
- /* Get the previous radio button. */
- for (n = 0; n < 24; n++) {
- b1 = ctk_xvideo->xv_sync_to_display_buttons[n];
- if (b1 != NULL) {
- prev_radio = b1;
- break;
- }
- }
- /* Get the next index where to add button. */
- for (n = 0; n < 24; n++) {
- b2 = ctk_xvideo->xv_sync_to_display_buttons[n];
- if (b2 == NULL) break;
- }
- ret = NvCtrlGetStringDisplayAttribute(ctk_xvideo->handle, add_device_mask,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &name);
- if ((ret != NvCtrlSuccess) || (!name)) {
- name = g_strdup("Unknown");
- }
- /* get the display device type */
- type = display_device_mask_to_display_device_name(add_device_mask);
- name_str = g_strdup_printf("%s (%s)", name, type);
- XFree(name);
- free(type);
+ xv_sync_to_display_rebuild_buttons(ctk_xvideo, TRUE);
+}
- radio[n] = xv_sync_to_display_radio_button_add(ctk_xvideo,
- prev_radio, name_str,
- add_device_mask, n);
- g_free(name_str);
- ctk_config_set_tooltip(ctk_xvideo->ctk_config, radio[n],
- __xv_sync_to_display_help);
-
-} /* xv_sync_to_display_radio_button_enabled_add() */
/*
- * xv_sync_to_display_update_received() - callback function for changed sync
- * to display settings; this is called when we receive an event indicating that
- * another NV-CONTROL client changed any of the settings that we care
- * about.
+ * Handler for NV_CTRL_XV_SYNC_TO_DISPLAY_ID events.
*/
-
-static void xv_sync_to_display_update_received(GtkObject *object,
- gpointer arg1,
- gpointer user_data)
+static void xv_sync_to_display_id_handler(GtkObject *object,
+ gpointer arg1,
+ gpointer user_data)
{
CtkEventStruct *event_struct = (CtkEventStruct *) arg1;
CtkXVideo *ctk_xvideo = CTK_XVIDEO(user_data);
- gint i;
- GtkWidget *b;
-
- switch (event_struct->attribute) {
- case NV_CTRL_XV_SYNC_TO_DISPLAY:
- for (i = 0; i < 24; i++) {
- b = ctk_xvideo->xv_sync_to_display_buttons[i];
- if (!b) continue;
- user_data = g_object_get_data(G_OBJECT(b), "xv_sync_to_display");
-
- if (GPOINTER_TO_INT(user_data) == event_struct->value) {
- xv_sync_to_display_update_radio_buttons(ctk_xvideo, i,
- TRUE);
- break;
- }
+ GSList *slist;
+
+ /* Find the right button and enable it */
+
+ slist =
+ gtk_radio_button_get_group(GTK_RADIO_BUTTON(ctk_xvideo->xv_sync_to_display_buttons));
+
+ while (slist) {
+ GtkWidget *button = GTK_WIDGET(slist->data);
+
+ user_data = g_object_get_data(G_OBJECT(button), "display_id");
+ if (GPOINTER_TO_INT(user_data) == event_struct->value) {
+ xv_sync_to_display_set_enabled(ctk_xvideo, button, TRUE);
+ break;
}
- break;
-
- default:
- break;
+
+ slist = g_slist_next(slist);
}
-
-} /* xv_sync_to_display_update_received() */
+}
+
/*
* ctk_xvideo_new() - constructor for the XVideo widget
*/
-
GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
CtkConfig *ctk_config,
CtkEvent *ctk_event)
@@ -395,147 +357,107 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
GtkWidget *frame;
GtkWidget *alignment;
GtkWidget *vbox;
- int sync_mask;
int xv_overlay_present, xv_texture_present, xv_blitter_present;
+ gboolean show_page;
ReturnStatus ret;
/*
* before we do anything else, determine if any of the Xv adapters
* are present
*/
-
+
ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_OVERLAY_PRESENT,
&xv_overlay_present);
-
- if (ret != NvCtrlSuccess) xv_overlay_present = FALSE;
-
+ if (ret != NvCtrlSuccess) {
+ xv_overlay_present = FALSE;
+ }
+
ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_TEXTURE_PRESENT,
&xv_texture_present);
+ if (ret != NvCtrlSuccess) {
+ xv_texture_present = FALSE;
+ }
- if (ret != NvCtrlSuccess) xv_texture_present = FALSE;
-
ret = NvCtrlGetAttribute(handle, NV_CTRL_ATTR_EXT_XV_BLITTER_PRESENT,
&xv_blitter_present);
-
- if (ret != NvCtrlSuccess) xv_blitter_present = FALSE;
-
+ if (ret != NvCtrlSuccess) {
+ xv_blitter_present = FALSE;
+ }
+
if (!xv_overlay_present && !xv_texture_present && !xv_blitter_present) {
return NULL;
}
-
-
+
+ /* If nothing to show, bail */
+
+ show_page = FALSE;
+ if (xv_texture_present || xv_blitter_present) {
+ int display_id;
+ ret = NvCtrlGetAttribute(handle,
+ NV_CTRL_XV_SYNC_TO_DISPLAY_ID,
+ &display_id);
+ if (ret == NvCtrlSuccess) {
+ show_page = TRUE;
+ }
+ }
+
+ if (!show_page) {
+ return NULL;
+ }
+
+
/* create the XVideo widget */
-
+
object = g_object_new(CTK_TYPE_XVIDEO, NULL);
ctk_xvideo = CTK_XVIDEO(object);
-
+
ctk_xvideo->handle = handle;
ctk_xvideo->ctk_config = ctk_config;
ctk_xvideo->active_attributes = 0;
-
+
gtk_box_set_spacing(GTK_BOX(ctk_xvideo), 10);
-
-
+
+
/* Video film banner */
-
+
banner = ctk_banner_image_new(BANNER_ARTWORK_XVIDEO);
gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
+
/* Sync to display selection */
- if (xv_texture_present || xv_blitter_present) {
- ret = NvCtrlGetAttribute(handle,
- NV_CTRL_XV_SYNC_TO_DISPLAY,
- &sync_mask);
- if (ret == NvCtrlSuccess) {
- int enabled;
- ret = NvCtrlGetAttribute(handle,
- NV_CTRL_ENABLED_DISPLAYS,
- &enabled);
- if (ret == NvCtrlSuccess) {
-
- GtkWidget *radio[24], *prev_radio;
- int i, n, current = -1, mask;
- char *name, *type;
- gchar *name_str;
- frame = gtk_frame_new("Sync to this display device");
- gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
-
- vbox = gtk_vbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
- gtk_container_add(GTK_CONTAINER(frame), vbox);
- ctk_xvideo->xv_sync_to_display_button_box = vbox;
-
- for (n=0, i = 0; i < 24; i++) {
-
- mask = 1 << i;
- if (!(enabled & mask)) continue;
-
- /* get the name of the display device */
-
- ret = NvCtrlGetStringDisplayAttribute(handle, mask,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &name);
-
- if ((ret != NvCtrlSuccess) || (!name)) {
- name = g_strdup("Unknown");
- }
-
- /* get the display device type */
-
- type = display_device_mask_to_display_device_name(mask);
-
- name_str = g_strdup_printf("%s (%s)", name, type);
- XFree(name);
- free(type);
-
- if (n==0) {
- prev_radio = NULL;
- } else {
- prev_radio = radio[n-1];
- }
- radio[n] = xv_sync_to_display_radio_button_add(ctk_xvideo,
- prev_radio,
- name_str,
- mask, n);
- g_free(name_str);
- ctk_config_set_tooltip(ctk_config, radio[n],
- __xv_sync_to_display_help);
-
- if (mask == sync_mask) {
- current = n;
- }
-
- n++;
- ctk_xvideo->active_attributes |= __XV_SYNC_TO_DISPLAY;
- }
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_XV_SYNC_TO_DISPLAY),
- G_CALLBACK(xv_sync_to_display_update_received),
- (gpointer) ctk_xvideo);
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
- G_CALLBACK(nv_ctrl_enabled_displays),
- (gpointer) ctk_xvideo);
-
- if (current != -1) {
- xv_sync_to_display_update_radio_buttons(ctk_xvideo,
- current, FALSE);
- }
- }
- }
- }
-
+
+ frame = gtk_frame_new("Sync to this display device");
+ gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+ ctk_xvideo->xv_sync_to_display_button_box = vbox;
+
+ xv_sync_to_display_rebuild_buttons(ctk_xvideo, FALSE);
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_XV_SYNC_TO_DISPLAY_ID),
+ G_CALLBACK(xv_sync_to_display_id_handler),
+ (gpointer) ctk_xvideo);
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
+ G_CALLBACK(enabled_displays_handler),
+ (gpointer) ctk_xvideo);
+
+
alignment = gtk_alignment_new(1, 1, 0, 0);
gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0);
-
+
/* finally, show the widget */
gtk_widget_show_all(GTK_WIDGET(ctk_xvideo));
return GTK_WIDGET(ctk_xvideo);
-
-} /* ctk_xvideo_new() */
+}
+
+
GtkTextBuffer *ctk_xvideo_create_help(GtkTextTagTable *table,
CtkXVideo *ctk_xvideo)
@@ -544,19 +466,19 @@ GtkTextBuffer *ctk_xvideo_create_help(GtkTextTagTable *table,
GtkTextBuffer *b;
b = gtk_text_buffer_new(table);
-
+
gtk_text_buffer_get_iter_at_offset(b, &i, 0);
ctk_help_title(b, &i, "X Server XVideo Settings Help");
ctk_help_para(b, &i, "The X Server XVideo Settings page uses the XVideo "
"X extension.");
-
+
if (ctk_xvideo->active_attributes & __XV_SYNC_TO_DISPLAY) {
ctk_help_heading(b, &i, "Sync to this display device");
ctk_help_para(b, &i, "%s", __xv_sync_to_display_help);
}
-
+
ctk_help_finish(b);
return b;
diff --git a/src/gtk+-2.x/ctkxvideo.h b/src/gtk+-2.x/ctkxvideo.h
index 56025fd..06cad06 100644
--- a/src/gtk+-2.x/ctkxvideo.h
+++ b/src/gtk+-2.x/ctkxvideo.h
@@ -54,7 +54,8 @@ struct _CtkXVideo
NvCtrlAttributeHandle *handle;
CtkConfig *ctk_config;
- GtkWidget *xv_sync_to_display_buttons[24];
+ GtkWidget *xv_sync_to_display_buttons; /* first button in group */
+
GtkWidget *xv_sync_to_display_button_box;
unsigned int active_attributes;
};
@@ -65,8 +66,8 @@ struct _CtkXVideoClass
};
GType ctk_xvideo_get_type (void) G_GNUC_CONST;
-GtkWidget* ctk_xvideo_new (NvCtrlAttributeHandle *, CtkConfig *,
- CtkEvent *ctk_event);
+GtkWidget* ctk_xvideo_new (NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config, CtkEvent *ctk_event);
GtkTextBuffer *ctk_xvideo_create_help(GtkTextTagTable *, CtkXVideo *);
diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h
index e1ab891..e50dd98 100644
--- a/src/libXNVCtrl/NVCtrl.h
+++ b/src/libXNVCtrl/NVCtrl.h
@@ -1891,19 +1891,7 @@
/*
- * NV_CTRL_FLATPANEL_NATIVE_RESOLUTION - Returns the dimensions of the
- * native resolution of the flat panel as determined by the
- * NVIDIA X Driver.
- *
- * The native resolution is the resolution at which a flat panel
- * must display any image. All other resolutions must be scaled to this
- * resolution through GPU scaling or the DFP's native scaling capabilities
- * in order to be displayed.
- *
- * This attribute is only valid for flat panel (DFP) display devices.
- *
- * This attribute is a packed integer; the width is packed in the upper
- * 16-bits and the height is packed in the lower 16-bits.
+ * NV_CTRL_FLATPANEL_NATIVE_RESOLUTION - not supported
*/
#define NV_CTRL_FLATPANEL_NATIVE_RESOLUTION 251 /* R-DG */
@@ -3298,7 +3286,25 @@
*/
#define NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE 400 /* R--G */
-#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE
+/*
+ * NV_CTRL_XV_SYNC_TO_DISPLAY_ID - When XVideo Sync To VBlank is enabled, this
+ * controls which display device will be synched to.
+ */
+#define NV_CTRL_XV_SYNC_TO_DISPLAY_ID 401 /* RW- */
+
+/*
+ * NV_CTRL_BACKLIGHT_BRIGHTNESS - The backlight brightness of an internal panel.
+ */
+#define NV_CTRL_BACKLIGHT_BRIGHTNESS 402 /* RWD- */
+
+/*
+ * NV_CTRL_THERMAL_COOLER_SPEED - Returns cooler's current operating speed in
+ * rotations per minute (RPM).
+ */
+
+#define NV_CTRL_THERMAL_COOLER_SPEED 405 /* R--C */
+
+#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_THERMAL_COOLER_SPEED
/**************************************************************************/
@@ -3701,6 +3707,12 @@
* "memclock" integer - the memory clocks (in MHz) for the perf level
* "memclockmin" integer - the memory clocks min (in MHz) for the perf level
* "memclockmax" integer - the memory clocks max (in MHz) for the perf level
+ * "memtransferrate" integer - the memory transfer rate (in MHz)
+ * for the perf level
+ * "memtransferratemin" integer - the memory transfer rate min (in MHz)
+ * for the perf level
+ * "memtransferratemax" integer - the memory transfer rate max (in MHz)
+ * for the perf level
* "processorclock" integer - the processor clocks (in MHz)
* for the perf level
* "processorclockmin" integer - the processor clocks min (in MHz)
@@ -3711,9 +3723,11 @@
* Example:
*
* perf=0, nvclock=324, nvclockmin=324, nvclockmax=324, memclock=324,
- * memclockmin=324, memclockmax=324 ;
+ * memclockmin=324, memclockmax=324, memtransferrate=648,
+ * memtransferratemin=648,memtransferratemax=648 ;
* perf=1, nvclock=324, nvclockmin=324, nvclockmax=640, memclock=810,
- * memclockmin=810, memclockmax=810 ;
+ * memclockmin=810, memclockmax=810, memtransferrate=1620,
+ * memtransferrate=1620, memtransferrate=1620 ;
*
* This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
* using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
@@ -3842,6 +3856,12 @@
* "memclock" integer - the memory clocks (in MHz) for the perf level
* "memclockmin" integer - the memory clocks min (in MHz) for the perf level
* "memclockmax" integer - the memory clocks (max in MHz) for the perf level
+ * "memtransferrate" integer - the memory transfer rate (in MHz)
+ * for the perf level
+ * "memtransferratemin" integer - the memory transfer rate min (in MHz)
+ * for the perf level
+ * "memtransferratemax" integer - the memory transfer rate max (in MHz)
+ * for the perf level
* "processorclock" integer - the processor clocks (in MHz)
* for the perf level
* "processorclockmin" integer - the processor clocks min (in MHz)
@@ -3852,7 +3872,7 @@
* Example:
*
* nvclock=324, nvclockmin=324, nvclockmax=324,
- * memclock=324, memclockmin=324, memclockmax=324
+ * memclock=324, memclockmin=324, memclockmax=324, memtrasferrate=628
*
* This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
* using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
@@ -3998,6 +4018,34 @@
*/
#define NV_CTRL_STRING_GPU_UUID 52 /* R--G */
+/*
+ * NV_CTRL_STRING_GPU_UTILIZATION - Returns the current percentage usage
+ * of the various components of the GPU.
+ *
+ * Current valid tokens are "graphics", "memory", "video" and "PCIe".
+ * Not all tokens will be reported on all GPUs, and additional tokens
+ * may be added in the future.
+ *
+ * Utilization values are returned as a comma-separated list of
+ * "token=value" pairs.
+ * Valid tokens:
+ *
+ * Token Value
+ * "graphics" integer - the percentage usage of graphics engine.
+ * "memory" integer - the percentage usage of FB.
+ * "video" integer - the percentage usage of video engine.
+ * "PCIe" integer - the percentage usage of PCIe bandwidth.
+ *
+ *
+ * Example:
+ *
+ * graphics=45, memory=6, video=0, PCIe=0
+ *
+ * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
+ * using an NV_CTRL_TARGET_TYPE_GPU.
+ */
+#define NV_CTRL_STRING_GPU_UTILIZATION 53 /* R--G */
+
/*
* NV_CTRL_STRING_MULTIGPU_MODE - returns a string describing the current
diff --git a/src/nvidia-settings.c b/src/nvidia-settings.c
index acfa685..bda2b20 100644
--- a/src/nvidia-settings.c
+++ b/src/nvidia-settings.c
@@ -29,6 +29,9 @@
#include <stdlib.h>
+extern int __list_targets;
+
+
int main(int argc, char **argv)
{
ConfigProperties conf;
@@ -119,11 +122,11 @@ int main(int argc, char **argv)
}
/*
- * if the user requested that we only load the config file, then
- * exit now
+ * if the user requested that we only load the config file, or that
+ * we only list the resolved targets, then exit now.
*/
-
- if (op->only_load) {
+
+ if (op->only_load || __list_targets) {
return ret ? 0 : 1;
}
diff --git a/src/option-table.h b/src/option-table.h
index 50b0356..403f19c 100644
--- a/src/option-table.h
+++ b/src/option-table.h
@@ -170,6 +170,16 @@ static const NVGetoptOption __options[] = {
"The first page with a name matching the &PAGE& argument will be used. "
"By default, the \"X Server Information\" page is displayed." },
+ { "list-targets-only", 'L', NVGETOPT_HELP_ALWAYS, NULL,
+ "When performing an attribute query (from the '--query' command line "
+ "option) or an attribute assignment (from the '--assign' command line "
+ "option or when loading an ~/.nvidia-settings-rc file), nvidia-settings "
+ "identifies one or more targets on which to query/assign the attribute.\n"
+ "\n"
+ "'--list-targets-only' will cause nvidia-settings to list the targets on "
+ " which the query/assign operation would have been performed, without "
+ "actually performing the operation(s), and exit." },
+
{ NULL, 0, 0, NULL, NULL},
};
diff --git a/src/parse.c b/src/parse.c
index 1f7d125..7aa50b1 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -39,6 +39,9 @@ static void nv_free_strtoks(char **s, int n);
static int ctoi(const char c);
static int count_number_of_chars(char *o, char d);
+static uint32 display_device_name_to_display_device_mask(const char *str);
+
+
/*
* Table of all attribute names recognized by the attribute string
* parser. Binds attribute names to attribute integers (for use in
@@ -61,6 +64,7 @@ static int count_number_of_chars(char *o, char d);
#define W NV_PARSER_TYPE_VALUE_IS_SWITCH_DISPLAY
#define M NV_PARSER_TYPE_SDI_CSC
#define T NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE
+#define V NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID
const AttributeTableEntry attributeTable[] = {
@@ -88,7 +92,6 @@ const AttributeTableEntry attributeTable[] = {
{ "AssociatedDisplays", NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, N|D, "Display device mask indicating which display devices are \"associated\" with the specified X screen (i.e., are available for displaying the desktop)." },
{ "ProbeDisplays", NV_CTRL_PROBE_DISPLAYS, A|D, "When this attribute is queried, the X driver re-probes the hardware to detect which display devices are connected to the GPU or DPU driving the specified X screen. Returns a display mask of the currently connected display devices." },
{ "InitialPixmapPlacement", NV_CTRL_INITIAL_PIXMAP_PLACEMENT, N, "Controls where X pixmaps are initially created." },
- { "DynamicTwinview", NV_CTRL_DYNAMIC_TWINVIEW, N, "Does the X screen support dynamic TwinView." },
{ "MultiGpuDisplayOwner", NV_CTRL_MULTIGPU_DISPLAY_OWNER, N, "GPU ID of the GPU that has the display device(s) used for showing the X screen." },
{ "HWOverlay", NV_CTRL_HWOVERLAY, 0, "When a workstation overlay is in use, this value is 1 if the hardware overlay is used, or 0 if the overlay is emulated." },
{ "OnDemandVBlankInterrupts", NV_CTRL_ONDEMAND_VBLANK_INTERRUPTS, 0, "Enable/Disable/Query of on-demand vertical blanking interrupt control on the GPU. The 'OnDemandVBlankInterrupts' X server configuration option must be enabled for this option to be available." },
@@ -174,8 +177,9 @@ const AttributeTableEntry attributeTable[] = {
{ "ECCDoubleBitErrors", NV_CTRL_GPU_ECC_DOUBLE_BIT_ERRORS, N, "Returns the number of double-bit ECC errors detected by the targeted GPU since the last POST." },
{ "ECCAggregateDoubleBitErrors", NV_CTRL_GPU_ECC_AGGREGATE_DOUBLE_BIT_ERRORS, N, "Returns the number of double-bit ECC errors detected by the targeted GPU since the last counter reset." },
{ "GPUFanControlState", NV_CTRL_GPU_COOLER_MANUAL_CONTROL, N, "The current fan control state; the value of this attribute controls the availability of additional fan control attributes. Note that this attribute is unavailable unless fan control support has been enabled by setting the \"Coolbits\" X config option." },
- { "GPUCurrentFanSpeed", NV_CTRL_THERMAL_COOLER_LEVEL, N, "Returns the GPU fan's current speed." },
+ { "GPUCurrentFanSpeed", NV_CTRL_THERMAL_COOLER_LEVEL, N, "Returns the GPU fan's currently programmed speed, as a percentage of the maximum speed." },
{ "GPUResetFanSpeed", NV_CTRL_THERMAL_COOLER_LEVEL_SET_DEFAULT, N, "Resets the GPU fan's speed to its default." },
+ { "GPUCurrentFanSpeedRPM", NV_CTRL_THERMAL_COOLER_SPEED, N, "Returns the GPU fan's tachometer-measured speed in rotations per minute (RPM)." },
{ "GPUFanControlType", NV_CTRL_THERMAL_COOLER_CONTROL_TYPE, N, "Returns how the GPU fan is controlled. '1' means the fan can only be toggled on and off; '2' means the fan has variable speed. '0' means the fan is restricted and cannot be adjusted under end user control." },
{ "GPUFanTarget", NV_CTRL_THERMAL_COOLER_TARGET, N, "Returns the objects the fan cools. '1' means the GPU, '2' means video memory, '4' means the power supply, and '7' means all of the above." },
{ "ThermalSensorReading", NV_CTRL_THERMAL_SENSOR_READING, N, "Returns the thermal sensor's current reading." },
@@ -310,6 +314,7 @@ const AttributeTableEntry attributeTable[] = {
{ "RandROutputID", NV_CTRL_DISPLAY_RANDR_OUTPUT_ID, N, "The RandR Output ID that corresponds to the display device." },
{ "FrameLockDisplayConfig", NV_CTRL_FRAMELOCK_DISPLAY_CONFIG, N, "Controls the FrameLock mode of operation for the display device." },
{ "Hdmi3D", NV_CTRL_DPY_HDMI_3D, N, "Returns whether the specified display device is currently using HDMI 3D Frame Packed Stereo mode. If so, the result of refresh rate queries will be doubled." },
+ { "BacklightBrightness", NV_CTRL_BACKLIGHT_BRIGHTNESS, N, "Controls the backlight brightness of an internal panel." },
/* TV */
{ "TVOverScan", NV_CTRL_TV_OVERSCAN, 0, "Adjusts the amount of overscan on the specified display device." },
@@ -320,7 +325,8 @@ const AttributeTableEntry attributeTable[] = {
{ "TVSaturation", NV_CTRL_TV_SATURATION, 0, "Adjusts the amount of saturation on the specified display device." },
/* X Video */
- { "XVideoSyncToDisplay", NV_CTRL_XV_SYNC_TO_DISPLAY, D|Z, "Controls which display device is synced to by the texture and blitter adaptors when they are set to synchronize to the vertical blanking." },
+ { "XVideoSyncToDisplay", NV_CTRL_XV_SYNC_TO_DISPLAY, D|Z|N, "Controls which display device is synced to by the texture and blitter adaptors when they are set to synchronize to the vertical blanking." },
+ { "XVideoSyncToDisplayID", NV_CTRL_XV_SYNC_TO_DISPLAY_ID, V, "Controls which display device is synced to by the texture and blitter adaptors when they are set to synchronize to the vertical blanking." },
/* 3D Vision Pro */
{"3DVisionProResetTransceiverToFactorySettings", NV_CTRL_3D_VISION_PRO_RESET_TRANSCEIVER_TO_FACTORY_SETTINGS, N, "Resets the 3D Vision Pro transceiver to its factory settings."},
@@ -346,6 +352,7 @@ const AttributeTableEntry attributeTable[] = {
{"3DVisionProGlassesFirmwareDateA", NV_CTRL_STRING_3D_VISION_PRO_GLASSES_FIRMWARE_DATE_A, S|N|T, "Returns the date of the firmware of chip A of the glasses."},
{"3DVisionProGlassesAddress", NV_CTRL_STRING_3D_VISION_PRO_GLASSES_ADDRESS, S|N|T, "Returns the RF address of the glasses."},
{"3DVisionProGlassesName", NV_CTRL_STRING_3D_VISION_PRO_GLASSES_NAME, S|N|T, "Controls the name the glasses should use."},
+ {"GPUUtilization", NV_CTRL_STRING_GPU_UTILIZATION, S|N, "Returns the current percentage utilization of the GPU components." },
{ NULL, 0, 0, NULL }
};
@@ -354,7 +361,6 @@ const AttributeTableEntry attributeTable[] = {
#undef C
#undef N
#undef G
-#undef V
#undef P
#undef D
#undef A
@@ -364,6 +370,9 @@ const AttributeTableEntry attributeTable[] = {
#undef S
#undef I
#undef W
+#undef M
+#undef T
+#undef V
/*
* When new integer attributes are added to NVCtrl.h, an entry should
@@ -372,7 +381,7 @@ const AttributeTableEntry attributeTable[] = {
* about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_GPU_POWER_MIZER_DEFAULT_MODE
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_THERMAL_COOLER_SPEED
#warning "Have you forgotten to add a new integer attribute to attributeTable?"
#endif
@@ -845,7 +854,8 @@ int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a)
if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
/* color attributes are floating point */
a->val.f = strtod(s, &tmp);
- } else if (a->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
+ } else if ((a->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) ||
+ (a->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID)) {
a->val.str = strdup(s);
tmp = s + strlen(s);
} else if (a->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
@@ -999,7 +1009,7 @@ int nv_strcasecmp(const char *a, const char *b)
*/
-uint32 display_device_name_to_display_device_mask(const char *str)
+static uint32 display_device_name_to_display_device_mask(const char *str)
{
uint32 mask = 0;
char *s, **toks, *endptr;
@@ -1179,17 +1189,16 @@ char *display_device_mask_to_display_device_name(const uint32 mask)
* mask.
*/
-uint32 expand_display_device_mask_wildcards(const uint32 d, const uint32 e)
+uint32 expand_display_device_mask_wildcards(const uint32 d)
{
uint32 mask = d & VALID_DISPLAY_DEVICES_MASK;
- if (d & DISPLAY_DEVICES_WILDCARD_CRT) mask |= (e & BITMASK_ALL_CRT);
- if (d & DISPLAY_DEVICES_WILDCARD_TV) mask |= (e & BITMASK_ALL_TV);
- if (d & DISPLAY_DEVICES_WILDCARD_DFP) mask |= (e & BITMASK_ALL_DFP);
-
- return mask;
+ if (d & DISPLAY_DEVICES_WILDCARD_CRT) mask |= BITMASK_ALL_CRT;
+ if (d & DISPLAY_DEVICES_WILDCARD_TV) mask |= BITMASK_ALL_TV;
+ if (d & DISPLAY_DEVICES_WILDCARD_DFP) mask |= BITMASK_ALL_DFP;
-} /* expand_display_device_mask_wildcards() */
+ return mask;
+}
diff --git a/src/parse.h b/src/parse.h
index d83cf2c..5ae7baa 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -54,6 +54,7 @@
#define NV_PARSER_TYPE_1000Hz (1<<28)
#define NV_PARSER_TYPE_SDI (1<<29)
#define NV_PARSER_TYPE_SDI_CSC (1<<30)
+#define NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID (1<<31)
#define NV_PARSER_ASSIGNMENT 0
#define NV_PARSER_QUERY 1
@@ -328,9 +329,8 @@ char *replace_characters(const char *o, const char c, const char r);
char *display_device_mask_to_display_device_name(const uint32);
-uint32 display_device_name_to_display_device_mask(const char *);
-uint32 expand_display_device_mask_wildcards(const uint32, const uint32);
+uint32 expand_display_device_mask_wildcards(const uint32);
ParsedAttribute *nv_parsed_attribute_init(void);
diff --git a/src/query-assign.c b/src/query-assign.c
index 95ae6c4..4bee53f 100644
--- a/src/query-assign.c
+++ b/src/query-assign.c
@@ -40,9 +40,12 @@
extern int __verbosity;
extern int __terse;
extern int __display_device_string;
+extern int __list_targets;
/* local prototypes */
+#define PRODUCT_NAME_LEN 64
+
static int process_attribute_queries(int, char**, const char *,
CtrlHandlesArray *);
@@ -252,7 +255,7 @@ static CtrlHandleTarget *nv_get_target(const CtrlHandles *handles,
const CtrlHandleTargets *targets;
int i;
- if (target_type < 0 || target_type >= MAX_TARGET_TYPES) {
+ if (!handles || target_type < 0 || target_type >= MAX_TARGET_TYPES) {
return NULL;
}
@@ -268,6 +271,34 @@ static CtrlHandleTarget *nv_get_target(const CtrlHandles *handles,
}
+/*!
+ * Returns the RandR name of the matching display target from the given
+ * target ID and the list of target handles.
+ *
+ * \param[in] handles Container for all the CtrlHandleTargets to search.
+ * \param[in] target_id The target id of the display CtrlHandleTarget to
+ * search.
+ *
+ * \return Returns the NV_DPY_PROTO_NAME_RANDR name string from the matching
+ * (display) CtrlHandleTarget from CtrlHandles on success; else,
+ * returns NULL.
+ *
+ */
+const char *nv_get_display_target_config_name(const CtrlHandles *handles,
+ int target_id)
+{
+ CtrlHandleTarget *t = nv_get_target(handles,
+ NV_CTRL_TARGET_TYPE_DISPLAY,
+ target_id);
+
+ if (!t) {
+ return NULL;
+ }
+
+ return t->protoNames[NV_DPY_PROTO_NAME_RANDR];
+}
+
+
/*!
* Returns the NvCtrlAttributeHandle from CtrlHandles with the given target
@@ -862,6 +893,126 @@ static int nv_infer_targets_from_specification(ParsedAttribute *a,
}
+/*
+ * nv_init_target() - Given the Display pointer, create an attribute
+ * handle and initialize the handle target.
+ */
+
+static void nv_init_target(Display *dpy, CtrlHandleTarget *t,
+ int target, int targetId)
+{
+ NvCtrlAttributeHandle *handle;
+ ReturnStatus status;
+ char *tmp;
+ int len, d, c;
+
+ /* allocate the handle */
+
+ handle = NvCtrlAttributeInit(dpy,
+ targetTypeTable[target].nvctrl, targetId,
+ NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS);
+
+ t->h = handle;
+
+ /*
+ * silently fail: this might happen if not all X screens
+ * are NVIDIA X screens
+ */
+
+ if (!handle) {
+ return;
+ }
+
+ /*
+ * get a name for this target; in the case of
+ * X_SCREEN_TARGET targets, just use the string returned
+ * from NvCtrlGetDisplayName(); for other target types,
+ * append a target specification.
+ */
+
+ tmp = NvCtrlGetDisplayName(t->h);
+
+ if (target == X_SCREEN_TARGET) {
+ t->name = tmp;
+ } else {
+ len = strlen(tmp) + strlen(targetTypeTable[target].parsed_name) + 16;
+ t->name = nvalloc(len);
+
+ if (t->name) {
+ snprintf(t->name, len, "%s[%s:%d]",
+ tmp, targetTypeTable[target].parsed_name, targetId);
+ free(tmp);
+ } else {
+ t->name = tmp;
+ }
+ }
+
+ load_target_proto_names(t);
+ t->relations = nv_target_list_init();
+
+ /*
+ * get the enabled display device mask; for X screens and
+ * GPUs we query NV-CONTROL; for anything else
+ * (framelock), we just assign this to 0.
+ */
+
+ if (targetTypeTable[target].uses_display_devices) {
+
+ status = NvCtrlGetAttribute(t->h,
+ NV_CTRL_ENABLED_DISPLAYS, &d);
+
+ if (status != NvCtrlSuccess) {
+ nv_error_msg("Error querying enabled displays on "
+ "%s %d (%s).", targetTypeTable[target].name, targetId,
+ NvCtrlAttributesStrError(status));
+ d = 0;
+ }
+
+ status = NvCtrlGetAttribute(t->h,
+ NV_CTRL_CONNECTED_DISPLAYS, &c);
+
+ if (status != NvCtrlSuccess) {
+ nv_error_msg("Error querying connected displays on "
+ "%s %d (%s).", targetTypeTable[target].name, targetId,
+ NvCtrlAttributesStrError(status));
+ c = 0;
+ }
+ } else {
+ d = 0;
+ c = 0;
+ }
+
+ t->d = d;
+ t->c = c;
+
+}
+
+
+/*
+ * nv_add_ctrl_handle_target() - add a CtrlHandleTarget to the array
+ * of Targets for the given target_index. This is used for dynamically
+ * created targets that don't exist when the CtrlHandles are initialized.
+ */
+
+NvCtrlAttributeHandle *nv_add_target(CtrlHandles *handles, Display *dpy,
+ int target_index, int display_id)
+{
+ CtrlHandleTargets *dt;
+ CtrlHandleTarget *t;
+
+ if (!handles) {
+ return NULL;
+ }
+
+ dt = &handles->targets[target_index];
+
+ dt->t = nvrealloc(dt->t, (dt->n+1) * sizeof(CtrlHandleTarget));
+ t = &dt->t[dt->n];
+ dt->n++;
+
+ nv_init_target(dpy, t, target_index, display_id);
+ return t->h;
+}
/*
* nv_alloc_ctrl_handles() - allocate a new CtrlHandles structure,
@@ -874,9 +1025,7 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
{
ReturnStatus status;
CtrlHandles *h, *pQueryHandle = NULL;
- NvCtrlAttributeHandle *handle;
- int i, j, val, d, c, len;
- char *tmp;
+ int i, j, val, len;
int *pData = NULL;
/* allocate the CtrlHandles struct */
@@ -1023,92 +1172,16 @@ CtrlHandles *nv_alloc_ctrl_handles(const char *display)
targetId = i;
}
- /* allocate the handle */
-
- handle = NvCtrlAttributeInit(h->dpy,
- targetTypeEntry->nvctrl, targetId,
- NV_CTRL_ATTRIBUTES_ALL_SUBSYSTEMS);
-
- t->h = handle;
-
- /*
- * silently fail: this might happen if not all X screens
- * are NVIDIA X screens
- */
-
- if (!handle) {
- continue;
- }
-
- /*
- * get a name for this target; in the case of
- * X_SCREEN_TARGET targets, just use the string returned
- * from NvCtrlGetDisplayName(); for other target types,
- * append a target specification.
- */
-
- tmp = NvCtrlGetDisplayName(handle);
-
- if (target == X_SCREEN_TARGET) {
- t->name = tmp;
- } else {
- len = strlen(tmp) + strlen(targetTypeEntry->parsed_name) +16;
- t->name = nvalloc(len);
-
- if (t->name) {
- snprintf(t->name, len, "%s[%s:%d]",
- tmp, targetTypeEntry->parsed_name, targetId);
- free(tmp);
- } else {
- t->name = tmp;
- }
- }
-
- load_target_proto_names(t);
- t->relations = nv_target_list_init();
-
+ nv_init_target(h->dpy, t, target, targetId);
/*
- * get the enabled display device mask; for X screens and
- * GPUs we query NV-CONTROL; for anything else
- * (framelock), we just assign this to 0.
+ * store this handle, if it exists, so that we can use it to
+ * query other target counts later
*/
- if (targetTypeEntry->uses_display_devices) {
-
- status = NvCtrlGetAttribute(handle,
- NV_CTRL_ENABLED_DISPLAYS, &d);
-
- if (status != NvCtrlSuccess) {
- nv_error_msg("Error querying enabled displays on "
- "%s %d (%s).", targetTypeEntry->name, i,
- NvCtrlAttributesStrError(status));
- d = 0;
- }
-
- status = NvCtrlGetAttribute(handle,
- NV_CTRL_CONNECTED_DISPLAYS, &c);
-
- if (status != NvCtrlSuccess) {
- nv_error_msg("Error querying connected displays on "
- "%s %d (%s).", targetTypeEntry->name, i,
- NvCtrlAttributesStrError(status));
- c = 0;
- }
- } else {
- d = 0;
- c = 0;
+ if (!pQueryHandle && t->h) {
+ pQueryHandle = t->h;
}
-
- t->d = d;
- t->c = c;
-
- /*
- * store this handle so that we can use it to query other
- * target counts later
- */
-
- if (!pQueryHandle) pQueryHandle = handle;
}
next_target_type:
@@ -1281,19 +1354,21 @@ static void include_target_idx_targets(ParsedAttribute *a, const CtrlHandles *h,
/*!
* Queries the permissions for the given attribute.
- * \param[in] a The attribute to query permissions for.
+ *
* \param[in] h CtrlHandles used to communicate with the X server.
+ * \param[in] attr The attribute to query permissions for.
+ * \param[in] flags The attribute flags to query permissions for.
* \param[out] perms The permissions of the attribute.
*
* \return Returns TRUE if the permissions were queried successfully; else,
* returns FALSE.
*/
-static Bool query_attribute_perms(ParsedAttribute *a, CtrlHandles *h,
- NVCTRLAttributePermissionsRec *perms)
+Bool nv_get_attribute_perms(CtrlHandles *h, int attr, uint32 flags,
+ NVCTRLAttributePermissionsRec *perms)
{
memset(perms, 0, sizeof(*perms));
- if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
+ if (flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
/* Allow non NV-CONTROL attributes to be read/written on X screen
* targets
*/
@@ -1306,11 +1381,11 @@ static Bool query_attribute_perms(ParsedAttribute *a, CtrlHandles *h,
return NV_TRUE;
}
- if (a->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
- return XNVCTRLQueryStringAttributePermissions(h->dpy, a->attr, perms);
+ if (flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
+ return XNVCTRLQueryStringAttributePermissions(h->dpy, attr, perms);
}
- return XNVCTRLQueryAttributePermissions(h->dpy, a->attr, perms);
+ return XNVCTRLQueryAttributePermissions(h->dpy, attr, perms);
}
@@ -1322,6 +1397,10 @@ static Bool query_attribute_perms(ParsedAttribute *a, CtrlHandles *h,
* the target type and target id are used. If nothing is specified, all the
* valid targets for the attribute are included.
*
+ * If this is a display attribute, and a (legacy) display mask string is given,
+ * all non-display targets are further resolved into the corresponding display
+ * targets that match the names represented by the display mask string.
+ *
* \param[in/out] a ParsedAttribute to resolve.
* \param[in] h CtrlHandles to resolve the target specification against.
*
@@ -1344,9 +1423,16 @@ static int resolve_attribute_targets(ParsedAttribute *a, CtrlHandles *h)
return NV_PARSER_STATUS_BAD_ARGUMENT;
}
- a->targets = nv_target_list_init();
+
+ status = nv_get_attribute_perms(h, a->attr, a->flags, &perms);
+ if (!status) {
+ // XXX Throw other error here...?
+ return NV_PARSER_STATUS_TARGET_SPEC_NO_TARGETS;
+ }
+ a->targets = nv_target_list_init();
+
/* If a target specification string was given, use that to determine the
* list of targets to include.
@@ -1390,12 +1476,6 @@ static int resolve_attribute_targets(ParsedAttribute *a, CtrlHandles *h)
/* If no target type was given, assume all the appropriate targets for the
* attribute by querying its permissions.
*/
- status = query_attribute_perms(a, h, &perms);
- if (!status) {
- // XXX Throw other error here...?
- return NV_PARSER_STATUS_TARGET_SPEC_NO_TARGETS;
- }
-
for (i = 0; i < MAX_TARGET_TYPES; i++) {
int permBit = targetTypeTable[i].permission_bit;
@@ -1407,8 +1487,100 @@ static int resolve_attribute_targets(ParsedAttribute *a, CtrlHandles *h)
include_target_idx_targets(a, h, i);
}
-
done:
+
+ /* If this attribute is a display attribute, include the related display
+ * targets of the (resolved) non display targets. If a display mask is
+ * specified via either name string or value, use that to limit the
+ * displays added, otherwise include all related display targets.
+ */
+ if (!(a->flags & NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE) &&
+ (perms.permissions & ATTRIBUTE_TYPE_DISPLAY)) {
+ CtrlHandleTargetNode *head = nv_target_list_init();
+ CtrlHandleTargetNode *n;
+
+ uint32 display_mask;
+ int bit, i;
+
+ char *name_list[32];
+ int num_names = 0;
+
+
+ /* Convert user string into display device mask */
+ if (a->flags & NV_PARSER_HAS_DISPLAY_DEVICE) {
+ display_mask =
+ expand_display_device_mask_wildcards(a->display_device_mask);
+ } else {
+ display_mask = VALID_DISPLAY_DEVICES_MASK;
+ }
+
+ /* Convert the bitmask into a list of names */
+ for (bit = 0; bit < 24; bit++) {
+ uint32 mask = (1 << bit);
+
+ if (!(mask & display_mask)) {
+ continue;
+ }
+
+ name_list[num_names] = display_device_mask_to_display_device_name(mask);
+ if (name_list[num_names]) {
+ num_names++;
+ }
+ }
+
+ /* Look at attribute's target list... */
+ for (n = a->targets; n->next; n = n->next) {
+ CtrlHandleTarget *t = n->t;
+ CtrlHandleTargetNode *n_other;
+ int target_type;
+
+ if (!t->h) {
+ continue;
+ }
+
+ target_type = NvCtrlGetTargetType(t->h);
+
+ /* Include display targets */
+ if (target_type == NV_CTRL_TARGET_TYPE_DISPLAY) {
+ /* Make sure to include display targets in final list */
+ nv_target_list_add(head, t);
+ continue;
+ }
+
+ /* Include non-display target's related display targets, if any */
+ for (n_other = t->relations;
+ n_other->next;
+ n_other = n_other->next) {
+ CtrlHandleTarget *t_other = n_other->t;
+
+ if (!t_other->h) {
+ continue;
+ }
+ target_type = NvCtrlGetTargetType(t_other->h);
+ if (target_type != NV_CTRL_TARGET_TYPE_DISPLAY) {
+ continue;
+ }
+
+ for (i = 0; i < num_names; i++) {
+ if (nv_strcasecmp(name_list[i],
+ t_other->protoNames[NV_DPY_PROTO_NAME_TYPE_ID])) {
+ nv_target_list_add(head, t_other);
+ break;
+ }
+ }
+ }
+ }
+
+ /* Cleanup */
+ for (i = 0; i < num_names; i++) {
+ nvfree(name_list[i]);
+ }
+
+ /* Apply the new targets list */
+ nv_target_list_free(a->targets);
+ a->targets = head;
+ }
+
/* Make sure at least one target was resolved */
if (ret == NV_PARSER_STATUS_SUCCESS) {
if (!(a->flags & NV_PARSER_HAS_TARGET)) {
@@ -1885,7 +2057,8 @@ typedef enum {
VerboseLevelVerbose,
} VerboseLevel;
-static void print_queried_value(CtrlHandleTarget *t,
+static void print_queried_value(const CtrlHandles *handles,
+ CtrlHandleTarget *t,
NVCTRLAttributeValidValuesRec *v,
int val,
uint32 flags,
@@ -1898,7 +2071,15 @@ static void print_queried_value(CtrlHandleTarget *t,
/* assign val_str */
- if ((flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY) &&
+ if ((flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID) &&
+ (__display_device_string)) {
+ const char *name = nv_get_display_target_config_name(handles, val);
+ if (name) {
+ snprintf(val_str, 64, "%s", name);
+ } else {
+ snprintf(val_str, 64, "%d", val);
+ }
+ } else if ((flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY) &&
(__display_device_string)) {
tmp_d_str = display_device_mask_to_display_device_name(val);
snprintf(val_str, 64, "%s", tmp_d_str);
@@ -2141,8 +2322,8 @@ static int query_all(const char *display_name, CtrlHandlesArray *handles_array)
goto exit_bit_loop;
}
- print_queried_value(t, &valid, val, a->flags, a->name,
- mask, INDENT, __terse ?
+ print_queried_value(h, t, &valid, val, a->flags,
+ a->name, mask, INDENT, __terse ?
VerboseLevelAbbreviated :
VerboseLevelVerbose);
@@ -2178,68 +2359,54 @@ exit_bit_loop:
/*
- * print_target_display_connections() - Print a list of all the
- * display devices connected to the given target (GPU/X Screen)
+ * get_product_name() Returns the (GPU, X screen, display device or VCS)
+ * product name of the given target.
*/
-static int print_target_display_connections(CtrlHandleTarget *t)
+static char * get_product_name(NvCtrlAttributeHandle *h, int attr)
{
- unsigned int bit;
- char *tmp_d_str, *name;
+ char *product_name;
ReturnStatus status;
- int plural;
-
- if (t->c == 0) {
- nv_msg(" ", "Is not connected to any display devices.");
- nv_msg(NULL, "");
- return NV_TRUE;
- }
-
- plural = (t->c & (t->c - 1)); /* Is more than one bit set? */
- nv_msg(" ", "Is connected to the following display device%s:",
- plural ? "s" : "");
-
- for (bit = 1; bit; bit <<= 1) {
- if (!(bit & t->c)) continue;
-
- status =
- NvCtrlGetStringDisplayAttribute(t->h, bit,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &name);
- if (status != NvCtrlSuccess) name = strdup("Unknown");
-
- tmp_d_str = display_device_mask_to_display_device_name(bit);
- nv_msg(" ", "%s (%s: 0x%.8X)", name, tmp_d_str, bit);
-
- free(name);
- free(tmp_d_str);
- }
- nv_msg(NULL, "");
+ status = NvCtrlGetStringAttribute(h, attr, &product_name);
- return NV_TRUE;
+ if (status != NvCtrlSuccess) return strdup("Unknown");
-} /* print_target_display_connections() */
+ return product_name;
+}
/*
- * get_product_name() Returns the (GPU, X screen, display device or VCS)
- * product name of the given target.
+ * Returns the (RandR) display device name to use for printing the given
+ * display target. If 'show_connected_state' is true, "connected" will be
+ * appended to the name.
*/
-static char * get_product_name(NvCtrlAttributeHandle *h, int attr)
+static void get_display_product_name(CtrlHandleTarget *t, char *buf, int len,
+ Bool show_connect_state)
{
- char *product_name;
- ReturnStatus status;
+ const CtrlHandleTargetNode *n;
+ const char *connected_str = "";
- status = NvCtrlGetStringAttribute(h, attr, &product_name);
+ /* Check to see if display is connected (has a GPU relation) */
+ if (show_connect_state) {
+ for (n = t->relations;
+ n->next;
+ n = n->next) {
+ int target_type = NvCtrlGetTargetType(n->t->h);
- if (status != NvCtrlSuccess) return strdup("Unknown");
-
- return product_name;
+ if (target_type == NV_CTRL_TARGET_TYPE_GPU) {
+ connected_str = ") (connected";
+ break;
+ }
+ }
+ }
-} /* get_product_name() */
+ snprintf(buf, len, "%s%s",
+ t->protoNames[NV_DPY_PROTO_NAME_RANDR],
+ connected_str);
+}
@@ -2251,6 +2418,7 @@ static char * get_product_name(NvCtrlAttributeHandle *h, int attr)
static int print_target_connections(CtrlHandles *h,
CtrlHandleTarget *t,
+ const char *relation_str,
unsigned int attrib,
unsigned int target_index)
{
@@ -2259,6 +2427,12 @@ static int print_target_connections(CtrlHandles *h,
ReturnStatus status;
char *product_name;
char *target_name;
+ const TargetTypeEntry *targetTypeEntry;
+ Bool show_dpy_connection_state =
+ (attrib == NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN) ?
+ NV_TRUE : NV_FALSE;
+
+ targetTypeEntry = &(targetTypeTable[target_index]);
/* Query the connected targets */
@@ -2270,45 +2444,45 @@ static int print_target_connections(CtrlHandles *h,
if (status != NvCtrlSuccess) return NV_FALSE;
if (pData[0] == 0) {
- nv_msg(" ", "Is not connected to any %s.",
- targetTypeTable[target_index].name);
+ nv_msg(" ", "Is not %s any %s.",
+ relation_str,
+ targetTypeEntry->name);
nv_msg(NULL, "");
XFree(pData);
return NV_TRUE;
}
- nv_msg(" ", "Is connected to the following %s%s:",
- targetTypeTable[target_index].name,
+ nv_msg(" ", "Is %s the following %s%s:",
+ relation_str,
+ targetTypeEntry->name,
((pData[0] > 1) ? "s" : ""));
-
/* List the connected targets */
for (i = 1; i <= pData[0]; i++) {
-
- if (pData[i] >= 0 &&
- pData[i] < h->targets[target_index].n) {
+ CtrlHandleTarget *target =
+ nv_get_target(h, targetTypeEntry->nvctrl, pData[i]);
- target_name = h->targets[target_index].t[ pData[i] ].name;
+ if (target) {
+ target_name = target->name;
switch (target_index) {
case GPU_TARGET:
product_name =
- get_product_name(h->targets[target_index].t[ pData[i] ].h,
- NV_CTRL_STRING_PRODUCT_NAME);
+ get_product_name(target->h, NV_CTRL_STRING_PRODUCT_NAME);
break;
-
+
case VCS_TARGET:
product_name =
- get_product_name(h->targets[target_index].t[ pData[i] ].h,
+ get_product_name(target->h,
NV_CTRL_STRING_VCSC_PRODUCT_NAME);
break;
case DISPLAY_TARGET:
- product_name =
- get_product_name(h->targets[target_index].t[ pData[i] ].h,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME);
+ product_name = nvalloc(PRODUCT_NAME_LEN);
+ get_display_product_name(target, product_name, PRODUCT_NAME_LEN,
+ show_dpy_connection_state);
break;
case NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET:
@@ -2328,17 +2502,17 @@ static int print_target_connections(CtrlHandles *h,
}
if (!target_name) {
- nv_msg(" ", "[?] Unknown %s",
- targetTypeTable[target_index].name);
+ nv_msg(" ", "Unknown %s",
+ targetTypeEntry->name);
} else if (product_name) {
- nv_msg(" ", "[%d] %s (%s)",
- pData[i], target_name, product_name);
+ nv_msg(" ", "%s (%s)",
+ target_name, product_name);
} else {
- nv_msg(" ", "[%d] %s (%s %d)",
- pData[i], target_name,
- targetTypeTable[target_index].name,
+ nv_msg(" ", "%s (%s %d)",
+ target_name,
+ targetTypeEntry->name,
pData[i]);
}
@@ -2402,7 +2576,7 @@ static int query_all_targets(const char *display_name, const int target_index,
/* print information per target */
for (i = 0; i < h->targets[target_index].n; i++) {
- char product_name[32];
+ char product_name[PRODUCT_NAME_LEN];
Bool is_x_name = NV_FALSE;
char *x_name = NULL;
@@ -2410,21 +2584,26 @@ static int query_all_targets(const char *display_name, const int target_index,
str = NULL;
if (target_index == NVIDIA_3D_VISION_PRO_TRANSCEIVER_TARGET) {
- snprintf(product_name, 32, "3D Vision Pro Transceiver %d", i);
+ snprintf(product_name, PRODUCT_NAME_LEN,
+ "3D Vision Pro Transceiver %d", i);
} else if (target_index == THERMAL_SENSOR_TARGET) {
- snprintf(product_name, 32, "Thermal Sensor %d", i);
+ snprintf(product_name, PRODUCT_NAME_LEN,
+ "Thermal Sensor %d", i);
} else if (target_index == COOLER_TARGET) {
- snprintf(product_name, 32, "Fan %d", i);
+ snprintf(product_name, PRODUCT_NAME_LEN,
+ "Fan %d", i);
} else if (target_index == FRAMELOCK_TARGET) {
- snprintf(product_name, 32, "Quadro Sync %d", i);
+ snprintf(product_name, PRODUCT_NAME_LEN,
+ "Quadro Sync %d", i);
} else if (target_index == VCS_TARGET) {
x_name = get_product_name(t->h, NV_CTRL_STRING_VCSC_PRODUCT_NAME);
is_x_name = NV_TRUE;
} else if (target_index == GVI_TARGET) {
- snprintf(product_name, 32, "SDI Input %d", i);
+ snprintf(product_name, PRODUCT_NAME_LEN,
+ "SDI Input %d", i);
} else if (target_index == DISPLAY_TARGET) {
- x_name = get_product_name(t->h, NV_CTRL_STRING_DISPLAY_DEVICE_NAME);
- is_x_name = NV_TRUE;
+ get_display_product_name(t, product_name, PRODUCT_NAME_LEN,
+ NV_FALSE);
} else {
x_name = get_product_name(t->h, NV_CTRL_STRING_PRODUCT_NAME);
is_x_name = NV_TRUE;
@@ -2452,59 +2631,82 @@ static int query_all_targets(const char *display_name, const int target_index,
/* Print connectivity information */
if (__verbosity >= VERBOSITY_ALL) {
- if (targetTypeEntry->uses_display_devices) {
- print_target_display_connections(t);
- }
-
switch (target_index) {
case GPU_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU,
+ (h, t,
+ "driving",
+ NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU,
X_SCREEN_TARGET);
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU,
+ DISPLAY_TARGET);
+ print_target_connections
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_FRAMELOCKS_USED_BY_GPU,
FRAMELOCK_TARGET);
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_VCSCS_USED_BY_GPU,
VCS_TARGET);
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU,
COOLER_TARGET);
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
THERMAL_SENSOR_TARGET);
- print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_DISPLAYS_CONNECTED_TO_GPU,
- GPU_TARGET);
break;
case X_SCREEN_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
+ (h, t,
+ "driven by",
+ NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
GPU_TARGET);
+ print_target_connections
+ (h, t,
+ "assigned",
+ NV_CTRL_BINARY_DATA_DISPLAYS_ASSIGNED_TO_XSCREEN,
+ DISPLAY_TARGET);
break;
case FRAMELOCK_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK,
GPU_TARGET);
break;
case VCS_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_GPUS_USING_VCSC,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_GPUS_USING_VCSC,
GPU_TARGET);
break;
case COOLER_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_COOLERS_USED_BY_GPU,
COOLER_TARGET);
break;
case THERMAL_SENSOR_TARGET:
print_target_connections
- (h, t, NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
+ (h, t,
+ "connected to",
+ NV_CTRL_BINARY_DATA_THERMAL_SENSORS_USED_BY_GPU,
THERMAL_SENSOR_TARGET);
break;
@@ -2528,7 +2730,8 @@ static int query_all_targets(const char *display_name, const int target_index,
* returned; if successful, NV_TRUE is returned.
*/
-static int process_parsed_attribute_internal(CtrlHandleTarget *t,
+static int process_parsed_attribute_internal(const CtrlHandles *handles,
+ CtrlHandleTarget *t,
ParsedAttribute *a, uint32 d,
int target_type, int assign,
int verbose, char *whence,
@@ -2620,8 +2823,8 @@ static int process_parsed_attribute_internal(CtrlHandleTarget *t,
NvCtrlAttributesStrError(status));
return NV_FALSE;
} else {
- print_queried_value(t, &valid, a->val.i, a->flags, a->name, d,
- " ", __terse ?
+ print_queried_value(handles, t, &valid, a->val.i, a->flags,
+ a->name, d, " ", __terse ?
VerboseLevelTerse : VerboseLevelVerbose);
print_valid_values(a->name, a->attr, a->flags, valid);
}
@@ -2688,11 +2891,12 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
int assign, int verbose,
char *whence_fmt, ...)
{
- int bit, ret, val;
+ int ret, val;
char *whence, *tmp_d_str0, *tmp_d_str1;
- uint32 display_devices;
ReturnStatus status;
CtrlHandleTargetNode *n;
+ NVCTRLAttributeValidValuesRec valid;
+
val = NV_FALSE;
@@ -2731,61 +2935,36 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
CtrlHandleTarget *t = n->t;
int target_type;
- const TargetTypeEntry *targetTypeEntry;
+ uint32 mask;
if (!t->h) continue; /* no handle on this target; silently skip */
target_type = NvCtrlGetTargetType(t->h);
- targetTypeEntry = nv_get_target_type_entry_by_nvctrl(target_type);
- /* validate any specified display device mask */
- if ((a->flags & NV_PARSER_HAS_DISPLAY_DEVICE) &&
- !(a->flags & NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE)) {
+ if (__list_targets) {
+ const char *name = t->protoNames[0];
+ const char *randr_name = NULL;
- /* Expand any wildcards in the display device mask */
-
- display_devices = expand_display_device_mask_wildcards
- (a->display_device_mask, t->d);
-
- if ((display_devices == 0) || (display_devices & ~t->d)) {
-
- /*
- * use a->display_device_mask rather than
- * display_devices when building the string (so that
- * display_device_mask_to_display_device_name() can
- * use wildcards if present).
- */
+ if (target_type == NV_CTRL_TARGET_TYPE_DISPLAY) {
+ name = t->protoNames[NV_DPY_PROTO_NAME_TARGET_INDEX];
+ randr_name =t->protoNames[NV_DPY_PROTO_NAME_RANDR];
+ }
- tmp_d_str0 = display_device_mask_to_display_device_name
- (a->display_device_mask);
- tmp_d_str1 = display_device_mask_to_display_device_name(t->d);
+ nv_msg(TAB, "%s '%s' on %s%s%s%s\n",
+ assign ? "Assign" : "Query",
+ a->name,
+ name,
+ randr_name ? " (" : "",
+ randr_name ? randr_name : "",
+ randr_name ? ")" : ""
+ );
+ continue;
+ }
- if (tmp_d_str1 && (*tmp_d_str1 != '\0')) {
- nv_error_msg("Invalid display device %s specified "
- "%s (the currently enabled display devices "
- "are %s on %s).",
- tmp_d_str0, whence, tmp_d_str1, t->name);
- } else {
- nv_error_msg("Invalid display device %s specified "
- "%s (there are currently no enabled display "
- "devices on %s).",
- tmp_d_str0, whence, t->name);
- }
- free(tmp_d_str0);
- free(tmp_d_str1);
-
- goto done;
- }
-
- } else {
- /* Just use the display device mask for this target */
- display_devices = t->d;
- }
-
/* special case the color attributes */
-
+
if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
float v[3];
if (!assign) {
@@ -2816,7 +2995,7 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
/*
* If we are assigning, and the value for this attribute is a
- * display device, then we need to validate the value against
+ * display device mask, then we need to validate the value against
* either the mask of enabled display devices or the mask of
* connected display devices.
*/
@@ -2871,6 +3050,79 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
}
}
+
+ /*
+ * If we are assigning, and the value for this attribute is a display
+ * device id/name string, then we need to validate and convert the
+ * given string against list of available display devices. The resulting
+ * id, if any, is then fed back into the ParsedAttrinute's value as an
+ * int which is ultimately written out to NV-CONTROL.
+ */
+ if (assign && (a->flags & NV_PARSER_TYPE_VALUE_IS_DISPLAY_ID)) {
+ CtrlHandleTargets *dpy_targets = &(h->targets[DISPLAY_TARGET]);
+ int i;
+ int found = NV_FALSE;
+ int multi_match = NV_FALSE;
+ int is_id;
+ char *tmp = NULL;
+ int id;
+
+
+ /* See if value is a simple number */
+ id = strtol(a->val.str, &tmp, 0);
+ is_id = (tmp &&
+ (tmp != a->val.str) &&
+ (*tmp == '\0'));
+
+ for (i = 0; i < dpy_targets->n; i++) {
+ CtrlHandleTarget *dpy_target = dpy_targets->t + i;
+
+ if (is_id) {
+ /* Value given as display device (target) ID */
+ if (id == NvCtrlGetTargetId(dpy_target->h)) {
+ found = NV_TRUE;
+ break;
+ }
+ } else {
+ /* Value given as display device name */
+ if (nv_target_has_name(dpy_target, a->val.str)) {
+ if (found) {
+ multi_match = TRUE;
+ break;
+ }
+ id = NvCtrlGetTargetId(dpy_target->h);
+ found = NV_TRUE;
+
+ /* Keep looking to make sure the name doesn't alias to
+ * another display device.
+ */
+ continue;
+ }
+ }
+ }
+
+ if (multi_match) {
+ nv_error_msg("The attribute '%s' specified %s cannot be "
+ "assigned the value of '%s' (This name matches "
+ "multiple display devices, please use a non-"
+ "ambiguous name.",
+ a->name, whence, a->val.str);
+ continue;
+ }
+
+ if (!found) {
+ nv_error_msg("The attribute '%s' specified %s cannot be "
+ "assigned the value of '%s' (This does not "
+ "name an available display device).",
+ a->name, whence, a->val.str);
+ continue;
+ }
+
+ /* Put converted id back into a->val */
+ a->val.i = id;
+ }
+
+
/*
* If we are assigning, and the value for this attribute is
* not allowed to be zero, check that the value is not zero.
@@ -3070,84 +3322,63 @@ int nv_process_parsed_attribute(ParsedAttribute *a, CtrlHandles *h,
}
- /* loop over the display devices */
-
- for (bit = 0; bit < 24; bit++) {
- uint32 mask;
- NVCTRLAttributeValidValuesRec valid;
-
-
- mask = (1 << bit);
-
- if (((mask & display_devices) == 0x0) &&
- (targetTypeEntry->uses_display_devices) &&
- (t->d)) {
- continue;
- }
+ /*
+ * special case the display device mask in the case that it
+ * was "hijacked" for something other than a display device:
+ * assign mask here so that it will be passed through to
+ * process_parsed_attribute_internal() unfiltered
+ */
- /*
- * special case the display device mask in the case that it
- * was "hijacked" for something other than a display device:
- * assign mask here so that it will be passed through to
- * process_parsed_attribute_internal() unfiltered
- */
+ if (a->flags & NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE) {
+ mask = a->display_device_mask;
+ } else {
+ mask = 0;
+ }
- if (a->flags & NV_PARSER_TYPE_HIJACK_DISPLAY_DEVICE) {
- mask = a->display_device_mask;
- }
+ if (a->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
+ status = NvCtrlGetValidStringDisplayAttributeValues(t->h,
+ mask,
+ a->attr,
+ &valid);
+ } else {
+ status = NvCtrlGetValidDisplayAttributeValues(t->h,
+ mask,
+ a->attr,
+ &valid);
+ }
- if (a->flags & NV_PARSER_TYPE_STRING_ATTRIBUTE) {
- status = NvCtrlGetValidStringDisplayAttributeValues(t->h, mask, a->attr, &valid);
+ if (status != NvCtrlSuccess) {
+ if (status == NvCtrlAttributeNotAvailable) {
+ nv_warning_msg("Attribute '%s' specified %s is not "
+ "available on %s.",
+ a->name, whence, t->name);
} else {
- status = NvCtrlGetValidDisplayAttributeValues(t->h, mask, a->attr, &valid);
- }
-
- if (status != NvCtrlSuccess) {
- if (status == NvCtrlAttributeNotAvailable) {
- nv_warning_msg("Attribute '%s' specified %s is not "
- "available on %s.",
- a->name, whence, t->name);
- } else {
- nv_error_msg("Error querying valid values for attribute "
- "'%s' on %s specified %s (%s).",
- a->name, t->name, whence,
- NvCtrlAttributesStrError(status));
- }
- goto done;
- }
-
- /*
- * if this attribute is going to be assigned, then check
- * that the attribute is writable; if it's not, give up
- */
-
- if ((assign) && (!(valid.permissions & ATTRIBUTE_TYPE_WRITE))) {
- nv_error_msg("The attribute '%s' specified %s cannot be "
- "assigned (it is a read-only attribute).",
- a->name, whence);
- goto done;
+ nv_error_msg("Error querying valid values for attribute "
+ "'%s' on %s specified %s (%s).",
+ a->name, t->name, whence,
+ NvCtrlAttributesStrError(status));
}
+ continue;
+ }
- ret = process_parsed_attribute_internal(t, a, mask, target_type,
- assign, verbose, whence,
- valid);
- if (ret == NV_FALSE) goto done;
-
- /*
- * if this attribute is not per-display device, or this
- * target does not know about display devices, or this target
- * does not have display devices, then once through this loop
- * is enough.
- */
-
- if ((!(valid.permissions & ATTRIBUTE_TYPE_DISPLAY)) ||
- (!(targetTypeEntry->uses_display_devices)) ||
- (!(t->d))) {
- break;
- }
+ /*
+ * if this attribute is going to be assigned, then check
+ * that the attribute is writable; if it's not, give up
+ */
- } /* bit */
+ if (assign && !(valid.permissions & ATTRIBUTE_TYPE_WRITE)) {
+ nv_error_msg("The attribute '%s' specified %s cannot be "
+ "assigned (it is a read-only attribute).",
+ a->name, whence);
+ continue;
+ }
+ ret = process_parsed_attribute_internal(h, t, a, mask, target_type,
+ assign, verbose, whence,
+ valid);
+ if (ret == NV_FALSE) {
+ continue;
+ }
} /* done looping over requested targets */
val = NV_TRUE;
diff --git a/src/query-assign.h b/src/query-assign.h
index 28e210c..6cc1538 100644
--- a/src/query-assign.h
+++ b/src/query-assign.h
@@ -105,8 +105,18 @@ NvCtrlAttributeHandle *nv_get_target_handle(const CtrlHandles *handles,
int target_type,
int target_id);
+Bool nv_get_attribute_perms(CtrlHandles *h, int attr, uint32 flags,
+ NVCTRLAttributePermissionsRec *perms);
+
int nv_process_parsed_attribute(ParsedAttribute*, CtrlHandles *h,
int, int, char*, ...) NV_ATTRIBUTE_PRINTF(5, 6);
void nv_target_list_free(CtrlHandleTargetNode *head);
+
+NvCtrlAttributeHandle *nv_add_target(CtrlHandles *handles, Display *dpy,
+ int target_index, int display_id);
+
+const char *nv_get_display_target_config_name(const CtrlHandles *handles,
+ int target_id);
+
#endif /* __QUERY_ASSIGN_H__ */
diff --git a/src/version.mk b/src/version.mk
index 8a89afe..2abb57a 100644
--- a/src/version.mk
+++ b/src/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 325.15
+NVIDIA_VERSION = 331.13
diff --git a/utils.mk b/utils.mk
index 54b76d6..ce645c7 100644
--- a/utils.mk
+++ b/utils.mk
@@ -31,7 +31,7 @@ LD ?= ld
# only set these warnings and optimizations if CFLAGS is unset
CFLAGS ?= -Wall -O2
# always set these -f CFLAGS
-CFLAGS += -fno-strict-aliasing -fno-omit-frame-pointer
+CFLAGS += -fno-strict-aliasing -fno-omit-frame-pointer -Wformat=2
CC_ONLY_CFLAGS ?=
LDFLAGS ?=
BIN_LDFLAGS ?=
diff --git a/version.mk b/version.mk
index 8a89afe..2abb57a 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 325.15
+NVIDIA_VERSION = 331.13