diff options
author | Jerome Glisse <jglisse@redhat.com> | 2012-10-19 19:10:16 -0400 |
---|---|---|
committer | Jerome Glisse <jglisse@redhat.com> | 2012-10-19 19:10:16 -0400 |
commit | 939e5b32c610ab4ce385b6156947726d7ec97bec (patch) | |
tree | 0ca20c2688f06f707a5ee9e0803ef297a2831541 |
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-- | Makefile | 13 | ||||
-rw-r--r-- | amd-gpu-name.c | 48 | ||||
-rw-r--r-- | amd_pci_helper.h | 452 | ||||
-rw-r--r-- | glgears-box-cstrealloc.c | 536 | ||||
-rw-r--r-- | glgears-box.c | 509 | ||||
-rw-r--r-- | glgears.c | 299 | ||||
-rw-r--r-- | gltransformfeedback.c | 332 |
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; +} |