diff options
author | Rob Clark <robdclark@gmail.com> | 2017-02-21 17:01:16 -0500 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2017-02-22 10:31:02 -0500 |
commit | 1f1158fe1279e845420d3cb838eff3bbf2e5701a (patch) | |
tree | 95fe331b322f1a4d67ed1f1c77b36c0cb8ece71c /kmscube.c | |
parent | 3e78eabeeeeb8476583cf2d37f1bd561307694db (diff) | |
download | kmscube-1f1158fe1279e845420d3cb838eff3bbf2e5701a.tar.gz |
split out legacy (pageflip) kms
Preping to add new atomic alternative path.
Diffstat (limited to 'kmscube.c')
-rw-r--r-- | kmscube.c | 271 |
1 files changed, 6 insertions, 265 deletions
@@ -24,213 +24,19 @@ /* Based on a egl cube test app originally written by Arvin Schnell */ -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> #include <string.h> #include <stdio.h> -#include <stdlib.h> #include <getopt.h> -#include <errno.h> - -#include <xf86drm.h> -#include <xf86drmMode.h> - -#include <assert.h> #include "common.h" +#include "drm.h" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static const struct egl *egl; static const struct gbm *gbm; - -static struct { - int fd; - drmModeModeInfo *mode; - uint32_t crtc_id; - uint32_t connector_id; -} drm; - -struct drm_fb { - struct gbm_bo *bo; - uint32_t fb_id; -}; - -static uint32_t find_crtc_for_encoder(const drmModeRes *resources, - const drmModeEncoder *encoder) { - int i; - - for (i = 0; i < resources->count_crtcs; i++) { - /* possible_crtcs is a bitmask as described here: - * https://dvdhrm.wordpress.com/2012/09/13/linux-drm-mode-setting-api - */ - const uint32_t crtc_mask = 1 << i; - const uint32_t crtc_id = resources->crtcs[i]; - if (encoder->possible_crtcs & crtc_mask) { - return crtc_id; - } - } - - /* no match found */ - return -1; -} - -static uint32_t find_crtc_for_connector(const drmModeRes *resources, - const drmModeConnector *connector) { - int i; - - for (i = 0; i < connector->count_encoders; i++) { - const uint32_t encoder_id = connector->encoders[i]; - drmModeEncoder *encoder = drmModeGetEncoder(drm.fd, encoder_id); - - if (encoder) { - const uint32_t crtc_id = find_crtc_for_encoder(resources, encoder); - - drmModeFreeEncoder(encoder); - if (crtc_id != 0) { - return crtc_id; - } - } - } - - /* no match found */ - return -1; -} - -static int init_drm(const char *dev) -{ - drmModeRes *resources; - drmModeConnector *connector = NULL; - drmModeEncoder *encoder = NULL; - int i, area; - - drm.fd = open(dev, O_RDWR); - - if (drm.fd < 0) { - printf("could not open drm device\n"); - return -1; - } - - resources = drmModeGetResources(drm.fd); - if (!resources) { - printf("drmModeGetResources failed: %s\n", strerror(errno)); - return -1; - } - - /* find a connected connector: */ - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(drm.fd, resources->connectors[i]); - if (connector->connection == DRM_MODE_CONNECTED) { - /* it's connected, let's use this! */ - break; - } - drmModeFreeConnector(connector); - connector = NULL; - } - - if (!connector) { - /* we could be fancy and listen for hotplug events and wait for - * a connector.. - */ - printf("no connected connector!\n"); - return -1; - } - - /* find prefered mode or the highest resolution mode: */ - for (i = 0, area = 0; i < connector->count_modes; i++) { - drmModeModeInfo *current_mode = &connector->modes[i]; - - if (current_mode->type & DRM_MODE_TYPE_PREFERRED) { - drm.mode = current_mode; - } - - int current_area = current_mode->hdisplay * current_mode->vdisplay; - if (current_area > area) { - drm.mode = current_mode; - area = current_area; - } - } - - if (!drm.mode) { - printf("could not find mode!\n"); - return -1; - } - - /* find encoder: */ - for (i = 0; i < resources->count_encoders; i++) { - encoder = drmModeGetEncoder(drm.fd, resources->encoders[i]); - if (encoder->encoder_id == connector->encoder_id) - break; - drmModeFreeEncoder(encoder); - encoder = NULL; - } - - if (encoder) { - drm.crtc_id = encoder->crtc_id; - } else { - uint32_t crtc_id = find_crtc_for_connector(resources, connector); - if (crtc_id == 0) { - printf("no crtc found!\n"); - return -1; - } - - drm.crtc_id = crtc_id; - } - - drm.connector_id = connector->connector_id; - - return 0; -} - -static void -drm_fb_destroy_callback(struct gbm_bo *bo, void *data) -{ - struct drm_fb *fb = data; - struct gbm_device *gbm = gbm_bo_get_device(bo); - - if (fb->fb_id) - drmModeRmFB(drm.fd, fb->fb_id); - - free(fb); -} - -static struct drm_fb * drm_fb_get_from_bo(struct gbm_bo *bo) -{ - struct drm_fb *fb = gbm_bo_get_user_data(bo); - uint32_t width, height, stride, handle; - int ret; - - if (fb) - return fb; - - fb = calloc(1, sizeof *fb); - fb->bo = bo; - - 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(drm.fd, width, height, 24, 32, stride, handle, &fb->fb_id); - if (ret) { - printf("failed to create fb: %s\n", strerror(errno)); - free(fb); - return NULL; - } - - gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); - - return fb; -} - -static void page_flip_handler(int fd, unsigned int frame, - unsigned int sec, unsigned int usec, void *data) -{ - int *waiting_for_flip = data; - *waiting_for_flip = 0; -} +static const struct drm *drm; static const char *shortopts = "D:M:"; @@ -256,14 +62,6 @@ static void usage(const char *name) int main(int argc, char *argv[]) { - fd_set fds; - drmEventContext evctx = { - .version = DRM_EVENT_CONTEXT_VERSION, - .page_flip_handler = page_flip_handler, - }; - struct gbm_bo *bo; - struct drm_fb *fb; - uint32_t i = 0; const char *device = "/dev/dri/card0"; enum mode mode = SMOOTH; int opt, ret; @@ -294,17 +92,13 @@ int main(int argc, char *argv[]) } } - ret = init_drm(device); - if (ret) { + drm = init_drm_legacy(device); + if (!drm) { printf("failed to initialize DRM\n"); return ret; } - FD_ZERO(&fds); - FD_SET(0, &fds); - FD_SET(drm.fd, &fds); - - gbm = init_gbm(drm.fd, drm.mode->hdisplay, drm.mode->vdisplay); + gbm = init_gbm(drm->fd, drm->mode->hdisplay, drm->mode->vdisplay); if (!gbm) { printf("failed to initialize GBM\n"); return -1; @@ -324,59 +118,6 @@ int main(int argc, char *argv[]) /* clear the color buffer */ glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(egl->display, egl->surface); - bo = gbm_surface_lock_front_buffer(gbm->surface); - fb = drm_fb_get_from_bo(bo); - - /* set mode: */ - ret = drmModeSetCrtc(drm.fd, drm.crtc_id, fb->fb_id, 0, 0, - &drm.connector_id, 1, drm.mode); - if (ret) { - printf("failed to set mode: %s\n", strerror(errno)); - return ret; - } - - while (1) { - struct gbm_bo *next_bo; - int waiting_for_flip = 1; - - egl->draw(i++); - - eglSwapBuffers(egl->display, egl->surface); - next_bo = gbm_surface_lock_front_buffer(gbm->surface); - fb = drm_fb_get_from_bo(next_bo); - - /* - * Here you could also update drm plane layers if you want - * hw composition - */ - - ret = drmModePageFlip(drm.fd, drm.crtc_id, fb->fb_id, - DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip); - if (ret) { - printf("failed to queue page flip: %s\n", strerror(errno)); - return -1; - } - - while (waiting_for_flip) { - ret = select(drm.fd + 1, &fds, NULL, NULL, NULL); - if (ret < 0) { - printf("select err: %s\n", strerror(errno)); - return ret; - } else if (ret == 0) { - printf("select timeout!\n"); - return -1; - } else if (FD_ISSET(0, &fds)) { - printf("user interrupted!\n"); - break; - } - drmHandleEvent(drm.fd, &evctx); - } - - /* release last buffer to render on again: */ - gbm_surface_release_buffer(gbm->surface, bo); - bo = next_bo; - } - return ret; + return drm->run(gbm, egl); } |