diff src/redisplay-output.c @ 404:2f8bb876ab1d r21-2-32

Import from CVS: tag r21-2-32
author cvs
date Mon, 13 Aug 2007 11:16:07 +0200
parents 74fd4e045ea6
children b8cc9ab3f761
line wrap: on
line diff
--- a/src/redisplay-output.c	Mon Aug 13 11:15:00 2007 +0200
+++ b/src/redisplay-output.c	Mon Aug 13 11:16:07 2007 +0200
@@ -101,7 +101,7 @@
  For the given LINE in window W, make the current display line equal
  the desired display line.
  ****************************************************************************/
-static void
+void
 sync_display_line_structs (struct window *w, int line, int do_blocks,
 			   display_line_dynarr *cdla,
 			   display_line_dynarr *ddla)
@@ -211,10 +211,7 @@
      #### It would really be worth it to arrange for this function to
      be (almost) a single call to memcmp. */
 
-  if ((crb->findex != drb->findex) ||
-      (WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
-    return 0;
-  else if (crb->xpos != drb->xpos)
+  if (crb->xpos != drb->xpos)
     return 0;
   else if (crb->width != drb->width)
     return 0;
@@ -236,17 +233,67 @@
     return 0;
   /* Only check dirtiness if we know something has changed. */
   else if (crb->type == RUNE_DGLYPH &&
-	   XFRAME (w->frame)->glyphs_changed)
+	   ((XFRAME (w->frame)->glyphs_changed &&
+	     XGLYPH_DIRTYP (crb->object.dglyph.glyph)) || 
+	    crb->findex != drb->findex))
     {
-      glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph);
-      /* Although doing the cachel lookup for every comparison is
-	 very expensive.we have to do it to make sure the cache is
-	 up-to-date. */
-      if (GLYPH_CACHEL_DIRTYP (w, gindex))
+      /* We need some way of telling redisplay_output_layout () that the
+         only reason we are outputting it is because something has
+         changed internally. That way we can optimize whether we need
+         to clear the layout first and also only output the components
+         that have changed. The image_instance dirty flag and
+         display_hash are no good to us because these will invariably
+         have been set anyway if the layout has changed. So it looks
+         like we need yet another change flag that we can set here and
+         then clear in redisplay_output_layout (). */
+      Lisp_Object window, image;
+      Lisp_Image_Instance* ii;
+      XSETWINDOW (window, w);
+      image = glyph_image_instance (crb->object.dglyph.glyph,
+				    window, ERROR_ME_NOT, 1);
+      ii = XIMAGE_INSTANCE (image);
+
+      if (TEXT_IMAGE_INSTANCEP (image) && 
+	  (crb->findex != drb->findex || 
+	   WINDOW_FACE_CACHEL_DIRTY (w, drb->findex)))
 	return 0;
+
+      /* It is quite common of the two glyphs to be EQ since in many
+	 cases they will actually be the same object. This does not
+	 mean, however, that nothing has changed. We therefore need to
+	 check the current hash of the glyph against the last recorded
+	 display hash. See update_subwindow (). */
+      if (IMAGE_INSTANCE_DISPLAY_HASH (ii) == 0 ||
+	  IMAGE_INSTANCE_DISPLAY_HASH (ii) != 
+	  internal_hash (image, IMAGE_INSTANCE_HASH_DEPTH) ||
+	  crb->findex != drb->findex || 
+	  WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
+	{
+	  /* We now now we are going to re-output the glyph, but since
+	     this is for some internal reason not related to geometry
+	     changes, send a hint to the output routines that they can
+	     take some short cuts. This is most useful for
+	     layouts. This flag should get reset by the output
+	     routines. 
+
+	     #### It is possible for us to get here when the
+	     face_cachel is dirty. I do not know what the implications
+	     of this are.*/
+	  IMAGE_INSTANCE_OPTIMIZE_OUTPUT (ii) = 1;
+	  return 0;
+	}
       else
 	return 1;
     }
+  /* We now do this last so that glyph checks can do their own thing
+     for face changes. Face changes quite often happen when we are
+     trying to output something in the gutter, this would normally
+     lead to a lot of flashing. The indices can quite often be
+     different and yet the faces are the same, we do not want to
+     re-output in this instance. */
+  else  if (crb->findex != drb->findex ||
+	    WINDOW_FACE_CACHEL_DIRTY (w, drb->findex))
+    return 0;
   else
     return 1;
 }
