Bug 548437 - Implement a SysV shared memory backend for Shmem and allow them to be used with Xshm. r=joe,sr=vladimir
authorOleg Romashin <romaxa@gmail.com>
Fri, 04 Jun 2010 09:58:22 -0400
changeset 46890 ae03b58ae4882cc6f0d7144b3e77e1f939723c67
parent 46889 f38dd60fc3841872ca75c43146a43b039e4ad55e
child 46891 68b902c3da0fbbce3a974690ac50a2267091be10
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjoe, vladimir
bugs548437
milestone1.9.3a5pre
Bug 548437 - Implement a SysV shared memory backend for Shmem and allow them to be used with Xshm. r=joe,sr=vladimir
content/canvas/public/DocumentRendererNativeIDChild.h
content/canvas/public/DocumentRendererNativeIDParent.h
content/canvas/public/DocumentRendererShmemChild.h
content/canvas/public/Makefile.in
content/canvas/public/nsICanvasRenderingContextInternal.h
content/canvas/src/DocumentRendererNativeIDChild.cpp
content/canvas/src/DocumentRendererNativeIDParent.cpp
content/canvas/src/DocumentRendererShmemChild.cpp
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.h
content/canvas/src/nsCanvasRenderingContext2D.cpp
dom/ipc/PDocumentRendererNativeID.ipdl
dom/ipc/PIFrameEmbedding.ipdl
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/ipdl.mk
gfx/thebes/public/gfxSharedImageSurface.h
gfx/thebes/src/gfxSharedImageSurface.cpp
new file mode 100644
--- /dev/null
+++ b/content/canvas/public/DocumentRendererNativeIDChild.h
@@ -0,0 +1,69 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   Nokia.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_dom_DocumentRendererNativeIDChild
+#define mozilla_dom_DocumentRendererNativeIDChild
+
+#include "mozilla/ipc/PDocumentRendererNativeIDChild.h"
+
+class nsIDOMWindow;
+class gfxMatrix;
+
+namespace mozilla {
+namespace ipc {
+
+class DocumentRendererNativeIDChild : public PDocumentRendererNativeIDChild
+{
+public:
+    DocumentRendererNativeIDChild();
+    virtual ~DocumentRendererNativeIDChild();
+
+    bool RenderDocument(nsIDOMWindow* window, const PRInt32& x,
+                        const PRInt32& y, const PRInt32& w,
+                        const PRInt32& h, const nsString& aBGColor,
+                        const PRUint32& flags, const PRBool& flush,
+                        const gfxMatrix& aMatrix,
+                        const PRInt32& nativeID);
+
+private:
+
+    DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererNativeIDChild);
+};
+
+}
+}
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/canvas/public/DocumentRendererNativeIDParent.h
@@ -0,0 +1,67 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   Nokia.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_dom_DocumentRendererNativeIDParent
+#define mozilla_dom_DocumentRendererNativeIDParent
+
+#include "mozilla/ipc/PDocumentRendererNativeIDParent.h"
+#include "nsICanvasRenderingContextInternal.h"
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+namespace ipc {
+
+class DocumentRendererNativeIDParent : public PDocumentRendererNativeIDParent
+{
+public:
+    DocumentRendererNativeIDParent();
+    virtual ~DocumentRendererNativeIDParent();
+
+    void SetCanvas(nsICanvasRenderingContextInternal* aCanvas);
+    virtual bool Recv__delete__(const PRInt32& x, const PRInt32& y,
+                                const PRInt32& w, const PRInt32& h,
+                                const PRUint32& nativeID);
+
+private:
+    nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererNativeIDParent);
+};
+
+}
+}
+
+#endif
--- a/content/canvas/public/DocumentRendererShmemChild.h
+++ b/content/canvas/public/DocumentRendererShmemChild.h
@@ -51,17 +51,16 @@ public:
     DocumentRendererShmemChild();
     virtual ~DocumentRendererShmemChild();
 
     bool RenderDocument(nsIDOMWindow *window, const PRInt32& x,
                         const PRInt32& y, const PRInt32& w,
                         const PRInt32& h, const nsString& aBGColor,
                         const PRUint32& flags, const PRBool& flush,
                         const gfxMatrix& aMatrix,
-                        const PRInt32& bufw, const PRInt32& bufh,
                         Shmem& data);
 
 private:
 
     DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererShmemChild);
 };
 
 }
--- a/content/canvas/public/Makefile.in
+++ b/content/canvas/public/Makefile.in
@@ -52,15 +52,17 @@ EXPORTS		= \
 		nsICanvasElementExternal.h \
 		$(NULL)
 
 EXPORTS_mozilla/ipc = \
 		DocumentRendererChild.h \
 		DocumentRendererParent.h \
 		DocumentRendererShmemChild.h \
 		DocumentRendererShmemParent.h \
+		DocumentRendererNativeIDChild.h \
+		DocumentRendererNativeIDParent.h \
 		$(NULL)
 
 XPIDLSRCS	= \
 		nsICanvasGLPrivate.idl \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/content/canvas/public/nsICanvasRenderingContextInternal.h
+++ b/content/canvas/public/nsICanvasRenderingContextInternal.h
@@ -116,14 +116,19 @@ public:
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsShmem(PRBool isShmem) = 0;
 
   // Swap this back buffer with the front, and copy its contents to the new
   // back. x, y, w, and h specify the area of |back| that is dirty.
   NS_IMETHOD Swap(mozilla::ipc::Shmem& back,
                   PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h) = 0;
+
+  // Sync back and front buffer, move ownership of back buffer to parent
+  NS_IMETHOD Swap(PRUint32 nativeID,
+                  PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h) = 0;
+
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
                               NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
 #endif /* nsICanvasRenderingContextInternal_h___ */
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/DocumentRendererNativeIDChild.cpp
@@ -0,0 +1,178 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   Nokia.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifdef MOZ_WIDGET_QT
+#include <QX11Info>
+#define DISPLAY QX11Info::display
+#endif
+
+#ifdef MOZ_WIDGET_GTK2
+#include <gdk/gdkx.h>
+#define DISPLAY GDK_DISPLAY
+#endif
+
+#include "base/basictypes.h"
+
+#include "gfxImageSurface.h"
+#include "gfxPattern.h"
+#include "nsPIDOMWindow.h"
+#include "nsIDOMWindow.h"
+#include "nsIDOMDocument.h"
+#include "nsIDocShell.h"
+#include "nsIDocShellTreeNode.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocument.h"
+#include "nsIInterfaceRequestorUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCSSParser.h"
+#include "nsPresContext.h"
+#include "nsCOMPtr.h"
+#include "nsColor.h"
+#include "gfxContext.h"
+#include "gfxImageSurface.h"
+#include "nsLayoutUtils.h"
+
+#include "mozilla/ipc/DocumentRendererNativeIDChild.h"
+
+#ifdef MOZ_X11
+#include "gfxXlibSurface.h"
+#endif
+
+using namespace mozilla::ipc;
+
+DocumentRendererNativeIDChild::DocumentRendererNativeIDChild()
+{}
+
+DocumentRendererNativeIDChild::~DocumentRendererNativeIDChild()
+{}
+
+static void
+FlushLayoutForTree(nsIDOMWindow* aWindow)
+{
+    nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
+    if (!piWin)
+        return;
+
+    // Note that because FlushPendingNotifications flushes parents, this
+    // is O(N^2) in docshell tree depth.  However, the docshell tree is
+    // usually pretty shallow.
+
+    nsCOMPtr<nsIDOMDocument> domDoc;
+    aWindow->GetDocument(getter_AddRefs(domDoc));
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
+    if (doc) {
+        doc->FlushPendingNotifications(Flush_Layout);
+    }
+
+    nsCOMPtr<nsIDocShellTreeNode> node =
+        do_QueryInterface(piWin->GetDocShell());
+    if (node) {
+        PRInt32 i = 0, i_end;
+        node->GetChildCount(&i_end);
+        for (; i < i_end; ++i) {
+            nsCOMPtr<nsIDocShellTreeItem> item;
+            node->GetChildAt(i, getter_AddRefs(item));
+            nsCOMPtr<nsIDOMWindow> win = do_GetInterface(item);
+            if (win) {
+                FlushLayoutForTree(win);
+            }
+        }
+    }
+}
+
+bool
+DocumentRendererNativeIDChild::RenderDocument(nsIDOMWindow* window, const PRInt32& x,
+                                      const PRInt32& y, const PRInt32& w,
+                                      const PRInt32& h, const nsString& aBGColor,
+                                      const PRUint32& flags, const PRBool& flush,
+                                      const gfxMatrix& aMatrix,
+                                      const PRInt32& nativeID)
+{
+    if (!nativeID)
+        return false;
+
+    if (flush)
+        FlushLayoutForTree(window);
+
+    nsCOMPtr<nsPresContext> presContext;
+    nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
+    if (win) {
+        nsIDocShell* docshell = win->GetDocShell();
+        if (docshell) {
+            docshell->GetPresContext(getter_AddRefs(presContext));
+        }
+    }
+    if (!presContext)
+        return false;
+
+    nscolor bgColor;
+    nsCSSParser parser;
+    nsresult rv = parser.ParseColorString(PromiseFlatString(aBGColor), nsnull, 0, &bgColor);
+    if (NS_FAILED(rv))
+        return false;
+
+    nsIPresShell* presShell = presContext->PresShell();
+
+    nsRect r(x, y, w, h);
+
+    // Draw directly into the output array.
+    nsRefPtr<gfxASurface> surf;
+#ifdef MOZ_X11
+    // Initialize gfxXlibSurface from native XID by using toolkit functionality
+    // Would be nice to have gfxXlibSurface(nativeID) implementation
+    Display* dpy = DISPLAY();
+    int depth = DefaultDepth(dpy, DefaultScreen(dpy));
+    XVisualInfo vinfo;
+    int foundVisual = XMatchVisualInfo(dpy,
+                                       DefaultScreen(dpy),
+                                       depth,
+                                       TrueColor,
+                                       &vinfo);
+    if (!foundVisual)
+        return false;
+
+    surf = new gfxXlibSurface(dpy, nativeID, vinfo.visual);
+    XSync(dpy, False);
+#else
+    NS_ERROR("NativeID handler not implemented for your platform");
+#endif
+
+    nsRefPtr<gfxContext> ctx = new gfxContext(surf);
+    ctx->SetMatrix(aMatrix);
+
+    presShell->RenderDocument(r, flags, bgColor, ctx);
+    return true;
+}
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/DocumentRendererNativeIDParent.cpp
@@ -0,0 +1,60 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Fennec Electrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   Nokia.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozilla/ipc/DocumentRendererNativeIDParent.h"
+
+using namespace mozilla::ipc;
+
+DocumentRendererNativeIDParent::DocumentRendererNativeIDParent()
+{}
+
+DocumentRendererNativeIDParent::~DocumentRendererNativeIDParent()
+{}
+
+void
+DocumentRendererNativeIDParent::SetCanvas(nsICanvasRenderingContextInternal* aCanvas)
+{
+    mCanvas = aCanvas;
+}
+
+bool
+DocumentRendererNativeIDParent::Recv__delete__(const PRInt32& x, const PRInt32& y,
+                                               const PRInt32& w, const PRInt32& h,
+                                               const PRUint32& nativeID)
+{
+    mCanvas->Swap(nativeID, x, y, w, h);
+    return true;
+}
--- a/content/canvas/src/DocumentRendererShmemChild.cpp
+++ b/content/canvas/src/DocumentRendererShmemChild.cpp
@@ -49,16 +49,19 @@
 #include "nsComponentManagerUtils.h"
 #include "nsCSSParser.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsColor.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "nsLayoutUtils.h"
+#ifdef MOZ_IPC
+#include "gfxSharedImageSurface.h"
+#endif
 
 #include "mozilla/ipc/DocumentRendererShmemChild.h"
 
 using namespace mozilla::ipc;
 
 DocumentRendererShmemChild::DocumentRendererShmemChild()
 {}
 
