Bug 548437 - Implement a SysV shared memory backend for Shmem and allow them to be used with Xshm. r=joe,sr=vladimir

This commit is contained in:
Oleg Romashin 2010-06-04 09:58:22 -04:00
parent d338144c26
commit 3ff669701f
20 changed files with 775 additions and 129 deletions

View File

@ -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

View File

@ -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

View File

@ -56,7 +56,6 @@ public:
const PRInt32& h, const nsString& aBGColor,
const PRUint32& flags, const PRBool& flush,
const gfxMatrix& aMatrix,
const PRInt32& bufw, const PRInt32& bufh,
Shmem& data);
private:

View File

@ -57,6 +57,8 @@ EXPORTS_mozilla/ipc = \
DocumentRendererParent.h \
DocumentRendererShmemChild.h \
DocumentRendererShmemParent.h \
DocumentRendererNativeIDChild.h \
DocumentRendererNativeIDParent.h \
$(NULL)
XPIDLSRCS = \

View File

@ -121,6 +121,11 @@ public:
// 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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -54,6 +54,9 @@
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "nsLayoutUtils.h"
#ifdef MOZ_IPC
#include "gfxSharedImageSurface.h"
#endif
#include "mozilla/ipc/DocumentRendererShmemChild.h"
@ -105,7 +108,6 @@ DocumentRendererShmemChild::RenderDocument(nsIDOMWindow *window, const PRInt32&
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)
@ -133,10 +135,7 @@ DocumentRendererShmemChild::RenderDocument(nsIDOMWindow *window, const PRInt32&
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);

View File

@ -60,6 +60,8 @@ ifdef MOZ_IPC
CPPSRCS += \
DocumentRendererParent.cpp \
DocumentRendererChild.cpp \
DocumentRendererNativeIDParent.cpp \
DocumentRendererNativeIDChild.cpp \
DocumentRendererShmemParent.cpp \
DocumentRendererShmemChild.cpp \
$(NULL)

View File

@ -248,6 +248,9 @@ public:
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, ...);

View File

