diff --git a/util/display-kms.c b/util/display-kms.c
index b9cdc4e7af2dca3985adc14ad213f4eccbbe08ff..89c480e25e57e7a58464e408084f2b660895d4d4 100644 (file)
--- a/util/display-kms.c
+++ b/util/display-kms.c
drmModeResPtr resources;
drmModePlaneRes *plane_resources;
struct buffer *current;
+ bool no_master;
+ int mastership;
};
#define to_buffer_kms(x) container_of(x, struct buffer_kms, base)
uint32_t fb_id;
};
+static int global_fd = 0;
+static uint32_t used_planes = 0;
+static int ndisplays = 0;
+
static struct omap_bo *
alloc_bo(struct display *disp, uint32_t bpp, uint32_t width, uint32_t height,
uint32_t *bo_handle, uint32_t *pitch)
bo_flags |= OMAP_BO_TILED_32;
}
}
-
bo_flags |= OMAP_BO_WC;
if (bo_flags & OMAP_BO_TILED) {
- bo = omap_bo_new_tiled(disp->dev, width, height, bo_flags);
+ bo = omap_bo_new_tiled(disp->dev, ALIGN2(width,7), height, bo_flags);
} else {
bo = omap_bo_new(disp->dev, width * height * bpp / 8, bo_flags);
}
buf->nbo = 2;
buf->bo[0] = alloc_bo(disp, 8, buf->width, buf->height,
&bo_handles[0], &buf->pitches[0]);
+ buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
buf->bo[1] = alloc_bo(disp, 16, buf->width/2, buf->height/2,
&bo_handles[1], &buf->pitches[1]);
+ buf->fd[1] = omap_bo_dmabuf(buf->bo[1]);
} else {
buf->nbo = 1;
buf->bo[0] = alloc_bo(disp, 8, buf->width, buf->height * 3 / 2,
&bo_handles[0], &buf->pitches[0]);
+ buf->fd[0] = omap_bo_dmabuf(buf->bo[0]);
bo_handles[1] = bo_handles[0];
buf->pitches[1] = buf->pitches[0];
offsets[1] = buf->width * buf->height;
return NULL;
}
+void
+free_buffers(struct display *disp, uint32_t n)
+{
+ uint32_t i;
+ for (i = 0; i < n; i++) {
+ if (disp->buf[i]) {
+ close(disp->buf[i]->fd[0]);
+ omap_bo_del(disp->buf[i]->bo[0]);
+ if(disp->multiplanar){
+ close(disp->buf[i]->fd[1]);
+ omap_bo_del(disp->buf[i]->bo[1]);
+ }
+ }
+ }
+free(disp->buf);
+}
+
static struct buffer **
alloc_buffers(struct display *disp, uint32_t n,
uint32_t fourcc, uint32_t w, uint32_t h)
goto fail;
}
}
-
+ disp->buf=bufs;
return bufs;
fail:
return last_err;
}
+int
+get_overlay_plane(struct display *disp, struct buffer *buf)
+{
+ struct display_kms *disp_kms = to_display_kms(disp);
+ uint32_t i, ret;
+
+ for (i = 0; i < disp_kms->connectors_count; i++) {
+ struct connector *connector = &disp_kms->connector[i];
+ drmModeModeInfo *mode = connector->mode;
+
+ disp_kms->ovr[i] = drmModeGetPlane(disp->fd,
+ disp_kms->plane_resources->planes[1]);
+
+ ret = drmModeObjectSetProperty(disp->fd,
+ disp_kms->ovr[i]->plane_id, DRM_MODE_OBJECT_PLANE, 7, 3);
+ if (ret < 0) {
+ MSG("Could not set Z order for plane");
+ return ret;
+ }
+ }
+ return 0;
+}
+
static int
post_vid_buffer(struct display *disp, struct buffer *buf,
uint32_t x, uint32_t y, uint32_t w, uint32_t h)
/* ensure we have the overlay setup: */
for (i = 0; i < disp_kms->connectors_count; i++) {
struct connector *connector = &disp_kms->connector[i];
- uint32_t used_planes = 0;
drmModeModeInfo *mode = connector->mode;
if (! mode) {
if (! disp_kms->ovr[i]) {
for (j = 0; j < disp_kms->plane_resources->count_planes; j++) {
+ if (used_planes & (1 << j)) {
+ continue;
+ }
drmModePlane *ovr = drmModeGetPlane(disp->fd,
disp_kms->plane_resources->planes[j]);
- if ((ovr->possible_crtcs & (1 << connector->pipe)) &&
- !(used_planes & (1 << j))) {
+ if (ovr->possible_crtcs & (1 << connector->pipe)) {
disp_kms->ovr[i] = ovr;
used_planes |= (1 << j);
break;
continue;
}
- ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
+ if(buf->noScale) {
+ ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
+ connector->crtc, buf_kms->fb_id, 0,
+ /* Use x and y as co-ordinates of overlay */
+ x, y, buf->width, buf->height,
+ /* Consider source x and y is 0 always */
+ 0, 0, w << 16, h << 16);
+ } else {
+ ret = drmModeSetPlane(disp->fd, disp_kms->ovr[i]->plane_id,
connector->crtc, buf_kms->fb_id, 0,
/* make video fullscreen: */
0, 0, mode->hdisplay, mode->vdisplay,
/* source/cropping coordinates are given in Q16 */
x << 16, y << 16, w << 16, h << 16);
+ }
if (ret) {
ERROR("failed to enable plane %d: %s",
disp_kms->ovr[i]->plane_id, strerror(errno));
}
}
+ if (disp_kms->no_master && disp_kms->mastership) {
+ /* Drop mastership after the first buffer on each plane is
+ * displayed. This will lock these planes for us and allow
+ * others to consume remaining
+ */
+ disp_kms->mastership = 0;
+ drmDropMaster(disp->fd);
+ }
+
return ret;
}
static void
close_kms(struct display *disp)
{
+ omap_device_del(disp->dev);
+ disp->dev = NULL;
+ if (used_planes) {
+ used_planes >>= 1;
+ }
+ if (--ndisplays == 0) {
+ close(global_fd);
+ }
}
static void
}
/* Now get the encoder */
- for (i = 0; i < disp_kms->resources->count_encoders; i++) {
+ for (i = 0; i < connector->count_encoders; i++) {
c->encoder = drmModeGetEncoder(disp->fd,
- disp_kms->resources->encoders[i]);
+ connector->encoders[i]);
if (!c->encoder) {
ERROR("could not get encoder %i: %s",
disp_kms->resources->encoders[i], strerror(errno));
- drmModeFreeEncoder(c->encoder);
continue;
}
- if (c->encoder->encoder_id == connector->encoder_id)
- break;
+ /* Take the fisrt one, if none is assigned */
+ if (!connector->encoder_id)
+ {
+ connector->encoder_id = c->encoder->encoder_id;
+ }
+
+ if (c->encoder->encoder_id == connector->encoder_id) {
+ /* find the first valid CRTC if not assigned */
+ if (!c->encoder->crtc_id)
+ {
+ int k;
+ for (k = 0; k < disp_kms->resources->count_crtcs; ++k) {
+ /* check whether this CRTC works with the encoder */
+ if (!(c->encoder->possible_crtcs & (1 << k)))
+ continue;
+
+ c->encoder->crtc_id = disp_kms->resources->crtcs[k];
+ break;
+ }
+ if (!c->encoder->crtc_id)
+ {
+ ERROR("Encoder(%d): no CRTC found!\n", c->encoder->encoder_id);
+ drmModeFreeEncoder(c->encoder);
+ continue;
+ }
+ }
+ break;
+ }
drmModeFreeEncoder(c->encoder);
}
{
struct display_kms *disp_kms = NULL;
struct display *disp;
+ struct buffer **bufs;
int i;
disp_kms = calloc(1, sizeof(*disp_kms));
}
disp = &disp_kms->base;
- disp->fd = drmOpen("omapdrm", NULL);
- if (disp->fd < 0) {
- ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
- goto fail;
+ if (!global_fd) {
+ global_fd = drmOpen("omapdrm", NULL);
+ if (global_fd < 0) {
+ ERROR("could not open drm device: %s (%d)", strerror(errno), errno);
+ goto fail;
+ }
}
+ disp->fd = global_fd;
+ ndisplays++; /* increment the number of displays counter */
+
disp->dev = omap_device_new(disp->fd);
if (!disp->dev) {
ERROR("couldn't create device");
disp->post_buffer = post_buffer;
disp->post_vid_buffer = post_vid_buffer;
disp->close = close_kms;
-
+ disp->disp_free_buf = free_buffers ;
disp_kms->resources = drmModeGetResources(disp->fd);
if (!disp_kms->resources) {
ERROR("drmModeGetResources failed: %s", strerror(errno));
goto fail;
}
disp_kms->bo_flags |= OMAP_BO_SCANOUT;
+ } else if (!strcmp("-nm", argv[i])) {
+ disp_kms->no_master = true;
+ disp_kms->mastership = 1;
} else {
/* ignore */
continue;
MSG("using %d connectors, %dx%d display, multiplanar: %d",
disp_kms->connectors_count, disp->width, disp->height, disp->multiplanar);
+ bufs = disp_get_buffers(disp, 1);
+ disp_post_buffer(disp, bufs[0]);
+
return disp;
fail: