Bug 524180 - Implement async drawWindow/Element() using shared memory. r=cjones

This commit is contained in:
Joe Drew 2010-03-24 03:47:18 -07:00
parent 3898298861
commit 3c10247655
22 changed files with 837 additions and 64 deletions

View File

@ -0,0 +1,70 @@
/* ***** 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
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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_DocumentRendererShmemChild
#define mozilla_dom_DocumentRendererShmemChild
#include "mozilla/ipc/PDocumentRendererShmemChild.h"
class nsIDOMWindow;
class gfxMatrix;
namespace mozilla {
namespace ipc {
class DocumentRendererShmemChild : public PDocumentRendererShmemChild
{
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);
};
}
}
#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
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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_DocumentRendererShmemParent
#define mozilla_dom_DocumentRendererShmemParent
#include "mozilla/ipc/PDocumentRendererShmemParent.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsCOMPtr.h"
namespace mozilla {
namespace ipc {
class DocumentRendererShmemParent : public PDocumentRendererShmemParent
{
public:
DocumentRendererShmemParent();
virtual ~DocumentRendererShmemParent();
void SetCanvas(nsICanvasRenderingContextInternal* aCanvas);
virtual bool Recv__delete__(const PRInt32& x, const PRInt32& y,
const PRInt32& w, const PRInt32& h,
Shmem& data);
private:
nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas;
DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererShmemParent);
};
}
}
#endif

View File

@ -56,6 +56,8 @@ EXPORTS = \
EXPORTS_mozilla/ipc = \
DocumentRendererChild.h \
DocumentRendererParent.h \
DocumentRendererShmemChild.h \
DocumentRendererShmemParent.h \
$(NULL)
XPIDLSRCS = \

View File

@ -44,13 +44,19 @@
#include "nsIDocShell.h"
#include "gfxPattern.h"
// {ed741c16-4039-469b-91da-dca742c51a9f}
// {3c4632ab-8443-4082-a8a310e7cfba4c74}
#define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
{ 0xed741c16, 0x4039, 0x469b, { 0x91, 0xda, 0xdc, 0xa7, 0x42, 0xc5, 0x1a, 0x9f } }
{ 0x3c4632ab, 0x8443, 0x4082, { 0xa8, 0xa3, 0x10, 0xe7, 0xcf, 0xba, 0x4c, 0x74 } }
class gfxContext;
class gfxASurface;
namespace mozilla {
namespace ipc {
class Shmem;
}
}
class nsICanvasRenderingContextInternal : public nsISupports {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
@ -90,6 +96,17 @@ public:
// Redraw the dirty rectangle of this canvas.
NS_IMETHOD Redraw(const gfxRect &dirty) = 0;
// If this context can be set to use Mozilla's Shmem segments as its backing
// store, this will set it to that state. Note that if you have drawn
// 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;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,

View File

@ -0,0 +1,145 @@
/* ***** 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
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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 "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/DocumentRendererShmemChild.h"
using namespace mozilla::ipc;
DocumentRendererShmemChild::DocumentRendererShmemChild()
{}
DocumentRendererShmemChild::~DocumentRendererShmemChild()
{}
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
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) {
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<gfxImageSurface> surf = new gfxImageSurface(data.get<PRUint8>(),
gfxIntSize(bufw, bufh),
4 * bufw,
gfxASurface::ImageFormatARGB32);
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
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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/DocumentRendererShmemParent.h"
using namespace mozilla::ipc;
DocumentRendererShmemParent::DocumentRendererShmemParent()
{}
DocumentRendererShmemParent::~DocumentRendererShmemParent()
{}
void
DocumentRendererShmemParent::SetCanvas(nsICanvasRenderingContextInternal* aCanvas)
{
mCanvas = aCanvas;
}
bool
DocumentRendererShmemParent::Recv__delete__(const PRInt32& x, const PRInt32& y,
const PRInt32& w, const PRInt32& h,
Shmem& data)
{
mCanvas->Swap(data, x, y, w, h);
return true;
}

View File

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

View File

@ -359,7 +359,6 @@ WebGLContext::GetThebesSurface(gfxASurface **surface)
return NS_OK;
}
//
// XPCOM goop
//

View File

@ -243,7 +243,13 @@ 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; }
#ifdef MOZ_IPC
NS_IMETHOD Swap(mozilla::ipc::Shmem& aBack,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
{ return NS_ERROR_NOT_IMPLEMENTED; }
#endif
protected:
GLES20Wrap *gl;

View File

@ -116,9 +116,12 @@
#include "CanvasUtils.h"
#ifdef MOZ_IPC
# include "mozilla/dom/ContentProcessParent.h"
# include "mozilla/ipc/PDocumentRendererParent.h"
# include "mozilla/ipc/PDocumentRendererShmemParent.h"
# include "mozilla/dom/PIFrameEmbeddingParent.h"
# include "mozilla/ipc/DocumentRendererParent.h"
# include "mozilla/ipc/DocumentRendererShmemParent.h"
// windows.h (included by chromium code) defines this, in its infinite wisdom
# undef DrawText
#endif
@ -171,6 +174,28 @@ static PRBool FloatValidate (double f1, double f2, double f3, double f4, double
#undef VALIDATE
static void
CopyContext(gfxContext* dest, gfxContext* src)
{
dest->Multiply(src->CurrentMatrix());
nsRefPtr<gfxPath> path = src->CopyPath();
dest->NewPath();
dest->AppendPath(path);
nsRefPtr<gfxPattern> pattern = src->GetPattern();
dest->SetPattern(pattern);
dest->SetLineWidth(src->CurrentLineWidth());
dest->SetLineCap(src->CurrentLineCap());
dest->SetLineJoin(src->CurrentLineJoin());
dest->SetMiterLimit(src->CurrentMiterLimit());
dest->SetFillRule(src->CurrentFillRule());
dest->SetAntialiasMode(src->CurrentAntialiasMode());
}
/**
** nsCanvasGradient
**/
@ -339,8 +364,15 @@ public:
nsIInputStream **aStream);
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
NS_IMETHOD SetIsOpaque(PRBool isOpaque);
NS_IMETHOD SetIsShmem(PRBool isShmem);
// this rect is in CSS pixels
NS_IMETHOD Redraw(const gfxRect &r);
#ifdef MOZ_IPC
// 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);
#endif
// nsISupports interface
NS_DECL_ISUPPORTS
@ -405,6 +437,21 @@ protected:
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;
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);
#endif
// the canvas element informs us when it's going away,
// so these are not nsCOMPtrs
nsICanvasElement* mCanvasElement;
@ -697,7 +744,7 @@ NS_NewCanvasRenderingContext2D(nsIDOMCanvasRenderingContext2D** aResult)
}
nsCanvasRenderingContext2D::nsCanvasRenderingContext2D()
: mValid(PR_FALSE), mOpaque(PR_FALSE), mCanvasElement(nsnull),
: mValid(PR_FALSE), mOpaque(PR_FALSE), mShmem(PR_FALSE), mCanvasElement(nsnull),
mSaveCount(0), mIsEntireFrameInvalid(PR_FALSE), mInvalidateCount(0),
mLastStyle(STYLE_MAX), mStyleStack(20)
{
@ -905,6 +952,26 @@ nsCanvasRenderingContext2D::Redraw(const gfxRect& r)
return mCanvasElement->InvalidateFrameSubrect(r);
}
#ifdef MOZ_IPC
bool
nsCanvasRenderingContext2D::CreateShmemSegments(PRInt32 width, PRInt32 height,
gfxASurface::gfxImageFormat format)
{
if (!mozilla::dom::ContentProcessParent::GetSingleton()->
AllocShmem(width * height * 4, &mFrontBuffer))
return false;
if (!mozilla::dom::ContentProcessParent::GetSingleton()->
AllocShmem(width * height * 4, &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)
{
@ -918,12 +985,19 @@ nsCanvasRenderingContext2D::SetDimensions(PRInt32 width, PRInt32 height)
if (mOpaque)
format = gfxASurface::ImageFormatRGB24;
surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface
(gfxIntSize(width, height), format);
#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);
if (surface->CairoStatus() != 0) {
surface = NULL;
}
if (surface && surface->CairoStatus() != 0)
surface = NULL;
}
return InitializeWithSurface(NULL, surface, width, height);
}
@ -1001,6 +1075,60 @@ nsCanvasRenderingContext2D::SetIsOpaque(PRBool isOpaque)
return NS_OK;
}
NS_IMETHODIMP
nsCanvasRenderingContext2D::SetIsShmem(PRBool isShmem)
{
if (isShmem == mShmem)
return NS_OK;
mShmem = isShmem;
if (mValid) {
/* If we've already been created, let SetDimensions take care of
* recreating our surface
*/
return SetDimensions(mWidth, mHeight);
}
return NS_OK;
}
#ifdef MOZ_IPC
NS_IMETHODIMP
nsCanvasRenderingContext2D::Swap(mozilla::ipc::Shmem& aBack,
PRInt32 x, PRInt32 y, PRInt32 w, PRInt32 h)
{
// 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);
return NS_OK;
}
#endif
NS_IMETHODIMP
nsCanvasRenderingContext2D::Render(gfxContext *ctx, gfxPattern::GraphicsFilter aFilter)
{
@ -1536,27 +1664,6 @@ nsCanvasRenderingContext2D::GetShadowColor(nsAString& color)
return NS_OK;
}
static void
CopyContext(gfxContext* dest, gfxContext* src)
{
dest->Multiply(src->CurrentMatrix());
nsRefPtr<gfxPath> path = src->CopyPath();
dest->NewPath();
dest->AppendPath(path);
nsRefPtr<gfxPattern> pattern = src->GetPattern();
dest->SetPattern(pattern);
dest->SetLineWidth(src->CurrentLineWidth());
dest->SetLineCap(src->CurrentLineCap());
dest->SetLineJoin(src->CurrentLineJoin());
dest->SetMiterLimit(src->CurrentMiterLimit());
dest->SetFillRule(src->CurrentFillRule());
dest->SetAntialiasMode(src->CurrentAntialiasMode());
}
static const gfxFloat SIGMA_MAX = 25;
gfxContext*
@ -3461,11 +3568,37 @@ nsCanvasRenderingContext2D::AsyncDrawXULElement(nsIDOMXULElement* aElem, float a
w = nsPresContext::CSSPixelsToAppUnits(aW),
h = nsPresContext::CSSPixelsToAppUnits(aH);
mozilla::ipc::PDocumentRendererParent *pdocrender =
child->SendPDocumentRendererConstructor(x, y, w, h, nsString(aBGColor), renderDocFlags, flush);
mozilla::ipc::DocumentRendererParent *docrender = static_cast<mozilla::ipc::DocumentRendererParent *>(pdocrender);
if (mShmem) {
if (!mBackBuffer.IsWritable())
return NS_ERROR_FAILURE;
docrender->SetCanvasContext(this, mThebes);
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 =
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);
docrender->SetCanvasContext(this, mThebes);
}
return NS_OK;
#else

