b=459150; avoid non-pixel-aligned clips to speed up mobile's DrawWindow usage; r=stuart
authorVladimir Vukicevic <vladimir@pobox.com>
Thu, 09 Oct 2008 14:49:15 -0700
changeset 20226 63c6632d85986a434ddf977b2545fd90b769aa29
parent 20225 60a855404ff85f9f4fdcedafa07b9b0b339b452b
child 20227 c6e54a6530ec542a08e6660cd2d2da4193ea756b
push idunknown
push userunknown
push dateunknown
reviewersstuart
bugs459150
milestone1.9.1b2pre
b=459150; avoid non-pixel-aligned clips to speed up mobile's DrawWindow usage; r=stuart
configure.in
gfx/src/thebes/nsThebesImage.cpp
gfx/thebes/src/gfxContext.cpp
layout/base/nsPresShell.cpp
--- a/configure.in
+++ b/configure.in
@@ -6085,17 +6085,19 @@ AC_SUBST(LIBHILDONMIME_LIBS)
 PKG_CHECK_MODULES(LIBOSSO,libosso,
                   NS_OSSO=1,
                   NS_OSSO=)
 
 if test $NS_OSSO; then
     if test -z "$MOZ_ENABLE_DBUS"; then
         AC_MSG_ERROR([DBus is required when building for OSSO])
     fi
-    AC_DEFINE(NS_OSSO)     
+    AC_DEFINE(NS_OSSO)
+    dnl XXX this should go somewhere else; it's not just for OSSO
+    AC_DEFINE(MOZ_GFX_OPTIMIZE_MOBILE)
 fi
 AC_SUBST(LIBOSSO_CFLAGS)
 AC_SUBST(LIBOSSO_LIBS)
 
 PKG_CHECK_MODULES(MOZ_LOCATION, [liblocation gpsbt],
                   NS_MAEMO_LOCATION=1,
                   NS_MAEMO_LOCATION=)
 
--- a/gfx/src/thebes/nsThebesImage.cpp
+++ b/gfx/src/thebes/nsThebesImage.cpp
@@ -624,17 +624,21 @@ nsThebesImage::Draw(nsIRenderingContext 
     }
 
     gfxContext::GraphicsOperator op = ctx->CurrentOperator();
     if (op == gfxContext::OPERATOR_OVER && mFormat == gfxASurface::ImageFormatRGB24)
         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
 
     ctx->NewPath();
     ctx->SetPattern(pat);
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+    ctx->Rectangle(destRect, PR_TRUE);
+#else
     ctx->Rectangle(destRect);
+#endif
     ctx->Fill();
 
     ctx->SetOperator(op);
     ctx->SetDeviceColor(gfxRGBA(0,0,0,0));
 
     return NS_OK;
 }
 