@@ -1067,6 +1114,8 @@
 {
   struct frame *f = XFRAME (w->frame);
   struct device *d = XDEVICE (f->device);
+  /* Temporarily disabled until generalization is done. */
+#if 0
   struct display_block *db = Dynarr_atp (dl->display_blocks, block);
   rune_dynarr *rba = db->runes;
   struct rune *rb;
@@ -1084,6 +1133,7 @@
 
   rb  = Dynarr_atp (rba, end - 1);
   width = rb->xpos + rb->width - xpos;
+#endif
   /* now actually output the block. */
   DEVMETH (d, output_display_block, (w, dl, block, start,
 				     end, start_pixpos,
@@ -1243,17 +1293,6 @@
   struct frame *f = XFRAME (w->frame);
   struct device *d = XDEVICE (f->device);
   int layout_height, layout_width;
-  /* We bogusly don't take f->extents_changed and f->glyphs_changed
-     into account. This is because if we do we always redisplay the
-     entire layout. So far I have seen no ill effects so we'll see. */
-  int frame_really_changed = (f->buffers_changed ||
-			      f->clip_changed ||
-			      f->faces_changed    ||
-			      f->frame_changed    ||
-			      f->modeline_changed ||
-			      f->subwindows_changed ||
-			      f->windows_changed ||
-			      f->windows_structure_changed);
 
   XSETWINDOW (window, w);
 
@@ -1269,7 +1308,7 @@
 
   /* Highly dodgy optimization. We want to only output the whole
      layout if we really have to. */
-  if (frame_really_changed 
+  if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p)
       || IMAGE_INSTANCE_LAYOUT_CHANGED (p)
       || IMAGE_INSTANCE_WIDGET_FACE_CHANGED (p)
       || IMAGE_INSTANCE_SIZE_CHANGED (p)
@@ -1342,6 +1381,7 @@
       if (IMAGE_INSTANCEP (child))
 	{
 	  Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child);
+
 	  /* The enclosing layout offsets are +ve at this point */
 	  struct display_glyph_area cdga;
 	  cdga.xoffset  = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset;
@@ -1349,6 +1389,9 @@
 	  cdga.width = glyph_width (child, window);
 	  cdga.height = glyph_height (child, window);
 
+	  IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 
+	    IMAGE_INSTANCE_OPTIMIZE_OUTPUT (p);
+
 	  /* Although normalization is done by the output routines
 	     we have to do it here so that they don't try and
 	     clear all of db. This is true below also. */
@@ -1375,7 +1418,8 @@
 		       generalisation.*/
 		    if (redisplay_normalize_glyph_area (&cdb, &cdga)
 			&&
-			(frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii)))
+			(!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
+			 IMAGE_INSTANCE_DIRTYP (childii)))
 		      {
 			struct display_line dl;	/* this is fake */
 			Lisp_Object string =
@@ -1409,14 +1453,16 @@
 
 		case IMAGE_MONO_PIXMAP:
 		case IMAGE_COLOR_PIXMAP:
-		  if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
+		  if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii)
+		      || IMAGE_INSTANCE_DIRTYP (childii))
 		    redisplay_output_pixmap (w, child, &cdb, &cdga, findex,
 					     0, 0, 0, 0);
 		  break;
 
 		case IMAGE_WIDGET:
 		case IMAGE_SUBWINDOW:
-		  if (frame_really_changed || IMAGE_INSTANCE_DIRTYP (childii))
+		  if (!IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) ||
+		      IMAGE_INSTANCE_DIRTYP (childii))
 		    redisplay_output_subwindow (w, child, &cdb, &cdga, findex,
 						0, 0, 0);
 		  break;
@@ -1435,6 +1481,7 @@
 		  abort ();
 		}
 	    }
+	  IMAGE_INSTANCE_OPTIMIZE_OUTPUT (childii) = 0;
 	}
     }