Let MetaMonitorManagerKms handle page flips
This commit completes the move of monitor logic to the monitor mangager. The renderer now only deals with framebuffers, asking the monitor manager to do the crtc flip tracking. https://bugzilla.gnome.org/show_bug.cgi?id=768976
This commit is contained in:
parent
12ef1a5e4b
commit
8bebb8126c
@ -32,6 +32,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#include <drm.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
@ -75,11 +76,28 @@ typedef struct {
|
|||||||
uint32_t rotation_map[ALL_TRANSFORMS];
|
uint32_t rotation_map[ALL_TRANSFORMS];
|
||||||
} MetaCRTCKms;
|
} MetaCRTCKms;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int pending;
|
||||||
|
|
||||||
|
MetaKmsFlipCallback callback;
|
||||||
|
void *user_data;
|
||||||
|
} MetaKmsFlipClosure;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GSource source;
|
||||||
|
|
||||||
|
gpointer fd_tag;
|
||||||
|
MetaMonitorManagerKms *manager_kms;
|
||||||
|
} MetaKmsSource;
|
||||||
|
|
||||||
struct _MetaMonitorManagerKms
|
struct _MetaMonitorManagerKms
|
||||||
{
|
{
|
||||||
MetaMonitorManager parent_instance;
|
MetaMonitorManager parent_instance;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
|
MetaKmsSource *source;
|
||||||
|
|
||||||
drmModeConnector **connectors;
|
drmModeConnector **connectors;
|
||||||
unsigned int n_connectors;
|
unsigned int n_connectors;
|
||||||
@ -87,6 +105,8 @@ struct _MetaMonitorManagerKms
|
|||||||
GUdevClient *udev;
|
GUdevClient *udev;
|
||||||
|
|
||||||
GSettings *desktop_settings;
|
GSettings *desktop_settings;
|
||||||
|
|
||||||
|
gboolean page_flips_not_supported;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaMonitorManagerKmsClass
|
struct _MetaMonitorManagerKmsClass
|
||||||
@ -954,8 +974,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
|||||||
MetaPowerSave mode)
|
MetaPowerSave mode)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||||
MetaBackend *backend;
|
|
||||||
MetaRenderer *renderer;
|
|
||||||
uint64_t state;
|
uint64_t state;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
@ -995,20 +1013,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
|||||||
meta_output->name, strerror (errno));
|
meta_output->name, strerror (errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backend = meta_get_backend ();
|
|
||||||
renderer = meta_backend_get_renderer (backend);
|
|
||||||
|
|
||||||
for (i = 0; i < manager->n_crtcs; i++)
|
|
||||||
meta_renderer_native_set_ignore_crtc (META_RENDERER_NATIVE (renderer),
|
|
||||||
manager->crtcs[i].crtc_id,
|
|
||||||
mode != META_POWER_SAVE_ON);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
crtc_free (CoglKmsCrtc *crtc)
|
|
||||||
{
|
|
||||||
g_slice_free (CoglKmsCrtc, crtc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1064,29 +1068,21 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
MetaBackend *backend;
|
MetaBackend *backend;
|
||||||
MetaRenderer *renderer;
|
MetaRenderer *renderer;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
GPtrArray *cogl_crtcs;
|
|
||||||
int screen_width, screen_height;
|
int screen_width, screen_height;
|
||||||
gboolean ok;
|
gboolean ok;
|
||||||
GError *error;
|
GError *error;
|
||||||
|
|
||||||
cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free);
|
|
||||||
screen_width = 0; screen_height = 0;
|
screen_width = 0; screen_height = 0;
|
||||||
for (i = 0; i < n_crtcs; i++)
|
for (i = 0; i < n_crtcs; i++)
|
||||||
{
|
{
|
||||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||||
MetaCRTC *crtc = crtc_info->crtc;
|
MetaCRTC *crtc = crtc_info->crtc;
|
||||||
MetaCRTCKms *crtc_kms = crtc->driver_private;
|
MetaCRTCKms *crtc_kms = crtc->driver_private;
|
||||||
CoglKmsCrtc *cogl_crtc;
|
|
||||||
|
|
||||||
crtc->is_dirty = TRUE;
|
crtc->is_dirty = TRUE;
|
||||||
|
|
||||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
|
||||||
g_ptr_array_add (cogl_crtcs, cogl_crtc);
|
|
||||||
|
|
||||||
if (crtc_info->mode == NULL)
|
if (crtc_info->mode == NULL)
|
||||||
{
|
{
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
|
|
||||||
crtc->rect.x = 0;
|
crtc->rect.x = 0;
|
||||||
crtc->rect.y = 0;
|
crtc->rect.y = 0;
|
||||||
crtc->rect.width = 0;
|
crtc->rect.width = 0;
|
||||||
@ -1096,24 +1092,15 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
MetaMonitorMode *mode;
|
MetaMonitorMode *mode;
|
||||||
uint32_t *connectors;
|
unsigned int j;
|
||||||
unsigned int j, n_connectors;
|
|
||||||
int width, height;
|
int width, height;
|
||||||
|
|
||||||
mode = crtc_info->mode;
|
mode = crtc_info->mode;
|
||||||
|
|
||||||
n_connectors = crtc_info->outputs->len;
|
for (j = 0; j < crtc_info->outputs->len; j++)
|
||||||
connectors = g_new (uint32_t, n_connectors);
|
|
||||||
|
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
cogl_crtc->connected = n_connectors > 0;
|
|
||||||
|
|
||||||
for (j = 0; j < n_connectors; j++)
|
|
||||||
{
|
{
|
||||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||||
|
|
||||||
connectors[j] = output->winsys_id;
|
|
||||||
|
|
||||||
output->is_dirty = TRUE;
|
output->is_dirty = TRUE;
|
||||||
output->crtc = crtc;
|
output->crtc = crtc;
|
||||||
}
|
}
|
||||||
@ -1153,7 +1140,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
for (i = 0; i < manager->n_crtcs; i++)
|
for (i = 0; i < manager->n_crtcs; i++)
|
||||||
{
|
{
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
MetaCRTC *crtc = &manager->crtcs[i];
|
||||||
CoglKmsCrtc *cogl_crtc;
|
|
||||||
|
|
||||||
crtc->logical_monitor = NULL;
|
crtc->logical_monitor = NULL;
|
||||||
|
|
||||||
@ -1163,11 +1149,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
|
|
||||||
g_ptr_array_add (cogl_crtcs, cogl_crtc);
|
|
||||||
|
|
||||||
cogl_crtc->id = crtc->crtc_id;
|
|
||||||
|
|
||||||
crtc->rect.x = 0;
|
crtc->rect.x = 0;
|
||||||
crtc->rect.y = 0;
|
crtc->rect.y = 0;
|
||||||
crtc->rect.width = 0;
|
crtc->rect.width = 0;
|
||||||
@ -1181,11 +1162,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
error = NULL;
|
error = NULL;
|
||||||
ok = meta_renderer_native_set_layout (META_RENDERER_NATIVE (renderer),
|
ok = meta_renderer_native_set_layout (META_RENDERER_NATIVE (renderer),
|
||||||
screen_width, screen_height,
|
screen_width, screen_height,
|
||||||
(CoglKmsCrtc**)cogl_crtcs->pdata,
|
|
||||||
cogl_crtcs->len,
|
|
||||||
&error);
|
&error);
|
||||||
g_ptr_array_unref (cogl_crtcs);
|
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
meta_warning ("Applying display configuration failed: %s\n", error->message);
|
meta_warning ("Applying display configuration failed: %s\n", error->message);
|
||||||
@ -1279,12 +1256,39 @@ on_uevent (GUdevClient *client,
|
|||||||
meta_monitor_manager_on_hotplug (manager);
|
meta_monitor_manager_on_hotplug (manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
kms_event_check (GSource *source)
|
||||||
|
{
|
||||||
|
MetaKmsSource *kms_source = (MetaKmsSource *) source;
|
||||||
|
|
||||||
|
return g_source_query_unix_fd (source, kms_source->fd_tag) & G_IO_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
kms_event_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaKmsSource *kms_source = (MetaKmsSource *) source;
|
||||||
|
|
||||||
|
meta_monitor_manager_kms_wait_for_flip (kms_source->manager_kms);
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs kms_event_funcs = {
|
||||||
|
NULL,
|
||||||
|
kms_event_check,
|
||||||
|
kms_event_dispatch
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
manager_kms->fd = meta_renderer_native_get_kms_fd (renderer_native);
|
manager_kms->fd = meta_renderer_native_get_kms_fd (renderer_native);
|
||||||
|
|
||||||
@ -1295,6 +1299,14 @@ meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
|||||||
g_signal_connect (manager_kms->udev, "uevent",
|
g_signal_connect (manager_kms->udev, "uevent",
|
||||||
G_CALLBACK (on_uevent), manager_kms);
|
G_CALLBACK (on_uevent), manager_kms);
|
||||||
|
|
||||||
|
source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource));
|
||||||
|
manager_kms->source = (MetaKmsSource *) source;
|
||||||
|
manager_kms->source->fd_tag = g_source_add_unix_fd (source,
|
||||||
|
manager_kms->fd,
|
||||||
|
G_IO_IN | G_IO_ERR);
|
||||||
|
manager_kms->source->manager_kms = manager_kms;
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
manager_kms->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
|
manager_kms->desktop_settings = g_settings_new ("org.gnome.desktop.interface");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1364,6 +1376,104 @@ meta_monitor_manager_kms_apply_crtc_modes (MetaMonitorManagerKms *manager_kms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_monitor_manager_kms_flip_all_crtcs (MetaMonitorManagerKms *manager_kms,
|
||||||
|
uint32_t fb_id,
|
||||||
|
MetaKmsFlipCallback flip_callback,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
|
MetaKmsFlipClosure *flip_closure = NULL;
|
||||||
|
unsigned int i;
|
||||||
|
gboolean fb_in_use = FALSE;
|
||||||
|
|
||||||
|
if (manager->power_save_mode != META_POWER_SAVE_ON)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < manager->n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTC *crtc = &manager->crtcs[i];
|
||||||
|
uint32_t *connectors;
|
||||||
|
unsigned int n_connectors;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
get_crtc_connectors (manager, crtc, &connectors, &n_connectors);
|
||||||
|
|
||||||
|
if (n_connectors == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fb_in_use = TRUE;
|
||||||
|
|
||||||
|
if (manager_kms->page_flips_not_supported)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!flip_closure)
|
||||||
|
{
|
||||||
|
flip_closure = g_new0 (MetaKmsFlipClosure, 1);
|
||||||
|
*flip_closure = (MetaKmsFlipClosure) {
|
||||||
|
.pending = 0,
|
||||||
|
.callback = flip_callback,
|
||||||
|
.user_data = user_data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = drmModePageFlip (manager_kms->fd,
|
||||||
|
crtc->crtc_id,
|
||||||
|
fb_id,
|
||||||
|
DRM_MODE_PAGE_FLIP_EVENT,
|
||||||
|
flip_closure);
|
||||||
|
if (ret != 0 && ret != -EACCES)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to flip: %s", strerror (-ret));
|
||||||
|
manager_kms->page_flips_not_supported = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
flip_closure->pending++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (manager_kms->page_flips_not_supported && fb_in_use)
|
||||||
|
{
|
||||||
|
/* If the driver doesn't support page flipping, just set the mode directly
|
||||||
|
* with the new framebuffer.
|
||||||
|
*/
|
||||||
|
meta_monitor_manager_kms_apply_crtc_modes (manager_kms, fb_id);
|
||||||
|
flip_callback (user_data);
|
||||||
|
g_free (flip_closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fb_in_use;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_flip_handler (int fd,
|
||||||
|
unsigned int frame,
|
||||||
|
unsigned int sec,
|
||||||
|
unsigned int usec,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
MetaKmsFlipClosure *flip_closure = data;
|
||||||
|
|
||||||
|
flip_closure->pending--;
|
||||||
|
if (flip_closure->pending == 0)
|
||||||
|
flip_closure->callback (flip_closure->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms)
|
||||||
|
{
|
||||||
|
drmEventContext evctx;
|
||||||
|
|
||||||
|
if (manager_kms->page_flips_not_supported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset (&evctx, 0, sizeof evctx);
|
||||||
|
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
||||||
|
evctx.page_flip_handler = page_flip_handler;
|
||||||
|
drmHandleEvent (manager_kms->fd, &evctx);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_kms_dispose (GObject *object)
|
meta_monitor_manager_kms_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@ -1381,6 +1491,7 @@ meta_monitor_manager_kms_finalize (GObject *object)
|
|||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
|
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
|
||||||
|
|
||||||
free_resources (manager_kms);
|
free_resources (manager_kms);
|
||||||
|
g_source_destroy ((GSource *) manager_kms->source);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,16 @@ typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
|
|||||||
|
|
||||||
GType meta_monitor_manager_kms_get_type (void);
|
GType meta_monitor_manager_kms_get_type (void);
|
||||||
|
|
||||||
|
typedef void (*MetaKmsFlipCallback) (void *user_data);
|
||||||
|
|
||||||
void meta_monitor_manager_kms_apply_crtc_modes (MetaMonitorManagerKms *manager_kms,
|
void meta_monitor_manager_kms_apply_crtc_modes (MetaMonitorManagerKms *manager_kms,
|
||||||
uint32_t fb_id);
|
uint32_t fb_id);
|
||||||
|
|
||||||
|
gboolean meta_monitor_manager_kms_flip_all_crtcs (MetaMonitorManagerKms *manager_kms,
|
||||||
|
uint32_t fb_id,
|
||||||
|
MetaKmsFlipCallback flip_callback,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
|
void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms);
|
||||||
|
|
||||||
#endif /* META_MONITOR_MANAGER_KMS_H */
|
#endif /* META_MONITOR_MANAGER_KMS_H */
|
||||||
|
@ -67,9 +67,6 @@ struct _MetaRendererNative
|
|||||||
int kms_fd;
|
int kms_fd;
|
||||||
struct gbm_device *gbm;
|
struct gbm_device *gbm;
|
||||||
CoglClosure *swap_notify_idle;
|
CoglClosure *swap_notify_idle;
|
||||||
gboolean page_flips_not_supported;
|
|
||||||
|
|
||||||
GList *crtcs;
|
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
gboolean pending_set_crtc;
|
gboolean pending_set_crtc;
|
||||||
@ -90,12 +87,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaRendererNative,
|
|||||||
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
||||||
static const CoglWinsysVtable *parent_vtable;
|
static const CoglWinsysVtable *parent_vtable;
|
||||||
|
|
||||||
typedef struct _CoglFlipKMS
|
|
||||||
{
|
|
||||||
CoglOnscreen *onscreen;
|
|
||||||
int pending;
|
|
||||||
} CoglFlipKMS;
|
|
||||||
|
|
||||||
typedef struct _CoglOnscreenKMS
|
typedef struct _CoglOnscreenKMS
|
||||||
{
|
{
|
||||||
struct gbm_surface *surface;
|
struct gbm_surface *surface;
|
||||||
@ -211,73 +202,6 @@ queue_swap_notify_for_onscreen (CoglOnscreen *onscreen)
|
|||||||
kms_onscreen->pending_swap_notify = TRUE;
|
kms_onscreen->pending_swap_notify = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
process_flip (CoglFlipKMS *flip)
|
|
||||||
{
|
|
||||||
/* We're only ready to dispatch a swap notification once all outputs
|
|
||||||
* have flipped... */
|
|
||||||
flip->pending--;
|
|
||||||
if (flip->pending == 0)
|
|
||||||
{
|
|
||||||
CoglOnscreen *onscreen = flip->onscreen;
|
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
|
||||||
|
|
||||||
queue_swap_notify_for_onscreen (onscreen);
|
|
||||||
|
|
||||||
free_current_bo (onscreen);
|
|
||||||
|
|
||||||
kms_onscreen->current_fb_id = kms_onscreen->next_fb_id;
|
|
||||||
kms_onscreen->next_fb_id = 0;
|
|
||||||
|
|
||||||
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
|
||||||
kms_onscreen->next_bo = NULL;
|
|
||||||
|
|
||||||
cogl_object_unref (flip->onscreen);
|
|
||||||
|
|
||||||
g_slice_free (CoglFlipKMS, flip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
page_flip_handler (int fd,
|
|
||||||
unsigned int frame,
|
|
||||||
unsigned int sec,
|
|
||||||
unsigned int usec,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
CoglFlipKMS *flip = data;
|
|
||||||
|
|
||||||
process_flip (flip);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_drm_event (MetaRendererNative *renderer_native)
|
|
||||||
{
|
|
||||||
drmEventContext evctx;
|
|
||||||
|
|
||||||
if (renderer_native->page_flips_not_supported)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memset (&evctx, 0, sizeof evctx);
|
|
||||||
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
|
||||||
evctx.page_flip_handler = page_flip_handler;
|
|
||||||
drmHandleEvent (renderer_native->kms_fd, &evctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
dispatch_kms_events (void *user_data, int revents)
|
|
||||||
{
|
|
||||||
CoglRenderer *renderer = user_data;
|
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
||||||
MetaRendererNative *renderer_native = egl_renderer->platform;
|
|
||||||
|
|
||||||
if (!revents)
|
|
||||||
return;
|
|
||||||
|
|
||||||
handle_drm_event (renderer_native);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_winsys_renderer_connect (CoglRenderer *cogl_renderer,
|
_cogl_winsys_renderer_connect (CoglRenderer *cogl_renderer,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
@ -315,13 +239,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *cogl_renderer,
|
|||||||
if (!_cogl_winsys_egl_renderer_connect_common (cogl_renderer, error))
|
if (!_cogl_winsys_egl_renderer_connect_common (cogl_renderer, error))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
_cogl_poll_renderer_add_fd (cogl_renderer,
|
|
||||||
renderer_native->kms_fd,
|
|
||||||
COGL_POLL_FD_EVENT_IN,
|
|
||||||
NULL, /* no prepare callback */
|
|
||||||
dispatch_kms_events,
|
|
||||||
cogl_renderer);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -342,63 +259,6 @@ setup_crtc_modes (CoglDisplay *display, int fb_id)
|
|||||||
meta_monitor_manager_kms_apply_crtc_modes (monitor_manager_kms, fb_id);
|
meta_monitor_manager_kms_apply_crtc_modes (monitor_manager_kms, fb_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
flip_all_crtcs (CoglDisplay *display, CoglFlipKMS *flip, int fb_id)
|
|
||||||
{
|
|
||||||
CoglDisplayEGL *egl_display = display->winsys;
|
|
||||||
MetaRendererNative *renderer_native = egl_display->platform;
|
|
||||||
GList *l;
|
|
||||||
gboolean needs_flip = FALSE;
|
|
||||||
|
|
||||||
for (l = renderer_native->crtcs; l; l = l->next)
|
|
||||||
{
|
|
||||||
CoglKmsCrtc *crtc = l->data;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!crtc->connected || crtc->ignore)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
needs_flip = TRUE;
|
|
||||||
|
|
||||||
if (!renderer_native->page_flips_not_supported)
|
|
||||||
{
|
|
||||||
ret = drmModePageFlip (renderer_native->kms_fd,
|
|
||||||
crtc->id, fb_id,
|
|
||||||
DRM_MODE_PAGE_FLIP_EVENT, flip);
|
|
||||||
if (ret != 0 && ret != -EACCES)
|
|
||||||
{
|
|
||||||
g_warning ("Failed to flip: %m");
|
|
||||||
renderer_native->page_flips_not_supported = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0)
|
|
||||||
flip->pending++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (renderer_native->page_flips_not_supported && needs_flip)
|
|
||||||
flip->pending = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
crtc_free (CoglKmsCrtc *crtc)
|
|
||||||
{
|
|
||||||
g_slice_free (CoglKmsCrtc, crtc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglKmsCrtc *
|
|
||||||
crtc_copy (CoglKmsCrtc *from)
|
|
||||||
{
|
|
||||||
CoglKmsCrtc *new;
|
|
||||||
|
|
||||||
new = g_slice_new (CoglKmsCrtc);
|
|
||||||
|
|
||||||
*new = *from;
|
|
||||||
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
_cogl_winsys_egl_display_setup (CoglDisplay *display,
|
_cogl_winsys_egl_display_setup (CoglDisplay *display,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
@ -490,11 +350,36 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flip_callback (void *user_data)
|
||||||
|
{
|
||||||
|
CoglOnscreen *onscreen = user_data;
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
|
|
||||||
|
queue_swap_notify_for_onscreen (onscreen);
|
||||||
|
|
||||||
|
free_current_bo (onscreen);
|
||||||
|
|
||||||
|
kms_onscreen->current_fb_id = kms_onscreen->next_fb_id;
|
||||||
|
kms_onscreen->next_fb_id = 0;
|
||||||
|
|
||||||
|
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
||||||
|
kms_onscreen->next_bo = NULL;
|
||||||
|
|
||||||
|
cogl_object_unref (onscreen);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||||
const int *rectangles,
|
const int *rectangles,
|
||||||
int n_rectangles)
|
int n_rectangles)
|
||||||
{
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
MetaMonitorManagerKms *monitor_manager_kms =
|
||||||
|
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||||
CoglRenderer *renderer = context->display->renderer;
|
CoglRenderer *renderer = context->display->renderer;
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
@ -502,11 +387,12 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||||
uint32_t handle, stride;
|
uint32_t handle, stride;
|
||||||
CoglFlipKMS *flip;
|
gboolean fb_in_use;
|
||||||
|
uint32_t next_fb_id;
|
||||||
|
|
||||||
/* If we already have a pending swap then block until it completes */
|
/* If we already have a pending swap then block until it completes */
|
||||||
while (kms_onscreen->next_fb_id != 0)
|
while (kms_onscreen->next_fb_id != 0)
|
||||||
handle_drm_event (renderer_native);
|
meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms);
|
||||||
|
|
||||||
if (kms_onscreen->pending_egl_surface)
|
if (kms_onscreen->pending_egl_surface)
|
||||||
{
|
{
|
||||||
@ -564,34 +450,27 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
renderer_native->pending_set_crtc = FALSE;
|
renderer_native->pending_set_crtc = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
flip = g_slice_new0 (CoglFlipKMS);
|
next_fb_id = kms_onscreen->next_fb_id;
|
||||||
flip->onscreen = onscreen;
|
|
||||||
|
|
||||||
flip_all_crtcs (context->display, flip, kms_onscreen->next_fb_id);
|
/* Reference will either be released in flip_callback, or if the fb
|
||||||
|
* wasn't used, indicated by the return value below.
|
||||||
|
*/
|
||||||
|
cogl_object_ref (onscreen);
|
||||||
|
fb_in_use = meta_monitor_manager_kms_flip_all_crtcs (monitor_manager_kms,
|
||||||
|
next_fb_id,
|
||||||
|
flip_callback, onscreen);
|
||||||
|
|
||||||
if (flip->pending == 0)
|
if (!fb_in_use)
|
||||||
{
|
{
|
||||||
drmModeRmFB (renderer_native->kms_fd, kms_onscreen->next_fb_id);
|
drmModeRmFB (renderer_native->kms_fd, kms_onscreen->next_fb_id);
|
||||||
gbm_surface_release_buffer (kms_onscreen->surface,
|
gbm_surface_release_buffer (kms_onscreen->surface,
|
||||||
kms_onscreen->next_bo);
|
kms_onscreen->next_bo);
|
||||||
kms_onscreen->next_bo = NULL;
|
kms_onscreen->next_bo = NULL;
|
||||||
kms_onscreen->next_fb_id = 0;
|
kms_onscreen->next_fb_id = 0;
|
||||||
g_slice_free (CoglFlipKMS, flip);
|
|
||||||
flip = NULL;
|
|
||||||
|
|
||||||
queue_swap_notify_for_onscreen (onscreen);
|
queue_swap_notify_for_onscreen (onscreen);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Ensure the onscreen remains valid while it has any pending flips... */
|
|
||||||
cogl_object_ref (flip->onscreen);
|
|
||||||
|
|
||||||
/* Process flip right away if we can't wait for vblank */
|
g_object_unref (onscreen);
|
||||||
if (renderer_native->page_flips_not_supported)
|
|
||||||
{
|
|
||||||
setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
|
|
||||||
process_flip (flip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,8 +643,6 @@ gboolean
|
|||||||
meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglKmsCrtc **crtcs,
|
|
||||||
int n_crtcs,
|
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
@ -774,8 +651,6 @@ meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
|||||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||||
CoglRenderer *renderer = cogl_display->renderer;
|
CoglRenderer *renderer = cogl_display->renderer;
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
GList *crtc_list;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((width != renderer_native->width ||
|
if ((width != renderer_native->width ||
|
||||||
height != renderer_native->height) &&
|
height != renderer_native->height) &&
|
||||||
@ -844,39 +719,11 @@ meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
|||||||
renderer_native->width = width;
|
renderer_native->width = width;
|
||||||
renderer_native->height = height;
|
renderer_native->height = height;
|
||||||
|
|
||||||
g_list_free_full (renderer_native->crtcs, (GDestroyNotify) crtc_free);
|
|
||||||
|
|
||||||
crtc_list = NULL;
|
|
||||||
for (i = 0; i < n_crtcs; i++)
|
|
||||||
{
|
|
||||||
crtc_list = g_list_prepend (crtc_list, crtc_copy (crtcs[i]));
|
|
||||||
}
|
|
||||||
crtc_list = g_list_reverse (crtc_list);
|
|
||||||
renderer_native->crtcs = crtc_list;
|
|
||||||
|
|
||||||
renderer_native->pending_set_crtc = TRUE;
|
renderer_native->pending_set_crtc = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
|
||||||
uint32_t id,
|
|
||||||
gboolean ignore)
|
|
||||||
{
|
|
||||||
GList *l;
|
|
||||||
|
|
||||||
for (l = renderer_native->crtcs; l; l = l->next)
|
|
||||||
{
|
|
||||||
CoglKmsCrtc *crtc = l->data;
|
|
||||||
if (crtc->id == id)
|
|
||||||
{
|
|
||||||
crtc->ignore = ignore;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const CoglWinsysVtable *
|
static const CoglWinsysVtable *
|
||||||
get_native_cogl_winsys_vtable (void)
|
get_native_cogl_winsys_vtable (void)
|
||||||
{
|
{
|
||||||
@ -966,8 +813,6 @@ meta_renderer_native_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object);
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (object);
|
||||||
|
|
||||||
g_list_free_full (renderer_native->crtcs, (GDestroyNotify) crtc_free);
|
|
||||||
|
|
||||||
g_clear_pointer (&renderer_native->dummy_gbm_surface, gbm_surface_destroy);
|
g_clear_pointer (&renderer_native->dummy_gbm_surface, gbm_surface_destroy);
|
||||||
g_clear_pointer (&renderer_native->gbm, gbm_device_destroy);
|
g_clear_pointer (&renderer_native->gbm, gbm_device_destroy);
|
||||||
|
|
||||||
|
@ -30,14 +30,6 @@
|
|||||||
|
|
||||||
#include "backends/meta-renderer.h"
|
#include "backends/meta-renderer.h"
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t id;
|
|
||||||
|
|
||||||
gboolean connected;
|
|
||||||
|
|
||||||
CoglBool ignore;
|
|
||||||
} CoglKmsCrtc;
|
|
||||||
|
|
||||||
#define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ())
|
#define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native,
|
G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native,
|
||||||
META, RENDERER_NATIVE,
|
META, RENDERER_NATIVE,
|
||||||
@ -55,8 +47,6 @@ void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native
|
|||||||
gboolean meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
gboolean meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
CoglKmsCrtc **crtcs,
|
|
||||||
int n_crtcs,
|
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
||||||
|
Loading…
Reference in New Issue
Block a user