Scan to open on your phone
Point a camera at the QR code - it opens this exact paste, no app needed.
https://codepastes.com/zzgsk5448cfdfk90drmPlain Text
#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