renderer-native: Draw stage separately per CRTC

Prior to this commit the stage was drawn separately for each logical
monitor. This allowed to draw different parts of the stage with
different transformations, e.g. with a different viewport to implement
HiDPI support.

Go even further and have one view per CRTC. This causes the stage to
e.g. draw two mirrored monitors twice, instead of using the same
framebuffer on both. This enables us to do two things: one is to support
tiled monitors and monitor mirroring using the EGLStreams backend; the
other is that it'll enable us to tie rendering directly to the CRTC it
will render for. It is also a requirement for rendering being affected
by CRTC state, such as gamma.

It'll be possible to still inhibit re-drawing of the same content
twice, but it should be implemented differently, so that it will still
be possible to implement features requiring the CRTC split.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042
This commit is contained in:
Jonas Ådahl 2020-01-17 21:08:02 +01:00
parent e3f30371aa
commit 1c98f01a65
11 changed files with 313 additions and 770 deletions

View File

@ -4476,49 +4476,42 @@ capture_view_into (ClutterStage *stage,
cogl_object_unref (bitmap); cogl_object_unref (bitmap);
} }
static ClutterStageView *
get_view_at_rect (ClutterStage *stage,
cairo_rectangle_int_t *rect)
{
ClutterStagePrivate *priv = stage->priv;
GList *views = _clutter_stage_window_get_views (priv->impl);
GList *l;
for (l = views; l; l = l->next)
{
ClutterStageView *view = l->data;
cairo_rectangle_int_t view_layout;
cairo_region_t *region;
cairo_rectangle_int_t view_capture_rect;
clutter_stage_view_get_layout (view, &view_layout);
region = cairo_region_create_rectangle (&view_layout);
cairo_region_intersect_rectangle (region, rect);
cairo_region_get_extents (region, &view_capture_rect);
cairo_region_destroy (region);
if (view_capture_rect.width == 0 || view_capture_rect.height == 0)
continue;
g_assert (view_capture_rect.width == rect->width &&
view_capture_rect.height == rect->height);
return view;
}
return NULL;
}
void void
clutter_stage_capture_into (ClutterStage *stage, clutter_stage_capture_into (ClutterStage *stage,
gboolean paint, gboolean paint,
cairo_rectangle_int_t *rect, cairo_rectangle_int_t *rect,
uint8_t *data) uint8_t *data)
{ {
ClutterStageView *view; ClutterStagePrivate *priv = stage->priv;
GList *l;
int bpp = 4; int bpp = 4;
int stride;
view = get_view_at_rect (stage, rect); stride = rect->width * 4;
capture_view_into (stage, paint, view, rect, data, rect->width * bpp);
for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next)
{
ClutterStageView *view = l->data;
cairo_rectangle_int_t view_layout;
cairo_region_t *region;
cairo_rectangle_int_t capture_rect;
int x_offset, y_offset;
clutter_stage_view_get_layout (view, &view_layout);
region = cairo_region_create_rectangle (&view_layout);
cairo_region_intersect_rectangle (region, rect);
cairo_region_get_extents (region, &capture_rect);
cairo_region_destroy (region);
x_offset = capture_rect.x - rect->x;
y_offset = capture_rect.y - rect->y;
capture_view_into (stage, paint, view,
&capture_rect,
data + (x_offset * bpp) + (y_offset * stride),
stride);
}
} }
/** /**

View File

@ -39,7 +39,6 @@ enum
{ {
PROP_0, PROP_0,
PROP_MONITOR_INFO,
PROP_TRANSFORM, PROP_TRANSFORM,
PROP_LAST PROP_LAST
@ -52,18 +51,11 @@ struct _MetaRendererView
ClutterStageViewCogl parent; ClutterStageViewCogl parent;
MetaMonitorTransform transform; MetaMonitorTransform transform;
MetaLogicalMonitor *logical_monitor;
}; };
G_DEFINE_TYPE (MetaRendererView, meta_renderer_view, G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
CLUTTER_TYPE_STAGE_VIEW_COGL) CLUTTER_TYPE_STAGE_VIEW_COGL)
MetaLogicalMonitor *
meta_renderer_view_get_logical_monitor (MetaRendererView *view)
{
return view->logical_monitor;
}
MetaMonitorTransform MetaMonitorTransform
meta_renderer_view_get_transform (MetaRendererView *view) meta_renderer_view_get_transform (MetaRendererView *view)
{ {
@ -146,9 +138,6 @@ meta_renderer_view_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_MONITOR_INFO:
g_value_set_pointer (value, view->logical_monitor);
break;
case PROP_TRANSFORM: case PROP_TRANSFORM:
g_value_set_uint (value, view->transform); g_value_set_uint (value, view->transform);
break; break;
@ -168,9 +157,6 @@ meta_renderer_view_set_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_MONITOR_INFO:
view->logical_monitor = g_value_get_pointer (value);
break;
case PROP_TRANSFORM: case PROP_TRANSFORM:
meta_renderer_view_set_transform (view, g_value_get_uint (value)); meta_renderer_view_set_transform (view, g_value_get_uint (value));
break; break;
@ -199,13 +185,6 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
object_class->get_property = meta_renderer_view_get_property; object_class->get_property = meta_renderer_view_get_property;
object_class->set_property = meta_renderer_view_set_property; object_class->set_property = meta_renderer_view_set_property;
obj_props[PROP_MONITOR_INFO] =
g_param_spec_pointer ("logical-monitor",
"MetaLogicalMonitor",
"The logical monitor of the view",
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS |
G_PARAM_CONSTRUCT_ONLY);
obj_props[PROP_TRANSFORM] = obj_props[PROP_TRANSFORM] =
g_param_spec_uint ("transform", g_param_spec_uint ("transform",
"Transform", "Transform",

View File

@ -26,8 +26,6 @@ G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view,
META, RENDERER_VIEW, META, RENDERER_VIEW,
ClutterStageViewCogl) ClutterStageViewCogl)
MetaLogicalMonitor *meta_renderer_view_get_logical_monitor (MetaRendererView *view);
MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view); MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view);
#endif /* META_RENDERER_VIEW_H */ #endif /* META_RENDERER_VIEW_H */

