Author: mdk
Date: 2008-02-14 10:25:50 -0500 (Thu, 14 Feb 2008)
New Revision: 95638
Modified:
trunk/moon/src/ChangeLog
trunk/moon/src/shape.cpp
trunk/moon/src/shape.h
Log:
2008-02-14 Michael Dominic K. <[EMAIL PROTECTED]>
* src/shape.cpp:
* src/shape.h: Adding surface caching for shapes. The strategy
is to cache big surfaces that have little transformations (such as
ie. backgrounds, fade overlays, etc.). Improves performance greatly
for many sites (ie. Showcase).
Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog 2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/ChangeLog 2008-02-14 15:25:50 UTC (rev 95638)
@@ -1,5 +1,13 @@
2008-02-14 Michael Dominic K. <[EMAIL PROTECTED]>
+ * src/shape.cpp:
+ * src/shape.h: Adding surface caching for shapes. The strategy
+ is to cache big surfaces that have little transformations (such as
+ ie. backgrounds, fade overlays, etc.). Improves performance greatly
+ for many sites (ie. Showcase).
+
+2008-02-14 Michael Dominic K. <[EMAIL PROTECTED]>
+
* src/uielement.cpp: Commenting out the timer in post-pre render as it's
broken and blocks the compilation with timers on.
Modified: trunk/moon/src/shape.cpp
===================================================================
--- trunk/moon/src/shape.cpp 2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/shape.cpp 2008-02-14 15:25:50 UTC (rev 95638)
@@ -5,6 +5,7 @@
* Miguel de Icaza ([EMAIL PROTECTED])
* Sebastien Pouliot <[EMAIL PROTECTED]>
* Stephane Delcroix <[EMAIL PROTECTED]>
+ * Michael Dominic K. <[EMAIL PROTECTED]>
*
* Copyright 2007-2008 Novell, Inc. (http://www.novell.com)
*
@@ -107,6 +108,7 @@
fill = NULL;
path = NULL;
origin = Point (0, 0);
+ cached_surface = NULL;
SetShapeFlags (UIElement::SHAPE_NORMAL);
}
@@ -121,6 +123,8 @@
fill->Detach (NULL, this);
fill->unref ();
}
+
+ // That also destroys the cached surface
InvalidatePathCache (true);
}
@@ -270,37 +274,79 @@
}
}
+int number = 0;
+
//
+// Returns TRUE if surface is a good candidate for caching.
+// Our current strategy is to cache big surfaces (likely backgrounds)
+// that don't scale tranformations. We accept a little bit of scaling though.
+//
+bool
+Shape::IsCandidateForCaching (void)
+{
+ if (bounds.w + bounds.h < 300)
+ return FALSE;
+
+ int diffw = fabs (bounds.w - extents.w);
+ int diffh = fabs (bounds.h - extents.h);
+
+ if (diffw > 5 || diffh > 5)
+ return FALSE;
+
+ return TRUE;
+}
+
+//
// This routine is useful for Shape derivatives: it can be used
// to either get the bounding box from cairo, or to paint it
//
void
Shape::DoDraw (cairo_t *cr, bool do_op)
{
+ int w;
+ int h;
+ cairo_t *cached_cr = NULL;
+ cairo_pattern_t *cached_pattern = NULL;
+ bool ret = FALSE;
+ gchar *fname;
+
// quick out if, when building the path, we detected a empty shape
if (IsEmpty ())
goto cleanpath;
- cairo_set_matrix (cr, &absolute_xform);
+ if (!do_op) {
+ cairo_set_matrix (cr, &absolute_xform);
+ Clip (cr);
-// printf ("Draw, xform: %g %g %g %g %g %g\n",
-// absolute_xform.xy,
-// absolute_xform.xx,
-// absolute_xform.yx,
-// absolute_xform.yy,
-// absolute_xform.x0,
-// absolute_xform.y0);
-
- Clip (cr);
-
- // if building the path detected a degenerate case
- if (IsDegenerate ()) {
- // FIXME: needs a DrawDegenerateShape to get more control over
output
if (DrawShape (cr, do_op))
return;
} else {
- if (DrawShape (cr, do_op))
- return;
+ if (cached_surface == NULL && IsCandidateForCaching ()) {
+ w = extents.w + extents.x;
+ h = extents.h + extents.y;
+ w = MAX (w, 1);
+ h = MAX (h, 1);
+
+ cached_surface = image_brush_create_similar (cr, w, h);
+ cached_cr = cairo_create (cached_surface);
+ ret = DrawShape (cached_cr, do_op);
+ cairo_destroy (cached_cr);
+ }
+
+ cairo_set_matrix (cr, &absolute_xform);
+ Clip (cr);
+
+ if (cached_surface) {
+ cached_pattern = cairo_pattern_create_for_surface
(cached_surface);
+ cairo_set_source (cr, cached_pattern);
+ cairo_paint (cr);
+ cairo_pattern_destroy (cached_pattern);
+ if (ret)
+ return;
+ } else {
+ if (DrawShape (cr, do_op))
+ return;
+ }
}
cleanpath:
@@ -397,6 +443,7 @@
void
Shape::OnPropertyChanged (DependencyProperty *prop)
{
+
if (prop->type != Type::SHAPE) {
if ((prop == FrameworkElement::HeightProperty) || (prop ==
FrameworkElement::WidthProperty))
InvalidatePathCache ();
@@ -420,6 +467,7 @@
stroke->ref ();
}
+ InvalidateSurfaceCache ();
UpdateBounds ();
} else if (prop == Shape::FillProperty) {
if (fill != NULL) {
@@ -432,6 +480,7 @@
fill->ref ();
}
+ InvalidateSurfaceCache ();
UpdateBounds ();
} else if (prop == Shape::StrokeThicknessProperty) {
InvalidatePathCache ();
@@ -442,6 +491,7 @@
|| prop == Shape::StrokeMiterLimitProperty
|| prop == Shape::StrokeStartLineCapProperty) {
UpdateBounds ();
+ InvalidateSurfaceCache ();
}
Invalidate ();
@@ -454,6 +504,7 @@
{
if (prop == Shape::FillProperty || prop == Shape::StrokeProperty) {
Invalidate ();
+ InvalidateSurfaceCache ();
}
else
FrameworkElement::OnSubPropertyChanged (prop, obj, subprop);
@@ -468,7 +519,6 @@
framework_element_get_height (this) * user_xform_origin.y);
}
-
void
Shape::InvalidatePathCache (bool free)
{
@@ -481,8 +531,19 @@
moon_path_clear (path);
}
}
+
+ InvalidateSurfaceCache ();
}
+void
+Shape::InvalidateSurfaceCache (void)
+{
+ if (cached_surface) {
+ cairo_surface_destroy (cached_surface);
+ cached_surface = NULL;
+ }
+}
+
Brush *
shape_get_fill (Shape *shape)
{
@@ -762,6 +823,7 @@
if ((prop == Shape::StrokeThicknessProperty) || (prop ==
Shape::StretchProperty) ||
(prop == FrameworkElement::WidthProperty) || (prop ==
FrameworkElement::HeightProperty)) {
BuildPath ();
+ InvalidateSurfaceCache ();
}
// Ellipse has no property of it's own
Modified: trunk/moon/src/shape.h
===================================================================
--- trunk/moon/src/shape.h 2008-02-14 15:23:13 UTC (rev 95637)
+++ trunk/moon/src/shape.h 2008-02-14 15:25:50 UTC (rev 95638)
@@ -4,6 +4,7 @@
* Author:
* Miguel de Icaza ([EMAIL PROTECTED])
* Sebastien Pouliot <[EMAIL PROTECTED]>
+ * Michael Dominic K. <[EMAIL PROTECTED]>
*
* Copyright 2007-2008 Novell, Inc. (http://www.novell.com)
*
@@ -36,6 +37,8 @@
protected:
Brush *stroke, *fill;
Point origin;
+ cairo_surface_t *cached_surface;
+
void DoDraw (cairo_t *cr, bool do_op);
void SetupLineCaps (cairo_t *cr);
@@ -49,6 +52,8 @@
moon_path *path;
virtual void InvalidatePathCache (bool free = false);
+ void InvalidateSurfaceCache (void);
+ bool IsCandidateForCaching (void);
virtual Rect ComputeShapeBounds ();
virtual Rect ComputeLargestRectangle ();
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches