mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
backends/native: Support drawing onto multiple onscreen framebuffers
Add support for drawing the stage using multiple stage views, where each stage view has its own onscreen framebuffer. https://bugzilla.gnome.org/show_bug.cgi?id=768976
This commit is contained in:
parent
d7b87799c8
commit
aecd98b847
@ -144,4 +144,6 @@ ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend);
|
|||||||
|
|
||||||
void meta_backend_monitors_changed (MetaBackend *backend);
|
void meta_backend_monitors_changed (MetaBackend *backend);
|
||||||
|
|
||||||
|
gboolean meta_is_stage_views_enabled (void);
|
||||||
|
|
||||||
#endif /* META_BACKEND_PRIVATE_H */
|
#endif /* META_BACKEND_PRIVATE_H */
|
||||||
|
@ -748,3 +748,19 @@ meta_clutter_init (void)
|
|||||||
|
|
||||||
meta_backend_post_init (_backend);
|
meta_backend_post_init (_backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_is_stage_views_enabled (void)
|
||||||
|
{
|
||||||
|
const gchar *mutter_stage_views;
|
||||||
|
|
||||||
|
if (!meta_is_wayland_compositor ())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS");
|
||||||
|
|
||||||
|
if (!mutter_stage_views)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return strcmp (mutter_stage_views, "1") == 0;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,17 @@
|
|||||||
#include "backends/meta-renderer.h"
|
#include "backends/meta-renderer.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_MONITOR_INFO,
|
||||||
|
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static GParamSpec *obj_props[PROP_LAST];
|
||||||
|
|
||||||
struct _MetaRendererView
|
struct _MetaRendererView
|
||||||
{
|
{
|
||||||
ClutterStageView parent;
|
ClutterStageView parent;
|
||||||
@ -32,6 +43,50 @@ struct _MetaRendererView
|
|||||||
G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
|
G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
|
||||||
CLUTTER_TYPE_STAGE_VIEW_COGL)
|
CLUTTER_TYPE_STAGE_VIEW_COGL)
|
||||||
|
|
||||||
|
MetaMonitorInfo *
|
||||||
|
meta_renderer_view_get_monitor_info (MetaRendererView *view)
|
||||||
|
{
|
||||||
|
return view->monitor_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_view_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaRendererView *view = META_RENDERER_VIEW (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_MONITOR_INFO:
|
||||||
|
g_value_set_pointer (value, view->monitor_info);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_view_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaRendererView *view = META_RENDERER_VIEW (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_MONITOR_INFO:
|
||||||
|
view->monitor_info = g_value_get_pointer (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_renderer_view_init (MetaRendererView *view)
|
meta_renderer_view_init (MetaRendererView *view)
|
||||||
{
|
{
|
||||||
@ -40,4 +95,17 @@ meta_renderer_view_init (MetaRendererView *view)
|
|||||||
static void
|
static void
|
||||||
meta_renderer_view_class_init (MetaRendererViewClass *klass)
|
meta_renderer_view_class_init (MetaRendererViewClass *klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->get_property = meta_renderer_view_get_property;
|
||||||
|
object_class->set_property = meta_renderer_view_set_property;
|
||||||
|
|
||||||
|
obj_props[PROP_MONITOR_INFO] =
|
||||||
|
g_param_spec_pointer ("monitor-info",
|
||||||
|
"MetaMonitorInfo",
|
||||||
|
"The monitor info of the view",
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
|
||||||
|
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||||
}
|
}
|
||||||
|
@ -26,4 +26,6 @@ G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view,
|
|||||||
META, RENDERER_VIEW,
|
META, RENDERER_VIEW,
|
||||||
ClutterStageViewCogl)
|
ClutterStageViewCogl)
|
||||||
|
|
||||||
|
MetaMonitorInfo *meta_renderer_view_get_monitor_info (MetaRendererView *view);
|
||||||
|
|
||||||
#endif /* META_RENDERER_VIEW_H */
|
#endif /* META_RENDERER_VIEW_H */
|
||||||
|
@ -390,7 +390,10 @@ meta_backend_native_update_screen_size (MetaBackend *backend,
|
|||||||
ClutterActor *stage = meta_backend_get_stage (backend);
|
ClutterActor *stage = meta_backend_get_stage (backend);
|
||||||
|
|
||||||
stage_native = meta_clutter_backend_native_get_stage_native (clutter_backend);
|
stage_native = meta_clutter_backend_native_get_stage_native (clutter_backend);
|
||||||
meta_stage_native_legacy_set_size (stage_native, width, height);
|
if (meta_is_stage_views_enabled ())
|
||||||
|
meta_stage_native_rebuild_views (stage_native);
|
||||||
|
else
|
||||||
|
meta_stage_native_legacy_set_size (stage_native, width, height);
|
||||||
|
|
||||||
clutter_actor_set_size (stage, width, height);
|
clutter_actor_set_size (stage, width, height);
|
||||||
}
|
}
|
||||||
|
@ -76,14 +76,6 @@ 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
|
typedef struct
|
||||||
{
|
{
|
||||||
GSource source;
|
GSource source;
|
||||||
@ -1065,12 +1057,8 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
unsigned int n_outputs)
|
unsigned int n_outputs)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
|
||||||
MetaBackend *backend;
|
|
||||||
MetaRenderer *renderer;
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int screen_width, screen_height;
|
int screen_width, screen_height;
|
||||||
gboolean ok;
|
|
||||||
GError *error;
|
|
||||||
|
|
||||||
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++)
|
||||||
@ -1156,20 +1144,6 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
|||||||
crtc->current_mode = NULL;
|
crtc->current_mode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
backend = meta_get_backend ();
|
|
||||||
renderer = meta_backend_get_renderer (backend);
|
|
||||||
|
|
||||||
error = NULL;
|
|
||||||
ok = meta_renderer_native_set_layout (META_RENDERER_NATIVE (renderer),
|
|
||||||
screen_width, screen_height,
|
|
||||||
&error);
|
|
||||||
if (!ok)
|
|
||||||
{
|
|
||||||
meta_warning ("Applying display configuration failed: %s\n", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n_outputs; i++)
|
for (i = 0; i < n_outputs; i++)
|
||||||
{
|
{
|
||||||
MetaOutputInfo *output_info = outputs[i];
|
MetaOutputInfo *output_info = outputs[i];
|
||||||
@ -1344,79 +1318,95 @@ get_crtc_connectors (MetaMonitorManager *manager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_monitor_manager_kms_apply_crtc_modes (MetaMonitorManagerKms *manager_kms,
|
meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||||
uint32_t fb_id)
|
MetaCRTC *crtc,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
uint32_t fb_id)
|
||||||
{
|
{
|
||||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
unsigned int i;
|
uint32_t *connectors;
|
||||||
|
unsigned int n_connectors;
|
||||||
|
drmModeModeInfo *mode;
|
||||||
|
|
||||||
for (i = 0; i < manager->n_crtcs; i++)
|
get_crtc_connectors (manager, crtc, &connectors, &n_connectors);
|
||||||
{
|
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
|
||||||
uint32_t *connectors;
|
|
||||||
unsigned int n_connectors;
|
|
||||||
drmModeModeInfo *mode;
|
|
||||||
|
|
||||||
get_crtc_connectors (manager, crtc, &connectors, &n_connectors);
|
if (connectors)
|
||||||
|
mode = crtc->current_mode->driver_private;
|
||||||
|
else
|
||||||
|
mode = NULL;
|
||||||
|
|
||||||
if (connectors)
|
if (drmModeSetCrtc (manager_kms->fd,
|
||||||
mode = crtc->current_mode->driver_private;
|
crtc->crtc_id,
|
||||||
else
|
fb_id,
|
||||||
mode = NULL;
|
x, y,
|
||||||
|
connectors, n_connectors,
|
||||||
|
mode) != 0)
|
||||||
|
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||||
|
|
||||||
if (drmModeSetCrtc (manager_kms->fd,
|
g_free (connectors);
|
||||||
crtc->crtc_id,
|
}
|
||||||
fb_id,
|
|
||||||
crtc->rect.x, crtc->rect.y,
|
|
||||||
connectors, n_connectors,
|
|
||||||
mode) != 0)
|
|
||||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
|
||||||
|
|
||||||
g_free (connectors);
|
static void
|
||||||
}
|
invoke_flip_closure (GClosure *flip_closure)
|
||||||
|
{
|
||||||
|
GValue param = G_VALUE_INIT;
|
||||||
|
|
||||||
|
g_value_init (¶m, G_TYPE_POINTER);
|
||||||
|
g_value_set_pointer (¶m, flip_closure);
|
||||||
|
g_closure_invoke (flip_closure, NULL, 1, ¶m, NULL);
|
||||||
|
g_closure_unref (flip_closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_monitor_manager_kms_flip_all_crtcs (MetaMonitorManagerKms *manager_kms,
|
meta_monitor_manager_kms_is_crtc_active (MetaMonitorManagerKms *manager_kms,
|
||||||
uint32_t fb_id,
|
MetaCRTC *crtc)
|
||||||
MetaKmsFlipCallback flip_callback,
|
|
||||||
void *user_data)
|
|
||||||
{
|
{
|
||||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
MetaKmsFlipClosure *flip_closure = NULL;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
gboolean fb_in_use = FALSE;
|
gboolean connected_crtc_found;
|
||||||
|
|
||||||
if (manager->power_save_mode != META_POWER_SAVE_ON)
|
if (manager->power_save_mode != META_POWER_SAVE_ON)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
for (i = 0; i < manager->n_crtcs; i++)
|
connected_crtc_found = FALSE;
|
||||||
|
for (i = 0; i < manager->n_outputs; i++)
|
||||||
{
|
{
|
||||||
MetaCRTC *crtc = &manager->crtcs[i];
|
MetaOutput *output = &manager->outputs[i];
|
||||||
uint32_t *connectors;
|
|
||||||
unsigned int n_connectors;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
get_crtc_connectors (manager, crtc, &connectors, &n_connectors);
|
if (output->crtc == crtc)
|
||||||
|
|
||||||
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);
|
connected_crtc_found = TRUE;
|
||||||
*flip_closure = (MetaKmsFlipClosure) {
|
break;
|
||||||
.pending = 0,
|
|
||||||
.callback = flip_callback,
|
|
||||||
.user_data = user_data
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!connected_crtc_found)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||||
|
MetaCRTC *crtc,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
uint32_t fb_id,
|
||||||
|
GClosure *flip_closure)
|
||||||
|
{
|
||||||
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
|
uint32_t *connectors;
|
||||||
|
unsigned int n_connectors;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
g_assert (manager->power_save_mode == META_POWER_SAVE_ON);
|
||||||
|
|
||||||
|
get_crtc_connectors (manager, crtc, &connectors, &n_connectors);
|
||||||
|
g_assert (n_connectors > 0);
|
||||||
|
|
||||||
|
if (!manager_kms->page_flips_not_supported)
|
||||||
|
{
|
||||||
ret = drmModePageFlip (manager_kms->fd,
|
ret = drmModePageFlip (manager_kms->fd,
|
||||||
crtc->crtc_id,
|
crtc->crtc_id,
|
||||||
fb_id,
|
fb_id,
|
||||||
@ -1426,24 +1416,21 @@ meta_monitor_manager_kms_flip_all_crtcs (MetaMonitorManagerKms *manager_kms,
|
|||||||
{
|
{
|
||||||
g_warning ("Failed to flip: %s", strerror (-ret));
|
g_warning ("Failed to flip: %s", strerror (-ret));
|
||||||
manager_kms->page_flips_not_supported = TRUE;
|
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 (manager_kms->page_flips_not_supported)
|
||||||
{
|
meta_monitor_manager_kms_apply_crtc_mode (manager_kms,
|
||||||
/* If the driver doesn't support page flipping, just set the mode directly
|
crtc,
|
||||||
* with the new framebuffer.
|
x, y,
|
||||||
*/
|
fb_id);
|
||||||
meta_monitor_manager_kms_apply_crtc_modes (manager_kms, fb_id);
|
|
||||||
flip_callback (user_data);
|
|
||||||
g_free (flip_closure);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fb_in_use;
|
if (ret != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_closure_ref (flip_closure);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1453,11 +1440,9 @@ page_flip_handler (int fd,
|
|||||||
unsigned int usec,
|
unsigned int usec,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
MetaKmsFlipClosure *flip_closure = data;
|
GClosure *flip_closure = data;
|
||||||
|
|
||||||
flip_closure->pending--;
|
invoke_flip_closure (flip_closure);
|
||||||
if (flip_closure->pending == 0)
|
|
||||||
flip_closure->callback (flip_closure->user_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -39,13 +39,21 @@ GType meta_monitor_manager_kms_get_type (void);
|
|||||||
|
|
||||||
typedef void (*MetaKmsFlipCallback) (void *user_data);
|
typedef void (*MetaKmsFlipCallback) (void *user_data);
|
||||||
|
|
||||||
void meta_monitor_manager_kms_apply_crtc_modes (MetaMonitorManagerKms *manager_kms,
|
void meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||||
uint32_t fb_id);
|
MetaCRTC *crtc,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
uint32_t fb_id);
|
||||||
|
|
||||||
gboolean meta_monitor_manager_kms_flip_all_crtcs (MetaMonitorManagerKms *manager_kms,
|
gboolean meta_monitor_manager_kms_is_crtc_active (MetaMonitorManagerKms *manager_kms,
|
||||||
uint32_t fb_id,
|
MetaCRTC *crtc);
|
||||||
MetaKmsFlipCallback flip_callback,
|
|
||||||
void *user_data);
|
gboolean meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||||
|
MetaCRTC *crtc,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
uint32_t fb_id,
|
||||||
|
GClosure *flip_closure);
|
||||||
|
|
||||||
void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms);
|
void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms);
|
||||||
|
|
||||||
|
@ -47,9 +47,11 @@
|
|||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/meta-renderer-view.h"
|
||||||
#include "backends/native/meta-monitor-manager-kms.h"
|
#include "backends/native/meta-monitor-manager-kms.h"
|
||||||
#include "backends/native/meta-renderer-native.h"
|
#include "backends/native/meta-renderer-native.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
#include "core/boxes-private.h"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -71,6 +73,11 @@ typedef struct _MetaOnscreenNative
|
|||||||
|
|
||||||
EGLSurface *pending_egl_surface;
|
EGLSurface *pending_egl_surface;
|
||||||
struct gbm_surface *pending_surface;
|
struct gbm_surface *pending_surface;
|
||||||
|
|
||||||
|
gboolean pending_set_crtc;
|
||||||
|
|
||||||
|
MetaRendererView *view;
|
||||||
|
int pending_flips;
|
||||||
} MetaOnscreenNative;
|
} MetaOnscreenNative;
|
||||||
|
|
||||||
struct _MetaRendererNative
|
struct _MetaRendererNative
|
||||||
@ -81,11 +88,9 @@ struct _MetaRendererNative
|
|||||||
struct gbm_device *gbm;
|
struct gbm_device *gbm;
|
||||||
CoglClosure *swap_notify_idle;
|
CoglClosure *swap_notify_idle;
|
||||||
|
|
||||||
int width, height;
|
int64_t frame_counter;
|
||||||
gboolean pending_set_crtc;
|
|
||||||
struct gbm_surface *dummy_gbm_surface;
|
|
||||||
|
|
||||||
CoglOnscreen *onscreen;
|
struct gbm_surface *dummy_gbm_surface;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -112,11 +117,8 @@ meta_renderer_native_disconnect (CoglRenderer *cogl_renderer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
flush_pending_swap_notify_cb (void *data,
|
flush_pending_swap_notify (CoglFramebuffer *framebuffer)
|
||||||
void *user_data)
|
|
||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer = data;
|
|
||||||
|
|
||||||
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
|
||||||
{
|
{
|
||||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
@ -130,7 +132,9 @@ flush_pending_swap_notify_cb (void *data,
|
|||||||
|
|
||||||
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
_cogl_onscreen_notify_frame_sync (onscreen, info);
|
||||||
_cogl_onscreen_notify_complete (onscreen, info);
|
_cogl_onscreen_notify_complete (onscreen, info);
|
||||||
|
|
||||||
onscreen_native->pending_swap_notify = FALSE;
|
onscreen_native->pending_swap_notify = FALSE;
|
||||||
|
cogl_object_unref (onscreen);
|
||||||
|
|
||||||
cogl_object_unref (info);
|
cogl_object_unref (info);
|
||||||
}
|
}
|
||||||
@ -143,15 +147,23 @@ flush_pending_swap_notify_idle (void *user_data)
|
|||||||
CoglContext *cogl_context = user_data;
|
CoglContext *cogl_context = user_data;
|
||||||
CoglRendererEGL *egl_renderer = cogl_context->display->renderer->winsys;
|
CoglRendererEGL *egl_renderer = cogl_context->display->renderer->winsys;
|
||||||
MetaRendererNative *renderer_native = egl_renderer->platform;
|
MetaRendererNative *renderer_native = egl_renderer->platform;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
/* This needs to be disconnected before invoking the callbacks in
|
/* This needs to be disconnected before invoking the callbacks in
|
||||||
* case the callbacks cause it to be queued again */
|
* case the callbacks cause it to be queued again */
|
||||||
_cogl_closure_disconnect (renderer_native->swap_notify_idle);
|
_cogl_closure_disconnect (renderer_native->swap_notify_idle);
|
||||||
renderer_native->swap_notify_idle = NULL;
|
renderer_native->swap_notify_idle = NULL;
|
||||||
|
|
||||||
g_list_foreach (cogl_context->framebuffers,
|
l = cogl_context->framebuffers;
|
||||||
flush_pending_swap_notify_cb,
|
while (l)
|
||||||
NULL);
|
{
|
||||||
|
GList *next = l->next;
|
||||||
|
CoglFramebuffer *framebuffer = l->data;
|
||||||
|
|
||||||
|
flush_pending_swap_notify (framebuffer);
|
||||||
|
|
||||||
|
l = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -179,11 +191,14 @@ free_current_bo (CoglOnscreen *onscreen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
queue_swap_notify_for_onscreen (CoglOnscreen *onscreen)
|
meta_onscreen_native_queue_swap_notify (CoglOnscreen *onscreen)
|
||||||
{
|
{
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||||
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
|
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
|
||||||
MetaRendererNative *renderer_native = egl_renderer->platform;
|
MetaRendererNative *renderer_native = egl_renderer->platform;
|
||||||
@ -200,6 +215,13 @@ queue_swap_notify_for_onscreen (CoglOnscreen *onscreen)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The framebuffer will have its own referenc while the swap notify is
|
||||||
|
* pending. Otherwise when destroying the view would drop the pending
|
||||||
|
* notification with if the destruction happens before the idle callback
|
||||||
|
* is invoked.
|
||||||
|
*/
|
||||||
|
cogl_object_ref (onscreen);
|
||||||
onscreen_native->pending_swap_notify = TRUE;
|
onscreen_native->pending_swap_notify = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,18 +270,6 @@ fail:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
setup_crtc_modes (CoglDisplay *cogl_display, int fb_id)
|
|
||||||
{
|
|
||||||
MetaBackend *backend = meta_get_backend ();
|
|
||||||
MetaMonitorManager *monitor_manager =
|
|
||||||
meta_backend_get_monitor_manager (backend);
|
|
||||||
MetaMonitorManagerKms *monitor_manager_kms =
|
|
||||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
|
||||||
|
|
||||||
meta_monitor_manager_kms_apply_crtc_modes (monitor_manager_kms, fb_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display,
|
meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display,
|
||||||
CoglError **error)
|
CoglError **error)
|
||||||
@ -273,7 +283,7 @@ meta_renderer_native_setup_egl_display (CoglDisplay *cogl_display,
|
|||||||
/* Force a full modeset / drmModeSetCrtc on
|
/* Force a full modeset / drmModeSetCrtc on
|
||||||
* the first swap buffers call.
|
* the first swap buffers call.
|
||||||
*/
|
*/
|
||||||
renderer_native->pending_set_crtc = TRUE;
|
meta_renderer_native_queue_modes_reset (renderer_native);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -352,14 +362,11 @@ meta_renderer_native_egl_cleanup_context (CoglDisplay *cogl_display)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
flip_callback (void *user_data)
|
meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
|
||||||
{
|
{
|
||||||
CoglOnscreen *onscreen = user_data;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
||||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
|
||||||
queue_swap_notify_for_onscreen (onscreen);
|
|
||||||
|
|
||||||
free_current_bo (onscreen);
|
free_current_bo (onscreen);
|
||||||
|
|
||||||
onscreen_native->current_fb_id = onscreen_native->next_fb_id;
|
onscreen_native->current_fb_id = onscreen_native->next_fb_id;
|
||||||
@ -367,8 +374,205 @@ flip_callback (void *user_data)
|
|||||||
|
|
||||||
onscreen_native->current_bo = onscreen_native->next_bo;
|
onscreen_native->current_bo = onscreen_native->next_bo;
|
||||||
onscreen_native->next_bo = NULL;
|
onscreen_native->next_bo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
cogl_object_unref (onscreen);
|
static void
|
||||||
|
on_crtc_flipped (GClosure *closure,
|
||||||
|
MetaRendererView *view)
|
||||||
|
{
|
||||||
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
clutter_stage_view_get_framebuffer (stage_view);
|
||||||
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
|
||||||
|
onscreen_native->pending_flips--;
|
||||||
|
if (onscreen_native->pending_flips == 0)
|
||||||
|
{
|
||||||
|
meta_onscreen_native_queue_swap_notify (onscreen);
|
||||||
|
meta_onscreen_native_swap_drm_fb (onscreen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
flip_closure_destroyed (MetaRendererView *view)
|
||||||
|
{
|
||||||
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
clutter_stage_view_get_framebuffer (stage_view);
|
||||||
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
|
||||||
|
if (onscreen_native->next_fb_id)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||||
|
|
||||||
|
drmModeRmFB (renderer_native->kms_fd, onscreen_native->next_fb_id);
|
||||||
|
gbm_surface_release_buffer (onscreen_native->surface,
|
||||||
|
onscreen_native->next_bo);
|
||||||
|
onscreen_native->next_bo = NULL;
|
||||||
|
onscreen_native->next_fb_id = 0;
|
||||||
|
|
||||||
|
meta_onscreen_native_queue_swap_notify (onscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (view);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_onscreen_native_flip_crtc (MetaOnscreenNative *onscreen_native,
|
||||||
|
GClosure *flip_closure,
|
||||||
|
MetaCRTC *crtc,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
gboolean *fb_in_use)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
MetaMonitorManagerKms *monitor_manager_kms =
|
||||||
|
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||||
|
|
||||||
|
if (!meta_monitor_manager_kms_is_crtc_active (monitor_manager_kms,
|
||||||
|
crtc))
|
||||||
|
{
|
||||||
|
*fb_in_use = FALSE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meta_monitor_manager_kms_flip_crtc (monitor_manager_kms,
|
||||||
|
crtc,
|
||||||
|
x, y,
|
||||||
|
onscreen_native->next_fb_id,
|
||||||
|
flip_closure))
|
||||||
|
onscreen_native->pending_flips++;
|
||||||
|
|
||||||
|
*fb_in_use = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_onscreen_native_set_crtc_modes (MetaOnscreenNative *onscreen_native)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
MetaMonitorManagerKms *monitor_manager_kms =
|
||||||
|
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||||
|
MetaRendererView *view = onscreen_native->view;
|
||||||
|
uint32_t next_fb_id = onscreen_native->next_fb_id;
|
||||||
|
MetaMonitorInfo *monitor_info;
|
||||||
|
|
||||||
|
monitor_info = meta_renderer_view_get_monitor_info (view);
|
||||||
|
if (monitor_info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < monitor_info->n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutput *output = monitor_info->outputs[i];
|
||||||
|
int x = output->crtc->rect.x - monitor_info->rect.x;
|
||||||
|
int y = output->crtc->rect.y - monitor_info->rect.y;
|
||||||
|
|
||||||
|
meta_monitor_manager_kms_apply_crtc_mode (monitor_manager_kms,
|
||||||
|
output->crtc,
|
||||||
|
x, y,
|
||||||
|
next_fb_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < monitor_manager->n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTC *crtc = &monitor_manager->crtcs[i];
|
||||||
|
|
||||||
|
meta_monitor_manager_kms_apply_crtc_mode (monitor_manager_kms,
|
||||||
|
crtc,
|
||||||
|
crtc->rect.x, crtc->rect.y,
|
||||||
|
next_fb_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
|
||||||
|
{
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
MetaRendererView *view = onscreen_native->view;
|
||||||
|
GClosure *flip_closure;
|
||||||
|
MetaMonitorInfo *monitor_info;
|
||||||
|
gboolean fb_in_use = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a closure that either will be invoked or destructed.
|
||||||
|
* Invoking the closure represents a completed flip. If the closure
|
||||||
|
* is destructed before being invoked, the framebuffer references will be
|
||||||
|
* cleaned up accordingly.
|
||||||
|
*
|
||||||
|
* Each successful flip will each own one reference to the closure, thus keep
|
||||||
|
* it alive until either invoked or destructed. If flipping failed, the
|
||||||
|
* closure will be destructed before this function goes out of scope.
|
||||||
|
*/
|
||||||
|
flip_closure = g_cclosure_new (G_CALLBACK (on_crtc_flipped),
|
||||||
|
g_object_ref (view),
|
||||||
|
(GClosureNotify) flip_closure_destroyed);
|
||||||
|
g_closure_set_marshal (flip_closure, g_cclosure_marshal_generic);
|
||||||
|
|
||||||
|
/* Either flip the CRTC's of the monitor info, if we are drawing just part
|
||||||
|
* of the stage, or all of the CRTC's if we are drawing the whole stage.
|
||||||
|
*/
|
||||||
|
monitor_info = meta_renderer_view_get_monitor_info (view);
|
||||||
|
if (monitor_info)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < monitor_info->n_outputs; i++)
|
||||||
|
{
|
||||||
|
MetaOutput *output = monitor_info->outputs[i];
|
||||||
|
int x = output->crtc->rect.x - monitor_info->rect.x;
|
||||||
|
int y = output->crtc->rect.y - monitor_info->rect.y;
|
||||||
|
|
||||||
|
meta_onscreen_native_flip_crtc (onscreen_native, flip_closure,
|
||||||
|
output->crtc, x, y,
|
||||||
|
&fb_in_use);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < monitor_manager->n_crtcs; i++)
|
||||||
|
{
|
||||||
|
MetaCRTC *crtc = &monitor_manager->crtcs[i];
|
||||||
|
|
||||||
|
meta_onscreen_native_flip_crtc (onscreen_native, flip_closure,
|
||||||
|
crtc, crtc->rect.x, crtc->rect.y,
|
||||||
|
&fb_in_use);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the framebuffer is in use, but we don't have any pending flips it means
|
||||||
|
* that flipping is not supported and we set the next framebuffer directly.
|
||||||
|
* Since we won't receive a flip callback, lets just notify listeners
|
||||||
|
* directly.
|
||||||
|
*/
|
||||||
|
if (fb_in_use && onscreen_native->pending_flips == 0)
|
||||||
|
{
|
||||||
|
meta_onscreen_native_queue_swap_notify (onscreen);
|
||||||
|
meta_onscreen_native_swap_drm_fb (onscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_closure_unref (flip_closure);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -387,27 +591,35 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
MetaRendererNative *renderer_native = egl_renderer->platform;
|
MetaRendererNative *renderer_native = egl_renderer->platform;
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
CoglFrameInfo *frame_info;
|
||||||
|
MetaRendererView *view;
|
||||||
|
cairo_rectangle_int_t view_layout;
|
||||||
uint32_t handle, stride;
|
uint32_t handle, stride;
|
||||||
gboolean fb_in_use;
|
|
||||||
uint32_t next_fb_id;
|
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
|
||||||
|
frame_info->global_frame_counter = renderer_native->frame_counter;
|
||||||
|
|
||||||
/* 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 (onscreen_native->next_fb_id != 0)
|
while (onscreen_native->next_fb_id != 0)
|
||||||
meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms);
|
meta_monitor_manager_kms_wait_for_flip (monitor_manager_kms);
|
||||||
|
|
||||||
|
view = onscreen_native->view;
|
||||||
|
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
|
||||||
|
|
||||||
if (onscreen_native->pending_egl_surface)
|
if (onscreen_native->pending_egl_surface)
|
||||||
{
|
{
|
||||||
CoglFramebuffer *fb = COGL_FRAMEBUFFER (renderer_native->onscreen);
|
CoglFramebuffer *fb = COGL_FRAMEBUFFER (onscreen);
|
||||||
|
|
||||||
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
||||||
egl_onscreen->egl_surface = onscreen_native->pending_egl_surface;
|
egl_onscreen->egl_surface = onscreen_native->pending_egl_surface;
|
||||||
onscreen_native->pending_egl_surface = NULL;
|
onscreen_native->pending_egl_surface = NULL;
|
||||||
|
|
||||||
_cogl_framebuffer_winsys_update_size (fb,
|
_cogl_framebuffer_winsys_update_size (fb,
|
||||||
renderer_native->width,
|
view_layout.width,
|
||||||
renderer_native->height);
|
view_layout.height);
|
||||||
cogl_context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
|
cogl_context->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||||
rectangles,
|
rectangles,
|
||||||
n_rectangles);
|
n_rectangles);
|
||||||
@ -420,6 +632,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
onscreen_native->surface = onscreen_native->pending_surface;
|
onscreen_native->surface = onscreen_native->pending_surface;
|
||||||
onscreen_native->pending_surface = NULL;
|
onscreen_native->pending_surface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now we need to set the CRTC to whatever is the front buffer */
|
/* Now we need to set the CRTC to whatever is the front buffer */
|
||||||
onscreen_native->next_bo =
|
onscreen_native->next_bo =
|
||||||
gbm_surface_lock_front_buffer (onscreen_native->surface);
|
gbm_surface_lock_front_buffer (onscreen_native->surface);
|
||||||
@ -428,8 +641,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
handle = gbm_bo_get_handle (onscreen_native->next_bo).u32;
|
handle = gbm_bo_get_handle (onscreen_native->next_bo).u32;
|
||||||
|
|
||||||
if (drmModeAddFB (renderer_native->kms_fd,
|
if (drmModeAddFB (renderer_native->kms_fd,
|
||||||
renderer_native->width,
|
view_layout.width,
|
||||||
renderer_native->height,
|
view_layout.height,
|
||||||
24, /* depth */
|
24, /* depth */
|
||||||
32, /* bpp */
|
32, /* bpp */
|
||||||
stride,
|
stride,
|
||||||
@ -446,34 +659,13 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
|||||||
|
|
||||||
/* If this is the first framebuffer to be presented then we now setup the
|
/* If this is the first framebuffer to be presented then we now setup the
|
||||||
* crtc modes, else we flip from the previous buffer */
|
* crtc modes, else we flip from the previous buffer */
|
||||||
if (renderer_native->pending_set_crtc)
|
if (onscreen_native->pending_set_crtc)
|
||||||
{
|
{
|
||||||
setup_crtc_modes (cogl_context->display, onscreen_native->next_fb_id);
|
meta_onscreen_native_set_crtc_modes (onscreen_native);
|
||||||
renderer_native->pending_set_crtc = FALSE;
|
onscreen_native->pending_set_crtc = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
next_fb_id = onscreen_native->next_fb_id;
|
meta_onscreen_native_flip_crtcs (onscreen);
|
||||||
|
|
||||||
/* 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 (!fb_in_use)
|
|
||||||
{
|
|
||||||
drmModeRmFB (renderer_native->kms_fd, onscreen_native->next_fb_id);
|
|
||||||
gbm_surface_release_buffer (onscreen_native->surface,
|
|
||||||
onscreen_native->next_bo);
|
|
||||||
onscreen_native->next_bo = NULL;
|
|
||||||
onscreen_native->next_fb_id = 0;
|
|
||||||
|
|
||||||
queue_swap_notify_for_onscreen (onscreen);
|
|
||||||
|
|
||||||
g_object_unref (onscreen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglBool
|
static CoglBool
|
||||||
@ -489,6 +681,62 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
|
|||||||
COGL_FLAGS_SET (cogl_context->winsys_features,
|
COGL_FLAGS_SET (cogl_context->winsys_features,
|
||||||
COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT,
|
COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT,
|
||||||
TRUE);
|
TRUE);
|
||||||
|
COGL_FLAGS_SET (cogl_context->winsys_features,
|
||||||
|
COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_renderer_native_create_surface (MetaRendererNative *renderer_native,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
struct gbm_surface **gbm_surface,
|
||||||
|
EGLSurface *egl_surface,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
CoglDisplay *cogl_display = cogl_context->display;
|
||||||
|
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||||
|
CoglRendererEGL *egl_renderer = cogl_display->renderer->winsys;
|
||||||
|
struct gbm_surface *new_gbm_surface;
|
||||||
|
EGLNativeWindowType egl_native_window;
|
||||||
|
EGLSurface new_egl_surface;
|
||||||
|
|
||||||
|
new_gbm_surface = gbm_surface_create (renderer_native->gbm,
|
||||||
|
width, height,
|
||||||
|
GBM_FORMAT_XRGB8888,
|
||||||
|
GBM_BO_USE_SCANOUT |
|
||||||
|
GBM_BO_USE_RENDERING);
|
||||||
|
|
||||||
|
if (!new_gbm_surface)
|
||||||
|
{
|
||||||
|
g_set_error (error, COGL_WINSYS_ERROR,
|
||||||
|
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||||
|
"Failed to allocate surface");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_native_window = (EGLNativeWindowType) new_gbm_surface;
|
||||||
|
new_egl_surface = eglCreateWindowSurface (egl_renderer->edpy,
|
||||||
|
egl_display->egl_config,
|
||||||
|
egl_native_window,
|
||||||
|
NULL);
|
||||||
|
if (new_egl_surface == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
gbm_surface_destroy (new_gbm_surface);
|
||||||
|
g_set_error (error, COGL_WINSYS_ERROR,
|
||||||
|
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||||
|
"Failed to allocate surface");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*gbm_surface = new_gbm_surface;
|
||||||
|
*egl_surface = new_egl_surface;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -506,66 +754,38 @@ meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
|
|||||||
MetaRendererNative *renderer_native = egl_renderer->platform;
|
MetaRendererNative *renderer_native = egl_renderer->platform;
|
||||||
CoglOnscreenEGL *egl_onscreen;
|
CoglOnscreenEGL *egl_onscreen;
|
||||||
MetaOnscreenNative *onscreen_native;
|
MetaOnscreenNative *onscreen_native;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
|
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
|
||||||
|
|
||||||
if (renderer_native->onscreen)
|
|
||||||
{
|
|
||||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
|
||||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
|
||||||
"Cannot have multiple onscreens in the KMS platform");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderer_native->onscreen = onscreen;
|
|
||||||
|
|
||||||
onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
|
onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
|
||||||
egl_onscreen = onscreen->winsys;
|
egl_onscreen = onscreen->winsys;
|
||||||
|
|
||||||
onscreen_native = g_slice_new0 (MetaOnscreenNative);
|
onscreen_native = g_slice_new0 (MetaOnscreenNative);
|
||||||
egl_onscreen->platform = onscreen_native;
|
egl_onscreen->platform = onscreen_native;
|
||||||
|
|
||||||
|
onscreen_native->pending_set_crtc = TRUE;
|
||||||
|
|
||||||
/* If a kms_fd is set then the display width and height
|
/* If a kms_fd is set then the display width and height
|
||||||
* won't be available until meta_renderer_native_set_layout
|
* won't be available until meta_renderer_native_set_layout
|
||||||
* is called. In that case, defer creating the surface
|
* is called. In that case, defer creating the surface
|
||||||
* until then.
|
* until then.
|
||||||
*/
|
*/
|
||||||
if (renderer_native->width == 0 ||
|
width = cogl_framebuffer_get_width (framebuffer);
|
||||||
renderer_native->height == 0)
|
height = cogl_framebuffer_get_height (framebuffer);
|
||||||
|
if (width == 0 || height == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
onscreen_native->surface =
|
if (!meta_renderer_native_create_surface (renderer_native,
|
||||||
gbm_surface_create (renderer_native->gbm,
|
width, height,
|
||||||
renderer_native->width,
|
&onscreen_native->surface,
|
||||||
renderer_native->height,
|
&egl_onscreen->egl_surface,
|
||||||
GBM_FORMAT_XRGB8888,
|
error))
|
||||||
GBM_BO_USE_SCANOUT |
|
return FALSE;
|
||||||
GBM_BO_USE_RENDERING);
|
|
||||||
|
|
||||||
if (!onscreen_native->surface)
|
|
||||||
{
|
|
||||||
_cogl_set_error (error, COGL_WINSYS_ERROR,
|
|
||||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
|
||||||
"Failed to allocate surface");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
egl_onscreen->egl_surface =
|
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||||
eglCreateWindowSurface (egl_renderer->edpy,
|
|
||||||
egl_display->egl_config,
|
|
||||||
(EGLNativeWindowType) onscreen_native->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,
|
|
||||||
renderer_native->width,
|
|
||||||
renderer_native->height);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -575,9 +795,6 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||||
CoglContext *cogl_context = framebuffer->context;
|
CoglContext *cogl_context = framebuffer->context;
|
||||||
CoglDisplay *cogl_display = cogl_context->display;
|
|
||||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
|
||||||
MetaRendererNative *renderer_native = egl_display->platform;
|
|
||||||
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
|
||||||
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
|
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
|
||||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
@ -587,8 +804,6 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
if (egl_onscreen == NULL)
|
if (egl_onscreen == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
renderer_native->onscreen = NULL;
|
|
||||||
|
|
||||||
onscreen_native = egl_onscreen->platform;
|
onscreen_native = egl_onscreen->platform;
|
||||||
|
|
||||||
/* flip state takes a reference on the onscreen so there should
|
/* flip state takes a reference on the onscreen so there should
|
||||||
@ -638,60 +853,57 @@ meta_renderer_native_get_kms_fd (MetaRendererNative *renderer_native)
|
|||||||
void
|
void
|
||||||
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
||||||
{
|
{
|
||||||
renderer_native->pending_set_crtc = TRUE;
|
MetaRenderer *renderer = META_RENDERER (renderer_native);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterStageView *stage_view = l->data;
|
||||||
|
CoglFramebuffer *framebuffer =
|
||||||
|
clutter_stage_view_get_framebuffer (stage_view);
|
||||||
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
|
|
||||||
|
onscreen_native->pending_set_crtc = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||||
int width,
|
MetaRendererView *view,
|
||||||
int height,
|
int width,
|
||||||
GError **error)
|
int height,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
CoglRendererEGL *egl_renderer = cogl_display->renderer->winsys;
|
||||||
CoglRenderer *cogl_renderer = cogl_display->renderer;
|
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
|
||||||
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
|
cairo_rectangle_int_t view_layout;
|
||||||
|
|
||||||
if ((width != renderer_native->width ||
|
clutter_stage_view_get_layout (stage_view, &view_layout);
|
||||||
height != renderer_native->height) &&
|
|
||||||
renderer_native->onscreen)
|
if (width != view_layout.width || height != view_layout.height)
|
||||||
{
|
{
|
||||||
CoglOnscreenEGL *egl_onscreen = renderer_native->onscreen->winsys;
|
CoglFramebuffer *framebuffer =
|
||||||
|
clutter_stage_view_get_framebuffer (stage_view);
|
||||||
|
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||||
struct gbm_surface *new_surface;
|
struct gbm_surface *new_surface;
|
||||||
EGLSurface new_egl_surface;
|
EGLSurface new_egl_surface;
|
||||||
|
|
||||||
/* Need to drop the GBM surface and create a new one */
|
/* Need to drop the GBM surface and create a new one */
|
||||||
|
|
||||||
new_surface = gbm_surface_create (renderer_native->gbm,
|
if (!meta_renderer_native_create_surface (renderer_native,
|
||||||
width, height,
|
width, height,
|
||||||
GBM_FORMAT_XRGB8888,
|
&new_surface,
|
||||||
GBM_BO_USE_SCANOUT |
|
&new_egl_surface,
|
||||||
GBM_BO_USE_RENDERING);
|
error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
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 (onscreen_native->pending_egl_surface)
|
if (onscreen_native->pending_egl_surface)
|
||||||
eglDestroySurface (egl_renderer->edpy,
|
eglDestroySurface (egl_renderer->edpy,
|
||||||
@ -710,8 +922,6 @@ meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (renderer_native->onscreen);
|
|
||||||
|
|
||||||
onscreen_native->surface = new_surface;
|
onscreen_native->surface = new_surface;
|
||||||
egl_onscreen->egl_surface = new_egl_surface;
|
egl_onscreen->egl_surface = new_egl_surface;
|
||||||
|
|
||||||
@ -719,10 +929,7 @@ meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer_native->width = width;
|
meta_renderer_native_queue_modes_reset (renderer_native);
|
||||||
renderer_native->height = height;
|
|
||||||
|
|
||||||
renderer_native->pending_set_crtc = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -773,6 +980,108 @@ meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer)
|
|||||||
return cogl_renderer;
|
return cogl_renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_onscreen_native_set_view (CoglOnscreen *onscreen,
|
||||||
|
MetaRendererView *view)
|
||||||
|
{
|
||||||
|
CoglOnscreenEGL *egl_onscreen;
|
||||||
|
MetaOnscreenNative *onscreen_native;
|
||||||
|
|
||||||
|
egl_onscreen = onscreen->winsys;
|
||||||
|
onscreen_native = egl_onscreen->platform;
|
||||||
|
onscreen_native->view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaRendererView *
|
||||||
|
meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
CoglOnscreen *onscreen;
|
||||||
|
CoglFramebuffer *framebuffer;
|
||||||
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||||
|
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
cairo_rectangle_int_t view_layout = { 0 };
|
||||||
|
MetaRendererView *view;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (!monitor_manager)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
meta_monitor_manager_get_screen_size (monitor_manager,
|
||||||
|
&view_layout.width,
|
||||||
|
&view_layout.height);
|
||||||
|
|
||||||
|
onscreen = cogl_onscreen_new (cogl_context,
|
||||||
|
view_layout.width,
|
||||||
|
view_layout.height);
|
||||||
|
cogl_onscreen_set_swap_throttled (onscreen,
|
||||||
|
_clutter_get_sync_to_vblank ());
|
||||||
|
|
||||||
|
framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||||
|
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||||
|
meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
|
||||||
|
error->message);
|
||||||
|
|
||||||
|
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||||
|
"layout", &view_layout,
|
||||||
|
"framebuffer", framebuffer,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
meta_onscreen_native_set_view (onscreen, view);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaRendererView *
|
||||||
|
meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||||
|
MetaMonitorInfo *monitor_info)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||||
|
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
CoglOnscreen *onscreen;
|
||||||
|
CoglFramebuffer *framebuffer;
|
||||||
|
cairo_rectangle_int_t view_layout;
|
||||||
|
MetaRendererView *view;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
view_layout = meta_rectangle_to_cairo_rectangle (&monitor_info->rect);
|
||||||
|
onscreen = cogl_onscreen_new (cogl_context,
|
||||||
|
view_layout.width,
|
||||||
|
view_layout.height);
|
||||||
|
cogl_onscreen_set_swap_throttled (onscreen,
|
||||||
|
_clutter_get_sync_to_vblank ());
|
||||||
|
|
||||||
|
framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||||
|
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||||
|
meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
|
||||||
|
error->message);
|
||||||
|
|
||||||
|
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||||
|
"layout", &view_layout,
|
||||||
|
"framebuffer", framebuffer,
|
||||||
|
"monitor-info", monitor_info,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
meta_onscreen_native_set_view (onscreen, view);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
|
||||||
|
{
|
||||||
|
renderer_native->frame_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native)
|
||||||
|
{
|
||||||
|
return renderer_native->frame_counter;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_renderer_native_get_property (GObject *object,
|
meta_renderer_native_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -879,6 +1188,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass)
|
|||||||
object_class->finalize = meta_renderer_native_finalize;
|
object_class->finalize = meta_renderer_native_finalize;
|
||||||
|
|
||||||
renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
|
renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer;
|
||||||
|
renderer_class->create_view = meta_renderer_native_create_view;
|
||||||
|
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_KMS_FD,
|
PROP_KMS_FD,
|
||||||
|
@ -44,13 +44,20 @@ int meta_renderer_native_get_kms_fd (MetaRendererNative *renderer_native);
|
|||||||
|
|
||||||
void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
gboolean meta_renderer_native_set_layout (MetaRendererNative *renderer_native,
|
gboolean meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||||
int width,
|
MetaRendererView *view,
|
||||||
int height,
|
int width,
|
||||||
GError **error);
|
int height,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
gboolean ignore);
|
gboolean ignore);
|
||||||
|
|
||||||
|
MetaRendererView * meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
|
void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
|
int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native);
|
||||||
|
|
||||||
#endif /* META_RENDERER_NATIVE_H */
|
#endif /* META_RENDERER_NATIVE_H */
|
||||||
|
@ -27,16 +27,22 @@
|
|||||||
#include "backends/native/meta-stage-native.h"
|
#include "backends/native/meta-stage-native.h"
|
||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/native/meta-renderer-native.h"
|
||||||
#include "meta/meta-backend.h"
|
#include "meta/meta-backend.h"
|
||||||
#include "meta/meta-monitor-manager.h"
|
#include "meta/meta-monitor-manager.h"
|
||||||
#include "meta/util.h"
|
#include "meta/util.h"
|
||||||
|
|
||||||
|
static GQuark quark_view_frame_closure = 0;
|
||||||
|
|
||||||
struct _MetaStageNative
|
struct _MetaStageNative
|
||||||
{
|
{
|
||||||
ClutterStageCogl parent;
|
ClutterStageCogl parent;
|
||||||
|
|
||||||
CoglOnscreen *pending_onscreen;
|
CoglOnscreen *pending_onscreen;
|
||||||
CoglClosure *frame_closure;
|
CoglClosure *frame_closure;
|
||||||
|
|
||||||
|
int64_t presented_frame_counter_sync;
|
||||||
|
int64_t presented_frame_counter_complete;
|
||||||
};
|
};
|
||||||
|
|
||||||
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
||||||
@ -63,25 +69,94 @@ get_legacy_view (MetaRenderer *renderer)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CoglOnscreen *
|
static void
|
||||||
get_legacy_onscreen (MetaStageNative *stage_native)
|
frame_cb (CoglOnscreen *onscreen,
|
||||||
|
CoglFrameEvent frame_event,
|
||||||
|
CoglFrameInfo *frame_info,
|
||||||
|
void *user_data)
|
||||||
|
|
||||||
{
|
{
|
||||||
if (stage_native->pending_onscreen)
|
MetaStageNative *stage_native = user_data;
|
||||||
{
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_native);
|
||||||
return stage_native->pending_onscreen;
|
int64_t global_frame_counter;
|
||||||
}
|
int64_t presented_frame_counter;
|
||||||
else
|
ClutterFrameInfo clutter_frame_info;
|
||||||
{
|
|
||||||
MetaBackend *backend = meta_get_backend ();
|
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
|
||||||
ClutterStageView *stage_view;
|
|
||||||
CoglFramebuffer *framebuffer;
|
|
||||||
|
|
||||||
stage_view = CLUTTER_STAGE_VIEW (get_legacy_view (renderer));
|
global_frame_counter = cogl_frame_info_get_global_frame_counter (frame_info);
|
||||||
framebuffer = clutter_stage_view_get_framebuffer (stage_view);
|
|
||||||
|
|
||||||
return COGL_ONSCREEN (framebuffer);
|
switch (frame_event)
|
||||||
|
{
|
||||||
|
case COGL_FRAME_EVENT_SYNC:
|
||||||
|
presented_frame_counter = stage_native->presented_frame_counter_sync;
|
||||||
|
stage_native->presented_frame_counter_sync = global_frame_counter;
|
||||||
|
break;
|
||||||
|
case COGL_FRAME_EVENT_COMPLETE:
|
||||||
|
presented_frame_counter = stage_native->presented_frame_counter_complete;
|
||||||
|
stage_native->presented_frame_counter_complete = global_frame_counter;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (global_frame_counter <= presented_frame_counter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clutter_frame_info = (ClutterFrameInfo) {
|
||||||
|
.frame_counter = global_frame_counter,
|
||||||
|
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
|
||||||
|
.presentation_time = cogl_frame_info_get_presentation_time (frame_info)
|
||||||
|
};
|
||||||
|
|
||||||
|
_clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_frame_callback (MetaStageNative *stage_native,
|
||||||
|
ClutterStageView *stage_view)
|
||||||
|
{
|
||||||
|
CoglFramebuffer *framebuffer;
|
||||||
|
CoglOnscreen *onscreen;
|
||||||
|
CoglClosure *closure;
|
||||||
|
|
||||||
|
closure = g_object_get_qdata (G_OBJECT (stage_view),
|
||||||
|
quark_view_frame_closure);
|
||||||
|
if (closure)
|
||||||
|
return;
|
||||||
|
|
||||||
|
framebuffer = clutter_stage_view_get_framebuffer (stage_view);
|
||||||
|
onscreen = COGL_ONSCREEN (framebuffer);
|
||||||
|
closure = cogl_onscreen_add_frame_callback (onscreen,
|
||||||
|
frame_cb,
|
||||||
|
stage_native,
|
||||||
|
NULL);
|
||||||
|
g_object_set_qdata (G_OBJECT (stage_view),
|
||||||
|
quark_view_frame_closure,
|
||||||
|
closure);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_frame_callbacks (MetaStageNative *stage_native)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||||
|
{
|
||||||
|
ClutterStageView *stage_view = l->data;
|
||||||
|
|
||||||
|
ensure_frame_callback (stage_native, stage_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_stage_native_rebuild_views (MetaStageNative *stage_native)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
|
||||||
|
meta_renderer_rebuild_views (renderer);
|
||||||
|
ensure_frame_callbacks (stage_native);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -91,13 +166,26 @@ meta_stage_native_legacy_set_size (MetaStageNative *stage_native,
|
|||||||
{
|
{
|
||||||
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);
|
||||||
MetaRendererView *legacy_view;
|
MetaRendererView *legacy_view;
|
||||||
|
GError *error = NULL;
|
||||||
cairo_rectangle_int_t view_layout;
|
cairo_rectangle_int_t view_layout;
|
||||||
|
|
||||||
legacy_view = get_legacy_view (renderer);
|
legacy_view = get_legacy_view (renderer);
|
||||||
if (!legacy_view)
|
if (!legacy_view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!meta_renderer_native_set_legacy_view_size (renderer_native,
|
||||||
|
legacy_view,
|
||||||
|
width, height,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
meta_warning ("Applying display configuration failed: %s\n",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
view_layout = (cairo_rectangle_int_t) {
|
view_layout = (cairo_rectangle_int_t) {
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = height
|
.height = height
|
||||||
@ -107,29 +195,6 @@ meta_stage_native_legacy_set_size (MetaStageNative *stage_native,
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
meta_stage_native_realize (ClutterStageWindow *stage_window)
|
|
||||||
{
|
|
||||||
MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
|
|
||||||
MetaBackend *backend = meta_get_backend ();
|
|
||||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
|
||||||
CoglFramebuffer *framebuffer;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
stage_native->pending_onscreen =
|
|
||||||
cogl_onscreen_new (clutter_backend->cogl_context, 1, 1);
|
|
||||||
|
|
||||||
framebuffer = COGL_FRAMEBUFFER (stage_native->pending_onscreen);
|
|
||||||
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
|
||||||
meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
|
|
||||||
error->message);
|
|
||||||
|
|
||||||
if (!(clutter_stage_window_parent_iface->realize (stage_window)))
|
|
||||||
meta_fatal ("Failed to realize native stage window");
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_stage_native_unrealize (ClutterStageWindow *stage_window)
|
meta_stage_native_unrealize (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
@ -137,16 +202,6 @@ meta_stage_native_unrealize (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
clutter_stage_window_parent_iface->unrealize (stage_window);
|
clutter_stage_window_parent_iface->unrealize (stage_window);
|
||||||
|
|
||||||
if (stage_native->frame_closure)
|
|
||||||
{
|
|
||||||
CoglOnscreen *onscreen;
|
|
||||||
|
|
||||||
onscreen = get_legacy_onscreen (stage_native);
|
|
||||||
cogl_onscreen_remove_frame_callback (onscreen,
|
|
||||||
stage_native->frame_closure);
|
|
||||||
stage_native->frame_closure = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer (&stage_native->pending_onscreen, cogl_object_unref);
|
g_clear_pointer (&stage_native->pending_onscreen, cogl_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,14 +216,18 @@ meta_stage_native_get_geometry (ClutterStageWindow *stage_window,
|
|||||||
cairo_rectangle_int_t *geometry)
|
cairo_rectangle_int_t *geometry)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
MetaMonitorManager *monitor_manager =
|
||||||
MetaRendererView *legacy_view;
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
|
||||||
legacy_view = get_legacy_view (renderer);
|
if (monitor_manager)
|
||||||
if (legacy_view)
|
|
||||||
{
|
{
|
||||||
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (legacy_view),
|
int width, height;
|
||||||
geometry);
|
|
||||||
|
meta_monitor_manager_get_screen_size (monitor_manager, &width, &height);
|
||||||
|
*geometry = (cairo_rectangle_int_t) {
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -179,62 +238,26 @@ meta_stage_native_get_geometry (ClutterStageWindow *stage_window,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
frame_cb (CoglOnscreen *onscreen,
|
|
||||||
CoglFrameEvent frame_event,
|
|
||||||
CoglFrameInfo *frame_info,
|
|
||||||
void *user_data)
|
|
||||||
{
|
|
||||||
MetaStageNative *stage_native = user_data;
|
|
||||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_native);
|
|
||||||
ClutterFrameInfo clutter_frame_info = {
|
|
||||||
.frame_counter = cogl_frame_info_get_frame_counter (frame_info),
|
|
||||||
.refresh_rate = cogl_frame_info_get_refresh_rate (frame_info),
|
|
||||||
.presentation_time = cogl_frame_info_get_presentation_time (frame_info)
|
|
||||||
};
|
|
||||||
|
|
||||||
_clutter_stage_cogl_presented (stage_cogl, frame_event, &clutter_frame_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ensure_legacy_view (ClutterStageWindow *stage_window)
|
ensure_legacy_view (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
|
MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
MetaMonitorManager *monitor_manager =
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||||
meta_backend_get_monitor_manager (backend);
|
|
||||||
MetaRendererView *legacy_view;
|
MetaRendererView *legacy_view;
|
||||||
cairo_rectangle_int_t view_layout = { 0 };
|
|
||||||
CoglFramebuffer *framebuffer;
|
|
||||||
CoglOnscreen *onscreen;
|
|
||||||
|
|
||||||
legacy_view = get_legacy_view (renderer);
|
legacy_view = get_legacy_view (renderer);
|
||||||
if (legacy_view)
|
if (legacy_view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!monitor_manager)
|
legacy_view = meta_renderer_native_create_legacy_view (renderer_native);
|
||||||
|
if (!legacy_view)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_monitor_manager_get_screen_size (monitor_manager,
|
|
||||||
&view_layout.width,
|
|
||||||
&view_layout.height);
|
|
||||||
framebuffer = g_steal_pointer (&stage_native->pending_onscreen);
|
|
||||||
legacy_view = g_object_new (META_TYPE_RENDERER_VIEW,
|
|
||||||
"layout", &view_layout,
|
|
||||||
"framebuffer", framebuffer,
|
|
||||||
NULL);
|
|
||||||
meta_renderer_set_legacy_view (renderer, legacy_view);
|
meta_renderer_set_legacy_view (renderer, legacy_view);
|
||||||
|
|
||||||
onscreen = COGL_ONSCREEN (framebuffer);
|
ensure_frame_callback (stage_native, CLUTTER_STAGE_VIEW (legacy_view));
|
||||||
cogl_onscreen_set_swap_throttled (onscreen,
|
|
||||||
_clutter_get_sync_to_vblank ());
|
|
||||||
|
|
||||||
stage_native->frame_closure =
|
|
||||||
cogl_onscreen_add_frame_callback (onscreen,
|
|
||||||
frame_cb,
|
|
||||||
stage_native,
|
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
@ -243,29 +266,43 @@ meta_stage_native_get_views (ClutterStageWindow *stage_window)
|
|||||||
MetaBackend *backend = meta_get_backend ();
|
MetaBackend *backend = meta_get_backend ();
|
||||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
|
||||||
ensure_legacy_view (stage_window);
|
if (!meta_is_stage_views_enabled ())
|
||||||
|
ensure_legacy_view (stage_window);
|
||||||
|
|
||||||
return meta_renderer_get_views (renderer);
|
return meta_renderer_get_views (renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
|
meta_stage_native_get_frame_counter (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
MetaStageNative *stage_native = META_STAGE_NATIVE (stage_window);
|
MetaBackend *backend = meta_get_backend ();
|
||||||
CoglOnscreen *legacy_onscreen;
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
|
||||||
|
|
||||||
legacy_onscreen = get_legacy_onscreen (stage_native);
|
return meta_renderer_native_get_frame_counter (renderer_native);
|
||||||
|
}
|
||||||
|
|
||||||
return cogl_onscreen_get_frame_counter (legacy_onscreen);
|
static void
|
||||||
|
meta_stage_native_finish_frame (ClutterStageWindow *stage_window)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
|
||||||
|
meta_renderer_native_finish_frame (META_RENDERER_NATIVE (renderer));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_stage_native_init (MetaStageNative *stage_native)
|
meta_stage_native_init (MetaStageNative *stage_native)
|
||||||
{
|
{
|
||||||
|
stage_native->presented_frame_counter_sync = -1;
|
||||||
|
stage_native->presented_frame_counter_complete = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_stage_native_class_init (MetaStageNativeClass *klass)
|
meta_stage_native_class_init (MetaStageNativeClass *klass)
|
||||||
{
|
{
|
||||||
|
quark_view_frame_closure =
|
||||||
|
g_quark_from_static_string ("-meta-native-stage-view-frame-closure");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -273,10 +310,10 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
|||||||
{
|
{
|
||||||
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
||||||
|
|
||||||
iface->realize = meta_stage_native_realize;
|
|
||||||
iface->unrealize = meta_stage_native_unrealize;
|
iface->unrealize = meta_stage_native_unrealize;
|
||||||
iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
|
iface->can_clip_redraws = meta_stage_native_can_clip_redraws;
|
||||||
iface->get_geometry = meta_stage_native_get_geometry;
|
iface->get_geometry = meta_stage_native_get_geometry;
|
||||||
iface->get_views = meta_stage_native_get_views;
|
iface->get_views = meta_stage_native_get_views;
|
||||||
iface->get_frame_counter = meta_stage_native_get_frame_counter;
|
iface->get_frame_counter = meta_stage_native_get_frame_counter;
|
||||||
|
iface->finish_frame = meta_stage_native_finish_frame;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
G_DECLARE_FINAL_TYPE (MetaStageNative, meta_stage_native,
|
G_DECLARE_FINAL_TYPE (MetaStageNative, meta_stage_native,
|
||||||
META, STAGE_NATIVE, ClutterStageCogl)
|
META, STAGE_NATIVE, ClutterStageCogl)
|
||||||
|
|
||||||
|
void meta_stage_native_rebuild_views (MetaStageNative *stage_native);
|
||||||
|
|
||||||
void meta_stage_native_legacy_set_size (MetaStageNative *stage_native,
|
void meta_stage_native_legacy_set_size (MetaStageNative *stage_native,
|
||||||
int width,
|
int width,
|
||||||
int height);
|
int height);
|
||||||
|
Loading…
Reference in New Issue
Block a user