@@ -100,17 +103,16 @@ FlushLayoutForTree(nsIDOMWindow* aWindow
 }
 
 bool
 DocumentRendererShmemChild::RenderDocument(nsIDOMWindow *window, const PRInt32& x,
                                       const PRInt32& y, const PRInt32& w,
                                       const PRInt32& h, const nsString& aBGColor,
                                       const PRUint32& flags, const PRBool& flush,
                                       const gfxMatrix& aMatrix,
-                                      const PRInt32& bufw, const PRInt32& bufh,
                                       Shmem& data)
 {
     if (flush)
         FlushLayoutForTree(window);
 
     nsCOMPtr<nsPresContext> presContext;
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(window);
     if (win) {
@@ -128,18 +130,15 @@ DocumentRendererShmemChild::RenderDocume
     if (NS_FAILED(rv))
         return false;
 
     nsIPresShell* presShell = presContext->PresShell();
 
     nsRect r(x, y, w, h);
 
     // Draw directly into the output array.
-    nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(data.get<PRUint8>(),
-                                                         gfxIntSize(bufw, bufh),
-                                                         4 * bufw,
-                                                         gfxASurface::ImageFormatARGB32);
+    nsRefPtr<gfxASurface> surf = new gfxSharedImageSurface(data);
     nsRefPtr<gfxContext> ctx = new gfxContext(surf);
     ctx->SetMatrix(aMatrix);
 
     presShell->RenderDocument(r, flags, bgColor, ctx);
     return true;
 }
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -55,16 +55,18 @@ CPPSRCS	= \
 	CanvasUtils.cpp \
 	nsCanvasRenderingContext2D.cpp \
 	$(NULL)
 
 ifdef MOZ_IPC
 CPPSRCS += \
 	DocumentRendererParent.cpp \
 	DocumentRendererChild.cpp \
+	DocumentRendererNativeIDParent.cpp \
+	DocumentRendererNativeIDChild.cpp \
 	DocumentRendererShmemParent.cpp \
 	DocumentRendererShmemChild.cpp \
 	$(NULL)
 endif
 
 # Canvas 3D Pieces
 
 ifdef MOZ_WEBGL
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -243,16 +243,19 @@ public:
                               nsIInputStream **aStream);
     NS_IMETHOD GetThebesSurface(gfxASurface **surface);
     NS_IMETHOD SetIsOpaque(PRBool b) { return NS_OK; };
     NS_IMETHOD SetIsShmem(PRBool b) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Redraw(const gfxRect&) { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack,
                     PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
                     { return NS_ERROR_NOT_IMPLEMENTED; }
+    NS_IMETHOD Swap(PRUint32 nativeID,
+                    PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
+                    { return NS_ERROR_NOT_IMPLEMENTED; }
 
     nsresult SynthesizeGLError(GLenum err);
     nsresult SynthesizeGLError(GLenum err, const char *fmt, ...);
 
     nsresult ErrorInvalidEnum(const char *fmt, ...);
     nsresult ErrorInvalidOperation(const char *fmt, ...);
     nsresult ErrorInvalidValue(const char *fmt, ...);
 
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -96,48 +96,62 @@
 
 #include "nsTArray.h"
 
 #include "imgIEncoder.h"
 
 #include "gfxContext.h"
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
+#ifdef MOZ_IPC
+#include "gfxSharedImageSurface.h"
+#endif
 #include "gfxPlatform.h"
 #include "gfxFont.h"
 #include "gfxTextRunCache.h"
 #include "gfxBlur.h"
+#include "gfxUtils.h"
 
 #include "nsFrameManager.h"
 
 #include "nsFrameLoader.h"
 
 #include "nsBidiPresUtils.h"
 
 #include "Layers.h"
 
 #include "CanvasUtils.h"
 
 #include "nsIMemoryReporter.h"
 
 #ifdef MOZ_IPC
+#  include <algorithm>
 #  include "mozilla/dom/ContentProcessParent.h"
 #  include "mozilla/ipc/PDocumentRendererParent.h"
 #  include "mozilla/ipc/PDocumentRendererShmemParent.h"
+#  include "mozilla/ipc/PDocumentRendererNativeIDParent.h"
 #  include "mozilla/dom/PIFrameEmbeddingParent.h"
 #  include "mozilla/ipc/DocumentRendererParent.h"
 #  include "mozilla/ipc/DocumentRendererShmemParent.h"
+#  include "mozilla/ipc/DocumentRendererNativeIDParent.h"
+#  include "mozilla/ipc/SharedMemorySysV.h"
+
 // windows.h (included by chromium code) defines this, in its infinite wisdom
 #  undef DrawText
 
-using mozilla::ipc::SharedMemory;
+using namespace mozilla::ipc;
+#endif
+
+#ifdef MOZ_X11
+#include "gfxXlibSurface.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::layers;
+using namespace mozilla::dom;
 
 #ifndef M_PI
 #define M_PI		3.14159265358979323846
 #define M_PI_2		1.57079632679489661923
 #endif
 
 /* Float validation stuff */
 
@@ -402,18 +416,21 @@ public:
     NS_IMETHOD SetIsOpaque(PRBool isOpaque);
     already_AddRefed<CanvasLayer> GetCanvasLayer(LayerManager *manager);
     void MarkContextClean();
     NS_IMETHOD SetIsShmem(PRBool isShmem);
     // this rect is in CSS pixels
     NS_IMETHOD Redraw(const gfxRect &r);
     // Swap this back buffer with the front, and copy its contents to the new back.
     // x, y, w, and h specify the area of |back| that is dirty.
-    NS_IMETHOD Swap(mozilla::ipc::Shmem& back, PRInt32 x, PRInt32 y, 
+    NS_IMETHOD Swap(Shmem& back, PRInt32 x, PRInt32 y, 
                     PRInt32 w, PRInt32 h);
+    NS_IMETHOD Swap(PRUint32 nativeID, PRInt32 x, PRInt32 y,
+                    PRInt32 w, PRInt32 h);
+ 
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // nsIDOMCanvasRenderingContext2D interface
     NS_DECL_NSIDOMCANVASRENDERINGCONTEXT2D
 
     enum Style {
@@ -463,34 +480,41 @@ protected:
      */
     void EnsureUnpremultiplyTable();
 
     /**
      * Creates the premultiply lookup table, if it doesn't exist.
      */
     void EnsurePremultiplyTable();
 
+    /**
+     * Returns the image format this canvas should be allocated using. Takes
+     * into account mOpaque, platform requirements, etc.
+     */
+    gfxASurface::gfxImageFormat GetImageFormat() const;
+
+    /**
+     * Sync data from mBackSurface to mSurface.
+     */
+    nsresult Swap(const gfxRect& aRect);
+
     // Member vars
     PRInt32 mWidth, mHeight;
     PRPackedBool mValid;
     PRPackedBool mOpaque;
 
 #ifdef MOZ_IPC
-    PRPackedBool mShmem;
-
-    // We always have a front buffer. We hand the back buffer to the other
-    // process to render to, and then swap our two buffers when it finishes.
-    mozilla::ipc::Shmem mFrontBuffer;
-    mozilla::ipc::Shmem mBackBuffer;
+    PRPackedBool mAsync;
+
+    // We always have a front buffer. We hand the mBackSurface to the other
+    // process to render to,
+    // and then sync data from mBackSurface to mSurface when it finishes.
     nsRefPtr<gfxASurface> mBackSurface;
-
-    // Creates a new mFrontBuffer and mBackBuffer of the correct size.
-    // Returns false if this wasn't possible, for whatever reason.
-    bool CreateShmemSegments(PRInt32 width, PRInt32 height,
-                             gfxASurface::gfxImageFormat format);
+    // for rendering with NativeID protocol, we should track backbuffer ownership
+    PRPackedBool mIsBackSurfaceReadable;
 #endif
 
     // the canvas element informs us when it's going away,
     // so these are not nsCOMPtrs
     nsHTMLCanvasElement* mCanvasElement;
 
     // If mCanvasElement is not provided, then a docshell is
     nsCOMPtr<nsIDocShell> mDocShell;
@@ -778,42 +802,55 @@ NS_NewCanvasRenderingContext2D(nsIDOMCan
     if (!ctx)
         return NS_ERROR_OUT_OF_MEMORY;
 
     *aResult = ctx.forget().get();
     return NS_OK;
 }
 
 nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
-    : mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
-      mSaveCount(0), mIsEntireFrameInvalid(PR_FALSE), mInvalidateCount(0),
-      mLastStyle(STYLE_MAX), mStyleStack(20)
+    : mValid(PR_FALSE), mOpaque(PR_FALSE)
 #ifdef MOZ_IPC
-    , mShmem(PR_FALSE)
+    , mAsync(PR_FALSE)
 #endif
+    , mCanvasElement(nsnull)
+    , mSaveCount(0), mIsEntireFrameInvalid(PR_FALSE), mInvalidateCount(0)
+    , mLastStyle(STYLE_MAX), mStyleStack(20)
 {
     sNumLivingContexts++;
 }
 
 nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
 {
     Destroy();
 
+    ContentProcessParent* allocator = ContentProcessParent::GetSingleton(PR_FALSE);
+    if (allocator && gfxSharedImageSurface::IsSharedImage(mBackSurface)) {
+        Shmem mem = static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem();
+        allocator->DeallocShmem(mem);
+    }
+    mBackSurface = nsnull;
+
     sNumLivingContexts--;
     if (!sNumLivingContexts) {
         delete[] sUnpremultiplyTable;
         delete[] sPremultiplyTable;
         sUnpremultiplyTable = nsnull;
         sPremultiplyTable = nsnull;
     }
 }
 
 void
 nsCanvasRenderingContext2D::Destroy()
 {
+    ContentProcessParent* allocator = ContentProcessParent::GetSingleton(PR_FALSE);
+    if (allocator && gfxSharedImageSurface::IsSharedImage(mSurface)) {
+        Shmem &mem = static_cast<gfxSharedImageSurface*>(mSurface.get())->GetShmem();
+        allocator->DeallocShmem(mem);
+    }
     if (mValid)
         gCanvasMemoryUsed -= mWidth * mHeight * 4;
 
     mSurface = nsnull;
     mThebes = nsnull;
     mValid = PR_FALSE;
     mIsEntireFrameInvalid = PR_FALSE;
 }
@@ -997,64 +1034,61 @@ nsCanvasRenderingContext2D::Redraw(const
     if (++mInvalidateCount > kCanvasMaxInvalidateCount)
         return Redraw();
 
     mCanvasElement->InvalidateFrame(&r);
 
     return NS_OK;
 }
 
-#ifdef MOZ_IPC
-bool
-nsCanvasRenderingContext2D::CreateShmemSegments(PRInt32 width, PRInt32 height,
-                                                gfxASurface::gfxImageFormat format)
-{
-    if (!mozilla::dom::ContentProcessParent::GetSingleton()->
-        AllocShmem(width * height * 4, SharedMemory::TYPE_BASIC,
-                   &mFrontBuffer))
-        return false;
-    if (!mozilla::dom::ContentProcessParent::GetSingleton()->
-                AllocShmem(width * height * 4, SharedMemory::TYPE_BASIC,
-                           &mBackBuffer))
-        return false;
-
-    mBackSurface = new gfxImageSurface(mBackBuffer.get<unsigned char>(),
-                                       gfxIntSize(width, height),
-                                       width * 4, format);
-
-    return true;
-}
-#endif
-
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
 {
     Destroy();
 
     nsRefPtr<gfxASurface> surface;
 
     // Check that the dimensions are sane
-    if (gfxASurface::CheckSurfaceSize(gfxIntSize(width, height), 0xffff)) {
-        gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
-        if (mOpaque)
-            format = gfxASurface::ImageFormatRGB24;
-
-#ifdef MOZ_IPC
-        if (mShmem && CreateShmemSegments(width, height, format)) {
-            NS_ABORT_IF_FALSE(mFrontBuffer.get<unsigned char>(), "No front buffer!");
-            surface = new gfxImageSurface(mFrontBuffer.get<unsigned char>(),
-                                          gfxIntSize(width, height),
-                                          width * 4, format);
-        } else
-#endif
-            surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
-                (gfxIntSize(width, height), format);
+    gfxIntSize size(width, height);
+    if (gfxASurface::CheckSurfaceSize(size, 0xffff)) {
+
+        gfxASurface::gfxImageFormat format = GetImageFormat();
+
+        surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
+            (gfxIntSize(width, height), format);
 
         if (surface && surface->CairoStatus() != 0)
             surface = NULL;
+
+#ifdef MOZ_IPC
+        if (mAsync && surface) {
+#ifdef MOZ_X11
+            if (surface->GetType() == gfxASurface::SurfaceTypeXlib) {
+                mBackSurface =
+                    gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, format);
+                NS_ABORT_IF_FALSE(mBackSurface->GetType() ==
+                                  gfxASurface::SurfaceTypeXlib, "need xlib surface");
+                mIsBackSurfaceReadable = PR_TRUE;
+                // Make sure that our XSurface created and synced properly
+                XSync(static_cast<gfxXlibSurface*>(mBackSurface.get())->XDisplay(), False);
+            } else
+#endif
+            {
+                if (surface->GetType() == gfxASurface::SurfaceTypeImage)
+                    format = static_cast<gfxImageSurface*>(surface.get())->Format();
+                SharedMemory::SharedMemoryType shmtype = SharedMemory::TYPE_BASIC;
+#ifdef MOZ_HAVE_SHAREDMEMORYSYSV
+                shmtype = SharedMemory::TYPE_SYSV;
+#endif
+                ContentProcessParent* allocator = ContentProcessParent::GetSingleton();
+                mBackSurface = new gfxSharedImageSurface();
+                static_cast<gfxSharedImageSurface*>(mBackSurface.get())->Init(allocator, size, format, shmtype);
+            }
+        }
+#endif
     }
     if (surface) {
         if (gCanvasMemoryReporter == nsnull) {
             gCanvasMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasMemory);
             NS_RegisterMemoryReporter(gCanvasMemoryReporter);
         }
 
         gCanvasMemoryUsed += width * height * 4;
@@ -1135,87 +1169,105 @@ nsCanvasRenderingContext2D::SetIsOpaque(
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::SetIsShmem(PRBool isShmem)
 {
 #ifdef MOZ_IPC
-    if (isShmem == mShmem)
+    if (isShmem == mAsync)
         return NS_OK;
 
-    mShmem = isShmem;
+    mAsync = isShmem;
 
     if (mValid) {
         /* If we've already been created, let SetDimensions take care of
          * recreating our surface
          */
         return SetDimensions(mWidth, mHeight);
     }
 
     return NS_OK;
 #else
     return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 }
 
-NS_IMETHODIMP
-nsCanvasRenderingContext2D::Swap(mozilla::ipc::Shmem& aBack, 
-                                 PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
+nsresult
+nsCanvasRenderingContext2D::Swap(const gfxRect& aRect)
 {
-#ifdef MOZ_IPC
-    // Our front buffer is always the correct size. If this back buffer doesn't
-    // match the front buffer's size, it's out of date (we've resized since
-    // this message was sent) and we should just ignore it.
-    if (mFrontBuffer.Size<unsigned char>() != aBack.Size<unsigned char>())
-        return NS_OK;
-
-    // Swap back and front.
-    // mBackBuffer should be null here, since we've previously sent it to the
-    // child process.
-    mBackBuffer = mFrontBuffer;
-    mFrontBuffer = aBack;
-
-    // do want mozilla::Swap
-    nsRefPtr<gfxASurface> tmp = mSurface;
-    mSurface = mBackSurface;
-    mBackSurface = tmp;
-
-    nsRefPtr<gfxContext> ctx = new gfxContext(mSurface);
-    CopyContext(ctx, mThebes);
-    mThebes = ctx;
-
-    Redraw(gfxRect(x, y, w, h));
-
-    // Copy the new contents to the old to keep them in sync. 
-    memcpy(mBackBuffer.get<unsigned char>(), mFrontBuffer.get<unsigned char>(),
-           mWidth * mHeight * 4);
+    gfxContextPathAutoSaveRestore pathSR(mThebes);
+    gfxContextAutoSaveRestore autoSR(mThebes);
+
+    mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
+    mThebes->NewPath();
+    mThebes->SetSource(mBackSurface);
+    mThebes->Rectangle(aRect, PR_TRUE);
+    mThebes->Clip();
+    mThebes->Paint();
+
+    Redraw(aRect);
 
     // Notify listeners that we've finished drawing
     nsCOMPtr<nsIContent> content =
       do_QueryInterface(static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement));
     nsIDocument* ownerDoc = nsnull;
     if (content)
         ownerDoc = content->GetOwnerDoc();
 
     if (ownerDoc && mCanvasElement) {
         nsContentUtils::DispatchTrustedEvent(ownerDoc,
                                              static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
                                              NS_LITERAL_STRING("MozAsyncCanvasRender"),
                                              /* aCanBubble = */ PR_TRUE, 
                                              /* aCancelable = */ PR_TRUE);
     }
     return NS_OK;
-#else
-    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsCanvasRenderingContext2D::Swap(Shmem& aBack,
+                                 PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
+{
+#ifdef MOZ_IPC
+    if (!gfxSharedImageSurface::IsSharedImage(mBackSurface))
+        return NS_ERROR_FAILURE;
+
+    nsRefPtr<gfxSharedImageSurface> aBackImage = new gfxSharedImageSurface(aBack);
+    if (aBackImage->Data() != static_cast<gfxImageSurface*>(mBackSurface.get())->Data()) {
+        NS_ERROR("Incoming back surface is not equal to our back surface");
+        // Delete orphaned memory and return
+        ContentProcessParent* allocator = ContentProcessParent::GetSingleton(PR_FALSE);
+        if (allocator)
+            allocator->DeallocShmem(aBack);
+        return NS_ERROR_FAILURE;
+    }
+
+    Shmem& mem = static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem();
+    if (mem.IsReadable())
+        NS_ERROR("Back surface readable before swap, this must not happen");
+
+    // Take mBackSurface shared memory ownership
+    mem = aBack;
+    return Swap(gfxRect(x, y, w, h));
 #endif
 }
 
 NS_IMETHODIMP
+nsCanvasRenderingContext2D::Swap(PRUint32 nativeID,
+                                 PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
+{
+    if (mIsBackSurfaceReadable)
+        NS_ERROR("Back surface readable before swap, this must not happen");
+    mIsBackSurfaceReadable = PR_TRUE;
+    return Swap(gfxRect(x, y, w, h));
+}
+
+NS_IMETHODIMP
 nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter)
 {
     nsresult rv = NS_OK;
 
     if (!mValid || !mSurface ||
         mSurface->CairoStatus() ||
         mThebes->HasError())
         return NS_ERROR_FAILURE;
@@ -1296,16 +1348,27 @@ nsCanvasRenderingContext2D::GetInputStre
                                mWidth * mHeight * 4, mWidth, mHeight, mWidth * 4,
                                imgIEncoder::INPUT_FORMAT_HOSTARGB,
                                nsDependentString(aEncoderOptions));
     NS_ENSURE_SUCCESS(rv, rv);
 
     return CallQueryInterface(encoder, aStream);
 }
 
+gfxASurface::gfxImageFormat
+nsCanvasRenderingContext2D::GetImageFormat() const
+{
+    gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
+
+    if (mOpaque)
+        format = gfxASurface::ImageFormatRGB24;
+
+    return format;
+}
+
 //
 // nsCanvasRenderingContext2D impl
 //
 
 NS_IMETHODIMP
 nsCanvasRenderingContext2D::SetCanvasElement(nsHTMLCanvasElement* aCanvasElement)
 {
     // don't hold a ref to this!
@@ -3615,17 +3678,17 @@ nsCanvasRenderingContext2D::AsyncDrawXUL
     if (!loaderOwner)
         return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsFrameLoader> frameloader = loaderOwner->GetFrameLoader();
     if (!frameloader)
         return NS_ERROR_FAILURE;
 
 #ifdef MOZ_IPC
-    mozilla::dom::PIFrameEmbeddingParent *child = frameloader->GetChildProcess();
+    PIFrameEmbeddingParent *child = frameloader->GetChildProcess();
     if (!child) {
         nsCOMPtr<nsIDOMWindow> window =
             do_GetInterface(frameloader->GetExistingDocShell());
         if (!window)
             return NS_ERROR_FAILURE;
 
         return DrawWindow(window, aX, aY, aW, aH, aBGColor, flags);
     }
@@ -3646,44 +3709,72 @@ nsCanvasRenderingContext2D::AsyncDrawXUL
         renderDocFlags &= ~nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
     }
 
     PRInt32 x = nsPresContext::CSSPixelsToAppUnits(aX),
             y = nsPresContext::CSSPixelsToAppUnits(aY),
             w = nsPresContext::CSSPixelsToAppUnits(aW),
             h = nsPresContext::CSSPixelsToAppUnits(aH);
 
-    if (mShmem) {
-        if (!mBackBuffer.IsWritable())
+    if (mAsync) {
+#ifdef MOZ_X11
+        if (mBackSurface &&
+				    mBackSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
+
+            if (!mIsBackSurfaceReadable)
+                return NS_ERROR_FAILURE;
+
+            PRInt32 nativeID = static_cast<gfxXlibSurface*>(mBackSurface.get())->XDrawable();
+            mIsBackSurfaceReadable = PR_FALSE;
+            PDocumentRendererNativeIDParent* pdocrender =
+                child->SendPDocumentRendererNativeIDConstructor(x, y, w, h,
+                                                                nsString(aBGColor),
+                                                                renderDocFlags, flush,
+                                                                mThebes->CurrentMatrix(),
+                                                                nativeID);
+            if (!pdocrender)
+                return NS_ERROR_FAILURE;
+
+            DocumentRendererNativeIDParent* docrender =
+                static_cast<DocumentRendererNativeIDParent *>(pdocrender);
+
+            docrender->SetCanvas(this);
+        }
+        else
+#endif
+        if (gfxSharedImageSurface::IsSharedImage(mBackSurface)) {
+            Shmem& backmem = static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem();
+            if (!backmem.IsWritable())
+                return NS_ERROR_FAILURE;
+            PDocumentRendererShmemParent* pdocrender =
+                child->SendPDocumentRendererShmemConstructor(x, y, w, h,
+                                                             nsString(aBGColor),
+                                                             renderDocFlags, flush,
+                                                             mThebes->CurrentMatrix(),
+                                                             backmem);
+
+            if (!pdocrender)
+                return NS_ERROR_FAILURE;
+
+            DocumentRendererShmemParent* docrender =
+                static_cast<DocumentRendererShmemParent*>(pdocrender);
+
+            docrender->SetCanvas(this);
+        } else
             return NS_ERROR_FAILURE;
-
-        mozilla::ipc::PDocumentRendererShmemParent *pdocrender =
-            child->SendPDocumentRendererShmemConstructor(x, y, w, h,
-                                                         nsString(aBGColor),
-                                                         renderDocFlags, flush,
-                                                         mThebes->CurrentMatrix(),
-                                                         mWidth, mHeight,
-                                                         mBackBuffer);
-        if (!pdocrender)
-            return NS_ERROR_FAILURE;
-
-        mozilla::ipc::DocumentRendererShmemParent *docrender = 
-            static_cast<mozilla::ipc::DocumentRendererShmemParent *>(pdocrender);
-
-        docrender->SetCanvas(this);
     } else {
-        mozilla::ipc::PDocumentRendererParent *pdocrender =
+        PDocumentRendererParent *pdocrender =
             child->SendPDocumentRendererConstructor(x, y, w, h,
                                                     nsString(aBGColor),
                                                     renderDocFlags, flush);
         if (!pdocrender)
             return NS_ERROR_FAILURE;
 
-        mozilla::ipc::DocumentRendererParent *docrender =
-            static_cast<mozilla::ipc::DocumentRendererParent *>(pdocrender);
+        DocumentRendererParent *docrender =
+            static_cast<DocumentRendererParent *>(pdocrender);
 
         docrender->SetCanvasContext(this, mThebes);
     }
 
     return NS_OK;
 #else
     nsCOMPtr<nsIDOMWindow> window =
         do_GetInterface(frameloader->GetExistingDocShell());
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PDocumentRendererNativeID.ipdl
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Fenntrolysis.
+ *
+ * The Initial Developer of the Original Code is
+ *   Nokia.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+include protocol PIFrameEmbedding;
+
+namespace mozilla {
+namespace ipc {
+
+protocol PDocumentRendererNativeID
+{
+  manager PIFrameEmbedding;
+
+parent:
+    // Returns the offset, width and height, in pixels, of the area in the
+    // buffer that was drawn.
+    __delete__(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, PRUint32 nativeID);
+};
+
+} // namespace ipc
+} // namespace mozilla
--- a/dom/ipc/PIFrameEmbedding.ipdl
+++ b/dom/ipc/PIFrameEmbedding.ipdl
@@ -35,16 +35,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol PContentProcess;
 include protocol PDocumentRenderer;
 include protocol PDocumentRendererShmem;
+include protocol PDocumentRendererNativeID;
 include protocol PObjectWrapper;
 include protocol PContextWrapper;
 include protocol PGeolocationRequest;
 include protocol PContentDialog;
 
 include "mozilla/TabTypes.h";
 include "TabMessageUtils.h";
 include "gfxMatrix.h";
@@ -58,16 +59,17 @@ using gfxMatrix;
 namespace mozilla {
 namespace dom {
 
 rpc protocol PIFrameEmbedding
 {
     manager PContentProcess;
     manages PDocumentRenderer;
     manages PDocumentRendererShmem;
+    manages PDocumentRendererNativeID;
     manages PContextWrapper;
     manages PGeolocationRequest;
     manages PContentDialog;
 
 child:
     __delete__();
 
 parent:
@@ -153,17 +155,18 @@ child:
 
     loadRemoteScript(nsString aURL);
 
     sendAsyncMessageToChild(nsString aMessage, nsString aJSON);
 
     PDocumentRenderer(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush);
 
     // @param matrix the transformation matrix the context we're going to draw into should have.
-    // @param bufw the width of @buf, in pixels
-    // @param bufh the height of @buf, in pixels
     PDocumentRendererShmem(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush,
-                           gfxMatrix matrix, PRInt32 bufw, PRInt32 bufh, Shmem buf);
+                           gfxMatrix matrix, Shmem buf);
 
+    // @param matrix the transformation matrix the context we're going to draw into should have.
+    PDocumentRendererNativeID(PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h, nsString bgcolor, PRUint32 flags, bool flush,
+                              gfxMatrix matrix, PRUint32 nativeID);
 };
 
 }
 }
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -46,16 +46,17 @@
 #include "nsComponentManagerUtils.h"
 #include "nsIBaseWindow.h"
 #include "nsIDOMWindow.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsThreadUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/DocumentRendererShmemChild.h"
+#include "mozilla/ipc/DocumentRendererNativeIDChild.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsISupportsImpl.h"
 #include "nsIURI.h"
 #include "nsIWebBrowserFocus.h"
 #include "nsIDOMEvent.h"
 #include "nsIPrivateDOMEvent.h"
@@ -705,18 +706,16 @@ TabChild::AllocPDocumentRendererShmem(
         const PRInt32& x,
         const PRInt32& y,
         const PRInt32& w,
         const PRInt32& h,
         const nsString& bgcolor,
         const PRUint32& flags,
         const bool& flush,
         const gfxMatrix& aMatrix,
-        const PRInt32& bufw,
-        const PRInt32& bufh,
         Shmem& buf)
 {
     return new mozilla::ipc::DocumentRendererShmemChild();
 }
 
 bool
 TabChild::DeallocPDocumentRendererShmem(PDocumentRendererShmemChild* actor)
 {
@@ -730,45 +729,103 @@ TabChild::RecvPDocumentRendererShmemCons
         const PRInt32& aX,
         const PRInt32& aY,
         const PRInt32& aW,
         const PRInt32& aH,
         const nsString& bgcolor,
         const PRUint32& flags,
         const bool& flush,
         const gfxMatrix& aMatrix,
-        const PRInt32& aBufW,
-        const PRInt32& aBufH,
         Shmem& aBuf)
 {
     mozilla::ipc::DocumentRendererShmemChild *render = 
         static_cast<mozilla::ipc::DocumentRendererShmemChild *>(__a);
 
     nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(mWebNav);
     if (!browser)
         return true; // silently ignore
  
    nsCOMPtr<nsIDOMWindow> window;
     if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
         !window)
          return true; // silently ignore
  
     render->RenderDocument(window, aX, aY, aW, aH, bgcolor, flags, flush,
-                           aMatrix, aBufW, aBufH, aBuf);
+                           aMatrix, aBuf);
 
     gfxRect dirtyArea(0, 0, nsPresContext::AppUnitsToIntCSSPixels(aW), 
                       nsPresContext::AppUnitsToIntCSSPixels(aH));
 
     dirtyArea = aMatrix.Transform(dirtyArea);
 
     return PDocumentRendererShmemChild::Send__delete__(__a, dirtyArea.X(), dirtyArea.Y(), 
                                                        dirtyArea.Width(), dirtyArea.Height(),
                                                        aBuf);
 }
 
+mozilla::ipc::PDocumentRendererNativeIDChild*
+TabChild::AllocPDocumentRendererNativeID(
+        const PRInt32& x,
+        const PRInt32& y,
+        const PRInt32& w,
+        const PRInt32& h,
+        const nsString& bgcolor,
+        const PRUint32& flags,
+        const bool& flush,
+        const gfxMatrix& aMatrix,
+        const PRUint32& nativeID)
+{
+    return new mozilla::ipc::DocumentRendererNativeIDChild();
+}
+
+bool
+TabChild::DeallocPDocumentRendererNativeID(PDocumentRendererNativeIDChild* actor)
+{
+    delete actor;
+    return true;
+}
+
+bool
+TabChild::RecvPDocumentRendererNativeIDConstructor(
+        PDocumentRendererNativeIDChild *__a,
+        const PRInt32& aX,
+        const PRInt32& aY,
+        const PRInt32& aW,
+        const PRInt32& aH,
+        const nsString& bgcolor,
+        const PRUint32& flags,
+        const bool& flush,
+        const gfxMatrix& aMatrix,
+        const PRUint32& aNativeID)
+{
+    mozilla::ipc::DocumentRendererNativeIDChild* render =
+        static_cast<mozilla::ipc::DocumentRendererNativeIDChild*>(__a);
+
+    nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(mWebNav);
+    if (!browser)
+        return true; // silently ignore
+
+    nsCOMPtr<nsIDOMWindow> window;
+    if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) ||
+        !window)
+        return true; // silently ignore
+
+    render->RenderDocument(window, aX, aY, aW, aH, bgcolor, flags, flush,
+                           aMatrix, aNativeID);
+
+    gfxRect dirtyArea(0, 0, nsPresContext::AppUnitsToIntCSSPixels(aW),
+                      nsPresContext::AppUnitsToIntCSSPixels(aH));
+
+    dirtyArea = aMatrix.Transform(dirtyArea);
+
+    return PDocumentRendererNativeIDChild::Send__delete__(__a, dirtyArea.X(), dirtyArea.Y(),
+                                                          dirtyArea.Width(), dirtyArea.Height(),
+                                                          aNativeID);
+}
+
 PContentDialogChild*
 TabChild::AllocPContentDialog(const PRUint32&,
                               const nsCString&,
                               const nsCString&,
                               const nsTArray<int>&,
                               const nsTArray<nsString>&)
 {
   return new ContentDialogChild();
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -232,34 +232,53 @@ public:
             const PRInt32& x,
             const PRInt32& y,
             const PRInt32& w,
             const PRInt32& h,
             const nsString& bgcolor,
             const PRUint32& flags,
             const bool& flush,
             const gfxMatrix& aMatrix,
-            const PRInt32& bufw,
-            const PRInt32& bufh,
             Shmem& buf);
     virtual bool DeallocPDocumentRendererShmem(PDocumentRendererShmemChild* actor);
     virtual bool RecvPDocumentRendererShmemConstructor(
             PDocumentRendererShmemChild *__a,
             const PRInt32& aX,
             const PRInt32& aY,
             const PRInt32& aW,
             const PRInt32& aH,
             const nsString& bgcolor,
             const PRUint32& flags,
             const bool& flush,
             const gfxMatrix& aMatrix,
-            const PRInt32& aBufW,
-            const PRInt32& aBufH,
             Shmem& aBuf);
 
+    virtual PDocumentRendererNativeIDChild* AllocPDocumentRendererNativeID(
+            const PRInt32& x,
+            const PRInt32& y,
+            const PRInt32& w,
+            const PRInt32& h,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush,
+            const gfxMatrix& aMatrix,
+            const PRUint32& nativeID);
+    virtual bool DeallocPDocumentRendererNativeID(PDocumentRendererNativeIDChild* actor);
+    virtual bool RecvPDocumentRendererNativeIDConstructor(
+            PDocumentRendererNativeIDChild *__a,
+            const PRInt32& aX,
+            const PRInt32& aY,
+            const PRInt32& aW,
+            const PRInt32& aH,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush,
+            const gfxMatrix& aMatrix,
+            const PRUint32& aNativeID);
+
     virtual PGeolocationRequestChild* AllocPGeolocationRequest(const IPC::URI& uri);
     virtual bool DeallocPGeolocationRequest(PGeolocationRequestChild* actor);
 
     nsIWebNavigation* WebNavigation() { return mWebNav; }
 
     JSContext* GetJSContext() { return mCx; }
 
     nsIPrincipal* GetPrincipal() { return mPrincipal; }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -35,16 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "TabParent.h"
 
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/DocumentRendererShmemParent.h"
+#include "mozilla/ipc/DocumentRendererNativeIDParent.h"
 #include "mozilla/dom/ContentProcessParent.h"
 #include "mozilla/jsipc/ContextWrapperParent.h"
 
 #include "nsIURI.h"
 #include "nsFocusManager.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMElement.h"
@@ -63,16 +64,17 @@
 #include "nsContentUtils.h"
 #include "nsGeolocationOOP.h"
 #include "nsIDOMNSHTMLFrameElement.h"
 #include "nsIDialogCreator.h"
 #include "nsThreadUtils.h"
 
 using mozilla::ipc::DocumentRendererParent;
 using mozilla::ipc::DocumentRendererShmemParent;
+using mozilla::ipc::DocumentRendererNativeIDParent;
 using mozilla::dom::ContentProcessParent;
 using mozilla::jsipc::PContextWrapperParent;
 using mozilla::jsipc::ContextWrapperParent;
 
 // The flags passed by the webProgress notifications are 16 bits shifted
 // from the ones registered by webProgressListeners.
 #define NOTIFY_FLAG_SHIFT 16
 
@@ -425,28 +427,44 @@ TabParent::DeallocPDocumentRenderer(PDoc
     delete actor;
     return true;
 }
 
 mozilla::ipc::PDocumentRendererShmemParent*
 TabParent::AllocPDocumentRendererShmem(const PRInt32& x,
         const PRInt32& y, const PRInt32& w, const PRInt32& h, const nsString& bgcolor,
         const PRUint32& flags, const bool& flush, const gfxMatrix& aMatrix,
-        const PRInt32& bufw, const PRInt32& bufh, Shmem &buf)
+        Shmem& buf)
 {
     return new DocumentRendererShmemParent();
 }
 
 bool
 TabParent::DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor)
 {
     delete actor;
     return true;
 }
 
+mozilla::ipc::PDocumentRendererNativeIDParent*
+TabParent::AllocPDocumentRendererNativeID(const PRInt32& x,
+        const PRInt32& y, const PRInt32& w, const PRInt32& h, const nsString& bgcolor,
+        const PRUint32& flags, const bool& flush, const gfxMatrix& aMatrix,
+        const PRUint32& nativeID)
+{
+    return new DocumentRendererNativeIDParent();
+}
+
+bool
+TabParent::DeallocPDocumentRendererNativeID(PDocumentRendererNativeIDParent* actor)
+{
+    delete actor;
+    return true;
+}
+
 PContextWrapperParent*
 TabParent::AllocPContextWrapper()
 {
     ContentProcessParent* cpp =
         static_cast<ContentProcessParent*>(Manager());
     return new ContextWrapperParent(cpp);
 }
 
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -160,21 +160,32 @@ public:
             const PRInt32& x,
             const PRInt32& y,
             const PRInt32& w,
             const PRInt32& h,
             const nsString& bgcolor,
             const PRUint32& flags,
             const bool& flush,
             const gfxMatrix& aMatrix,
-            const PRInt32& bufw,
-            const PRInt32& bufh,
             Shmem& buf);
     virtual bool DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor);
 