View File

@ -126,6 +126,8 @@ protected:
nsresult ToDataURLImpl(const nsAString& aMimeType,
const nsAString& aEncoderOptions,
nsAString& aDataURL);
nsresult GetContextHelper(const nsAString& aContextId,
nsICanvasRenderingContextInternal **aContext);
nsString mCurrentContextId;
nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
@ -412,6 +414,55 @@ nsHTMLCanvasElement::ToDataURLImpl(const nsAString& aMimeType,
return NS_OK;
}
nsresult
nsHTMLCanvasElement::GetContextHelper(const nsAString& aContextId,
nsICanvasRenderingContextInternal **aContext)
{
NS_ENSURE_ARG(aContext);
nsCString ctxId;
ctxId.Assign(NS_LossyConvertUTF16toASCII(aContextId));
// check that ctxId is clamped to A-Za-z0-9_-
for (PRUint32 i = 0; i < ctxId.Length(); i++) {
if ((ctxId[i] < 'A' || ctxId[i] > 'Z') &&
(ctxId[i] < 'a' || ctxId[i] > 'z') &&
(ctxId[i] < '0' || ctxId[i] > '9') &&
(ctxId[i] != '-') &&
(ctxId[i] != '_'))
{
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_INVALID_ARG;
}
}
nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id=");
ctxString.Append(ctxId);
nsresult rv;
nsCOMPtr<nsICanvasRenderingContextInternal> ctx =
do_CreateInstance(nsPromiseFlatCString(ctxString).get(), &rv);
if (rv == NS_ERROR_OUT_OF_MEMORY) {
*aContext = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
if (NS_FAILED(rv)) {
*aContext = nsnull;
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_INVALID_ARG;
}
rv = ctx->SetCanvasElement(this);
if (NS_FAILED(rv)) {
*aContext = nsnull;
return rv;
}
*aContext = ctx.forget().get();
return rv;
}
NS_IMETHODIMP
nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
nsISupports **aContext)
@ -419,37 +470,9 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
nsresult rv;
if (mCurrentContextId.IsEmpty()) {
nsCString ctxId;
ctxId.Assign(NS_LossyConvertUTF16toASCII(aContextId));
// check that ctxId is clamped to A-Za-z0-9_-
for (PRUint32 i = 0; i < ctxId.Length(); i++) {
if ((ctxId[i] < 'A' || ctxId[i] > 'Z') &&
(ctxId[i] < 'a' || ctxId[i] > 'z') &&
(ctxId[i] < '0' || ctxId[i] > '9') &&
(ctxId[i] != '-') &&
(ctxId[i] != '_'))
{
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_INVALID_ARG;
}
}
nsCString ctxString("@mozilla.org/content/canvas-rendering-context;1?id=");
ctxString.Append(ctxId);
mCurrentContext = do_CreateInstance(nsPromiseFlatCString(ctxString).get(), &rv);
if (rv == NS_ERROR_OUT_OF_MEMORY)
return NS_ERROR_OUT_OF_MEMORY;
rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext));
if (NS_FAILED(rv))
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_INVALID_ARG;
rv = mCurrentContext->SetCanvasElement(this);
if (NS_FAILED(rv)) {
mCurrentContext = nsnull;
return rv;
}
rv = UpdateContext();
if (NS_FAILED(rv)) {
@ -467,6 +490,48 @@ nsHTMLCanvasElement::GetContext(const nsAString& aContextId,
return NS_OK;
}
NS_IMETHODIMP
nsHTMLCanvasElement::MozGetShmemContext(const nsAString& aContextId,
nsISupports **aContext)
{
#ifdef MOZ_IPC
if(!nsContentUtils::IsCallerTrustedForRead()) {
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
return NS_ERROR_DOM_SECURITY_ERR;
}
// We only support 2d shmem contexts for now.
if (!aContextId.Equals(NS_LITERAL_STRING("2d")))
return NS_ERROR_INVALID_ARG;
nsresult rv;
if (mCurrentContextId.IsEmpty()) {
rv = GetContextHelper(aContextId, getter_AddRefs(mCurrentContext));
if (NS_FAILED(rv))
return rv;
mCurrentContext->SetIsShmem(PR_TRUE);
rv = UpdateContext();
if (NS_FAILED(rv)) {
mCurrentContext = nsnull;
return rv;
}
mCurrentContextId.Assign(aContextId);
} else if (!mCurrentContextId.Equals(aContextId)) {
//XXX eventually allow for more than one active context on a given canvas
return NS_ERROR_INVALID_ARG;
}
NS_ADDREF (*aContext = mCurrentContext);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
nsresult
nsHTMLCanvasElement::UpdateContext()
{

View File

@ -47,7 +47,7 @@
* @status UNDER_DEVELOPMENT
*/
[scriptable, uuid(b5f8239b-2abf-4896-b772-71e1e374a661)]
[scriptable, uuid(5ef1c2ee-4b3a-4015-8e38-c27ddb306c39)]
interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
{
attribute long width;
@ -70,5 +70,9 @@ interface nsIDOMHTMLCanvasElement : nsIDOMHTMLElement
// the options string that it supports. Separate multiple options with
// semicolons.
[noscript] DOMString toDataURLAs(in DOMString mimeType, in DOMString encoderOptions);
// A Mozilla-only extension to get a canvas context backed by double-buffered
// shared memory. Only privileged callers can call this.
nsISupports MozGetShmemContext(in DOMString contextId);
};

View File

@ -70,6 +70,9 @@ public:
return sSingleton;
}
/* if you remove this, please talk to cjones or dougt */
virtual bool RecvDummy(Shmem& foo) { return true; }
virtual PIFrameEmbeddingChild* AllocPIFrameEmbedding();
virtual bool DeallocPIFrameEmbedding(PIFrameEmbeddingChild*);

View File

@ -61,6 +61,10 @@ child:
PTestShell();
// A dummy message to make sure PContentProcess contains methods to create
// Shmem segments.
async Dummy(Shmem foo);
RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
OverrideMapping[] overrides);

View File

@ -45,6 +45,7 @@ protocol PDocumentRenderer
manager PIFrameEmbedding;
parent:
// Returns the width and height, in pixels, of the returned ARGB32 data.
__delete__(PRUint32 w, PRUint32 h, nsCString data);
};

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
* The Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* 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.ipdl";
namespace mozilla {
namespace ipc {
protocol PDocumentRendererShmem
{
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, Shmem data);
};
} // namespace ipc
} // namespace mozilla

