#include "renderer.h" #include "fb.h" #include #include #include #include #include static int drm_fd; static drmModeConnector *conn; static drmModeCrtc *crtc; static uint32_t conn_id; static fb_info_t fbs[2]; static int front, back; static uint32_t width, height; static void page_flip_handler(int, unsigned, unsigned, unsigned, void *) { } static void set_pixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) { /* x %= width; */ /* y %= height; */ const uint32_t offset = y * (fbs[back].pitch / 4) + x; assert(offset < fbs[back].size); fbs[back].buf[offset] = (r << 16) | (g << 8) | b; } renderer_params_t renderer_init() { drm_fd = open("/dev/dri/card1", O_RDWR | O_CLOEXEC); assert(drm_fd != -1); drmModeRes *res = drmModeGetResources(drm_fd); assert(res != nullptr); conn = drmModeGetConnector(drm_fd, res->connectors[0]); assert(conn != nullptr); drmModeModeInfo mode = conn->modes[0]; conn_id = conn->connector_id; fbs[0] = fb_init(drm_fd, mode); fbs[1] = fb_init(drm_fd, mode); front = 0; back = 1; const int err = drmModeSetCrtc( drm_fd, res->crtcs[0], fbs[front].id, 0, 0, &conn_id, 1, &mode); assert(err == 0); crtc = drmModeGetCrtc(drm_fd, res->crtcs[0]); assert(crtc != nullptr); drmModeFreeResources(res); width = mode.hdisplay; height = mode.vdisplay; return (renderer_params_t) { .drm_fd = drm_fd, .aspect = (float)mode.hdisplay / (float)mode.vdisplay, }; } void renderer_cleanup() { drmModeSetCrtc( drm_fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &conn_id, 1, &crtc->mode); fb_cleanup(drm_fd, fbs[0]); fb_cleanup(drm_fd, fbs[1]); drmModeFreeCrtc(crtc); drmModeFreeConnector(conn); close(drm_fd); } void renderer_handle() { drmEventContext ev = { .version = DRM_EVENT_CONTEXT_VERSION, .page_flip_handler = page_flip_handler, }; drmHandleEvent(drm_fd, &ev); } void renderer_clear() { memset(fbs[back].buf, 0, fbs[back].size); } void renderer_swap() { const int err = drmModePageFlip( drm_fd, crtc->crtc_id, fbs[back].id, DRM_MODE_PAGE_FLIP_EVENT, nullptr); assert(err == 0); front = (front + 1) & 1; back = (back + 1) & 1; } void renderer_draw() { for (unsigned y = 0; y < height; ++y) { for (unsigned x = 0; x < width; ++x) set_pixel(x, y, (x * 255) / width, (y * 255) / height, 128); } }