+    virtual mozilla::ipc::PDocumentRendererNativeIDParent* AllocPDocumentRendererNativeID(
+            const PRInt32& x,
+            const PRInt32& y,
+            const PRInt32& w,
+            const PRInt32& h,
+            const nsString& bgcolor,
+            const PRUint32& flags,
+            const bool& flush,
+            const gfxMatrix& aMatrix,
+            const PRUint32& nativeID);
+    virtual bool DeallocPDocumentRendererNativeID(PDocumentRendererNativeIDParent* actor);
+
+
     virtual PContextWrapperParent* AllocPContextWrapper();
     virtual bool DeallocPContextWrapper(PContextWrapperParent* actor);
 
     virtual PGeolocationRequestParent* AllocPGeolocationRequest(const IPC::URI& uri);
     virtual bool DeallocPGeolocationRequest(PGeolocationRequestParent* actor);
 
     JSBool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
 
--- a/dom/ipc/ipdl.mk
+++ b/dom/ipc/ipdl.mk
@@ -34,10 +34,11 @@
 #
 # ***** END LICENSE BLOCK *****
 
 IPDLSRCS = \
   PContentProcess.ipdl \
   PIFrameEmbedding.ipdl \
   PDocumentRenderer.ipdl \
   PDocumentRendererShmem.ipdl \
