kmssink: configure display mode during set_caps

Configure the display mode when setting the negotiated caps instead of
during showing the first frame.

A framebuffer is required to set the mode. Allocate a buffer object
according to the negotiated caps and use it to set the mode. This buffer
object cannot be freed until another page flip happened on the crtc
(i.e., until the first frame is rendered).

https://bugzilla.gnome.org/show_bug.cgi?id=773473

Signed-off-by: Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
This commit is contained in:
Michael Tretter 2016-10-20 12:37:48 +02:00 committed by Víctor Manuel Jáquez Leal
parent dff77fd15f
commit 649364b923
2 changed files with 30 additions and 18 deletions

View file

@ -321,7 +321,7 @@ get_drm_caps (GstKMSSink * self)
}
static gboolean
configure_mode_setting (GstKMSSink * self, guint32 fb_id)
configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo)
{
gboolean ret;
drmModeConnector *conn;
@ -329,17 +329,25 @@ configure_mode_setting (GstKMSSink * self, guint32 fb_id)
drmModeFB *fb;
gint i;
drmModeModeInfo *mode;
guint32 fb_id;
GstKMSMemory *kmsmem;
ret = FALSE;
conn = NULL;
fb = NULL;
mode = NULL;
kmsmem = NULL;
if (self->conn_id < 0)
goto bail;
GST_INFO_OBJECT (self, "configuring mode setting");
kmsmem = (GstKMSMemory *) gst_kms_allocator_bo_alloc (self->allocator, vinfo);
if (!kmsmem)
goto bo_failed;
fb_id = kmsmem->fb_id;
conn = drmModeGetConnector (self->fd, self->conn_id);
if (!conn)
goto connector_failed;
@ -363,6 +371,8 @@ configure_mode_setting (GstKMSSink * self, guint32 fb_id)
if (err)
goto modesetting_failed;
self->tmp_kmsmem = (GstMemory *) kmsmem;
ret = TRUE;
bail:
@ -374,6 +384,12 @@ bail:
return ret;
/* ERRORS */
bo_failed:
{
GST_ERROR_OBJECT (self,
"failed to allocate buffer object for mode setting");
goto bail;
}
connector_failed:
{
GST_ERROR_OBJECT (self, "Could not find a valid monitor connector");
@ -815,6 +831,9 @@ gst_kms_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
gst_object_unref (oldpool);
}
if (self->modesetting_enabled && !configure_mode_setting (self, &vinfo))
goto modesetting_failed;
self->vinfo = vinfo;
GST_DEBUG_OBJECT (self, "negotiated caps = %" GST_PTR_FORMAT, caps);
@ -846,6 +865,14 @@ no_pool:
/* Already warned in create_pool */
return FALSE;
}
modesetting_failed:
{
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, (NULL),
("failed to configure video mode"));
return FALSE;
}
}
static gboolean
@ -1168,7 +1195,6 @@ error_map_src_buffer:
static GstFlowReturn
gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
{
static gboolean setup = FALSE;
gint ret;
GstBuffer *buffer;
guint32 fb_id;
@ -1193,17 +1219,6 @@ gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
GST_TRACE_OBJECT (self, "displaying fb %d", fb_id);
if (self->modesetting_enabled) {
/* Use the current buffer object for configuring the mode, if the mode is
* not configured. Preferably the display mode should be set when
* configuring the pipeline (during set_caps), but we do not have a buffer
* object at that time. */
if (!setup) {
ret = configure_mode_setting (self, fb_id);
if (!ret)
goto modesetting_failed;
setup = TRUE;
}
self->buffer_id = fb_id;
goto sync_frame;
}
@ -1253,6 +1268,7 @@ sync_frame:
goto bail;
gst_buffer_replace (&self->last_buffer, buffer);
g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
res = GST_FLOW_OK;
@ -1266,11 +1282,6 @@ buffer_invalid:
GST_ERROR_OBJECT (self, "invalid buffer: it doesn't have a fb id");
goto bail;
}
modesetting_failed:
{
GST_ERROR_OBJECT (self, "failed to configure display mode");
goto bail;
}
set_plane_failed:
{
GST_DEBUG_OBJECT (self, "result = { %d, %d, %d, %d} / "

View file

@ -69,6 +69,7 @@ struct _GstKMSSink {
GstBufferPool *pool;
GstAllocator *allocator;
GstBuffer *last_buffer;
GstMemory *tmp_kmsmem;
gchar *devname;