testglobe

Website Repository WebGL

testglobe displays a 3D globe through different graphics APIs and hardware, with an emphasis on systems from the late 1980s and early 1990s. It compares detail from flat-shaded polygons with detail from texture mapping: flat shading assigns each triangle or quad an Earth-map color, while texturing samples the map across it. Texture mapping starts disabled. Higher resolutions use more memory and rendering time.

OpenGL is the original backend. The additional backends and subsequent changes include AI-generated code. The experimental native backends have host regression coverage; native validation remains pending. See Testing and validation for the distinction between host checks and native rendering.

Browser version: live WebGL demo.

OpenGL rendering of the Earth

OpenGL driver running on macOS

Video: testglobe on a Sun Ultra 60 with Elite3D-m6 graphics

Contents

Current drivers

Earth maps store 8-bit palette indices. OpenGL and IRIS GL use those indices in either RGB(A) or color-index windows; Sun XGL expands them to RGB. Matrox LibShell, Windows GDI, and QuickDraw draw through the Earth palette. The browser frontend uses WebGL 2 with the same maps and palette.

Driver Platform Default globe Texture toggle
WebGL Modern browsers with WebGL 2 Key 5: 512 × 256 Yes
OpenGL Linux, Unix and modern macOS Key 5: 512 × 256 Yes
IRIS GL IRIX 4.0, 32-bit MIPS Key 3: 128 × 64 Yes
Sun XGL Solaris 2.6, 32-bit SPARC Key 3: 128 × 64 Yes
Matrox LibShell MS-DOS, PG-641-compatible hardware Key 1: 32 × 16 No
Windows GDI Windows 3.1, 16-bit Key 1: 32 × 16 No
QuickDraw Classic Macintosh System 7, 68000 Key 1: 32 × 16 No

Controls and status

Letter controls accept either case.

Input Action
1–5 Select globe resolution; Matrox LibShell supports only 1 and 2.
Left mouse drag Rotate the globe; the WebGL frontend also supports touch dragging.
a Toggle automatic rotation.
f Toggle FPS measurement and its on-screen statistic.
o Toggle the on-screen display (OSD).
t Toggle texture mapping in OpenGL, IRIS GL, Sun XGL, and WebGL.
d Toggle display lists in OpenGL; enabled by default.
Esc Exit native applications; in WebGL, pause rotation and release dragging.

WebGL also provides on-screen controls and a Reset view button. Its retained GPU buffers replace display lists; the d control applies only to native OpenGL.

Keys 1–5 select maps 32, 64, 128, 256, and 512 pixels wide (EARTH_32 through EARTH_512); map height is half the width. The OSD counts quad patches for Matrox, GDI, and QuickDraw, and triangles for the other drivers. Pole patches count as quads even when coincident vertices collapse to a triangle for drawing.

Console builds print the globe resolution, vertex count, and triangle or quad count after each successful mesh construction. Failed attempts and selecting the current resolution do not repeat these messages. GDI and QuickDraw use their native OSD.

Matrox, GDI, and QuickDraw also report polygons retained after software culling. The other drivers report totals because native culling supplies no visibility count. FPS starts enabled; turning it off leaves rotation timing active. FPS measures the interval between completed presentations, including event-loop waits. It is an interactive frame rate, not a synchronized GPU throughput benchmark; native swap and flush calls provide different completion guarantees. Scene and rendering-mode changes restart the sample.

Status Meaning
texture on The frame uses the graphics API’s texturing path; this does not guarantee hardware acceleration.
texture soft OpenGL or IRIS GL uses the application’s software texture rasterizer.
texture off Texture mapping is disabled.
texture loading WebGL is fetching or uploading a texture; flat colors remain visible.
texture fail Texturing is enabled but a detected failure prevents its use; recoverable failures draw flat colors.
dlist on OpenGL successfully uses a display list for the current frame.
dlist off Display lists are disabled.
dlist fail Lists are enabled but unavailable, failed, or bypassed.
GWorld on / GWorld off QuickDraw is drawing through an offscreen GWorld / directly to the window.

Toggle t off and on to retry after a recoverable texture failure. OpenGL software texturing bypasses display lists, so enabled lists report dlist fail on that path. XGL’s internal software pipeline still reports texture on; IRIS GL cannot detect all silent native texture failures. Their driver sections describe these limits. OpenGL places dlist after FPS and before texture status, with its d help last. QuickDraw appends GWorld status after the other statistics. When a smaller texture is active, its width follows the status, for example texture on (128) or texture soft (128). GDI reports direct drawing, individual polygons, reduced colors, or manual rotation when those fallbacks are active.

On displays of 640 × 480 or smaller, GDI and QuickDraw default to a 320 × 240 client area; larger displays use 640 × 480. Explicit size requests are preserved, with QuickDraw clamping its window to the selected screen.

Resource recovery

Native backends do not rebuild the mesh when its current resolution is selected. When a new mesh cannot be allocated, optional rendering caches are released before retrying. The application can restore the previous resolution or select a smaller supported level; startup uses the same lower-resolution fallback. The OSD identifies the active result and any recovery notice. A scene that still cannot be built leaves a responsive empty window so another resolution can be selected. Bad data and invalid requests remain distinct from insufficient memory.