+  PDocumentRendererNativeID.ipdl \
   PContentDialog.ipdl \
   $(NULL)
--- a/gfx/thebes/public/gfxSharedImageSurface.h
+++ b/gfx/thebes/public/gfxSharedImageSurface.h
@@ -82,17 +82,17 @@ public:
 
         return InitSurface(PR_TRUE);
     }
 
     /* Gives Shmem data, which can be passed to IPDL interfaces */
     mozilla::ipc::Shmem& GetShmem() { return mShmem; }
 
     // This can be used for recognizing normal gfxImageSurface as SharedImage
-    static cairo_user_data_key_t SHM_KEY;
+    static PRBool IsSharedImage(gfxASurface *aSurface);
 
 private:
     size_t GetAlignedSize();
     bool InitSurface(PRBool aUpdateShmemInfo);
 
     mozilla::ipc::Shmem mShmem;
 };
 
--- a/gfx/thebes/src/gfxSharedImageSurface.cpp
+++ b/gfx/thebes/src/gfxSharedImageSurface.cpp
@@ -39,17 +39,17 @@
 #include "base/basictypes.h"
 #include "gfxSharedImageSurface.h"
 #include "cairo.h"
 
 #define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
 
 using mozilla::ipc::SharedMemory;
 
-cairo_user_data_key_t gfxSharedImageSurface::SHM_KEY;
+static cairo_user_data_key_t SHM_KEY;
 
 typedef struct _SharedImageInfo
 {
     PRInt32 width;
     PRInt32 height;
     PRInt32 format;
 } SharedImageInfo;
 
