Writing an OS Kernel from Scratch | Display — From Framebuffer to GPU
Have you ever wondered: How is a single pixel lit up on the screen? The CPU only sends a few bytes of data, yet the display can render a complete Windows desktop or game scene. The chain in between — Framebuffer, DRM/KMS, GPU instructions — is deeper than you think.
This article starts from the basic principles of display, breaks down Framebuffer, display timing, DRM/KMS architecture, and finally provides reproducible Linux debugging commands.
I. Framebuffer: The Lowest-Level Display Memory
Framebuffer is the simplest abstraction in display hardware: a region of memory where each pixel corresponds to one or more bytes; CPU writes to memory equals writing to the screen.
Pixel coordinates (0,0) Pixel coordinates (1,0) Pixel coordinates (2,0)
┌──────────┐ ┌──────────┐ ┌──────────┐
│ R G B │ │ R G B │ │ R G B │
│08 16 24b │ │08 16 24b │ │08 16 24b │
└──────────┘ └──────────┘ └──────────┘
←─── Horizontal scanline ───→
Resolution 1920×1080 @ 60Hz
→ Each row: 1920 pixels, each frame: 1080 rows
→ Refresh: 60 frames per second
→ Bandwidth: 1920×1080×3×60 ≈ 373 MB/s (24bpp)Framebuffer memory layout (RGB888, 24bpp):
0x0000: [B0][G0][R0][B1][G1][R1]...
←───── 3 bytes per pixel ─────→Viewing Framebuffer in Linux:
$ cat /dev/fb0 | head -c 100 # Read Framebuffer content (raw pixel data)
$ fbset -s # View current display mode
mode "1920x1080-60"
geometry 1920 1080 1920 1080 32
timings 162 240 80 30 3 104 0
accel true rgba 8/16,8/8,8/0,0/0
$ ls /dev/fb*
/dev/fb0 /dev/fb1II. Display Timing: HSync, VSync, and Pixel Clock
The display doesn’t directly show pixels — it scans line by line following a fixed timing sequence controlled by multiple signals:
Horizontal Timing (one line):
───────────────────────────────────────────────────────
│ Front │ Sync │ Back │ Active Video │
│ Porch │ Pulse │ Porch │ (Active pixels) │
───────────────────────────────────────────────────────
│ ← HFP → │← HSP →│← HBP → │←─────── 1920 ─────→│
Vertical Timing (one frame):
───────────────────────────────────────────────────────
│ VFP │ VSync │ VBP │ Active Video │ Total 1080 rows
───────────────────────────────────────────────────────Timing parameter explanations:
HFP/HBP/HSP: Horizontal front porch/back porch/sync pulseVFP/VBP/VSP: Vertical front porch/back porch/sync pulsePixel Clock: Number of clock cycles per pixel
Calculating bandwidth:
Pixel Clock = 162 MHz (162 in timing)
Horizontal total = 1920 + 240 + 80 + 104 = 2344
Vertical total = 1080 + 30 + 3 + 23 = 1136
Refresh rate = 162 MHz / (2344 × 1136) ≈ 60.9 Hz
Effective bandwidth = 1920 × 1080 × 3 × 60 ≈ 373 MB/sIII. DRM/KMS: Modern Display Driver Architecture
DRM (Direct Rendering Manager) / KMS (Kernel Mode Setting):
User space:
Applications → Wayland/X11 → libdrm → ioctl
Kernel space:
┌─────────────────────────────────────────────────┐
│ DRM Core (drm.ko) │
│ - GEM (Graphics Execution Manager) │
│ - KMS (Kernel Mode Setting) │
│ - FBDEV compatibility layer │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ GPU Driver (amdgpu.ko / i915.ko / ...) │
│ - Command submission │
│ - Memory management │
│ - Display controller programming │
└─────────────────────────────────────────────────┘
│
▼
Hardware (GPU)
DRM objects:
CRTC: Display controller (timing generation)
Encoder: Signal encoding (LVDS/HDMI/DP)
Connector: Physical connector status
Plane: Hardware overlay layer
FB: Framebuffer (memory buffer)IV. Linux Debugging Commands
$ cat /sys/class/drm/card0-HDMI-A-1/modes # Supported modes
$ modetest -M xlnx -c # Show DRM connectors
$ modetest -M xlnx -e # Show DRM encoders
$ modetest -M xlnx -p # Show DRM CRTCs
$ modetest -M xlnx -s 40:1920x1080-60 # Test mode-set
$ xrandr # X11 display configuration
Comments