View File

@ -47,6 +47,7 @@
#include <glib-object.h> #include <glib-object.h>
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/meta-logical-monitor.h"
enum enum
{ {
@ -93,10 +94,14 @@ meta_renderer_create_cogl_renderer (MetaRenderer *renderer)
static MetaRendererView * static MetaRendererView *
meta_renderer_create_view (MetaRenderer *renderer, meta_renderer_create_view (MetaRenderer *renderer,
MetaLogicalMonitor *logical_monitor) MetaLogicalMonitor *logical_monitor,
MetaOutput *output,
MetaCrtc *crtc)
{ {
return META_RENDERER_GET_CLASS (renderer)->create_view (renderer, return META_RENDERER_GET_CLASS (renderer)->create_view (renderer,
logical_monitor); logical_monitor,
output,
crtc);
} }
/** /**
@ -114,6 +119,21 @@ meta_renderer_rebuild_views (MetaRenderer *renderer)
return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer); return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer);
} }
static void
create_crtc_view (MetaLogicalMonitor *logical_monitor,
MetaMonitor *monitor,
MetaOutput *output,
MetaCrtc *crtc,
gpointer user_data)
{
MetaRenderer *renderer = user_data;
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
MetaRendererView *view;
view = meta_renderer_create_view (renderer, logical_monitor, output, crtc);
priv->views = g_list_append (priv->views, view);
}
static void static void
meta_renderer_real_rebuild_views (MetaRenderer *renderer) meta_renderer_real_rebuild_views (MetaRenderer *renderer)
{ {
@ -132,10 +152,10 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
for (l = logical_monitors; l; l = l->next) for (l = logical_monitors; l; l = l->next)
{ {
MetaLogicalMonitor *logical_monitor = l->data; MetaLogicalMonitor *logical_monitor = l->data;
MetaRendererView *view;
view = meta_renderer_create_view (renderer, logical_monitor); meta_logical_monitor_foreach_crtc (logical_monitor,
priv->views = g_list_append (priv->views, view); create_crtc_view,
renderer);
} }
} }
@ -168,24 +188,6 @@ meta_renderer_get_views (MetaRenderer *renderer)
return priv->views; return priv->views;
} }
MetaRendererView *
meta_renderer_get_view_from_logical_monitor (MetaRenderer *renderer,
MetaLogicalMonitor *logical_monitor)
{
GList *l;
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
MetaRendererView *view = l->data;
if (meta_renderer_view_get_logical_monitor (view) ==
logical_monitor)
return view;
}
return NULL;
}
gboolean gboolean
meta_renderer_is_hardware_accelerated (MetaRenderer *renderer) meta_renderer_is_hardware_accelerated (MetaRenderer *renderer)
{ {

View File

@ -42,7 +42,9 @@ struct _MetaRendererClass
CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer); CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer);
MetaRendererView * (* create_view) (MetaRenderer *renderer, MetaRendererView * (* create_view) (MetaRenderer *renderer,
MetaLogicalMonitor *logical_monitor); MetaLogicalMonitor *logical_monitor,
MetaOutput *output,
MetaCrtc *crtc);
void (* rebuild_views) (MetaRenderer *renderer); void (* rebuild_views) (MetaRenderer *renderer);
}; };
@ -58,9 +60,6 @@ void meta_renderer_set_legacy_view (MetaRenderer *renderer,
META_EXPORT_TEST META_EXPORT_TEST
GList * meta_renderer_get_views (MetaRenderer *renderer); GList * meta_renderer_get_views (MetaRenderer *renderer);
MetaRendererView * meta_renderer_get_view_from_logical_monitor (MetaRenderer *renderer,
MetaLogicalMonitor *logical_monitor);
gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer); gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer);
#endif /* META_RENDERER_H */ #endif /* META_RENDERER_H */

View File

@ -42,9 +42,9 @@ struct _MetaScreenCastMonitorStreamSrc
MetaScreenCastStreamSrc parent; MetaScreenCastStreamSrc parent;
gboolean cursor_bitmap_invalid; gboolean cursor_bitmap_invalid;
gboolean hw_cursor_inhibited;
MetaStageWatch *paint_watch; GList *watches;
MetaStageWatch *after_paint_watch;
gulong cursor_moved_handler_id; gulong cursor_moved_handler_id;
gulong cursor_changed_handler_id; gulong cursor_changed_handler_id;
@ -226,9 +226,13 @@ inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
MetaCursorRenderer *cursor_renderer; MetaCursorRenderer *cursor_renderer;
MetaHwCursorInhibitor *inhibitor; MetaHwCursorInhibitor *inhibitor;
g_return_if_fail (!monitor_src->hw_cursor_inhibited);
cursor_renderer = get_cursor_renderer (monitor_src); cursor_renderer = get_cursor_renderer (monitor_src);
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src); inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor); meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
monitor_src->hw_cursor_inhibited = TRUE;
} }
static void static void
@ -237,9 +241,53 @@ uninhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
MetaCursorRenderer *cursor_renderer; MetaCursorRenderer *cursor_renderer;
MetaHwCursorInhibitor *inhibitor; MetaHwCursorInhibitor *inhibitor;
g_return_if_fail (monitor_src->hw_cursor_inhibited);
cursor_renderer = get_cursor_renderer (monitor_src); cursor_renderer = get_cursor_renderer (monitor_src);
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src); inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor); meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
monitor_src->hw_cursor_inhibited = FALSE;
}
static void
add_view_painted_watches (MetaScreenCastMonitorStreamSrc *monitor_src,
MetaStageWatchPhase watch_phase)
{
MetaBackend *backend = get_backend (monitor_src);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
ClutterStage *stage;
MetaStage *meta_stage;
MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor;
MetaRectangle logical_monitor_layout;
GList *l;
stage = get_stage (monitor_src);
meta_stage = META_STAGE (stage);
monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
MetaRendererView *view = l->data;
MetaRectangle view_layout;
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
if (meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
{
MetaStageWatch *watch;
watch = meta_stage_watch_view (meta_stage,
CLUTTER_STAGE_VIEW (view),
watch_phase,
stage_painted,
monitor_src);
monitor_src->watches = g_list_prepend (monitor_src->watches, watch);
}
}
} }
static void static void
@ -248,28 +296,12 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
MetaScreenCastMonitorStreamSrc *monitor_src = MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (src); META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
MetaBackend *backend = get_backend (monitor_src); MetaBackend *backend = get_backend (monitor_src);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
MetaRendererView *view;
MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor;
MetaStage *meta_stage;
ClutterStageView *stage_view;
ClutterStage *stage; ClutterStage *stage;
MetaScreenCastStream *stream; MetaScreenCastStream *stream;
stream = meta_screen_cast_stream_src_get_stream (src); stream = meta_screen_cast_stream_src_get_stream (src);
stage = get_stage (monitor_src); stage = get_stage (monitor_src);
meta_stage = META_STAGE (stage);
monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
view = meta_renderer_get_view_from_logical_monitor (renderer,
logical_monitor);
if (view)
stage_view = CLUTTER_STAGE_VIEW (view);
else
stage_view = NULL;
switch (meta_screen_cast_stream_get_cursor_mode (stream)) switch (meta_screen_cast_stream_get_cursor_mode (stream))
{ {
@ -284,21 +316,13 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
monitor_src); monitor_src);
G_GNUC_FALLTHROUGH; G_GNUC_FALLTHROUGH;
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
monitor_src->paint_watch = add_view_painted_watches (monitor_src,
meta_stage_watch_view (meta_stage, META_STAGE_WATCH_AFTER_ACTOR_PAINT);
stage_view,
META_STAGE_WATCH_AFTER_ACTOR_PAINT,
stage_painted,
monitor_src);
break; break;
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
inhibit_hw_cursor (monitor_src); inhibit_hw_cursor (monitor_src);
monitor_src->after_paint_watch = add_view_painted_watches (monitor_src,
meta_stage_watch_view (meta_stage, META_STAGE_WATCH_AFTER_PAINT);
stage_view,
META_STAGE_WATCH_AFTER_PAINT,
stage_painted,
monitor_src);
break; break;
} }
@ -314,22 +338,21 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
ClutterStage *stage; ClutterStage *stage;
MetaStage *meta_stage; MetaStage *meta_stage;
GList *l;
stage = get_stage (monitor_src); stage = get_stage (monitor_src);
meta_stage = META_STAGE (stage); meta_stage = META_STAGE (stage);
if (monitor_src->paint_watch) for (l = monitor_src->watches; l; l = l->next)
{ {
meta_stage_remove_watch (meta_stage, monitor_src->paint_watch); MetaStageWatch *watch = l->data;
monitor_src->paint_watch = NULL;
}
if (monitor_src->after_paint_watch) meta_stage_remove_watch (meta_stage, watch);
{
meta_stage_remove_watch (meta_stage, monitor_src->after_paint_watch);
monitor_src->after_paint_watch = NULL;
uninhibit_hw_cursor (monitor_src);
} }
g_clear_pointer (&monitor_src->watches, g_list_free);
if (monitor_src->hw_cursor_inhibited)
uninhibit_hw_cursor (monitor_src);
g_clear_signal_handler (&monitor_src->cursor_moved_handler_id, g_clear_signal_handler (&monitor_src->cursor_moved_handler_id,
cursor_tracker); cursor_tracker);
@ -367,13 +390,11 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
MetaBackend *backend = get_backend (monitor_src); MetaBackend *backend = get_backend (monitor_src);
MetaCursorRenderer *cursor_renderer = MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (backend); meta_backend_get_cursor_renderer (backend);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaCursorSprite *cursor_sprite; MetaCursorSprite *cursor_sprite;
MetaMonitor *monitor; MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor; MetaLogicalMonitor *logical_monitor;
MetaRectangle logical_monitor_layout; MetaRectangle logical_monitor_layout;
graphene_rect_t logical_monitor_rect; graphene_rect_t logical_monitor_rect;
MetaRendererView *view;
float view_scale; float view_scale;
graphene_point_t cursor_position; graphene_point_t cursor_position;
int x, y; int x, y;
@ -393,10 +414,8 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
logical_monitor_rect = logical_monitor_rect =
meta_rectangle_to_graphene_rect (&logical_monitor_layout); meta_rectangle_to_graphene_rect (&logical_monitor_layout);
view = meta_renderer_get_view_from_logical_monitor (renderer, if (meta_is_stage_views_scaled ())
logical_monitor); view_scale = meta_logical_monitor_get_scale (logical_monitor);
if (view)
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
else else
view_scale = 1.0; view_scale = 1.0;

