summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2012-10-19 19:10:16 -0400
committerJerome Glisse <jglisse@redhat.com>2012-10-19 19:10:16 -0400
commit939e5b32c610ab4ce385b6156947726d7ec97bec (patch)
tree0ca20c2688f06f707a5ee9e0803ef297a2831541
gputoolbox: initial commit
Repository to gather customized gl test program either to stress test some architecture change like kernel. Or to help in reverse engineering process. Signed-off-by: Jerome Glisse <jglisse@redhat.com>
-rw-r--r--Makefile13
-rw-r--r--amd-gpu-name.c48
-rw-r--r--amd_pci_helper.h452
-rw-r--r--glgears-box-cstrealloc.c536
-rw-r--r--glgears-box.c509
-rw-r--r--glgears.c299
-rw-r--r--gltransformfeedback.c332
7 files changed, 2189 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1f754f1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+CC = gcc
+CFLAGS = -I . -g -O0 -Wall -std=c99 -lGL -lGLU -lm -D_BSD_SOURCE
+
+TARGETS = amd-gpu-name glgears glgears-box glgears-box-cstrealloc \
+ gltransformfeedback
+
+all: $(TARGETS)
+
+$(TARGETS): %: %.c
+ $(CC) $(CFLAGS) $< -lpciaccess -lX11 -lGLEW -lglut -o $@
+
+clean:
+ rm -f $(TARGETS)
diff --git a/amd-gpu-name.c b/amd-gpu-name.c
new file mode 100644
index 0000000..f8386a3
--- /dev/null
+++ b/amd-gpu-name.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * author: Jerome Glisse
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pciaccess.h>
+#include "amd_pci_helper.h"
+
+int main(int argc, const char *argv[])
+{
+ struct amd_device adev;
+ int r;
+
+ r = amd_pci_probe(&adev);
+ if (r) {
+ return r;
+ }
+
+ printf("%s-%s", amd_family_name(adev.info.family), amd_chip_name(adev.info.family));
+
+ return 0;
+}
diff --git a/amd_pci_helper.h b/amd_pci_helper.h
new file mode 100644
index 0000000..6be5c12
--- /dev/null
+++ b/amd_pci_helper.h
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * author: Jerome Glisse
+ */
+#ifndef AMD_PCI_HELPER_H
+#define AMD_PCI_HELPER_H
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pciaccess.h>
+
+enum radeon_family {
+ CHIP_UNKNOWN,
+ CHIP_R600,
+ CHIP_RV610,
+ CHIP_RV630,
+ CHIP_RV670,
+ CHIP_RV620,
+ CHIP_RV635,
+ CHIP_RS780,
+ CHIP_RS880,
+ CHIP_RV770,
+ CHIP_RV730,
+ CHIP_RV710,
+ CHIP_RV740,
+ CHIP_CEDAR,
+ CHIP_REDWOOD,
+ CHIP_JUNIPER,
+ CHIP_CYPRESS,
+ CHIP_HEMLOCK,
+ CHIP_PALM,
+ CHIP_SUMO,
+ CHIP_SUMO2,
+ CHIP_BARTS,
+ CHIP_TURKS,
+ CHIP_CAICOS,
+ CHIP_CAYMAN,
+ CHIP_LAST,
+};
+
+static const char *amd_chip_name(unsigned family)
+{
+ switch (family) {
+ case CHIP_R600: return "r600";
+ case CHIP_RV610: return "rv610";
+ case CHIP_RV630: return "rv630";
+ case CHIP_RV670: return "rv670";
+ case CHIP_RV620: return "rv620";
+ case CHIP_RV635: return "rv635";
+ case CHIP_RS780: return "rs780";
+ case CHIP_RS880: return "rs880";
+ case CHIP_RV770: return "rv770";
+ case CHIP_RV730: return "rv730";
+ case CHIP_RV710: return "rv710";
+ case CHIP_RV740: return "rv740";
+ case CHIP_CEDAR: return "cedar";
+ case CHIP_REDWOOD: return "redwood";
+ case CHIP_JUNIPER: return "juniper";
+ case CHIP_CYPRESS: return "cypress";
+ case CHIP_HEMLOCK: return "hemlock";
+ case CHIP_PALM: return "palm";
+ case CHIP_SUMO: return "sumo";
+ case CHIP_SUMO2: return "sumo2";
+ case CHIP_BARTS: return "barts";
+ case CHIP_TURKS: return "turks";
+ case CHIP_CAICOS: return "caicos";
+ case CHIP_CAYMAN: return "cayman";
+ case CHIP_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
+
+static const char *amd_family_name(unsigned family)
+{
+ switch (family) {
+ case CHIP_R600:
+ case CHIP_RV610:
+ case CHIP_RV630:
+ case CHIP_RV670:
+ case CHIP_RV620:
+ case CHIP_RV635:
+ case CHIP_RS780:
+ case CHIP_RS880:
+ return "hd2xxx";
+ case CHIP_RV770:
+ case CHIP_RV730:
+ case CHIP_RV710:
+ case CHIP_RV740:
+ return "hd4xxx";
+ case CHIP_CEDAR:
+ case CHIP_REDWOOD:
+ case CHIP_JUNIPER:
+ case CHIP_CYPRESS:
+ case CHIP_HEMLOCK:
+ case CHIP_PALM:
+ case CHIP_SUMO:
+ case CHIP_SUMO2:
+ case CHIP_BARTS:
+ case CHIP_TURKS:
+ case CHIP_CAICOS:
+ case CHIP_CAYMAN:
+ return "hd5xxx";
+ case CHIP_UNKNOWN:
+ default:
+ return "unknown";
+ }
+}
+
+struct amd_info {
+ unsigned vendor;
+ unsigned device;
+ unsigned family;
+};
+
+static const struct amd_info amd_infos[] = {
+ {0x1002, 0x9610, CHIP_RS780},
+ {0x1002, 0x9611, CHIP_RS780},
+ {0x1002, 0x9612, CHIP_RS780},
+ {0x1002, 0x9613, CHIP_RS780},
+ {0x1002, 0x9614, CHIP_RS780},
+ {0x1002, 0x9615, CHIP_RS780},
+ {0x1002, 0x9616, CHIP_RS780},
+ {0x1002, 0x9710, CHIP_RS880},
+ {0x1002, 0x9711, CHIP_RS880},
+ {0x1002, 0x9712, CHIP_RS880},
+ {0x1002, 0x9713, CHIP_RS880},
+ {0x1002, 0x9714, CHIP_RS880},
+ {0x1002, 0x9715, CHIP_RS880},
+ {0x1002, 0x9400, CHIP_R600},
+ {0x1002, 0x9401, CHIP_R600},
+ {0x1002, 0x9402, CHIP_R600},
+ {0x1002, 0x9403, CHIP_R600},
+ {0x1002, 0x9405, CHIP_R600},
+ {0x1002, 0x940A, CHIP_R600},
+ {0x1002, 0x940B, CHIP_R600},
+ {0x1002, 0x940F, CHIP_R600},
+ {0x1002, 0x94C0, CHIP_RV610},
+ {0x1002, 0x94C1, CHIP_RV610},
+ {0x1002, 0x94C3, CHIP_RV610},
+ {0x1002, 0x94C4, CHIP_RV610},
+ {0x1002, 0x94C5, CHIP_RV610},
+ {0x1002, 0x94C6, CHIP_RV610},
+ {0x1002, 0x94C7, CHIP_RV610},
+ {0x1002, 0x94C8, CHIP_RV610},
+ {0x1002, 0x94C9, CHIP_RV610},
+ {0x1002, 0x94CB, CHIP_RV610},
+ {0x1002, 0x94CC, CHIP_RV610},
+ {0x1002, 0x94CD, CHIP_RV610},
+ {0x1002, 0x95C0, CHIP_RV620},
+ {0x1002, 0x95C2, CHIP_RV620},
+ {0x1002, 0x95C4, CHIP_RV620},
+ {0x1002, 0x95C5, CHIP_RV620},
+ {0x1002, 0x95C6, CHIP_RV620},
+ {0x1002, 0x95C7, CHIP_RV620},
+ {0x1002, 0x95C9, CHIP_RV620},
+ {0x1002, 0x95CC, CHIP_RV620},
+ {0x1002, 0x95CD, CHIP_RV620},
+ {0x1002, 0x95CE, CHIP_RV620},
+ {0x1002, 0x95CF, CHIP_RV620},
+ {0x1002, 0x9580, CHIP_RV630},
+ {0x1002, 0x9581, CHIP_RV630},
+ {0x1002, 0x9583, CHIP_RV630},
+ {0x1002, 0x9586, CHIP_RV630},
+ {0x1002, 0x9587, CHIP_RV630},
+ {0x1002, 0x9588, CHIP_RV630},
+ {0x1002, 0x9589, CHIP_RV630},
+ {0x1002, 0x958A, CHIP_RV630},
+ {0x1002, 0x958B, CHIP_RV630},
+ {0x1002, 0x958C, CHIP_RV630},
+ {0x1002, 0x958D, CHIP_RV630},
+ {0x1002, 0x958E, CHIP_RV630},
+ {0x1002, 0x958F, CHIP_RV630},
+ {0x1002, 0x9590, CHIP_RV635},
+ {0x1002, 0x9591, CHIP_RV635},
+ {0x1002, 0x9593, CHIP_RV635},
+ {0x1002, 0x9595, CHIP_RV635},
+ {0x1002, 0x9596, CHIP_RV635},
+ {0x1002, 0x9597, CHIP_RV635},
+ {0x1002, 0x9598, CHIP_RV635},
+ {0x1002, 0x9599, CHIP_RV635},
+ {0x1002, 0x959B, CHIP_RV635},
+ {0x1002, 0x9500, CHIP_RV670},
+ {0x1002, 0x9501, CHIP_RV670},
+ {0x1002, 0x9504, CHIP_RV670},
+ {0x1002, 0x9505, CHIP_RV670},
+ {0x1002, 0x9506, CHIP_RV670},
+ {0x1002, 0x9507, CHIP_RV670},
+ {0x1002, 0x9508, CHIP_RV670},
+ {0x1002, 0x9509, CHIP_RV670},
+ {0x1002, 0x950F, CHIP_RV670},
+ {0x1002, 0x9511, CHIP_RV670},
+ {0x1002, 0x9515, CHIP_RV670},
+ {0x1002, 0x9517, CHIP_RV670},
+ {0x1002, 0x9519, CHIP_RV670},
+ {0x1002, 0x9540, CHIP_RV710},
+ {0x1002, 0x9541, CHIP_RV710},
+ {0x1002, 0x9542, CHIP_RV710},
+ {0x1002, 0x954E, CHIP_RV710},
+ {0x1002, 0x954F, CHIP_RV710},
+ {0x1002, 0x9552, CHIP_RV710},
+ {0x1002, 0x9553, CHIP_RV710},
+ {0x1002, 0x9555, CHIP_RV710},
+ {0x1002, 0x9557, CHIP_RV710},
+ {0x1002, 0x9480, CHIP_RV730},
+ {0x1002, 0x9487, CHIP_RV730},
+ {0x1002, 0x9488, CHIP_RV730},
+ {0x1002, 0x9489, CHIP_RV730},
+ {0x1002, 0x948F, CHIP_RV730},
+ {0x1002, 0x9490, CHIP_RV730},
+ {0x1002, 0x9491, CHIP_RV730},
+ {0x1002, 0x9495, CHIP_RV730},
+ {0x1002, 0x9498, CHIP_RV730},
+ {0x1002, 0x949C, CHIP_RV730},
+ {0x1002, 0x949E, CHIP_RV730},
+ {0x1002, 0x949F, CHIP_RV730},
+ {0x1002, 0x94A0, CHIP_RV740},
+ {0x1002, 0x94A1, CHIP_RV740},
+ {0x1002, 0x94A3, CHIP_RV740},
+ {0x1002, 0x94B1, CHIP_RV740},
+ {0x1002, 0x94B3, CHIP_RV740},
+ {0x1002, 0x94B4, CHIP_RV740},
+ {0x1002, 0x94B5, CHIP_RV740},
+ {0x1002, 0x94B9, CHIP_RV740},
+ {0x1002, 0x9440, CHIP_RV770},
+ {0x1002, 0x9441, CHIP_RV770},
+ {0x1002, 0x9442, CHIP_RV770},
+ {0x1002, 0x9443, CHIP_RV770},
+ {0x1002, 0x9444, CHIP_RV770},
+ {0x1002, 0x9446, CHIP_RV770},
+ {0x1002, 0x944A, CHIP_RV770},
+ {0x1002, 0x944B, CHIP_RV770},
+ {0x1002, 0x944C, CHIP_RV770},
+ {0x1002, 0x944E, CHIP_RV770},
+ {0x1002, 0x9450, CHIP_RV770},
+ {0x1002, 0x9452, CHIP_RV770},
+ {0x1002, 0x9456, CHIP_RV770},
+ {0x1002, 0x945A, CHIP_RV770},
+ {0x1002, 0x945B, CHIP_RV770},
+ {0x1002, 0x9460, CHIP_RV770},
+ {0x1002, 0x9462, CHIP_RV770},
+ {0x1002, 0x946A, CHIP_RV770},
+ {0x1002, 0x946B, CHIP_RV770},
+ {0x1002, 0x947A, CHIP_RV770},
+ {0x1002, 0x947B, CHIP_RV770},
+ {0x1002, 0x68e0, CHIP_CEDAR},
+ {0x1002, 0x68e1, CHIP_CEDAR},
+ {0x1002, 0x68e4, CHIP_CEDAR},
+ {0x1002, 0x68e5, CHIP_CEDAR},
+ {0x1002, 0x68e8, CHIP_CEDAR},
+ {0x1002, 0x68e9, CHIP_CEDAR},
+ {0x1002, 0x68f1, CHIP_CEDAR},
+ {0x1002, 0x68f8, CHIP_CEDAR},
+ {0x1002, 0x68f9, CHIP_CEDAR},
+ {0x1002, 0x68fe, CHIP_CEDAR},
+ {0x1002, 0x68c0, CHIP_REDWOOD},
+ {0x1002, 0x68c1, CHIP_REDWOOD},
+ {0x1002, 0x68c8, CHIP_REDWOOD},
+ {0x1002, 0x68c9, CHIP_REDWOOD},
+ {0x1002, 0x68d8, CHIP_REDWOOD},
+ {0x1002, 0x68d9, CHIP_REDWOOD},
+ {0x1002, 0x68da, CHIP_REDWOOD},
+ {0x1002, 0x68de, CHIP_REDWOOD},
+ {0x1002, 0x68a0, CHIP_JUNIPER},
+ {0x1002, 0x68a1, CHIP_JUNIPER},
+ {0x1002, 0x68a8, CHIP_JUNIPER},
+ {0x1002, 0x68a9, CHIP_JUNIPER},
+ {0x1002, 0x68b0, CHIP_JUNIPER},
+ {0x1002, 0x68b8, CHIP_JUNIPER},
+ {0x1002, 0x68b9, CHIP_JUNIPER},
+ {0x1002, 0x68be, CHIP_JUNIPER},
+ {0x1002, 0x689e, CHIP_CYPRESS},
+ {0x1002, 0x6880, CHIP_CYPRESS},
+ {0x1002, 0x6888, CHIP_CYPRESS},
+ {0x1002, 0x6889, CHIP_CYPRESS},
+ {0x1002, 0x688A, CHIP_CYPRESS},
+ {0x1002, 0x6898, CHIP_CYPRESS},
+ {0x1002, 0x6899, CHIP_CYPRESS},
+ {0x1002, 0x689c, CHIP_HEMLOCK},
+ {0x1002, 0x689d, CHIP_HEMLOCK},
+ {0x1002, 0x9802, CHIP_PALM},
+ {0x1002, 0x9803, CHIP_PALM},
+ {0x1002, 0x9804, CHIP_PALM},
+ {0x1002, 0x9805, CHIP_PALM},
+ {0x1002, 0x9806, CHIP_PALM},
+ {0x1002, 0x9807, CHIP_PALM},
+ {0x1002, 0x9808, CHIP_PALM},
+ {0x1002, 0x9809, CHIP_PALM},
+ {0x1002, 0x980A, CHIP_PALM},
+ {0x1002, 0x9640, CHIP_SUMO},
+ {0x1002, 0x9641, CHIP_SUMO},
+ {0x1002, 0x9642, CHIP_SUMO2},
+ {0x1002, 0x9643, CHIP_SUMO2},
+ {0x1002, 0x9644, CHIP_SUMO2},
+ {0x1002, 0x9645, CHIP_SUMO2},
+ {0x1002, 0x9647, CHIP_SUMO},
+ {0x1002, 0x9648, CHIP_SUMO},
+ {0x1002, 0x9649, CHIP_SUMO},
+ {0x1002, 0x964a, CHIP_SUMO},
+ {0x1002, 0x964b, CHIP_SUMO},
+ {0x1002, 0x964c, CHIP_SUMO},
+ {0x1002, 0x964e, CHIP_SUMO},
+ {0x1002, 0x964f, CHIP_SUMO},
+ {0x1002, 0x6720, CHIP_BARTS},
+ {0x1002, 0x6721, CHIP_BARTS},
+ {0x1002, 0x6722, CHIP_BARTS},
+ {0x1002, 0x6723, CHIP_BARTS},
+ {0x1002, 0x6724, CHIP_BARTS},
+ {0x1002, 0x6725, CHIP_BARTS},
+ {0x1002, 0x6726, CHIP_BARTS},
+ {0x1002, 0x6727, CHIP_BARTS},
+ {0x1002, 0x6728, CHIP_BARTS},
+ {0x1002, 0x6729, CHIP_BARTS},
+ {0x1002, 0x6738, CHIP_BARTS},
+ {0x1002, 0x6739, CHIP_BARTS},
+ {0x1002, 0x673E, CHIP_BARTS},
+ {0x1002, 0x6700, CHIP_CAYMAN},
+ {0x1002, 0x6701, CHIP_CAYMAN},
+ {0x1002, 0x6702, CHIP_CAYMAN},
+ {0x1002, 0x6703, CHIP_CAYMAN},
+ {0x1002, 0x6704, CHIP_CAYMAN},
+ {0x1002, 0x6705, CHIP_CAYMAN},
+ {0x1002, 0x6706, CHIP_CAYMAN},
+ {0x1002, 0x6707, CHIP_CAYMAN},
+ {0x1002, 0x6708, CHIP_CAYMAN},
+ {0x1002, 0x6709, CHIP_CAYMAN},
+ {0x1002, 0x6718, CHIP_CAYMAN},
+ {0x1002, 0x6719, CHIP_CAYMAN},
+ {0x1002, 0x671C, CHIP_CAYMAN},
+ {0x1002, 0x671D, CHIP_CAYMAN},
+ {0x1002, 0x671F, CHIP_CAYMAN},
+ {0x1002, 0x6740, CHIP_TURKS},
+ {0x1002, 0x6741, CHIP_TURKS},
+ {0x1002, 0x6742, CHIP_TURKS},
+ {0x1002, 0x6743, CHIP_TURKS},
+ {0x1002, 0x6744, CHIP_TURKS},
+ {0x1002, 0x6745, CHIP_TURKS},
+ {0x1002, 0x6746, CHIP_TURKS},
+ {0x1002, 0x6747, CHIP_TURKS},
+ {0x1002, 0x6748, CHIP_TURKS},
+ {0x1002, 0x6749, CHIP_TURKS},
+ {0x1002, 0x674A, CHIP_TURKS},
+ {0x1002, 0x6750, CHIP_TURKS},
+ {0x1002, 0x6751, CHIP_TURKS},
+ {0x1002, 0x6758, CHIP_TURKS},
+ {0x1002, 0x6759, CHIP_TURKS},
+ {0x1002, 0x675B, CHIP_TURKS},
+ {0x1002, 0x675D, CHIP_TURKS},
+ {0x1002, 0x675F, CHIP_TURKS},
+ {0x1002, 0x6840, CHIP_TURKS},
+ {0x1002, 0x6841, CHIP_TURKS},
+ {0x1002, 0x6842, CHIP_TURKS},
+ {0x1002, 0x6843, CHIP_TURKS},
+ {0x1002, 0x6849, CHIP_TURKS},
+ {0x1002, 0x6850, CHIP_TURKS},
+ {0x1002, 0x6858, CHIP_TURKS},
+ {0x1002, 0x6859, CHIP_TURKS},
+ {0, 0},
+};
+
+void amd_info_match(struct amd_info *info)
+{
+ info->family = CHIP_UNKNOWN;
+ for (unsigned i = 0; ; i++) {
+ if (!amd_infos[i].vendor) {
+ return;
+ }
+ if (info->device == amd_infos[i].device) {
+ *info = amd_infos[i];
+ return;
+ }
+ }
+}
+
+struct amd_device {
+ struct pci_device *device;
+ struct amd_info info;
+};
+
+static int amd_pci_probe(struct amd_device *adev)
+{
+ struct pci_slot_match match;
+ struct pci_device_iterator *iter;
+ struct pci_device *device;
+ int r;
+
+ adev->device = NULL;
+
+ r = pci_system_init();
+ if (r) {
+ fprintf(stderr, "error: failed to initialise libpciaccess: %s\n", strerror(r));
+ return r;
+ }
+
+ match.domain = PCI_MATCH_ANY;
+ match.bus = PCI_MATCH_ANY;
+ match.dev = PCI_MATCH_ANY;
+ match.func = 0;
+ match.match_data = 0;
+ iter = pci_slot_match_iterator_create(&match);
+
+ while ((device = pci_device_next(iter))) {
+ pci_device_probe(device);
+ if (device->vendor_id != 0x1002) {
+ continue;
+ }
+ if ((device->device_class & 0x00ffff00) != 0x00030000 &&
+ (device->device_class & 0x00ffff00) != 0x00038000) {
+ continue;
+ }
+ break;
+ }
+ pci_iterator_destroy(iter);
+
+ if (device == NULL) {
+ fprintf(stderr, "cannot find amd gpu device\n");
+ return -ENODEV;
+ }
+
+ adev->device = device;
+ adev->info.vendor = device->vendor_id;
+ adev->info.device = device->device_id;
+ amd_info_match(&adev->info);
+ return 0;
+}
+
+#endif
diff --git a/glgears-box-cstrealloc.c b/glgears-box-cstrealloc.c
new file mode 100644
index 0000000..e76fff7
--- /dev/null
+++ b/glgears-box-cstrealloc.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * This is a port of the infamous "glxgears" demo to straight EGL
+ * Port by Dane Rushton 10 July 2005
+ *
+ * No command line options.
+ * Program runs for 5 seconds then exits, outputing framerate to console
+ */
+#define MAXFRAME 50000
+#define PFINISH 0
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glew.h>
+#include <GL/glut.h>
+#include <GL/glu.h>
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+static GLfloat cube_rot = 0.0;
+static GLuint gears_fbo, gears_tex;
+static GLuint win_width = 1024;
+static GLuint win_height = 512;
+static GLuint frames = 0;
+static GLuint renderbuffers[3];
+static GLuint nrenderbuffers = 0;
+static GLint T0 = 0;
+
+GLuint generate_simple_fbo(unsigned width, unsigned height)
+{
+ GLuint fb;
+ GLenum status;
+ unsigned color, stencil, depth, packed;
+
+ color = stencil = depth = packed = 1;
+
+ /* texture */
+ glGenTextures(1, &gears_tex);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ glGenFramebuffers(1, &fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+
+
+ if (color) {
+#if 0
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+#else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gears_tex, 0);
+#endif
+ }
+
+ if (stencil) {
+ const GLenum format = (packed)
+ ? GL_DEPTH24_STENCIL8
+ : GL_STENCIL_INDEX8;
+ const GLenum attachment = (packed)
+ ? GL_DEPTH_STENCIL_ATTACHMENT
+ : GL_STENCIL_ATTACHMENT;
+
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ if (!packed && depth) {
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "%s %d Unexpected GL error: 0x%x %s\n", __func__, __LINE__, status, gluErrorString(status));
+ exit(1);
+ }
+
+ /* All of the possible combinations that we can generate are required
+ * to be supported by all OpenGL 3.0 implementations, with one
+ * exception. As far as I can tell, implementations are not required
+ * to support separate depth and stencil. That one option is handled
+ * specially.
+ */
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE
+ && !(status == GL_FRAMEBUFFER_UNSUPPORTED && stencil && !packed)) {
+ fprintf(stderr,
+ "Framebuffer %s color, %s stencil (%s) was not "
+ "complete: 0x%04x\n",
+ color ? "with" : "without",
+ stencil ? "with" : "without",
+ packed ? "packed" : "separate",
+ status);
+ exit(1);
+ }
+
+ if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
+ glDeleteFramebuffers(1, &fb);
+ glDeleteRenderbuffers(nrenderbuffers, renderbuffers);
+ fprintf(stderr, "Unsupported framebuffer\n");
+ exit(1);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+#if 0
+ glClearColor(0.2, 0.4, 0.6, 1.0);
+ glClearDepth(0.5);
+ glClearStencil(0x7a);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glFinish();
+#endif
+ return fb;
+}
+
+void freefbo(void)
+{
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &gears_fbo);
+ glDeleteRenderbuffers(nrenderbuffers, renderbuffers);
+ glDeleteTextures(1, &gears_tex);
+ nrenderbuffers = 0;
+}
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ glShadeModel(GL_FLAT);
+
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ u = r2 * cos(angle + da) - r1 * cos(angle);
+ v = r2 * sin(angle + da) - r1 * sin(angle);
+ len = sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ }
+
+ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glNormal3f(-cos(angle), -sin(angle), 0.0);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ }
+ glEnd();
+}
+
+static void draw_gear(void)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, gears_fbo);
+#if PFINISH
+ fprintf(stderr, "EE CLEAR FBO -------------------------------------------------\n");
+#endif
+ glClearColor(0.5, 0.5, 0.8, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR FBO _________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW FBO --------------------------------------------------\n");
+#endif
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(angle, 0.0, 0.0, 1.0);
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1, -2.0, 0.0);
+ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1, 4.2, 0.0);
+ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW FBO __________________________________________________\n");
+#endif
+}
+
+static void draw_cube(void)
+{
+ static const GLfloat texcoords[4][2] = {
+ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
+ };
+ static const GLfloat vertices[4][2] = {
+ { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
+ };
+ static const GLfloat xforms[6][4] = {
+ { 0, 0, 1, 0 },
+ { 90, 0, 1, 0 },
+ { 180, 0, 1, 0 },
+ { 270, 0, 1, 0 },
+ { 90, 1, 0, 0 },
+ { -90, 1, 0, 0 }
+ };
+ static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
+ float ar;
+ GLint i, j;
+
+#if PFINISH
+ fprintf(stderr, "EE CLEAR -----------------------------------------------------\n");
+#endif
+ glClearColor(0.8, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR _____________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW ------------------------------------------------------\n");
+#endif
+ ar = (float)win_width / win_height;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(15, 1, 0, 0);
+ glRotatef(cube_rot, 0, 1, 0);
+ glScalef(4, 4, 4);
+
+ for (i = 0; i < 6; i++) {
+ glPushMatrix();
+ glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
+ glTranslatef(0, 0, 1.1);
+ glBegin(GL_POLYGON);
+ glNormal3f(0, 0, 1);
+ for (j = 0; j < 4; j++) {
+ glTexCoord2fv(texcoords[j]);
+ glVertex2fv(vertices[j]);
+ }
+ glEnd();
+ glPopMatrix();
+ }
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW ______________________________________________________\n");
+#endif
+}
+
+static void draw(void)
+{
+ draw_gear();
+ draw_cube();
+ glutSwapBuffers();
+
+ frames++;
+ if (frames >= MAXFRAME) {
+ glFinish();
+ exit(0);
+ }
+ {
+ GLint t = glutGet(GLUT_ELAPSED_TIME);
+ if (t - T0 >= 5000) {
+ GLfloat seconds = (t - T0) / 1000.0;
+ GLfloat fps = frames / seconds;
+ printf("%d frames in %6.3f seconds = %6.3f FPS\n", frames, seconds, fps);
+ fflush(stdout);
+ T0 = t;
+ frames = 0;
+ exit(0);
+ }
+ }
+
+ freefbo();
+ gears_fbo = generate_simple_fbo(512, 512);
+}
+
+static void idle(void)
+{
+ static double t0 = -1.;
+ double dt, t;
+
+ t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+
+ angle += 70.0 * dt; /* 70 degrees per second */
+ angle = fmod(angle, 360.0); /* prevents eventual overflow */
+ cube_rot = fmod(cube_rot + 15.0 * dt, 360.0); /* 15 deg/sec */
+
+ glutPostRedisplay();
+}
+
+/* new window size or exposure */
+static void reshape(int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ win_width = width;
+ win_height = height;
+}
+
+static void init(void)
+{
+ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0, 4.0, 1.0, 20, 0.7);
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5, 2.0, 2.0, 10, 0.7);
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3, 2.0, 0.5, 10, 0.7);
+ glEndList();
+
+ gears_fbo = generate_simple_fbo(512, 512);
+
+ glEnable(GL_NORMALIZE);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
+ glutInitWindowSize(win_width, win_height);
+ glutCreateWindow("eglgears");
+
+ GLenum err = glewInit();
+ if (GLEW_OK != err) {
+ fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
+ return -1;
+ }
+
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+
+ init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/glgears-box.c b/glgears-box.c
new file mode 100644
index 0000000..6e0f9c9
--- /dev/null
+++ b/glgears-box.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+/*
+ * This is a port of the infamous "glxgears" demo to straight EGL
+ * Port by Dane Rushton 10 July 2005
+ *
+ * No command line options.
+ * Program runs for 5 seconds then exits, outputing framerate to console
+ */
+#define MAXFRAME 5
+#define PFINISH 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+static GLfloat cube_rot = 0.0;
+static GLuint gears_fbo, gears_tex;
+static GLuint win_width = 1024;
+static GLuint win_height = 512;
+static GLuint frames = 0;
+static GLuint renderbuffers[3];
+static GLuint nrenderbuffers = 0;
+
+GLuint generate_simple_fbo(unsigned width, unsigned height)
+{
+ GLuint fb;
+ GLenum status;
+ unsigned color, stencil, depth, packed;
+
+ color = stencil = depth = packed = 1;
+
+ /* texture */
+ glGenTextures(1, &gears_tex);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ glGenFramebuffers(1, &fb);
+ glBindFramebuffer(GL_FRAMEBUFFER, fb);
+
+
+ if (color) {
+#if 0
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+#else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gears_tex, 0);
+#endif
+ }
+
+ if (stencil) {
+ const GLenum format = (packed)
+ ? GL_DEPTH24_STENCIL8
+ : GL_STENCIL_INDEX8;
+ const GLenum attachment = (packed)
+ ? GL_DEPTH_STENCIL_ATTACHMENT
+ : GL_STENCIL_ATTACHMENT;
+
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ if (!packed && depth) {
+ glGenRenderbuffers(1, &renderbuffers[nrenderbuffers]);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffers[nrenderbuffers]);
+ nrenderbuffers++;
+ }
+
+ status = glGetError();
+ if (status != GL_NO_ERROR) {
+ fprintf(stderr, "Unexpected GL error: 0x%x\n", status);
+ exit(1);
+ }
+
+ /* All of the possible combinations that we can generate are required
+ * to be supported by all OpenGL 3.0 implementations, with one
+ * exception. As far as I can tell, implementations are not required
+ * to support separate depth and stencil. That one option is handled
+ * specially.
+ */
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if (status != GL_FRAMEBUFFER_COMPLETE
+ && !(status == GL_FRAMEBUFFER_UNSUPPORTED && stencil && !packed)) {
+ fprintf(stderr,
+ "Framebuffer %s color, %s stencil (%s) was not "
+ "complete: 0x%04x\n",
+ color ? "with" : "without",
+ stencil ? "with" : "without",
+ packed ? "packed" : "separate",
+ status);
+ exit(1);
+ }
+
+ if (status == GL_FRAMEBUFFER_UNSUPPORTED) {
+ glDeleteRenderbuffers(nrenderbuffers, renderbuffers);
+ glDeleteFramebuffers(1, &fb);
+ fprintf(stderr, "Unsupported framebuffer\n");
+ exit(1);
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+#if 0
+ glClearColor(0.2, 0.4, 0.6, 1.0);
+ glClearDepth(0.5);
+ glClearStencil(0x7a);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glFinish();
+#endif
+ return fb;
+}
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ glShadeModel(GL_FLAT);
+
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ u = r2 * cos(angle + da) - r1 * cos(angle);
+ v = r2 * sin(angle + da) - r1 * sin(angle);
+ len = sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ }
+
+ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glNormal3f(-cos(angle), -sin(angle), 0.0);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ }
+ glEnd();
+}
+
+static void draw_gear(void)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, gears_fbo);
+#if PFINISH
+ fprintf(stderr, "EE CLEAR FBO -------------------------------------------------\n");
+#endif
+ glClearColor(0.5, 0.5, 0.8, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR FBO _________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW FBO --------------------------------------------------\n");
+#endif
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(angle, 0.0, 0.0, 1.0);
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1, -2.0, 0.0);
+ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1, 4.2, 0.0);
+ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW FBO __________________________________________________\n");
+#endif
+}
+
+static void draw_cube(void)
+{
+ static const GLfloat texcoords[4][2] = {
+ { 0, 0 }, { 1, 0 }, { 1, 1 }, { 0, 1 }
+ };
+ static const GLfloat vertices[4][2] = {
+ { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 }
+ };
+ static const GLfloat xforms[6][4] = {
+ { 0, 0, 1, 0 },
+ { 90, 0, 1, 0 },
+ { 180, 0, 1, 0 },
+ { 270, 0, 1, 0 },
+ { 90, 1, 0, 0 },
+ { -90, 1, 0, 0 }
+ };
+ static const GLfloat mat[4] = { 1.0, 1.0, 0.5, 1.0 };
+ float ar;
+ GLint i, j;
+
+#if PFINISH
+ fprintf(stderr, "EE CLEAR -----------------------------------------------------\n");
+#endif
+ glClearColor(0.8, 0.5, 0.5, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE CLEAR _____________________________________________________\n");
+#endif
+
+#if PFINISH
+ fprintf(stderr, "EE DRAW ------------------------------------------------------\n");
+#endif
+ ar = (float)win_width / win_height;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, mat);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, gears_tex);
+
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(15, 1, 0, 0);
+ glRotatef(cube_rot, 0, 1, 0);
+ glScalef(4, 4, 4);
+
+ for (i = 0; i < 6; i++) {
+ glPushMatrix();
+ glRotatef(xforms[i][0], xforms[i][1], xforms[i][2], xforms[i][3]);
+ glTranslatef(0, 0, 1.1);
+ glBegin(GL_POLYGON);
+ glNormal3f(0, 0, 1);
+ for (j = 0; j < 4; j++) {
+ glTexCoord2fv(texcoords[j]);
+ glVertex2fv(vertices[j]);
+ }
+ glEnd();
+ glPopMatrix();
+ }
+ glPopMatrix();
+
+ glDisable(GL_TEXTURE_2D);
+#if PFINISH
+ glFinish();
+ fprintf(stderr, "EE DRAW ______________________________________________________\n");
+#endif
+}
+
+static void draw(void)
+{
+ draw_gear();
+
+ draw_cube();
+ glutSwapBuffers();
+ frames++;
+ if (frames >= MAXFRAME) {
+ glFinish();
+ exit(0);
+ }
+}
+
+static void idle(void)
+{
+ static double t0 = -1.;
+ double dt, t;
+
+ t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+
+ angle += 70.0 * dt; /* 70 degrees per second */
+ angle = fmod(angle, 360.0); /* prevents eventual overflow */
+ cube_rot = fmod(cube_rot + 15.0 * dt, 360.0); /* 15 deg/sec */
+
+ glutPostRedisplay();
+}
+
+/* new window size or exposure */
+static void reshape(int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ win_width = width;
+ win_height = height;
+}
+
+static void init(void)
+{
+ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0, 4.0, 1.0, 20, 0.7);
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5, 2.0, 2.0, 10, 0.7);
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3, 2.0, 0.5, 10, 0.7);
+ glEndList();
+
+ gears_fbo = generate_simple_fbo(512, 512);
+
+ glEnable(GL_NORMALIZE);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
+ glutInitWindowSize(win_width, win_height);
+ glutCreateWindow("glgears");
+
+ GLenum err = glewInit();
+ if (GLEW_OK != err) {
+ fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
+ return -1;
+ }
+
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+
+ init();
+ glutMainLoop();
+ return 0;
+}
diff --git a/glgears.c b/glgears.c
new file mode 100644
index 0000000..5432464
--- /dev/null
+++ b/glgears.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is a port of the infamous "glxgears" demo to straight EGL
+ * Port by Dane Rushton 10 July 2005
+ *
+ * No command line options.
+ * Program runs for 5 seconds then exits, outputing framerate to console
+ */
+#define MAXFRAME 5
+
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/glut.h>
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+static GLuint win_width = 1024;
+static GLuint win_height = 512;
+static GLuint frames = 0;
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0;
+ r2 = outer_radius + tooth_depth / 2.0;
+
+ da = 2.0 * M_PI / teeth / 4.0;
+
+ glShadeModel(GL_FLAT);
+
+ glNormal3f(0.0, 0.0, 1.0);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ if (i < teeth) {
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ }
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.0 * M_PI / teeth / 4.0;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+ u = r2 * cos(angle + da) - r1 * cos(angle);
+ v = r2 * sin(angle + da) - r1 * sin(angle);
+ len = sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ width * 0.5);
+ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
+ -width * 0.5);
+ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ width * 0.5);
+ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
+ -width * 0.5);
+ glNormal3f(cos(angle), sin(angle), 0.0);
+ }
+
+ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.0 * M_PI / teeth;
+ glNormal3f(-cos(angle), -sin(angle), 0.0);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+ }
+ glEnd();
+}
+
+static void draw(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(angle, 0.0, 0.0, 1.0);
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1, -2.0, 0.0);
+ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1, 4.2, 0.0);
+ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+ glutSwapBuffers();
+
+ frames++;
+ if (frames >= MAXFRAME) {
+ glFinish();
+ exit(0);
+ }
+}
+
+static void idle(void)
+{
+ static double t0 = -1.;
+ double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+
+ angle += 70.0 * dt; /* 70 degrees per second */
+ angle = fmod(angle, 360.0); /* prevents eventual overflow */
+
+ glutPostRedisplay();
+}
+
+/* new window size or exposure */
+static void reshape(int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+}
+
+
+static void init(void)
+{
+ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 };
+ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.0, 4.0, 1.0, 20, 0.7);
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5, 2.0, 2.0, 10, 0.7);
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3, 2.0, 0.5, 10, 0.7);
+ glEndList();
+
+ glEnable(GL_NORMALIZE);
+}
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
+ glutInitWindowSize(win_width, win_height);
+
+ glutCreateWindow("glgears");
+
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+
+ init();
+ glDrawBuffer(GL_BACK);
+ glutMainLoop();
+
+ return 0;
+}
diff --git a/gltransformfeedback.c b/gltransformfeedback.c
new file mode 100644
index 0000000..c991b75
--- /dev/null
+++ b/gltransformfeedback.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * author: Jerome Glisse
+ */
+#define MAXFRAME 50000
+#define PFINISH 1
+#define MAX_PARTICLES 256
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#define GL_GLEXT_PROTOTYPES
+#include <GL/glew.h>
+#include <GL/glut.h>
+
+struct particle {
+ float pos[4];
+ float vel[4];
+};
+
+static struct particle *particles;
+
+static GLuint particle_buffer[2];
+static GLuint tfb_shader_prog;
+static GLuint tfb_vs_shader;
+static GLuint random_tex;
+
+static GLint ptime = 0;
+static GLfloat pdt = 0.0f;
+static GLuint curr_vb = 0;
+static GLuint frames = 0;
+static GLuint win_width = 1024;
+static GLuint win_height = 1024;
+
+static GLint attrib_velocity;
+static GLint uni_delta_time_ms;
+static GLint uni_tex;
+
+static const char tfb_shader_src[] =
+ "#version 120 \n"
+ " \n"
+ "attribute vec4 velocity; \n"
+ "attribute float age; \n"
+ " \n"
+ "varying vec4 ovelocity; \n"
+ " \n"
+ "uniform float dt; \n"
+ "uniform sampler1D tex; \n"
+ " \n"
+ "void main() \n"
+ "{ \n"
+ " if (velocity.w > 5.0) { \n"
+ " ovelocity = texture1D(tex, ovelocity.w); \n"
+ " ovelocity -= vec4(0.5, 0.5, 0.5, 0.5); \n"
+ " gl_Position = ovelocity * dt; \n"
+ " } else { \n"
+ " ovelocity = velocity; \n"
+ " ovelocity.w = velocity.w + dt; \n"
+ " gl_Position.xyz = gl_Vertex.xyz + velocity.xyz * dt; \n"
+ " } \n"
+ "} \n";
+
+static void particles_update(void)
+{
+ glUseProgram(tfb_shader_prog);
+ glUniform1f(uni_delta_time_ms, pdt);
+ glUniform1i(uni_tex, 0);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_1D, random_tex);
+
+ glBindBuffer(GL_ARRAY_BUFFER, particle_buffer[curr_vb]);
+ glEnableVertexAttribArray(attrib_velocity);
+ glVertexAttribPointer(attrib_velocity, 4, GL_FLOAT, GL_FALSE, sizeof(struct particle), (const GLvoid*)16);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(4, GL_FLOAT, sizeof(struct particle), 0);
+
+ glEnable(GL_RASTERIZER_DISCARD);
+ glBindBufferBaseEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particle_buffer[(curr_vb + 1) & 1]);
+ glBeginTransformFeedback(GL_POINTS);
+ glDrawArrays(GL_POINTS, 0, MAX_PARTICLES);
+ glEndTransformFeedback();
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableVertexAttribArray(attrib_velocity);
+ glDisable(GL_RASTERIZER_DISCARD);
+ glUseProgram(0);
+
+ /* swap */
+ curr_vb = (curr_vb + 1) & 1;
+ ptime += pdt;
+}
+
+void particle_draw()
+{
+ float ar;
+
+ ar = (float)win_width / win_height;
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-ar, ar, -1.0, 1.0, 5.0, 60.0);
+ glMatrixMode(GL_MODELVIEW);
+ glPointSize(8.0);
+
+ glColor3f(0,1,0);
+ glBindBuffer(GL_ARRAY_BUFFER, particle_buffer[curr_vb]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(struct particle), 0);
+ glDrawArrays(GL_POINTS, 0, MAX_PARTICLES);
+ glDisableClientState(GL_VERTEX_ARRAY);
+}
+
+static void draw(void)
+{
+ particles_update();
+ glClear(GL_COLOR_BUFFER_BIT);
+ particle_draw();
+
+ glutSwapBuffers();
+ frames++;
+ if (frames >= MAXFRAME) {
+ glFinish();
+ exit(0);
+ }
+}
+
+static void idle(void)
+{
+ static double t0 = -1.;
+ double dt, t;
+
+ t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
+ if (t0 < 0.0)
+ t0 = t;
+ dt = t - t0;
+ t0 = t;
+ pdt = dt;
+
+ glutPostRedisplay();
+}
+
+/* new window size or exposure */
+static void reshape(int width, int height)
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+
+ glViewport(0, 0, (GLint) width, (GLint) height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0, 0.0, -40.0);
+
+ win_width = width;
+ win_height = height;
+}
+
+float random_0to1(void)
+{
+ return (float)rand() / RAND_MAX;
+}
+
+static void init(void)
+{
+ size_t particles_size;
+ const GLchar *p[1];
+ GLint len[1];
+ GLint status;
+ const GLchar* varyings[4];
+ unsigned texsize = 512;
+ float *randomtex;
+
+ glDisable(GL_DEPTH_TEST);
+
+ /* random texture */
+ srand(glutGet(GLUT_ELAPSED_TIME));
+ randomtex = malloc(texsize * 4 * 4);
+ if (randomtex == NULL) {
+ exit(1);
+ }
+ for (unsigned i = 0 ; i < (texsize * 4); i++) {
+ randomtex[i] = random_0to1();
+ }
+ glGenTextures(1, &random_tex);
+ glBindTexture(GL_TEXTURE_1D, random_tex);
+ glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, texsize, 0.0f, GL_RGBA, GL_FLOAT, randomtex);
+ glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ free(randomtex);
+ glBindTexture(GL_TEXTURE_1D, 0);
+
+ particles_size = sizeof(*particles) * MAX_PARTICLES;
+ particles = malloc(particles_size);
+ if (particles == NULL) {
+ exit(-ENOMEM);
+ }
+ glGenBuffers(2, particle_buffer);
+ for (unsigned i = 0; i < MAX_PARTICLES; i++) {
+ particles[i].pos[0] = random_0to1();
+ particles[i].pos[1] = random_0to1();
+ particles[i].pos[2] = random_0to1();
+ particles[i].pos[3] = 0.0f;
+ particles[i].vel[0] = random_0to1() - 0.5f;
+ particles[i].vel[1] = random_0to1() - 0.5f;
+ particles[i].vel[2] = random_0to1() - 0.5f;
+ particles[i].vel[3] = random_0to1() - 0.5f;
+ }
+ for (unsigned i = 0; i < 2 ; i++) {
+ glBindBuffer(GL_ARRAY_BUFFER, particle_buffer[i]);
+ glBufferData(GL_ARRAY_BUFFER, particles_size, particles, GL_DYNAMIC_DRAW);
+ }
+ free(particles);
+
+#if 1
+ /* tfb shader */
+ tfb_shader_prog = glCreateProgram();
+ tfb_vs_shader = glCreateShader(GL_VERTEX_SHADER);
+ p[0] = tfb_shader_src;
+ len[0] = strlen(tfb_shader_src);
+ glShaderSource(tfb_vs_shader, 1, p, len);
+ glCompileShader(tfb_vs_shader);
+ glGetShaderiv(tfb_vs_shader, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ GLchar log[1024];
+
+ glGetShaderInfoLog(tfb_vs_shader, 1024, NULL, log);
+ fprintf(stderr, "Error compiling tfb vs shader %s: \n", log);
+ exit(1);
+ }
+ glAttachShader(tfb_shader_prog, tfb_vs_shader);
+
+ /* tfb linking */
+ varyings[0] = "gl_Position";
+ varyings[1] = "ovelocity";
+ glTransformFeedbackVaryings(tfb_shader_prog, 2, varyings, GL_INTERLEAVED_ATTRIBS);
+
+ glLinkProgram(tfb_shader_prog);
+ glGetProgramiv(tfb_shader_prog, GL_LINK_STATUS, &status);
+ if (!status) {
+ GLchar log[1024];
+
+ glGetProgramInfoLog(tfb_shader_prog, 1024, NULL, log);
+ fprintf(stderr, "Error linking tfb shader %s: \n", log);
+ exit(1);
+ }
+ glValidateProgram(tfb_shader_prog);
+ glGetProgramiv(tfb_shader_prog, GL_VALIDATE_STATUS, &status);
+ if (!status) {
+ GLchar log[1024];
+
+ glGetProgramInfoLog(tfb_shader_prog, 1024, NULL, log);
+ fprintf(stderr, "Invalid tfb shader program %s: \n", log);
+ exit(1);
+ }
+ uni_delta_time_ms = glGetUniformLocation(tfb_shader_prog, "dt");
+ uni_tex = glGetUniformLocation(tfb_shader_prog, "tex");
+
+ attrib_velocity = glGetAttribLocation(tfb_shader_prog, "velocity");
+ if (attrib_velocity == -1) {
+ fprintf(stderr, "invalid attribute location %d\n", attrib_velocity);
+ exit(-1);
+ }
+#endif
+}
+
+static void key(unsigned char k, int x, int y)
+{
+ switch (k) {
+ case 27: /* Escape */
+ exit(0);
+ break;
+ default:
+ return;
+ }
+ glutPostRedisplay();
+}
+
+int main(int argc, char *argv[])
+{
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_STENCIL);
+ glutInitWindowSize(win_width, win_height);
+ glutCreateWindow("glgears");
+
+ GLenum err = glewInit();
+ if (GLEW_OK != err) {
+ fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
+ return -1;
+ }
+ if (!GLEW_EXT_transform_feedback) {
+ fprintf(stderr, "EXT_transform_feedback not supported\n");
+ return -1;
+ }
+
+ glutKeyboardFunc(key);
+ glutIdleFunc(idle);
+ glutReshapeFunc(reshape);
+ glutDisplayFunc(draw);
+
+ init();
+ glutMainLoop();
+ return 0;
+}