modeset-page-flip.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #define _GNU_SOURCE
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <stdbool.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/mman.h>
  10. #include <time.h>
  11. #include <unistd.h>
  12. #include <signal.h>
  13. #include <xf86drm.h>
  14. #include <xf86drmMode.h>
  15. struct buffer_object {
  16. uint32_t width;
  17. uint32_t height;
  18. uint32_t pitch;
  19. uint32_t handle;
  20. uint32_t size;
  21. uint32_t *vaddr;
  22. uint32_t fb_id;
  23. };
  24. struct buffer_object buf[2] = {0};
  25. static int terminate = 0;
  26. static int modeset_create_fb(int fd, struct buffer_object *bo, uint32_t color)
  27. {
  28. struct drm_mode_create_dumb create = {};
  29. struct drm_mode_map_dumb map = {};
  30. uint32_t i;
  31. create.width = bo->width;
  32. create.height = bo->height;
  33. create.bpp = 32;
  34. drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
  35. bo->pitch = create.pitch;
  36. bo->size = create.size;
  37. bo->handle = create.handle;
  38. // {24, 32}
  39. drmModeAddFB(fd, bo->width, bo->height, 32, 32, bo->pitch,
  40. bo->handle, &bo->fb_id);
  41. map.handle = create.handle;
  42. drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
  43. bo->vaddr = mmap(0, create.size, PROT_READ | PROT_WRITE,
  44. MAP_SHARED, fd, map.offset);
  45. for (i = 0; i < (bo->size / 4); i++)
  46. bo->vaddr[i] = color;
  47. return 0;
  48. }
  49. static void modeset_destroy_fb(int fd, struct buffer_object *bo)
  50. {
  51. struct drm_mode_destroy_dumb destroy = {};
  52. drmModeRmFB(fd, bo->fb_id);
  53. munmap(bo->vaddr, bo->size);
  54. destroy.handle = bo->handle;
  55. drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy);
  56. }
  57. static void modeset_page_flip_handler(int fd, uint32_t frame,
  58. uint32_t sec, uint32_t usec,
  59. void *data)
  60. {
  61. static int i = 0;
  62. uint32_t crtc_id = *(uint32_t *)data;
  63. drmMsg("[%s,%d]: fd=%d, sec=%d, usec=%d,crtc_id=%d\n",__FUNCTION__,__LINE__,
  64. fd, sec, usec, crtc_id);
  65. i ^= 1;
  66. drmModePageFlip(fd, crtc_id, buf[i].fb_id,
  67. DRM_MODE_PAGE_FLIP_EVENT, data);
  68. usleep(500000);
  69. }
  70. static void sigint_handler(int arg)
  71. {
  72. terminate = 1;
  73. }
  74. int main(int argc, char **argv)
  75. {
  76. int fd;
  77. drmEventContext ev = {};
  78. drmModeConnector *conn;
  79. drmModeRes *res;
  80. uint32_t conn_id;
  81. uint32_t crtc_id;
  82. signal(SIGINT, sigint_handler);
  83. ev.version = DRM_EVENT_CONTEXT_VERSION;
  84. ev.page_flip_handler = modeset_page_flip_handler;
  85. fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
  86. res = drmModeGetResources(fd);
  87. crtc_id = res->crtcs[0];
  88. conn_id = res->connectors[0];
  89. conn = drmModeGetConnector(fd, conn_id);
  90. buf[0].width = conn->modes[0].hdisplay;
  91. buf[0].height = conn->modes[0].vdisplay;
  92. buf[1].width = conn->modes[0].hdisplay;
  93. buf[1].height = conn->modes[0].vdisplay;
  94. modeset_create_fb(fd, &buf[0], 0xff0000);
  95. modeset_create_fb(fd, &buf[1], 0x0000ff);
  96. drmModeSetCrtc(fd, crtc_id, buf[0].fb_id,
  97. 0, 0, &conn_id, 1, &conn->modes[0]);
  98. drmModePageFlip(fd, crtc_id, buf[0].fb_id,
  99. DRM_MODE_PAGE_FLIP_EVENT, &crtc_id);
  100. while (!terminate) {
  101. drmHandleEvent(fd, &ev);
  102. }
  103. modeset_destroy_fb(fd, &buf[1]);
  104. modeset_destroy_fb(fd, &buf[0]);
  105. drmModeFreeConnector(conn);
  106. drmModeFreeResources(res);
  107. close(fd);
  108. return 0;
  109. }