DirectX and OpenGL for Win32 programs
How a Windows program's 3D reaches the GPU — Direct3D 7 through 11, DirectDraw, DirectInput and WGL.
This is how a Windows program's 3D reaches the GPU. It is part of the Win32 subsystem.
The stack
game.exe (32-bit)
d3d9 / d3d8 / d3d11 + dxgi / ddraw Wine's PE DLLs
wined3d Wine's PE DLL
opengl32 built in, 64-bit host
Mesa — libEGL + libglapi
hardware driver → the Intel iGPU
software rasteriser → no GPU
A program that uses OpenGL directly enters at opengl32.
Why Wine's wined3d rather than a native Direct3D
wined3d provides Direct3D 8, 9, 10 and 11 plus DXGI — and Direct3D 7 through Wine's DirectDraw — from one mature code base, and its only hardware boundary is OpenGL, which Mesa accelerates on the supported Intel GPUs.
A native Direct3D built on Grafika would have no GPU 3D pipeline to target, because Grafika's GPU backend is a blitter, and it would need its own shader translator. DXVK is not an option either: it requires a Vulkan version these GPUs do not have.
Using it
The DirectX build of the loader is dynamically linked, because a static binary cannot load Mesa at runtime:
/System/Win32/bin/win32loader-directx game.exe
The static loader still contains OpenGL, but there it reports no pixel formats and says why in its log rather than failing obscurely.
Wine's DLLs are looked up like any other PE DLL: the program's directory, then the system directory. A built-in DLL wins over a PE file of the same name, so DirectDraw programs keep the host's own DirectDraw; a Direct3D 7 program can be given Wine's instead with a per-DLL override.
DirectInput
dinput8 and dinput are built in: the system keyboard and mouse through
DirectInput 1 to 8, with immediate state, buffered data, cooperative levels and
event notification.
Keys arrive as scancodes, mouse motion as relative deltas — or absolute, if the program asks for it — and the wheel in the usual units. An exclusive foreground mouse hides and confines the pointer while acquired.
There are no joysticks, no force feedback and no action mapping; those report unsupported rather than pretending.
Options
| Word | Meaning |
|---|---|
w32gl=off |
Never load Mesa: OpenGL and Direct3D report no hardware. |
w32gl=software |
Force Mesa's software rasteriser. |
w32glpersistent |
Leave persistent buffer storage visible and the GL version uncapped. |
w32trace=gl |
Contexts, pixel formats and drawables, plus periodic frame rate and present cost. |
What differs from Windows, and why
Presentation is a read-back. Each window with a GL pixel format owns an
off-screen buffer the size of its client area; SwapBuffers reads the back
buffer and paints it through GDI. Clipping, child windows and both display
drivers work unchanged, and the cost is one copy per frame.
32-bit programs cannot address Mesa's mappings. A buffer mapped above 4 GiB is shadowed in guest memory and copied back on unmap — and for an explicitly flushed map, only the flushed ranges are copied. The shadow is filled from the real mapping only when the program may actually read it, or when the unmap copies everything back anyway.
A persistent map cannot be shadowed at all, so persistent buffer storage is hidden and the GL version is capped just below the level that requires it. This is Wine's own policy for the same situation, and wined3d then uses ordinary maps.
One display adapter and one output. Video memory budget queries report zero, which is what Wine reports without Vulkan, because it is not measurable here.
No display gamma. Setting a gamma ramp fails unless the ramp is the identity.
What runs
The OpenGL path covers WGL, fixed-function and shader pipelines, buffer mapping, core contexts and resize. Direct3D 9 creates a windowed hardware device and draws through the usual clear, draw and present cycle. Direct3D 11 creates a device and swap chain, compiles HLSL, and draws at feature level 10_1 on supported hardware.
On the Intel GPUs in the lab machines this is real hardware acceleration. On a machine with no usable GPU the same programs run on Mesa's software rasteriser, more slowly, with no change to the program.
Measured
On a MacBookPro8,3 with an HD 3000, before and after the import path was optimised:
| Before | After | |
|---|---|---|
| One Win32 import through the gate | 2,881 ns | 482 ns |
SwapBuffers at 640×480 |
22.5 ms (44 fps) | 4.6 ms (215 fps) |
SwapBuffers at 1292×812 |
77 ms (12.9 fps) | 15.3 ms (65 fps) |
The remaining present cost is the read-back itself.
More documentation
- Booting the live image
- Installing to disk
- Packages and the filesystem
- How it boots
- The syscall ABI
- Hardware support
- ACPI
- UEFI boot entries
- NetBooting a Mac
- The AO toolkit
- Grafika — the graphics API
- The display protocol
- Desktop effects
- The level bezel
- Notifications
- Rastinis — the file manager
- File operations
- Audio — Garsas
- Hardware video decode
- Networking — Tinklas
- Network shares — SMB and NFS
- Remote control
- The Win32 subsystem
- Ports and packaging