#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; 
 | 
  
 | 
  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; 
 | 
    } 
 | 
  
 | 
    if (!c->encoder_id) { 
 | 
      /* 
 | 
       * default drm encoder not attached connector, just 
 | 
       * select the first one. 
 | 
       */ 
 | 
      if (dev->num_encoders) { 
 | 
        e = dev->encoders[0]; 
 | 
        c->encoder_id = e->encoder_id; 
 | 
      } else { 
 | 
        printf("no encoder attached to the connector\n"); 
 | 
        continue; 
 | 
      } 
 | 
    } 
 | 
  
 | 
    for (j = 0; j < dev->num_encoders; j++) { 
 | 
      e = dev->encoders[j]; 
 | 
      if (e->encoder_id == c->encoder_id) 
 | 
        break; 
 | 
    } 
 | 
    if (j == dev->num_encoders) { 
 | 
      printf("could not find encoder for the connector\n"); 
 | 
      continue; 
 | 
    } 
 | 
  
 | 
    if (!e->crtc_id) { 
 | 
      /* 
 | 
       * default drm crtc not attached encoder, just 
 | 
       * select the first one. 
 | 
       */ 
 | 
      if (dev->num_crtcs) { 
 | 
        cr = &dev->crtcs[j]; 
 | 
        e->crtc_id = cr->crtc->crtc_id; 
 | 
      } else { 
 | 
        printf("no crtc attached to the encoder\n"); 
 | 
        continue; 
 | 
      } 
 | 
    } 
 | 
  
 | 
    for (j = 0; j < dev->num_crtcs; j++) { 
 | 
      cr = &dev->crtcs[j]; 
 | 
  
 | 
      if (cr->crtc->crtc_id == e->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; 
 | 
    } 
 | 
  
 | 
    ret = add_fb_sp_bo(cr->scanout, DRM_FORMAT_XRGB8888); 
 | 
    if (ret) { 
 | 
      printf("failed to add fb ret=%d\n", ret); 
 | 
      continue; 
 | 
    } 
 | 
  
 | 
    fill_bo(cr->scanout, 0xFF, 0x0, 0x0, 0xFF); 
 | 
  
 | 
    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 = drmModeGetCrtc(dev->fd, cr->crtc->crtc_id); 
 | 
    /* 
 | 
     * Todo: 
 | 
     * I don't know why crtc mode is empty, just copy PREFERRED mode 
 | 
     * for it. 
 | 
     */ 
 | 
    memcpy(&cr->crtc->mode, m, sizeof(*m)); 
 | 
  } 
 | 
  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 
 |