Bug 740200 - Azure support in nsWindow; r=mattwoodrow
☠☠ backed out by 25ee493a6e17 ☠ ☠
authorAnthony Jones <ajones@mozilla.com>
Thu, 19 Sep 2013 16:29:51 +1200
changeset 147842 dc8bddfca5f10514f1012c9d9d94a5643d16ca3a
parent 147841 439ff7e64d35daa305fcdcb49916da890fec931f
child 147843 bf8d5d78b27e91fe55deb25203c6ed23a1c963f8
push id25317
push useremorley@mozilla.com
push dateThu, 19 Sep 2013 14:37:38 +0000
treeherdermozilla-central@70a765607344 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs740200
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 740200 - Azure support in nsWindow; r=mattwoodrow
widget/gtk2/nsWindow.cpp
widget/gtk2/nsWindow.h
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -2107,22 +2107,41 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 
         listener->PaintWindow(this, region);
         listener->DidPaintWindow();
 
         g_free(rects);
         return TRUE;
     }
 
+    gfxASurface* surf;
 #if defined(MOZ_WIDGET_GTK2)
-    nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface());
+    surf = GetThebesSurface();
 #else
-    nsRefPtr<gfxContext> ctx = new gfxContext(GetThebesSurface(cr));
+    surf = GetThebesSurface(cr);
 #endif
 
+    nsRefPtr<gfxContext> ctx;
+    if (gfxPlatform::GetPlatform()->
+            SupportsAzureContentForType(BACKEND_CAIRO)) {
+        IntSize intSize(surf->GetSize().width, surf->GetSize().height);
+        ctx = new gfxContext(gfxPlatform::GetPlatform()->
+            CreateDrawTargetForSurface(surf, intSize));
+    } else if (gfxPlatform::GetPlatform()->
+                   SupportsAzureContentForType(BACKEND_SKIA) &&
+               surf->GetType() != gfxASurface::SurfaceTypeImage) {
+       gfxImageSurface* imgSurf = static_cast<gfxImageSurface*>(surf);
+       SurfaceFormat format = ImageFormatToSurfaceFormat(imgSurf->Format());
+       IntSize intSize(surf->GetSize().width, surf->GetSize().height);
+       ctx = new gfxContext(gfxPlatform::GetPlatform()->CreateDrawTargetForData(
+           imgSurf->Data(), intSize, imgSurf->Stride(), format));
+    }  else {
+        ctx = new gfxContext(surf);
+    }
+
 #ifdef MOZ_X11
     nsIntRect boundsRect; // for shaped only
 
     ctx->NewPath();
     if (shaped) {
         // Collapse update area to the bounding box. This is so we only have to
         // call UpdateTranslucentWindowAlpha once. After we have dropped
         // support for non-Thebes graphics, UpdateTranslucentWindowAlpha will be
@@ -2176,33 +2195,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 #ifdef MOZ_X11
     // PaintWindow can Destroy us (bug 378273), avoid doing any paint
     // operations below if that happened - it will lead to XError and exit().
     if (shaped) {
         if (MOZ_LIKELY(!mIsDestroyed)) {
             if (painted) {
                 nsRefPtr<gfxPattern> pattern = ctx->PopGroup();
 
-                nsRefPtr<gfxImageSurface> img =
-                    new gfxImageSurface(gfxIntSize(boundsRect.width, boundsRect.height),
-                                        gfxImageSurface::ImageFormatA8);
-                if (img && !img->CairoStatus()) {
-                    img->SetDeviceOffset(gfxPoint(-boundsRect.x, -boundsRect.y));
-
-                    nsRefPtr<gfxContext> imgCtx = new gfxContext(img);
-                    if (imgCtx) {
-                        imgCtx->SetPattern(pattern);
-                        imgCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
-                        imgCtx->Paint();
-                    }
-
-                    UpdateTranslucentWindowAlphaInternal(nsIntRect(boundsRect.x, boundsRect.y,
-                                                                   boundsRect.width, boundsRect.height),
-                                                         img->Data(), img->Stride());
-                }
+                UpdateAlpha(pattern, boundsRect);
 
                 ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
                 ctx->SetPattern(pattern);
                 ctx->Paint();
             }
         }
     }
 #  ifdef MOZ_HAVE_SHMIMAGE
@@ -2240,16 +2243,54 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 #endif
         gdk_window_process_updates(mGdkWindow, false);
     }
 
     // check the return value!
     return TRUE;
 }
 
+void
+nsWindow::UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect)
+{
+  if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
+      // We need to create our own buffer to force the stride to match the
+      // expected stride.
+      int32_t stride = GetAlignedStride<4>(BytesPerPixel(FORMAT_A8) *
+                                           aBoundsRect.width);
+      int32_t bufferSize = stride * aBoundsRect.height;
+      nsAutoArrayPtr<PRUint8> imageBuffer(new (std::nothrow) PRUint8[bufferSize]);
+      RefPtr<DrawTarget> drawTarget = gfxPlatform::GetPlatform()->
+          CreateDrawTargetForData(imageBuffer, ToIntSize(aBoundsRect.Size()),
+                                  stride, FORMAT_A8);
+
+      if (drawTarget) {
+          drawTarget->FillRect(ToRect(aBoundsRect),
+                               *aPattern->GetPattern(drawTarget),
+                               DrawOptions(1.0, OP_SOURCE));
+      }
+      UpdateTranslucentWindowAlphaInternal(aBoundsRect, imageBuffer, stride);
+  } else {
+      nsRefPtr<gfxImageSurface> img =
+          new gfxImageSurface(ThebesIntSize(aBoundsRect.Size()),
+                              gfxImageSurface::ImageFormatA8);
+      if (img && !img->CairoStatus()) {
+          img->SetDeviceOffset(-aBoundsRect.TopLeft());
+
+          nsRefPtr<gfxContext> imgCtx = new gfxContext(img);
+          imgCtx->SetPattern(aPattern);
+          imgCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+          imgCtx->Paint();
+
+          UpdateTranslucentWindowAlphaInternal(aBoundsRect, img->Data(),
+                                               img->Stride());
+      }
+  }
+}
+
 gboolean
 nsWindow::OnConfigureEvent(GtkWidget *aWidget, GdkEventConfigure *aEvent)
 {
     // These events are only received on toplevel windows.
     //
     // GDK ensures that the coordinates are the client window top-left wrt the
     // root window.
     //
--- a/widget/gtk2/nsWindow.h
+++ b/widget/gtk2/nsWindow.h
@@ -59,16 +59,17 @@ extern PRLogModuleInfo *gWidgetDrawLog;
 
 #define LOG(args)
 #define LOGFOCUS(args)
 #define LOGDRAG(args)
 #define LOGDRAW(args)
 
 #endif /* MOZ_LOGGING */
 
+class gfxPattern;
 class nsDragService;
 #if defined(MOZ_X11) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)
 #  define MOZ_HAVE_SHMIMAGE
 
 class nsShmImage;
 #endif
 
 class nsWindow : public nsBaseWidget, public nsSupportsWeakReference
@@ -196,16 +197,18 @@ public:
                                                guint            aTime,
                                                gpointer         aData);
 
 #if defined(MOZ_WIDGET_GTK2)
   mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() MOZ_OVERRIDE;
 #endif
 
 private:
+    void               UpdateAlpha(gfxPattern* aPattern, nsIntRect aBoundsRect);
+
     void               NativeResize(int32_t aWidth,
                                     int32_t aHeight,
                                     bool    aRepaint);
 
     void               NativeResize(int32_t aX,
                                     int32_t aY,
                                     int32_t aWidth,
                                     int32_t aHeight,