+static void
+pageFlipHandler(int /*fd*/, unsigned int /*frame*/, unsigned int /*sec*/,
+ unsigned int /*usec*/, void *data)
+{
+ struct DrmOutput *output = static_cast<struct DrmOutput*>(data);
+
+ output->pageFlipPending = 0;
+
+ if (output->current)
+ {
+ gbm_surface_release_buffer(output->surface, output->current->bo);
+ }
+
+ output->current = output->next;
+ output->next = NULL;
+
+ if (output->windowSystem)
+ {
+ output->windowSystem->finishFrame();
+ }
+}
+
+static int
+onDrmInput(int fd, uint32_t /*mask*/, void * /*data*/)
+{
+ drmEventContext evctx;
+ memset(&evctx, 0, sizeof evctx);
+
+ evctx.version = DRM_EVENT_CONTEXT_VERSION;
+ evctx.page_flip_handler = pageFlipHandler;
+ evctx.vblank_handler = NULL;
+
+ drmHandleEvent(fd, &evctx);
+
+ return 1;
+}
+
+static void
+drmFbDestroyCallback(struct gbm_bo *bo, void *data)
+{
+ struct DrmFb *fb = (struct DrmFb*)data;
+ struct gbm_device *gbm = gbm_bo_get_device(bo);
+
+ if (fb->fbId)
+ drmModeRmFB(gbm_device_get_fd(gbm), fb->fbId);
+
+ free(data);
+}
+
+struct DrmFb*
+drmFbGetFromBo(struct gbm_bo *bo, int fdDev, struct DrmOutput *output)
+{
+ struct DrmFb *fb = (struct DrmFb*)gbm_bo_get_user_data(bo);
+ uint32_t width, height, stride, handle;
+ int ret;
+
+ if (fb)
+ return fb;
+
+ fb = (struct DrmFb*)malloc(sizeof *fb);
+ fb->bo = bo;
+ fb->output = output;
+
+ width = gbm_bo_get_width(bo);
+ height = gbm_bo_get_height(bo);
+ stride = gbm_bo_get_stride(bo);
+ handle = gbm_bo_get_handle(bo).u32;
+
+ ret = drmModeAddFB(fdDev, width, height, 24, 32, stride, handle, &fb->fbId);
+ if (ret)
+ {
+ return NULL;
+ }
+
+ gbm_bo_set_user_data(bo, fb, drmFbDestroyCallback);
+
+ return fb;
+}
+