Compare commits
12 Commits
3.23.3
...
wip/garnac
Author | SHA1 | Date | |
---|---|---|---|
cb16822780 | |||
06112b1b0f | |||
c7ff89bb01 | |||
f36ae220c1 | |||
8a50db5959 | |||
8f05b0e020 | |||
534f3aa5c9 | |||
f1a0985e3a | |||
6302ffe8ac | |||
acc2ad9658 | |||
d58f94dd47 | |||
c63558dded |
@ -27,6 +27,7 @@ enum
|
||||
|
||||
PROP_LAYOUT,
|
||||
PROP_FRAMEBUFFER,
|
||||
PROP_OFFSCREEN,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@ -37,6 +38,10 @@ typedef struct _ClutterStageViewPrivate
|
||||
{
|
||||
cairo_rectangle_int_t layout;
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
CoglOffscreen *offscreen;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
guint dirty_viewport : 1;
|
||||
guint dirty_projection : 1;
|
||||
} ClutterStageViewPrivate;
|
||||
@ -55,6 +60,18 @@ clutter_stage_view_get_layout (ClutterStageView *view,
|
||||
|
||||
CoglFramebuffer *
|
||||
clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
if (priv->offscreen)
|
||||
return priv->offscreen;
|
||||
else
|
||||
return priv->framebuffer;
|
||||
}
|
||||
|
||||
CoglFramebuffer *
|
||||
clutter_stage_view_get_onscreen (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
@ -62,6 +79,108 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
||||
return priv->framebuffer;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
ClutterStageViewClass *view_class =
|
||||
CLUTTER_STAGE_VIEW_GET_CLASS (view);
|
||||
|
||||
g_assert (priv->offscreen != NULL);
|
||||
|
||||
if (priv->pipeline)
|
||||
return;
|
||||
|
||||
priv->pipeline =
|
||||
cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
|
||||
cogl_pipeline_set_layer_filters (priv->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0,
|
||||
cogl_offscreen_get_texture (priv->offscreen));
|
||||
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
if (view_class->setup_offscreen_blit_pipeline)
|
||||
view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_rect_to_onscreen (ClutterStageView *view,
|
||||
const cairo_rectangle_t *rect,
|
||||
cairo_rectangle_t *rect_out)
|
||||
{
|
||||
float x1, y1, x2, y2;
|
||||
|
||||
x1 = rect->x;
|
||||
y1 = rect->y;
|
||||
clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
|
||||
|
||||
x2 = rect->x + rect->width;
|
||||
y2 = rect->y + rect->height;
|
||||
clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
|
||||
|
||||
*rect_out = (cairo_rectangle_t) {
|
||||
.x = MIN (x1, x2),
|
||||
.y = MIN (y1, y2),
|
||||
.width = ABS (x2 - x1),
|
||||
.height = ABS (y2 - y1)
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
cairo_rectangle_t texture_rect, onscreen_rect;
|
||||
CoglMatrix matrix;
|
||||
|
||||
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
|
||||
cogl_framebuffer_push_matrix (priv->framebuffer);
|
||||
|
||||
/* Set transform so 0,0 is on the top left corner and 1,1 on
|
||||
* the bottom right corner.
|
||||
*/
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
cogl_matrix_translate (&matrix, -1, 1, 0);
|
||||
cogl_matrix_scale (&matrix, 2, -2, 0);
|
||||
cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
|
||||
|
||||
texture_rect = (cairo_rectangle_t) {
|
||||
.x = (double) rect->x / cogl_framebuffer_get_width (priv->offscreen),
|
||||
.y = (double) rect->y / cogl_framebuffer_get_height (priv->offscreen),
|
||||
.width = (double) rect->width / cogl_framebuffer_get_width (priv->offscreen),
|
||||
.height = (double) rect->height / cogl_framebuffer_get_height (priv->offscreen)
|
||||
};
|
||||
|
||||
transform_rect_to_onscreen (view, &texture_rect, &onscreen_rect);
|
||||
|
||||
cogl_framebuffer_draw_textured_rectangle (priv->framebuffer,
|
||||
priv->pipeline,
|
||||
onscreen_rect.x,
|
||||
onscreen_rect.y,
|
||||
onscreen_rect.x + onscreen_rect.width,
|
||||
onscreen_rect.y + onscreen_rect.height,
|
||||
texture_rect.x,
|
||||
texture_rect.y,
|
||||
texture_rect.x + texture_rect.width,
|
||||
texture_rect.y + texture_rect.height);
|
||||
|
||||
cogl_framebuffer_pop_matrix (priv->framebuffer);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_stage_view_is_dirty_viewport (ClutterStageView *view)
|
||||
{
|
||||
@ -100,6 +219,27 @@ clutter_stage_view_set_dirty_projection (ClutterStageView *view,
|
||||
priv->dirty_projection = dirty;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
|
||||
gfloat *x,
|
||||
gfloat *y)
|
||||
{
|
||||
ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_GET_CLASS (view);
|
||||
gfloat z = 0, w = 1;
|
||||
CoglMatrix matrix;
|
||||
|
||||
view_class->get_offscreen_transformation_matrix (view, &matrix);
|
||||
cogl_matrix_get_inverse (&matrix, &matrix);
|
||||
cogl_matrix_transform_point (&matrix, x, y, &z, &w);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_default_get_offscreen_transformation_matrix (ClutterStageView *view,
|
||||
CoglMatrix *matrix)
|
||||
{
|
||||
cogl_matrix_init_identity (matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -118,6 +258,11 @@ clutter_stage_view_get_property (GObject *object,
|
||||
case PROP_FRAMEBUFFER:
|
||||
g_value_set_boxed (value, priv->framebuffer);
|
||||
break;
|
||||
case PROP_OFFSCREEN:
|
||||
g_value_set_boxed (value, priv->offscreen);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,6 +286,11 @@ clutter_stage_view_set_property (GObject *object,
|
||||
case PROP_FRAMEBUFFER:
|
||||
priv->framebuffer = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_OFFSCREEN:
|
||||
priv->offscreen = g_value_dup_boxed (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +302,10 @@ clutter_stage_view_dispose (GObject *object)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -169,6 +323,9 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->get_offscreen_transformation_matrix =
|
||||
clutter_stage_default_get_offscreen_transformation_matrix;
|
||||
|
||||
object_class->get_property = clutter_stage_view_get_property;
|
||||
object_class->set_property = clutter_stage_view_set_property;
|
||||
object_class->dispose = clutter_stage_view_dispose;
|
||||
@ -184,10 +341,19 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
||||
obj_props[PROP_FRAMEBUFFER] =
|
||||
g_param_spec_boxed ("framebuffer",
|
||||
"View framebuffer",
|
||||
"The framebuffer of the view",
|
||||
"The front buffer of the view",
|
||||
COGL_TYPE_HANDLE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_OFFSCREEN] =
|
||||
g_param_spec_boxed ("offscreen",
|
||||
"Offscreen buffer",
|
||||
"Framebuffer used as intermediate buffer",
|
||||
COGL_TYPE_HANDLE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
@ -33,6 +33,12 @@ G_DECLARE_DERIVABLE_TYPE (ClutterStageView, clutter_stage_view,
|
||||
struct _ClutterStageViewClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* setup_offscreen_blit_pipeline) (ClutterStageView *view,
|
||||
CoglPipeline *pipeline);
|
||||
|
||||
void (* get_offscreen_transformation_matrix) (ClutterStageView *view,
|
||||
CoglMatrix *matrix);
|
||||
};
|
||||
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
@ -41,6 +47,18 @@ void clutter_stage_view_get_layout (ClutterStageView *view,
|
||||
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
CoglFramebuffer *clutter_stage_view_get_framebuffer (ClutterStageView *view);
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view);
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
void clutter_stage_view_transform_to_onscreen (ClutterStageView *view,
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
|
||||
void clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *clip);
|
||||
|
||||
gboolean clutter_stage_view_is_dirty_viewport (ClutterStageView *view);
|
||||
|
||||
|
@ -676,6 +676,12 @@ clutter_stage_do_paint_view (ClutterStage *stage,
|
||||
_clutter_stage_paint_volume_stack_free_all (stage);
|
||||
_clutter_stage_update_active_framebuffer (stage, framebuffer);
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
||||
|
||||
if (clutter_stage_view_get_onscreen (view) !=
|
||||
clutter_stage_view_get_framebuffer (view))
|
||||
{
|
||||
clutter_stage_view_blit_offscreen (view, clip);
|
||||
}
|
||||
}
|
||||
|
||||
/* This provides a common point of entry for painting the scenegraph
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "clutter-stage-cogl.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-backend-private.h"
|
||||
@ -357,7 +358,7 @@ swap_framebuffer (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *swap_region,
|
||||
gboolean swap_with_damage)
|
||||
{
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_framebuffer (view);
|
||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
int damage[4], ndamage;
|
||||
|
||||
damage[0] = swap_region->x;
|
||||
@ -438,6 +439,42 @@ fill_current_damage_history_and_step (ClutterStageView *view)
|
||||
view_priv->damage_index++;
|
||||
}
|
||||
|
||||
static void
|
||||
transform_swap_region_to_onscreen (ClutterStageView *view,
|
||||
cairo_rectangle_int_t *swap_region)
|
||||
{
|
||||
CoglFramebuffer *framebuffer;
|
||||
cairo_rectangle_int_t layout;
|
||||
gfloat x1, y1, x2, y2;
|
||||
gint width, height;
|
||||
|
||||
framebuffer = clutter_stage_view_get_onscreen (view);
|
||||
clutter_stage_view_get_layout (view, &layout);
|
||||
|
||||
x1 = (float) swap_region->x / layout.width;
|
||||
y1 = (float) swap_region->y / layout.height;
|
||||
x2 = (float) (swap_region->x + swap_region->width) / layout.width;
|
||||
y2 = (float) (swap_region->y + swap_region->height) / layout.height;
|
||||
|
||||
clutter_stage_view_transform_to_onscreen (view, &x1, &y1);
|
||||
clutter_stage_view_transform_to_onscreen (view, &x2, &y2);
|
||||
|
||||
width = cogl_framebuffer_get_width (framebuffer);
|
||||
height = cogl_framebuffer_get_height (framebuffer);
|
||||
|
||||
x1 = floor (x1 * width);
|
||||
y1 = floor (height - (y1 * height));
|
||||
x2 = ceil (x2 * width);
|
||||
y2 = ceil (height - (y2 * height));
|
||||
|
||||
*swap_region = (cairo_rectangle_int_t) {
|
||||
.x = x1,
|
||||
.y = y1,
|
||||
.width = x2 - x1,
|
||||
.height = y2 - y1
|
||||
};
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
ClutterStageView *view)
|
||||
@ -708,6 +745,12 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
||||
|
||||
if (do_swap_buffer)
|
||||
{
|
||||
if (clutter_stage_view_get_onscreen (view) !=
|
||||
clutter_stage_view_get_framebuffer (view))
|
||||
{
|
||||
transform_swap_region_to_onscreen (view, &swap_region);
|
||||
}
|
||||
|
||||
return swap_framebuffer (stage_window,
|
||||
view,
|
||||
&swap_region,
|
||||
|
@ -27,6 +27,7 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_MONITOR_INFO,
|
||||
PROP_TRANSFORM,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
@ -37,6 +38,7 @@ struct _MetaRendererView
|
||||
{
|
||||
ClutterStageViewCogl parent;
|
||||
|
||||
MetaMonitorTransform transform;
|
||||
MetaMonitorInfo *monitor_info;
|
||||
};
|
||||
|
||||
@ -49,6 +51,72 @@ meta_renderer_view_get_monitor_info (MetaRendererView *view)
|
||||
return view->monitor_info;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_get_offscreen_transformation_matrix (ClutterStageView *view,
|
||||
CoglMatrix *matrix)
|
||||
{
|
||||
MetaRendererView *renderer_view = META_RENDERER_VIEW (view);
|
||||
|
||||
cogl_matrix_init_identity (matrix);
|
||||
|
||||
switch (renderer_view->transform)
|
||||
{
|
||||
case META_MONITOR_TRANSFORM_NORMAL:
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_90:
|
||||
cogl_matrix_rotate (matrix, 90, 0, 0, 1);
|
||||
cogl_matrix_translate (matrix, 0, -1, 0);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_180:
|
||||
cogl_matrix_rotate (matrix, 180, 0, 0, 1);
|
||||
cogl_matrix_translate (matrix, -1, -1, 0);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_270:
|
||||
cogl_matrix_rotate (matrix, 270, 0, 0, 1);
|
||||
cogl_matrix_translate (matrix, -1, 0, 0);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_FLIPPED:
|
||||
cogl_matrix_scale (matrix, -1, 1, 1);
|
||||
cogl_matrix_translate (matrix, -1, 0, 0);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
||||
cogl_matrix_scale (matrix, -1, 1, 1);
|
||||
cogl_matrix_rotate (matrix, 90, 0, 0, 1);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
||||
cogl_matrix_scale (matrix, -1, 1, 1);
|
||||
cogl_matrix_rotate (matrix, 180, 0, 0, 1);
|
||||
cogl_matrix_translate (matrix, 0, -1, 0);
|
||||
break;
|
||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
||||
cogl_matrix_scale (matrix, -1, 1, 1);
|
||||
cogl_matrix_rotate (matrix, 270, 0, 0, 1);
|
||||
cogl_matrix_translate (matrix, -1, -1, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_setup_offscreen_blit_pipeline (ClutterStageView *view,
|
||||
CoglPipeline *pipeline)
|
||||
{
|
||||
CoglMatrix matrix;
|
||||
|
||||
meta_renderer_view_get_offscreen_transformation_matrix (view, &matrix);
|
||||
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_set_transform (MetaRendererView *view,
|
||||
MetaMonitorTransform transform)
|
||||
{
|
||||
if (view->transform == transform)
|
||||
return;
|
||||
|
||||
view->transform = transform;
|
||||
clutter_stage_view_invalidate_offscreen_blit_pipeline (CLUTTER_STAGE_VIEW (view));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_renderer_view_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -62,6 +130,9 @@ meta_renderer_view_get_property (GObject *object,
|
||||
case PROP_MONITOR_INFO:
|
||||
g_value_set_pointer (value, view->monitor_info);
|
||||
break;
|
||||
case PROP_TRANSFORM:
|
||||
g_value_set_uint (value, view->transform);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -81,6 +152,9 @@ meta_renderer_view_set_property (GObject *object,
|
||||
case PROP_MONITOR_INFO:
|
||||
view->monitor_info = g_value_get_pointer (value);
|
||||
break;
|
||||
case PROP_TRANSFORM:
|
||||
meta_renderer_view_set_transform (view, g_value_get_uint (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -96,6 +170,12 @@ static void
|
||||
meta_renderer_view_class_init (MetaRendererViewClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterStageViewClass *view_class = CLUTTER_STAGE_VIEW_CLASS (klass);
|
||||
|
||||
view_class->setup_offscreen_blit_pipeline =
|
||||
meta_renderer_view_setup_offscreen_blit_pipeline;
|
||||
view_class->get_offscreen_transformation_matrix =
|
||||
meta_renderer_view_get_offscreen_transformation_matrix;
|
||||
|
||||
object_class->get_property = meta_renderer_view_get_property;
|
||||
object_class->set_property = meta_renderer_view_set_property;
|
||||
@ -107,6 +187,16 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
obj_props[PROP_TRANSFORM] =
|
||||
g_param_spec_uint ("transform",
|
||||
"Transform",
|
||||
"Transform to apply to the view",
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
META_MONITOR_TRANSFORM_FLIPPED_270,
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#define ALL_TRANSFORMS (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)
|
||||
#define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1)
|
||||
|
||||
typedef struct {
|
||||
drmModeConnector *connector;
|
||||
@ -77,6 +78,7 @@ typedef struct {
|
||||
uint32_t primary_plane_id;
|
||||
uint32_t rotation_prop_id;
|
||||
uint32_t rotation_map[ALL_TRANSFORMS];
|
||||
uint32_t all_hw_transforms;
|
||||
} MetaCRTCKms;
|
||||
|
||||
typedef struct
|
||||
@ -530,7 +532,7 @@ parse_transforms (MetaMonitorManager *manager,
|
||||
|
||||
if (cur != -1)
|
||||
{
|
||||
crtc->all_transforms |= 1 << cur;
|
||||
crtc_kms->all_hw_transforms |= 1 << cur;
|
||||
crtc_kms->rotation_map[cur] = 1 << prop->enums[i].value;
|
||||
}
|
||||
}
|
||||
@ -606,6 +608,8 @@ init_crtc_rotations (MetaMonitorManager *manager,
|
||||
drmModeFreePlane (drm_plane);
|
||||
}
|
||||
|
||||
crtc->all_transforms |= crtc_kms->all_hw_transforms;
|
||||
|
||||
drmModeFreePlaneResources (planes);
|
||||
}
|
||||
|
||||
@ -623,8 +627,8 @@ init_crtc (MetaCRTC *crtc,
|
||||
crtc->rect.height = drm_crtc->height;
|
||||
crtc->is_dirty = FALSE;
|
||||
crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
/* FIXME: implement! */
|
||||
crtc->all_transforms = 1 << META_MONITOR_TRANSFORM_NORMAL;
|
||||
crtc->all_transforms = meta_is_stage_views_enabled () ?
|
||||
ALL_TRANSFORMS_MASK : META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
if (drm_crtc->mode_valid)
|
||||
{
|
||||
@ -1184,6 +1188,7 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
MetaCRTCInfo *crtc_info = crtcs[i];
|
||||
MetaCRTC *crtc = crtc_info->crtc;
|
||||
MetaCRTCKms *crtc_kms = crtc->driver_private;
|
||||
MetaMonitorTransform hw_transform;
|
||||
|
||||
crtc->is_dirty = TRUE;
|
||||
|
||||
@ -1234,14 +1239,17 @@ meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc->all_transforms & (1 << crtc->transform))
|
||||
drmModeObjectSetProperty (manager_kms->fd,
|
||||
crtc_kms->primary_plane_id,
|
||||
DRM_MODE_OBJECT_PLANE,
|
||||
crtc_kms->rotation_prop_id,
|
||||
crtc_kms->rotation_map[crtc->transform]);
|
||||
}
|
||||
if (crtc_kms->all_hw_transforms & (1 << crtc->transform))
|
||||
hw_transform = crtc->transform;
|
||||
else
|
||||
hw_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||
|
||||
drmModeObjectSetProperty (manager_kms->fd,
|
||||
crtc_kms->primary_plane_id,
|
||||
DRM_MODE_OBJECT_PLANE,
|
||||
crtc_kms->rotation_prop_id,
|
||||
crtc_kms->rotation_map[hw_transform]);
|
||||
}
|
||||
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
|
||||
because they weren't seen in the first loop) */
|
||||
for (i = 0; i < manager->n_crtcs; i++)
|
||||
@ -1617,3 +1625,18 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
|
||||
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
|
||||
}
|
||||
|
||||
MetaMonitorTransform
|
||||
meta_monitor_manager_kms_get_view_transform (MetaMonitorManagerKms *manager,
|
||||
MetaCRTC *crtc)
|
||||
{
|
||||
MetaCRTCKms *crtc_kms;
|
||||
|
||||
crtc_kms = crtc->driver_private;
|
||||
if ((1 << crtc->transform) & crtc_kms->all_hw_transforms)
|
||||
{
|
||||
/* Transform is managed by the hardware, the view is untransformed */
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
}
|
||||
|
||||
return crtc->transform;
|
||||
}
|
||||
|
@ -57,4 +57,9 @@ gboolean meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||
|
||||
void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms);
|
||||
|
||||
MetaMonitorTransform
|
||||
meta_monitor_manager_kms_get_view_transform (MetaMonitorManagerKms *manager,
|
||||
MetaCRTC *crtc);
|
||||
|
||||
|
||||
#endif /* META_MONITOR_MANAGER_KMS_H */
|
||||
|
@ -379,7 +379,7 @@ on_crtc_flipped (GClosure *closure,
|
||||
{
|
||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_stage_view_get_framebuffer (stage_view);
|
||||
clutter_stage_view_get_onscreen (stage_view);
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
@ -397,7 +397,7 @@ flip_closure_destroyed (MetaRendererView *view)
|
||||
{
|
||||
ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (view);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_stage_view_get_framebuffer (stage_view);
|
||||
clutter_stage_view_get_onscreen (stage_view);
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
@ -589,8 +589,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
CoglFrameInfo *frame_info;
|
||||
MetaRendererView *view;
|
||||
cairo_rectangle_int_t view_layout;
|
||||
uint32_t handle, stride;
|
||||
|
||||
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
|
||||
@ -600,9 +598,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
while (onscreen_native->next_fb_id != 0)
|
||||
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);
|
||||
|
||||
parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
|
||||
rectangles,
|
||||
n_rectangles);
|
||||
@ -615,8 +610,8 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
|
||||
handle = gbm_bo_get_handle (onscreen_native->next_bo).u32;
|
||||
|
||||
if (drmModeAddFB (renderer_native->kms_fd,
|
||||
view_layout.width,
|
||||
view_layout.height,
|
||||
cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen)),
|
||||
cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen)),
|
||||
24, /* depth */
|
||||
32, /* bpp */
|
||||
stride,
|
||||
@ -751,17 +746,11 @@ meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
|
||||
if (width == 0 || height == 0)
|
||||
return TRUE;
|
||||
|
||||
if (!meta_renderer_native_create_surface (renderer_native,
|
||||
width, height,
|
||||
&onscreen_native->surface,
|
||||
&egl_onscreen->egl_surface,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||
|
||||
return TRUE;
|
||||
return meta_renderer_native_create_surface (renderer_native,
|
||||
width, height,
|
||||
&onscreen_native->surface,
|
||||
&egl_onscreen->egl_surface,
|
||||
error);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -834,7 +823,7 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
||||
{
|
||||
ClutterStageView *stage_view = l->data;
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_stage_view_get_framebuffer (stage_view);
|
||||
clutter_stage_view_get_onscreen (stage_view);
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
@ -843,6 +832,92 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
|
||||
}
|
||||
}
|
||||
|
||||
static MetaMonitorTransform
|
||||
meta_renderer_native_get_monitor_info_transform (MetaRenderer *renderer,
|
||||
MetaMonitorInfo *monitor_info)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerKms *monitor_manager_kms =
|
||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||
|
||||
g_assert (monitor_info->n_outputs > 0);
|
||||
|
||||
return meta_monitor_manager_kms_get_view_transform (monitor_manager_kms,
|
||||
monitor_info->outputs[0]->crtc);
|
||||
}
|
||||
|
||||
static CoglOnscreen *
|
||||
meta_renderer_native_create_onscreen (MetaRendererNative *renderer,
|
||||
CoglContext *context,
|
||||
MetaMonitorTransform transform,
|
||||
gint view_width,
|
||||
gint view_height)
|
||||
{
|
||||
CoglOnscreen *onscreen;
|
||||
gint width, height;
|
||||
GError *error = NULL;
|
||||
|
||||
if (meta_monitor_transform_is_rotated (transform))
|
||||
{
|
||||
width = view_height;
|
||||
height = view_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
width = view_width;
|
||||
height = view_height;
|
||||
}
|
||||
|
||||
onscreen = cogl_onscreen_new (context, width, height);
|
||||
cogl_onscreen_set_swap_throttled (onscreen,
|
||||
_clutter_get_sync_to_vblank ());
|
||||
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), &error))
|
||||
{
|
||||
g_warning ("Could not create onscreen: %s", error->message);
|
||||
cogl_object_unref (onscreen);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return onscreen;
|
||||
}
|
||||
|
||||
static CoglOffscreen *
|
||||
meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
|
||||
CoglContext *context,
|
||||
MetaMonitorTransform transform,
|
||||
gint view_width,
|
||||
gint view_height)
|
||||
{
|
||||
CoglOffscreen *fb;
|
||||
CoglTexture2D *tex;
|
||||
GError *error = NULL;
|
||||
|
||||
tex = cogl_texture_2d_new_with_size (context, view_width, view_height);
|
||||
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (tex), FALSE);
|
||||
|
||||
if (!cogl_texture_allocate (COGL_TEXTURE (tex), &error))
|
||||
{
|
||||
cogl_object_unref (tex);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fb = cogl_offscreen_new_with_texture (COGL_TEXTURE (tex));
|
||||
cogl_object_unref (tex);
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (fb), &error))
|
||||
{
|
||||
g_warning ("Could not create offscreen: %s", error->message);
|
||||
g_error_free (error);
|
||||
cogl_object_unref (fb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return fb;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||
MetaRendererView *view,
|
||||
@ -867,13 +942,14 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||
MetaMonitorManagerKms *monitor_manager_kms =
|
||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||
CoglFramebuffer *framebuffer =
|
||||
clutter_stage_view_get_framebuffer (stage_view);
|
||||
clutter_stage_view_get_onscreen (stage_view);
|
||||
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
struct gbm_surface *new_surface;
|
||||
EGLSurface new_egl_surface;
|
||||
cairo_rectangle_int_t view_layout;
|
||||
|
||||
/*
|
||||
* Ensure we don't have any pending flips that will want
|
||||
@ -920,6 +996,14 @@ meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native,
|
||||
egl_onscreen->egl_surface,
|
||||
egl_display->egl_context);
|
||||
|
||||
view_layout = (cairo_rectangle_int_t) {
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
g_object_set (G_OBJECT (view),
|
||||
"layout", &view_layout,
|
||||
NULL);
|
||||
|
||||
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
|
||||
}
|
||||
|
||||
@ -992,13 +1076,11 @@ 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;
|
||||
CoglOnscreen *onscreen = NULL;
|
||||
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;
|
||||
@ -1007,22 +1089,20 @@ meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native)
|
||||
&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 ());
|
||||
onscreen = meta_renderer_native_create_onscreen (renderer_native,
|
||||
cogl_context,
|
||||
META_MONITOR_TRANSFORM_NORMAL,
|
||||
view_layout.width,
|
||||
view_layout.height);
|
||||
|
||||
framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||
meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
|
||||
error->message);
|
||||
if (!onscreen)
|
||||
meta_fatal ("Failed to allocate onscreen framebuffer\n");
|
||||
|
||||
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||
"layout", &view_layout,
|
||||
"framebuffer", framebuffer,
|
||||
"framebuffer", onscreen,
|
||||
NULL);
|
||||
cogl_object_unref (framebuffer);
|
||||
cogl_object_unref (onscreen);
|
||||
|
||||
meta_onscreen_native_set_view (onscreen, view);
|
||||
|
||||
@ -1036,28 +1116,52 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
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;
|
||||
CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
|
||||
CoglDisplayEGL *egl_display = cogl_display->winsys;
|
||||
CoglOnscreenEGL *egl_onscreen;
|
||||
MetaMonitorTransform transform;
|
||||
CoglOnscreen *onscreen = NULL;
|
||||
CoglOffscreen *offscreen = NULL;
|
||||
MetaRendererView *view;
|
||||
GError *error = NULL;
|
||||
|
||||
onscreen = cogl_onscreen_new (cogl_context,
|
||||
monitor_info->rect.width,
|
||||
monitor_info->rect.height);
|
||||
cogl_onscreen_set_swap_throttled (onscreen,
|
||||
_clutter_get_sync_to_vblank ());
|
||||
transform = meta_renderer_native_get_monitor_info_transform (renderer,
|
||||
monitor_info);
|
||||
|
||||
framebuffer = COGL_FRAMEBUFFER (onscreen);
|
||||
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||
meta_fatal ("Failed to allocate onscreen framebuffer: %s\n",
|
||||
error->message);
|
||||
onscreen = meta_renderer_native_create_onscreen (META_RENDERER_NATIVE (renderer),
|
||||
cogl_context,
|
||||
transform,
|
||||
monitor_info->rect.width,
|
||||
monitor_info->rect.height);
|
||||
if (!onscreen)
|
||||
meta_fatal ("Failed to allocate onscreen framebuffer\n");
|
||||
|
||||
/* Ensure we don't point to stale surfaces when creating the offscreen */
|
||||
egl_onscreen = onscreen->winsys;
|
||||
_cogl_winsys_egl_make_current (cogl_display,
|
||||
egl_onscreen->egl_surface,
|
||||
egl_onscreen->egl_surface,
|
||||
egl_display->egl_context);
|
||||
|
||||
if (transform != META_MONITOR_TRANSFORM_NORMAL)
|
||||
{
|
||||
offscreen = meta_renderer_native_create_offscreen (META_RENDERER_NATIVE (renderer),
|
||||
cogl_context,
|
||||
transform,
|
||||
monitor_info->rect.width,
|
||||
monitor_info->rect.height);
|
||||
if (!offscreen)
|
||||
meta_fatal ("Failed to allocate back buffer texture\n");
|
||||
}
|
||||
|
||||
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||
"layout", &monitor_info->rect,
|
||||
"framebuffer", framebuffer,
|
||||
"framebuffer", onscreen,
|
||||
"offscreen", offscreen,
|
||||
"monitor-info", monitor_info,
|
||||
"transform", transform,
|
||||
NULL);
|
||||
cogl_object_unref (framebuffer);
|
||||
cogl_object_unref (onscreen);
|
||||
g_clear_pointer (&offscreen, cogl_object_unref);
|
||||
|
||||
meta_onscreen_native_set_view (onscreen, view);
|
||||
|
||||
|
@ -127,7 +127,7 @@ ensure_frame_callback (MetaStageNative *stage_native,
|
||||
if (closure)
|
||||
return;
|
||||
|
||||
framebuffer = clutter_stage_view_get_framebuffer (stage_view);
|
||||
framebuffer = clutter_stage_view_get_onscreen (stage_view);
|
||||
onscreen = COGL_ONSCREEN (framebuffer);
|
||||
closure = cogl_onscreen_add_frame_callback (onscreen,
|
||||
frame_cb,
|
||||
@ -270,7 +270,6 @@ maybe_resize_legacy_view (MetaStageNative *stage_native)
|
||||
int width = stage_native->pending_width;
|
||||
int height = stage_native->pending_height;
|
||||
GError *error = NULL;
|
||||
cairo_rectangle_int_t view_layout;
|
||||
|
||||
if (!stage_native->pending_resize)
|
||||
return;
|
||||
@ -288,16 +287,7 @@ maybe_resize_legacy_view (MetaStageNative *stage_native)
|
||||
meta_warning ("Applying display configuration failed: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
view_layout = (cairo_rectangle_int_t) {
|
||||
.width = width,
|
||||
.height = height
|
||||
};
|
||||
g_object_set (G_OBJECT (legacy_view),
|
||||
"layout", &view_layout,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Reference in New Issue
Block a user