summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo De La Garza <pdelagarza@nvidia.com>2017-10-26 10:37:22 -0700
committerAaron Plattner <aplattner@nvidia.com>2018-01-04 10:11:25 -0800
commit635666ba50f11d9975844e997b0dce26e86d0a03 (patch)
tree53f590ff0b064ad16f1ca96a02fa71a804896a1a
parent554b47144aff1c9ab25ac14e33219a29167e13d5 (diff)
Stereo Test
It had been requested to provide end users with a way to test if stereo mode has been configured and is working properly. To address such, it was decided to create a simple demo/test and to get such app embedded in nvidia settings by creating a custom gtk widget on which to render opengl. (Such widget seems to exist, but only in versions of gtk3 that are newer to what nvidia-settings use, hence the need to create our own). This implementation will work with gtk3 and ignored on gtk2.
-rw-r--r--src/gtk+-2.x/ctkglstereo.c213
-rw-r--r--src/gtk+-2.x/ctkglstereo.h44
-rw-r--r--src/gtk+-2.x/ctkglwidget.c282
-rw-r--r--src/gtk+-2.x/ctkglwidget.h91
-rw-r--r--src/gtk+-2.x/ctkscreen.c14
-rw-r--r--src/gtk+-2.x/ctkwindow.c16
-rw-r--r--src/gtk+-2.x/matrix_utils.c122
-rw-r--r--src/gtk+-2.x/matrix_utils.h39
-rw-r--r--src/gtk+-2.x/opengl_loading.c104
-rw-r--r--src/gtk+-2.x/opengl_loading.h90
-rw-r--r--src/gtk+-2.x/opengl_wrappers.c410
-rw-r--r--src/gtk+-2.x/opengl_wrappers.h68
-rw-r--r--src/image_data/left.pngbin0 -> 329 bytes
-rw-r--r--src/image_data/nvlogo.pngbin0 -> 17496 bytes
-rw-r--r--src/image_data/right.pngbin0 -> 1799 bytes
-rw-r--r--src/src.mk13
16 files changed, 1506 insertions, 0 deletions
diff --git a/src/gtk+-2.x/ctkglstereo.c b/src/gtk+-2.x/ctkglstereo.c
new file mode 100644
index 0000000..135bb8c
--- /dev/null
+++ b/src/gtk+-2.x/ctkglstereo.c
@@ -0,0 +1,213 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#include "ctkutils.h"
+#include "ctkglstereo.h"
+
+#ifdef CTK_GTK3
+#include <GL/gl.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "right.png.h"
+#include "left.png.h"
+#include "nvlogo.png.h"
+
+#include "matrix_utils.h"
+#include "opengl_loading.h"
+#include "ctkglwidget.h"
+#endif
+
+#ifdef CTK_GTK3
+const unsigned int animateDiv = 1000;
+static void animate(StereoAppData *appData, int eye)
+{
+ float x;
+ int op;
+ float delta = 0.2;
+
+ GLfloat tm[16]; // Temporary matrix
+ GLfloat *mvp; // Model-View-Projection matrix
+ mvp = appData->cube->mvp;
+
+ if (eye == GL_LEFT) {
+ op = 1;
+ } else {
+ op = -1;
+ }
+
+ x = 2 * M_PI / animateDiv * appData->animationCounter;
+
+ genIdentityMatrix(mvp);
+
+ genRotateMatrixX(M_PI / 4, tm);
+ matrixMult(mvp, tm);
+
+ genRotateMatrixZ(M_PI / 4, tm);
+ matrixMult(mvp, tm);
+
+ // Apply the calculated rotation for this
+ // frame along axis X and Y to generate the
+ // animated effect
+ genRotateMatrixX(x, tm);
+ matrixMult(mvp, tm);
+ genRotateMatrixY(x, tm);
+ matrixMult(mvp, tm);
+
+ // Translates depending on eye
+ // and locates the object away from zero in the z-axis so
+ // that is viewable in the fov we define in the next step.
+ genTranslateMatrix(op * delta, 0, -1.5, tm);
+ matrixMult(mvp, tm);
+
+ genPerspectiveMatrix(M_PI / 2 , 1, 0.5, 5, tm);
+ matrixMult(mvp, tm);
+}
+
+static void produceFrameStereoTest(void *_appData)
+{
+ StereoAppData *appData = _appData;
+
+ dGL.glDrawBuffer(GL_BACK_LEFT);
+
+ dGL.glClearColor(206.0/255, 206.0/255, 206.0/255, 1);
+ dGL.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ animate(appData, GL_LEFT);
+ drawModel(appData->cube);
+ drawModel(appData->labelLeft);
+
+ dGL.glDrawBuffer(GL_BACK_RIGHT);
+ dGL.glClearColor(206.0/255, 206.0/255, 206.0/255, 1);
+ dGL.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ animate(appData, GL_RIGHT);
+ drawModel(appData->cube);
+ drawModel(appData->labelRight);
+
+ appData->animationCounter++;
+ appData->animationCounter %= animateDiv;
+}
+
+static int verifyOpenglForStereo(void)
+{
+ GLint majorVer = 0;
+
+ dGL.glGetIntegerv(GL_MAJOR_VERSION, &majorVer);
+
+ if (majorVer < 3) {
+ return -1;
+ }
+ return 0;
+}
+
+static int setupStereoTest(void *_appData)
+{
+ StereoAppData *appData = _appData;
+
+ GdkPixbuf *nvidiaLogo = CTK_LOAD_PIXBUF(nvlogo);
+ GdkPixbuf *imageLeft = CTK_LOAD_PIXBUF(left);
+ GdkPixbuf *imageRight = CTK_LOAD_PIXBUF(right);
+
+ if (verifyOpenglForStereo() != 0) {
+ return -2;
+ }
+
+ dGL.glViewport(0, 0, 200, 200);
+
+ dGL.glEnable(GL_DEPTH_TEST);
+
+ dGL.glEnable(GL_BLEND);
+ dGL.glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ dGL.glEnable(GL_TEXTURE_2D);
+ dGL.glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ appData->animationCounter = 0;
+
+ appData->cube = cubeSetup(nvidiaLogo);
+
+ appData->labelLeft = labelSetup(-0.75, 0.90, // x and y
+ 0.5, 0.20, // width and height
+ 1, 0, 0, // rgb
+ imageLeft // GdkPixbuf *
+ );
+
+ appData->labelRight = labelSetup(0.70, 0.85, // x and y
+ 0.6, 0.20, // width and height
+ 0, 0, 1, // rgb
+ imageRight // GdkPixbuf *
+ );
+
+ g_object_unref(nvidiaLogo);
+ g_object_unref(imageLeft);
+ g_object_unref(imageRight);
+
+ if (appData->cube == NULL ||
+ appData->labelLeft == NULL ||
+ appData->labelRight == NULL) {
+
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif
+
+GtkWidget *ctk_glstereo_new(void)
+{
+#ifdef CTK_GTK3
+ GtkWidget *gtk_widget;
+ CtkGLWidget *ctk_glwidget;
+ int glx_attributes[] = {
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER, 1,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_ALPHA_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ GLX_STEREO, 1,
+ None
+ };
+
+ void *app_data;
+ app_data = malloc(sizeof(StereoAppData));
+ gtk_widget = ctk_glwidget_new(glx_attributes,
+ app_data,
+ setupStereoTest,
+ produceFrameStereoTest);
+
+ ctk_glwidget = CTK_GLWIDGET(gtk_widget);
+
+ if (ctk_glwidget) {
+ ctk_glwidget->timer_interval = 10; // In milliseconds
+ gtk_widget_set_size_request(GTK_WIDGET(ctk_glwidget), 200, 200);
+ return GTK_WIDGET(ctk_glwidget);
+ }
+
+ free(app_data);
+
+#endif
+ return NULL;
+}
+
diff --git a/src/gtk+-2.x/ctkglstereo.h b/src/gtk+-2.x/ctkglstereo.h
new file mode 100644
index 0000000..c598839
--- /dev/null
+++ b/src/gtk+-2.x/ctkglstereo.h
@@ -0,0 +1,44 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __CTK_GLSTEREO_H__
+#define __CTK_GLSTEREO_H__
+
+#include "ctkutils.h"
+
+#ifdef CTK_GTK3
+#include "opengl_wrappers.h"
+#endif
+
+GtkWidget *ctk_glstereo_new(void);
+
+
+#ifdef CTK_GTK3
+typedef struct _StereoAppData StereoAppData;
+struct _StereoAppData
+{
+ OpenGLModelData *cube;
+ OpenGLModelData *labelLeft;
+ OpenGLModelData *labelRight;
+ unsigned int animationCounter;
+};
+
+#endif
+
+#endif
diff --git a/src/gtk+-2.x/ctkglwidget.c b/src/gtk+-2.x/ctkglwidget.c
new file mode 100644
index 0000000..bd47bcd
--- /dev/null
+++ b/src/gtk+-2.x/ctkglwidget.c
@@ -0,0 +1,282 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#include "ctkutils.h"
+#include "ctkglwidget.h"
+
+#include <assert.h>
+#include <gtk/gtk.h>
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+#include <stdlib.h>
+#include "opengl_loading.h"
+
+GtkWidget *ctk_glwidget_new(int glx_attributes[],
+ void *app_data,
+ int (*app_setup_callback) (void *app_data),
+ void (*draw_frame_callback) (void *app_data) )
+{
+#ifdef CTK_GTK3
+ GObject *object;
+ CtkGLWidget *ctk_glwidget;
+ GLXFBConfig *fb_configs;
+ int n_elements;
+ int x_visual_id;
+
+ GdkDisplay *gdk_display;
+ Display *display;
+ GLXContext glx_context;
+ GdkVisual *gdk_visual;
+
+ gdk_display = gdk_display_get_default();
+
+
+ display = gdk_x11_display_get_xdisplay(gdk_display);
+
+ if (!loadGL()) {
+ return NULL;
+ }
+
+ fb_configs = dGL.glXChooseFBConfig(display,
+ DefaultScreen(display),
+ glx_attributes, &n_elements);
+ if (n_elements == 0) {
+ return NULL;
+ }
+
+ dGL.glXGetFBConfigAttrib(display,
+ fb_configs[0],
+ GLX_VISUAL_ID,
+ &x_visual_id);
+
+ gdk_visual = gdk_x11_screen_lookup_visual(gdk_screen_get_default(),
+ x_visual_id);
+
+ if (gdk_visual == NULL) {
+ XFree(fb_configs);
+ return NULL;
+ }
+
+ gdk_x11_display_error_trap_push(gdk_display);
+ glx_context = dGL.glXCreateNewContext(display,
+ fb_configs[0],
+ GLX_RGBA_TYPE,
+ NULL,
+ GL_TRUE);
+
+ if (gdk_x11_display_error_trap_pop(gdk_display) != 0) {
+ glx_context = NULL;
+ }
+
+ XFree(fb_configs);
+
+ if (glx_context == NULL) {
+ return NULL;
+ }
+
+ object = g_object_new(CTK_TYPE_GLWIDGET, NULL);
+ ctk_glwidget = CTK_GLWIDGET(object);
+
+ ctk_glwidget->app_data = app_data;
+ ctk_glwidget->app_setup_callback = app_setup_callback;
+ ctk_glwidget->draw_frame_callback = draw_frame_callback;
+
+ ctk_glwidget->gdk_display = gdk_display;
+ ctk_glwidget->gdk_window = NULL;
+ ctk_glwidget->display = display;
+
+ ctk_glwidget->is_error = FALSE;
+ ctk_glwidget->timer_interval = 100;
+
+ ctk_glwidget->glx_context = glx_context;
+ ctk_glwidget->gdk_visual = gdk_visual;
+
+ return GTK_WIDGET(ctk_glwidget);
+
+#else
+ return NULL;
+#endif
+}
+
+#ifdef CTK_GTK3
+static void on_error(CtkGLWidget *ctk_glwidget);
+static gboolean draw_frame_in_glwidget(gpointer p);
+
+static void ctk_glwidget_realize(GtkWidget *gtk_widget)
+{
+ CtkGLWidget *ctk_glwidget;
+ GdkWindowAttr gdk_attributes;
+ gint attributes_mask;
+ GtkAllocation allocation;
+
+ ctk_glwidget = CTK_GLWIDGET(gtk_widget);
+
+ gtk_widget_set_realized(gtk_widget, TRUE);
+ gtk_widget_set_has_window(gtk_widget, TRUE);
+
+ if (ctk_glwidget->is_error) {
+ return;
+ }
+
+ if (ctk_glwidget->gdk_window) {
+ gdk_window_set_user_data(ctk_glwidget->gdk_window,
+ gtk_widget);
+ return;
+ }
+
+ gtk_widget_get_allocation(gtk_widget, &allocation);
+
+ gdk_attributes.x = allocation.x;
+ gdk_attributes.y = allocation.y;
+ gdk_attributes.width = allocation.width;
+ gdk_attributes.height = allocation.height;
+ gdk_attributes.wclass = GDK_INPUT_OUTPUT;
+ gdk_attributes.window_type = GDK_WINDOW_CHILD;
+ gdk_attributes.event_mask = gtk_widget_get_events(gtk_widget);
+ gdk_attributes.visual = ctk_glwidget->gdk_visual;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+ ctk_glwidget->gdk_window =
+ gdk_window_new(gtk_widget_get_parent_window(gtk_widget),
+ &gdk_attributes, attributes_mask);
+
+ if (ctk_glwidget->gdk_window == NULL) {
+ on_error(ctk_glwidget);
+ return;
+ }
+
+ ctk_glwidget->window = gdk_x11_window_get_xid(ctk_glwidget->gdk_window);
+ gdk_window_set_user_data(ctk_glwidget->gdk_window, gtk_widget);
+ gtk_widget_set_window(gtk_widget, ctk_glwidget->gdk_window);
+
+ dGL.glXMakeContextCurrent(ctk_glwidget->display, ctk_glwidget->window,
+ ctk_glwidget->window, ctk_glwidget->glx_context);
+
+ if (ctk_glwidget->app_setup_callback(ctk_glwidget->app_data) != 0) {
+ on_error(ctk_glwidget);
+ return;
+ }
+
+ g_timeout_add_full(G_PRIORITY_LOW,
+ ctk_glwidget->timer_interval,
+ draw_frame_in_glwidget,
+ ctk_glwidget,
+ 0);
+
+}
+
+static void ctk_glwidget_unrealize(GtkWidget *gtk_widget)
+{
+
+ if (CTK_GLWIDGET(gtk_widget)->is_error) {
+ return;
+ }
+
+ if (gtk_widget_get_has_window(gtk_widget)) {
+ gdk_window_set_user_data(CTK_GLWIDGET(gtk_widget)->gdk_window, NULL);
+ }
+
+ gtk_selection_remove_all(gtk_widget);
+ gtk_widget_set_realized(gtk_widget, FALSE);
+}
+
+static void ctk_glwidget_finalize(GObject *gobject)
+{
+ assert(!"unimplemented");
+}
+
+static void ctk_glwidget_class_init(CtkGLWidgetClass *klass)
+{
+ GtkWidgetClass *widget_class;
+ GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
+ widget_class = (GtkWidgetClass *) klass;
+
+ widget_class->realize = ctk_glwidget_realize;
+ widget_class->unrealize = ctk_glwidget_unrealize;
+ gobject_class->finalize = ctk_glwidget_finalize;
+}
+
+GType ctk_glwidget_get_type(void)
+{
+ static GType ctk_glwidget_type = 0;
+
+ if (!ctk_glwidget_type) {
+ static const GTypeInfo info_ctk_glwidget = {
+ sizeof (CtkGLWidgetClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ctk_glwidget_class_init, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CtkGLWidget),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ NULL /* value_table */
+ };
+ ctk_glwidget_type = g_type_register_static(GTK_TYPE_WIDGET,
+ "CtkGLWidget", &info_ctk_glwidget, 0);
+ }
+ return ctk_glwidget_type;
+}
+
+static gboolean draw_frame_in_glwidget(gpointer p)
+{
+ CtkGLWidget *ctk_glwidget = CTK_GLWIDGET(p);
+
+ if (ctk_glwidget->is_error) {
+ return FALSE;
+ }
+
+ if (!gtk_widget_get_realized(GTK_WIDGET(p))) {
+ return TRUE;
+ }
+
+ if (ctk_widget_is_drawable(GTK_WIDGET(ctk_glwidget))) {
+ ctk_glwidget_make_current(ctk_glwidget);
+ ctk_glwidget->draw_frame_callback(ctk_glwidget->app_data);
+ ctk_glwidget_swap(ctk_glwidget);
+ }
+ return TRUE;
+}
+
+static void on_error(CtkGLWidget *ctk_glwidget)
+{
+ ctk_glwidget->is_error = TRUE;
+ gtk_widget_set_size_request(GTK_WIDGET(ctk_glwidget), 0, 0);
+
+ if (ctk_glwidget->gdk_window) {
+ gdk_window_set_user_data(ctk_glwidget->gdk_window, NULL);
+ }
+}
+
+void ctk_glwidget_make_current(CtkGLWidget *ctk_glwidget)
+{
+ dGL.glXMakeContextCurrent(ctk_glwidget->display,
+ ctk_glwidget->window,
+ ctk_glwidget->window,
+ ctk_glwidget->glx_context);
+}
+
+void ctk_glwidget_swap(CtkGLWidget *ctk_glwidget)
+{
+ dGL.glXSwapBuffers(ctk_glwidget->display, ctk_glwidget->window);
+}
+#endif
+
diff --git a/src/gtk+-2.x/ctkglwidget.h b/src/gtk+-2.x/ctkglwidget.h
new file mode 100644
index 0000000..f4154dd
--- /dev/null
+++ b/src/gtk+-2.x/ctkglwidget.h
@@ -0,0 +1,91 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __CTK_GLWIDGET_H__
+#define __CTK_GLWIDGET_H__
+
+#include <gtk/gtk.h>
+#include <GL/gl.h>
+#include <GL/glx.h>
+#include <gdk/gdkx.h>
+
+#include "ctkconfig.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_GLWIDGET (ctk_glwidget_get_type())
+
+#define CTK_GLWIDGET(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_GLWIDGET, CtkGLWidget))
+
+#define CTK_GLWIDGET_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_GLWIDGET, CtkGLWidgetClass))
+
+#define CTK_IS_GLWIDGET(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_GLWIDGET))
+
+#define CTK_IS_GLWIDGET_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_GLWIDGET))
+
+#define CTK_GLWIDGET_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_GLWIDGET, CtkGLWidgetClass))
+
+
+typedef struct _CtkGLWidget CtkGLWidget;
+typedef struct _CtkGLWidgetClass CtkGLWidgetClass;
+
+struct _CtkGLWidget
+{
+ GtkWidget parent;
+
+ GdkDisplay *gdk_display;
+ GdkWindow *gdk_window;
+ Display *display;
+ Window window;
+ GLXContext glx_context;
+ GdkVisual *gdk_visual;
+
+ gboolean is_error;
+ int timer_interval;
+ void *app_data;
+
+ int (*app_setup_callback) (void *app_data);
+ void (*draw_frame_callback) (void *app_data);
+};
+
+struct _CtkGLWidgetClass
+{
+ GtkWidgetClass parent_class;
+};
+
+GType ctk_glwidget_get_type (void);
+
+GtkWidget *ctk_glwidget_new(int glx_attributes[],
+ void *app_data,
+ int (*app_setup_callback) (void *app_data),
+ void (*draw_frame_callback) (void *app_data));
+
+#ifdef CTK_GTK3
+void ctk_glwidget_make_current(CtkGLWidget *ctk_glwidget);
+void ctk_glwidget_swap(CtkGLWidget *ctk_glwidget);
+#endif
+
+G_END_DECLS
+
+#endif
diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c
index b7e465d..a452849 100644
--- a/src/gtk+-2.x/ctkscreen.c
+++ b/src/gtk+-2.x/ctkscreen.c
@@ -34,6 +34,9 @@
#include "ctkutils.h"
#include "ctkbanner.h"
+#include "ctkglwidget.h"
+#include "ctkglstereo.h"
+
void ctk_screen_event_handler(GtkWidget *widget,
CtrlEvent *event,
gpointer data);
@@ -131,6 +134,7 @@ GtkWidget* ctk_screen_new(CtrlTarget *ctrl_target, CtkEvent *ctk_event)
GtkWidget *banner;
GtkWidget *hseparator;
GtkWidget *table;
+ GtkWidget *ctk_glstereo;
ReturnStatus ret;
@@ -311,6 +315,16 @@ GtkWidget* ctk_screen_new(CtrlTarget *ctrl_target, CtkEvent *ctk_event)
if (ctk_screen->stereo_available) {
add_table_row(table, 20, 0, 0, "Stereo Mode:", 0, 0,
NvCtrlGetStereoModeName(stereo_mode));
+
+ if (stereo_mode != NV_CTRL_STEREO_OFF) {
+ ctk_glstereo = ctk_glstereo_new();
+ if (ctk_glstereo) {
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_glstereo,
+ FALSE, FALSE, 0);
+ }
+ }
}
g_free(screen_number);
diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c
index bff0775..da06ddd 100644
--- a/src/gtk+-2.x/ctkwindow.c
+++ b/src/gtk+-2.x/ctkwindow.c
@@ -26,6 +26,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
+#include <gdk/gdkx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -72,6 +73,7 @@
#include "common-utils.h"
#include "query-assign.h"
+#include "opengl_loading.h"
/* column enumeration */
@@ -1343,6 +1345,20 @@ static GtkWidget *create_quit_dialog(CtkWindow *ctk_window)
static void save_settings_and_exit(CtkWindow *ctk_window)
{
+#ifdef CTK_GTK3
+ GdkDisplay *gdk_display;
+ Display *display;
+ GdkScreen *gdk_screen;
+
+ if (dGL.glXMakeContextCurrent) {
+ gdk_screen = gtk_window_get_screen(GTK_WINDOW(ctk_window));
+ gdk_display = gdk_screen_get_display(gdk_screen);
+ display = gdk_x11_display_get_xdisplay(gdk_display);
+ dGL.glXMakeContextCurrent(display, 0, 0, 0);
+ }
+
+#endif
+
add_special_config_file_attributes(ctk_window);
gtk_main_quit();
}
diff --git a/src/gtk+-2.x/matrix_utils.c b/src/gtk+-2.x/matrix_utils.c
new file mode 100644
index 0000000..3667843
--- /dev/null
+++ b/src/gtk+-2.x/matrix_utils.c
@@ -0,0 +1,122 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include "matrix_utils.h"
+
+void matrixMult(float a[16], const float b[16])
+{
+ int i, j, k;
+ float aa[16];
+
+ memcpy(aa, a, sizeof(aa));
+ memset(a, 0, 16 * sizeof(float));
+
+ for (j = 0; j < 4; j++) {
+ for (i = 0; i < 4; i++) {
+ for (k = 0; k < 4; k++) {
+ a[4 * j + i] += aa[4 * j + k] * b[4 * k + i];
+ }
+ }
+ }
+}
+
+void matrixTranspose(float m[16])
+{
+ int i, j;
+ float tmp;
+
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < j; ++i) {
+ tmp = m[4 * j + i];
+ m[4 * j + i] = m[4 * i + j];
+ m[4 * i + j] = tmp;
+ }
+ }
+}
+
+void genZeroMatrix(float matrix[16])
+{
+ memset(matrix, 0, 16 * sizeof(float));
+}
+
+void genIdentityMatrix(float matrix[16])
+{
+ genZeroMatrix(matrix);
+ matrix[0] = 1;
+ matrix[5] = 1;
+ matrix[10] = 1;
+ matrix[15] = 1;
+}
+
+void genTranslateMatrix(float x, float y, float z, float matrix[16])
+{
+ genIdentityMatrix(matrix);
+ matrix[12] = x;
+ matrix[13] = y;
+ matrix[14] = z;
+}
+
+void genRotateMatrixX(float radians, float matrix[16])
+{
+ genIdentityMatrix(matrix);
+ matrix[5] = cosf(radians);
+ matrix[6] = -1 * sinf(radians);
+ matrix[9] = sinf(radians);
+ matrix[10] = cosf(radians);
+}
+
+void genRotateMatrixY(float radians, float matrix[16])
+{
+ genIdentityMatrix(matrix);
+ matrix[0] = cosf(radians);
+ matrix[2] = -1 * sinf(radians);
+ matrix[8] = sinf(radians);
+ matrix[10] = cosf(radians);
+}
+
+void genRotateMatrixZ(float radians, float matrix[16])
+{
+ genIdentityMatrix(matrix);
+ matrix[0] = cosf(radians);
+ matrix[1] = sinf(radians);
+ matrix[4] = -1 * sinf(radians);
+ matrix[5] = cosf(radians);
+}
+
+void genPerspectiveMatrix(float fovY,
+ float aspect,
+ float zNear,
+ float zFar,
+ float matrix[16])
+{
+ float f;
+
+ f = 1 / tanf(fovY / 2);
+
+ genZeroMatrix(matrix);
+ matrix[0] = f / aspect;
+ matrix[5] = f;
+ matrix[10] = (zFar + zNear) / (zNear - zFar);
+ matrix[11] = 2 * zFar * zNear / (zNear - zFar);
+ matrix[14] = -1;
+}
+
diff --git a/src/gtk+-2.x/matrix_utils.h b/src/gtk+-2.x/matrix_utils.h
new file mode 100644
index 0000000..822702d
--- /dev/null
+++ b/src/gtk+-2.x/matrix_utils.h
@@ -0,0 +1,39 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __MATRIX_UTILS_H__
+#define __MATRIX_UTILS_H__
+
+void matrixMult(float a[16], const float b[16]);
+void matrixTranspose(float m[16]);
+
+void genZeroMatrix(float matrix[16]);
+void genIdentityMatrix(float matrix[16]);
+
+void genTranslateMatrix(float x, float y, float z, float matrix[16]);
+void genRotateMatrixX(float radians, float matrix[16]);
+void genRotateMatrixY(float radians, float matrix[16]);
+void genRotateMatrixZ(float radians, float matrix[16]);
+void genPerspectiveMatrix(float fovY,
+ float aspect,
+ float zNear,
+ float zFar,
+ float matrix[16]);
+
+#endif /*__MATRIX_UTILS_H__*/
diff --git a/src/gtk+-2.x/opengl_loading.c b/src/gtk+-2.x/opengl_loading.c
new file mode 100644
index 0000000..1e3454e
--- /dev/null
+++ b/src/gtk+-2.x/opengl_loading.c
@@ -0,0 +1,104 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#include <stdio.h>
+#include <GL/glx.h>
+#include <dlfcn.h>
+#include "opengl_loading.h"
+
+libGLData dGL;
+
+#define LOAD_GL_FUNCTION(func) \
+ dGL.func = dGL.glXGetProcAddress((const GLubyte *) #func); \
+ if (dGL.func == NULL) { \
+ fprintf(stderr, "Failed to load " #func "\n"); \
+ return GL_FALSE; \
+ }
+
+GLboolean loadGL(void)
+{
+ dGL.handle = dlopen("libGL.so.1", RTLD_LAZY);
+ if (dGL.handle == NULL) {
+ return GL_FALSE;
+ }
+
+ dGL.glXGetProcAddress = dlsym(dGL.handle, "glXGetProcAddress");
+ if (dGL.glXGetProcAddress == NULL) {
+ return GL_FALSE;
+ }
+
+ LOAD_GL_FUNCTION(glGetString)
+ LOAD_GL_FUNCTION(glGetIntegerv)
+ LOAD_GL_FUNCTION(glGetStringi)
+
+ LOAD_GL_FUNCTION(glXCreateNewContext)
+ LOAD_GL_FUNCTION(glXDestroyContext)
+ LOAD_GL_FUNCTION(glXMakeContextCurrent)
+ LOAD_GL_FUNCTION(glXSwapBuffers)
+ LOAD_GL_FUNCTION(glXChooseFBConfig)
+ LOAD_GL_FUNCTION(glXGetFBConfigAttrib)
+ LOAD_GL_FUNCTION(glXGetProcAddress)
+ LOAD_GL_FUNCTION(glXCreateWindow)
+ LOAD_GL_FUNCTION(glXGetVisualFromFBConfig)
+
+ LOAD_GL_FUNCTION(glBindTexture)
+ LOAD_GL_FUNCTION(glBlendFunc)
+ LOAD_GL_FUNCTION(glClear)
+ LOAD_GL_FUNCTION(glClearColor)
+ LOAD_GL_FUNCTION(glClearDepth)
+ LOAD_GL_FUNCTION(glDepthFunc)
+ LOAD_GL_FUNCTION(glDepthMask)
+ LOAD_GL_FUNCTION(glDrawArrays)
+ LOAD_GL_FUNCTION(glDrawBuffer)
+ LOAD_GL_FUNCTION(glEnable)
+ LOAD_GL_FUNCTION(glGenTextures)
+ LOAD_GL_FUNCTION(glGetError)
+ LOAD_GL_FUNCTION(glPixelStorei)
+ LOAD_GL_FUNCTION(glTexImage2D)
+ LOAD_GL_FUNCTION(glTexParameteri)
+ LOAD_GL_FUNCTION(glViewport)
+ LOAD_GL_FUNCTION(glAttachShader)
+ LOAD_GL_FUNCTION(glBindBuffer)
+ LOAD_GL_FUNCTION(glBindVertexArray)
+ LOAD_GL_FUNCTION(glBufferData)
+ LOAD_GL_FUNCTION(glCompileShader)
+ LOAD_GL_FUNCTION(glCreateProgram)
+ LOAD_GL_FUNCTION(glCreateShader)
+ LOAD_GL_FUNCTION(glDeleteShader)
+ LOAD_GL_FUNCTION(glEnableVertexAttribArray)
+ LOAD_GL_FUNCTION(glGenBuffers)
+ LOAD_GL_FUNCTION(glGenVertexArrays)
+ LOAD_GL_FUNCTION(glGetProgramiv)
+ LOAD_GL_FUNCTION(glGetShaderInfoLog)
+ LOAD_GL_FUNCTION(glGetShaderiv)
+ LOAD_GL_FUNCTION(glLinkProgram)
+ LOAD_GL_FUNCTION(glShaderSource)
+ LOAD_GL_FUNCTION(glUniform4f)
+ LOAD_GL_FUNCTION(glUniformMatrix4fv)
+ LOAD_GL_FUNCTION(glUseProgram)
+ LOAD_GL_FUNCTION(glVertexAttribPointer)
+ LOAD_GL_FUNCTION(glGetUniformLocation)
+
+ return GL_TRUE;
+}
+
+void closeDynamicGL(void)
+{
+ dlclose(dGL.handle);
+}
diff --git a/src/gtk+-2.x/opengl_loading.h b/src/gtk+-2.x/opengl_loading.h
new file mode 100644
index 0000000..1afbc73
--- /dev/null
+++ b/src/gtk+-2.x/opengl_loading.h
@@ -0,0 +1,90 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __OPENGL_LOADING_H__
+#define __OPENGL_LOADING_H__
+
+#include <GL/gl.h>
+#include <GL/glx.h>
+
+typedef struct _libGLData libGLData;
+struct _libGLData {
+
+ void *handle;
+
+ const GLubyte *(*glGetString) (GLenum);
+ const GLubyte *(*glGetStringi) (GLenum, GLuint);
+ void (*glGetIntegerv) (GLenum, GLint *);
+
+ // GLX function pointers
+ GLXContext (*glXCreateNewContext) (Display *, GLXFBConfig, int, GLXContext,Bool);
+ void (*glXDestroyContext) (Display *, GLXContext);
+ Bool (*glXMakeContextCurrent) (Display *, GLXDrawable, GLXDrawable, GLXContext);
+ void (*glXSwapBuffers) (Display *, GLXDrawable);
+ GLXFBConfig *(*glXChooseFBConfig) (Display *, int, const int * , int *);
+ int (*glXGetFBConfigAttrib) (Display *, GLXFBConfig, int, int *);
+ void *(*glXGetProcAddress) (const GLubyte *);
+ GLXWindow (*glXCreateWindow) (Display *, GLXFBConfig, Window win, const int *);
+ XVisualInfo* (*glXGetVisualFromFBConfig) (Display *, GLXFBConfig);
+
+ void (*glBindTexture) (GLenum, GLuint);
+ void (*glBlendFunc) (GLenum, GLenum);
+ void (*glClear) (GLbitfield);
+ void (*glClearColor) (GLclampf, GLclampf, GLclampf, GLclampf);
+ void (*glClearDepth) (GLdouble);
+ void (*glDepthFunc) (GLenum);
+ void (*glDepthMask) (GLboolean);
+ void (*glDrawArrays) (GLenum, GLint, GLsizei);
+ void (*glDrawBuffer) (GLenum);
+ void (*glEnable) (GLenum);
+ void (*glGenTextures) (GLsizei, GLuint *);
+ GLenum (*glGetError) (void);
+ void (*glPixelStorei) (GLenum, GLint);
+ void (*glTexImage2D) (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
+ void (*glTexParameteri) (GLenum, GLenum, GLint);
+ void (*glViewport) (GLint, GLint, GLsizei, GLsizei);
+ void (*glAttachShader) (GLuint, GLuint);
+ void (*glBindBuffer) (GLenum, GLuint);
+ void (*glBindVertexArray) (GLuint);
+ void (*glBufferData) (GLenum, GLsizeiptr, const GLvoid *, GLenum);
+ void (*glCompileShader) (GLuint);
+ GLuint (*glCreateProgram) (void);
+ GLuint (*glCreateShader) (GLenum);
+ void (*glDeleteShader) (GLuint);
+ void (*glEnableVertexAttribArray) (GLuint);
+ void (*glGenBuffers) (GLsizei, GLuint *);
+ void (*glGenVertexArrays) (GLsizei, GLuint *);
+ void (*glGetProgramiv) (GLuint, GLenum, GLint *);
+ void (*glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, GLchar *);
+ void (*glGetShaderiv) (GLuint, GLenum, GLint *);
+ void (*glLinkProgram) (GLuint);
+ void (*glShaderSource) (GLuint, GLsizei, const GLchar* const *, const GLint *);
+ void (*glUniform4f) (GLint, GLfloat, GLfloat, GLfloat, GLfloat);
+ void (*glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+ void (*glUseProgram) (GLuint);
+ void (*glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+ GLint (*glGetUniformLocation) (GLuint, const GLchar *);
+
+};
+
+extern libGLData dGL;
+void closeDynamicGL(void);
+GLboolean loadGL(void);
+
+#endif /* __OPENGL_LOADING_H__ */
diff --git a/src/gtk+-2.x/opengl_wrappers.c b/src/gtk+-2.x/opengl_wrappers.c
new file mode 100644
index 0000000..7ce2323
--- /dev/null
+++ b/src/gtk+-2.x/opengl_wrappers.c
@@ -0,0 +1,410 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#include "ctkutils.h"
+
+#ifdef CTK_GTK3
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "opengl_loading.h"
+#include "opengl_wrappers.h"
+#include "matrix_utils.h"
+
+GLchar const * const cubeVertexShaderSource[] =
+{
+ "#version 450 core\n"
+ "in vec3 xyz;\n"
+ "in vec2 uv;\n"
+ "out vec2 uvFromV;\n"
+ "uniform mat4 mvp;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = vec4(xyz, 1) * mvp;\n"
+ " uvFromV = uv;\n"
+ "}\n"
+};
+
+GLchar const * const cubeFragmentShaderSource[] =
+{
+ "#version 450 core\n"
+ "out vec4 color;\n"
+ "in vec2 uvFromV;\n"
+ "uniform sampler2D textureSampler;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = texture(textureSampler, uvFromV);\n"
+ " if (color.a == 0) {\n"
+ " color = vec4(0, 0, 0, 1);\n"
+ " }\n"
+ "}\n"
+};
+
+GLchar const * const textVertexShaderSource[] =
+{
+ "#version 450 core\n"
+ "in vec3 xyz;\n"
+ "in vec2 uv;\n"
+ "out vec2 uvFromV;\n"
+ "uniform vec4 textColor;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = vec4(xyz, 1);\n"
+ " uvFromV = uv;\n"
+ "}\n"
+};
+
+GLchar const * const textFragmentShaderSource[] =
+{
+ "#version 450 core\n"
+ "out vec4 color;\n"
+ "in vec2 uvFromV;\n"
+ "uniform sampler2D textureSampler;\n"
+ "uniform vec4 textColor;\n"
+ "void main(void)\n"
+ "{\n"
+ " color = texture(textureSampler, uvFromV);\n"
+ " color.rgb = textColor.rgb;\n"
+ "}\n"
+};
+
+void freeOglmd(OpenGLModelData *p)
+{
+ if (p) {
+ free(p->uniforms);
+ p->uniforms = NULL;
+ free(p->mvp);
+ p->mvp = NULL;
+ }
+ free(p);
+ p = NULL;
+}
+
+static GLboolean verifyShaderCompilation(GLuint shader)
+{
+ GLint status;
+ char compilationLog[2048];
+
+ dGL.glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ dGL.glGetShaderInfoLog(shader, 2000, NULL, compilationLog);
+ fprintf(stderr, "Shader compilation failed for shaderID=%i\n", shader);
+ fprintf(stderr, "Error message:\n");
+ fprintf(stderr, "%s\n", compilationLog);
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+static GLuint makeProgram(char const * const * vertexShaderSource,
+ char const * const * fragmentShaderSource)
+{
+ GLuint program, vertexShader, fragmentShader;
+ GLint status;
+
+ vertexShader = dGL.glCreateShader(GL_VERTEX_SHADER);
+ dGL.glShaderSource(vertexShader, 1, vertexShaderSource, NULL);
+ dGL.glCompileShader(vertexShader);
+ if (!verifyShaderCompilation(vertexShader)) {
+ return 0;
+ }
+
+ fragmentShader = dGL.glCreateShader(GL_FRAGMENT_SHADER);
+ dGL.glShaderSource(fragmentShader, 1, fragmentShaderSource, NULL);
+ dGL.glCompileShader(fragmentShader);
+ if (!verifyShaderCompilation(fragmentShader)) {
+ return 0;
+ }
+
+ program = dGL.glCreateProgram();
+ dGL.glAttachShader(program, vertexShader);
+ dGL.glAttachShader(program, fragmentShader);
+
+ dGL.glDeleteShader(vertexShader);
+ dGL.glDeleteShader(fragmentShader);
+
+ dGL.glLinkProgram(program);
+
+ dGL.glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (!status) {
+ fprintf(stderr, "Link failed for programID=%i\n",program);
+ return 0;
+ }
+ return program;
+}
+
+void drawModel(OpenGLModelData *data)
+{
+ int i;
+
+ dGL.glBindVertexArray(data->vao);
+ dGL.glBindTexture(GL_TEXTURE_2D, data->tex);
+ dGL.glUseProgram(data->program);
+
+ for (i = 0; i < data->uniformCount; i++) {
+ dGL.glUniform4f(data->uniforms[i].index,
+ data->uniforms[i].data[0],
+ data->uniforms[i].data[1],
+ data->uniforms[i].data[2],
+ data->uniforms[i].data[3]);
+ }
+
+ if (data->mvp != NULL) {
+ // This functions expects the mvp to be row-major, openGL internally
+ // uses column major, so we set the transpose parameter to GL_TRUE
+ dGL.glUniformMatrix4fv(dGL.glGetUniformLocation(data->program, "mvp"),
+ 1, GL_TRUE, data->mvp);
+ }
+
+ dGL.glDrawArrays(GL_TRIANGLES, 0, data->vboLen / 3);
+}
+
+static GLuint drawModelSetup(float *modelData,
+ unsigned int modelDataLen,
+ float *textureCoordinates,
+ unsigned int textureCoordinatesLen)
+{
+ GLuint vao;
+ GLuint vertexBuffer, uvBuffer;
+
+ dGL.glGenVertexArrays(1, &vao);
+ dGL.glBindVertexArray(vao);
+
+ dGL.glGenBuffers(1, &vertexBuffer);
+ dGL.glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
+ dGL.glBufferData(GL_ARRAY_BUFFER, modelDataLen * sizeof(float),
+ modelData, GL_STATIC_DRAW);
+ dGL.glEnableVertexAttribArray(0);
+ dGL.glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+ dGL.glGenBuffers(1, &uvBuffer);
+ dGL.glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
+ dGL.glBufferData(GL_ARRAY_BUFFER, textureCoordinatesLen * sizeof(float),
+ textureCoordinates, GL_STATIC_DRAW);
+ dGL.glEnableVertexAttribArray(1);
+ dGL.glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+ return vao;
+}
+
+static GLuint textureSetup(int textureWidth, int textureHeight,
+ void *textureDataRaw32)
+{
+ GLuint texName;
+ dGL.glGenTextures(1, &texName);
+ dGL.glBindTexture(GL_TEXTURE_2D, texName);
+ dGL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ dGL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ dGL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ dGL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ dGL.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+ textureWidth, textureHeight,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, textureDataRaw32);
+
+ return texName;
+}
+
+OpenGLModelData *cubeSetup(GdkPixbuf *image)
+{
+ OpenGLModelData *cube;
+
+ float d = 1;
+ int tmp;
+
+ float modelData[] = {
+ -d / 2, d / 2, -d / 2, // 1
+ d / 2, d / 2, -d / 2, // 2
+ -d / 2, -d / 2, -d / 2, // 3
+ d / 2, -d / 2, -d / 2, // 4
+ -d / 2, -d / 2, -d / 2, // 5
+ d / 2, d / 2, -d / 2, // 6
+
+ -d / 2, d / 2, d / 2, // 7
+ -d / 2, d / 2, -d / 2, // 8
+ -d / 2, -d / 2, d / 2, // 9
+ -d / 2, -d / 2, -d / 2, // 10
+ -d / 2, -d / 2, d / 2, // 11
+ -d / 2, d / 2, -d / 2, // 12
+
+ -d / 2, d / 2, d / 2, // 13
+ d / 2, d / 2, d / 2, // 14
+ -d / 2, d / 2, -d / 2, // 15
+ d / 2, d / 2, -d / 2, // 16
+ -d / 2, d / 2, -d / 2, // 17
+ d / 2, d / 2, d / 2, // 18
+
+ d / 2, d / 2, -d / 2, // 19
+ d / 2, d / 2, d / 2, // 20
+ d / 2, -d / 2, -d / 2, // 21
+ d / 2, -d / 2, d / 2, // 22
+ d / 2, -d / 2, -d / 2, // 23
+ d / 2, d / 2, d / 2, // 24
+
+ -d / 2, -d / 2, -d / 2, // 25
+ d / 2, -d / 2, -d / 2, // 26
+ -d / 2, -d / 2, d / 2, // 27
+ d / 2, -d / 2, d / 2, // 28
+ -d / 2, -d / 2, d / 2, // 29
+ d / 2, -d / 2, -d / 2, // 30
+
+ d / 2, d / 2, d / 2, // 31
+ -d / 2, d / 2, d / 2, // 32
+ d / 2, -d / 2, d / 2, // 33
+ -d / 2, -d / 2, d / 2, // 34
+ d / 2, -d / 2, d / 2, // 35
+ -d / 2, d / 2, d / 2, // 36
+
+ };
+
+ float textureCoordinates[] = {
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+
+ 0, 1,
+ 1, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 1,
+ };
+
+ tmp = makeProgram(cubeVertexShaderSource, cubeFragmentShaderSource);
+
+ if (tmp == 0) {
+ return NULL;
+ }
+
+ cube = malloc(sizeof(OpenGLModelData));
+ memset(cube, 0, sizeof(OpenGLModelData));
+
+ cube->program = (GLuint) tmp;
+
+ // 6 sides in a cube
+ // 2 triangles per side
+ // 3 vertices per triangle
+ // 3 vertex coordinates per vertex
+ // 2 texture coordinates per vertex
+ cube->vboLen = 6 * 2 * 3 * 3;
+ cube->vao = drawModelSetup(modelData, cube->vboLen,
+ textureCoordinates, cube->vboLen / 3 * 2);
+
+ cube->tex = textureSetup(gdk_pixbuf_get_width(image),
+ gdk_pixbuf_get_height(image),
+ gdk_pixbuf_get_pixels(image));
+
+ cube->mvp = malloc(16 * sizeof(float));
+ genIdentityMatrix(cube->mvp);
+
+ return cube;
+}
+
+OpenGLModelData *labelSetup(float x, float y,
+ float width, float height,
+ float red, float green, float blue,
+ GdkPixbuf *image)
+{
+ OpenGLModelData *label;
+ int tmp;
+
+ float modelData[] = {
+ -width/2 + x, height/2 + y, 0, // 1
+ width/2 + x, height/2 + y, 0, // 2
+ -width/2 + x, -height/2 + y, 0, // 3
+ width/2 + x, -height/2 + y, 0, // 4
+ -width/2 + x, -height/2 + y, 0, // 5
+ width/2 + x, height/2 + y, 0, // 6
+ };
+
+ float textureCoordinates[] = {
+ 0, 0,
+ 1, 0,
+ 0, 1,
+ 1, 1,
+ 0, 1,
+ 1, 0,
+ };
+
+ tmp = makeProgram(textVertexShaderSource, textFragmentShaderSource);
+ if (tmp == 0) {
+ return NULL;
+ }
+
+ label = malloc(sizeof(OpenGLModelData));
+ memset(label, 0, sizeof(OpenGLModelData));
+
+ label->program = (GLuint) tmp;
+
+ // 2 triangles
+ // 3 vertices per triangle
+ // 3 vertex coordinates per vertex
+ // 2 texture coordinates per vertex
+ label->vboLen = 2 * 3 * 3;
+ label->vao = drawModelSetup(modelData, label->vboLen,
+ textureCoordinates, label->vboLen/3 * 2);
+
+ label->tex = textureSetup(gdk_pixbuf_get_width(image),
+ gdk_pixbuf_get_height(image),
+ gdk_pixbuf_get_pixels(image));
+
+ label->uniformCount = 1;
+ label->uniforms = malloc(label->uniformCount * sizeof(uniformVec4f));
+ label->uniforms[0].index = dGL.glGetUniformLocation(label->program, "textColor");
+ label->uniforms[0].data[0] = red;
+ label->uniforms[0].data[1] = green;
+ label->uniforms[0].data[2] = blue;
+ label->uniforms[0].data[3] = 0;
+
+ return label;
+}
+
+#endif
diff --git a/src/gtk+-2.x/opengl_wrappers.h b/src/gtk+-2.x/opengl_wrappers.h
new file mode 100644
index 0000000..17ecd18
--- /dev/null
+++ b/src/gtk+-2.x/opengl_wrappers.h
@@ -0,0 +1,68 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2017 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, 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 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, see <http://www.gnu.org/licenses>.
+ */
+
+#ifndef __OPENGL_WRAPPERS_H__
+#define __OPENGL_WRAPPERS_H__
+
+#include "ctkutils.h"
+
+#ifdef CTK_GTK3
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <GL/gl.h>
+
+typedef struct _uniformVec4f uniformVec4f;
+struct _uniformVec4f
+{
+ GLuint index;
+ float data[4];
+};
+
+typedef struct _OpenGLModelData OpenGLModelData;
+struct _OpenGLModelData
+{
+ GLuint vao;
+ int vboLen;
+ GLuint tex;
+ GLuint program;
+ float *mvp;
+ uniformVec4f *uniforms;
+ int uniformCount;
+};
+
+void freeOglmd(OpenGLModelData *p);
+
+extern char const * const cubeVertexShaderSource[1];
+extern char const * const cubeFragmentShaderSource[1];
+extern char const * const textVertexShaderSource[1];
+extern char const * const textFragmentShaderSource[1];
+
+void drawModel(OpenGLModelData *data);
+
+OpenGLModelData *cubeSetup(GdkPixbuf *image);
+
+OpenGLModelData *labelSetup(float x, float y,
+ float width, float height,
+ float red, float green, float blue,
+ GdkPixbuf *image);
+
+#endif
+
+#endif /*__OPENGL_WRAPPERS_H__*/
+
diff --git a/src/image_data/left.png b/src/image_data/left.png
new file mode 100644
index 0000000..a29f632
--- /dev/null
+++ b/src/image_data/left.png
Binary files differ
diff --git a/src/image_data/nvlogo.png b/src/image_data/nvlogo.png
new file mode 100644
index 0000000..dcae1b7
--- /dev/null
+++ b/src/image_data/nvlogo.png
Binary files differ
diff --git a/src/image_data/right.png b/src/image_data/right.png
new file mode 100644
index 0000000..f25e16f
--- /dev/null
+++ b/src/image_data/right.png
Binary files differ
diff --git a/src/src.mk b/src/src.mk
index 10c22de..66ec238 100644
--- a/src/src.mk
+++ b/src/src.mk
@@ -60,11 +60,14 @@ IMAGE_FILES += image_data/help.png
IMAGE_FILES += image_data/led_green.png
IMAGE_FILES += image_data/led_grey.png
IMAGE_FILES += image_data/led_red.png
+IMAGE_FILES += image_data/left.png
IMAGE_FILES += image_data/logo.png
IMAGE_FILES += image_data/logo_tall.png
IMAGE_FILES += image_data/nvidia_icon.png
+IMAGE_FILES += image_data/nvlogo.png
IMAGE_FILES += image_data/opengl.png
IMAGE_FILES += image_data/penguin.png
+IMAGE_FILES += image_data/right.png
IMAGE_FILES += image_data/rj45_input.png
IMAGE_FILES += image_data/rj45_output.png
IMAGE_FILES += image_data/rj45_unused.png
@@ -180,6 +183,11 @@ GTK_SRC += gtk+-2.x/ctkcolorcontrols.c
GTK_SRC += gtk+-2.x/ctk3dvisionpro.c
GTK_SRC += gtk+-2.x/ctkvdpau.c
GTK_SRC += gtk+-2.x/ctkgridlicense.c
+GTK_SRC += gtk+-2.x/ctkglwidget.c
+GTK_SRC += gtk+-2.x/ctkglstereo.c
+GTK_SRC += gtk+-2.x/opengl_loading.c
+GTK_SRC += gtk+-2.x/opengl_wrappers.c
+GTK_SRC += gtk+-2.x/matrix_utils.c
GTK_EXTRA_DIST += gtk+-2.x/ctkxvideo.h
@@ -228,6 +236,11 @@ GTK_EXTRA_DIST += gtk+-2.x/ctkcolorcontrols.h
GTK_EXTRA_DIST += gtk+-2.x/ctk3dvisionpro.h
GTK_EXTRA_DIST += gtk+-2.x/ctkvdpau.h
GTK_EXTRA_DIST += gtk+-2.x/ctkgridlicense.h
+GTK_EXTRA_DIST += gtk+-2.x/ctkglwidget.h
+GTK_EXTRA_DIST += gtk+-2.x/ctkglstereo.h
+GTK_EXTRA_DIST += gtk+-2.x/opengl_loading.h
+GTK_EXTRA_DIST += gtk+-2.x/opengl_wrappers.h
+GTK_EXTRA_DIST += gtk+-2.x/matrix_utils.h
NVIDIA_SETTINGS_EXTRA_DIST += $(GTK_EXTRA_DIST)