Compare commits
	
		
			5 Commits
		
	
	
		
			pwood/fix-
			...
			gbsneto/co
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | dd39d7a060 | ||
|   | e1c272e3d7 | ||
|   | 41ece851d6 | ||
|   | d5262f0f4d | ||
|   | fd99a56fd6 | 
| @@ -38,6 +38,7 @@ | ||||
|  | ||||
| #include "clutter-build-config.h" | ||||
|  | ||||
| #include "clutter-actor-private.h" | ||||
| #include "clutter-content-private.h" | ||||
|  | ||||
| #include "clutter-debug.h" | ||||
| @@ -91,6 +92,11 @@ clutter_content_real_invalidate (ClutterContent *content) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_content_real_invalidate_size (ClutterContent *content) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_content_real_paint_content (ClutterContent   *content, | ||||
|                                     ClutterActor     *actor, | ||||
| @@ -108,6 +114,7 @@ clutter_content_default_init (ClutterContentInterface *iface) | ||||
|   iface->attached = clutter_content_real_attached; | ||||
|   iface->detached = clutter_content_real_detached; | ||||
|   iface->invalidate = clutter_content_real_invalidate; | ||||
|   iface->invalidate_size = clutter_content_real_invalidate_size; | ||||
|  | ||||
|   /** | ||||
|    * ClutterContent::attached: | ||||
| @@ -188,6 +195,45 @@ clutter_content_invalidate (ClutterContent *content) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_content_invalidate_size: | ||||
|  * @content: a #ClutterContent | ||||
|  * | ||||
|  * Signals that @content's size changed. Attached actors with request mode | ||||
|  * set to %CLUTTER_REQUEST_CONTENT_SIZE will have a relayout queued. | ||||
|  * | ||||
|  * Attached actors with other request modes are not redrawn. To redraw them | ||||
|  * too, use clutter_content_invalidate(). | ||||
|  */ | ||||
| void | ||||
| clutter_content_invalidate_size (ClutterContent *content) | ||||
| { | ||||
|   ClutterActor *actor; | ||||
|   GHashTable *actors; | ||||
|   GHashTableIter iter; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_CONTENT (content)); | ||||
|  | ||||
|   CLUTTER_CONTENT_GET_IFACE (content)->invalidate_size (content); | ||||
|  | ||||
|   actors = g_object_get_qdata (G_OBJECT (content), quark_content_actors); | ||||
|   if (actors == NULL) | ||||
|     return; | ||||
|  | ||||
|   g_hash_table_iter_init (&iter, actors); | ||||
|   while (g_hash_table_iter_next (&iter, (gpointer *) &actor, NULL)) | ||||
|     { | ||||
|       ClutterRequestMode request_mode; | ||||
|  | ||||
|       g_assert (actor != NULL); | ||||
|  | ||||
|       request_mode = clutter_actor_get_request_mode (actor); | ||||
|  | ||||
|       if (request_mode == CLUTTER_REQUEST_CONTENT_SIZE) | ||||
|         _clutter_actor_queue_only_relayout (actor); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /*< private > | ||||
|  * _clutter_content_attached: | ||||
|  * @content: a #ClutterContent | ||||
|   | ||||
| @@ -86,6 +86,8 @@ struct _ClutterContentIface | ||||
|                                          ClutterActor     *actor); | ||||
|  | ||||
|   void          (* invalidate)          (ClutterContent   *content); | ||||
|  | ||||
|   void          (* invalidate_size)     (ClutterContent   *content); | ||||
| }; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| @@ -98,6 +100,9 @@ gboolean        clutter_content_get_preferred_size      (ClutterContent *content | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_content_invalidate              (ClutterContent *content); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void            clutter_content_invalidate_size         (ClutterContent *content); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_CONTENT_H__ */ | ||||
|   | ||||
| @@ -53,6 +53,8 @@ | ||||
| struct _ClutterImagePrivate | ||||
| { | ||||
|   CoglTexture *texture; | ||||
|   gint width; | ||||
|   gint height; | ||||
| }; | ||||
|  | ||||
| static void clutter_content_iface_init (ClutterContentIface *iface); | ||||
| @@ -68,6 +70,27 @@ clutter_image_error_quark (void) | ||||
|   return g_quark_from_static_string ("clutter-image-error-quark"); | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_image_size (ClutterImage *self) | ||||
| { | ||||
|   gint width, height; | ||||
|  | ||||
|   if (self->priv->texture == NULL) | ||||
|     return; | ||||
|  | ||||
|   width = cogl_texture_get_width (self->priv->texture); | ||||
|   height = cogl_texture_get_height (self->priv->texture); | ||||
|  | ||||
|   if (self->priv->width == width && | ||||
|       self->priv->height == height) | ||||
|     return; | ||||
|  | ||||
|   self->priv->width = width; | ||||
|   self->priv->height = height; | ||||
|  | ||||
|   clutter_content_invalidate_size (CLUTTER_CONTENT (self)); | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_image_finalize (GObject *gobject) | ||||
| { | ||||
| @@ -238,6 +261,7 @@ clutter_image_set_data (ClutterImage     *image, | ||||
|     } | ||||
|  | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (image)); | ||||
|   update_image_size (image); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -306,6 +330,7 @@ clutter_image_set_bytes (ClutterImage     *image, | ||||
|     } | ||||
|  | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (image)); | ||||
|   update_image_size (image); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -399,6 +424,7 @@ clutter_image_set_area (ClutterImage                 *image, | ||||
|     } | ||||
|  | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (image)); | ||||
|   update_image_size (image); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|   | ||||
| @@ -77,6 +77,7 @@ struct _ClutterPaintNodeClass | ||||
| typedef enum { | ||||
|   PAINT_OP_INVALID = 0, | ||||
|   PAINT_OP_TEX_RECT, | ||||
|   PAINT_OP_MULTITEX_RECT, | ||||
|   PAINT_OP_PATH, | ||||
|   PAINT_OP_PRIMITIVE | ||||
| } PaintOpCode; | ||||
| @@ -85,6 +86,8 @@ struct _ClutterPaintOperation | ||||
| { | ||||
|   PaintOpCode opcode; | ||||
|  | ||||
|   GArray *multitex_coords; | ||||
|  | ||||
|   union { | ||||
|     float texrect[8]; | ||||
|  | ||||
| @@ -142,30 +145,6 @@ ClutterPaintNode *      clutter_paint_node_get_parent                   (Clutter | ||||
| G_GNUC_INTERNAL | ||||
| CoglFramebuffer *       clutter_paint_node_get_framebuffer              (ClutterPaintNode      *node); | ||||
|  | ||||
| #define CLUTTER_TYPE_LAYER_NODE                 (_clutter_layer_node_get_type ()) | ||||
| #define CLUTTER_LAYER_NODE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYER_NODE, ClutterLayerNode)) | ||||
| #define CLUTTER_IS_LAYER_NODE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYER_NODE)) | ||||
|  | ||||
| /* | ||||
|  * ClutterLayerNode: | ||||
|  * | ||||
|  * The #ClutterLayerNode structure is an opaque | ||||
|  * type whose members cannot be directly accessed. | ||||
|  * | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| typedef struct _ClutterLayerNode                ClutterLayerNode; | ||||
| typedef struct _ClutterLayerNodeClass           ClutterLayerNodeClass; | ||||
|  | ||||
| GType _clutter_layer_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| ClutterPaintNode *      _clutter_layer_node_new         (const CoglMatrix        *projection, | ||||
|                                                          const cairo_rectangle_t *viewport, | ||||
|                                                          float                    width, | ||||
|                                                          float                    height, | ||||
|                                                          guint8                   opacity); | ||||
|  | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_PAINT_NODE_PRIVATE_H__ */ | ||||
|   | ||||
| @@ -761,6 +761,11 @@ clutter_paint_operation_clear (ClutterPaintOperation *op) | ||||
|     case PAINT_OP_TEX_RECT: | ||||
|       break; | ||||
|  | ||||
|     case PAINT_OP_MULTITEX_RECT: | ||||
|       if (op->multitex_coords != NULL) | ||||
|         g_array_unref (op->multitex_coords); | ||||
|       break; | ||||
|  | ||||
|     case PAINT_OP_PATH: | ||||
|       if (op->op.path != NULL) | ||||
|         cogl_object_unref (op->op.path); | ||||
| @@ -794,6 +799,27 @@ clutter_paint_op_init_tex_rect (ClutterPaintOperation *op, | ||||
|   op->op.texrect[7] = y_2; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| clutter_paint_op_init_multitex_rect (ClutterPaintOperation *op, | ||||
|                                      const ClutterActorBox *rect, | ||||
|                                      const float           *tex_coords, | ||||
|                                      unsigned int           tex_coords_len) | ||||
| { | ||||
|   clutter_paint_operation_clear (op); | ||||
|  | ||||
|   op->opcode = PAINT_OP_MULTITEX_RECT; | ||||
|   op->multitex_coords = g_array_sized_new (FALSE, FALSE, | ||||
|                                            sizeof (float), | ||||
|                                            tex_coords_len); | ||||
|  | ||||
|   g_array_append_vals (op->multitex_coords, tex_coords, tex_coords_len); | ||||
|  | ||||
|   op->op.texrect[0] = rect->x1; | ||||
|   op->op.texrect[1] = rect->y1; | ||||
|   op->op.texrect[2] = rect->x2; | ||||
|   op->op.texrect[3] = rect->y2; | ||||
| } | ||||
|  | ||||
| static inline void | ||||
| clutter_paint_op_init_path (ClutterPaintOperation *op, | ||||
|                             CoglPath              *path) | ||||
| @@ -881,6 +907,33 @@ clutter_paint_node_add_texture_rectangle (ClutterPaintNode      *node, | ||||
|   g_array_append_val (node->operations, operation); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * clutter_paint_node_add_multitexture_rectangle: | ||||
|  * @node: a #ClutterPaintNode | ||||
|  * @rect: a #ClutterActorBox | ||||
|  * @text_coords: array of multitexture values | ||||
|  * @text_coords_len: number of items of @text_coords | ||||
|  * | ||||
|  * Adds a rectangle region to the @node, with multitexture coordinates. | ||||
|  */ | ||||
| void | ||||
| clutter_paint_node_add_multitexture_rectangle (ClutterPaintNode      *node, | ||||
|                                                const ClutterActorBox *rect, | ||||
|                                                const float           *text_coords, | ||||
|                                                unsigned int           text_coords_len) | ||||
| { | ||||
|   ClutterPaintOperation operation = PAINT_OP_INIT; | ||||
|  | ||||
|   g_return_if_fail (CLUTTER_IS_PAINT_NODE (node)); | ||||
|   g_return_if_fail (rect != NULL); | ||||
|  | ||||
|   clutter_paint_node_maybe_init_operations (node); | ||||
|  | ||||
|   clutter_paint_op_init_multitex_rect (&operation, rect, text_coords, text_coords_len); | ||||
|   g_array_append_val (node->operations, operation); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * clutter_paint_node_add_path: (skip) | ||||
|  * @node: a #ClutterPaintNode | ||||
| @@ -1006,7 +1059,7 @@ clutter_paint_node_to_json (ClutterPaintNode *node) | ||||
|  | ||||
|   if (node->operations != NULL) | ||||
|     { | ||||
|       guint i; | ||||
|       guint i, j; | ||||
|  | ||||
|       for (i = 0; i < node->operations->len; i++) | ||||
|         { | ||||
| @@ -1031,6 +1084,19 @@ clutter_paint_node_to_json (ClutterPaintNode *node) | ||||
|               json_builder_end_array (builder); | ||||
|               break; | ||||
|  | ||||
|             case PAINT_OP_MULTITEX_RECT: | ||||
|               json_builder_set_member_name (builder, "texrect"); | ||||
|               json_builder_begin_array (builder); | ||||
|  | ||||
|               for (j = 0; i < op->multitex_coords->len; j++) | ||||
|                 { | ||||
|                   float coord = g_array_index (op->multitex_coords, float, j); | ||||
|                   json_builder_add_double_value (builder, coord); | ||||
|                 } | ||||
|  | ||||
|               json_builder_end_array (builder); | ||||
|               break; | ||||
|  | ||||
|             case PAINT_OP_PATH: | ||||
|               json_builder_set_member_name (builder, "path"); | ||||
|               json_builder_add_int_value (builder, (gint64) op->op.path); | ||||
|   | ||||
| @@ -67,6 +67,12 @@ void                    clutter_paint_node_add_texture_rectangle        (Clutter | ||||
|                                                                          float                  x_2, | ||||
|                                                                          float                  y_2); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                   clutter_paint_node_add_multitexture_rectangle   (ClutterPaintNode       *node, | ||||
|                                                                         const ClutterActorBox  *rect, | ||||
|                                                                         const float            *text_coords, | ||||
|                                                                         unsigned int            text_coords_len); | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| void                    clutter_paint_node_add_path                     (ClutterPaintNode      *node, | ||||
|                                                                          CoglPath              *path); | ||||
|   | ||||
| @@ -431,6 +431,17 @@ clutter_pipeline_node_draw (ClutterPaintNode *node) | ||||
|                                               op->op.texrect[7]); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|           cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                                          pnode->pipeline, | ||||
|                                                          op->op.texrect[0], | ||||
|                                                          op->op.texrect[1], | ||||
|                                                          op->op.texrect[2], | ||||
|                                                          op->op.texrect[3], | ||||
|                                                          (float*) op->multitex_coords->data, | ||||
|                                                          op->multitex_coords->len); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PATH: | ||||
|           cogl_path_fill (op->op.path); | ||||
|           break; | ||||
| @@ -827,6 +838,7 @@ clutter_text_node_draw (ClutterPaintNode *node) | ||||
|             cogl_framebuffer_pop_clip (fb); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PATH: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|         case PAINT_OP_INVALID: | ||||
| @@ -992,6 +1004,7 @@ clutter_clip_node_pre_draw (ClutterPaintNode *node) | ||||
|           retval = TRUE; | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|         case PAINT_OP_INVALID: | ||||
|           break; | ||||
| @@ -1025,6 +1038,7 @@ clutter_clip_node_post_draw (ClutterPaintNode *node) | ||||
|           cogl_framebuffer_pop_clip (fb); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|         case PAINT_OP_PRIMITIVE: | ||||
|         case PAINT_OP_INVALID: | ||||
|           break; | ||||
| @@ -1065,11 +1079,9 @@ clutter_clip_node_new (void) | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * ClutterLayerNode (private) | ||||
|  * ClutterLayerNode | ||||
|  */ | ||||
|  | ||||
| #define clutter_layer_node_get_type     _clutter_layer_node_get_type | ||||
|  | ||||
| struct _ClutterLayerNode | ||||
| { | ||||
|   ClutterPaintNode parent_instance; | ||||
| @@ -1180,6 +1192,17 @@ clutter_layer_node_post_draw (ClutterPaintNode *node) | ||||
|           cogl_pop_source (); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_MULTITEX_RECT: | ||||
|           cogl_framebuffer_draw_multitextured_rectangle (cogl_get_draw_framebuffer (), | ||||
|                                                          lnode->state, | ||||
|                                                          op->op.texrect[0], | ||||
|                                                          op->op.texrect[1], | ||||
|                                                          op->op.texrect[2], | ||||
|                                                          op->op.texrect[3], | ||||
|                                                          (float*) op->multitex_coords->data, | ||||
|                                                          op->multitex_coords->len); | ||||
|           break; | ||||
|  | ||||
|         case PAINT_OP_PATH: | ||||
|           cogl_push_source (lnode->state); | ||||
|           cogl_path_fill (op->op.path); | ||||
| @@ -1244,11 +1267,11 @@ clutter_layer_node_init (ClutterLayerNode *self) | ||||
|  * Since: 1.10 | ||||
|  */ | ||||
| ClutterPaintNode * | ||||
| _clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|                          const cairo_rectangle_t *viewport, | ||||
|                          float                    width, | ||||
|                          float                    height, | ||||
|                          guint8                   opacity) | ||||
| clutter_layer_node_new (const CoglMatrix        *projection, | ||||
|                         const cairo_rectangle_t *viewport, | ||||
|                         float                    width, | ||||
|                         float                    height, | ||||
|                         guint8                   opacity) | ||||
| { | ||||
|   ClutterLayerNode *res; | ||||
|   CoglColor color; | ||||
|   | ||||
| @@ -143,6 +143,29 @@ CLUTTER_EXPORT | ||||
| ClutterPaintNode *      clutter_text_node_new           (PangoLayout           *layout, | ||||
|                                                          const ClutterColor    *color); | ||||
|  | ||||
| #define CLUTTER_TYPE_LAYER_NODE                 (clutter_layer_node_get_type ()) | ||||
| #define CLUTTER_LAYER_NODE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYER_NODE, ClutterLayerNode)) | ||||
| #define CLUTTER_IS_LAYER_NODE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYER_NODE)) | ||||
|  | ||||
| /* | ||||
|  * ClutterLayerNode: | ||||
|  * | ||||
|  * The #ClutterLayerNode structure is an opaque | ||||
|  * type whose members cannot be directly accessed. | ||||
|  */ | ||||
| typedef struct _ClutterLayerNode                ClutterLayerNode; | ||||
| typedef struct _ClutterLayerNodeClass           ClutterLayerNodeClass; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| GType clutter_layer_node_get_type (void) G_GNUC_CONST; | ||||
|  | ||||
| CLUTTER_EXPORT | ||||
| ClutterPaintNode *      clutter_layer_node_new          (const CoglMatrix        *projection, | ||||
|                                                          const cairo_rectangle_t *viewport, | ||||
|                                                          float                    width, | ||||
|                                                          float                    height, | ||||
|                                                          guint8                   opacity); | ||||
|  | ||||
| G_END_DECLS | ||||
|  | ||||
| #endif /* __CLUTTER_PAINT_NODES_H__ */ | ||||
|   | ||||
| @@ -44,5 +44,13 @@ gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); | ||||
| cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex); | ||||
| void meta_shaped_texture_set_transform (MetaShapedTexture    *stex, | ||||
|                                         MetaMonitorTransform  transform); | ||||
| void meta_shaped_texture_cull_out (MetaShapedTexture *stex, | ||||
|                                    cairo_region_t    *unobscured_region, | ||||
|                                    cairo_region_t    *clip_region, | ||||
|                                    uint8_t            opacity); | ||||
| void meta_shaped_texture_reset_culling (MetaShapedTexture *stex); | ||||
| void meta_shaped_texture_set_scale (MetaShapedTexture *stex, | ||||
|                                     double             scale); | ||||
| double meta_shaped_texture_get_scale (MetaShapedTexture *stex); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -57,21 +57,7 @@ | ||||
|  | ||||
| static void meta_shaped_texture_dispose  (GObject    *object); | ||||
|  | ||||
| static void meta_shaped_texture_paint (ClutterActor       *actor); | ||||
|  | ||||
| static void meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|                                                      gfloat        for_height, | ||||
|                                                      gfloat       *min_width_p, | ||||
|                                                      gfloat       *natural_width_p); | ||||
|  | ||||
| static void meta_shaped_texture_get_preferred_height (ClutterActor *self, | ||||
|                                                       gfloat        for_width, | ||||
|                                                       gfloat       *min_height_p, | ||||
|                                                       gfloat       *natural_height_p); | ||||
|  | ||||
| static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume); | ||||
|  | ||||
| static void cullable_iface_init (MetaCullableInterface *iface); | ||||
| static void clutter_content_iface_init (ClutterContentIface *iface); | ||||
|  | ||||
| enum { | ||||
|   SIZE_CHANGED, | ||||
| @@ -83,7 +69,7 @@ static guint signals[LAST_SIGNAL]; | ||||
|  | ||||
| struct _MetaShapedTexture | ||||
| { | ||||
|   ClutterActor parent; | ||||
|   GObject parent; | ||||
|  | ||||
|   MetaTextureTower *paint_tower; | ||||
|  | ||||
| @@ -116,25 +102,21 @@ struct _MetaShapedTexture | ||||
|   guint remipmap_timeout_id; | ||||
|   gint64 earliest_remipmap; | ||||
|  | ||||
|   double scale; | ||||
|  | ||||
|   guint create_mipmaps : 1; | ||||
| }; | ||||
|  | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR, | ||||
|                          G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); | ||||
| G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT, | ||||
|                          G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, clutter_content_iface_init)); | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_class_init (MetaShapedTextureClass *klass) | ||||
| { | ||||
|   GObjectClass *gobject_class = (GObjectClass *) klass; | ||||
|   ClutterActorClass *actor_class = (ClutterActorClass *) klass; | ||||
|  | ||||
|   gobject_class->dispose = meta_shaped_texture_dispose; | ||||
|  | ||||
|   actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height; | ||||
|   actor_class->paint = meta_shaped_texture_paint; | ||||
|   actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume; | ||||
|  | ||||
|   signals[SIZE_CHANGED] = g_signal_new ("size-changed", | ||||
|                                         G_TYPE_FROM_CLASS (gobject_class), | ||||
|                                         G_SIGNAL_RUN_LAST, | ||||
| @@ -154,16 +136,12 @@ meta_shaped_texture_init (MetaShapedTexture *stex) | ||||
| { | ||||
|   stex->paint_tower = meta_texture_tower_new (); | ||||
|  | ||||
|   stex->scale = 1.0; | ||||
|   stex->texture = NULL; | ||||
|   stex->mask_texture = NULL; | ||||
|   stex->create_mipmaps = TRUE; | ||||
|   stex->is_y_inverted = TRUE; | ||||
|   stex->transform = META_MONITOR_TRANSFORM_NORMAL; | ||||
|  | ||||
|   g_signal_connect (stex, | ||||
|                     "notify::scale-x", | ||||
|                     G_CALLBACK (invalidate_size), | ||||
|                     stex); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -207,7 +185,7 @@ update_size (MetaShapedTexture *stex) | ||||
|       stex->dst_width = dst_width; | ||||
|       stex->dst_height = dst_height; | ||||
|       meta_shaped_texture_set_mask_texture (stex, NULL); | ||||
|       clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); | ||||
|       clutter_content_invalidate_size (CLUTTER_CONTENT (stex)); | ||||
|       g_signal_emit (stex, signals[SIZE_CHANGED], 0); | ||||
|     } | ||||
| } | ||||
| @@ -436,6 +414,40 @@ paint_clipped_rectangle (CoglFramebuffer       *fb, | ||||
|                                                  &coords[0], 8); | ||||
| } | ||||
|  | ||||
| static void | ||||
| paint_clipped_rectangle_node (ClutterPaintNode      *root_node, | ||||
|                               CoglPipeline          *pipeline, | ||||
|                               cairo_rectangle_int_t *rect, | ||||
|                               ClutterActorBox       *alloc) | ||||
| { | ||||
|   g_autoptr(ClutterPaintNode) node = NULL; | ||||
|   float coords[8]; | ||||
|  | ||||
|   coords[0] = rect->x / (alloc->x2 - alloc->x1); | ||||
|   coords[1] = rect->y / (alloc->y2 - alloc->y1); | ||||
|   coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1); | ||||
|   coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1); | ||||
|  | ||||
|   coords[4] = coords[0]; | ||||
|   coords[5] = coords[1]; | ||||
|   coords[6] = coords[2]; | ||||
|   coords[7] = coords[3]; | ||||
|  | ||||
|   node = clutter_pipeline_node_new (pipeline); | ||||
|   clutter_paint_node_set_name (node, "MetaShapedTexture (clipped)"); | ||||
|   clutter_paint_node_add_child (root_node, node); | ||||
|  | ||||
|   clutter_paint_node_add_multitexture_rectangle (node, | ||||
|                                                  &(ClutterActorBox) | ||||
|                                                    { | ||||
|                                                      .x1 = rect->x, | ||||
|                                                      .x2 = rect->x + rect->width, | ||||
|                                                      .y1 = rect->y, | ||||
|                                                      .y2 = rect->y + rect->height, | ||||
|                                                    }, | ||||
|                                                  coords, 8); | ||||
| } | ||||
|  | ||||
| static void | ||||
| set_cogl_texture (MetaShapedTexture *stex, | ||||
|                   CoglTexture       *cogl_tex) | ||||
| @@ -476,6 +488,8 @@ set_cogl_texture (MetaShapedTexture *stex, | ||||
|  | ||||
|   if (stex->create_mipmaps) | ||||
|     meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); | ||||
|  | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (stex)); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| @@ -486,12 +500,31 @@ texture_is_idle_and_not_mipmapped (gpointer user_data) | ||||
|   if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0) | ||||
|     return G_SOURCE_CONTINUE; | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (stex)); | ||||
|   stex->remipmap_timeout_id = 0; | ||||
|  | ||||
|   return G_SOURCE_REMOVE; | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *stex) | ||||
| { | ||||
|   /* | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   actor = CLUTTER_ACTOR (stex); | ||||
|   do | ||||
|     { | ||||
|       if (clutter_actor_has_mapped_clones (actor)) | ||||
|         return NULL; | ||||
|       actor = clutter_actor_get_parent (actor); | ||||
|     } | ||||
|   while (actor != NULL); | ||||
|    */ | ||||
|  | ||||
|   return stex->unobscured_region; | ||||
| } | ||||
|  | ||||
| static void | ||||
| do_paint (MetaShapedTexture *stex, | ||||
|           CoglFramebuffer   *fb, | ||||
| @@ -696,21 +729,262 @@ do_paint (MetaShapedTexture *stex, | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_paint (ClutterActor *actor) | ||||
| { | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); | ||||
|   CoglTexture *paint_tex; | ||||
|   CoglFramebuffer *fb; | ||||
| do_paint_content (MetaShapedTexture *stex, | ||||
|                   ClutterPaintNode  *root_node, | ||||
|                   CoglTexture       *paint_tex, | ||||
|                   ClutterActorBox   *alloc, | ||||
|                   double             tex_scale, | ||||
|                   guchar             opacity) | ||||
|  | ||||
|   if (!stex->texture) | ||||
| { | ||||
|   int dst_width, dst_height; | ||||
|   cairo_rectangle_int_t tex_rect; | ||||
|   gboolean use_opaque_region; | ||||
|   cairo_region_t *clip_tex_region; | ||||
|   cairo_region_t *opaque_tex_region; | ||||
|   cairo_region_t *blended_tex_region; | ||||
|   CoglContext *ctx; | ||||
|   CoglPipelineFilter filter; | ||||
|  | ||||
|   ensure_size_valid (stex); | ||||
|  | ||||
|   dst_width = stex->dst_width; | ||||
|   dst_height = stex->dst_height; | ||||
|  | ||||
|   if (dst_width == 0 || dst_height == 0) /* no contents yet */ | ||||
|     return; | ||||
|  | ||||
|   tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height }; | ||||
|  | ||||
|   /* Use nearest-pixel interpolation if the texture is unscaled. This | ||||
|    * improves performance, especially with software rendering. | ||||
|    */ | ||||
|  | ||||
|   filter = COGL_PIPELINE_FILTER_LINEAR; | ||||
|  | ||||
|   /* FIXME: evil cogl_get_draw_framebuffer() */ | ||||
|   if (meta_actor_painting_untransformed (cogl_get_draw_framebuffer (), | ||||
|                                          dst_width, dst_height, | ||||
|                                          NULL, NULL)) | ||||
|     filter = COGL_PIPELINE_FILTER_NEAREST; | ||||
|  | ||||
|   ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); | ||||
|  | ||||
|   if (stex->opaque_region && opacity == 255) | ||||
|     { | ||||
|       opaque_tex_region = | ||||
|         meta_region_scale_double (stex->opaque_region, | ||||
|                                   1.0 / tex_scale, | ||||
|                                   META_ROUNDING_STRATEGY_SHRINK); | ||||
|       use_opaque_region = TRUE; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       opaque_tex_region = NULL; | ||||
|       use_opaque_region = FALSE; | ||||
|     } | ||||
|  | ||||
|   if (stex->clip_region) | ||||
|     { | ||||
|       clip_tex_region = | ||||
|         meta_region_scale_double (stex->clip_region, | ||||
|                                   1.0 / tex_scale, | ||||
|                                   META_ROUNDING_STRATEGY_GROW); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       clip_tex_region = NULL; | ||||
|     } | ||||
|  | ||||
|   if (use_opaque_region) | ||||
|     { | ||||
|       if (clip_tex_region) | ||||
|         blended_tex_region = cairo_region_copy (clip_tex_region); | ||||
|       else | ||||
|         blended_tex_region = cairo_region_create_rectangle (&tex_rect); | ||||
|  | ||||
|       cairo_region_subtract (blended_tex_region, opaque_tex_region); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (clip_tex_region) | ||||
|         blended_tex_region = cairo_region_reference (clip_tex_region); | ||||
|       else | ||||
|         blended_tex_region = NULL; | ||||
|     } | ||||
|  | ||||
|   /* Limit to how many separate rectangles we'll draw; beyond this just | ||||
|    * fall back and draw the whole thing */ | ||||
| #define MAX_RECTS 16 | ||||
|  | ||||
|   if (blended_tex_region) | ||||
|     { | ||||
|       int n_rects = cairo_region_num_rectangles (blended_tex_region); | ||||
|       if (n_rects > MAX_RECTS) | ||||
|         { | ||||
|           /* Fall back to taking the fully blended path. */ | ||||
|           use_opaque_region = FALSE; | ||||
|  | ||||
|           g_clear_pointer (&blended_tex_region, cairo_region_destroy); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   /* First, paint the unblended parts, which are part of the opaque region. */ | ||||
|   if (use_opaque_region) | ||||
|     { | ||||
|       cairo_region_t *region; | ||||
|       int n_rects; | ||||
|       int i; | ||||
|  | ||||
|       if (clip_tex_region) | ||||
|         { | ||||
|           region = cairo_region_copy (clip_tex_region); | ||||
|           cairo_region_intersect (region, opaque_tex_region); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           region = cairo_region_reference (opaque_tex_region); | ||||
|         } | ||||
|  | ||||
|       if (!cairo_region_is_empty (region)) | ||||
|         { | ||||
|           CoglPipeline *opaque_pipeline; | ||||
|  | ||||
|           opaque_pipeline = get_unblended_pipeline (stex, ctx); | ||||
|           cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); | ||||
|           cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); | ||||
|  | ||||
|           n_rects = cairo_region_num_rectangles (region); | ||||
|           for (i = 0; i < n_rects; i++) | ||||
|             { | ||||
|               cairo_rectangle_int_t rect; | ||||
|               cairo_region_get_rectangle (region, i, &rect); | ||||
|               paint_clipped_rectangle_node (root_node, opaque_pipeline, &rect, alloc); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|       cairo_region_destroy (region); | ||||
|     } | ||||
|  | ||||
|   /* Now, go ahead and paint the blended parts. */ | ||||
|  | ||||
|   /* We have three cases: | ||||
|    *   1) blended_tex_region has rectangles - paint the rectangles. | ||||
|    *   2) blended_tex_region is empty - don't paint anything | ||||
|    *   3) blended_tex_region is NULL - paint fully-blended. | ||||
|    * | ||||
|    *   1) and 3) are the times where we have to paint stuff. This tests | ||||
|    *   for 1) and 3). | ||||
|    */ | ||||
|   if (!blended_tex_region || !cairo_region_is_empty (blended_tex_region)) | ||||
|     { | ||||
|       CoglPipeline *blended_pipeline; | ||||
|  | ||||
|       if (stex->mask_texture == NULL) | ||||
|         { | ||||
|           blended_pipeline = get_unmasked_pipeline (stex, ctx); | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           blended_pipeline = get_masked_pipeline (stex, ctx); | ||||
|           cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); | ||||
|           cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); | ||||
|         } | ||||
|  | ||||
|       cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); | ||||
|       cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); | ||||
|  | ||||
|       CoglColor color; | ||||
|       cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); | ||||
|       cogl_pipeline_set_color (blended_pipeline, &color); | ||||
|  | ||||
|       if (blended_tex_region) | ||||
|         { | ||||
|           /* 1) blended_tex_region is not empty. Paint the rectangles. */ | ||||
|           int i; | ||||
|           int n_rects = cairo_region_num_rectangles (blended_tex_region); | ||||
|  | ||||
|           for (i = 0; i < n_rects; i++) | ||||
|             { | ||||
|               cairo_rectangle_int_t rect; | ||||
|               cairo_region_get_rectangle (blended_tex_region, i, &rect); | ||||
|  | ||||
|               if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect)) | ||||
|                 continue; | ||||
|  | ||||
|               paint_clipped_rectangle_node (root_node, blended_pipeline, &rect, alloc); | ||||
|             } | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           g_autoptr(ClutterPaintNode) node = NULL; | ||||
|  | ||||
|           node = clutter_pipeline_node_new (blended_pipeline); | ||||
|           clutter_paint_node_set_name (node, "MetaShapedTexture (unclipped)"); | ||||
|           clutter_paint_node_add_child (root_node, node); | ||||
|  | ||||
|           /* 3) blended_tex_region is NULL. Do a full paint. */ | ||||
|           clutter_paint_node_add_rectangle (node, alloc); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   g_clear_pointer (&clip_tex_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&opaque_tex_region, cairo_region_destroy); | ||||
|   g_clear_pointer (&blended_tex_region, cairo_region_destroy); | ||||
| } | ||||
|  | ||||
| static CoglTexture * | ||||
| select_texture_for_paint (MetaShapedTexture *stex) | ||||
| { | ||||
|   CoglTexture *texture = NULL; | ||||
|   gint64 now = g_get_monotonic_time (); | ||||
|  | ||||
|   if (stex->create_mipmaps && stex->last_invalidation) | ||||
|     { | ||||
|       gint64 age = now - stex->last_invalidation; | ||||
|  | ||||
|       if (age >= MIN_MIPMAP_AGE_USEC || | ||||
|           stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) | ||||
|         texture = meta_texture_tower_get_paint_texture (stex->paint_tower); | ||||
|     } | ||||
|  | ||||
|   if (texture == NULL) | ||||
|     { | ||||
|       texture = COGL_TEXTURE (stex->texture); | ||||
|  | ||||
|       if (texture == NULL) | ||||
|         return NULL; | ||||
|  | ||||
|       if (stex->create_mipmaps) | ||||
|         { | ||||
|           /* Minus 1000 to ensure we don't fail the age test in timeout */ | ||||
|           stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000; | ||||
|  | ||||
|           if (!stex->remipmap_timeout_id) | ||||
|             stex->remipmap_timeout_id = | ||||
|               g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000, | ||||
|                              texture_is_idle_and_not_mipmapped, | ||||
|                              stex); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   return texture; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_paint_content (ClutterContent   *content, | ||||
|                                    ClutterActor     *actor, | ||||
|                                    ClutterPaintNode *root_node) | ||||
| { | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); | ||||
|   ClutterActorBox alloc; | ||||
|   CoglTexture *paint_tex = NULL; | ||||
|   double tex_scale; | ||||
|   guchar opacity; | ||||
|  | ||||
|   if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) | ||||
|     return; | ||||
|  | ||||
|   if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) | ||||
|     clutter_actor_realize (CLUTTER_ACTOR (stex)); | ||||
|  | ||||
|   /* The GL EXT_texture_from_pixmap extension does allow for it to be | ||||
|    * used together with SGIS_generate_mipmap, however this is very | ||||
|    * rarely supported. Also, even when it is supported there | ||||
| @@ -726,100 +1000,40 @@ meta_shaped_texture_paint (ClutterActor *actor) | ||||
|    * Setting the texture quality to high without SGIS_generate_mipmap | ||||
|    * support for TFP textures will result in fallbacks to XGetImage. | ||||
|    */ | ||||
|   if (stex->create_mipmaps) | ||||
|     { | ||||
|       int64_t now = g_get_monotonic_time (); | ||||
|       int64_t age = now - stex->last_invalidation; | ||||
|  | ||||
|       if (age >= MIN_MIPMAP_AGE_USEC || | ||||
|           stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP) | ||||
|         { | ||||
|           paint_tex = meta_texture_tower_get_paint_texture (stex->paint_tower); | ||||
|           if (!paint_tex) | ||||
|             paint_tex = stex->texture; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           paint_tex = stex->texture; | ||||
|  | ||||
|           /* Minus 1000 to ensure we don't fail the age test in timeout */ | ||||
|           stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000; | ||||
|  | ||||
|           if (!stex->remipmap_timeout_id) | ||||
|             stex->remipmap_timeout_id = | ||||
|               g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000, | ||||
|                              texture_is_idle_and_not_mipmapped, | ||||
|                              stex); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       paint_tex = COGL_TEXTURE (stex->texture); | ||||
|     } | ||||
|  | ||||
|   if (cogl_texture_get_width (paint_tex) == 0 || | ||||
|       cogl_texture_get_height (paint_tex) == 0) | ||||
|   paint_tex = select_texture_for_paint (stex); | ||||
|   if (!paint_tex) | ||||
|     return; | ||||
|  | ||||
|   fb = cogl_get_draw_framebuffer (); | ||||
|   do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region); | ||||
| } | ||||
|   clutter_actor_get_scale (actor, &tex_scale, NULL); | ||||
|   opacity = clutter_actor_get_paint_opacity (actor); | ||||
|   clutter_actor_get_content_box (actor, &alloc); | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_get_preferred_width (ClutterActor *self, | ||||
|                                          gfloat        for_height, | ||||
|                                          gfloat       *min_width_p, | ||||
|                                          gfloat       *natural_width_p) | ||||
| { | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); | ||||
|  | ||||
|   ensure_size_valid (stex); | ||||
|  | ||||
|   if (min_width_p) | ||||
|     *min_width_p = stex->dst_width; | ||||
|   if (natural_width_p) | ||||
|     *natural_width_p = stex->dst_width; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_get_preferred_height (ClutterActor *self, | ||||
|                                           gfloat        for_width, | ||||
|                                           gfloat       *min_height_p, | ||||
|                                           gfloat       *natural_height_p) | ||||
| { | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); | ||||
|  | ||||
|   ensure_size_valid (stex); | ||||
|  | ||||
|   if (min_height_p) | ||||
|     *min_height_p = stex->dst_height; | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p = stex->dst_height; | ||||
| } | ||||
|  | ||||
| static cairo_region_t * | ||||
| effective_unobscured_region (MetaShapedTexture *stex) | ||||
| { | ||||
|   ClutterActor *actor; | ||||
|  | ||||
|   /* Fail if we have any mapped clones. */ | ||||
|   actor = CLUTTER_ACTOR (stex); | ||||
|   do | ||||
|     { | ||||
|       if (clutter_actor_has_mapped_clones (actor)) | ||||
|         return NULL; | ||||
|       actor = clutter_actor_get_parent (actor); | ||||
|     } | ||||
|   while (actor != NULL); | ||||
|  | ||||
|   return stex->unobscured_region; | ||||
|   do_paint_content (stex, root_node, paint_tex, &alloc, tex_scale, opacity); | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_shaped_texture_get_paint_volume (ClutterActor *actor, | ||||
|                                       ClutterPaintVolume *volume) | ||||
| meta_shaped_texture_get_preferred_size (ClutterContent *content, | ||||
|                                         float          *width, | ||||
|                                         float          *height) | ||||
| { | ||||
|   return clutter_paint_volume_set_from_allocation (volume, actor); | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (content); | ||||
|  | ||||
|   ensure_size_valid (stex); | ||||
|  | ||||
|   if (width) | ||||
|     *width = stex->dst_width * stex->scale; | ||||
|  | ||||
|   if (height) | ||||
|     *height = stex->dst_height * stex->scale; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| clutter_content_iface_init (ClutterContentIface *iface) | ||||
| { | ||||
|   iface->paint_content = meta_shaped_texture_paint_content; | ||||
|   iface->get_preferred_size = meta_shaped_texture_get_preferred_size; | ||||
| } | ||||
|  | ||||
| void | ||||
| @@ -853,7 +1067,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, | ||||
|       cogl_object_ref (stex->mask_texture); | ||||
|     } | ||||
|  | ||||
|   clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); | ||||
|   clutter_content_invalidate (CLUTTER_CONTENT (stex)); | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| @@ -944,7 +1158,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|         { | ||||
|           cairo_rectangle_int_t damage_rect; | ||||
|           cairo_region_get_extents (intersection, &damage_rect); | ||||
|           clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect); | ||||
|           clutter_content_invalidate (CLUTTER_CONTENT (stex)); | ||||
|           //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect); | ||||
|           cairo_region_destroy (intersection); | ||||
|           return TRUE; | ||||
|         } | ||||
| @@ -954,7 +1169,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); | ||||
|       clutter_content_invalidate (CLUTTER_CONTENT (stex)); | ||||
|       //clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip); | ||||
|       return TRUE; | ||||
|     } | ||||
| } | ||||
| @@ -1230,7 +1446,7 @@ meta_shaped_texture_get_image (MetaShapedTexture     *stex, | ||||
|  | ||||
|       transformed_clip = alloca (sizeof (cairo_rectangle_int_t)); | ||||
|  | ||||
|       clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); | ||||
|       tex_scale = stex->scale; | ||||
|       meta_rectangle_scale_double (clip, 1.0 / tex_scale, | ||||
|                                    META_ROUNDING_STRATEGY_GROW, | ||||
|                                    transformed_clip); | ||||
| @@ -1318,17 +1534,47 @@ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, | ||||
|   invalidate_size (stex); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_cull_out (MetaCullable   *cullable, | ||||
|                               cairo_region_t *unobscured_region, | ||||
|                               cairo_region_t *clip_region) | ||||
| ClutterActor * | ||||
| meta_shaped_texture_new (void) | ||||
| { | ||||
|   MetaShapedTexture *stex = META_SHAPED_TEXTURE (cullable); | ||||
|   return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_shaped_texture_set_scale (MetaShapedTexture *stex, | ||||
|                                double             scale) | ||||
| { | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   if (scale == stex->scale) | ||||
|     return; | ||||
|  | ||||
|   stex->scale = scale; | ||||
|  | ||||
|   invalidate_size (stex); | ||||
|   clutter_content_invalidate_size (CLUTTER_CONTENT (stex)); | ||||
| } | ||||
|  | ||||
| double | ||||
| meta_shaped_texture_get_scale (MetaShapedTexture *stex) | ||||
| { | ||||
|   g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 0.0); | ||||
|  | ||||
|   return stex->scale; | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_shaped_texture_cull_out (MetaShapedTexture *stex, | ||||
|                               cairo_region_t    *unobscured_region, | ||||
|                               cairo_region_t    *clip_region, | ||||
|                               uint8_t            opacity) | ||||
| { | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
|   set_unobscured_region (stex, unobscured_region); | ||||
|   set_clip_region (stex, clip_region); | ||||
|  | ||||
|   if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)) == 0xff) | ||||
|   if (opacity == 0xff) | ||||
|     { | ||||
|       if (stex->opaque_region) | ||||
|         { | ||||
| @@ -1340,22 +1586,10 @@ meta_shaped_texture_cull_out (MetaCullable   *cullable, | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_shaped_texture_reset_culling (MetaCullable *cullable) | ||||
| void | ||||
| meta_shaped_texture_reset_culling (MetaShapedTexture *stex) | ||||
| { | ||||
|   MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable); | ||||
|   set_clip_region (self, NULL); | ||||
| } | ||||
|   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); | ||||
|  | ||||
| static void | ||||
| cullable_iface_init (MetaCullableInterface *iface) | ||||
| { | ||||
|   iface->cull_out = meta_shaped_texture_cull_out; | ||||
|   iface->reset_culling = meta_shaped_texture_reset_culling; | ||||
| } | ||||
|  | ||||
| ClutterActor * | ||||
| meta_shaped_texture_new (void) | ||||
| { | ||||
|   return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL); | ||||
|   set_clip_region (stex, NULL); | ||||
| } | ||||
|   | ||||
| @@ -110,54 +110,6 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor) | ||||
|   return surface->window; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_get_preferred_width  (ClutterActor *actor, | ||||
|                                                  gfloat        for_height, | ||||
|                                                  gfloat       *min_width_p, | ||||
|                                                  gfloat       *natural_width_p) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaShapedTexture *stex; | ||||
|   double scale; | ||||
|  | ||||
|   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL); | ||||
|   clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex), | ||||
|                                      for_height, | ||||
|                                      min_width_p, | ||||
|                                      natural_width_p); | ||||
|  | ||||
|   if (min_width_p) | ||||
|      *min_width_p *= scale; | ||||
|  | ||||
|   if (natural_width_p) | ||||
|     *natural_width_p *= scale; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_get_preferred_height  (ClutterActor *actor, | ||||
|                                                   gfloat        for_width, | ||||
|                                                   gfloat       *min_height_p, | ||||
|                                                   gfloat       *natural_height_p) | ||||
| { | ||||
|   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); | ||||
|   MetaShapedTexture *stex; | ||||
|   double scale; | ||||
|  | ||||
|   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); | ||||
|   clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale); | ||||
|   clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex), | ||||
|                                       for_width, | ||||
|                                       min_height_p, | ||||
|                                       natural_height_p); | ||||
|  | ||||
|   if (min_height_p) | ||||
|      *min_height_p *= scale; | ||||
|  | ||||
|   if (natural_height_p) | ||||
|     *natural_height_p *= scale; | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_wayland_paint (ClutterActor *actor) | ||||
| { | ||||
| @@ -203,8 +155,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) | ||||
|   ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); | ||||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass); | ||||
|  | ||||
|   actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width; | ||||
|   actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height; | ||||
|   actor_class->paint = meta_surface_actor_wayland_paint; | ||||
|  | ||||
|   surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; | ||||
|   | ||||
| @@ -158,13 +158,22 @@ meta_surface_actor_cull_out (MetaCullable   *cullable, | ||||
|                              cairo_region_t *unobscured_region, | ||||
|                              cairo_region_t *clip_region) | ||||
| { | ||||
|   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); | ||||
|   MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); | ||||
|   MetaSurfaceActorPrivate *priv = | ||||
|     meta_surface_actor_get_instance_private (surface_actor); | ||||
|   uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable)); | ||||
|  | ||||
|   meta_shaped_texture_cull_out (priv->texture, unobscured_region, clip_region, opacity); | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_surface_actor_reset_culling (MetaCullable *cullable) | ||||
| { | ||||
|   meta_cullable_reset_culling_children (cullable); | ||||
|   MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable); | ||||
|   MetaSurfaceActorPrivate *priv = | ||||
|     meta_surface_actor_get_instance_private (surface_actor); | ||||
|  | ||||
|   meta_shaped_texture_reset_culling (priv->texture); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -191,7 +200,8 @@ meta_surface_actor_init (MetaSurfaceActor *self) | ||||
|   priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ()); | ||||
|   g_signal_connect_object (priv->texture, "size-changed", | ||||
|                            G_CALLBACK (texture_size_changed), self, 0); | ||||
|   clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture)); | ||||
|   clutter_actor_set_content (CLUTTER_ACTOR (self), CLUTTER_CONTENT (priv->texture)); | ||||
|   clutter_actor_set_request_mode (CLUTTER_ACTOR (self), CLUTTER_REQUEST_CONTENT_SIZE); | ||||
| } | ||||
|  | ||||
| cairo_surface_t * | ||||
|   | ||||
| @@ -829,14 +829,14 @@ meta_window_actor_get_meta_window (MetaWindowActor *self) | ||||
|  * | ||||
|  * Return value: (transfer none): the #ClutterActor for the contents | ||||
|  */ | ||||
| ClutterActor * | ||||
| MetaShapedTexture * | ||||
| meta_window_actor_get_texture (MetaWindowActor *self) | ||||
| { | ||||
|   MetaWindowActorPrivate *priv = | ||||
|     meta_window_actor_get_instance_private (self); | ||||
|  | ||||
|   if (priv->surface) | ||||
|     return CLUTTER_ACTOR (meta_surface_actor_get_texture (priv->surface)); | ||||
|     return meta_surface_actor_get_texture (priv->surface); | ||||
|   else | ||||
|     return NULL; | ||||
| } | ||||
| @@ -1875,19 +1875,19 @@ meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, | ||||
|   MetaShapedTexture *stex; | ||||
|   MetaRectangle buffer_rect; | ||||
|   MetaRectangle frame_rect; | ||||
|   double scale_x, scale_y; | ||||
|   double scale; | ||||
|  | ||||
|   stex = meta_surface_actor_get_texture (priv->surface); | ||||
|   clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y); | ||||
|   scale = meta_shaped_texture_get_scale (stex); | ||||
|  | ||||
|   window = priv->window; | ||||
|   meta_window_get_buffer_rect (window, &buffer_rect); | ||||
|   meta_window_get_frame_rect (window, &frame_rect); | ||||
|  | ||||
|   bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x); | ||||
|   bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y); | ||||
|   bounds->width = (int) ceil (frame_rect.width / scale_x); | ||||
|   bounds->height = (int) ceil (frame_rect.height / scale_y); | ||||
|   bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale); | ||||
|   bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale); | ||||
|   bounds->width = (int) ceil (frame_rect.width / scale); | ||||
|   bounds->height = (int) ceil (frame_rect.height / scale); | ||||
| } | ||||
|  | ||||
| static void | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
|  | ||||
| #include "clutter/clutter.h" | ||||
| #include "meta/compositor.h" | ||||
| #include "meta/meta-shaped-texture.h" | ||||
|  | ||||
| #define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ()) | ||||
|  | ||||
| @@ -43,7 +44,7 @@ META_EXPORT | ||||
| MetaWindow *       meta_window_actor_get_meta_window      (MetaWindowActor *self); | ||||
|  | ||||
| META_EXPORT | ||||
| ClutterActor *     meta_window_actor_get_texture          (MetaWindowActor *self); | ||||
| MetaShapedTexture *meta_window_actor_get_texture          (MetaWindowActor *self); | ||||
|  | ||||
| META_EXPORT | ||||
| void               meta_window_actor_sync_visibility      (MetaWindowActor *self); | ||||
|   | ||||
| @@ -163,7 +163,7 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor | ||||
|   stex = meta_surface_actor_get_texture (surface_actor); | ||||
|  | ||||
|   actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface); | ||||
|   clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale); | ||||
|   meta_shaped_texture_set_scale (stex, actor_scale); | ||||
|  | ||||
|   /* Wayland surface coordinate space -> stage coordinate space */ | ||||
|   geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface); | ||||
|   | ||||
| @@ -1123,7 +1123,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice                 *data | ||||
|  | ||||
|   surface_actor = meta_wayland_surface_get_actor (surface); | ||||
|  | ||||
|   clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)), | ||||
|   clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor), | ||||
|                                        seat->pointer->grab_x, | ||||
|                                        seat->pointer->grab_y, | ||||
|                                        &surface_pos.x, &surface_pos.y); | ||||
|   | ||||
| @@ -1514,7 +1514,7 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface, | ||||
|   else | ||||
|     { | ||||
|       ClutterActor *actor = | ||||
|         CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface))); | ||||
|         CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); | ||||
|  | ||||
|       clutter_actor_transform_stage_point (actor, abs_x, abs_y, sx, sy); | ||||
|       *sx /= surface->scale; | ||||
| @@ -1530,7 +1530,7 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface, | ||||
|                                                float               *y) | ||||
| { | ||||
|   ClutterActor *actor = | ||||
|     CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface))); | ||||
|     CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface)); | ||||
|   ClutterVertex sv = { | ||||
|     .x = sx * surface->scale, | ||||
|     .y = sy * surface->scale, | ||||
|   | ||||
| @@ -640,7 +640,7 @@ meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool, | ||||
|   surface_actor = meta_wayland_surface_get_actor (surface); | ||||
|  | ||||
|   clutter_event_get_coords (event, &xf, &yf); | ||||
|   clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)), | ||||
|   clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor), | ||||
|                                        xf, yf, &xf, &yf); | ||||
|  | ||||
|   *sx = wl_fixed_from_double (xf) / surface->scale; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user