View File

@ -76,14 +76,10 @@ meta_crtc_kms_apply_transform (MetaCrtc *crtc,
void void
meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc, meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
MetaMonitor *monitor,
MetaOutput *output,
uint32_t fb_id, uint32_t fb_id,
MetaKmsUpdate *kms_update) MetaKmsUpdate *kms_update)
{ {
MetaMonitorMode *monitor_mode;
MetaCrtcConfig *crtc_config; MetaCrtcConfig *crtc_config;
int crtc_x, crtc_y;
MetaFixed16Rectangle src_rect; MetaFixed16Rectangle src_rect;
MetaFixed16Rectangle dst_rect; MetaFixed16Rectangle dst_rect;
MetaKmsAssignPlaneFlag flags; MetaKmsAssignPlaneFlag flags;
@ -94,17 +90,10 @@ meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
crtc_config = crtc->config; crtc_config = crtc->config;
monitor_mode = meta_monitor_get_current_mode (monitor);
meta_monitor_calculate_crtc_pos (monitor,
monitor_mode,
output,
crtc_config->transform,
&crtc_x,
&crtc_y);
src_rect = (MetaFixed16Rectangle) { src_rect = (MetaFixed16Rectangle) {
.x = meta_fixed_16_from_int (crtc_x), .x = meta_fixed_16_from_int (0),
.y = meta_fixed_16_from_int (crtc_y), .y = meta_fixed_16_from_int (0),
.width = meta_fixed_16_from_int (crtc_config->mode->width), .width = meta_fixed_16_from_int (crtc_config->mode->width),
.height = meta_fixed_16_from_int (crtc_config->mode->height), .height = meta_fixed_16_from_int (crtc_config->mode->height),
}; };

View File

@ -38,8 +38,6 @@ void meta_crtc_kms_apply_transform (MetaCrtc *crtc,
MetaKmsPlaneAssignment *kms_plane_assignment); MetaKmsPlaneAssignment *kms_plane_assignment);
void meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc, void meta_crtc_kms_assign_primary_plane (MetaCrtc *crtc,
MetaMonitor *monitor,
MetaOutput *output,
uint32_t fb_id, uint32_t fb_id,
MetaKmsUpdate *kms_update); MetaKmsUpdate *kms_update);

