x11/nested: Always draw to an offscreen framebuffer

Always draw the stage to an offscreen framebuffer when using the nested
backend, so that we more emulate things more similarly to how it works
real-world, i.e. it'll work the way whether stage views are enabled or
not.

https://bugzilla.gnome.org/show_bug.cgi?id=777732
This commit is contained in:
Jonas Ådahl 2017-03-20 17:04:45 +08:00
parent 9d914091f5
commit 93c6a869ec
3 changed files with 138 additions and 28 deletions

View File

@ -28,6 +28,7 @@
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/meta-renderer.h" #include "backends/meta-renderer.h"
#include "backends/x11/nested/meta-renderer-x11-nested.h"
#include "clutter/clutter-mutter.h" #include "clutter/clutter-mutter.h"
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
@ -53,6 +54,25 @@ typedef struct _ClutterStageX11View
ClutterStageViewCogl *view; ClutterStageViewCogl *view;
} MetaStageX11NestedView; } MetaStageX11NestedView;
static void
meta_stage_x11_nested_resize (ClutterStageWindow *stage_window,
gint width,
gint height)
{
if (!meta_is_stage_views_enabled ())
{
MetaBackend *backend = meta_get_backend ();
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererX11Nested *renderer_x11_nested =
META_RENDERER_X11_NESTED (renderer);
meta_renderer_x11_nested_ensure_legacy_view (renderer_x11_nested,
width, height);
}
clutter_stage_window_parent_iface->resize (stage_window, width, height);
}
static gboolean static gboolean
meta_stage_x11_nested_can_clip_redraws (ClutterStageWindow *stage_window) meta_stage_x11_nested_can_clip_redraws (ClutterStageWindow *stage_window)
{ {
@ -65,10 +85,7 @@ meta_stage_x11_nested_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);
if (meta_is_stage_views_enabled ()) return meta_renderer_get_views (renderer);
return meta_renderer_get_views (renderer);
else
return clutter_stage_window_parent_iface->get_views (stage_window);
} }
static void static void
@ -82,12 +99,6 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen); CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen);
GList *l; GList *l;
/*
* If we are in legacy mode, the stage is already on the onscreen.
*/
if (!meta_is_stage_views_enabled ())
return;
if (!stage_nested->pipeline) if (!stage_nested->pipeline)
stage_nested->pipeline = cogl_pipeline_new (clutter_backend->cogl_context); stage_nested->pipeline = cogl_pipeline_new (clutter_backend->cogl_context);
@ -177,9 +188,9 @@ 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->resize = meta_stage_x11_nested_resize;
iface->can_clip_redraws = meta_stage_x11_nested_can_clip_redraws; iface->can_clip_redraws = meta_stage_x11_nested_can_clip_redraws;
iface->unrealize = meta_stage_x11_nested_unrealize; iface->unrealize = meta_stage_x11_nested_unrealize;
iface->get_views = meta_stage_x11_nested_get_views; iface->get_views = meta_stage_x11_nested_get_views;
iface->finish_frame = meta_stage_x11_nested_finish_frame; iface->finish_frame = meta_stage_x11_nested_finish_frame;
} }

View File

@ -65,6 +65,104 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
return logical_monitor->transform; return logical_monitor->transform;
} }
static MetaRendererView *
get_legacy_view (MetaRenderer *renderer)
{
GList *views;
views = meta_renderer_get_views (renderer);
if (views)
return META_RENDERER_VIEW (views->data);
else
return NULL;
}
static CoglOffscreen *
create_offscreen (CoglContext *cogl_context,
int width,
int height)
{
CoglTexture2D *texture_2d;
CoglOffscreen *offscreen;
GError *error = NULL;
texture_2d = cogl_texture_2d_new_with_size (cogl_context, width, height);
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture_2d));
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
meta_fatal ("Couldn't allocate framebuffer: %s", error->message);
return offscreen;
}
static void
meta_renderer_x11_nested_resize_legacy_view (MetaRendererX11Nested *renderer_x11_nested,
int width,
int height)
{
MetaRenderer *renderer = META_RENDERER (renderer_x11_nested);
MetaBackend *backend = meta_get_backend ();
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
MetaRendererView *legacy_view;
cairo_rectangle_int_t view_layout;
CoglOffscreen *fake_onscreen;
legacy_view = get_legacy_view (renderer);
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (legacy_view),
&view_layout);
if (view_layout.width == width &&
view_layout.height == height)
return;
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height
};
fake_onscreen = create_offscreen (cogl_context, width, height);
g_object_set (G_OBJECT (legacy_view),
"layout", &view_layout,
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
NULL);
}
void
meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11_nested,
int width,
int height)
{
MetaRenderer *renderer = META_RENDERER (renderer_x11_nested);
MetaBackend *backend = meta_get_backend ();
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;
CoglOffscreen *fake_onscreen;
MetaRendererView *legacy_view;
if (get_legacy_view (renderer))
{
meta_renderer_x11_nested_resize_legacy_view (renderer_x11_nested,
width, height);
return;
}
fake_onscreen = create_offscreen (cogl_context, width, height);
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height
};
legacy_view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &view_layout,
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
NULL);
meta_renderer_set_legacy_view (renderer, legacy_view);
}
static MetaRendererView * static MetaRendererView *
meta_renderer_x11_nested_create_view (MetaRenderer *renderer, meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
MetaLogicalMonitor *logical_monitor) MetaLogicalMonitor *logical_monitor)
@ -77,10 +175,8 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
MetaMonitorTransform view_transform; MetaMonitorTransform view_transform;
int view_scale; int view_scale;
int width, height; int width, height;
CoglTexture2D *texture_2d;
CoglOffscreen *fake_onscreen; CoglOffscreen *fake_onscreen;
CoglOffscreen *offscreen; CoglOffscreen *offscreen;
GError *error = NULL;
view_transform = calculate_view_transform (monitor_manager, logical_monitor); view_transform = calculate_view_transform (monitor_manager, logical_monitor);
@ -89,26 +185,25 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
else else
view_scale = 1; view_scale = 1;
width = logical_monitor->rect.width * view_scale; if (meta_monitor_transform_is_rotated (view_transform))
height = logical_monitor->rect.height * view_scale;
texture_2d = cogl_texture_2d_new_with_size (cogl_context, width, height);
fake_onscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture_2d));
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (fake_onscreen), &error))
meta_fatal ("Couldn't allocate framebuffer: %s", error->message);
if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
{ {
texture_2d = cogl_texture_2d_new_with_size (cogl_context, width, height); width = logical_monitor->rect.height;
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture_2d)); height = logical_monitor->rect.width;
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), &error))
meta_fatal ("Couldn't allocate offscreen framebuffer: %s", error->message);
} }
else else
{ {
offscreen = NULL; width = logical_monitor->rect.width;
height = logical_monitor->rect.height;
} }
width *= view_scale;
height *= view_scale;
fake_onscreen = create_offscreen (cogl_context, width, height);
if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
offscreen = create_offscreen (cogl_context, width, height);
else
offscreen = NULL;
return g_object_new (META_TYPE_RENDERER_VIEW, return g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &logical_monitor->rect, "layout", &logical_monitor->rect,

View File

@ -30,4 +30,8 @@ G_DECLARE_FINAL_TYPE (MetaRendererX11Nested, meta_renderer_x11_nested,
META, RENDERER_X11_NESTED, META, RENDERER_X11_NESTED,
MetaRendererX11) MetaRendererX11)
void meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11_nested,
int width,
int height);
#endif /* META_RENDERER_X11_NESTED_H */ #endif /* META_RENDERER_X11_NESTED_H */