diff --git a/src/backends/x11/meta-stage-x11-nested.c b/src/backends/x11/meta-stage-x11-nested.c index b2732c345..cf3b92029 100644 --- a/src/backends/x11/meta-stage-x11-nested.c +++ b/src/backends/x11/meta-stage-x11-nested.c @@ -27,6 +27,8 @@ #include "backends/x11/meta-stage-x11-nested.h" #include "backends/meta-backend-private.h" +#include "backends/meta-logical-monitor.h" +#include "backends/meta-monitor.h" #include "backends/meta-renderer.h" #include "backends/x11/nested/meta-renderer-x11-nested.h" #include "clutter/clutter-mutter.h" @@ -88,6 +90,149 @@ meta_stage_x11_nested_get_views (ClutterStageWindow *stage_window) return meta_renderer_get_views (renderer); } +typedef struct +{ + MetaStageX11Nested *stage_nested; + CoglTexture *texture; + ClutterStageView *view; + MetaLogicalMonitor *logical_monitor; +} DrawCrtcData; + +static gboolean +draw_crtc (MetaMonitor *monitor, + MetaMonitorMode *monitor_mode, + MetaMonitorCrtcMode *monitor_crtc_mode, + gpointer user_data, + GError **error) +{ + DrawCrtcData *data = user_data; + ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (data->stage_nested); + CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen); + CoglTexture *texture = data->texture; + MetaLogicalMonitor *logical_monitor = data->logical_monitor; + MetaOutput *output = monitor_crtc_mode->output; + MetaCrtc *crtc = output->crtc; + 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 transform; + float texture_width, texture_height; + float sample_x, sample_y, sample_width, sample_height; + int viewport_x, viewport_y; + int viewport_width, viewport_height; + float s_1, t_1, s_2, t_2; + + texture_width = cogl_texture_get_width (texture); + texture_height = cogl_texture_get_height (texture); + + clutter_stage_view_get_layout (data->view, &view_layout); + sample_x = crtc->rect.x - view_layout.x; + sample_y = crtc->rect.y - view_layout.y; + sample_width = crtc->rect.width; + sample_height = crtc->rect.height; + + clutter_stage_view_get_offscreen_transformation_matrix (data->view, + &transform); + + cogl_framebuffer_push_matrix (onscreen); + cogl_matrix_init_identity (&projection_matrix); + cogl_matrix_translate (&projection_matrix, -1, 1, 0); + cogl_matrix_scale (&projection_matrix, 2, -2, 0); + + cogl_matrix_multiply (&projection_matrix, &projection_matrix, &transform); + cogl_framebuffer_set_projection_matrix (onscreen, &projection_matrix); + + s_1 = sample_x / texture_width; + t_1 = sample_y / texture_height; + s_2 = (sample_x + sample_width) / texture_width; + 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; + } + cogl_framebuffer_set_viewport (onscreen, + viewport_x, viewport_y, + viewport_width, viewport_height); + + cogl_framebuffer_draw_textured_rectangle (onscreen, + data->stage_nested->pipeline, + 0, 0, 1, 1, + s_1, t_1, s_2, t_2); + + cogl_framebuffer_pop_matrix (onscreen); + 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 meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window) { @@ -109,29 +254,40 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window) for (l = meta_renderer_get_views (renderer); l; l = l->next) { ClutterStageView *view = l->data; + MetaRendererView *renderer_view = META_RENDERER_VIEW (view); + MetaLogicalMonitor *logical_monitor; cairo_rectangle_int_t view_layout; CoglFramebuffer *framebuffer; CoglTexture *texture; - CoglMatrix matrix; clutter_stage_view_get_layout (view, &view_layout); framebuffer = clutter_stage_view_get_onscreen (view); texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer)); - clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); - cogl_matrix_get_inverse (&matrix, &matrix); - cogl_pipeline_set_layer_matrix (stage_nested->pipeline, 0, &matrix); - - cogl_framebuffer_set_viewport (onscreen, - view_layout.x, - view_layout.y, - view_layout.width, - view_layout.height); cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture); - cogl_framebuffer_draw_rectangle (onscreen, - stage_nested->pipeline, - -1, 1, 1, -1); + + logical_monitor = meta_renderer_view_get_logical_monitor (renderer_view); + 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); diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c index 8162062d6..884325214 100644 --- a/src/backends/x11/nested/meta-renderer-x11-nested.c +++ b/src/backends/x11/nested/meta-renderer-x11-nested.c @@ -211,6 +211,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer, "offscreen", COGL_FRAMEBUFFER (offscreen), "transform", view_transform, "scale", view_scale, + "logical-monitor", logical_monitor, NULL); }