@@ -651,17 +655,21 @@ nsThebesImage::ThebesDrawTile(gfxContext
 
     if (targetRect.size.width <= 0.0 || targetRect.size.height <= 0.0)
         return NS_OK;
 
     // don't do anything if we have a transparent pixel source
     if (mSinglePixel && mSinglePixelColor.a == 0.0)
         return NS_OK;
 
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+    PRBool doSnap = PR_TRUE;
+#else
     PRBool doSnap = !(thebesContext->CurrentMatrix().HasNonTranslation());
+#endif
     PRBool hasPadding = ((xPadding != 0) || (yPadding != 0));
     gfxImageSurface::gfxImageFormat format = mFormat;
     
     gfxPoint tmpOffset = offset;
 
     if (mSinglePixel && !hasPadding) {
         thebesContext->SetDeviceColor(mSinglePixelColor);
     } else {
--- a/gfx/thebes/src/gfxContext.cpp
+++ b/gfx/thebes/src/gfxContext.cpp
@@ -212,17 +212,22 @@ gfxContext::Line(const gfxPoint& start, 
 // For odd-width stroked rectangles, we need to offset x/y by
 // 0.5...
 void
 gfxContext::Rectangle(const gfxRect& rect, PRBool snapToPixels)
 {
     if (snapToPixels) {
         gfxRect snappedRect(rect);
 
-        if (UserToDevicePixelSnapped(snappedRect)) {
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+        if (UserToDevicePixelSnapped(snappedRect, PR_TRUE))
+#else
+        if (UserToDevicePixelSnapped(snappedRect))
+#endif
+        {
             cairo_matrix_t mat;
             cairo_get_matrix(mCairo, &mat);
             cairo_identity_matrix(mCairo);
             Rectangle(snappedRect);
             cairo_set_matrix(mCairo, &mat);
 
             return;
         }
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -4910,34 +4910,52 @@ PresShell::RenderDocument(const nsRect& 
                           gfxContext* aThebesContext)
 {
   NS_ENSURE_TRUE(!aUntrusted, NS_ERROR_NOT_IMPLEMENTED);
 
   gfxRect r(0, 0,
             nsPresContext::AppUnitsToFloatCSSPixels(aRect.width),
             nsPresContext::AppUnitsToFloatCSSPixels(aRect.height));
   aThebesContext->Save();
-  aThebesContext->Clip(r);
-
-  aThebesContext->PushGroup(NS_GET_A(aBackgroundColor) == 0xff ?
-                            gfxASurface::CONTENT_COLOR :
-                            gfxASurface::CONTENT_COLOR_ALPHA);
-
-  aThebesContext->Save();
+
+  aThebesContext->NewPath();
+#ifdef MOZ_GFX_MOBILE_OPTIMIZE
+  aThebesContext->Rectangle(r, PR_TRUE);
+#else
+  aThebesContext->Rectangle(r);
+#endif
+  aThebesContext->Clip();
+
+  // we can avoid using a temporary surface if we're using OPERATOR_OVER
+  // and our background color has no alpha (so we'll be compositing on top
+  // of a fully opaque solid color region)
+  PRBool needsGroup = PR_TRUE;
+  if (aThebesContext->CurrentOperator() == gfxContext::OPERATOR_OVER &&
+      NS_GET_A(aBackgroundColor) == 0xff)
+    needsGroup = PR_FALSE;
+
+  if (needsGroup) {
+    aThebesContext->PushGroup(NS_GET_A(aBackgroundColor) == 0xff ?
+                              gfxASurface::CONTENT_COLOR :
+                              gfxASurface::CONTENT_COLOR_ALPHA);
+
+    aThebesContext->Save();
+  }
 
   // draw background color
   if (NS_GET_A(aBackgroundColor) > 0) {
     aThebesContext->SetColor(gfxRGBA(aBackgroundColor));
     aThebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);
     aThebesContext->Paint();
   }
 
   // we want the window to be composited as a single image using
-  // whatever operator was set, so set this to the default OVER;
-  // the original operator will be present when we PopGroup
+  // whatever operator was set; set OPERATOR_OVER here, which is
+  // either already the case, or overrides the operator in a group.
+  // the original operator will be present when we PopGroup.
   aThebesContext->SetOperator(gfxContext::OPERATOR_OVER);
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
   if (rootFrame) {
     nsDisplayListBuilder builder(rootFrame, PR_FALSE, PR_FALSE);
     nsDisplayList list;
 
     nsRect rect(aRect);
@@ -4974,19 +4992,22 @@ PresShell::RenderDocument(const nsRect& 
       list.Paint(&builder, rc, rect);
       // Flush the list so we don't trigger the IsEmpty-on-destruction assertion
       list.DeleteAll();
 
       aThebesContext->Restore();
     }
   }
 
-  aThebesContext->Restore();
-  aThebesContext->PopGroupToSource();
-  aThebesContext->Paint();
+  // if we had to use a group, paint it to the destination now
+  if (needsGroup) {
+    aThebesContext->Restore();
+    aThebesContext->PopGroupToSource();
+    aThebesContext->Paint();
+  }
 
   aThebesContext->Restore();
 
   return NS_OK;
 }
 
 /*
  * Clip the display list aList to a range. Returns the clipped