Insufficient texture memory or a queried native size limit can reduce the image from 512 through 256, 128, 64, and 32 pixels wide. Other native errors are not assumed to be memory shortages. If no usable texture can be created, the request remains enabled while flat colors are drawn and texture fail is reported. Geometry caches and large submission packets are optional: direct drawing or smaller packets preserve the same globe. Fallback resolution, texture size, buffering, and cache use affect performance, so compare runs using the actual reported settings.

These fallbacks preserve usable native rendering resources. Selecting another valid resource can recover from bad map data, but does not repair the damaged resource. A lost device or an opaque native-library error can still require shutdown.

Binary releases

The v0.1 release provides OpenGL binaries for these platforms:

Operating system Architecture
IRIX MIPS IV
Linux ARM64
macOS x86-64 / ARM64
Solaris SPARCv8

Build instructions

The WebGL frontend runs without a native build. The portable Makefiles use plain macro assignments and explicit rules shared by traditional Unix/System V make, IRIX/Solaris make, and Microsoft NMAKE. GNU make is not required. Run the following commands from the repository root or src, with the appropriate platform’s compiler and libraries installed:

Target Command Output
OpenGL (default) make or make opengl testglobe-opengl
Solaris OpenGL make solaris-opengl testglobe-opengl
Apple OpenGL make apple-opengl testglobe-opengl
IRIS GL make irisgl testglobe-irisgl
Sun XGL make xgl testglobe-xgl
Matrox LibShell nmake matrox testglob.exe
Windows GDI nmake gdi testglob.exe
QuickDraw (MPW bridge) make quickdraw TestglobeQD

Native MPW users build QuickDraw with Makefile.mpw as described in its section. The portable quickdraw target requires a configured bridge to the MPW tools.

Common build settings

Objects and executables are written in the directory where make runs. For an out-of-tree build, create a build directory, enter it, then run:

make -f /path/to/testglobe/src/Makefile SRC=/path/to/testglobe/src

Append the desired target, such as apple-opengl. OpenGL’s three targets share testglobe-opengl; Matrox and GDI share testglob.exe. Selecting a target relinks its executable. Driver objects have separate names, so the Unix backends can coexist.

Traditional make does not track compiler-option changes. Clean the affected objects before changing the compiler or build flags:

Command Removes
make clean All build objects, generated build sources, temporary files, and application/helper binaries.
make clean-<target> That backend’s objects, executable, and backend-specific intermediates. Shared data sources and helpers generally remain.
make clean-earth-data Generated e_data.c/m_data.c, converter binaries, and data-generation temporary files.

Individual targets are clean-opengl, clean-solaris-opengl, clean-apple-opengl, clean-irisgl, clean-xgl, clean-matrox, clean-gdi, and clean-quickdraw. Under DOS use nmake with RM=del, for example nmake clean RM=del. Cleanup preserves the supplied src/e_saved.c, canonical binary maps, and recovery .bak files.

Each build section lists its compiler and flag variables. The default Unix SYS_FLAGS=-DNO_SINF -DNO_GENMIPMAP selects C89 sin/cos and GLU mipmaps for older libraries. Apple OpenGL uses separate APPLE_SYS_FLAGS and the modern system math library. See OpenGL platform notes for optional mipmap support.

DEBUG defaults to 0. After cleaning, use make opengl CPPFLAGS=-DDEBUG=1 to enable pixel-storage and right-button diagnostics. A System 7 single-button mouse has no separate right-button state. Software texture buffers are released when texturing is disabled; CPPFLAGS=-DTEXTURE_CACHE_RASTER=1 retains them instead. Use the corresponding CPPFLAGS variable for other targets. Development notes describe the cache and memory policy.

Earth map data

Each native application embeds its selected Earth maps and needs no external data files at runtime. WebGL fetches the same binary inputs from the static site’s data/ directory. Preserve binary bytes when transferring the project; preserve QuickDraw’s application resource fork when copying its executable.

