DrmSampleTestcode

Pasted Oct 27, 2026, 2:59 AM1 file250 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgsk5448cfdfk90
drm

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#include <xf86drm.h>
#include <xf86drmMode.h>
#include <drm.h>
#include <drm_mode.h>

int main(void)
{
    int fd = -1;
    drmModeRes *res = NULL;
    drmModeConnector *conn = NULL;
    drmModeEncoder *enc = NULL;
    drmModeCrtc *old_crtc = NULL;

    uint32_t connector_id = 0, crtc_id = 0;
    uint32_t fb_id = 0, handle = 0;
    int crtc_index = -1;
    int result = 1;
    int modeset_done = 0;

    struct drm_mode_create_dumb create = {0};
    struct drm_mode_map_dumb map = {0};
    struct drm_mode_destroy_dumb destroy = {0};

    void *pixels = MAP_FAILED;
    size_t buffer_size = 0;

    fd = open("/dev/dri/card1", O_RDWR | O_CLOEXEC);
    if (fd < 0) {
        perror("open card1");
        goto cleanup;
    }

    /* Get display resources */
    res = drmModeGetResources(fd);
    if (!res) {
        perror("drmModeGetResources");
        goto cleanup;
    }

    /* Find a connected display and compatible CRTC */
    for (int i = 0; i < res->count_connectors; i++) {
        conn = drmModeGetConnector(fd, res->connectors[i]);
        if (!conn)
            continue;

        if (conn->connection == DRM_MODE_CONNECTED &&
            conn->count_modes > 0) {

            for (int e = 0; e < conn->count_encoders + 1; e++) {
                uint32_t encoder_id;

                if (e == 0)
                    encoder_id = conn->encoder_id;
                else if (e - 1 < conn->count_encoders)
                    encoder_id = conn->encoders[e - 1];
                else
                    break;

                if (!encoder_id)
                    continue;

                enc = drmModeGetEncoder(fd, encoder_id);
                if (!enc)
                    continue;

                /* Prefer the encoder's current CRTC */
                for (int c = 0; c < res->count_crtcs; c++) {
                    if (enc->crtc_id == res->crtcs[c]) {
                        crtc_index = c;
                        break;
                    }
                }

                /* Otherwise find a compatible CRTC */
                if (crtc_index < 0) {
                    for (int c = 0; c < res->count_crtcs; c++) {
                        if (enc->possible_crtcs & (1U << c)) {
                            crtc_index = c;
                            break;
                        }
                    }
                }

                if (crtc_index >= 0) {
                    connector_id = conn->connector_id;
                    crtc_id = res->crtcs[crtc_index];
                    goto display_found;
                }

                drmModeFreeEncoder(enc);
                enc = NULL;
            }
        }

        drmModeFreeConnector(conn);
        conn = NULL;
    }

    fprintf(stderr, "No connected display with a compatible CRTC\n");
    goto cleanup;

display_found:
    printf("Connector: %u, CRTC: %u\n", connector_id, crtc_id);

    /* Choose the preferred mode, if available */
    drmModeModeInfo mode = conn->modes[0];

    for (int i = 0; i < conn->count_modes; i++) {
        if (conn->modes[i].type & DRM_MODE_TYPE_PREFERRED) {
            mode = conn->modes[i];
            break;
        }
    }

    uint32_t width = mode.hdisplay;
    uint32_t height = mode.vdisplay;

    printf("Display mode: %ux%u\n", width, height);

    /* Save the old CRTC state for restoration */
    old_crtc = drmModeGetCrtc(fd, crtc_id);
    if (!old_crtc) {
        perror("drmModeGetCrtc");
        goto cleanup;
    }

    /* Create a 32-bit dumb buffer */
    create.width = width;
    create.height = height;
    create.bpp = 32;

    if (ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create) < 0) {
        perror("CREATE_DUMB");
        goto cleanup;
    }

    handle = create.handle;
    buffer_size = create.size;

    /* Map the buffer into this process's memory */
    map.handle = handle;

    if (ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map) < 0) {
        perror("MAP_DUMB");
        goto cleanup;
    }

    pixels = mmap(NULL, buffer_size,
                  PROT_READ | PROT_WRITE,
                  MAP_SHARED, fd, map.offset);

    if (pixels == MAP_FAILED) {
        perror("mmap");
        goto cleanup;
    }

    /* Start with a black background */
    memset(pixels, 0, buffer_size);

    /*
     * Draw a red rectangle in the center.
     * XRGB8888: red pixel = 0x00FF0000
     */
    uint32_t *framebuffer = (uint32_t *)pixels;
    uint32_t pitch_pixels = create.pitch / sizeof(uint32_t);

    uint32_t x1 = width / 4;
    uint32_t x2 = (width * 3) / 4;
    uint32_t y1 = height / 4;
    uint32_t y2 = (height * 3) / 4;

    for (uint32_t y = y1; y < y2; y++) {
        for (uint32_t x = x1; x < x2; x++) {
            framebuffer[y * pitch_pixels + x] = 0x00FF0000;
        }
    }

    /* Register the buffer as a DRM framebuffer */
    if (drmModeAddFB(fd, width, height, 24, 32,
                     create.pitch, handle, &fb_id) < 0) {
        perror("drmModeAddFB");
        goto cleanup;
    }

    /* Display the framebuffer */
    if (drmModeSetCrtc(fd, crtc_id, fb_id, 0, 0,
                       &connector_id, 1, &mode) < 0) {
        perror("drmModeSetCrtc");
        goto cleanup;
    }

    modeset_done = 1;
    printf("Red rectangle displayed. Press Enter to restore the old display.\n");
    getchar();

    result = 0;

cleanup:
    if (modeset_done && old_crtc) {
        if (old_crtc->mode_valid) {
            if (drmModeSetCrtc(fd, old_crtc->crtc_id,
                               old_crtc->buffer_id,
                               old_crtc->x, old_crtc->y,
                               &connector_id, 1,
                               &old_crtc->mode) < 0)
                perror("Restore CRTC");
        } else {
            if (drmModeSetCrtc(fd, crtc_id, 0, 0, 0,
                               NULL, 0, NULL) < 0)
                perror("Disable test CRTC");
        }
    }

    if (fb_id && fd >= 0)
        drmModeRmFB(fd, fb_id);

    if (pixels != MAP_FAILED)
        munmap(pixels, buffer_size);

    if (handle && fd >= 0) {
        destroy.handle = handle;
        if (ioctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy) < 0)
            perror("DESTROY_DUMB");
    }

    if (old_crtc)
        drmModeFreeCrtc(old_crtc);
    if (enc)
        drmModeFreeEncoder(enc);
    if (conn)
        drmModeFreeConnector(conn);
    if (res)
        drmModeFreeResources(res);
    if (fd >= 0)
        close(fd);

    return result;
}

6,609 chars · codepastes.com