File diff suppressed because it is too large Load Diff

View File

@ -172,7 +172,9 @@ meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11
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,
MetaOutput *output,
MetaCrtc *crtc)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
@ -184,6 +186,8 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
int width, height; int width, height;
CoglOffscreen *fake_onscreen; CoglOffscreen *fake_onscreen;
CoglOffscreen *offscreen; CoglOffscreen *offscreen;
MetaRectangle view_layout;
MetaRendererView *view;
view_transform = calculate_view_transform (monitor_manager, logical_monitor); view_transform = calculate_view_transform (monitor_manager, logical_monitor);
@ -192,18 +196,8 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
else else
view_scale = 1.0; view_scale = 1.0;
if (meta_monitor_transform_is_rotated (view_transform)) width = roundf (crtc->config->layout.size.width * view_scale);
{ height = roundf (crtc->config->layout.size.height * view_scale);
width = logical_monitor->rect.height;
height = logical_monitor->rect.width;
}
else
{
width = logical_monitor->rect.width;
height = logical_monitor->rect.height;
}
width = roundf (width * view_scale);
height = roundf (height * view_scale);
fake_onscreen = create_offscreen (cogl_context, width, height); fake_onscreen = create_offscreen (cogl_context, width, height);
@ -212,14 +206,20 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer,
else else
offscreen = NULL; offscreen = NULL;
return g_object_new (META_TYPE_RENDERER_VIEW, meta_rectangle_from_graphene_rect (&crtc->config->layout,
"layout", &logical_monitor->rect, META_ROUNDING_STRATEGY_ROUND,
&view_layout);
view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &view_layout,
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen), "framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
"offscreen", COGL_FRAMEBUFFER (offscreen), "offscreen", COGL_FRAMEBUFFER (offscreen),
"transform", view_transform, "transform", view_transform,
"scale", view_scale, "scale", view_scale,
"logical-monitor", logical_monitor,
NULL); NULL);
g_object_set_data (G_OBJECT (view), "crtc", crtc);
return view;
} }
static void static void