File Role
data/*.bin Canonical 8-bit Earth palette indices; edit these to change map data.
src/e_bin.c Build-time converter for Unix and DOS.
e_data.c / m_data.c Disposable generated C source in the Unix / DOS build directory.
src/e_saved.c Supplied generated copy for manual builds; normal builds generate their own source.
src/e_cmap.h Earth color palette.
web/e_cmap.js Browser palette generated from src/e_cmap.h by web/gen_cmap.py.
src/earthres.h Shared chunk size and native resource IDs.
src/gdi.rc / src/qd.r Embed binary chunks as Windows RCDATA / Macintosh EART resources.
Map width Binary inputs Total bytes
32 e32.bin 512
64 e64.bin 2,048
128 e128.bin 8,192
256 e256_0.bin, e256_1.bin 32,768
512 e512_0.bin through e512_7.bin 131,072

OpenGL, IRIS GL, Sun XGL, and Matrox compile generated arrays of at most 16 KiB. Driver EARTH_* defines select the maps included in each executable; Matrox includes only the 32- and 64-wide maps. GDI and QuickDraw embed all maps as native resources. The five maps total 170.5 KiB; Matrox’s two maps total 2.5 KiB. Generated and saved source files are build copies, not additional runtime map allocations. Compiled-data paths borrow bounded read-only map spans. GDI and QuickDraw load selected chunks directly into the final owned index buffer; neither retains a second full source map.

Make regenerates build source when missing or when an input changes. EARTH_DATA (Unix) and MTX_DATA (DOS) select the input directory, defaulting to data beside SRC. EARTH_CC and EARTH_CFLAGS select the Unix converter compiler and options; DOS uses the Matrox compiler settings.

Task Command
Refresh the supplied copy after changing binary inputs make earth-data or nmake earth-data-dos
Remove build copies and converter tools make clean-earth-data or nmake clean-earth-data RM=del

The next application build regenerates removed source. For manual builds, compile src/e_saved.c instead of the build copy; do not link both. The supplied copy was formerly named src/e_data.c, so older manual compile commands need that filename change.

The converter rejects input/output aliases, nonregular destinations, occupied .tmp/.bak paths, and Unix symbolic-link outputs. After an interrupted replacement, keep any .bak until the output is verified or restored. Changing the chunk size also requires resplitting the binaries and updating generator/resource tables; a compile-time guard rejects stale generated readers.

WebGL

Requirements

A modern browser with WebGL 2 enabled is required. Unsupported browsers show an explanation; there is no WebGL 1 renderer. The frontend uses plain JavaScript ES modules, with no framework, npm dependencies, or server-side application.

Run and host

Serve the repository root with any static HTTP server. For example:

python3 -m http.server 8000

Open http://localhost:8000/web/. Opening web/index.html directly through a file: URL does not provide the HTTP fetching needed for modules and map data. Publish web/ and data/ as sibling directories to retain the relative data URLs. The browser page is independent of the existing README-based site landing page.

For GitHub Pages, include those directories in the branch/folder or Actions artifact selected in Settings → Pages. Keep the existing README publishing setup and CNAME; the demo is an additional page at https://testglobe.dev/web/. If Pages publishes main, changes on develop must reach main before the demo becomes live. The checked-in browser files need no build step during deployment.

The palette module is checked in. Regenerate it only when src/e_cmap.h changes:

python3 web/gen_cmap.py
python3 web/gen_cmap.py --check

The binary maps remain canonical; the browser does not maintain another map-data source. web/package.json supplies ES-module scope for Node-based checks and does not add a runtime package-install step. Native Makefile targets and historical toolchains do not require any browser tooling.

Rendering and controls

The default is key 5, with texturing off. Keys 1–5 select the same 32- through 512-wide maps as the native drivers. Keyboard controls, on-screen buttons, and mouse/touch dragging operate the globe; Reset view restores the initial view and pauses automatic rotation. Esc pauses rotation and releases dragging without closing the browser.

WebGL retains vertex/index buffers and draws latitude strips with native transforms, depth testing, and back-face culling. Flat shading quantizes UV coordinates to Earth patches, then looks up each patch’s palette index and RGB color. Texture mapping normally uses a separate 512 × 256 RGB image and GPU-generated mipmaps, independently of the selected globe resolution. There is no display-list toggle.

Missing map data or allocation shortages at startup can select smaller resolutions. A failed resolution change preserves an existing globe; Retry requests the chosen level again. Texture data or allocation failures try smaller images before falling back to flat colors with texture fail; the OSD reports reduced texture sizes. Toggle texture off and on to retry. Unrelated graphics errors are not treated as evidence of insufficient memory. Context loss suspends drawing while retaining the requested settings, then rebuilds resources when the browser restores the context. Errors and recovery messages remain visible outside the optional overlay.

The canvas follows its available size, with a capped rendering resolution for large or high-density displays. FPS follows requestAnimationFrame and browser refresh scheduling; it is not directly comparable to native GPU benchmark results.

Validation

See the WebGL checks for palette/data checks and browser tests. Browser rendering depends on its graphics implementation and available device resources; desktop and mobile environments can differ.

OpenGL

Requirements

OpenGL 1.1, GLU, and GLUT are required, with a legacy or compatibility context. On Debian or Ubuntu, install the development libraries with:

sudo apt-get install freeglut3-dev

Archived Solaris GLUT packages are available for 32-bit SPARC and 64-bit SPARC. Modern macOS uses Apple’s frameworks.

Build

Unix build (opengl)
make opengl
./testglobe-opengl

The default compiler is cc with -O. Override CC, CPPFLAGS, CFLAGS, SYS_FLAGS, and LDFLAGS for the installed compiler and libraries.

Solaris (solaris-opengl)

Use the Solaris C compiler, OpenGL/GLU, GLUT, and OpenWindows libraries:

make solaris-opengl
./testglobe-opengl

SOLARIS_CC defaults to CC; SOLARIS_CFLAGS defaults to CFLAGS. OPENWINHOME=/usr/openwin selects headers, libraries, and the runtime search path. Override SOLARIS_CPPFLAGS, SOLARIS_SYS_FLAGS, and SOLARIS_LDFLAGS as needed. The compiler’s default architecture and ABI are retained.

The equivalent library settings for the generic target are:

make opengl CC=cc CPPFLAGS=-I/usr/openwin/include \
  LDFLAGS="-L/usr/openwin/lib -R/usr/openwin/lib -lglut -lGL -lGLU -lX11 -lXmu -lm"
Modern macOS (apple-opengl)

Use the selected Xcode Command Line Tools and their macOS SDK:

make apple-opengl
./testglobe-opengl

This target links -framework GLUT -framework OpenGL -framework Cocoa; GLU comes from OpenGL.framework and math functions from the system runtime. No Homebrew or XQuartz installation is needed. The selected toolchain supplies Intel or Apple silicon architecture and SDK defaults.

APPLE_CC defaults to CC (cc, normally Apple’s Clang); APPLE_CFLAGS defaults to CFLAGS. Override APPLE_CPPFLAGS, APPLE_SYS_FLAGS, and APPLE_LDFLAGS as needed. The default APPLE_SYS_FLAGS=-DNO_GENMIPMAP -DGLUT_SILENCE_DEPRECATION selects GLU mipmaps and suppresses GLUT deprecation warnings. Apple builds use <GLUT/glut.h>.

Rendering and color

Each interior latitude band uses a triangle strip; both polar caps share one batch of nondegenerate triangles. Flat colors, winding, and texture seams match the independent triangle path. The default globe is key 5. Display lists cache native geometry and start enabled; disabling them deletes the cache, while enabling them rebuilds it on the next native frame. See Controls and status.

The driver probes RGBA, RGB, and color-index formats with single/double-buffer and depth-buffer alternatives. It prefers RGB(A) over color index, then greater total RGB-plus-alpha precision before buffering. Requests include 8/8/8/8, 8/8/8, 5/6/5, 5/5/5, unconstrained RGB(A), and color index with at least eight bits. GLUT probes do not enumerate every native visual; older implementations may expose fewer choices. Classic GLUT RGB fallbacks do not require an alpha channel.

When GLUT lacks GLUT_DISPLAY_MODE_POSSIBLE, the driver makes the original single RGB, double-buffered window request and reads the resulting window attributes. It cannot safely probe alternative formats on those implementations: an unsupported request may terminate GLUT instead of returning a failure.

Flat shading retains each Earth palette byte, converting it to RGB for RGB(A) windows or submitting the index directly. Color-index windows use the shared software texture rasterizer because classic OpenGL texturing requires RGB(A) mode. That path bypasses display lists.

Platform notes

Display-list allocation, compilation, validation, and execution are checked with OpenGL 1.1 calls, including glIsList and glGetError. A failed cache is discarded and geometry is drawn immediately. Texture-memory shortages and native size limits try smaller images; other texture failures release failed resources and draw flat colors. Failed lists are not rebuilt every frame or on resolution changes; toggling d or t explicitly permits a retry. Diagnostics use glGetError, without modern debug extensions.

All three targets default to GLU mipmaps. Omitting NO_GENMIPMAP permits an optional path when FreeGLUT 2.0 or later headers are available: the running context must report OpenGL 3.0 or later, glGenerateMipmap must resolve at runtime, and the image must fit the texture limit. Otherwise the driver uses gluBuild2DMipmaps. No post-1.1 OpenGL symbol is required at link time, and GL_GLEXT_PROTOTYPES is unnecessary.

Validation

See the OpenGL host checks. Physical color-index behavior requires an implementation offering that visual. Native Apple SDK compilation and rendering require macOS; Solaris builds require its installed graphics libraries.

IRIS GL

Requirements

Use native 32-bit MIPS IRIX 4.0 with the IRIS GL development headers and runtime. Windowing, input, and rendering use IRIS GL directly.

Build

make irisgl
./testglobe-irisgl

IGL_CC defaults to CC; override IGL_CPPFLAGS, IGL_CFLAGS, IGL_SYS_FLAGS, and IGL_LDFLAGS for the installed tools. Defaults select FLAT, DRV_IGL, C89 math, and -lc_s -lgl_s -lm, following the IRIS GL Programming Guide’s shared-library example. No later MIPS ISA or ABI is imposed.

Rendering and color

The default globe is key 3. IRIS GL performs model/view transforms, 45-degree perspective, clipping, triangle-mesh drawing, back-face rejection, and bitmap-font OSD. Geometry is cached in a GL object and rebuilt for resolution or texture changes. If the object cannot be allocated or validated, the driver draws the same geometry directly and retains the user’s requested rendering settings. Interior bands use bgntmesh/endtmesh; polar caps use three-vertex meshes.

Runtime queries compare single- and double-buffered RGB(A) formats, preferring total channel precision, then alpha and RGB precision, then double buffering. If RGB is unavailable, the driver selects the largest color-index mode with at least eight bits. Flat colors retain the Earth index and convert to RGB when needed. Color-index mode installs the Earth palette and restores it at exit. A z-buffer is used when available; the convex globe can also be drawn with back-face rejection alone.

Native texturing uses texdef2d, t2f, mipmaps, and bilinear filtering. When unavailable, the shared software rasterizer draws the textured globe using matrices supplied by IRIS GL, then presents the image through IRIS GL. Flat rendering remains native.

Platform notes

The event queue supplies keyboard, drag, resize, focus, and close events. Interrupted tied mouse samples and queue overflow resample mouse state without blocking on missing samples or discarding later keyboard/close events.

Texture definition, binding, and pixel-transfer calls return no success value. The driver detects allocation failures, missing data, and lost texture capability, but cannot confirm silent failures inside the native library. Consequently, texture on means native submission for that frame. Recoverable failures discard failed state and cached geometry before drawing flat colors.

Validation

See the IRIS GL host checks. Native validation must cover the IRIX 32-bit ABI, graphics hardware, fonts, window manager, and pixel transfer.

Sun XGL

Requirements

Use 32-bit SPARC Solaris 2.6 with Sun XGL 3.x, X11/OpenWindows, and a 24-bit TrueColor visual. The driver uses Xlib directly.

Build

make xgl
./testglobe-xgl
# For nonstandard SDK locations:
make xgl XGLHOME=/path/to/xgl OPENWINHOME=/path/to/openwin

Defaults are /opt/SUNWits/Graphics-sw/xgl and /usr/openwin. Override XGL_CPPFLAGS, XGL_CFLAGS, XGL_SYS_FLAGS, and XGL_LDFLAGS as needed; the native compiler’s 32-bit default is used. When relocating the runtime, also set the shell’s XGLHOME for the installed pipeline and font files.

Rendering and color

The default globe is key 3. Each interior latitude band uses xgl_triangle_strip; polar caps use nondegenerate three-vertex strips. Both triangles of each Earth patch share its flat RGB color. XGL performs transforms, clipping, back-face handling, depth testing, and texturing. Texture mapping uses REPLACE mode and preserves UV seams. X11 handles keyboard, mouse, expose, resize, and window-close events.

Platform notes

XGL supplies its own software pipeline when hardware cannot accelerate texturing. Because the API exposes no reliable per-frame backend query, successful texturing reports texture on for either internal path. Recoverable texture failures release partial resources and draw flat colors. Nonrecoverable errors and unrelated setup, native rendering, or OSD errors remain fatal. Native texture rasters are filled from indexed map rows without an intermediate full RGB image. Packet allocation failures use smaller strips, retaining overlap, winding, colors, and UVs.

Validation

See the Sun XGL host checks. Native SDK compilation, ABI compatibility, and physical rendering require the Sun SDK/runtime on Solaris.

Matrox LibShell

Requirements

Use MS-DOS, Microsoft C 7.0 with its huge-model runtime and NMAKE, and the matching Matrox LibShell C binding. The driver assumes a 640 × 480, 256-color PG-641-compatible display. Initialize the board and firmware according to the SDK. A Microsoft-compatible DOS mouse driver enables dragging; keyboard controls work without one.

Build

Place the SDK at the repository root:

XGX1/HEADERS/DEF.H
XGX1/HEADERS/LIBFN.H
XGX1/HEADERS/IOLIB.H
libsv5/lscl.lib

With the compiler and linker on PATH, run:

nmake matrox

The output is testglob.exe. For an external SDK use XGX_ROOT=C:\MATROX; the default is . in the root Makefile and .. in src/Makefile. Override MTX_CC, MTX_CFLAGS, MTX_CPPFLAGS, MTX_LIB, and MTX_LDFLAGS as needed, keeping -AH. DOS rules use backslash paths, 8.3 generated names, and response files for command-line limits.

Rendering and color

The default globe is key 1; only keys 1 and 2 are available, with no texture controls. LibShell performs transforms, orthographic projection, viewport clipping, and filled world-coordinate polygons through v3arwplygn (V3ARWPLYGN). Patches are quads, with coincident pole vertices collapsed to triangles. All 256 LUT entries come from earth_cmap, and polygons use the original palette indices.

Platform notes

The host rejects back-facing polygons because the base PG-641 interface documents neither a depth buffer nor a back-face switch. DOS uses normalized huge pointers, _halloc/_hfree, long mesh counts, and DOS timing.

LibShell errors are serviced while waiting for inquiry replies between bounded command packets. Diagnostics identify the operation and error bits. Reply polling has a ten-second deadline; short malformed replies are drained, while oversized replies or timeouts abandon communication. Cleanup restores the palette and error policy when communication remains usable and sends no further board commands after abandonment.

Validation

See the Matrox SDK host checks. Native validation requires Microsoft C 7, LSCL.LIB, and the board. Polling assumes a nonblocking iogeterror() and a positive rdfifocnt() permitting a complete iogetw() without waiting. The supplied headers do not establish FIFO count units or atomic word availability; verify these assumptions against the installed binding and board.

Windows GDI

Requirements

Use Windows 3.1 in a 256-color display mode, Microsoft C/C++ 7.0 with the Windows emulation runtime (LLIBCEW.LIB), and the Windows 3.1 SDK headers, LIBW.LIB, 16-bit linker, and resource compiler. This target produces a native 16-bit application.

Build

Configure PATH, INCLUDE, and LIB, then run:

nmake gdi

Run testglob.exe inside Windows 3.1. Override GDI_CC, GDI_LINK, GDI_RC, GDI_CFLAGS, GDI_CPPFLAGS, GDI_LIBS, GDI_LDFLAGS, GDI_RCFLAGS, and GDI_DATA as needed. Preserve -AH -G2 -Gw -Zp1 -FPi when overriding GDI_CFLAGS to keep the memory model, Windows ABI, and optional FPU settings. GDI_DATA defaults to data at the root and ..\data inside src.

The .def file exports the window procedure and specifies segment attributes, an 8 KiB local heap, and a 16 KiB stack. RC -r -fo compiles src/gdi.rc and all 13 map chunks into g_earth.res; RC -t g_earth.res testglob.exe attaches it. Discardable RCDATA chunks avoid large static arrays. The huge-model app permits one running instance at a time.

Rendering and color

The default globe is key 1, with all five resolutions and no texture mapping. The window uses the display’s 8-bit depth. A 256-entry logical Earth palette is realized on activation; Windows retains its reserved system colors. An 8-bit compatible bitmap and memory DC normally provide the back buffer. If they cannot be allocated, the driver paints directly into the window’s paint DC.

Software transforms, perspective projection, clipping, and culling operate on whole quads. Shared vertices are transformed once per packet, then retained polygons are grouped by palette index for PolyPolygon calls of at most 64 polygons. Pole vertices collapse to triangles. Visibility relies on the convex globe rather than a depth buffer for intersecting geometry. Native Windows messages handle input, resizing, palette changes, and window closure. Failed PolyPolygon submission can fall back to individual Polygon calls. Brush allocation can reclaim cached brushes or use a stock color. Failure to create the animation timer leaves manual rotation and keyboard input available.

Platform notes

GetWinFlags selects floating-point transforms on supported 80387-or-later systems; other systems use the shared integer pipeline. Mesh generation and FPS bookkeeping still use floating point. Keep -FPi so the Windows runtime can emulate those operations when necessary; -FPi87 would require a coprocessor.

Windows global memory supplies allocations larger than 64 KiB. SEG86 shares the segmented pointer model with DOS, while GDI selects Windows allocation, startup, errors, and timing. Fatal errors stop rendering, animation, capture, and input before showing a modal dialog, preventing reentrant access to incomplete state.

Validation

See the GDI host checks. Microsoft C 7 and Windows 3.1 must validate segmented code, loader format, emulator dispatch, and physical palette mapping.

QuickDraw

Requirements

The QuickDraw driver targets a System 7 application built with Apple’s 68K MPW C compiler and Macintosh interfaces. Use the System 7-compatible Universal Interfaces 2.2 headers and Rez templates, the matching MPW C libraries, and the C, Link, Rez, and Make tools. Set MPW’s CIncludes, RIncludes, Libraries, and CLibraries to the installed interface/library folders. The SDK files and tools are external dependencies and are not redistributed here.

Build

Makefile.mpw is a separate, native MPW Make file: MPW’s rule syntax, variables, and shell differ from Solaris make and Microsoft NMAKE. It is stored in MacRoman with classic CR line endings; preserve those bytes. Transfer the ASCII C/header/Rez sources as Macintosh text, converting their Unix line endings to CR in the build copy (for example, unix2mac src/*.c src/*.h src/*.r before transfer). Do not convert Makefile.mpw from UTF-8; it is already in its native encoding.

In MPW Shell, set the current directory to the repository root and run:

Make -f Makefile.mpw quickdraw > QDBuild
Execute QDBuild

MPW Make emits commands rather than executing them; the second line runs the generated commands. From src, use Make -f ::Makefile.mpw -d QD_SRC=: quickdraw > QDBuild, then Execute QDBuild. Build output is TestglobeQD, a Finder-launchable APPL with creator Tglo. Preserve its resource fork when transferring it to another Mac, using a resource-aware copy or a MacBinary/BinHex archive.

The build needs the C/header files in src, src/qd.r, Makefile.mpw, and all 13 data/*.bin files. The binary files contain Earth palette indices in chunks of at most 16 KiB; transfer them as binary without newline conversion. Rez embeds them as EART resources with IDs from src/earthres.h, keeping large initialized arrays out of the A5-relative globals. Keep data beside src: the Rez read statements use explicit source-relative ::data: paths, since native MPW Rez does not use its -i header search paths for these binary reads.

The portable make quickdraw target can use the external MPW tool/shell bridge with a configured MPW installation: MPW_EXEC defaults to its mpw-make executable. It invokes the same native file and passes QD_DEFINES (-d SEG68 -d DRV_QD -d DRV -d NO_SINF) and the source directory; MPW_EXEC, QD_MAKEFILE, QD_SOURCE, and QD_DEFINES are overridable. Native MPW builds need no bridge or modern scripting language. Use Make -f Makefile.mpw clean > QDBuild and Execute QDBuild for native cleanup. The portable clean-quickdraw target and ordinary make clean remove the seven QuickDraw objects and application using RM, without requiring MPW tools.

Rendering and color

The default globe is key 1, with all five resolutions and no texture mapping. Software quad batches share vertex transformations, then clip and cull whole polygons. Pole vertices collapse to triangles. QuickDraw fills each retained polygon with PaintPoly, FillCPoly, or FillPoly; batching shares geometry work rather than adding a native multiple-polygon call. OSD text uses QuickDraw.

The driver chooses the highest currently configured depth among active displays, without changing display modes. It supports monochrome and Color QuickDraw: 1-bit output uses ordered luminance patterns, 4/8-bit output maps Earth RGB colors to the device palette, and 16/32-bit output uses native RGB drawing. Unavailable optional palettes or color patterns fall back to native nearest-color drawing. Polygon allocation failures unwind the native drawing scope and release optional resources before one retry; repeated failure pauses drawing until input requests another attempt.

With 32-bit QuickDraw, an optional GWorld supplies an offscreen back buffer presented through CopyBits. This uses ordinary GWorld pixel memory. QuickDraw selects available display acceleration; allocation or pixel-lock failure falls back to the window. The OSD reports the actual buffer path. Activation, resume, and completed window drags recheck device depth and bounds, rebuilding display resources when they change.

Platform notes

The baseline 68000 sources are main.c, drv.c, err.c, globe.c, drv_qd.c, and integer-only soft3d.c, built with SEG68 and DRV_QD. MPW’s SANE floating-point code works without a coprocessor. Only qd_fpu.c receives -mc68020 -mc68881; its pointer-and-integer interface and separate QDFPU code segment avoid mixing SANE and hardware floating-point calling conventions. The driver checks both CPU and FPU before calling it. Do not enable direct FPU flags for baseline objects.

Linking uses MPW’s startup/runtime, interface, standard C, Math.o, and CSANELib.o libraries. QD_RUNTIME defaults to {Libraries}Runtime.o; override it and QD_LIBRARIES for MPW releases with different runtime filenames.

src/qd.r supplies an 8 MiB preferred and 512 KiB minimum application partition, suspend/resume and 24/32-bit addressing attributes, and error-alert resources. Higher resolutions and larger GWorlds need a larger partition. Windows and menus are created by the driver. Heap allocation and TickCount timing use SEG68; classic Macintosh A5-relative globals and segmented CODE resources have their own memory model.

Before a fatal alert, the driver releases pending polygons, unlocks pixels, and restores the caller’s port/device. Readiness guards prevent reentrant rendering during setup, errors, or teardown. GWorld presentation temporarily uses black/white destination colors and restores them afterward, including after a direct-rendering fallback.

Validation

See the QuickDraw host checks. Native MPW builds must validate code-resource linkage and SANE/68881 dispatch. Physical depth/palette behavior, resource forks, and acceleration require System 7 hardware or a suitable emulator.

Testing and validation

Run the baseline checks from the repository root on a supported host:

python3 tests/run.py

The host regression guide lists prerequisites, optional native driver checks, coverage, and result interpretation. These tests compile production code with host call recorders and sanitizers. They check data, geometry, API arguments, input, and resource handling, but do not establish historical binary ABI compatibility or physical graphics behavior. Native validation requires each platform’s compiler, SDK/runtime, and hardware or suitable emulator; specific limits appear in its driver section. Native application builds do not require the Python test runner. The WebGL checks run separately with Node.js and a browser; those tools are not native build dependencies.

Development notes

Configuration and file responsibilities

Native Makefiles choose the memory model and driver; driver headers choose primitives and capabilities. Keep those responsibilities separate:

Driver Build defines Primitive Additional geometry capabilities
OpenGL FLAT, DRV_OGL TRISTRIP DRV_TRI_CAPS, color/RGB/UV triangle callbacks
IRIS GL FLAT, DRV_IGL TRISTRIP Color/UV triangle callbacks
Sun XGL FLAT, DRV_XGL TRISTRIP RGB/UV strip callbacks
Matrox SEG86, DRV_MTX QUAD Color triangle callbacks
GDI SEG86, DRV_GDI QUAD DRV_QUAD_BATCH
QuickDraw SEG68, DRV_QD QUAD DRV_QUAD_BATCH

All native application targets also define DRV; Microsoft C builds use -AH. The GDI header supplies GDI for Windows-specific integration. Primitive/callback-capability defines belong in headers, not compiler flags. TRI remains a tested reference path. DRV_TRI_COLOR, DRV_TRI_RGB, and DRV_TRI_UV expose only implemented callbacks. DRV_COLORMAP selects palette-byte geometry inputs; drv_colormapped describes the window’s runtime mode. All native drivers except XGL define DRV_COLORMAP, even when they can draw to RGB windows.

Location Responsibility
src/globe.c Scene ownership, recoverable mesh construction, and plural traversals: globe_draw_tris(), globe_draw_tristrips(), globe_draw_quads(), globe_draw_quadbatches(), and OpenGL pole-cap traversal.
src/drv_*.c Singular native callbacks such as drv_draw_tri_*, drv_draw_tristrip_*, drv_draw_quad_*, and drv_draw_quadbatch_*; group color/RGB/UV variants by primitive.
src/drv.c Shared allocation/clock services, input, rotation, FPS/OSD, geometry-packet helpers, and Earth-resource traversal.
Driver-private helpers Backend-prefixed windowing, events, timing, transforms/caches, and drawing state.
src/e_ext.h Shared palette and bounded map-reader declarations; generated arrays remain private.
web/ Browser frontend, WebGL rendering, and generated palette module; reads canonical data/ maps.

Shared geometry helpers include drv_validate_quadbatch(), drv_submit_quad_as_batch(), drv_expand_tristrip_uv(), and drv_split_tristrip_batches(). Shared input uses drv_handle_key(), drv_rotate_drag(), and drv_rotate_elapsed(). Backend resize and texture-loading helpers remain private; drv_render() and drv_close() are common driver entry points. Drawing callbacks borrow inputs for the call and never rebuild the scene inside a native begin/end or paint scope. Scene revisions invalidate geometry caches; texture intent and the active draw pass are separate. Drv_result distinguishes allocation, data, input, unavailable-feature, and native failures. Optional-cache eviction occurs outside rendering scopes through drv_release_optional(). Unsupported PGC/PHIGS selections report configuration errors; their headers are reference stubs. types.h provides wide arithmetic aliases for segmented builds.

Root and src Makefiles intentionally duplicate rules with different directory defaults because historical NMAKE and Solaris make lack a common include syntax. Keep both files synchronized. OpenGL uses ordinary .o names; Solaris, Apple, IRIS GL, and XGL use s_, a_, i_, and x_ prefixes. DOS uses .obj, GDI uses g_*.obj, and QuickDraw uses q_*.o. MPW has a separate Makefile grammar.

Geometry submission

The scene contract is one opaque convex globe, with the camera, clipping limits, radius, and starting pose defined in globe.h. Back-face rejection supplies visibility for paths without a depth buffer; those paths are not general renderers for intersecting or transparent objects.

The default radius remains 1,000. OpenGL, IRIS GL, and XGL accept positive finite custom radii without the software drivers’ limit; their camera and clipping values must still suit the chosen scene. GDI and QuickDraw retain a maximum radius of 1,000 for their shared fixed-point pipeline. Matrox retains the validated 1,000-unit range for LibShell’s fixed-point transforms. These limits are driver capabilities rather than a restriction on every globe.

Triangle strips follow complete interior latitude bands. At key 5, an interior strip has 1,026 vertices and 1,024 triangles. OpenGL sends 254 such strips plus one cap batch: 263,676 submitted vertices for 261,120 triangles, compared with 783,360 vertices for independent triangles. IRIS GL and XGL use separate three-vertex cap meshes/strips. Flat colors and UVs preserve the independent-triangle topology. Under allocation pressure, bounded packets may split a latitude band without changing its facets. UVs are generated from grid coordinates for submission instead of retaining a full two-dimensional UV array. XGL expands palette indices only for its current RGB packet.

DRV_QUAD_BATCH is a capability of QUAD. GDI and QuickDraw use at most 64 quads and 130 shared vertices per packet, with four indices and one palette byte per quad. Each shared vertex is transformed once. GDI groups visible polygons by color for PolyPolygon; QuickDraw fills them individually. Individual quad submission remains available, including Matrox. XGL has separate drv_draw_tristrip_flat_rgb() and drv_draw_tristrip_flat_uv() callbacks.

Shared rendering pipelines

GDI and QuickDraw share src/soft3d.c/.h for integer IEEE-float decoding, fixed-point rotation/transforms, clipping, projection, and back-face rejection. Driver-local caches hold transformed packets; projection validates indices against their actual point count. GDI also has a floating-point path. QuickDraw’s isolated qd_fpu.c/qd_math.h interface preserves the SANE/68881 boundary. Only these two targets link the integer pipeline (g_soft.obj or q_soft.o). Resource-backed indices are loaded into their final storage, avoiding an extra full-map allocation during mesh construction.

OpenGL and IRIS GL share src/texsoft.c/.h for software texturing: homogeneous clipping, depth/culling, perspective-correct UVs, repeat sampling, and filtered mipmaps. They link it as texsoft.o and i_soft.o; the OpenGL platform variants use their own object prefixes. src/texture.h sets TEXTURE_MAX_SIZE=512, TEXTURE_PALETTE_SIZE=256, and TEXTURE_CACHE_RASTER=0 by default. Disabling software texturing releases frame/depth buffers and OpenGL’s transfer copy while retaining mipmaps. Resizing releases obsolete rasters before replacement. Same-size staging images reuse allocation; changed sizes replace the old image only after completion. The software mipmap builder can adopt the generated RGB base image instead of copying it. IRIS GL fills its native packed image directly from indexed rows; XGL fills its native raster the same way. OpenGL’s GLU path retains the complete RGB staging image required by that interface. Native libraries may retain their own texture, geometry, and framebuffer storage.

The Earth converter uses POSIX file operations on Unix and Microsoft runtime calls on DOS to reserve output paths safely. Generated readers handle chunk and 64 KiB boundaries; texture expansion and globe color sampling share those readers.

Planned work

Version history

v0.2 (in development)

v0.1

First release, with OpenGL/GLUT and binaries for several platforms.

License

GNU General Public License, version 3 or later. See LICENSE.