Move cogl KMS winsys into the native backend
Move the KMS interaction from cogl into mutter, where most of the other KMS interaction already takes place. This also removes dead code which were only excercised when non-mutter callers used the cogl KMS backend. The cogl KMS API was updated to pass via MetaRendererNative instead of via the different cogl objects. https://bugzilla.gnome.org/show_bug.cgi?id=768976
This commit is contained in:
@ -34,7 +34,9 @@
|
||||
#include <meta/util.h>
|
||||
#include <meta/meta-backend.h>
|
||||
|
||||
#include "meta-monitor-manager-private.h"
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-monitor-manager-private.h"
|
||||
#include "backends/native/meta-renderer-native.h"
|
||||
#include "meta/boxes.h"
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||
@ -657,7 +659,6 @@ static void
|
||||
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaMonitorManager *monitors;
|
||||
|
||||
monitors = meta_monitor_manager_get ();
|
||||
@ -667,9 +668,12 @@ meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||
#if defined(CLUTTER_WINDOWING_EGL)
|
||||
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
|
||||
{
|
||||
CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_context_get_display (ctx));
|
||||
priv->drm_fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
priv->gbm = cogl_kms_renderer_get_gbm (cogl_renderer);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
|
||||
priv->drm_fd = meta_renderer_native_get_kms_fd (renderer_native);
|
||||
priv->gbm = meta_renderer_native_get_gbm (renderer_native);
|
||||
|
||||
uint64_t width, height;
|
||||
if (drmGetCap (priv->drm_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
#include "meta-idle-monitor-native.h"
|
||||
#include "meta-renderer-native.h"
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevDevice, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref)
|
||||
@ -108,21 +109,20 @@ get_seat_proxy (GCancellable *cancellable,
|
||||
static void
|
||||
session_unpause (void)
|
||||
{
|
||||
ClutterBackend *clutter_backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
MetaBackend *backend;
|
||||
MetaRenderer *renderer;
|
||||
|
||||
clutter_backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
cogl_kms_display_queue_modes_reset (cogl_display);
|
||||
backend = meta_get_backend ();
|
||||
renderer = meta_backend_get_renderer (backend);
|
||||
meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer));
|
||||
|
||||
clutter_evdev_reclaim_devices ();
|
||||
clutter_egl_thaw_master_clock ();
|
||||
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorRendererNative *cursor_renderer_native =
|
||||
META_CURSOR_RENDERER_NATIVE (meta_backend_get_cursor_renderer (backend));
|
||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||
|
||||
/* When we mode-switch back, we need to immediately queue a redraw
|
||||
@ -130,7 +130,7 @@ session_unpause (void)
|
||||
* update. */
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
meta_cursor_renderer_native_force_update (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
meta_cursor_renderer_native_force_update (cursor_renderer_native);
|
||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@
|
||||
|
||||
#include "meta-monitor-manager-kms.h"
|
||||
#include "meta-monitor-config.h"
|
||||
#include "meta-backend-private.h"
|
||||
#include "meta-renderer-native.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -952,9 +954,8 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
MetaPowerSave mode)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
MetaBackend *backend;
|
||||
MetaRenderer *renderer;
|
||||
uint64_t state;
|
||||
unsigned i;
|
||||
|
||||
@ -995,13 +996,13 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
|
||||
}
|
||||
}
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
backend = meta_get_backend ();
|
||||
renderer = meta_backend_get_renderer (backend);
|
||||
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
cogl_kms_display_set_ignore_crtc (cogl_display, manager->crtcs[i].crtc_id,
|
||||
mode != META_POWER_SAVE_ON);
|
||||
meta_renderer_native_set_ignore_crtc (META_RENDERER_NATIVE (renderer),
|
||||
manager->crtcs[i].crtc_id,
|
||||
mode != META_POWER_SAVE_ON);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1061,9 +1062,8 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
MetaBackend *backend;
|
||||
MetaRenderer *renderer;
|
||||
unsigned i;
|
||||
GPtrArray *cogl_crtcs;
|
||||
int screen_width, screen_height;
|
||||
@ -1191,13 +1191,15 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
crtc->current_mode = NULL;
|
||||
}
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
backend = meta_get_backend ();
|
||||
renderer = meta_backend_get_renderer (backend);
|
||||
|
||||
error = NULL;
|
||||
ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height,
|
||||
(CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error);
|
||||
ok = meta_renderer_native_set_layout (META_RENDERER_NATIVE (renderer),
|
||||
screen_width, screen_height,
|
||||
(CoglKmsCrtc**)cogl_crtcs->pdata,
|
||||
cogl_crtcs->len,
|
||||
&error);
|
||||
g_ptr_array_unref (cogl_crtcs);
|
||||
|
||||
if (!ok)
|
||||
@ -1296,17 +1298,11 @@ on_uevent (GUdevClient *client,
|
||||
static void
|
||||
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
CoglRenderer *cogl_renderer;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
cogl_renderer = cogl_display_get_renderer (cogl_display);
|
||||
|
||||
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
|
||||
manager_kms->fd = meta_renderer_native_get_kms_fd (renderer_native);
|
||||
|
||||
drmSetClientCap (manager_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Intel Corporation.
|
||||
* Copyright (C) 2016 Red Hat
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
@ -23,14 +24,28 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
* Authors:
|
||||
* Rob Bradford <rob@linux.intel.com> (from cogl-winsys-egl-kms.c)
|
||||
* Kristian Høgsberg (from eglkms.c)
|
||||
* Benjamin Franzke (from eglkms.c)
|
||||
* Robert Bragg <robert@linux.intel.com> (from cogl-winsys-egl-kms.c)
|
||||
* Neil Roberts <neil@linux.intel.com> (from cogl-winsys-egl-kms.c)
|
||||
* Jonas Ådahl <jadahl@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <glib-object.h>
|
||||
#include <gbm.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/native/meta-renderer-native.h"
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
@ -52,16 +67,932 @@ struct _MetaRendererNative
|
||||
|
||||
G_DEFINE_TYPE (MetaRendererNative, meta_renderer_native, META_TYPE_RENDERER)
|
||||
|
||||
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
||||
static const CoglWinsysVtable *parent_vtable;
|
||||
|
||||
typedef struct _CoglRendererKMS
|
||||
{
|
||||
int fd;
|
||||
struct gbm_device *gbm;
|
||||
CoglClosure *swap_notify_idle;
|
||||
CoglBool page_flips_not_supported;
|
||||
} CoglRendererKMS;
|
||||
|
||||
typedef struct _CoglDisplayKMS
|
||||
{
|
||||
GList *crtcs;
|
||||
|
||||
int width, height;
|
||||
CoglBool pending_set_crtc;
|
||||
struct gbm_surface *dummy_gbm_surface;
|
||||
|
||||
CoglOnscreen *onscreen;
|
||||
} CoglDisplayKMS;
|
||||
|
||||
typedef struct _CoglFlipKMS
|
||||
{
|
||||
CoglOnscreen *onscreen;
|
||||
int pending;
|
||||
} CoglFlipKMS;
|
||||
|
||||
typedef struct _CoglOnscreenKMS
|
||||
{
|
||||
struct gbm_surface *surface;
|
||||
uint32_t current_fb_id;
|
||||
uint32_t next_fb_id;
|
||||
struct gbm_bo *current_bo;
|
||||
struct gbm_bo *next_bo;
|
||||
CoglBool pending_swap_notify;
|
||||
|
||||
EGLSurface *pending_egl_surface;
|
||||
struct gbm_surface *pending_surface;
|
||||
} CoglOnscreenKMS;
|
||||
|
||||
static void
|
||||
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
|
||||
{
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
if (egl_renderer->edpy != EGL_NO_DISPLAY)
|
||||
eglTerminate (egl_renderer->edpy);
|
||||
|
||||
if (kms_renderer->gbm != NULL)
|
||||
gbm_device_destroy (kms_renderer->gbm);
|
||||
|
||||
g_slice_free (CoglRendererKMS, kms_renderer);
|
||||
g_slice_free (CoglRendererEGL, egl_renderer);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_pending_swap_notify_cb (void *data,
|
||||
void *user_data)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = data;
|
||||
|
||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||
{
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||
|
||||
if (kms_onscreen->pending_swap_notify)
|
||||
{
|
||||
CoglFrameInfo *info = g_queue_pop_head (&onscreen->pending_frame_infos);
|
||||
|
||||
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
||||
_cogl_onscreen_notify_complete (onscreen, info);
|
||||
kms_onscreen->pending_swap_notify = FALSE;
|
||||
|
||||
cogl_object_unref (info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flush_pending_swap_notify_idle (void *user_data)
|
||||
{
|
||||
CoglContext *context = user_data;
|
||||
CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
/* This needs to be disconnected before invoking the callbacks in
|
||||
* case the callbacks cause it to be queued again */
|
||||
_cogl_closure_disconnect (kms_renderer->swap_notify_idle);
|
||||
kms_renderer->swap_notify_idle = NULL;
|
||||
|
||||
g_list_foreach (context->framebuffers,
|
||||
flush_pending_swap_notify_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
free_current_bo (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
if (kms_onscreen->current_fb_id)
|
||||
{
|
||||
drmModeRmFB (kms_renderer->fd,
|
||||
kms_onscreen->current_fb_id);
|
||||
kms_onscreen->current_fb_id = 0;
|
||||
}
|
||||
if (kms_onscreen->current_bo)
|
||||
{
|
||||
gbm_surface_release_buffer (kms_onscreen->surface,
|
||||
kms_onscreen->current_bo);
|
||||
kms_onscreen->current_bo = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queue_swap_notify_for_onscreen (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
/* We only want to notify that the swap is complete when the
|
||||
* application calls cogl_context_dispatch so instead of
|
||||
* immediately notifying we queue an idle callback */
|
||||
if (!kms_renderer->swap_notify_idle)
|
||||
{
|
||||
kms_renderer->swap_notify_idle =
|
||||
_cogl_poll_renderer_add_idle (renderer,
|
||||
flush_pending_swap_notify_idle,
|
||||
context,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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 (CoglRendererKMS *kms_renderer)
|
||||
{
|
||||
drmEventContext evctx;
|
||||
|
||||
if (kms_renderer->page_flips_not_supported)
|
||||
return;
|
||||
|
||||
memset (&evctx, 0, sizeof evctx);
|
||||
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
||||
evctx.page_flip_handler = page_flip_handler;
|
||||
drmHandleEvent (kms_renderer->fd, &evctx);
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch_kms_events (void *user_data, int revents)
|
||||
{
|
||||
CoglRenderer *renderer = user_data;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
if (!revents)
|
||||
return;
|
||||
|
||||
handle_drm_event (kms_renderer);
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_renderer_connect (CoglRenderer *cogl_renderer,
|
||||
CoglError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
CoglRendererEGL *egl_renderer;
|
||||
CoglRendererKMS *kms_renderer;
|
||||
|
||||
cogl_renderer->winsys = g_slice_new0 (CoglRendererEGL);
|
||||
egl_renderer = cogl_renderer->winsys;
|
||||
|
||||
egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable;
|
||||
egl_renderer->platform = g_slice_new0 (CoglRendererKMS);
|
||||
kms_renderer = egl_renderer->platform;
|
||||
|
||||
kms_renderer->fd = meta_renderer_native_get_kms_fd (renderer_native);
|
||||
|
||||
egl_renderer->edpy = EGL_NO_DISPLAY;
|
||||
|
||||
kms_renderer->gbm = gbm_create_device (kms_renderer->fd);
|
||||
if (kms_renderer->gbm == NULL)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_INIT,
|
||||
"Couldn't create gbm device");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
egl_renderer->edpy = eglGetDisplay ((EGLNativeDisplayType)kms_renderer->gbm);
|
||||
if (egl_renderer->edpy == EGL_NO_DISPLAY)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_INIT,
|
||||
"Couldn't get eglDisplay");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!_cogl_winsys_egl_renderer_connect_common (cogl_renderer, error))
|
||||
goto fail;
|
||||
|
||||
_cogl_poll_renderer_add_fd (cogl_renderer,
|
||||
kms_renderer->fd,
|
||||
COGL_POLL_FD_EVENT_IN,
|
||||
NULL, /* no prepare callback */
|
||||
dispatch_kms_events,
|
||||
cogl_renderer);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
_cogl_winsys_renderer_disconnect (cogl_renderer);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_crtc_modes (CoglDisplay *display, int fb_id)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRendererEGL *egl_renderer = display->renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
GList *l;
|
||||
|
||||
for (l = kms_display->crtcs; l; l = l->next)
|
||||
{
|
||||
CoglKmsCrtc *crtc = l->data;
|
||||
|
||||
int ret = drmModeSetCrtc (kms_renderer->fd,
|
||||
crtc->id,
|
||||
fb_id, crtc->x, crtc->y,
|
||||
crtc->connectors, crtc->count,
|
||||
crtc->count ? &crtc->mode : NULL);
|
||||
if (ret)
|
||||
g_warning ("Failed to set crtc mode %s: %m", crtc->mode.name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flip_all_crtcs (CoglDisplay *display, CoglFlipKMS *flip, int fb_id)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRendererEGL *egl_renderer = display->renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
GList *l;
|
||||
gboolean needs_flip = FALSE;
|
||||
|
||||
for (l = kms_display->crtcs; l; l = l->next)
|
||||
{
|
||||
CoglKmsCrtc *crtc = l->data;
|
||||
int ret = 0;
|
||||
|
||||
if (crtc->count == 0 || crtc->ignore)
|
||||
continue;
|
||||
|
||||
needs_flip = TRUE;
|
||||
|
||||
if (!kms_renderer->page_flips_not_supported)
|
||||
{
|
||||
ret = drmModePageFlip (kms_renderer->fd,
|
||||
crtc->id, fb_id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, flip);
|
||||
if (ret != 0 && ret != -EACCES)
|
||||
{
|
||||
g_warning ("Failed to flip: %m");
|
||||
kms_renderer->page_flips_not_supported = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
flip->pending++;
|
||||
}
|
||||
|
||||
if (kms_renderer->page_flips_not_supported && needs_flip)
|
||||
flip->pending = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
crtc_free (CoglKmsCrtc *crtc)
|
||||
{
|
||||
g_free (crtc->connectors);
|
||||
g_slice_free (CoglKmsCrtc, crtc);
|
||||
}
|
||||
|
||||
static CoglKmsCrtc *
|
||||
crtc_copy (CoglKmsCrtc *from)
|
||||
{
|
||||
CoglKmsCrtc *new;
|
||||
|
||||
new = g_slice_new (CoglKmsCrtc);
|
||||
|
||||
*new = *from;
|
||||
new->connectors = g_memdup (from->connectors, from->count * sizeof(uint32_t));
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_egl_display_setup (CoglDisplay *display,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display;
|
||||
CoglRendererEGL *egl_renderer = display->renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
kms_display = g_slice_new0 (CoglDisplayKMS);
|
||||
egl_display->platform = kms_display;
|
||||
|
||||
/* Force a full modeset / drmModeSetCrtc on
|
||||
* the first swap buffers call.
|
||||
*/
|
||||
kms_display->pending_set_crtc = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_winsys_egl_display_destroy (CoglDisplay *display)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
GList *l;
|
||||
|
||||
g_list_free_full (kms_display->crtcs, (GDestroyNotify) crtc_free);
|
||||
|
||||
g_slice_free (CoglDisplayKMS, egl_display->platform);
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_egl_context_created (CoglDisplay *display,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
|
||||
if ((egl_renderer->private_features &
|
||||
COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0)
|
||||
{
|
||||
kms_display->dummy_gbm_surface =
|
||||
gbm_surface_create (kms_renderer->gbm,
|
||||
16, 16,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_RENDERING);
|
||||
if (!kms_display->dummy_gbm_surface)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
||||
"Failed to create dummy GBM surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
egl_display->dummy_surface =
|
||||
eglCreateWindowSurface (egl_renderer->edpy,
|
||||
egl_display->egl_config,
|
||||
(EGLNativeWindowType)
|
||||
kms_display->dummy_gbm_surface,
|
||||
NULL);
|
||||
if (egl_display->dummy_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
||||
"Failed to create dummy EGL surface");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_cogl_winsys_egl_make_current (display,
|
||||
egl_display->dummy_surface,
|
||||
egl_display->dummy_surface,
|
||||
egl_display->egl_context))
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
||||
"Failed to make context current");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_winsys_egl_cleanup_context (CoglDisplay *display)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
|
||||
if (egl_display->dummy_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface);
|
||||
egl_display->dummy_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (kms_display->dummy_gbm_surface != NULL)
|
||||
{
|
||||
gbm_surface_destroy (kms_display->dummy_gbm_surface);
|
||||
kms_display->dummy_gbm_surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
const int *rectangles,
|
||||
int n_rectangles)
|
||||
{
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglDisplayEGL *egl_display = context->display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||
uint32_t handle, stride;
|
||||
CoglFlipKMS *flip;
|
||||
|
||||
/* If we already have a pending swap then block until it completes */
|
||||
while (kms_onscreen->next_fb_id != 0)
|
||||
handle_drm_event (kms_renderer);
|
||||
|
||||
if (kms_onscreen->pending_egl_surface)
|
||||
{
|
||||
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
||||
egl_onscreen->egl_surface = kms_onscreen->pending_egl_surface;
|
||||
kms_onscreen->pending_egl_surface = NULL;
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (COGL_FRAMEBUFFER (kms_display->onscreen),
|
||||
kms_display->width, kms_display->height);
|
||||
context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
|
||||
}
|
||||
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
|
||||
if (kms_onscreen->pending_surface)
|
||||
{
|
||||
free_current_bo (onscreen);
|
||||
if (kms_onscreen->surface)
|
||||
gbm_surface_destroy (kms_onscreen->surface);
|
||||
kms_onscreen->surface = kms_onscreen->pending_surface;
|
||||
kms_onscreen->pending_surface = NULL;
|
||||
}
|
||||
/* Now we need to set the CRTC to whatever is the front buffer */
|
||||
kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);
|
||||
|
||||
stride = gbm_bo_get_stride (kms_onscreen->next_bo);
|
||||
handle = gbm_bo_get_handle (kms_onscreen->next_bo).u32;
|
||||
|
||||
if (drmModeAddFB (kms_renderer->fd,
|
||||
kms_display->width,
|
||||
kms_display->height,
|
||||
24, /* depth */
|
||||
32, /* bpp */
|
||||
stride,
|
||||
handle,
|
||||
&kms_onscreen->next_fb_id))
|
||||
{
|
||||
g_warning ("Failed to create new back buffer handle: %m");
|
||||
gbm_surface_release_buffer (kms_onscreen->surface,
|
||||
kms_onscreen->next_bo);
|
||||
kms_onscreen->next_bo = NULL;
|
||||
kms_onscreen->next_fb_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If this is the first framebuffer to be presented then we now setup the
|
||||
* crtc modes, else we flip from the previous buffer */
|
||||
if (kms_display->pending_set_crtc)
|
||||
{
|
||||
setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
|
||||
kms_display->pending_set_crtc = FALSE;
|
||||
}
|
||||
|
||||
flip = g_slice_new0 (CoglFlipKMS);
|
||||
flip->onscreen = onscreen;
|
||||
|
||||
flip_all_crtcs (context->display, flip, kms_onscreen->next_fb_id);
|
||||
|
||||
if (flip->pending == 0)
|
||||
{
|
||||
drmModeRmFB (kms_renderer->fd, kms_onscreen->next_fb_id);
|
||||
gbm_surface_release_buffer (kms_onscreen->surface,
|
||||
kms_onscreen->next_bo);
|
||||
kms_onscreen->next_bo = NULL;
|
||||
kms_onscreen->next_fb_id = 0;
|
||||
g_slice_free (CoglFlipKMS, flip);
|
||||
flip = NULL;
|
||||
|
||||
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 */
|
||||
if (kms_renderer->page_flips_not_supported)
|
||||
{
|
||||
setup_crtc_modes (context->display, kms_onscreen->next_fb_id);
|
||||
process_flip (flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_egl_context_init (CoglContext *context,
|
||||
CoglError **error)
|
||||
{
|
||||
COGL_FLAGS_SET (context->features,
|
||||
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, TRUE);
|
||||
/* TODO: remove this deprecated feature */
|
||||
COGL_FLAGS_SET (context->winsys_features,
|
||||
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
|
||||
TRUE);
|
||||
COGL_FLAGS_SET (context->winsys_features,
|
||||
COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT,
|
||||
TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *context = framebuffer->context;
|
||||
CoglDisplay *display = context->display;
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
CoglOnscreenEGL *egl_onscreen;
|
||||
CoglOnscreenKMS *kms_onscreen;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
|
||||
|
||||
if (kms_display->onscreen)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Cannot have multiple onscreens in the KMS platform");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
kms_display->onscreen = onscreen;
|
||||
|
||||
onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
|
||||
egl_onscreen = onscreen->winsys;
|
||||
|
||||
kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
|
||||
egl_onscreen->platform = kms_onscreen;
|
||||
|
||||
/* If a kms_fd is set then the display width and height
|
||||
* won't be available until meta_renderer_native_set_layout
|
||||
* is called. In that case, defer creating the surface
|
||||
* until then.
|
||||
*/
|
||||
if (kms_display->width == 0 ||
|
||||
kms_display->height == 0)
|
||||
return TRUE;
|
||||
|
||||
kms_onscreen->surface =
|
||||
gbm_surface_create (kms_renderer->gbm,
|
||||
kms_display->width,
|
||||
kms_display->height,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_SCANOUT |
|
||||
GBM_BO_USE_RENDERING);
|
||||
|
||||
if (!kms_onscreen->surface)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Failed to allocate surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
egl_onscreen->egl_surface =
|
||||
eglCreateWindowSurface (egl_renderer->edpy,
|
||||
egl_display->egl_config,
|
||||
(EGLNativeWindowType) kms_onscreen->surface,
|
||||
NULL);
|
||||
if (egl_onscreen->egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Failed to allocate surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer,
|
||||
kms_display->width,
|
||||
kms_display->height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
CoglContext *context = framebuffer->context;
|
||||
CoglDisplay *display = context->display;
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen;
|
||||
|
||||
/* If we never successfully allocated then there's nothing to do */
|
||||
if (egl_onscreen == NULL)
|
||||
return;
|
||||
|
||||
kms_display->onscreen = NULL;
|
||||
|
||||
kms_onscreen = egl_onscreen->platform;
|
||||
|
||||
/* flip state takes a reference on the onscreen so there should
|
||||
* never be outstanding flips when we reach here. */
|
||||
g_return_if_fail (kms_onscreen->next_fb_id == 0);
|
||||
|
||||
free_current_bo (onscreen);
|
||||
|
||||
if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
|
||||
{
|
||||
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
||||
egl_onscreen->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
if (kms_onscreen->surface)
|
||||
{
|
||||
gbm_surface_destroy (kms_onscreen->surface);
|
||||
kms_onscreen->surface = NULL;
|
||||
}
|
||||
|
||||
g_slice_free (CoglOnscreenKMS, kms_onscreen);
|
||||
g_slice_free (CoglOnscreenEGL, onscreen->winsys);
|
||||
onscreen->winsys = NULL;
|
||||
}
|
||||
|
||||
static const CoglWinsysEGLVtable
|
||||
_cogl_winsys_egl_vtable = {
|
||||
.display_setup = _cogl_winsys_egl_display_setup,
|
||||
.display_destroy = _cogl_winsys_egl_display_destroy,
|
||||
.context_created = _cogl_winsys_egl_context_created,
|
||||
.cleanup_context = _cogl_winsys_egl_cleanup_context,
|
||||
.context_init = _cogl_winsys_egl_context_init
|
||||
};
|
||||
|
||||
struct gbm_device *
|
||||
meta_renderer_native_get_gbm (MetaRendererNative *renderer_native)
|
||||
{
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglRenderer *renderer = cogl_display->renderer;
|
||||
|
||||
if (renderer->connected)
|
||||
{
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
return kms_renderer->gbm;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
meta_renderer_native_get_kms_fd (MetaRendererNative *renderer_native)
|
||||
{
|
||||
return renderer_native->kms_fd;
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
||||
{
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
|
||||
if (cogl_display->setup)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
kms_display->pending_set_crtc = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
||||
int width,
|
||||
int height,
|
||||
CoglKmsCrtc **crtcs,
|
||||
int n_crtcs,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
CoglRenderer *renderer = cogl_display->renderer;
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
||||
GList *crtc_list;
|
||||
int i;
|
||||
|
||||
if ((width != kms_display->width ||
|
||||
height != kms_display->height) &&
|
||||
kms_display->onscreen)
|
||||
{
|
||||
CoglOnscreenEGL *egl_onscreen = kms_display->onscreen->winsys;
|
||||
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
||||
struct gbm_surface *new_surface;
|
||||
EGLSurface new_egl_surface;
|
||||
|
||||
/* Need to drop the GBM surface and create a new one */
|
||||
|
||||
new_surface = gbm_surface_create (kms_renderer->gbm,
|
||||
width, height,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_SCANOUT |
|
||||
GBM_BO_USE_RENDERING);
|
||||
|
||||
if (!new_surface)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Failed to allocate new surface");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
new_egl_surface =
|
||||
eglCreateWindowSurface (egl_renderer->edpy,
|
||||
egl_display->egl_config,
|
||||
(EGLNativeWindowType) new_surface,
|
||||
NULL);
|
||||
if (new_egl_surface == EGL_NO_SURFACE)
|
||||
{
|
||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Failed to allocate new surface");
|
||||
gbm_surface_destroy (new_surface);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (kms_onscreen->pending_egl_surface)
|
||||
eglDestroySurface (egl_renderer->edpy, kms_onscreen->pending_egl_surface);
|
||||
if (kms_onscreen->pending_surface)
|
||||
gbm_surface_destroy (kms_onscreen->pending_surface);
|
||||
|
||||
/* If there's already a surface, wait until the next swap to switch
|
||||
* it out, otherwise, if we're just starting up we can use the new
|
||||
* surface right away.
|
||||
*/
|
||||
if (kms_onscreen->surface != NULL)
|
||||
{
|
||||
kms_onscreen->pending_surface = new_surface;
|
||||
kms_onscreen->pending_egl_surface = new_egl_surface;
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (kms_display->onscreen);
|
||||
|
||||
kms_onscreen->surface = new_surface;
|
||||
egl_onscreen->egl_surface = new_egl_surface;
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
kms_display->width = width;
|
||||
kms_display->height = height;
|
||||
|
||||
g_list_free_full (kms_display->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);
|
||||
kms_display->crtcs = crtc_list;
|
||||
|
||||
kms_display->pending_set_crtc = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
||||
uint32_t id,
|
||||
gboolean ignore)
|
||||
{
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
CoglDisplayKMS *kms_display = egl_display->platform;
|
||||
GList *l;
|
||||
|
||||
for (l = kms_display->crtcs; l; l = l->next)
|
||||
{
|
||||
CoglKmsCrtc *crtc = l->data;
|
||||
if (crtc->id == id)
|
||||
{
|
||||
crtc->ignore = ignore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const CoglWinsysVtable *
|
||||
get_native_cogl_winsys_vtable (void)
|
||||
{
|
||||
static CoglBool vtable_inited = FALSE;
|
||||
static CoglWinsysVtable vtable;
|
||||
|
||||
if (!vtable_inited)
|
||||
{
|
||||
/* The this winsys is a subclass of the EGL winsys so we
|
||||
start by copying its vtable */
|
||||
|
||||
parent_vtable = _cogl_winsys_egl_get_vtable ();
|
||||
vtable = *parent_vtable;
|
||||
|
||||
vtable.id = COGL_WINSYS_ID_CUSTOM;
|
||||
vtable.name = "EGL_KMS";
|
||||
|
||||
vtable.renderer_connect = _cogl_winsys_renderer_connect;
|
||||
vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
|
||||
|
||||
vtable.onscreen_init = _cogl_winsys_onscreen_init;
|
||||
vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
|
||||
|
||||
/* The KMS winsys doesn't support swap region */
|
||||
vtable.onscreen_swap_region = NULL;
|
||||
vtable.onscreen_swap_buffers_with_damage =
|
||||
_cogl_winsys_onscreen_swap_buffers_with_damage;
|
||||
|
||||
vtable_inited = TRUE;
|
||||
}
|
||||
|
||||
return &vtable;
|
||||
}
|
||||
|
||||
static CoglRenderer *
|
||||
meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer)
|
||||
{
|
||||
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||
CoglRenderer *cogl_renderer;
|
||||
|
||||
cogl_renderer = cogl_renderer_new ();
|
||||
cogl_renderer_set_custom_winsys (cogl_renderer,
|
||||
_cogl_winsys_egl_kms_get_vtable);
|
||||
cogl_kms_renderer_set_kms_fd (cogl_renderer, renderer_native->kms_fd);
|
||||
get_native_cogl_winsys_vtable);
|
||||
|
||||
return cogl_renderer;
|
||||
}
|
||||
|
@ -26,12 +26,41 @@
|
||||
#define META_RENDERER_NATIVE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "backends/meta-renderer.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
uint32_t x, y;
|
||||
drmModeModeInfo mode;
|
||||
|
||||
uint32_t *connectors;
|
||||
uint32_t count;
|
||||
|
||||
CoglBool ignore;
|
||||
} CoglKmsCrtc;
|
||||
|
||||
#define META_TYPE_RENDERER_NATIVE (meta_renderer_native_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native,
|
||||
META, RENDERER_NATIVE,
|
||||
MetaRenderer)
|
||||
|
||||
struct gbm_device * meta_renderer_native_get_gbm (MetaRendererNative *renderer_native);
|
||||
|
||||
int meta_renderer_native_get_kms_fd (MetaRendererNative *renderer_native);
|
||||
|
||||
void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
||||
|
||||
gboolean meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
||||
int width,
|
||||
int height,
|
||||
CoglKmsCrtc **crtcs,
|
||||
int n_crtcs,
|
||||
GError **error);
|
||||
|
||||
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
||||
uint32_t id,
|
||||
gboolean ignore);
|
||||
|
||||
#endif /* META_RENDERER_NATIVE_H */
|
||||
|
Reference in New Issue
Block a user