@ -101,10 +101,14 @@
#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"
@ -119,20 +123,30 @@
#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
@ -407,8 +421,11 @@ public:
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
@ -468,24 +485,31 @@ protected:
*/
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;
PRPackedBool mAsync;
// 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;
// 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,
@ -783,12 +807,13 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
}
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++;
}
@ -797,6 +822,13 @@ 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;
@ -809,6 +841,11 @@ nsCanvasRenderingContext2D::~nsCanvasRenderingContext2D()
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;
@ -1002,28 +1039,6 @@ nsCanvasRenderingContext2D::Redraw(const gfxRect& 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)
{
@ -1032,24 +1047,43 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
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;
gfxIntSize size(width, height);
if (gfxASurface::CheckSurfaceSize(size, 0xffff)) {
#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);
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) {
@ -1140,10 +1174,10 @@ 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
@ -1158,37 +1192,20 @@ nsCanvasRenderingContext2D::SetIsShmem(PRBool isShmem)
#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;
gfxContextPathAutoSaveRestore pathSR(mThebes);
gfxContextAutoSaveRestore autoSR(mThebes);
// Swap back and front.
// mBackBuffer should be null here, since we've previously sent it to the
// child process.
mBackBuffer = mFrontBuffer;
mFrontBuffer = aBack;
mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
mThebes->NewPath();
mThebes->SetSource(mBackSurface);
mThebes->Rectangle(aRect, PR_TRUE);
mThebes->Clip();
mThebes->Paint();
// 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);
Redraw(aRect);
// Notify listeners that we've finished drawing
nsCOMPtr<nsIContent> content =
@ -1205,11 +1222,46 @@ nsCanvasRenderingContext2D::Swap(mozilla::ipc::Shmem& aBack,
/* 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)
{
@ -1301,6 +1353,17 @@ nsCanvasRenderingContext2D::GetInputStream(const char *aMimeType,
return CallQueryInterface(encoder, aStream);
}
gfxASurface::gfxImageFormat
nsCanvasRenderingContext2D::GetImageFormat() const
{
gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatARGB32;
if (mOpaque)
format = gfxASurface::ImageFormatRGB24;
return format;
}
//
// nsCanvasRenderingContext2D impl
//
@ -3620,7 +3683,7 @@ nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float a
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());
@ -3651,34 +3714,62 @@ nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float a
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);
}

View File

@ -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

View File

@ -40,6 +40,7 @@
include protocol PContentProcess;
include protocol PDocumentRenderer;
include protocol PDocumentRendererShmem;
include protocol PDocumentRendererNativeID;
include protocol PObjectWrapper;
include protocol PContextWrapper;
include protocol PGeolocationRequest;
@ -63,6 +64,7 @@ rpc protocol PIFrameEmbedding
manager PContentProcess;
manages PDocumentRenderer;
manages PDocumentRendererShmem;
manages PDocumentRendererNativeID;
manages PContextWrapper;
manages PGeolocationRequest;
manages PContentDialog;
@ -158,11 +160,12 @@ child:
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);
};
}

View File

@ -51,6 +51,7 @@
#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"
@ -710,8 +711,6 @@ TabChild::AllocPDocumentRendererShmem(
const PRUint32& flags,
const bool& flush,
const gfxMatrix& aMatrix,
const PRInt32& bufw,
const PRInt32& bufh,
Shmem& buf)
{
return new mozilla::ipc::DocumentRendererShmemChild();
@ -735,8 +734,6 @@ TabChild::RecvPDocumentRendererShmemConstructor(
const PRUint32& flags,
const bool& flush,
const gfxMatrix& aMatrix,
const PRInt32& aBufW,
const PRInt32& aBufH,
Shmem& aBuf)
{
mozilla::ipc::DocumentRendererShmemChild *render =
@ -752,7 +749,7 @@ TabChild::RecvPDocumentRendererShmemConstructor(
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));
@ -764,6 +761,66 @@ TabChild::RecvPDocumentRendererShmemConstructor(
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&,

View File

@ -237,8 +237,6 @@ public:
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(
@ -251,10 +249,31 @@ public:
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);

View File

@ -40,6 +40,7 @@
#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"
@ -68,6 +69,7 @@
using mozilla::ipc::DocumentRendererParent;
using mozilla::ipc::DocumentRendererShmemParent;
using mozilla::ipc::DocumentRendererNativeIDParent;
using mozilla::dom::ContentProcessParent;
using mozilla::jsipc::PContextWrapperParent;
using mozilla::jsipc::ContextWrapperParent;
@ -430,7 +432,7 @@ 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();
}
@ -442,6 +444,22 @@ TabParent::DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* 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()
{

View File

@ -165,11 +165,22 @@ public:
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);

View File

@ -39,5 +39,6 @@ IPDLSRCS = \
PIFrameEmbedding.ipdl \
PDocumentRenderer.ipdl \
PDocumentRendererShmem.ipdl \
PDocumentRendererNativeID.ipdl \
PContentDialog.ipdl \
$(NULL)

View File

@ -87,7 +87,7 @@ public:
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();

View File

@ -44,7 +44,7 @@
using mozilla::ipc::SharedMemory;
cairo_user_data_key_t gfxSharedImageSurface::SHM_KEY;
static cairo_user_data_key_t SHM_KEY;
typedef struct _SharedImageInfo
{
@ -83,7 +83,7 @@ gfxSharedImageSurface::InitSurface(PRBool aUpdateShmemInfo)
return false;
cairo_surface_set_user_data(surface,
&gfxSharedImageSurface::SHM_KEY,
&SHM_KEY,
this, NULL);
if (aUpdateShmemInfo) {
@ -117,3 +117,11 @@ gfxSharedImageSurface::gfxSharedImageSurface(const mozilla::ipc::Shmem &aShmem)
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));
}