1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /*
4  * Copyright (C) 2013 Red Hat
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19  * 02111-1307, USA.
20  *
21  * Written by:
22  *     Jasper St. Pierre <jstpierre@mecheye.net>
23  */
24 
25 #include "config.h"
26 
27 #include "compositor/meta-surface-actor-wayland.h"
28 
29 #include <math.h>
30 
31 #include "backends/meta-backend-private.h"
32 #include "backends/meta-logical-monitor.h"
33 #include "cogl/cogl-wayland-server.h"
34 #include "compositor/meta-shaped-texture-private.h"
35 #include "compositor/region-utils.h"
36 #include "wayland/meta-wayland-buffer.h"
37 #include "wayland/meta-wayland-private.h"
38 #include "wayland/meta-window-wayland.h"
39 
40 struct _MetaSurfaceActorWayland
41 {
42   MetaSurfaceActor parent;
43 
44   MetaWaylandSurface *surface;
45 };
46 
G_DEFINE_TYPE(MetaSurfaceActorWayland,meta_surface_actor_wayland,META_TYPE_SURFACE_ACTOR)47 G_DEFINE_TYPE (MetaSurfaceActorWayland,
48                meta_surface_actor_wayland,
49                META_TYPE_SURFACE_ACTOR)
50 
51 static void
52 meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
53                                            int               x,
54                                            int               y,
55                                            int               width,
56                                            int               height)
57 {
58   meta_surface_actor_update_area (actor, x, y, width, height);
59 }
60 
61 static gboolean
meta_surface_actor_wayland_is_opaque(MetaSurfaceActor * actor)62 meta_surface_actor_wayland_is_opaque (MetaSurfaceActor *actor)
63 {
64   MetaShapedTexture *stex = meta_surface_actor_get_texture (actor);
65 
66   return meta_shaped_texture_is_opaque (stex);
67 }
68 
69 CoglScanout *
meta_surface_actor_wayland_try_acquire_scanout(MetaSurfaceActorWayland * self,CoglOnscreen * onscreen)70 meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self,
71                                                 CoglOnscreen            *onscreen)
72 {
73   MetaWaylandSurface *surface;
74   CoglScanout *scanout;
75 
76   surface = meta_surface_actor_wayland_get_surface (self);
77   if (!surface)
78     return NULL;
79 
80   scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen);
81   if (!scanout)
82     return NULL;
83 
84   return scanout;
85 }
86 
87 #define UNOBSCURED_TRESHOLD 0.1
88 
89 ClutterStageView *
meta_surface_actor_wayland_get_current_primary_view(MetaSurfaceActor * actor,ClutterStage * stage)90 meta_surface_actor_wayland_get_current_primary_view (MetaSurfaceActor *actor,
91                                                      ClutterStage     *stage)
92 {
93   ClutterStageView *current_primary_view = NULL;
94   float highest_refresh_rate = 0.f;
95   float biggest_unobscurred_fraction = 0.f;
96   GList *l;
97 
98   for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
99     {
100       ClutterStageView *stage_view = l->data;
101       float refresh_rate;
102       float unobscurred_fraction = 1.f;
103 
104       if (clutter_actor_has_mapped_clones (CLUTTER_ACTOR (actor)))
105         {
106           if (!clutter_actor_is_effectively_on_stage_view (CLUTTER_ACTOR (actor),
107                                                            stage_view))
108             continue;
109         }
110       else
111         {
112           if (l->next || biggest_unobscurred_fraction > 0.f)
113             {
114               if (meta_surface_actor_is_obscured_on_stage_view (actor,
115                                                                 stage_view,
116                                                                 &unobscurred_fraction))
117                 continue;
118             }
119           else
120             {
121               if (meta_surface_actor_is_obscured (actor))
122                 continue;
123             }
124         }
125 
126       refresh_rate = clutter_stage_view_get_refresh_rate (stage_view);
127 
128       if ((refresh_rate > highest_refresh_rate &&
129            (unobscurred_fraction > UNOBSCURED_TRESHOLD ||
130             biggest_unobscurred_fraction < UNOBSCURED_TRESHOLD)) ||
131           (biggest_unobscurred_fraction < UNOBSCURED_TRESHOLD &&
132            unobscurred_fraction > UNOBSCURED_TRESHOLD))
133         {
134           current_primary_view = stage_view;
135           highest_refresh_rate = refresh_rate;
136           biggest_unobscurred_fraction = unobscurred_fraction;
137         }
138     }
139 
140   return current_primary_view;
141 }
142 
143 static void
meta_surface_actor_wayland_dispose(GObject * object)144 meta_surface_actor_wayland_dispose (GObject *object)
145 {
146   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (object);
147   MetaShapedTexture *stex;
148 
149   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
150   if (stex)
151     meta_shaped_texture_set_texture (stex, NULL);
152 
153   if (self->surface)
154     {
155       g_object_remove_weak_pointer (G_OBJECT (self->surface),
156                                     (gpointer *) &self->surface);
157       self->surface = NULL;
158     }
159 
160   G_OBJECT_CLASS (meta_surface_actor_wayland_parent_class)->dispose (object);
161 }
162 
163 static void
meta_surface_actor_wayland_class_init(MetaSurfaceActorWaylandClass * klass)164 meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
165 {
166   MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
167   GObjectClass *object_class = G_OBJECT_CLASS (klass);
168 
169   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
170   surface_actor_class->is_opaque = meta_surface_actor_wayland_is_opaque;
171 
172   object_class->dispose = meta_surface_actor_wayland_dispose;
173 }
174 
175 static void
meta_surface_actor_wayland_init(MetaSurfaceActorWayland * self)176 meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
177 {
178 }
179 
180 MetaSurfaceActor *
meta_surface_actor_wayland_new(MetaWaylandSurface * surface)181 meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
182 {
183   MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
184 
185   g_assert (meta_is_wayland_compositor ());
186 
187   self->surface = surface;
188   g_object_add_weak_pointer (G_OBJECT (self->surface),
189                              (gpointer *) &self->surface);
190 
191   return META_SURFACE_ACTOR (self);
192 }
193 
194 MetaWaylandSurface *
meta_surface_actor_wayland_get_surface(MetaSurfaceActorWayland * self)195 meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
196 {
197   return self->surface;
198 }
199