*.d
*.swp
test
+test.exe
+Debug/
+Release/
+*.obj
+*.suo
bin = test
CFLAGS = -pedantic -Wall -g
-LDFLAGS = -lX11 -lGL -lm
+
+sys ?= $(shell uname -s | sed 's/MINGW.*/mingw/')
+ifeq ($(sys), mingw)
+ obj = $(src:.c=.w32.o)
+ bin = test.exe
+
+ LDFLAGS = -mconsole -lopengl32 -lgdi32 -lwinmm
+else
+ LDFLAGS = -lX11 -lGL
+endif
$(bin): $(obj)
$(CC) -o $@ $(obj) $(LDFLAGS)
+%.w32.o: %.c
+ $(CC) -o $@ $(CFLAGS) -c $<
+
.PHONY: clean
clean:
rm -f $(obj) $(bin)
+
+.PHONY: cross
+cross:
+ $(MAKE) CC=i686-w64-mingw32-gcc sys=mingw
+
+.PHONY: cross-clean
+cross-clean:
+ $(MAKE) CC=i686-w64-mingw32-gcc sys=mingw clean
into your project source tree, or by building MiniGLUT as a static library and
linking with it.
-MiniGLUT does not intend to replace a proper GLUT library like FreeGLUT for
-hacking OpenGL experiments and small programs. The purpose of MiniGLUT is to
-replace a proper GLUT library when it's time for release, in order to minimize
-runtime dependencies of the resulting binary.
+MiniGLUT does not intend to replace a full GLUT library, like FreeGLUT, for
+hacking small to medium OpenGL programs. The purpose of MiniGLUT is to
+potentially replace a full GLUT library when it's time for release, in order to
+minimize runtime dependencies of the resulting binary.
-A second reason is for porting UNIX OpenGL programs to Windows, especially when
-using the microsoft compiler, where setting up and linking with a proper
-3rd-party library like FreeGLUT is an ordeal in itself. Even more so if you
-decide to statically link, at which point you need to deal with the whole "MSVC
-runtime" chaos. Since MiniGLUT does not call any C library functions, even if
-you decide to link it as a static library, it will not affect your choice of
-MSVC runtime library.
+A second reason to use MiniGLUT is to ease porting of UNIX OpenGL programs to
+Windows, especially when using the microsoft compiler, where setting up and
+linking with a proper 3rd-party library is an ordeal in itself. Even more so if
+you decide to statically link, at which point you need to deal with the whole
+"MSVC runtime" chaos. Even if you decide to link MiniGLUT as a static library,
+instead of dropping it in your code, it still won't present any MSVC runtime
+compatibility issues, since it doesn't call any C library functions whatsoever.
-Missing features
-----------------
+Build
+-----
+Under X11 MiniGLUT depends only on Xlib and OpenGL. Therefore to build a program
+using MiniGLUT you'll need to link with `-lX11 -lGL`.
+
+Under Windows MiniGLUT depends only on OpenGL, GDI and winmm. Therefore to build
+a program using MiniGLUT you'll need to link with `-lopengl32 -lgdi32 -lwinmm`.
+When building with MSVC, linking with the correct libraries is taken care by
+pragmas in the header file. If you wish to avoid the winmm dependency, define
+`MINIGLUT_NO_WINMM`.
+
+To avoid calling C library functions, MiniGLUT uses inline assembly code for
+system calls and trigonometric operations. This makes the default build
+incompatible with non-x86 systems, and with MSVC x64 builds. If you don't mind
+linking with the C library, you can define `MINIGLUT_USE_LIBC` to lift these
+limitations.
+
+License
+-------
+Copyright (C) 2020 John Tsiombikas <nuclear@member.fsf.org>
+
+MiniGLUT is free software. Feel free to use, modify and/or redistribute it,
+under the terms of the GNU General Public License v3, or at your option any
+newer version published by the Free Software Foundation. See COPYING for
+details.
+
+The intention is not to dictate a specific free software license (GPL) but to
+shut the door to proprietary programs. If you want to use MiniGLUT in a free
+software project with an incompatible license, contact me and we will figure out
+a way to enable that.
+
+To learn more about GPL-incompatible free software licenses where this might
+be an issue, see:
+https://www.gnu.org/licenses/license-list.en.html#GPLIncompatibleLicenses
+
+Known Issues
+------------
MiniGLUT being a subset of GLUT, is missing a number of features. Some of them
on purpose to keep it minimal, and some of them because I didn't happen to use
them in a program I wanted to link with MiniGLUT yet.
Missing GLUT features:
- - Only supported systems are UNIX with X11 (GLX) and Windows (WGL).
- - Indexed color contexts.
+ - The only supported systems are: UNIX with X11 (GLX), and Windows (WGL).
- Multiple windows.
- Subwindows.
- Overlays.
- More missing primitives.
If wish to let me know how much you need one of the missing features, or even
-better if you are volunteering to implement it yourself, contact me through
-through email at: nuclear@member.fsf.org
+better if you are volunteering to implement it yourself, send me an email at:
+nuclear@member.fsf.org
Only plain-text emails, hard-wrapped at 72 columns will be accepted.
-
-License
--------
-Copyright (C) 2020 John Tsiombikas <nuclear@member.fsf.org>
-
-MiniGLUT is free software. Feel free to use, modify and/or redistribute it,
-under the terms of the GNU General Public License v3, or at your option any
-newer version published by the Free Software Foundation. See COPYING for
-details.
-
-The intention is not to dictate a specific free software license (GPL) but to
-shut the door to proprietary programs. If you want to use MiniGLUT in a free
-software project with an incompatible free software license, contact me, and we
-will figure out a way to enable that. Usually only other copyleft licenses are
-incompatible with the GPL. There's no issue with combining GPL code with code
-using other non-copyleft free software licenses like MIT/X11, 3-clause BSD, and
-so on.
-See: https://www.gnu.org/licenses/license-list.en.html#GPLIncompatibleLicenses
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-/*#define MINIGLUT_GCC_NO_BUILTIN*/
-
#ifdef MINIGLUT_USE_LIBC
#define _GNU_SOURCE
#include <stdlib.h>
#include <math.h>
#else
-
-#if defined(__GNUC__) && !defined(MINIGLUT_GCC_NO_BUILTIN)
-#define mglut_sincosf(a, s, c) __builtin_sincosf(a, s, c)
-#define mglut_atan(x) __builtin_atan(x)
-#else
static void mglut_sincosf(float angle, float *sptr, float *cptr);
static float mglut_atan(float x);
#endif
-#endif
-
#define PI 3.1415926536f
#if defined(__unix__)
static int win_width, win_height;
static int mapped;
static int quit;
-static int upd_pending, reshape_pending;
+static int upd_pending;
static int modstate;
static XVisualInfo *choose_visual(unsigned int mode)
{
XVisualInfo *vi;
- int attr[32] = {
- GLX_RGBA,
- GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 4,
- GLX_GREEN_SIZE, 4,
- GLX_BLUE_SIZE, 4
- };
- int *aptr = attr + 8;
+ int attr[32];
+ int *aptr = attr;
int *samples = 0;
+ if(mode & GLUT_DOUBLE) {
+ *aptr++ = GLX_DOUBLEBUFFER;
+ }
+
+ if(mode & GLUT_INDEX) {
+ *aptr++ = GLX_BUFFER_SIZE;
+ *aptr++ = 1;
+ } else {
+ *aptr++ = GLX_RGBA;
+ *aptr++ = GLX_RED_SIZE; *aptr++ = 4;
+ *aptr++ = GLX_GREEN_SIZE; *aptr++ = 4;
+ *aptr++ = GLX_BLUE_SIZE; *aptr++ = 4;
+ }
if(mode & GLUT_ALPHA) {
*aptr++ = GLX_ALPHA_SIZE;
*aptr++ = 4;
/* --------------- windows implementation ----------------- */
#ifdef BUILD_WIN32
+static int reshape_pending;
+
static void update_modkeys(void);
static int translate_vkey(int vkey);
static void handle_mbutton(int bn, int st, WPARAM wparam, LPARAM lparam);
void glutMainLoopEvent(void)
{
MSG msg;
-
+
if(!cb_display) {
panic("display callback not set");
}
#if defined(__unix__) || defined(__APPLE__)
#include <sys/time.h>
+#ifdef MINIGLUT_USE_LIBC
+#define sys_gettimeofday(tv, tz) gettimeofday(tv, tz)
+#else
+static int sys_gettimeofday(struct timeval *tv, struct timezone *tz);
+#endif
+
static long get_msec(void)
{
static struct timeval tv0;
struct timeval tv;
- gettimeofday(&tv, 0);
+ sys_gettimeofday(&tv, 0);
if(tv0.tv_sec == 0 && tv0.tv_usec == 0) {
tv0 = tv;
return 0;
static long get_msec(void)
{
static long t0;
+ long tm;
+#ifdef MINIGLUT_NO_WINMM
+ tm = GetTickCount();
+#else
+ tm = timeGetTime();
+#endif
if(!t0) {
- t0 = timeGetTime();
+ t0 = tm;
return 0;
}
- return timeGetTime() - t0;
+ return tm - t0;
}
#endif
return write(fd, buf, count);
}
+static int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ return gettimeofday(tv, tz);
+}
+
#else /* !MINIGLUT_USE_LIBC */
-#if defined(__GNUC__) && defined(MINIGLUT_GCC_NO_BUILTIN)
+#ifdef __GNUC__
static void mglut_sincosf(float angle, float *sptr, float *cptr)
{
asm volatile(
{
asm volatile(
"syscall\n\t"
- :: "a"(60), "D"(status)
- );
+ :: "a"(60), "D"(status));
}
static int sys_write(int fd, const void *buf, int count)
{
asm volatile(
"syscall\n\t"
: "=a"(res)
- : "a"(1), "D"(fd), "S"(buf), "d"(count)
- );
+ : "a"(1), "D"(fd), "S"(buf), "d"(count));
+ return res;
+}
+static int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ int res;
+ asm volatile(
+ "syscall\n\t"
+ : "=a"(res)
+ : "a"(96), "D"(tv), "S"(tz));
return res;
}
#endif
static void sys_exit(int status)
{
asm volatile(
- "mov $1, %%eax\n\t"
"int $0x80\n\t"
- :: "b"(status)
- : "eax"
- );
+ :: "a"(1), "b"(status));
}
static int sys_write(int fd, const void *buf, int count)
{
int res;
asm volatile(
- "mov $4, %%eax\n\t"
"int $0x80\n\t"
- :: "b"(fd), "c"(buf), "d"(count));
+ : "=a"(res)
+ : "a"(4), "b"(fd), "c"(buf), "d"(count));
+ return res;
+}
+static int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ int res;
+ asm volatile(
+ "int $0x80\n\t"
+ : "=a"(res)
+ : "a"(78), "b"(tv), "c"(tz));
return res;
}
#endif
}
static int sys_write(int fd, const void *buf, int count)
{
- int wrsz;
+ unsigned long wrsz = 0;
HANDLE out = GetStdHandle(fd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
if(!WriteFile(out, buf, count, &wrsz, 0)) {
#ifdef _MSC_VER
#pragma comment (lib, "opengl32")
+#ifndef MINIGLUT_NO_WINMM
#pragma comment (lib, "winmm")
+#endif
#endif /* MSVC */
#endif
#include "miniglut.h"
+void idle(void);
void display(void);
void reshape(int x, int y);
void keypress(unsigned char key, int x, int y);
float cam_theta, cam_phi = 25, cam_dist = 8;
int mouse_x, mouse_y;
int bnstate[8];
+int anim;
int main(int argc, char **argv)
{
return 0;
}
+void idle(void)
+{
+ glutPostRedisplay();
+}
void display(void)
{
+ long tm;
float lpos[] = {-1, 2, 3, 0};
+
+ tm = glutGet(GLUT_ELAPSED_TIME);
+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
+ glPushMatrix();
+ if(anim) {
+ glRotatef(tm / 10.0f, 1, 0, 0);
+ glRotatef(tm / 10.0f, 0, 1, 0);
+ }
glutSolidTorus(0.3, 1, 16, 24);
+ glPopMatrix();
+
glutSolidSphere(0.4, 16, 8);
glPushMatrix();
void keypress(unsigned char key, int x, int y)
{
- if(key == 27 || key == 'q') {
+ switch(key) {
+ case 27:
+ case 'q':
glutExit();
+ break;
+
+ case ' ':
+ anim ^= 1;
+ glutIdleFunc(anim ? idle : 0);
+ glutPostRedisplay();
+ break;
}
}