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 static gboolean
configure_mode_setting (GstKMSSink * self, guint32 fb_id) configure_mode_setting (GstKMSSink * self, GstVideoInfo * vinfo)
{ {
gboolean ret; gboolean ret;
drmModeConnector *conn; drmModeConnector *conn;
@ -329,17 +329,25 @@ configure_mode_setting (GstKMSSink * self, guint32 fb_id)
drmModeFB *fb; drmModeFB *fb;
gint i; gint i;
drmModeModeInfo *mode; drmModeModeInfo *mode;
guint32 fb_id;
GstKMSMemory *kmsmem;
ret = FALSE; ret = FALSE;
conn = NULL; conn = NULL;
fb = NULL; fb = NULL;
mode = NULL; mode = NULL;
kmsmem = NULL;
if (self->conn_id < 0) if (self->conn_id < 0)
goto bail; goto bail;
GST_INFO_OBJECT (self, "configuring mode setting"); 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); conn = drmModeGetConnector (self->fd, self->conn_id);
if (!conn) if (!conn)
goto connector_failed; goto connector_failed;
@ -363,6 +371,8 @@ configure_mode_setting (GstKMSSink * self, guint32 fb_id)
if (err) if (err)
goto modesetting_failed; goto modesetting_failed;
self->tmp_kmsmem = (GstMemory *) kmsmem;
ret = TRUE; ret = TRUE;
bail: bail:
@ -374,6 +384,12 @@ bail:
return ret; return ret;
/* ERRORS */ /* ERRORS */
bo_failed:
{
GST_ERROR_OBJECT (self,
"failed to allocate buffer object for mode setting");
goto bail;
}
connector_failed: connector_failed:
{ {
GST_ERROR_OBJECT (self, "Could not find a valid monitor connector"); 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); gst_object_unref (oldpool);
} }
if (self->modesetting_enabled && !configure_mode_setting (self, &vinfo))
goto modesetting_failed;
self->vinfo = vinfo; self->vinfo = vinfo;
GST_DEBUG_OBJECT (self, "negotiated caps = %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (self, "negotiated caps = %" GST_PTR_FORMAT, caps);
@ -846,6 +865,14 @@ no_pool:
/* Already warned in create_pool */ /* Already warned in create_pool */
return FALSE; return FALSE;
} }
modesetting_failed:
{
GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, (NULL),
("failed to configure video mode"));
return FALSE;
}
} }
static gboolean static gboolean
@ -1168,7 +1195,6 @@ error_map_src_buffer:
static GstFlowReturn static GstFlowReturn
gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) gst_kms_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
{ {
static gboolean setup = FALSE;
gint ret; gint ret;
GstBuffer *buffer; GstBuffer *buffer;
guint32 fb_id; 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); GST_TRACE_OBJECT (self, "displaying fb %d", fb_id);
if (self->modesetting_enabled) { 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; self->buffer_id = fb_id;
goto sync_frame; goto sync_frame;
} }
@ -1253,6 +1268,7 @@ sync_frame:
goto bail; goto bail;
gst_buffer_replace (&self->last_buffer, buffer); gst_buffer_replace (&self->last_buffer, buffer);
g_clear_pointer (&self->tmp_kmsmem, gst_memory_unref);
res = GST_FLOW_OK; res = GST_FLOW_OK;
@ -1266,11 +1282,6 @@ buffer_invalid:
GST_ERROR_OBJECT (self, "invalid buffer: it doesn't have a fb id"); GST_ERROR_OBJECT (self, "invalid buffer: it doesn't have a fb id");
goto bail; goto bail;
} }
modesetting_failed:
{
GST_ERROR_OBJECT (self, "failed to configure display mode");
goto bail;
}
set_plane_failed: set_plane_failed:
{ {
GST_DEBUG_OBJECT (self, "result = { %d, %d, %d, %d} / " GST_DEBUG_OBJECT (self, "result = { %d, %d, %d, %d} / "

View file

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