View File

@ -39,12 +39,15 @@
include protocol "PContentProcess.ipdl";
include protocol "PDocumentRenderer.ipdl";
include protocol "PDocumentRendererShmem.ipdl";
include "mozilla/TabTypes.h";
include "TabMessageUtils.h";
include "gfxMatrix.h";
using MagicWindowHandle;
using RemoteDOMEvent;
using gfxMatrix;
namespace mozilla {
namespace dom {
@ -53,6 +56,7 @@ rpc protocol PIFrameEmbedding
{
manager PContentProcess;
manages PDocumentRenderer;
manages PDocumentRendererShmem;
child:
__delete__();
@ -115,6 +119,13 @@ child:
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);
};
}

View File

@ -47,6 +47,7 @@
#include "nsThreadUtils.h"
#include "nsIInterfaceRequestorUtils.h"
#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/DocumentRendererShmemChild.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMWindowUtils.h"
@ -66,6 +67,7 @@
#include "nsScriptLoader.h"
#include "nsPIWindowRoot.h"
#include "nsIScriptContext.h"
#include "nsPresContext.h"
#ifdef MOZ_WIDGET_QT
#include <QX11EmbedWidget>
@ -485,6 +487,70 @@ TabChild::RecvPDocumentRendererConstructor(
return PDocumentRendererChild::Send__delete__(__a, width, height, data);
}
mozilla::ipc::PDocumentRendererShmemChild*
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)
{
delete actor;
return true;
}
bool
TabChild::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)
{
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);
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);
}
bool
TabChild::RecvactivateFrameEvent(const nsString& aType, const bool& capture)
{

View File

@ -66,6 +66,8 @@
#include "nsIScriptObjectPrincipal.h"
#include "nsIScriptContext.h"
class gfxMatrix;
namespace mozilla {
namespace dom {
@ -194,6 +196,33 @@ public:
const PRUint32& flags,
const bool& flush);
virtual PDocumentRendererShmemChild* 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);
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);
nsIWebNavigation* WebNavigation() { return mWebNav; }
JSContext* GetJSContext() { return mCx; }

