| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <xf86drm.h> |
| #include <xf86drmMode.h> |
| #include <drm_fourcc.h> |
| |
| #include "modeset.h" |
| #include "bo.h" |
| #include "dev.h" |
| |
| int initialize_screens(struct sp_dev *dev) |
| { |
| int ret, i, j, k; |
| |
| for (i = 0; i < dev->num_connectors; i++) { |
| drmModeConnectorPtr c = dev->connectors[i]; |
| drmModeModeInfoPtr m = NULL; |
| drmModeEncoderPtr e = NULL; |
| struct sp_crtc *cr = NULL; |
| |
| if (c->connection != DRM_MODE_CONNECTED) |
| continue; |
| |
| if (!c->count_modes) { |
| printf("connector has no modes, skipping\n"); |
| continue; |
| } |
| |
| /* Take the first unless there's a preferred mode */ |
| m = &c->modes[0]; |
| for (j = 0; j < c->count_modes; j++) { |
| drmModeModeInfoPtr tmp_m = &c->modes[j]; |
| |
| if (!(tmp_m->type & DRM_MODE_TYPE_PREFERRED)) |
| continue; |
| |
| m = tmp_m; |
| break; |
| } |
| |
| for (j = 0; j < dev->num_encoders; j++) { |
| e = dev->encoders[j]; |
| if (!e) |
| continue; |
| for (k = 0; k < c->count_encoders; k++) { |
| if (e->encoder_id == c->encoders[k]) |
| break; |
| } |
| if (k < c->count_encoders) |
| break; |
| } |
| |
| if (j == dev->num_encoders) { |
| printf("could not find supported encoder for the connector\n"); |
| continue; |
| } |
| |
| for (j = 0; j < dev->num_crtcs; j++) { |
| cr = &dev->crtcs[j]; |
| if (e->possible_crtcs & (1 << j)) { |
| e->crtc_id = cr->crtc->crtc_id; |
| break; |
| } |
| } |
| |
| if (j == dev->num_crtcs) { |
| printf("could not find crtc for the encoder\n"); |
| continue; |
| } |
| |
| if (cr->scanout) { |
| printf("crtc already in use\n"); |
| continue; |
| } |
| |
| /* XXX: Hardcoding the format here... :| */ |
| cr->scanout = create_sp_bo(dev, m->hdisplay, m->vdisplay, |
| 24, 32, DRM_FORMAT_XRGB8888, 0); |
| if (!cr->scanout) { |
| printf("failed to create new scanout bo\n"); |
| continue; |
| } |
| |
| fill_bo(cr->scanout, 0xFF, 0xFF, 0xFF, 0x00); |
| |
| ret = drmModeSetCrtc(dev->fd, cr->crtc->crtc_id, |
| cr->scanout->fb_id, 0, 0, &c->connector_id, |
| 1, m); |
| if (ret) { |
| printf("failed to set crtc mode ret=%d\n", ret); |
| continue; |
| } |
| |
| cr->crtc->mode.hdisplay = m->hdisplay; |
| cr->crtc->mode.vdisplay = m->vdisplay; |
| } |
| return 0; |
| } |
| |
| struct sp_plane *get_sp_plane(struct sp_dev *dev, struct sp_crtc *crtc) |
| { |
| int i; |
| |
| for(i = 0; i < dev->num_planes; i++) { |
| struct sp_plane *p = &dev->planes[i]; |
| |
| if (p->in_use) |
| continue; |
| |
| if (!(p->plane->possible_crtcs & (1 << crtc->pipe))) |
| continue; |
| |
| p->in_use = 1; |
| return p; |
| } |
| return NULL; |
| } |
| |
| void put_sp_plane(struct sp_plane *plane) |
| { |
| drmModePlanePtr p; |
| |
| /* Get the latest plane information (most notably the crtc_id) */ |
| p = drmModeGetPlane(plane->dev->fd, plane->plane->plane_id); |
| if (p) |
| plane->plane = p; |
| |
| if (plane->plane->crtc_id) |
| drmModeSetPlane(plane->dev->fd, plane->plane->plane_id, |
| plane->plane->crtc_id, 0, 0, |
| 0, 0, 0, 0, 0, 0, 0, 0); |
| |
| if (plane->bo) { |
| free_sp_bo(plane->bo); |
| plane->bo = NULL; |
| } |
| plane->in_use = 0; |
| } |
| |
| int set_sp_plane(struct sp_dev *dev, struct sp_plane *plane, |
| struct sp_crtc *crtc, int x, int y) |
| { |
| int ret; |
| uint32_t w, h; |
| |
| w = plane->bo->width; |
| h = plane->bo->height; |
| |
| if ((w + x) > crtc->crtc->mode.hdisplay) |
| w = crtc->crtc->mode.hdisplay - x; |
| if ((h + y) > crtc->crtc->mode.vdisplay) |
| h = crtc->crtc->mode.vdisplay - y; |
| |
| ret = drmModeSetPlane(dev->fd, plane->plane->plane_id, |
| crtc->crtc->crtc_id, plane->bo->fb_id, 0, x, y, w, h, |
| 0, 0, w << 16, h << 16); |
| if (ret) { |
| printf("failed to set plane to crtc ret=%d\n", ret); |
| return ret; |
| } |
| |
| return ret; |
| } |
| #ifdef USE_ATOMIC_API |
| int set_sp_plane_pset(struct sp_dev *dev, struct sp_plane *plane, |
| drmModePropertySetPtr pset, struct sp_crtc *crtc, int x, int y) |
| { |
| int ret; |
| uint32_t w, h; |
| |
| w = plane->bo->width; |
| h = plane->bo->height; |
| |
| if ((w + x) > crtc->crtc->mode.hdisplay) |
| w = crtc->crtc->mode.hdisplay - x; |
| if ((h + y) > crtc->crtc->mode.vdisplay) |
| h = crtc->crtc->mode.vdisplay - y; |
| |
| ret = drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->crtc_pid, crtc->crtc->crtc_id) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->fb_pid, plane->bo->fb_id) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->crtc_x_pid, x) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->crtc_y_pid, y) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->crtc_w_pid, w) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->crtc_h_pid, h) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->src_x_pid, 0) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->src_y_pid, 0) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->src_w_pid, w << 16) |
| || drmModePropertySetAdd(pset, plane->plane->plane_id, |
| plane->src_h_pid, h << 16); |
| if (ret) { |
| printf("failed to add properties to the set\n"); |
| return -1; |
| } |
| |
| return ret; |
| } |
| #endif |