Advertisement
Guest User

DRM sample app

a guest
Jan 6th, 2025
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.36 KB | Source Code | 0 0
  1.  
  2. #include <fcntl.h>
  3. #include <gbm.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <time.h>
  10. #include <unistd.h>
  11. #include <xf86drm.h>
  12. #include <xf86drmMode.h>
  13.  
  14. typedef struct __attribute__((packed)) {
  15.   uint8_t b;
  16.   uint8_t g;
  17.   uint8_t r;
  18.   uint8_t x;
  19. } xrgb8888_pixel;
  20.  
  21. typedef struct {
  22.     int card_fd;
  23.  
  24.     struct gbm_device * gbm_dev;
  25.     struct gbm_bo * gbm_bo;
  26.  
  27.     uint32_t crtc_id;
  28.     uint32_t conn_id;
  29.     uint32_t buffer_handle;
  30.  
  31.     drmModeModeInfo mode_info;
  32.  
  33. } drm_app_context;
  34.  
  35.  
  36. #define COUNT_CARD_NAMES 2
  37. static const char *const card_names[]=
  38.         {"/dev/dri/card0",
  39.         "/dev/dri/card1"};
  40.  
  41. uint32_t modeset_find_suitable_crtc(int fd, drmModeResPtr resources,
  42.                                     drmModeConnector *conn) {
  43.  
  44.   drmModeEncoder *enc;
  45.  
  46.   for (int i = 0; i < resources->count_encoders; ++i) {
  47.     enc = drmModeGetEncoder(fd, resources->encoders[i]);
  48.     if (!enc) {
  49.       continue;
  50.     }
  51.  
  52.     for (int j = 0; j < resources->count_crtcs; ++j) {
  53.       if (enc->possible_crtcs & (1 << j)) {
  54.         drmModeFreeEncoder(enc);
  55.         return resources->crtcs[j];
  56.       }
  57.     }
  58.   }
  59.  
  60.   drmModeFreeEncoder(enc);
  61.   return -1;
  62. }
  63.  
  64. drm_app_context *init_drm_app() {
  65.   int card_fd = -1;
  66.   drmModeRes *res = NULL;
  67.   drmModeConnector *conn = NULL;
  68.   drmModeCrtc *crtc = NULL;
  69.   drm_app_context *ctx = NULL;
  70.  
  71.   struct gbm_device *device = NULL;
  72.   struct gbm_bo *bo = NULL;
  73.  
  74.   for (int i = 0; i < COUNT_CARD_NAMES; ++i) {
  75.     card_fd = open(card_names[i], O_RDWR | O_NONBLOCK);
  76.     if (card_fd >= 0) {
  77.       break;
  78.     }
  79.   }
  80.   if(card_fd < 0){
  81.       fprintf(stderr, "Unable to open any of {card0, card1}\n");
  82.       goto err;
  83.   }
  84.  
  85.   if(drmSetMaster(card_fd) < 0){
  86.     fprintf(stderr, "Master for card is already set");
  87.     goto err;
  88.   }
  89.  
  90.   if (card_fd < 0) {
  91.     fprintf(stderr, "Could not open any dri cards\n");
  92.     goto err;
  93.   }
  94.  
  95.   res = drmModeGetResources(card_fd);
  96.   if (!res) {
  97.     fprintf(stderr, "Could not obtain drm resources\n");
  98.     goto err;
  99.   }
  100.  
  101.   for (int i = 0; i < res->count_connectors; ++i) {
  102.     conn = drmModeGetConnector(card_fd, res->connectors[i]);
  103.     if (conn && conn->count_modes > 0) {
  104.       break;
  105.     }
  106.   }
  107.  
  108.   if (!conn || conn->count_modes == 0) {
  109.     fprintf(stderr, "No active connectors found\n");
  110.     goto err;
  111.   }
  112.  
  113.   uint32_t crtc_id = modeset_find_suitable_crtc(card_fd, res, conn);
  114.   if (crtc_id == -1) {
  115.     fprintf(stderr, "No suitable crtcs found");
  116.     goto err;
  117.   }
  118.  
  119.   device = gbm_create_device(card_fd);
  120.   if (!device) {
  121.     fprintf(stderr, "GBM device creation failed");
  122.     goto err;
  123.   }
  124.  
  125.   bo = gbm_bo_create(device, conn->modes[0].hdisplay, conn->modes[0].vdisplay,
  126.                      GBM_FORMAT_XRGB8888,
  127.                      GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
  128.   if (!bo) {
  129.     fprintf(stderr, "Failed to create buffer object");
  130.     goto err;
  131.   }
  132.  
  133.   int plane_count = gbm_bo_get_plane_count(bo);
  134.  
  135.   uint32_t handles[4] = {};
  136.   uint32_t pitches[4] = {};
  137.   uint32_t offsets[4] = {};
  138.   for (int i = 0; i < plane_count; ++i) {
  139.     handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32;
  140.     pitches[i] = gbm_bo_get_stride_for_plane(bo, i);
  141.     offsets[i] = gbm_bo_get_offset(bo, i);
  142.   }
  143.   uint32_t buf_id;
  144.   uint32_t bo_format = gbm_bo_get_format(bo);
  145.  
  146.   if (drmModeAddFB2(card_fd, conn->modes[0].hdisplay, conn->modes[0].vdisplay,
  147.                     bo_format, handles, pitches, offsets, &buf_id, 0) != 0) {
  148.  
  149.     fprintf(stderr, "Unable to add FB");
  150.     goto err;
  151.   }
  152.  
  153.  
  154.   uint32_t connector_id = conn->connector_id;
  155.   drmModeModeInfo mode_info = conn->modes[0];
  156.  
  157.   drmModeFreeResources(res);
  158.   drmModeFreeConnector(conn);
  159.   drmModeFreeCrtc(crtc);
  160.  
  161.   ctx = (drm_app_context *)malloc(sizeof(drm_app_context));
  162.   ctx->card_fd = card_fd;
  163.   ctx->gbm_bo = bo;
  164.   ctx->gbm_dev = device;
  165.   ctx->mode_info = mode_info;
  166.  
  167.   ctx->crtc_id = crtc_id;
  168.   ctx->conn_id = connector_id;
  169.   ctx->buffer_handle = buf_id;
  170.   return ctx;
  171.  
  172. err:
  173.   // works fine with NULL pointers
  174.   drmModeFreeResources(res);
  175.   drmModeFreeConnector(conn);
  176.   drmModeFreeCrtc(crtc);
  177.   if (card_fd > 0) {
  178.     drmDropMaster(card_fd);
  179.     drmModeRmFB(card_fd, buf_id);
  180.   }
  181.   if (bo)
  182.     gbm_bo_destroy(bo);
  183.   if (device)
  184.     gbm_device_destroy(device);
  185.   close(card_fd);
  186.  
  187.   return NULL;
  188. }
  189.  
  190. void destroy_context(drm_app_context *ctx) {
  191.   drmDropMaster(ctx->card_fd);
  192.   drmModeRmFB(ctx->card_fd, ctx->buffer_handle);
  193.   gbm_bo_destroy(ctx->gbm_bo);
  194.   gbm_device_destroy(ctx->gbm_dev);
  195.   close(ctx->card_fd);
  196. }
  197.  
  198. // This does work, but the buffer is mapped before rendering each frame
  199.  
  200. int main() {
  201.   drm_app_context *ctx = init_drm_app();
  202.   if (ctx == NULL) {
  203.     return 1;
  204.   }
  205.   xrgb8888_pixel *fb = NULL;
  206.   uint32_t map_stride;
  207.   void *map_data = NULL;
  208.   for (int i = 0; i < 256; ++i) {
  209.     fb = (xrgb8888_pixel *)gbm_bo_map(
  210.         ctx->gbm_bo, 0, 0, gbm_bo_get_width(ctx->gbm_bo),
  211.         gbm_bo_get_height(ctx->gbm_bo), GBM_BO_TRANSFER_READ_WRITE, &map_stride,
  212.         &map_data);
  213.  
  214.    int bufsize = map_stride * ctx->mode_info.vdisplay;
  215.  
  216.     for (int j = 0; j < bufsize / 4; ++j) {
  217.       fb[j].r = (2 * i + j) % 256;
  218.       fb[j].g = (4 * i + 2*j) % 256;
  219.       fb[j].b = (8 * i + 4*j) % 256;
  220.     }
  221.  
  222.     gbm_bo_unmap(ctx->gbm_bo, map_data);
  223.     map_data = NULL;
  224.     drmModeSetCrtc(ctx->card_fd, ctx->crtc_id, ctx->buffer_handle, 0, 0,
  225.                    &ctx->conn_id, 1, &ctx->mode_info);
  226.   }
  227.  
  228.   destroy_context(ctx);
  229.   return 0;
  230. }
  231.  
  232.  
  233. // This doesn't work
  234.  
  235. /* int main() {
  236.   drm_app_context *ctx = init_drm_app();
  237.   if (ctx == NULL) {
  238.     return 1;
  239.   }
  240.   xrgb8888_pixel *fb = NULL;
  241.   uint32_t map_stride;
  242.   void *map_data = NULL;
  243.   fb = (xrgb8888_pixel *)gbm_bo_map(
  244.         ctx->gbm_bo, 0, 0, gbm_bo_get_width(ctx->gbm_bo),
  245.         gbm_bo_get_height(ctx->gbm_bo), GBM_BO_TRANSFER_READ_WRITE, &map_stride,
  246.         &map_data);
  247.   for (int i = 0; i < 256; ++i) {
  248.  
  249.    int bufsize = map_stride * ctx->mode_info.vdisplay;
  250.  
  251.     for (int j = 0; j < bufsize / 4; ++j) {
  252.       fb[j].r = (2 * i + j) % 256;
  253.       fb[j].g = (4 * i + 2*j) % 256;
  254.       fb[j].b = (8 * i + 4*j) % 256;
  255.     }
  256.  
  257.     drmModeSetCrtc(ctx->card_fd, ctx->crtc_id, ctx->buffer_handle, 0, 0,
  258.                    &ctx->conn_id, 1, &ctx->mode_info);
  259.   }
  260.  
  261.   gbm_bo_unmap(ctx->gbm_bo, map_data);
  262.   destroy_context(ctx);
  263.   return 0;
  264. } */
  265.  
  266.  
  267.  
  268.  
  269.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement