summaryrefslogtreecommitdiff
path: root/samples/nv-control-framelock.c
diff options
context:
space:
mode:
Diffstat (limited to 'samples/nv-control-framelock.c')
-rw-r--r--samples/nv-control-framelock.c567
1 files changed, 567 insertions, 0 deletions
diff --git a/samples/nv-control-framelock.c b/samples/nv-control-framelock.c
new file mode 100644
index 0000000..2e251ee
--- /dev/null
+++ b/samples/nv-control-framelock.c
@@ -0,0 +1,567 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2006 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+
+/*
+ * nv-control-framelock.c - NV-CONTROL client that demonstrates how to
+ * interact with the frame lock capabilities on an X Server.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <X11/Xlib.h>
+
+#include "NVCtrl.h"
+#include "NVCtrlLib.h"
+
+
+/*
+ * do_help()
+ *
+ * Prints some help on how to use this app.
+ *
+ */
+static void do_help(void)
+{
+ printf("usage:\n");
+ printf("-q: query system frame lock information.\n");
+ printf("-e: enable frame lock on system.\n");
+ printf("-d: disable frame lock on system.\n");
+ printf("\n");
+
+} /* do_help()*/
+
+
+
+/*
+ * do_query()
+ *
+ * Prints information for all frame lock (g-sync) devices found on
+ * the given X server.
+ *
+ */
+static void do_query(Display *dpy)
+{
+ Bool ret;
+ int num_framelocks;
+ int framelock;
+ int gpu;
+ int mask;
+ char *name;
+
+ int *data;
+ int len;
+ int i;
+
+ int enabled;
+
+
+ /* Query the number of frame lock devices on the server */
+
+ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ &num_framelocks);
+ if (!ret) {
+ printf("Failed to query number of frame lock devices!\n");
+ return;
+ }
+ printf("Found %d frame lock device(s) on server.\n", num_framelocks);
+ if ( !num_framelocks ) {
+ return;
+ }
+
+ /* Display information for all frame lock devices found */
+
+ for (framelock = 0; framelock < num_framelocks; framelock++) {
+
+ printf("\n");
+ printf("- Frame Lock Board %d :\n", framelock);
+
+ /* Query the GPUs connected to this frame lock device */
+
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ framelock, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK,
+ (unsigned char **) &data,
+ &len);
+ if (!ret) {
+ printf(" - Failed to query list of GPUs!\n");
+ continue;
+ }
+
+ /* Display information for all GPUs connected to frame lock device */
+
+ if ( !data[0] ) {
+ printf(" - No GPUs found!\n");
+ } else {
+ printf(" - Found %d GPU(s).\n", data[0]);
+ }
+
+ for (i = 1; i <= data[0]; i++) {
+ gpu = data[i];
+
+ /* Query GPU product name */
+
+ ret = XNVCTRLQueryTargetStringAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_STRING_PRODUCT_NAME,
+ &name);
+ if (!ret) {
+ printf(" - Failed to query GPU %d product name.\n", gpu);
+ continue;
+ }
+ printf(" - GPU %d (%s) :\n", gpu, name);
+
+ /* Query GPU sync state */
+
+ printf(" - Sync : ");
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SYNC,
+ &enabled);
+ if (!ret) {
+ printf("Failed to query sync state.\n");
+ } else {
+ printf("%sabled\n", enabled ? "En" : "Dis");
+ }
+
+ /* Query GPU displays */
+
+ printf(" - Displays Mask : ");
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_ENABLED_DISPLAYS,
+ &mask);
+ if (!ret) {
+ printf("Failed to query enabled displays.\n");
+ } else {
+ printf("0x%08u\n", mask);
+ }
+
+ /* Query GPU server (master) */
+
+ printf(" - Server Mask : ");
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_MASTER,
+ &mask);
+ if (!ret) {
+ printf("Failed to query server mask.\n");
+ } else {
+ printf("0x%08u\n", mask);
+ }
+
+ /* Query GPU clients (slaves) */
+
+ printf(" - Clients Mask : ");
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SLAVES,
+ &mask);
+ if (!ret) {
+ printf("Failed to query clients mask.\n");
+ } else {
+ printf("0x%08u\n", mask);
+ }
+
+ } /* Done disabling GPUs */
+
+ } /* Done disabling Frame Lock Devices */
+
+} /* do_query() */
+
+
+
+/*
+ * do_enable()
+ *
+ * Enables frame lock on the X Server by setting the first capable/available
+ * display device as the frame lock server (master) and setting all other
+ * display devices as clients (slaves).
+ *
+ * NOTE: It is up to the user to ensure that each display device is set with
+ * the same refresh rate (mode timings).
+ *
+ */
+static void do_enable(Display *dpy)
+{
+ Bool ret;
+ int num_framelocks;
+ int framelock;
+ int gpu;
+ unsigned int mask;
+
+ int *data;
+ int len;
+ int i;
+
+ int enabled;
+ int masterable;
+ int pick_server = 1;
+ int server_set = 0;
+
+
+ /* Query the number of frame lock devices to enable */
+
+ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ &num_framelocks);
+ if (!ret) {
+ printf("Failed to query number of frame lock devices!\n");
+ return;
+ }
+ printf("Found %d frame lock device(s) on server.\n", num_framelocks);
+ if ( !num_framelocks ) {
+ return;
+ }
+
+ /* Enable frame lock on all GPUs connected to each frame lock device */
+
+ for (framelock = 0; framelock < num_framelocks; framelock++) {
+
+ printf("\n");
+ printf("- Frame Lock Board %d :\n", framelock);
+
+ /* Query the GPUs connected to this frame lock device */
+
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ framelock, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK,
+ (unsigned char **) &data,
+ &len);
+ if (!ret) {
+ printf(" - Failed to query list of GPUs!\n");
+ continue;
+ }
+
+ /* Enable frame lock on all GPUs connected to the frame lock device */
+
+ if ( !data[0] ) {
+ printf(" - No GPUs found!\n");
+ } else {
+ printf(" - Found %d GPU(s).\n", data[0]);
+ }
+
+ for (i = 1; i <= data[0]; i++) {
+ gpu = data[i];
+
+ printf(" - Enabling G-Sync Device %d - GPU %d... ",
+ framelock, gpu);
+
+ /* Make sure frame lock is disabled */
+
+ XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SYNC,
+ &enabled);
+ if (enabled != NV_CTRL_FRAMELOCK_SYNC_DISABLE) {
+ printf("Frame lock already enabled!\n");
+ continue;
+ }
+
+ /* Get the list of displays to enable */
+
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_ENABLED_DISPLAYS,
+ &mask);
+ if (!ret) {
+ printf("Failed to query enabled displays!\n");
+ continue;
+ }
+
+ /* Query if this GPU can be set as master */
+
+ ret = XNVCTRLQueryTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ mask, // display_mask
+ NV_CTRL_FRAMELOCK_MASTERABLE,
+ &masterable);
+ if (!ret) {
+ printf("Failed to query masterable!\n");
+ continue;
+ }
+
+ /* Clear the master setting if any */
+
+ if (masterable == NV_CTRL_FRAMELOCK_MASTERABLE_TRUE) {
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_MASTER,
+ 0);
+ }
+
+ /* Clear the slaves setting if any */
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SLAVES,
+ 0);
+
+ printf("\n");
+
+ /* Pick the first available/capable display device as master */
+
+ if (pick_server &&
+ masterable == NV_CTRL_FRAMELOCK_MASTERABLE_TRUE) {
+
+ /* Just pick the first enabled display */
+
+ unsigned int master = (1<<31);
+ while (master && !(master & mask)) {
+ master >>= 1;
+ }
+
+ if (master) {
+ mask &= ~master;
+
+ /* Make sure we're not using the House Sync signal. */
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ framelock, // target_id
+ 0, // display_mask
+ NV_CTRL_USE_HOUSE_SYNC,
+ NV_CTRL_USE_HOUSE_SYNC_FALSE);
+
+ /* Set the master */
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_MASTER,
+ master);
+
+ printf(" - Set Server Display : 0x%08u\n", master);
+ pick_server = 0;
+ server_set = 1;
+ }
+ }
+
+ /* Set rest of enabled display devices as clients (slaves) */
+
+ if (mask) {
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SLAVES,
+ mask);
+ printf(" - Set Client Display(s) : 0x%08u\n", mask);
+ }
+
+ /* Enable frame lock */
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SYNC,
+ NV_CTRL_FRAMELOCK_SYNC_ENABLE);
+ XFlush(dpy);
+ printf(" - Frame Lock Sync Enabled.\n");
+
+ /* If we just enabled the server, also toggle the test signal
+ * to guarentee accuracy of the universal frame count (as
+ * returned by the glXQueryFrameCountNV() function in the
+ * GLX_NV_swap_group extension).
+ */
+ if (server_set) {
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_TEST_SIGNAL,
+ NV_CTRL_FRAMELOCK_TEST_SIGNAL_ENABLE);
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_TEST_SIGNAL,
+ NV_CTRL_FRAMELOCK_TEST_SIGNAL_DISABLE);
+
+ printf(" - Frame Lock Test Signal Toggled.\n");
+ server_set = 0;
+ }
+
+ } /* Done enabling GPUs */
+
+ } /* Done enabling framelocks */
+}
+
+
+
+static void do_disable(Display *dpy)
+{
+ Bool ret;
+ int num_framelocks;
+ int framelock;
+ int gpu;
+
+ int *data;
+ int len;
+ int i;
+
+ /* Query the number of frame lock devices to disable */
+
+ ret = XNVCTRLQueryTargetCount(dpy, NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ &num_framelocks);
+ if (!ret) {
+ printf("Failed to query number of frame lock devices!\n");
+ return;
+ }
+ printf("Found %d frame lock device(s) on server.\n", num_framelocks);
+ if ( !num_framelocks ) {
+ return;
+ }
+
+ /* Disable frame lock on all GPUs connected to each frame lock device */
+
+ for (framelock = 0; framelock < num_framelocks; framelock++) {
+
+ printf("\n");
+ printf("- Frame Lock Board %d :\n", framelock);
+
+ /* Query the GPUs connected to this frame lock device */
+
+ ret = XNVCTRLQueryTargetBinaryData
+ (dpy,
+ NV_CTRL_TARGET_TYPE_FRAMELOCK,
+ framelock, // target_id
+ 0, // display_mask
+ NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK,
+ (unsigned char **) &data,
+ &len);
+ if (!ret) {
+ printf(" - Failed to query list of GPUs!\n");
+ continue;
+ }
+
+ /* Disable frame lock on all GPUs connected to the frame lock device */
+
+ if ( !data[0] ) {
+ printf(" - No GPUs found!\n");
+ } else {
+ printf(" - Found %d GPU(s).\n", data[0]);
+ }
+
+ for (i = 1; i <= data[0]; i++) {
+ gpu = data[i];
+
+ printf(" - Disabling G-Sync Device %d - GPU %d... ",
+ framelock, gpu);
+
+ XNVCTRLSetTargetAttribute(dpy,
+ NV_CTRL_TARGET_TYPE_GPU,
+ gpu, // target_id
+ 0, // display_mask
+ NV_CTRL_FRAMELOCK_SYNC,
+ NV_CTRL_FRAMELOCK_SYNC_DISABLE);
+ XFlush(dpy);
+ printf("Done.\n");
+
+ } /* Done disabling GPUs */
+
+ } /* Done disabling Frame Lock Devices */
+
+} /* do_disable() */
+
+
+
+int main(int argc, char *argv[])
+{
+ Display *dpy;
+ Bool ret;
+ int major, minor;
+
+ /*
+ * Open a display connection, and make sure the NV-CONTROL X
+ * extension is present on the screen we want to use.
+ */
+
+ dpy = XOpenDisplay(NULL);
+ if (!dpy) {
+ printf("Cannot open display '%s'.\n", XDisplayName(NULL));
+ return 1;
+ }
+
+ /* Query the NV-CONTROL version */
+
+ ret = XNVCTRLQueryVersion(dpy, &major, &minor);
+ if (ret != True) {
+ printf("The NV-CONTROL X extension does not exist on '%s'.\n",
+ XDisplayName(NULL));
+ return 1;
+ }
+
+ /* Print some information */
+
+ printf("Using NV-CONTROL extension %d.%d on %s\n\n",
+ major, minor, XDisplayName(NULL));
+
+ /* Do what the user wants */
+
+ if (argc <= 1 || (strcmp(argv[1], "-q") == 0)) {
+ do_query(dpy);
+
+ } else if (strcmp(argv[1], "-e") == 0) {
+ do_enable(dpy);
+
+ } else if (strcmp(argv[1], "-d") == 0) {
+ do_disable(dpy);
+
+ } else {
+ do_help();
+ }
+
+ return 0;
+}