View File

@ -101,46 +101,33 @@ typedef struct
} DrawCrtcData; } DrawCrtcData;
static gboolean static gboolean
draw_crtc (MetaMonitor *monitor, draw_view (MetaStageX11Nested *stage_nested,
MetaMonitorMode *monitor_mode, MetaRendererView *renderer_view,
MetaMonitorCrtcMode *monitor_crtc_mode, CoglTexture *texture)
gpointer user_data,
GError **error)
{ {
DrawCrtcData *data = user_data; MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_nested);
MetaStageX11 *stage_x11 = META_STAGE_X11 (data->stage_nested);
CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen); CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen);
CoglTexture *texture = data->texture; ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view);
MetaLogicalMonitor *logical_monitor = data->logical_monitor;
MetaOutput *output = monitor_crtc_mode->output;
MetaCrtc *crtc; MetaCrtc *crtc;
MetaCrtcConfig *crtc_config; MetaCrtcConfig *crtc_config;
MetaRendererView *renderer_view = META_RENDERER_VIEW (data->view);
MetaMonitorTransform view_transform;
MetaMonitorTransform layout_transform = META_MONITOR_TRANSFORM_NORMAL;
cairo_rectangle_int_t view_layout;
CoglMatrix projection_matrix; CoglMatrix projection_matrix;
CoglMatrix transform; CoglMatrix transform;
float texture_width, texture_height; float texture_width, texture_height;
float sample_x, sample_y, sample_width, sample_height; float sample_x, sample_y, sample_width, sample_height;
float scale;
int viewport_x, viewport_y;
int viewport_width, viewport_height;
float s_1, t_1, s_2, t_2; float s_1, t_1, s_2, t_2;
texture_width = cogl_texture_get_width (texture); texture_width = cogl_texture_get_width (texture);
texture_height = cogl_texture_get_height (texture); texture_height = cogl_texture_get_height (texture);
crtc = meta_output_get_assigned_crtc (output); crtc = g_object_get_data (G_OBJECT (renderer_view), "crtc");
crtc_config = crtc->config; crtc_config = crtc->config;
clutter_stage_view_get_layout (data->view, &view_layout); sample_x = 0;
sample_x = (int) roundf (crtc_config->layout.origin.x) - view_layout.x; sample_y = 0;
sample_y = (int) roundf (crtc_config->layout.origin.y) - view_layout.y; sample_width = texture_width;
sample_width = (int) roundf (crtc_config->layout.size.width); sample_height = texture_height;
sample_height = (int) roundf (crtc_config->layout.size.height);
clutter_stage_view_get_offscreen_transformation_matrix (data->view, clutter_stage_view_get_offscreen_transformation_matrix (stage_view,
&transform); &transform);
cogl_framebuffer_push_matrix (onscreen); cogl_framebuffer_push_matrix (onscreen);
@ -156,62 +143,14 @@ draw_crtc (MetaMonitor *monitor,
s_2 = (sample_x + sample_width) / texture_width; s_2 = (sample_x + sample_width) / texture_width;
t_2 = (sample_y + sample_height) / texture_height; t_2 = (sample_y + sample_height) / texture_height;
view_transform = meta_renderer_view_get_transform (renderer_view);
if (view_transform == logical_monitor->transform)
{
switch (view_transform)
{
case META_MONITOR_TRANSFORM_NORMAL:
case META_MONITOR_TRANSFORM_FLIPPED:
layout_transform = META_MONITOR_TRANSFORM_NORMAL;
break;
case META_MONITOR_TRANSFORM_270:
case META_MONITOR_TRANSFORM_FLIPPED_270:
layout_transform = META_MONITOR_TRANSFORM_90;
break;
case META_MONITOR_TRANSFORM_180:
case META_MONITOR_TRANSFORM_FLIPPED_180:
layout_transform = META_MONITOR_TRANSFORM_180;
break;
case META_MONITOR_TRANSFORM_90:
case META_MONITOR_TRANSFORM_FLIPPED_90:
layout_transform = META_MONITOR_TRANSFORM_270;
break;
}
}
else
{
layout_transform = logical_monitor->transform;
}
meta_monitor_calculate_crtc_pos (monitor, monitor_mode, output,
layout_transform,
&viewport_x,
&viewport_y);
viewport_x += logical_monitor->rect.x;
viewport_y += logical_monitor->rect.y;
if (meta_monitor_transform_is_rotated (logical_monitor->transform))
{
viewport_width = monitor_crtc_mode->crtc_mode->height;
viewport_height = monitor_crtc_mode->crtc_mode->width;
}
else
{
viewport_width = monitor_crtc_mode->crtc_mode->width;
viewport_height = monitor_crtc_mode->crtc_mode->height;
}
scale = clutter_stage_view_get_scale (data->view);
viewport_width = roundf (viewport_width / scale);
viewport_height = roundf (viewport_height / scale);
cogl_framebuffer_set_viewport (onscreen, cogl_framebuffer_set_viewport (onscreen,
viewport_x, viewport_y, crtc_config->layout.origin.x,
viewport_width, viewport_height); crtc_config->layout.origin.y,
crtc_config->layout.size.width,
crtc_config->layout.size.height);
cogl_framebuffer_draw_textured_rectangle (onscreen, cogl_framebuffer_draw_textured_rectangle (onscreen,
data->stage_nested->pipeline, stage_nested->pipeline,
0, 0, 1, 1, 0, 0, 1, 1,
s_1, t_1, s_2, t_2); s_1, t_1, s_2, t_2);
@ -219,32 +158,6 @@ draw_crtc (MetaMonitor *monitor,
return TRUE; return TRUE;
} }
static void
draw_logical_monitor (MetaStageX11Nested *stage_nested,
MetaLogicalMonitor *logical_monitor,
CoglTexture *texture,
ClutterStageView *view,
cairo_rectangle_int_t *view_layout)
{
MetaMonitor *monitor;
MetaMonitorMode *current_mode;
cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
current_mode = meta_monitor_get_current_mode (monitor);
meta_monitor_mode_foreach_crtc (monitor, current_mode,
draw_crtc,
&(DrawCrtcData) {
.stage_nested = stage_nested,
.texture = texture,
.view = view,
.logical_monitor = logical_monitor
},
NULL);
}
static void static void
meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window) meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
{ {
@ -267,39 +180,17 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
{ {
ClutterStageView *view = l->data; ClutterStageView *view = l->data;
MetaRendererView *renderer_view = META_RENDERER_VIEW (view); MetaRendererView *renderer_view = META_RENDERER_VIEW (view);
MetaLogicalMonitor *logical_monitor;
cairo_rectangle_int_t view_layout;
CoglFramebuffer *framebuffer; CoglFramebuffer *framebuffer;
CoglTexture *texture; CoglTexture *texture;
clutter_stage_view_get_layout (view, &view_layout);
framebuffer = clutter_stage_view_get_onscreen (view); framebuffer = clutter_stage_view_get_onscreen (view);
texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer)); texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer));
cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture); cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture);
cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0,
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
logical_monitor = meta_renderer_view_get_logical_monitor (renderer_view); draw_view (stage_nested, renderer_view, texture);
if (logical_monitor)
{
draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
}
else
{
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
GList *logical_monitors;
GList *k;
logical_monitors =
meta_monitor_manager_get_logical_monitors (monitor_manager);
for (k = logical_monitors; k; k = k->next)
{
logical_monitor = k->data;
draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
}
}
} }
cogl_onscreen_swap_buffers (stage_x11->onscreen); cogl_onscreen_swap_buffers (stage_x11->onscreen);