View File

@ -39,6 +39,7 @@
#include "TabParent.h"
#include "mozilla/ipc/DocumentRendererParent.h"
#include "mozilla/ipc/DocumentRendererShmemParent.h"
#include "nsIURI.h"
#include "nsFocusManager.h"
@ -52,6 +53,7 @@
#include "nsFrameLoader.h"
using mozilla::ipc::DocumentRendererParent;
using mozilla::ipc::DocumentRendererShmemParent;
namespace mozilla {
namespace dom {
@ -155,6 +157,22 @@ TabParent::DeallocPDocumentRenderer(PDocumentRendererParent* 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)
{
return new DocumentRendererShmemParent();
}
bool
TabParent::DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor)
{
delete actor;
return true;
}
void
TabParent::SendMouseEvent(const nsAString& aType, float aX, float aY,
PRInt32 aButton, PRInt32 aClickCount,

View File

@ -48,6 +48,7 @@
class nsIURI;
class nsIDOMElement;
class gfxMatrix;
namespace mozilla {
namespace dom {
@ -90,6 +91,21 @@ public:
const PRUint32& flags,
const bool& flush);
virtual bool DeallocPDocumentRenderer(PDocumentRendererParent* actor);
virtual mozilla::ipc::PDocumentRendererShmemParent* 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);
virtual bool DeallocPDocumentRendererShmem(PDocumentRendererShmemParent* actor);
protected:
nsIDOMElement* mFrameElement;
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;

View File

@ -38,4 +38,5 @@ IPDLSRCS = \
PContentProcess.ipdl \
PIFrameEmbedding.ipdl \
PDocumentRenderer.ipdl \
PDocumentRendererShmem.ipdl \
$(NULL)