@@ -78,17 +78,17 @@ gfxSharedImageSurface::InitSurface(PRBoo
                                             mSize.width,
                                             mSize.height,
                                             mStride);
 
     if (!surface)
         return false;
 
     cairo_surface_set_user_data(surface,
-                                &gfxSharedImageSurface::SHM_KEY,
+                                &SHM_KEY,
                                 this, NULL);
 
     if (aUpdateShmemInfo) {
         SharedImageInfo *shmInfo = GetShmInfoPtr(mShmem);
         shmInfo->width = mSize.width;
         shmInfo->height = mSize.height;
         shmInfo->format = mFormat;
     }
@@ -112,8 +112,16 @@ gfxSharedImageSurface::gfxSharedImageSur
     mSize.width = shmInfo->width;
     mSize.height = shmInfo->height;
     mFormat = (gfxImageFormat)shmInfo->format;
     mStride = ComputeStride();
 
     if (!InitSurface(PR_FALSE))
         NS_RUNTIMEABORT("Shared memory is bad");
 }
+
+PRBool
+gfxSharedImageSurface::IsSharedImage(gfxASurface *aSurface)
+{
+    return (aSurface
+            && aSurface->GetType() == gfxASurface::SurfaceTypeImage
+            && aSurface->GetData(&SHM_KEY));
+}