From 7de7f5bfb01586176c2ff4031d43c0319b66dbd5 Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sun, 12 Oct 2025 18:22:18 +0100 Subject: [PATCH] Set up drawing to framebuffer --- .gitignore | 1 + build.sh | 8 ++++++ main.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 .gitignore create mode 100755 build.sh create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7c8a79d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +asteroids diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..7ed6d33 --- /dev/null +++ b/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +cc="gcc" +warn="-std=c23 -pedantic -Wall -Wextra" +opt="-O2 -march=native" +libs="-I/usr/include/libdrm -ldrm" + +$cc $flags $libs main.c -o asteroids diff --git a/main.c b/main.c new file mode 100644 index 0000000..0b14878 --- /dev/null +++ b/main.c @@ -0,0 +1,82 @@ +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + int err; + + const int fd = open("/dev/dri/card1", O_RDWR | O_CLOEXEC); + assert(fd != -1); + + drmModeRes *res = drmModeGetResources(fd); + assert(res != nullptr); + drmModeConnector *conn = drmModeGetConnector(fd, res->connectors[0]); + assert(conn != nullptr); + drmModeModeInfo mode = conn->modes[0]; + uint32_t conn_id = conn->connector_id; + + struct drm_mode_create_dumb create_req = { + .width = mode.hdisplay, + .height = mode.vdisplay, + .bpp = 32, + }; + err = ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_req); + assert(err != -1); + + uint32_t fb_id; + err = drmModeAddFB( + fd, create_req.width, create_req.height, 24, 32, create_req.pitch, + create_req.handle, &fb_id); + assert(err == 0); + + err = drmModeSetCrtc(fd, res->crtcs[0], fb_id, 0, 0, &conn_id, 1, &mode); + assert(err == 0); + drmModeCrtc *crtc = drmModeGetCrtc(fd, res->crtcs[0]); + assert(crtc != nullptr); + + struct drm_mode_map_dumb map_req = { .handle = create_req.handle }; + err = ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map_req); + assert(err != -1); + + uint32_t *const fb = mmap( + 0, create_req.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + map_req.offset); + assert(fb != MAP_FAILED); + + for (int y = 0; y < mode.vdisplay; ++y) { + for (int x = 0; x < mode.hdisplay; ++x) { + const uint8_t r = (x * 255) / mode.hdisplay; + const uint8_t g = (y * 255) / mode.vdisplay; + const uint8_t b = 128; + fb[y * (create_req.pitch / 4) + x] = (r << 16) | (g << 8) | b; + } + } + + getchar(); + + munmap(fb, create_req.size); + struct drm_mode_destroy_dumb delete_req + = { .handle = create_req.handle }; + ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &delete_req); + + drmModeSetCrtc( + fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &conn_id, 1, + &crtc->mode); + drmModeFreeCrtc(crtc); + drmModeFreeConnector(conn); + drmModeFreeResources(res); + close(fd); + + return 0; +}