зеркало из https://github.com/mozilla/pjs.git
merge. a=backout
This commit is contained in:
Коммит
2426dac662
|
@ -29,3 +29,5 @@
|
|||
<!ENTITY testpilot.feedbackbutton.label "Feedback">
|
||||
<!ENTITY testpilot.happy.label "Firefox Made Me Happy Because…">
|
||||
<!ENTITY testpilot.sad.label "Firefox Made Me Sad Because…">
|
||||
<!ENTITY testpilot.broken.label "Report this website as broken…">
|
||||
<!ENTITY testpilot.idea.label "Give us a suggestion…">
|
||||
|
|
|
@ -62,7 +62,7 @@ ConsoleAPI.prototype = {
|
|||
}
|
||||
|
||||
let self = this;
|
||||
return {
|
||||
let chromeObject = {
|
||||
// window.console API
|
||||
log: function CA_log() {
|
||||
self.notifyObservers(id, "log", arguments);
|
||||
|
@ -76,10 +76,32 @@ ConsoleAPI.prototype = {
|
|||
error: function CA_error() {
|
||||
self.notifyObservers(id, "error", arguments);
|
||||
},
|
||||
// many flavors of console objects exist on the web, so calling
|
||||
// unimplemented methods shouldn't be fatal. See bug 614350
|
||||
__noSuchMethod__: function CA_nsm() {}
|
||||
__exposedProps__: {
|
||||
log: "r",
|
||||
info: "r",
|
||||
warn: "r",
|
||||
error: "r"
|
||||
}
|
||||
};
|
||||
|
||||
// We need to return an actual content object here, instead of a wrapped
|
||||
// chrome object. This allows things like console.log.bind() to work.
|
||||
let sandbox = Cu.Sandbox(aWindow);
|
||||
let contentObject = Cu.evalInSandbox(
|
||||
"(function(x) {\
|
||||
var bind = Function.bind;\
|
||||
var obj = {\
|
||||
log: bind.call(x.log, x),\
|
||||
info: bind.call(x.info, x),\
|
||||
warn: bind.call(x.warn, x),\
|
||||
error: bind.call(x.error, x),\
|
||||
__noSuchMethod__: function() {}\
|
||||
};\
|
||||
Object.defineProperty(obj, '__mozillaConsole__', { value: true });\
|
||||
return obj;\
|
||||
})", sandbox)(chromeObject);
|
||||
|
||||
return contentObject;
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=8 et :
|
||||
*/
|
||||
/* ***** 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 Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* 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 PPluginInstance;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* This protocol exists to allow us to correctly destroy background
|
||||
* surfaces. The browser owns the surfaces, but shares a "reference"
|
||||
* with the plugin. The browser needs to notify the plugin when the
|
||||
* background is going to be destroyed, but it can't rely on the
|
||||
* plugin to destroy it because the plugin may crash at any time. So
|
||||
* the plugin instance relinquishes destruction of the its old
|
||||
* background to actors of this protocol, which can deal with crashy
|
||||
* corner cases more easily than the instance.
|
||||
*/
|
||||
protocol PPluginBackgroundDestroyer {
|
||||
manager PPluginInstance;
|
||||
|
||||
// The ctor message for this protocol serves double-duty as
|
||||
// notification that that the background is stale.
|
||||
|
||||
parent:
|
||||
__delete__();
|
||||
|
||||
state DESTROYING:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -37,6 +37,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
include protocol PPluginBackgroundDestroyer;
|
||||
include protocol PPluginModule;
|
||||
include protocol PPluginScriptableObject;
|
||||
include protocol PBrowserStream;
|
||||
|
@ -57,6 +58,7 @@ using mozilla::gfxSurfaceType;
|
|||
using gfxIntSize;
|
||||
using mozilla::null_t;
|
||||
using mozilla::plugins::WindowsSharedMemoryHandle;
|
||||
using nsIntRect;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -83,6 +85,7 @@ rpc protocol PPluginInstance
|
|||
{
|
||||
manager PPluginModule;
|
||||
|
||||
manages PPluginBackgroundDestroyer;
|
||||
manages PPluginScriptableObject;
|
||||
manages PBrowserStream;
|
||||
manages PPluginStream;
|
||||
|
@ -126,6 +129,13 @@ child:
|
|||
// with type equals to surfaceType
|
||||
async AsyncSetWindow(gfxSurfaceType surfaceType, NPRemoteWindow window);
|
||||
|
||||
// There is now an opaque background behind this instance (or the
|
||||
// background was updated). The changed area is |rect|. The
|
||||
// browser owns the background surface, and it's read-only from
|
||||
// within the plugin process. |background| is either null_t to
|
||||
// refer to the existing background or a fresh descriptor.
|
||||
async UpdateBackground(SurfaceDescriptor background, nsIntRect rect);
|
||||
|
||||
rpc NPP_Destroy()
|
||||
returns (NPError rv);
|
||||
|
||||
|
@ -236,6 +246,8 @@ parent:
|
|||
child:
|
||||
rpc SetPluginFocus();
|
||||
rpc UpdateWindow();
|
||||
|
||||
async PPluginBackgroundDestroyer();
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=8 et :
|
||||
*/
|
||||
/* ***** 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 Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* 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 dom_plugins_PluginBackgroundDestroyer
|
||||
#define dom_plugins_PluginBackgroundDestroyer
|
||||
|
||||
#include "mozilla/plugins/PPluginBackgroundDestroyerChild.h"
|
||||
#include "mozilla/plugins/PPluginBackgroundDestroyerParent.h"
|
||||
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* When instances of this class are destroyed, the old background goes
|
||||
* along with them, completing the destruction process (whether or not
|
||||
* the plugin stayed alive long enough to ack).
|
||||
*/
|
||||
class PluginBackgroundDestroyerParent : public PPluginBackgroundDestroyerParent {
|
||||
public:
|
||||
PluginBackgroundDestroyerParent(gfxASurface* aDyingBackground)
|
||||
: mDyingBackground(aDyingBackground)
|
||||
{ }
|
||||
|
||||
virtual ~PluginBackgroundDestroyerParent() { }
|
||||
|
||||
private:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
switch(why) {
|
||||
case Deletion:
|
||||
case AncestorDeletion:
|
||||
if (gfxSharedImageSurface::IsSharedImage(mDyingBackground)) {
|
||||
gfxSharedImageSurface* s =
|
||||
static_cast<gfxSharedImageSurface*>(mDyingBackground.get());
|
||||
DeallocShmem(s->GetShmem());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// We're shutting down or crashed, let automatic cleanup
|
||||
// take care of our shmem, if we have one.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> mDyingBackground;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class exists solely to instruct its instance to release its
|
||||
* current background, a new one may be coming.
|
||||
*/
|
||||
class PluginBackgroundDestroyerChild : public PPluginBackgroundDestroyerChild {
|
||||
public:
|
||||
PluginBackgroundDestroyerChild() { }
|
||||
virtual ~PluginBackgroundDestroyerChild() { }
|
||||
|
||||
private:
|
||||
// Implementing this for good hygiene.
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why)
|
||||
{ }
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // dom_plugins_PluginBackgroundDestroyer
|
|
@ -37,6 +37,7 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "PluginBackgroundDestroyer.h"
|
||||
#include "PluginInstanceChild.h"
|
||||
#include "PluginModuleChild.h"
|
||||
#include "BrowserStreamChild.h"
|
||||
|
@ -166,7 +167,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
|||
#endif // OS_WIN
|
||||
#if defined(OS_WIN)
|
||||
InitPopupMenuHook();
|
||||
HookSystemParametersInfo();
|
||||
#endif // OS_WIN
|
||||
#ifdef MOZ_X11
|
||||
// Maemo flash can render plugin with any provided rectangle and not require this quirk.
|
||||
|
@ -924,6 +924,11 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
|||
}
|
||||
#endif
|
||||
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] Answer_SetWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
||||
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
||||
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
||||
|
||||
if (mPluginIface->setwindow)
|
||||
(void) mPluginIface->setwindow(&mData, &mWindow);
|
||||
|
||||
|
@ -1228,47 +1233,6 @@ PluginInstanceChild::PluginWindowProc(HWND hWnd,
|
|||
return res;
|
||||
}
|
||||
|
||||
/* system parameters info hook for flash */
|
||||
|
||||
typedef BOOL (WINAPI *User32SystemParametersInfoW)(UINT uiAction,
|
||||
UINT uiParam,
|
||||
PVOID pvParam,
|
||||
UINT fWinIni);
|
||||
|
||||
static User32SystemParametersInfoW sUser32SystemParametersInfoWStub = NULL;
|
||||
|
||||
static BOOL WINAPI User32SystemParametersInfoHook(UINT uiAction,
|
||||
UINT uiParam,
|
||||
PVOID pvParam,
|
||||
UINT fWinIni)
|
||||
{
|
||||
if (!sUser32SystemParametersInfoWStub) {
|
||||
NS_NOTREACHED("sUser32SystemParametersInfoWStub not set??");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Tell them cleartype is disabled, so they don't mess with
|
||||
// the alpha channel in our buffers.
|
||||
if (uiAction == SPI_GETFONTSMOOTHINGTYPE && pvParam) {
|
||||
*((UINT*)(pvParam)) = FE_FONTSMOOTHINGSTANDARD;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return sUser32SystemParametersInfoWStub(uiAction, uiParam, pvParam, fWinIni);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::HookSystemParametersInfo()
|
||||
{
|
||||
if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_MASK_CLEARTYPE_SETTINGS))
|
||||
return;
|
||||
if (sUser32SystemParametersInfoWStub)
|
||||
return;
|
||||
sUser32Intercept.Init("gdi32.dll");
|
||||
sUser32Intercept.AddHook("SystemParametersInfoW", User32SystemParametersInfoHook,
|
||||
(void**) &sUser32SystemParametersInfoWStub);
|
||||
}
|
||||
|
||||
/* set window long ptr hook for flash */
|
||||
|
||||
/*
|
||||
|
@ -2287,6 +2251,10 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
|||
const NPRemoteWindow& aWindow,
|
||||
bool aIsAsync)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] AsyncSetWindow to <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, aWindow.x, aWindow.y, aWindow.width, aWindow.height));
|
||||
|
||||
AssertPluginThread();
|
||||
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
|
||||
NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!");
|
||||
|
@ -2300,6 +2268,10 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
|||
|
||||
mWindow.window = NULL;
|
||||
if (mWindow.width != aWindow.width || mWindow.height != aWindow.height) {
|
||||
// We weakly assume here that the SetWindow arrives before the
|
||||
// next UpdateBackground, for the new window size, if we were
|
||||
// going to get one.
|
||||
mBackground = nsnull;
|
||||
ClearCurrentSurface();
|
||||
mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
|
||||
}
|
||||
|
@ -2347,9 +2319,11 @@ PluginInstanceChild::CreateOptSurface(void)
|
|||
NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
|
||||
|
||||
nsRefPtr<gfxASurface> retsurf;
|
||||
// Use an opaque surface unless we're transparent and *don't* have
|
||||
// a background to source from.
|
||||
gfxASurface::gfxImageFormat format =
|
||||
mIsTransparent ? gfxASurface::ImageFormatARGB32 :
|
||||
gfxASurface::ImageFormatRGB24;
|
||||
(mIsTransparent && !mBackground) ? gfxASurface::ImageFormatARGB32 :
|
||||
gfxASurface::ImageFormatRGB24;
|
||||
|
||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||
// On Maemo 5, we must send the Visibility event to activate the plugin
|
||||
|
@ -2387,10 +2361,12 @@ PluginInstanceChild::CreateOptSurface(void)
|
|||
#ifdef XP_WIN
|
||||
if (mSurfaceType == gfxASurface::SurfaceTypeWin32 ||
|
||||
mSurfaceType == gfxASurface::SurfaceTypeD2D) {
|
||||
bool willHaveTransparentPixels = mIsTransparent && !mBackground;
|
||||
|
||||
SharedDIBSurface* s = new SharedDIBSurface();
|
||||
if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
|
||||
mWindow.width, mWindow.height, mIsTransparent))
|
||||
mWindow.width, mWindow.height,
|
||||
willHaveTransparentPixels))
|
||||
return false;
|
||||
|
||||
mCurrentSurface = s;
|
||||
|
@ -2471,6 +2447,8 @@ PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
#elif defined(XP_WIN)
|
||||
mDoAlphaExtraction = mIsTransparent && !mBackground;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -2529,7 +2507,7 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
|||
mWindow.window = nsnull;
|
||||
mWsInfo.depth = gfxUtils::ImageFormatToDepth(img->Format());
|
||||
mWsInfo.colormap = 0;
|
||||
needWindowUpdate = PR_TRUE;
|
||||
needWindowUpdate = true;
|
||||
}
|
||||
}
|
||||
#endif // MAEMO
|
||||
|
@ -2538,8 +2516,8 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
|||
HDC dc = NULL;
|
||||
|
||||
if (curSurface) {
|
||||
NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(curSurface),
|
||||
"Expected (SharedDIB) image surface.");
|
||||
if (!SharedDIBSurface::IsSharedDIBSurface(curSurface))
|
||||
NS_RUNTIMEABORT("Expected SharedDIBSurface!");
|
||||
|
||||
SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get());
|
||||
dc = dibsurf->GetHDC();
|
||||
|
@ -2595,6 +2573,11 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
|||
}
|
||||
#endif
|
||||
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] UpdateWindow w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
||||
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
||||
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
||||
|
||||
if (mPluginIface->setwindow) {
|
||||
mPluginIface->setwindow(&mData, &mWindow);
|
||||
}
|
||||
|
@ -2604,12 +2587,6 @@ void
|
|||
PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface)
|
||||
{
|
||||
bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
|
||||
if (temporarilyMakeVisible) {
|
||||
mWindow.clipRect.right = mWindow.width;
|
||||
mWindow.clipRect.bottom = mWindow.height;
|
||||
}
|
||||
|
||||
UpdateWindowAttributes();
|
||||
|
||||
#ifdef MOZ_X11
|
||||
|
@ -2698,14 +2675,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
|||
#else
|
||||
NS_RUNTIMEABORT("Surface type not implemented.");
|
||||
#endif
|
||||
|
||||
if (temporarilyMakeVisible) {
|
||||
mWindow.clipRect.right = mWindow.clipRect.bottom = 0;
|
||||
|
||||
if (mPluginIface->setwindow) {
|
||||
mPluginIface->setwindow(&mData, &mWindow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2735,7 +2704,7 @@ PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
|||
}
|
||||
#endif
|
||||
|
||||
if (mIsTransparent) {
|
||||
if (aColor.a > 0.0) {
|
||||
// Clear surface content for transparent rendering
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface);
|
||||
ctx->SetColor(aColor);
|
||||
|
@ -2760,50 +2729,112 @@ void
|
|||
PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface)
|
||||
{
|
||||
// Paint onto black image
|
||||
bool needImageSurface = true;
|
||||
nsRefPtr<gfxImageSurface> blackImage;
|
||||
gfxIntSize clipSize(aRect.width, aRect.height);
|
||||
gfxPoint deviceOffset(-aRect.x, -aRect.y);
|
||||
// Try to re-use existing image surface, and avoid one copy
|
||||
if (aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
|
||||
if (surface->Format() == gfxASurface::ImageFormatARGB32) {
|
||||
needImageSurface = false;
|
||||
blackImage = surface->GetSubimage(GfxFromNsRect(aRect));
|
||||
NS_ABORT_IF_FALSE(aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA,
|
||||
"Refusing to pointlessly recover alpha");
|
||||
|
||||
nsIntRect rect(aRect);
|
||||
// If |aSurface| can be used to paint and can have alpha values
|
||||
// recovered directly to it, do that to save a tmp surface and
|
||||
// copy.
|
||||
bool useSurfaceSubimageForBlack = false;
|
||||
if (gfxASurface::SurfaceTypeImage == aSurface->GetType()) {
|
||||
gfxImageSurface* surfaceAsImage =
|
||||
static_cast<gfxImageSurface*>(aSurface);
|
||||
useSurfaceSubimageForBlack =
|
||||
(surfaceAsImage->Format() == gfxASurface::ImageFormatARGB32);
|
||||
// If we're going to use a subimage, nudge the rect so that we
|
||||
// can use optimal alpha recovery. If we're not using a
|
||||
// subimage, the temporaries should automatically get
|
||||
// fast-path alpha recovery so we don't need to do anything.
|
||||
if (useSurfaceSubimageForBlack) {
|
||||
rect =
|
||||
gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect,
|
||||
surfaceAsImage);
|
||||
}
|
||||
}
|
||||
// otherwise create new helper surface
|
||||
if (needImageSurface) {
|
||||
blackImage = new gfxImageSurface(clipSize, gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxImageSurface> whiteImage;
|
||||
nsRefPtr<gfxImageSurface> blackImage;
|
||||
gfxRect targetRect(rect.x, rect.y, rect.width, rect.height);
|
||||
gfxIntSize targetSize(rect.width, rect.height);
|
||||
gfxPoint deviceOffset = -targetRect.pos;
|
||||
|
||||
// We always use a temporary "white image"
|
||||
whiteImage = new gfxImageSurface(targetSize, gfxASurface::ImageFormatRGB24);
|
||||
|
||||
#ifdef XP_WIN
|
||||
// On windows, we need an HDC and so can't paint directly to
|
||||
// vanilla image surfaces. Bifurcate this painting code so that
|
||||
// we don't accidentally attempt that.
|
||||
if (!SharedDIBSurface::IsSharedDIBSurface(aSurface))
|
||||
NS_RUNTIMEABORT("Expected SharedDIBSurface!");
|
||||
|
||||
// Paint the plugin directly onto the target, with a white
|
||||
// background and copy the result
|
||||
PaintRectToSurface(rect, aSurface, gfxRGBA(1.0, 1.0, 1.0));
|
||||
{
|
||||
gfxRect copyRect(gfxPoint(0, 0), targetRect.size);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(whiteImage);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(aSurface, deviceOffset);
|
||||
ctx->Rectangle(copyRect);
|
||||
ctx->Fill();
|
||||
}
|
||||
|
||||
// Paint to black image
|
||||
blackImage->SetDeviceOffset(deviceOffset);
|
||||
PaintRectToSurface(aRect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
|
||||
// Paint the plugin directly onto the target, with a black
|
||||
// background
|
||||
PaintRectToSurface(rect, aSurface, gfxRGBA(0.0, 0.0, 0.0));
|
||||
|
||||
// Paint onto white image
|
||||
nsRefPtr<gfxImageSurface> whiteImage =
|
||||
new gfxImageSurface(clipSize, gfxASurface::ImageFormatRGB24);
|
||||
// Don't copy the result, just extract a subimage so that we can
|
||||
// recover alpha directly into the target
|
||||
gfxImageSurface *image = static_cast<gfxImageSurface*>(aSurface);
|
||||
blackImage = image->GetSubimage(targetRect);
|
||||
|
||||
#else
|
||||
// Paint onto white background
|
||||
whiteImage->SetDeviceOffset(deviceOffset);
|
||||
PaintRectToSurface(aRect, whiteImage, gfxRGBA(1.0, 1.0, 1.0));
|
||||
PaintRectToSurface(rect, whiteImage, gfxRGBA(1.0, 1.0, 1.0));
|
||||
|
||||
// Extract Alpha from black and white image and store to black Image
|
||||
gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage, nsnull)) {
|
||||
if (useSurfaceSubimageForBlack) {
|
||||
gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
|
||||
blackImage = surface->GetSubimage(targetRect);
|
||||
} else {
|
||||
blackImage = new gfxImageSurface(targetSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
// Paint onto black background
|
||||
blackImage->SetDeviceOffset(deviceOffset);
|
||||
PaintRectToSurface(rect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
|
||||
#endif
|
||||
|
||||
NS_ABORT_IF_FALSE(whiteImage && blackImage, "Didn't paint enough!");
|
||||
|
||||
// Extract alpha from black and white image and store to black
|
||||
// image
|
||||
if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (needImageSurface) {
|
||||
// If we had to use a temporary black surface, copy the pixels
|
||||
// with alpha back to the target
|
||||
if (!useSurfaceSubimageForBlack) {
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(blackImage);
|
||||
ctx->Rectangle(GfxFromNsRect(aRect));
|
||||
ctx->Rectangle(targetRect);
|
||||
ctx->Fill();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::CanPaintOnBackground()
|
||||
{
|
||||
return (mBackground &&
|
||||
mCurrentSurface &&
|
||||
mCurrentSurface->GetSize() == mBackground->GetSize());
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::ShowPluginFrame()
|
||||
{
|
||||
|
@ -2818,11 +2849,20 @@ PluginInstanceChild::ShowPluginFrame()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Make expose rect not bigger than clip rect
|
||||
mAccumulatedInvalidRect.IntersectRect(mAccumulatedInvalidRect,
|
||||
nsIntRect(mWindow.clipRect.left, mWindow.clipRect.top,
|
||||
mWindow.clipRect.right - mWindow.clipRect.left,
|
||||
mWindow.clipRect.bottom - mWindow.clipRect.top));
|
||||
bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
|
||||
if (temporarilyMakeVisible) {
|
||||
mWindow.clipRect.right = mWindow.width;
|
||||
mWindow.clipRect.bottom = mWindow.height;
|
||||
} else if (!IsVisible()) {
|
||||
// If we're not visible, don't bother painting a <0,0,0,0>
|
||||
// rect. If we're eventually made visible, the visibility
|
||||
// change will invalidate our window.
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mWindow.width == (mWindow.clipRect.right - mWindow.clipRect.left) &&
|
||||
mWindow.height == (mWindow.clipRect.bottom - mWindow.clipRect.top),
|
||||
"Clip rect should be same size as window when using layers");
|
||||
|
||||
// Clear accRect here to be able to pass
|
||||
// test_invalidate_during_plugin_paint test
|
||||
|
@ -2830,17 +2870,54 @@ PluginInstanceChild::ShowPluginFrame()
|
|||
mAccumulatedInvalidRect.Empty();
|
||||
|
||||
if (!ReadbackDifferenceRect(rect)) {
|
||||
// Just repaint whole plugin, because we cannot read back from Shmem which is owned by another process
|
||||
// We couldn't read back the pixels that differ between the
|
||||
// current surface and last, so we have to invalidate the
|
||||
// entire window.
|
||||
rect.SetRect(0, 0, mWindow.width, mWindow.height);
|
||||
}
|
||||
|
||||
if (mDoAlphaExtraction) {
|
||||
bool haveTransparentPixels =
|
||||
gfxASurface::CONTENT_COLOR_ALPHA == mCurrentSurface->GetContentType();
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] Painting%s <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, haveTransparentPixels ? " with alpha" : "",
|
||||
rect.x, rect.y, rect.width, rect.height));
|
||||
|
||||
if (CanPaintOnBackground()) {
|
||||
PLUGIN_LOG_DEBUG((" (on background)"));
|
||||
// Source the background pixels ...
|
||||
{
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
||||
ctx->SetSource(mBackground);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->Rectangle(gfxRect(rect.x, rect.y, rect.width, rect.height));
|
||||
ctx->Fill();
|
||||
}
|
||||
// ... and hand off to the plugin
|
||||
// BEWARE: mBackground may die during this call
|
||||
PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0));
|
||||
} else if (mDoAlphaExtraction) {
|
||||
PLUGIN_LOG_DEBUG((" (with alpha recovery)"));
|
||||
PaintRectWithAlphaExtraction(rect, mCurrentSurface);
|
||||
} else {
|
||||
PLUGIN_LOG_DEBUG((" (onto opaque surface)"));
|
||||
PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0));
|
||||
}
|
||||
mHasPainted = true;
|
||||
|
||||
if (temporarilyMakeVisible) {
|
||||
mWindow.clipRect.right = mWindow.clipRect.bottom = 0;
|
||||
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] Undoing temporary clipping w=<x=%d,y=%d, w=%d,h=%d>, clip=<l=%d,t=%d,r=%d,b=%d>",
|
||||
this, mWindow.x, mWindow.y, mWindow.width, mWindow.height,
|
||||
mWindow.clipRect.left, mWindow.clipRect.top, mWindow.clipRect.right, mWindow.clipRect.bottom));
|
||||
|
||||
if (mPluginIface->setwindow) {
|
||||
mPluginIface->setwindow(&mData, &mWindow);
|
||||
}
|
||||
}
|
||||
|
||||
NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
|
||||
(uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
|
||||
SurfaceDescriptor currSurf;
|
||||
|
@ -2864,7 +2941,7 @@ PluginInstanceChild::ShowPluginFrame()
|
|||
mCurrentSurfaceActor =
|
||||
SendPPluginSurfaceConstructor(handle,
|
||||
mCurrentSurface->GetSize(),
|
||||
mIsTransparent);
|
||||
haveTransparentPixels);
|
||||
}
|
||||
currSurf = mCurrentSurfaceActor;
|
||||
s->Flush();
|
||||
|
@ -2908,9 +2985,17 @@ PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
|
|||
return false;
|
||||
#endif
|
||||
|
||||
if (mCurrentSurface->GetContentType() != mBackSurface->GetContentType())
|
||||
return false;
|
||||
|
||||
if (mSurfaceDifferenceRect.IsEmpty())
|
||||
return true;
|
||||
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceChild][%p] Reading back part of <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, mSurfaceDifferenceRect.x, mSurfaceDifferenceRect.y,
|
||||
mSurfaceDifferenceRect.width, mSurfaceDifferenceRect.height));
|
||||
|
||||
// Read back previous content
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
|
@ -2987,6 +3072,110 @@ PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
|
|||
SendNPN_InvalidateRect(*aInvalidRect);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground,
|
||||
const nsIntRect& aRect)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mIsTransparent, "Only transparent plugins use backgrounds");
|
||||
|
||||
if (SurfaceDescriptor::Tnull_t == aBackground.type()) {
|
||||
// null_t here means "use existing background". We're
|
||||
// notified when we lose our background through
|
||||
// PPluginBackgroundDestroyer. We might have already dropped
|
||||
// our background from an ill-timed SetWindow, though.
|
||||
if (!mBackground) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
NS_ABORT_IF_FALSE(!mBackground, "Shouldn't have background here");
|
||||
|
||||
// Now that we have a new background, our choice of surface
|
||||
// format and/or size should have changed.
|
||||
ClearCurrentSurface();
|
||||
|
||||
// XXX refactor me
|
||||
switch (aBackground.type()) {
|
||||
#ifdef MOZ_X11
|
||||
case SurfaceDescriptor::TSurfaceDescriptorX11: {
|
||||
SurfaceDescriptorX11 xdesc = aBackground.get_SurfaceDescriptorX11();
|
||||
XRenderPictFormat pf;
|
||||
pf.id = xdesc.xrenderPictID();
|
||||
XRenderPictFormat *incFormat =
|
||||
XRenderFindFormat(DefaultXDisplay(), PictFormatID, &pf, 0);
|
||||
mBackground =
|
||||
new gfxXlibSurface(DefaultScreenOfDisplay(DefaultXDisplay()),
|
||||
xdesc.XID(), incFormat, xdesc.size());
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case SurfaceDescriptor::TShmem: {
|
||||
mBackground = gfxSharedImageSurface::Open(aBackground.get_Shmem());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("Unexpected background surface descriptor");
|
||||
}
|
||||
}
|
||||
|
||||
if (!mBackground) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// XXX refactor me
|
||||
mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect);
|
||||
|
||||
// The browser is limping along with a stale copy of our pixels.
|
||||
// Try to repaint ASAP.
|
||||
if (!ShowPluginFrame()) {
|
||||
NS_WARNING("Couldn't immediately repaint plugin instance");
|
||||
AsyncShowPluginFrame();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PPluginBackgroundDestroyerChild*
|
||||
PluginInstanceChild::AllocPPluginBackgroundDestroyer()
|
||||
{
|
||||
return new PluginBackgroundDestroyerChild();
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvPPluginBackgroundDestroyerConstructor(
|
||||
PPluginBackgroundDestroyerChild* aActor)
|
||||
{
|
||||
// Our background changed, so we have to invalidate the area
|
||||
// painted with the old background. If the background was
|
||||
// destroyed because we have a new background, then we expect to
|
||||
// be notified of that "soon", before processing the asynchronous
|
||||
// invalidation here. If we're *not* getting a new background,
|
||||
// our current front surface is stale and we want to repaint
|
||||
// "soon" so that we can hand the browser back a surface with
|
||||
// alpha values. (We should be notified of that invalidation soon
|
||||
// too, but we don't assume that here.)
|
||||
if (mBackground) {
|
||||
gfxIntSize bgsize = mBackground->GetSize();
|
||||
mAccumulatedInvalidRect.UnionRect(
|
||||
nsIntRect(0, 0, bgsize.width, bgsize.height), mAccumulatedInvalidRect);
|
||||
AsyncShowPluginFrame();
|
||||
|
||||
// NB: we don't have to XSync here because only ShowPluginFrame()
|
||||
// uses mBackground, and it always XSyncs after finishing.
|
||||
mBackground = nsnull;
|
||||
ClearCurrentSurface();
|
||||
}
|
||||
|
||||
return PPluginBackgroundDestroyerChild::Send__delete__(aActor);
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::DeallocPPluginBackgroundDestroyer(
|
||||
PPluginBackgroundDestroyerChild* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat,
|
||||
TimerFunc func)
|
||||
|
@ -3076,7 +3265,8 @@ PluginInstanceChild::SwapSurfaces()
|
|||
// Outdated back surface... not usable anymore due to changed plugin size.
|
||||
// Dropping obsolete surface
|
||||
if (mCurrentSurface && mBackSurface &&
|
||||
mCurrentSurface->GetSize() != mBackSurface->GetSize()) {
|
||||
(mCurrentSurface->GetSize() != mBackSurface->GetSize() ||
|
||||
mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) {
|
||||
mCurrentSurface = nsnull;
|
||||
#ifdef XP_WIN
|
||||
if (mCurrentSurfaceActor) {
|
||||
|
|
|
@ -236,6 +236,22 @@ private:
|
|||
InternalGetNPObjectForValue(NPNVariable aValue,
|
||||
NPObject** aObject);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool RecvUpdateBackground(const SurfaceDescriptor& aBackground,
|
||||
const nsIntRect& aRect);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual PPluginBackgroundDestroyerChild*
|
||||
AllocPPluginBackgroundDestroyer();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool
|
||||
RecvPPluginBackgroundDestroyerConstructor(PPluginBackgroundDestroyerChild* aActor);
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool
|
||||
DeallocPPluginBackgroundDestroyer(PPluginBackgroundDestroyerChild* aActor);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
static bool RegisterWindowClass();
|
||||
bool CreatePluginWindow();
|
||||
|
@ -290,7 +306,6 @@ private:
|
|||
int nIndex,
|
||||
LONG newLong);
|
||||
#endif
|
||||
void HookSystemParametersInfo();
|
||||
|
||||
class FlashThrottleAsyncMsg : public ChildAsyncCall
|
||||
{
|
||||
|
@ -407,6 +422,8 @@ private:
|
|||
const NPCocoaEvent *mCurrentEvent;
|
||||
#endif
|
||||
|
||||
bool CanPaintOnBackground();
|
||||
|
||||
bool IsVisible() {
|
||||
return mWindow.clipRect.top != 0 ||
|
||||
mWindow.clipRect.left != 0 ||
|
||||
|
@ -488,6 +505,13 @@ private:
|
|||
// surface which is on ParentProcess side
|
||||
nsRefPtr<gfxASurface> mBackSurface;
|
||||
|
||||
// (Not to be confused with mBackSurface). This is a recent copy
|
||||
// of the opaque pixels under our object frame, if
|
||||
// |mIsTransparent|. We ask the plugin render directly onto a
|
||||
// copy of the background pixels if available, and fall back on
|
||||
// alpha recovery otherwise.
|
||||
nsRefPtr<gfxASurface> mBackground;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// These actors mirror mCurrentSurface/mBackSurface
|
||||
PPluginSurfaceChild* mCurrentSurfaceActor;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "PluginInstanceParent.h"
|
||||
|
||||
#include "BrowserStreamParent.h"
|
||||
#include "PluginBackgroundDestroyer.h"
|
||||
#include "PluginModuleParent.h"
|
||||
#include "PluginStreamParent.h"
|
||||
#include "StreamNotifyParent.h"
|
||||
|
@ -108,6 +109,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
|||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mIOSurface(nsnull)
|
||||
#endif
|
||||
, mNewBackground(false)
|
||||
{
|
||||
InitQuirksModes(aMimeType);
|
||||
}
|
||||
|
@ -498,6 +500,12 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||
const SurfaceDescriptor& newSurface,
|
||||
SurfaceDescriptor* prevSurface)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceParent][%p] RecvShow for <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, updatedRect.left, updatedRect.top,
|
||||
updatedRect.right - updatedRect.left,
|
||||
updatedRect.bottom - updatedRect.top));
|
||||
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
if (newSurface.type() == SurfaceDescriptor::TShmem) {
|
||||
if (!newSurface.get_Shmem().IsReadable()) {
|
||||
|
@ -529,6 +537,11 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||
#ifdef MOZ_X11
|
||||
if (mFrontSurface &&
|
||||
mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib)
|
||||
// This is the "old front buffer" we're about to hand back to
|
||||
// the plugin. We might still have drawing operations
|
||||
// referencing it, so we XSync here to let them finish before
|
||||
// the plugin starts scribbling on it again, or worse,
|
||||
// destroys it.
|
||||
XSync(DefaultXDisplay(), False);
|
||||
#endif
|
||||
|
||||
|
@ -540,6 +553,9 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||
mFrontSurface = surface;
|
||||
RecvNPN_InvalidateRect(updatedRect);
|
||||
|
||||
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
|
||||
mFrontSurface.get()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -572,6 +588,175 @@ PluginInstanceParent::GetSurface(gfxASurface** aSurface)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::SetBackgroundUnknown()
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this));
|
||||
|
||||
NS_ABORT_IF_FALSE(!mNewBackground, "Forgot EndUpdateBackground?");
|
||||
|
||||
if (mBackground) {
|
||||
DestroyBackground();
|
||||
NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
|
||||
gfxContext** aCtx)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, aRect.x, aRect.y, aRect.width, aRect.height));
|
||||
|
||||
NS_ABORT_IF_FALSE(!mNewBackground, "Forgot EndUpdateBackground?");
|
||||
|
||||
if (!mBackground) {
|
||||
// XXX if we failed to create a background surface on one
|
||||
// update, there's no guarantee that later updates will be for
|
||||
// the entire background area until successful. We might want
|
||||
// to fix that eventually.
|
||||
NS_ABORT_IF_FALSE(aRect.TopLeft() == nsIntPoint(0, 0),
|
||||
"Expecting rect for whole frame");
|
||||
if (!CreateBackground(aRect.Size())) {
|
||||
*aCtx = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The new background forwarded over in EndUpdate below.
|
||||
mNewBackground = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
gfxIntSize sz = mBackground->GetSize();
|
||||
NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
|
||||
"Update outside of background area");
|
||||
#endif
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mBackground);
|
||||
*aCtx = ctx.forget().get();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::EndUpdateBackground(gfxContext* aCtx,
|
||||
const nsIntRect& aRect)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(
|
||||
("[InstanceParent][%p] EndUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
||||
this, aRect.x, aRect.y, aRect.width, aRect.height));
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Have to XSync here to avoid the plugin trying to draw with this
|
||||
// surface racing with its creation in the X server. We also want
|
||||
// to avoid the plugin drawing onto stale pixels, then handing us
|
||||
// back a front surface from those pixels that we might
|
||||
// recomposite for "a while" until the next update. This XSync
|
||||
// still doesn't guarantee that the plugin draws onto a consistent
|
||||
// view of its background, but it does mean that the plugin is
|
||||
// drawing onto pixels no older than those in the latest
|
||||
// EndUpdateBackground().
|
||||
XSync(DefaultXDisplay(), False);
|
||||
#endif
|
||||
|
||||
unused << SendUpdateBackground(
|
||||
mNewBackground ? BackgroundDescriptor() : SurfaceDescriptor(null_t()),
|
||||
aRect);
|
||||
mNewBackground = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::CreateBackground(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(!mBackground, "Already have a background");
|
||||
|
||||
// XXX refactor me
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay());
|
||||
Visual* visual = DefaultVisualOfScreen(screen);
|
||||
mBackground = gfxXlibSurface::Create(screen, visual,
|
||||
gfxIntSize(aSize.width, aSize.height));
|
||||
return !!mBackground;
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
// We have chosen to create an unsafe surface in which the plugin
|
||||
// can read from the region while we're writing to it.
|
||||
mBackground =
|
||||
gfxSharedImageSurface::CreateUnsafe(
|
||||
this,
|
||||
gfxIntSize(aSize.width, aSize.height),
|
||||
gfxASurface::ImageFormatRGB24);
|
||||
return !!mBackground;
|
||||
#else
|
||||
return nsnull;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceParent::DestroyBackground()
|
||||
{
|
||||
if (!mBackground) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Relinquish ownership of |mBackground| to its destroyer
|
||||
PPluginBackgroundDestroyerParent* pbd =
|
||||
new PluginBackgroundDestroyerParent(mBackground);
|
||||
mBackground = nsnull;
|
||||
|
||||
// If this fails, there's no problem: |bd| will be destroyed along
|
||||
// with the old background surface.
|
||||
unused << SendPPluginBackgroundDestroyerConstructor(pbd);
|
||||
}
|
||||
|
||||
SurfaceDescriptor
|
||||
PluginInstanceParent::BackgroundDescriptor()
|
||||
{
|
||||
NS_ABORT_IF_FALSE(mBackground, "Need a background here");
|
||||
|
||||
// XXX refactor me
|
||||
|
||||
#ifdef MOZ_X11
|
||||
gfxXlibSurface* xsurf = static_cast<gfxXlibSurface*>(mBackground.get());
|
||||
return SurfaceDescriptorX11(xsurf->XDrawable(), xsurf->XRenderFormat()->id,
|
||||
xsurf->GetSize());
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
NS_ABORT_IF_FALSE(gfxSharedImageSurface::IsSharedImage(mBackground),
|
||||
"Expected shared image surface");
|
||||
gfxSharedImageSurface* shmem =
|
||||
static_cast<gfxSharedImageSurface*>(mBackground.get());
|
||||
return shmem->GetShmem();
|
||||
#endif
|
||||
|
||||
// If this is ever used, which it shouldn't be, it will trigger a
|
||||
// hard assertion in IPDL-generated code.
|
||||
return SurfaceDescriptor();
|
||||
}
|
||||
|
||||
PPluginBackgroundDestroyerParent*
|
||||
PluginInstanceParent::AllocPPluginBackgroundDestroyer()
|
||||
{
|
||||
NS_RUNTIMEABORT("'Power-user' ctor is used exclusively");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceParent::DeallocPPluginBackgroundDestroyer(
|
||||
PPluginBackgroundDestroyerParent* aActor)
|
||||
{
|
||||
delete aActor;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NPError
|
||||
PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
||||
{
|
||||
|
|
|
@ -277,8 +277,27 @@ public:
|
|||
|
||||
nsresult AsyncSetWindow(NPWindow* window);
|
||||
nsresult GetSurface(gfxASurface** aSurface);
|
||||
nsresult SetBackgroundUnknown();
|
||||
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
||||
gfxContext** aCtx);
|
||||
nsresult EndUpdateBackground(gfxContext* aCtx,
|
||||
const nsIntRect& aRect);
|
||||
|
||||
private:
|
||||
// Create an appropriate platform surface for a background of size
|
||||
// |aSize|. Return true if successful.
|
||||
bool CreateBackground(const nsIntSize& aSize);
|
||||
void DestroyBackground();
|
||||
SurfaceDescriptor BackgroundDescriptor() /*const*/;
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual PPluginBackgroundDestroyerParent*
|
||||
AllocPPluginBackgroundDestroyer();
|
||||
|
||||
NS_OVERRIDE
|
||||
virtual bool
|
||||
DeallocPPluginBackgroundDestroyer(PPluginBackgroundDestroyerParent* aActor);
|
||||
|
||||
// Quirks mode support for various plugin mime types
|
||||
enum PluginQuirks {
|
||||
// OSX: Don't use the refresh timer for plug-ins
|
||||
|
@ -335,6 +354,19 @@ private:
|
|||
|
||||
// ObjectFrame layer wrapper
|
||||
nsRefPtr<gfxASurface> mFrontSurface;
|
||||
// For windowless+transparent instances, this surface contains a
|
||||
// "pretty recent" copy of the pixels under its <object> frame.
|
||||
// On the plugin side, we use this surface to avoid doing alpha
|
||||
// recovery when possible. This surface is created and owned by
|
||||
// the browser, but a "read-only" reference is sent to the plugin.
|
||||
//
|
||||
// We have explicitly chosen not to provide any guarantees about
|
||||
// the consistency of the pixels in |mBackground|. A plugin may
|
||||
// be able to observe partial updates to the background.
|
||||
nsRefPtr<gfxASurface> mBackground;
|
||||
// True when we just created a background and it needs to be
|
||||
// shared to the plugin subprocess.
|
||||
bool mNewBackground;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -46,9 +46,11 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsPluginError.h"
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
class nsCString;
|
||||
struct nsIntRect;
|
||||
class nsNPAPIPlugin;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -89,6 +91,16 @@ public:
|
|||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0;
|
||||
virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface) = 0;
|
||||
virtual bool UseAsyncPainting() = 0;
|
||||
/**
|
||||
* The next three methods are the third leg in the trip to
|
||||
* PluginInstanceParent. They approximately follow the ReadbackSink
|
||||
* API.
|
||||
*/
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
|
||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
||||
const nsIntRect&, gfxContext**) = 0;
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
gfxContext*, const nsIntRect&) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -137,14 +137,9 @@ PluginModuleChild::~PluginModuleChild()
|
|||
if (mLibrary) {
|
||||
PR_UnloadLibrary(mLibrary);
|
||||
}
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
nsQAppInstance::Release();
|
||||
if (sGtkLib) {
|
||||
PR_UnloadLibrary(sGtkLib);
|
||||
sGtkLib = nsnull;
|
||||
s_gtk_init = nsnull;
|
||||
}
|
||||
#endif
|
||||
|
||||
DeinitGraphics();
|
||||
|
||||
gInstance = nsnull;
|
||||
}
|
||||
|
||||
|
@ -559,6 +554,26 @@ PluginModuleChild::InitGraphics()
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
PluginModuleChild::DeinitGraphics()
|
||||
{
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
nsQAppInstance::Release();
|
||||
if (sGtkLib) {
|
||||
PR_UnloadLibrary(sGtkLib);
|
||||
sGtkLib = nsnull;
|
||||
s_gtk_init = nsnull;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11) && defined(NS_FREE_PERMANENT_DATA)
|
||||
// We free some data off of XDisplay close hooks, ensure they're
|
||||
// run. Closing the display is pretty scary, so we only do it to
|
||||
// silence leak checkers.
|
||||
XCloseDisplay(DefaultXDisplay());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PluginModuleChild::AnswerNP_Shutdown(NPError *rv)
|
||||
{
|
||||
|
@ -1861,7 +1876,6 @@ PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
|
|||
mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
|
||||
mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
|
||||
mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
|
||||
mQuirks |= QUIRK_FLASH_MASK_CLEARTYPE_SETTINGS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -246,9 +246,6 @@ public:
|
|||
// results so mouse input works when flash is displaying it's settings
|
||||
// window.
|
||||
QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5,
|
||||
// Win: Flash trashes the alpha channel in our buffers when cleartype
|
||||
// is enabled. Mask this setting so they don't know it's enabled.
|
||||
QUIRK_FLASH_MASK_CLEARTYPE_SETTINGS = 1 << 6,
|
||||
};
|
||||
|
||||
int GetQuirks() { return mQuirks; }
|
||||
|
@ -261,6 +258,7 @@ public:
|
|||
private:
|
||||
void InitQuirksModes(const nsCString& aMimeType);
|
||||
bool InitGraphics();
|
||||
void DeinitGraphics();
|
||||
#if defined(MOZ_WIDGET_GTK2)
|
||||
static gboolean DetectNestedEventLoop(gpointer data);
|
||||
static gboolean ProcessBrowserEvents(gpointer data);
|
||||
|
|
|
@ -682,6 +682,40 @@ PluginModuleParent::GetSurface(NPP instance, gfxASurface** aSurface)
|
|||
return i->GetSurface(aSurface);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::SetBackgroundUnknown(NPP instance)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
if (!i)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return i->SetBackgroundUnknown();
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::BeginUpdateBackground(NPP instance,
|
||||
const nsIntRect& aRect,
|
||||
gfxContext** aCtx)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
if (!i)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return i->BeginUpdateBackground(aRect, aCtx);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginModuleParent::EndUpdateBackground(NPP instance,
|
||||
gfxContext* aCtx,
|
||||
const nsIntRect& aRect)
|
||||
{
|
||||
PluginInstanceParent* i = InstCast(instance);
|
||||
if (!i)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return i->EndUpdateBackground(aCtx, aRect);
|
||||
}
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
nsresult
|
||||
PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
|
||||
|
|
|
@ -232,6 +232,16 @@ private:
|
|||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
|
||||
virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface);
|
||||
NS_OVERRIDE virtual bool UseAsyncPainting() { return true; }
|
||||
NS_OVERRIDE
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance);
|
||||
NS_OVERRIDE
|
||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
||||
const nsIntRect& aRect,
|
||||
gfxContext** aCtx);
|
||||
NS_OVERRIDE
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
gfxContext* aCtx,
|
||||
const nsIntRect& aRect);
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
IPDLSRCS = \
|
||||
PPluginBackgroundDestroyer.ipdl \
|
||||
PPluginModule.ipdl \
|
||||
PPluginIdentifier.ipdl \
|
||||
PPluginInstance.ipdl \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Guillermo Robla Vicario <groblavicario@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -52,6 +53,7 @@
|
|||
#include "nsIDNSRecord.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICryptoHash.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
@ -190,6 +192,8 @@ nsAuthSSPI::nsAuthSSPI(pType package)
|
|||
: mServiceFlags(REQ_DEFAULT)
|
||||
, mMaxTokenLen(0)
|
||||
, mPackage(package)
|
||||
, mCertDERData(nsnull)
|
||||
, mCertDERLength(0)
|
||||
{
|
||||
memset(&mCred, 0, sizeof(mCred));
|
||||
memset(&mCtxt, 0, sizeof(mCtxt));
|
||||
|
@ -212,6 +216,14 @@ nsAuthSSPI::~nsAuthSSPI()
|
|||
void
|
||||
nsAuthSSPI::Reset()
|
||||
{
|
||||
mIsFirst = PR_TRUE;
|
||||
|
||||
if (mCertDERData){
|
||||
nsMemory::Free(mCertDERData);
|
||||
mCertDERData = nsnull;
|
||||
mCertDERLength = 0;
|
||||
}
|
||||
|
||||
if (mCtxt.dwLower || mCtxt.dwUpper) {
|
||||
(sspi->DeleteSecurityContext)(&mCtxt);
|
||||
memset(&mCtxt, 0, sizeof(mCtxt));
|
||||
|
@ -229,6 +241,10 @@ nsAuthSSPI::Init(const char *serviceName,
|
|||
{
|
||||
LOG((" nsAuthSSPI::Init\n"));
|
||||
|
||||
mIsFirst = PR_TRUE;
|
||||
mCertDERLength = 0;
|
||||
mCertDERData = nsnull;
|
||||
|
||||
// The caller must supply a service name to be used. (For why we now require
|
||||
// a service name for NTLM, see bug 487872.)
|
||||
NS_ENSURE_TRUE(serviceName && *serviceName, NS_ERROR_INVALID_ARG);
|
||||
|
@ -314,19 +330,32 @@ nsAuthSSPI::Init(const char *serviceName,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// The arguments inToken and inTokenLen are used to pass in the server
|
||||
// certificate (when available) in the first call of the function. The
|
||||
// second time these arguments hold an input token.
|
||||
NS_IMETHODIMP
|
||||
nsAuthSSPI::GetNextToken(const void *inToken,
|
||||
PRUint32 inTokenLen,
|
||||
void **outToken,
|
||||
PRUint32 *outTokenLen)
|
||||
{
|
||||
// String for end-point bindings.
|
||||
const char end_point[] = "tls-server-end-point:";
|
||||
const int end_point_length = sizeof(end_point) - 1;
|
||||
const int hash_size = 32; // Size of a SHA256 hash.
|
||||
const int cbt_size = hash_size + end_point_length;
|
||||
|
||||
SECURITY_STATUS rc;
|
||||
TimeStamp ignored;
|
||||
|
||||
DWORD ctxAttr, ctxReq = 0;
|
||||
CtxtHandle *ctxIn;
|
||||
SecBufferDesc ibd, obd;
|
||||
SecBuffer ib, ob;
|
||||
// Optional second input buffer for the CBT (Channel Binding Token)
|
||||
SecBuffer ib[2], ob;
|
||||
// Pointer to the block of memory that stores the CBT
|
||||
char* sspi_cbt = nsnull;
|
||||
SEC_CHANNEL_BINDINGS pendpoint_binding;
|
||||
|
||||
LOG(("entering nsAuthSSPI::GetNextToken()\n"));
|
||||
|
||||
|
@ -341,26 +370,123 @@ nsAuthSSPI::GetNextToken(const void *inToken,
|
|||
ctxReq |= ISC_REQ_MUTUAL_AUTH;
|
||||
|
||||
if (inToken) {
|
||||
ib.BufferType = SECBUFFER_TOKEN;
|
||||
ib.cbBuffer = inTokenLen;
|
||||
ib.pvBuffer = (void *) inToken;
|
||||
ibd.ulVersion = SECBUFFER_VERSION;
|
||||
ibd.cBuffers = 1;
|
||||
ibd.pBuffers = &ib;
|
||||
ctxIn = &mCtxt;
|
||||
}
|
||||
else {
|
||||
// If there is no input token, then we are starting a new
|
||||
// authentication sequence. If we have already initialized our
|
||||
// security context, then we're in trouble because it means that the
|
||||
// first sequence failed. We need to bail or else we might end up in
|
||||
// an infinite loop.
|
||||
if (mCtxt.dwLower || mCtxt.dwUpper) {
|
||||
if (mIsFirst) {
|
||||
// First time if it comes with a token,
|
||||
// the token represents the server certificate.
|
||||
mIsFirst = PR_FALSE;
|
||||
mCertDERLength = inTokenLen;
|
||||
mCertDERData = nsMemory::Alloc(inTokenLen);
|
||||
if (!mCertDERData)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
memcpy(mCertDERData, inToken, inTokenLen);
|
||||
|
||||
// We are starting a new authentication sequence.
|
||||
// If we have already initialized our
|
||||
// security context, then we're in trouble because it means that the
|
||||
// first sequence failed. We need to bail or else we might end up in
|
||||
// an infinite loop.
|
||||
if (mCtxt.dwLower || mCtxt.dwUpper) {
|
||||
LOG(("Cannot restart authentication sequence!"));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
ctxIn = nsnull;
|
||||
// The certificate needs to be erased before being passed
|
||||
// to InitializeSecurityContextW().
|
||||
inToken = nsnull;
|
||||
inTokenLen = 0;
|
||||
} else {
|
||||
ibd.ulVersion = SECBUFFER_VERSION;
|
||||
ibd.cBuffers = 0;
|
||||
ibd.pBuffers = ib;
|
||||
|
||||
// If we have stored a certificate, the Channel Binding Token
|
||||
// needs to be generated and sent in the first input buffer.
|
||||
if (mCertDERLength > 0) {
|
||||
// First we create a proper Endpoint Binding structure.
|
||||
pendpoint_binding.dwInitiatorAddrType = 0;
|
||||
pendpoint_binding.cbInitiatorLength = 0;
|
||||
pendpoint_binding.dwInitiatorOffset = 0;
|
||||
pendpoint_binding.dwAcceptorAddrType = 0;
|
||||
pendpoint_binding.cbAcceptorLength = 0;
|
||||
pendpoint_binding.dwAcceptorOffset = 0;
|
||||
pendpoint_binding.cbApplicationDataLength = cbt_size;
|
||||
pendpoint_binding.dwApplicationDataOffset =
|
||||
sizeof(SEC_CHANNEL_BINDINGS);
|
||||
|
||||
// Then add it to the array of sec buffers accordingly.
|
||||
ib[ibd.cBuffers].BufferType = SECBUFFER_CHANNEL_BINDINGS;
|
||||
ib[ibd.cBuffers].cbBuffer =
|
||||
pendpoint_binding.cbApplicationDataLength
|
||||
+ pendpoint_binding.dwApplicationDataOffset;
|
||||
|
||||
sspi_cbt = (char *) nsMemory::Alloc(ib[ibd.cBuffers].cbBuffer);
|
||||
if (!sspi_cbt){
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Helper to write in the memory block that stores the CBT
|
||||
char* sspi_cbt_ptr = sspi_cbt;
|
||||
|
||||
ib[ibd.cBuffers].pvBuffer = sspi_cbt;
|
||||
ibd.cBuffers++;
|
||||
|
||||
memcpy(sspi_cbt_ptr, &pendpoint_binding,
|
||||
pendpoint_binding.dwApplicationDataOffset);
|
||||
sspi_cbt_ptr += pendpoint_binding.dwApplicationDataOffset;
|
||||
|
||||
memcpy(sspi_cbt_ptr, end_point, end_point_length);
|
||||
sspi_cbt_ptr += end_point_length;
|
||||
|
||||
// Start hashing. We are always doing SHA256, but depending
|
||||
// on the certificate, a different alogirthm might be needed.
|
||||
nsCAutoString hashString;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICryptoHash> crypto;
|
||||
crypto = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = crypto->Init(nsICryptoHash::SHA256);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = crypto->Update((unsigned char*)mCertDERData, mCertDERLength);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = crypto->Finish(PR_FALSE, hashString);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsMemory::Free(mCertDERData);
|
||||
mCertDERData = nsnull;
|
||||
mCertDERLength = 0;
|
||||
nsMemory::Free(sspi_cbt);
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Once the hash has been computed, we store it in memory right
|
||||
// after the Endpoint structure and the "tls-server-end-point:"
|
||||
// char array.
|
||||
memcpy(sspi_cbt_ptr, hashString.get(), hash_size);
|
||||
|
||||
// Free memory used to store the server certificate
|
||||
nsMemory::Free(mCertDERData);
|
||||
mCertDERData = nsnull;
|
||||
mCertDERLength = 0;
|
||||
} // End of CBT computation.
|
||||
|
||||
// We always need this SECBUFFER.
|
||||
ib[ibd.cBuffers].BufferType = SECBUFFER_TOKEN;
|
||||
ib[ibd.cBuffers].cbBuffer = inTokenLen;
|
||||
ib[ibd.cBuffers].pvBuffer = (void *) inToken;
|
||||
ibd.cBuffers++;
|
||||
ctxIn = &mCtxt;
|
||||
}
|
||||
} else { // First time and without a token (no server certificate)
|
||||
// We are starting a new authentication sequence. If we have already
|
||||
// initialized our security context, then we're in trouble because it
|
||||
// means that the first sequence failed. We need to bail or else we
|
||||
// might end up in an infinite loop.
|
||||
if (mCtxt.dwLower || mCtxt.dwUpper || mCertDERData || mCertDERLength) {
|
||||
LOG(("Cannot restart authentication sequence!"));
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
ctxIn = NULL;
|
||||
mIsFirst = PR_FALSE;
|
||||
}
|
||||
|
||||
obd.ulVersion = SECBUFFER_VERSION;
|
||||
|
@ -369,8 +495,11 @@ nsAuthSSPI::GetNextToken(const void *inToken,
|
|||
ob.BufferType = SECBUFFER_TOKEN;
|
||||
ob.cbBuffer = mMaxTokenLen;
|
||||
ob.pvBuffer = nsMemory::Alloc(ob.cbBuffer);
|
||||
if (!ob.pvBuffer)
|
||||
if (!ob.pvBuffer){
|
||||
if (sspi_cbt)
|
||||
nsMemory::Free(sspi_cbt);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
memset(ob.pvBuffer, 0, ob.cbBuffer);
|
||||
|
||||
NS_ConvertUTF8toUTF16 wSN(mServiceName);
|
||||
|
@ -396,7 +525,9 @@ nsAuthSSPI::GetNextToken(const void *inToken,
|
|||
else
|
||||
LOG(("InitializeSecurityContext: continue.\n"));
|
||||
#endif
|
||||
|
||||
if (sspi_cbt)
|
||||
nsMemory::Free(sspi_cbt);
|
||||
|
||||
if (!ob.cbBuffer) {
|
||||
nsMemory::Free(ob.pvBuffer);
|
||||
ob.pvBuffer = NULL;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
* Guillermo Robla Vicario <groblavicario@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -81,6 +82,9 @@ private:
|
|||
nsString mDomain;
|
||||
nsString mUsername;
|
||||
nsString mPassword;
|
||||
PRBool mIsFirst;
|
||||
void* mCertDERData;
|
||||
PRUint32 mCertDERLength;
|
||||
};
|
||||
|
||||
#endif /* nsAuthSSPI_h__ */
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "SharedDIBWin.h"
|
||||
#include "gfxAlphaRecovery.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
|
@ -44,6 +45,9 @@ namespace mozilla {
|
|||
namespace gfx {
|
||||
|
||||
static const PRUint32 kBytesPerPixel = 4;
|
||||
static const PRUint32 kByteAlign = 1 << gfxAlphaRecovery::GoodAlignmentLog2();
|
||||
static const PRUint32 kHeaderBytes =
|
||||
(sizeof(BITMAPV4HEADER) + kByteAlign - 1) & ~(kByteAlign - 1);
|
||||
|
||||
SharedDIBWin::SharedDIBWin() :
|
||||
mSharedHdc(nsnull)
|
||||
|
@ -140,7 +144,7 @@ SharedDIBWin::SetupBitmapHeader(PRUint32 aWidth, PRUint32 aHeight,
|
|||
if (aTransparent)
|
||||
aHeader->bV4AlphaMask = 0xFF000000;
|
||||
|
||||
return (sizeof(BITMAPV4HEADER) + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel));
|
||||
return (kHeaderBytes + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel));
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -156,7 +160,7 @@ SharedDIBWin::SetupSurface(HDC aHdc, BITMAPV4HEADER *aHdr)
|
|||
DIB_RGB_COLORS,
|
||||
&mBitmapBits,
|
||||
mShMem->handle(),
|
||||
(unsigned long)sizeof(BITMAPV4HEADER));
|
||||
kHeaderBytes);
|
||||
if (!mSharedBmp)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "ImageLayers.h"
|
||||
#include "Layers.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
using namespace mozilla::layers;
|
||||
|
||||
|
@ -65,6 +66,15 @@ namespace {
|
|||
|
||||
// XXX pretty general utilities, could centralize
|
||||
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const void* p,
|
||||
const char* pfx="", const char* sfx="")
|
||||
{
|
||||
s += pfx;
|
||||
s += nsPrintfCString(64, "%p", p);
|
||||
return s += sfx;
|
||||
}
|
||||
|
||||
nsACString&
|
||||
AppendToString(nsACString& s, const gfxPattern::GraphicsFilter& f,
|
||||
const char* pfx="", const char* sfx="")
|
||||
|
@ -391,6 +401,30 @@ ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix& aTransf
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayer::DidRemoveChild(Layer* aLayer)
|
||||
{
|
||||
ThebesLayer* tl = aLayer->AsThebesLayer();
|
||||
if (tl && tl->UsedForReadback()) {
|
||||
for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
|
||||
if (l->GetType() == TYPE_READBACK) {
|
||||
static_cast<ReadbackLayer*>(l)->NotifyThebesLayerRemoved(tl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aLayer->GetType() == TYPE_READBACK) {
|
||||
static_cast<ReadbackLayer*>(aLayer)->NotifyRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayer::DidInsertChild(Layer* aLayer)
|
||||
{
|
||||
if (aLayer->GetType() == TYPE_READBACK) {
|
||||
mMayHaveReadbackChild = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
|
||||
static nsACString& PrintInfo(nsACString& aTo, ShadowLayer* aShadowLayer);
|
||||
|
@ -534,6 +568,22 @@ ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
|||
return aTo;
|
||||
}
|
||||
|
||||
nsACString&
|
||||
ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
{
|
||||
Layer::PrintInfo(aTo, aPrefix);
|
||||
AppendToString(aTo, mSize, " [size=", "]");
|
||||
if (mBackgroundLayer) {
|
||||
AppendToString(aTo, mBackgroundLayer, " [backgroundLayer=", "]");
|
||||
AppendToString(aTo, mBackgroundLayerOffset, " [backgroundOffset=", "]");
|
||||
} else if (mBackgroundColor.a == 1.0) {
|
||||
AppendToString(aTo, mBackgroundColor, " [backgroundColor=", "]");
|
||||
} else {
|
||||
aTo += " [nobackground]";
|
||||
}
|
||||
return aTo;
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// LayerManager
|
||||
|
||||
|
@ -665,6 +715,10 @@ nsACString&
|
|||
ImageLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
{ return aTo; }
|
||||
|
||||
nsACString&
|
||||
ReadbackLayer::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||
{ return aTo; }
|
||||
|
||||
void LayerManager::Dump(FILE* aFile, const char* aPrefix) {}
|
||||
void LayerManager::DumpSelf(FILE* aFile, const char* aPrefix) {}
|
||||
void LayerManager::Log(const char* aPrefix) {}
|
||||
|
|
|
@ -78,6 +78,8 @@ class ColorLayer;
|
|||
class ImageContainer;
|
||||
class CanvasLayer;
|
||||
class ShadowLayer;
|
||||
class ReadbackLayer;
|
||||
class ReadbackProcessor;
|
||||
class SpecificLayerAttributes;
|
||||
|
||||
/**
|
||||
|
@ -394,6 +396,11 @@ public:
|
|||
* Create a CanvasLayer for this manager's layer tree.
|
||||
*/
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() = 0;
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Create a ReadbackLayer for this manager's layer tree.
|
||||
*/
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer() { return nsnull; }
|
||||
|
||||
/**
|
||||
* Can be called anytime
|
||||
|
@ -503,13 +510,15 @@ class THEBES_API Layer {
|
|||
NS_INLINE_DECL_REFCOUNTING(Layer)
|
||||
|
||||
public:
|
||||
// Keep these in alphabetical order
|
||||
enum LayerType {
|
||||
TYPE_THEBES,
|
||||
TYPE_CANVAS,
|
||||
TYPE_COLOR,
|
||||
TYPE_CONTAINER,
|
||||
TYPE_IMAGE,
|
||||
TYPE_COLOR,
|
||||
TYPE_CANVAS,
|
||||
TYPE_SHADOW
|
||||
TYPE_READBACK,
|
||||
TYPE_SHADOW,
|
||||
TYPE_THEBES
|
||||
};
|
||||
|
||||
virtual ~Layer() {}
|
||||
|
@ -928,12 +937,16 @@ public:
|
|||
mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nsnull);
|
||||
}
|
||||
|
||||
bool UsedForReadback() { return mUsedForReadback; }
|
||||
void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
|
||||
|
||||
protected:
|
||||
ThebesLayer(LayerManager* aManager, void* aImplData)
|
||||
: Layer(aManager, aImplData)
|
||||
, mValidRegion()
|
||||
, mXResolution(1.0)
|
||||
, mYResolution(1.0)
|
||||
, mUsedForReadback(false)
|
||||
{
|
||||
mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
|
||||
}
|
||||
|
@ -956,6 +969,11 @@ protected:
|
|||
// sense for all backends to fully support it.
|
||||
float mXResolution;
|
||||
float mYResolution;
|
||||
/**
|
||||
* Set when this ThebesLayer is participating in readback, i.e. some
|
||||
* ReadbackLayer (may) be getting its background from this layer.
|
||||
*/
|
||||
bool mUsedForReadback;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1025,12 +1043,18 @@ public:
|
|||
PRBool SupportsComponentAlphaChildren() { return mSupportsComponentAlphaChildren; }
|
||||
|
||||
protected:
|
||||
friend class ReadbackProcessor;
|
||||
|
||||
void DidInsertChild(Layer* aLayer);
|
||||
void DidRemoveChild(Layer* aLayer);
|
||||
|
||||
ContainerLayer(LayerManager* aManager, void* aImplData)
|
||||
: Layer(aManager, aImplData),
|
||||
mFirstChild(nsnull),
|
||||
mLastChild(nsnull),
|
||||
mUseIntermediateSurface(PR_FALSE),
|
||||
mSupportsComponentAlphaChildren(PR_FALSE)
|
||||
mSupportsComponentAlphaChildren(PR_FALSE),
|
||||
mMayHaveReadbackChild(PR_FALSE)
|
||||
{
|
||||
mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
|
||||
}
|
||||
|
@ -1053,6 +1077,7 @@ protected:
|
|||
FrameMetrics mFrameMetrics;
|
||||
PRPackedBool mUseIntermediateSurface;
|
||||
PRPackedBool mSupportsComponentAlphaChildren;
|
||||
PRPackedBool mMayHaveReadbackChild;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -68,12 +68,14 @@ EXPORTS = \
|
|||
Layers.h \
|
||||
LayerManagerOGL.h \
|
||||
LayerManagerOGLProgram.h \
|
||||
ReadbackLayer.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
Layers.cpp \
|
||||
BasicImages.cpp \
|
||||
BasicLayers.cpp \
|
||||
Layers.cpp \
|
||||
ReadbackProcessor.cpp \
|
||||
ThebesLayerBuffer.cpp \
|
||||
CanvasLayerOGL.cpp \
|
||||
ColorLayerOGL.cpp \
|
||||
|
@ -104,6 +106,7 @@ endif
|
|||
ifdef MOZ_ENABLE_D3D10_LAYER
|
||||
EXPORTS += \
|
||||
LayerManagerD3D10.h \
|
||||
ReadbackManagerD3D10.h \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS += \
|
||||
|
@ -113,6 +116,7 @@ CPPSRCS += \
|
|||
ImageLayerD3D10.cpp \
|
||||
ColorLayerD3D10.cpp \
|
||||
CanvasLayerD3D10.cpp \
|
||||
ReadbackManagerD3D10.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert O'Callahan <robert@ocallahan.org>
|
||||
*
|
||||
* 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 GFX_READBACKLAYER_H
|
||||
#define GFX_READBACKLAYER_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ReadbackProcessor;
|
||||
|
||||
/**
|
||||
* A ReadbackSink receives a stream of updates to a rectangle of pixels.
|
||||
* These update callbacks are always called on the main thread, either during
|
||||
* EndTransaction or from the event loop.
|
||||
*/
|
||||
class THEBES_API ReadbackSink {
|
||||
public:
|
||||
ReadbackSink() {}
|
||||
virtual ~ReadbackSink() {}
|
||||
|
||||
/**
|
||||
* Sends an update to indicate that the background is currently unknown.
|
||||
*/
|
||||
virtual void SetUnknown(PRUint64 aSequenceNumber) = 0;
|
||||
/**
|
||||
* Called by the layer system to indicate that the contents of part of
|
||||
* the readback area are changing.
|
||||
* @param aRect is the rectangle of content that is being updated,
|
||||
* in the coordinate system of the ReadbackLayer.
|
||||
* @param aSequenceNumber updates issued out of order should be ignored.
|
||||
* Only use updates whose sequence counter is greater than all other updates
|
||||
* seen so far. Return null when a non-fresh sequence value is given.
|
||||
* @return a context into which the update should be drawn. This should be
|
||||
* set up to clip to aRect. Zero should never be passed as a sequence number.
|
||||
* If this returns null, EndUpdate should NOT be called. If it returns
|
||||
* non-null, EndUpdate must be called.
|
||||
*
|
||||
* We don't support partially unknown backgrounds. Therefore, the
|
||||
* first BeginUpdate after a SetUnknown will have the complete background.
|
||||
*/
|
||||
virtual already_AddRefed<gfxContext>
|
||||
BeginUpdate(const nsIntRect& aRect, PRUint64 aSequenceNumber) = 0;
|
||||
/**
|
||||
* EndUpdate must be called immediately after BeginUpdate, without returning
|
||||
* to the event loop.
|
||||
* @param aContext the context returned by BeginUpdate
|
||||
* Implicitly Restore()s the state of aContext.
|
||||
*/
|
||||
virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A ReadbackLayer never renders anything. It enables clients to extract
|
||||
* the rendered contents of the layer tree below the ReadbackLayer.
|
||||
* The rendered contents are delivered asynchronously via calls to a
|
||||
* ReadbackSink object supplied by the client.
|
||||
*
|
||||
* This is a "best effort" API; it is possible for the layer system to tell
|
||||
* the ReadbackSink that the contents of the readback area are unknown.
|
||||
*
|
||||
* This API exists to work around the limitations of transparent windowless
|
||||
* plugin rendering APIs. It should not be used for anything else.
|
||||
*/
|
||||
class THEBES_API ReadbackLayer : public Layer {
|
||||
public:
|
||||
MOZ_LAYER_DECL_NAME("ReadbackLayer", TYPE_READBACK)
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
|
||||
{
|
||||
// Snap our local transform first, and snap the inherited transform as well.
|
||||
// This makes our snapping equivalent to what would happen if our content
|
||||
// was drawn into a ThebesLayer (gfxContext would snap using the local
|
||||
// transform, then we'd snap again when compositing the ThebesLayer).
|
||||
mEffectiveTransform =
|
||||
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mSize.width, mSize.height),
|
||||
nsnull)*
|
||||
SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nsnull);
|
||||
}
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the callback object to which readback updates will be delivered.
|
||||
* This also resets the "needed rectangle" so that on the next layer tree
|
||||
* transaction we will try to deliver the full contents of the readback
|
||||
* area to the sink.
|
||||
* This layer takes ownership of the sink. It will be deleted when the
|
||||
* layer is destroyed or when a new sink is set.
|
||||
* Initially the contents of the readback area are completely unknown.
|
||||
*/
|
||||
void SetSink(ReadbackSink* aSink)
|
||||
{
|
||||
SetUnknown();
|
||||
mSink = aSink;
|
||||
}
|
||||
ReadbackSink* GetSink() { return mSink; }
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the size of content that should be read back. The readback area
|
||||
* has its top-left at 0,0 and has size aSize.
|
||||
* Can only be called while the sink is null!
|
||||
*/
|
||||
void SetSize(const nsIntSize& aSize)
|
||||
{
|
||||
NS_ASSERTION(!mSink, "Should have no sink while changing size!");
|
||||
mSize = aSize;
|
||||
}
|
||||
const nsIntSize& GetSize() { return mSize; }
|
||||
nsIntRect GetRect() { return nsIntRect(nsIntPoint(0, 0), mSize); }
|
||||
|
||||
PRBool IsBackgroundKnown()
|
||||
{
|
||||
return mBackgroundLayer || mBackgroundColor.a == 1.0;
|
||||
}
|
||||
|
||||
void NotifyRemoved() {
|
||||
SetUnknown();
|
||||
mSink = nsnull;
|
||||
}
|
||||
|
||||
void NotifyThebesLayerRemoved(ThebesLayer* aLayer)
|
||||
{
|
||||
if (mBackgroundLayer == aLayer) {
|
||||
mBackgroundLayer = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
const nsIntPoint& GetBackgroundLayerOffset() { return mBackgroundLayerOffset; }
|
||||
|
||||
PRUint64 AllocateSequenceNumber() { return ++mSequenceCounter; }
|
||||
|
||||
void SetUnknown()
|
||||
{
|
||||
if (IsBackgroundKnown()) {
|
||||
if (mSink) {
|
||||
mSink->SetUnknown(AllocateSequenceNumber());
|
||||
}
|
||||
mBackgroundLayer = nsnull;
|
||||
mBackgroundColor = gfxRGBA(0,0,0,0);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class ReadbackProcessor;
|
||||
|
||||
ReadbackLayer(LayerManager* aManager, void* aImplData) :
|
||||
Layer(aManager, aImplData),
|
||||
mSequenceCounter(0),
|
||||
mSize(0,0),
|
||||
mBackgroundLayer(nsnull),
|
||||
mBackgroundLayerOffset(0, 0),
|
||||
mBackgroundColor(gfxRGBA(0,0,0,0))
|
||||
{}
|
||||
|
||||
// Print interesting information about this into aTo. Internally
|
||||
// used to implement Dump*() and Log*().
|
||||
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||
|
||||
PRUint64 mSequenceCounter;
|
||||
nsAutoPtr<ReadbackSink> mSink;
|
||||
nsIntSize mSize;
|
||||
|
||||
// This can refer to any (earlier) sibling ThebesLayer. That ThebesLayer
|
||||
// must have mUsedForReadback set on it. If the ThebesLayer is removed
|
||||
// for the container, this will be set to null by NotifyThebesLayerRemoved.
|
||||
// This ThebesLayer contains the contents which have previously been reported
|
||||
// to mSink. The ThebesLayer had only an integer translation transform,
|
||||
// and it covered the entire readback area. This layer also had only an
|
||||
// integer translation transform.
|
||||
ThebesLayer* mBackgroundLayer;
|
||||
// When mBackgroundLayer is non-null, this is the offset to add to
|
||||
// convert from the coordinates of mBackgroundLayer to the coordinates
|
||||
// of this layer.
|
||||
nsIntPoint mBackgroundLayerOffset;
|
||||
// When mBackgroundColor is opaque, this is the color of the ColorLayer
|
||||
// that contained the contents we reported to mSink, which covered the
|
||||
// entire readback area.
|
||||
gfxRGBA mBackgroundColor;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* GFX_READBACKLAYER_H */
|
|
@ -0,0 +1,198 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert O'Callahan <robert@ocallahan.org>
|
||||
*
|
||||
* 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 "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
void
|
||||
ReadbackProcessor::BuildUpdates(ContainerLayer* aContainer)
|
||||
{
|
||||
NS_ASSERTION(mAllUpdates.IsEmpty(), "Some updates not processed?");
|
||||
|
||||
if (!aContainer->mMayHaveReadbackChild)
|
||||
return;
|
||||
|
||||
aContainer->mMayHaveReadbackChild = PR_FALSE;
|
||||
// go backwards so the updates read from earlier layers are later in the
|
||||
// array.
|
||||
for (Layer* l = aContainer->GetLastChild(); l; l = l->GetPrevSibling()) {
|
||||
if (l->GetType() == Layer::TYPE_READBACK) {
|
||||
aContainer->mMayHaveReadbackChild = PR_TRUE;
|
||||
BuildUpdatesForLayer(static_cast<ReadbackLayer*>(l));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Layer*
|
||||
FindBackgroundLayer(ReadbackLayer* aLayer, nsIntPoint* aOffset)
|
||||
{
|
||||
gfxMatrix transform;
|
||||
if (!aLayer->GetTransform().Is2D(&transform) ||
|
||||
transform.HasNonIntegerTranslation())
|
||||
return nsnull;
|
||||
nsIntPoint transformOffset(PRInt32(transform.x0), PRInt32(transform.y0));
|
||||
|
||||
for (Layer* l = aLayer->GetPrevSibling(); l; l = l->GetPrevSibling()) {
|
||||
gfxMatrix backgroundTransform;
|
||||
if (!l->GetTransform().Is2D(&backgroundTransform) ||
|
||||
backgroundTransform.HasNonIntegerTranslation())
|
||||
return nsnull;
|
||||
|
||||
nsIntPoint backgroundOffset(PRInt32(backgroundTransform.x0), PRInt32(backgroundTransform.y0));
|
||||
nsIntRect rectInBackground(transformOffset - backgroundOffset, aLayer->GetSize());
|
||||
const nsIntRegion& visibleRegion = l->GetEffectiveVisibleRegion();
|
||||
if (!visibleRegion.Intersects(rectInBackground))
|
||||
continue;
|
||||
// Since l is present in the background, from here on we either choose l
|
||||
// or nothing.
|
||||
if (!visibleRegion.Contains(rectInBackground))
|
||||
return nsnull;
|
||||
|
||||
if (l->GetEffectiveOpacity() != 1.0 ||
|
||||
!(l->GetContentFlags() & Layer::CONTENT_OPAQUE))
|
||||
return nsnull;
|
||||
|
||||
// cliprects are post-transform
|
||||
const nsIntRect* clipRect = l->GetEffectiveClipRect();
|
||||
if (clipRect && !clipRect->Contains(nsIntRect(transformOffset, aLayer->GetSize())))
|
||||
return nsnull;
|
||||
|
||||
Layer::LayerType type = l->GetType();
|
||||
if (type != Layer::TYPE_COLOR && type != Layer::TYPE_THEBES)
|
||||
return nsnull;
|
||||
|
||||
*aOffset = backgroundOffset - transformOffset;
|
||||
return l;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackProcessor::BuildUpdatesForLayer(ReadbackLayer* aLayer)
|
||||
{
|
||||
if (!aLayer->mSink)
|
||||
return;
|
||||
|
||||
nsIntPoint offset;
|
||||
Layer* newBackground = FindBackgroundLayer(aLayer, &offset);
|
||||
if (!newBackground) {
|
||||
aLayer->SetUnknown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (newBackground->GetType() == Layer::TYPE_COLOR) {
|
||||
ColorLayer* colorLayer = static_cast<ColorLayer*>(newBackground);
|
||||
if (aLayer->mBackgroundColor != colorLayer->GetColor()) {
|
||||
aLayer->mBackgroundLayer = nsnull;
|
||||
aLayer->mBackgroundColor = colorLayer->GetColor();
|
||||
NS_ASSERTION(aLayer->mBackgroundColor.a == 1.0,
|
||||
"Color layer said it was opaque!");
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
aLayer->mSink->BeginUpdate(aLayer->GetRect(),
|
||||
aLayer->AllocateSequenceNumber());
|
||||
if (ctx) {
|
||||
ctx->SetColor(aLayer->mBackgroundColor);
|
||||
nsIntSize size = aLayer->GetSize();
|
||||
ctx->Rectangle(gfxRect(0, 0, size.width, size.height));
|
||||
ctx->Fill();
|
||||
aLayer->mSink->EndUpdate(ctx, aLayer->GetRect());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NS_ASSERTION(newBackground->AsThebesLayer(), "Must be ThebesLayer");
|
||||
ThebesLayer* thebesLayer = static_cast<ThebesLayer*>(newBackground);
|
||||
// updateRect is relative to the ThebesLayer
|
||||
nsIntRect updateRect = aLayer->GetRect() - offset;
|
||||
if (thebesLayer != aLayer->mBackgroundLayer ||
|
||||
offset != aLayer->mBackgroundLayerOffset) {
|
||||
aLayer->mBackgroundLayer = thebesLayer;
|
||||
aLayer->mBackgroundLayerOffset = offset;
|
||||
aLayer->mBackgroundColor = gfxRGBA(0,0,0,0);
|
||||
thebesLayer->SetUsedForReadback(true);
|
||||
} else {
|
||||
nsIntRegion invalid;
|
||||
invalid.Sub(updateRect, thebesLayer->GetValidRegion());
|
||||
updateRect = invalid.GetBounds();
|
||||
}
|
||||
|
||||
Update update = { aLayer, updateRect, aLayer->AllocateSequenceNumber() };
|
||||
mAllUpdates.AppendElement(update);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackProcessor::GetThebesLayerUpdates(ThebesLayer* aLayer,
|
||||
nsTArray<Update>* aUpdates,
|
||||
nsIntRegion* aUpdateRegion)
|
||||
{
|
||||
// All ThebesLayers used for readback are in mAllUpdates (some possibly
|
||||
// with an empty update rect).
|
||||
aLayer->SetUsedForReadback(false);
|
||||
if (aUpdateRegion) {
|
||||
aUpdateRegion->SetEmpty();
|
||||
}
|
||||
for (PRUint32 i = mAllUpdates.Length(); i > 0; --i) {
|
||||
const Update& update = mAllUpdates[i - 1];
|
||||
if (update.mLayer->mBackgroundLayer == aLayer) {
|
||||
aLayer->SetUsedForReadback(true);
|
||||
// Don't bother asking for updates if we have an empty update rect.
|
||||
if (!update.mUpdateRect.IsEmpty()) {
|
||||
aUpdates->AppendElement(update);
|
||||
if (aUpdateRegion) {
|
||||
aUpdateRegion->Or(*aUpdateRegion, update.mUpdateRect);
|
||||
}
|
||||
}
|
||||
mAllUpdates.RemoveElementAt(i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReadbackProcessor::~ReadbackProcessor()
|
||||
{
|
||||
for (PRUint32 i = mAllUpdates.Length(); i > 0; --i) {
|
||||
const Update& update = mAllUpdates[i - 1];
|
||||
// Unprocessed update. Notify the readback sink that this content is
|
||||
// unknown.
|
||||
update.mLayer->SetUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert O'Callahan <robert@ocallahan.org>
|
||||
*
|
||||
* 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 GFX_READBACKPROCESSOR_H
|
||||
#define GFX_READBACKPROCESSOR_H
|
||||
|
||||
#include "ReadbackLayer.h"
|
||||
#include "ThebesLayerBuffer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ReadbackProcessor {
|
||||
public:
|
||||
/**
|
||||
* Called by the container before processing any child layers. Call this
|
||||
* if any child layer might have changed in any way (other than content-only
|
||||
* changes to layers other than ColorLayers and ThebesLayers).
|
||||
*
|
||||
* This method recomputes the relationship between ReadbackLayers and
|
||||
* sibling layers, and dispatches changes to ReadbackLayers. Except that
|
||||
* if a ThebesLayer needs its contents sent to some ReadbackLayer, we'll
|
||||
* just record that internally and later the ThebesLayer should call
|
||||
* GetThebesLayerUpdates when it paints, to find out which rectangle needs
|
||||
* to be sent, and the ReadbackLayer it needs to be sent to.
|
||||
*/
|
||||
void BuildUpdates(ContainerLayer* aContainer);
|
||||
|
||||
struct Update {
|
||||
/**
|
||||
* The layer a ThebesLayer should send its contents to.
|
||||
*/
|
||||
ReadbackLayer* mLayer;
|
||||
/**
|
||||
* The rectangle of content that it should send, in the ThebesLayer's
|
||||
* coordinate system. This rectangle is guaranteed to be in the ThebesLayer's
|
||||
* visible region. Translate it to mLayer's coordinate system
|
||||
* by adding mLayer->GetBackgroundLayerOffset().
|
||||
*/
|
||||
nsIntRect mUpdateRect;
|
||||
/**
|
||||
* The sequence counter value to use when calling DoUpdate
|
||||
*/
|
||||
PRUint64 mSequenceCounter;
|
||||
};
|
||||
/**
|
||||
* Appends any ReadbackLayers that need to be updated, and the rects that
|
||||
* need to be updated, to aUpdates. Only need to call this for ThebesLayers
|
||||
* that have been marked UsedForReadback().
|
||||
* Each Update's mLayer's mBackgroundLayer will have been set to aLayer.
|
||||
* If a ThebesLayer doesn't call GetThebesLayerUpdates, then all the
|
||||
* ReadbackLayers that needed data from that ThebesLayer will be marked
|
||||
* as having unknown backgrounds.
|
||||
* @param aUpdateRegion if non-null, this region is set to the union
|
||||
* of the mUpdateRects.
|
||||
*/
|
||||
void GetThebesLayerUpdates(ThebesLayer* aLayer,
|
||||
nsTArray<Update>* aUpdates,
|
||||
nsIntRegion* aUpdateRegion = nsnull);
|
||||
|
||||
~ReadbackProcessor();
|
||||
|
||||
protected:
|
||||
void BuildUpdatesForLayer(ReadbackLayer* aLayer);
|
||||
|
||||
nsTArray<Update> mAllUpdates;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* GFX_READBACKPROCESSOR_H */
|
|
@ -58,6 +58,7 @@
|
|||
#include "gfxUtils.h"
|
||||
#include "ThebesLayerBuffer.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
|
||||
|
@ -106,9 +107,16 @@ public:
|
|||
* set up to account for all the properties of the layer (transform,
|
||||
* opacity, etc).
|
||||
*/
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData) {}
|
||||
virtual void Paint(gfxContext* aContext) {}
|
||||
|
||||
/**
|
||||
* Like Paint() but called for ThebesLayers with the additional parameters
|
||||
* they need.
|
||||
*/
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback) {}
|
||||
|
||||
virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
|
||||
|
||||
|
@ -236,8 +244,6 @@ ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
|
|||
aAfter->GetParent() == aContainer),
|
||||
"aAfter is not our child");
|
||||
|
||||
NS_ADDREF(aChild);
|
||||
|
||||
aChild->SetParent(aContainer);
|
||||
if (aAfter == aContainer->mLastChild) {
|
||||
aContainer->mLastChild = aChild;
|
||||
|
@ -248,6 +254,8 @@ ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
|
|||
aContainer->mFirstChild->SetPrevSibling(aChild);
|
||||
}
|
||||
aContainer->mFirstChild = aChild;
|
||||
NS_ADDREF(aChild);
|
||||
aContainer->DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -258,6 +266,8 @@ ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
|
|||
next->SetPrevSibling(aChild);
|
||||
}
|
||||
aAfter->SetNextSibling(aChild);
|
||||
NS_ADDREF(aChild);
|
||||
aContainer->DidInsertChild(aChild);
|
||||
}
|
||||
|
||||
template<class Container>
|
||||
|
@ -286,6 +296,7 @@ ContainerRemoveChild(Layer* aChild, Container* aContainer)
|
|||
aChild->SetPrevSibling(nsnull);
|
||||
aChild->SetParent(nsnull);
|
||||
|
||||
aContainer->DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
}
|
||||
|
||||
|
@ -377,9 +388,10 @@ public:
|
|||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
|
||||
virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); }
|
||||
|
||||
|
@ -504,14 +516,20 @@ PushGroupForLayer(gfxContext* aContext, Layer* aLayer, const nsIntRegion& aRegio
|
|||
}
|
||||
|
||||
void
|
||||
BasicThebesLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
NS_ASSERTION(BasicManager()->InDrawing(),
|
||||
"Can only draw in drawing phase");
|
||||
nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
|
||||
}
|
||||
|
||||
PRBool canUseOpaqueSurface = CanUseOpaqueSurface();
|
||||
Buffer::ContentType contentType =
|
||||
canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
|
||||
|
@ -522,6 +540,8 @@ BasicThebesLayer::Paint(gfxContext* aContext,
|
|||
(!canUseOpaqueSurface &&
|
||||
(mContentFlags & CONTENT_COMPONENT_ALPHA) &&
|
||||
!MustRetainContent())) {
|
||||
NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
|
||||
|
||||
mValidRegion.SetEmpty();
|
||||
mBuffer.Clear();
|
||||
|
||||
|
@ -584,6 +604,20 @@ BasicThebesLayer::Paint(gfxContext* aContext,
|
|||
}
|
||||
|
||||
mBuffer.DrawTo(this, aContext, opacity);
|
||||
|
||||
for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
|
||||
ReadbackProcessor::Update& update = readbackUpdates[i];
|
||||
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
|
||||
update.mSequenceCounter);
|
||||
if (ctx) {
|
||||
NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
|
||||
ctx->Translate(gfxPoint(offset.x, offset.y));
|
||||
mBuffer.DrawTo(this, ctx, 1.0);
|
||||
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PRBool
|
||||
|
@ -664,9 +698,7 @@ public:
|
|||
ImageLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
static void PaintContext(gfxPattern* aPattern,
|
||||
const nsIntRegion& aVisible,
|
||||
|
@ -688,9 +720,7 @@ protected:
|
|||
};
|
||||
|
||||
void
|
||||
BasicImageLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicImageLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
nsRefPtr<gfxPattern> dontcare =
|
||||
GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
|
||||
|
@ -796,9 +826,7 @@ public:
|
|||
ColorLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
virtual void Paint(gfxContext* aContext)
|
||||
{
|
||||
PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
|
||||
}
|
||||
|
@ -844,9 +872,7 @@ public:
|
|||
|
||||
virtual void Initialize(const Data& aData);
|
||||
virtual void Updated(const nsIntRect& aRect);
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
virtual void PaintWithOpacity(gfxContext* aContext,
|
||||
float aOpacity);
|
||||
|
@ -956,9 +982,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
|
|||
}
|
||||
|
||||
void
|
||||
BasicCanvasLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicCanvasLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
PaintWithOpacity(aContext, GetEffectiveOpacity());
|
||||
}
|
||||
|
@ -995,6 +1019,34 @@ BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
|
|||
mUpdatedRect.Empty();
|
||||
}
|
||||
|
||||
class BasicReadbackLayer : public ReadbackLayer,
|
||||
BasicImplData
|
||||
{
|
||||
public:
|
||||
BasicReadbackLayer(BasicLayerManager* aLayerManager) :
|
||||
ReadbackLayer(aLayerManager, static_cast<BasicImplData*>(this))
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicReadbackLayer);
|
||||
}
|
||||
virtual ~BasicReadbackLayer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(BasicReadbackLayer);
|
||||
}
|
||||
|
||||
virtual void SetVisibleRegion(const nsIntRegion& aRegion)
|
||||
{
|
||||
NS_ASSERTION(BasicManager()->InConstruction(),
|
||||
"Can only set properties in construction phase");
|
||||
ReadbackLayer::SetVisibleRegion(aRegion);
|
||||
}
|
||||
|
||||
protected:
|
||||
BasicLayerManager* BasicManager()
|
||||
{
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
};
|
||||
|
||||
static nsIntRect
|
||||
ToOutsideIntRect(const gfxRect &aRect)
|
||||
{
|
||||
|
@ -1297,7 +1349,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
|||
MarkLeafLayersCoveredByOpaque(mRoot,
|
||||
mRoot->GetEffectiveVisibleRegion().GetBounds(),
|
||||
region);
|
||||
PaintLayer(mRoot, aCallback, aCallbackData);
|
||||
PaintLayer(mRoot, aCallback, aCallbackData, nsnull);
|
||||
|
||||
// If we're doing manual double-buffering, we need to avoid drawing
|
||||
// the results of an incomplete transaction to the destination surface.
|
||||
|
@ -1368,7 +1420,8 @@ BasicLayerManager::SetRoot(Layer* aLayer)
|
|||
void
|
||||
BasicLayerManager::PaintLayer(Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
|
||||
const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
|
||||
|
@ -1430,11 +1483,21 @@ BasicLayerManager::PaintLayer(Layer* aLayer,
|
|||
(void*)aLayer, data->IsCoveredByOpaque()));
|
||||
#endif
|
||||
if (!data->IsCoveredByOpaque()) {
|
||||
data->Paint(mTarget, aCallback, aCallbackData);
|
||||
if (aLayer->GetType() == Layer::TYPE_THEBES) {
|
||||
data->PaintThebes(mTarget, aCallback, aCallbackData, aReadback);
|
||||
} else {
|
||||
data->Paint(mTarget);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ReadbackProcessor readback;
|
||||
if (IsRetained()) {
|
||||
ContainerLayer* container = static_cast<ContainerLayer*>(aLayer);
|
||||
readback.BuildUpdates(container);
|
||||
}
|
||||
|
||||
for (; child; child = child->GetNextSibling()) {
|
||||
PaintLayer(child, aCallback, aCallbackData);
|
||||
PaintLayer(child, aCallback, aCallbackData, &readback);
|
||||
if (mTransactionIncomplete)
|
||||
break;
|
||||
}
|
||||
|
@ -1518,6 +1581,13 @@ BasicLayerManager::CreateCanvasLayer()
|
|||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ReadbackLayer>
|
||||
BasicLayerManager::CreateReadbackLayer()
|
||||
{
|
||||
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
|
||||
nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
#ifdef MOZ_IPC
|
||||
|
||||
|
@ -1574,6 +1644,19 @@ ToShadowable(Layer* aLayer)
|
|||
return ToData(aLayer)->AsShadowableLayer();
|
||||
}
|
||||
|
||||
// Some layers, like ReadbackLayers, can't be shadowed and shadowing
|
||||
// them doesn't make sense anyway
|
||||
static bool
|
||||
ShouldShadow(Layer* aLayer)
|
||||
{
|
||||
if (!ToShadowable(aLayer)) {
|
||||
NS_ABORT_IF_FALSE(aLayer->GetType() == Layer::TYPE_READBACK,
|
||||
"Only expect not to shadow ReadbackLayers");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class OpT>
|
||||
static BasicShadowableLayer*
|
||||
GetBasicShadowable(const OpT& op)
|
||||
|
@ -1621,7 +1704,10 @@ private:
|
|||
void
|
||||
BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
|
||||
{
|
||||
if (HasShadow()) {
|
||||
if (HasShadow() && ShouldShadow(aChild)) {
|
||||
while (aAfter && !ShouldShadow(aAfter)) {
|
||||
aAfter = aAfter->GetPrevSibling();
|
||||
}
|
||||
ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
|
||||
ShadowManager()->Hold(aChild),
|
||||
aAfter ? ShadowManager()->Hold(aAfter) : nsnull);
|
||||
|
@ -1632,7 +1718,7 @@ BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
|
|||
void
|
||||
BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
|
||||
{
|
||||
if (HasShadow()) {
|
||||
if (HasShadow() && ShouldShadow(aChild)) {
|
||||
ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
|
||||
ShadowManager()->Hold(aChild));
|
||||
}
|
||||
|
@ -1856,9 +1942,7 @@ public:
|
|||
MOZ_COUNT_DTOR(BasicShadowableImageLayer);
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
{
|
||||
|
@ -1889,9 +1973,7 @@ private:
|
|||
};
|
||||
|
||||
void
|
||||
BasicShadowableImageLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicShadowableImageLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
gfxIntSize oldSize = mSize;
|
||||
nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
|
||||
|
@ -1976,9 +2058,7 @@ public:
|
|||
}
|
||||
|
||||
virtual void Initialize(const Data& aData);
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||
{
|
||||
|
@ -2039,11 +2119,9 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
|
|||
}
|
||||
|
||||
void
|
||||
BasicShadowableCanvasLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
BasicCanvasLayer::Paint(aContext, aCallback, aCallbackData);
|
||||
BasicCanvasLayer::Paint(aContext);
|
||||
if (!HasShadow())
|
||||
return;
|
||||
|
||||
|
@ -2166,9 +2244,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void PaintThebes(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
|
||||
private:
|
||||
BasicShadowLayerManager* BasicManager()
|
||||
|
@ -2260,9 +2339,10 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
|
|||
}
|
||||
|
||||
void
|
||||
BasicShadowThebesLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback)
|
||||
{
|
||||
NS_ASSERTION(BasicManager()->InDrawing(),
|
||||
"Can only draw in drawing phase");
|
||||
|
@ -2356,9 +2436,7 @@ public:
|
|||
mFrontSurface = nsnull;
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
protected:
|
||||
BasicShadowLayerManager* BasicManager()
|
||||
|
@ -2389,9 +2467,7 @@ BasicShadowImageLayer::Swap(gfxSharedImageSurface* newFront)
|
|||
}
|
||||
|
||||
void
|
||||
BasicShadowImageLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicShadowImageLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
if (!mFrontSurface) {
|
||||
return;
|
||||
|
@ -2417,9 +2493,7 @@ public:
|
|||
MOZ_COUNT_DTOR(BasicShadowColorLayer);
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
virtual void Paint(gfxContext* aContext)
|
||||
{
|
||||
BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
|
||||
}
|
||||
|
@ -2461,9 +2535,7 @@ public:
|
|||
mFrontSurface = nsnull;
|
||||
}
|
||||
|
||||
virtual void Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
virtual void Paint(gfxContext* aContext);
|
||||
|
||||
private:
|
||||
BasicShadowLayerManager* BasicManager()
|
||||
|
@ -2495,9 +2567,7 @@ BasicShadowCanvasLayer::Swap(gfxSharedImageSurface* newFront)
|
|||
}
|
||||
|
||||
void
|
||||
BasicShadowCanvasLayer::Paint(gfxContext* aContext,
|
||||
LayerManager::DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
BasicShadowCanvasLayer::Paint(gfxContext* aContext)
|
||||
{
|
||||
NS_ASSERTION(BasicManager()->InDrawing(),
|
||||
"Can only draw in drawing phase");
|
||||
|
@ -2668,7 +2738,7 @@ BasicShadowLayerManager::Mutated(Layer* aLayer)
|
|||
BasicLayerManager::Mutated(aLayer);
|
||||
|
||||
NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
|
||||
if (HasShadowManager()) {
|
||||
if (HasShadowManager() && ShouldShadow(aLayer)) {
|
||||
ShadowLayerForwarder::Mutated(Hold(aLayer));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ class ShadowContainerLayer;
|
|||
class ShadowImageLayer;
|
||||
class ShadowCanvasLayer;
|
||||
class ShadowColorLayer;
|
||||
class ReadbackProcessor;
|
||||
|
||||
/**
|
||||
* This is a cairo/Thebes-only, main-thread-only implementation of layers.
|
||||
|
@ -152,16 +153,17 @@ public:
|
|||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
|
||||
virtual already_AddRefed<ImageContainer> CreateImageContainer();
|
||||
virtual already_AddRefed<ColorLayer> CreateColorLayer();
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
|
||||
virtual already_AddRefed<ShadowThebesLayer> CreateShadowThebesLayer()
|
||||
{ return NULL; }
|
||||
{ return nsnull; }
|
||||
virtual already_AddRefed<ShadowContainerLayer> CreateShadowContainerLayer()
|
||||
{ return NULL; }
|
||||
{ return nsnull; }
|
||||
virtual already_AddRefed<ShadowImageLayer> CreateShadowImageLayer()
|
||||
{ return NULL; }
|
||||
{ return nsnull; }
|
||||
virtual already_AddRefed<ShadowColorLayer> CreateShadowColorLayer()
|
||||
{ return NULL; }
|
||||
{ return nsnull; }
|
||||
virtual already_AddRefed<ShadowCanvasLayer> CreateShadowCanvasLayer()
|
||||
{ return NULL; }
|
||||
{ return nsnull; }
|
||||
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
|
||||
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Basic"); }
|
||||
|
@ -197,7 +199,8 @@ protected:
|
|||
// Paints aLayer to mTarget.
|
||||
void PaintLayer(Layer* aLayer,
|
||||
DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
void* aCallbackData,
|
||||
ReadbackProcessor* aReadback);
|
||||
|
||||
// Clear the contents of a layer
|
||||
void ClearLayer(Layer* aLayer);
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_CANVASLAYEROGL_H
|
||||
#define GFX_CANVASLAYEROGL_H
|
||||
#ifndef GFX_CANVASLAYERD3D10_H
|
||||
#define GFX_CANVASLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "GLContext.h"
|
||||
|
|
|
@ -40,6 +40,9 @@
|
|||
#include "gfxUtils.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
#include "ThebesLayerD3D10.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -72,6 +75,7 @@ ContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter)
|
|||
mLastChild = aChild;
|
||||
}
|
||||
NS_ADDREF(aChild);
|
||||
DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
for (Layer *child = GetFirstChild();
|
||||
|
@ -87,6 +91,7 @@ ContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter)
|
|||
}
|
||||
aChild->SetPrevSibling(child);
|
||||
NS_ADDREF(aChild);
|
||||
DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -106,6 +111,7 @@ ContainerLayerD3D10::RemoveChild(Layer *aChild)
|
|||
aChild->SetNextSibling(nsnull);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
aChild->SetParent(nsnull);
|
||||
DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
@ -123,6 +129,7 @@ ContainerLayerD3D10::RemoveChild(Layer *aChild)
|
|||
child->SetNextSibling(nsnull);
|
||||
child->SetPrevSibling(nsnull);
|
||||
child->SetParent(nsnull);
|
||||
DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
@ -398,9 +405,16 @@ ContainerLayerD3D10::Validate()
|
|||
(mParent && mParent->SupportsComponentAlphaChildren());
|
||||
}
|
||||
|
||||
ReadbackProcessor readback;
|
||||
readback.BuildUpdates(this);
|
||||
|
||||
Layer *layer = GetFirstChild();
|
||||
while (layer) {
|
||||
static_cast<LayerD3D10*>(layer->ImplData())->Validate();
|
||||
if (layer->GetType() == TYPE_THEBES) {
|
||||
static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback);
|
||||
} else {
|
||||
static_cast<LayerD3D10*>(layer->ImplData())->Validate();
|
||||
}
|
||||
layer = layer->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,11 @@ SurfaceToTexture(ID3D10Device *aDevice,
|
|||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
HRESULT hr = aDevice->CreateTexture2D(&desc, &data, getter_AddRefs(texture));
|
||||
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for image surface"),
|
||||
hr);
|
||||
if (FAILED(hr)) {
|
||||
LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create texture for image surface"),
|
||||
hr);
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "LayerManagerD3D10Effect.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "gfxFailure.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "dxgi.h"
|
||||
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "ThebesLayerD3D10.h"
|
||||
#include "ColorLayerD3D10.h"
|
||||
#include "CanvasLayerD3D10.h"
|
||||
#include "ReadbackLayerD3D10.h"
|
||||
#include "ImageLayerD3D10.h"
|
||||
|
||||
#include "../d3d9/Nv3DVUtils.h"
|
||||
|
@ -67,15 +69,12 @@ struct Vertex
|
|||
float position[2];
|
||||
};
|
||||
|
||||
// {17F88CCB-1F49-4c08-8002-ADA7BD44856D}
|
||||
static const GUID sEffect =
|
||||
{ 0x17f88ccb, 0x1f49, 0x4c08, { 0x80, 0x2, 0xad, 0xa7, 0xbd, 0x44, 0x85, 0x6d } };
|
||||
// {19599D91-912C-4C2F-A8C5-299DE85FBD34}
|
||||
static const GUID sInputLayout =
|
||||
{ 0x19599d91, 0x912c, 0x4c2f, { 0xa8, 0xc5, 0x29, 0x9d, 0xe8, 0x5f, 0xbd, 0x34 } };
|
||||
// {293157D2-09C7-4680-AE27-C28E370E418B}
|
||||
static const GUID sVertexBuffer =
|
||||
{ 0x293157d2, 0x9c7, 0x4680, { 0xae, 0x27, 0xc2, 0x8e, 0x37, 0xe, 0x41, 0x8b } };
|
||||
// {592BF306-0EED-4F76-9D03-A0846450F472}
|
||||
static const GUID sDeviceAttachments =
|
||||
{ 0x592bf306, 0xeed, 0x4f76, { 0x9d, 0x3, 0xa0, 0x84, 0x64, 0x50, 0xf4, 0x72 } };
|
||||
// {716AEDB1-C9C3-4B4D-8332-6F65D44AF6A8}
|
||||
static const GUID sLayerManagerCount =
|
||||
{ 0x716aedb1, 0xc9c3, 0x4b4d, { 0x83, 0x32, 0x6f, 0x65, 0xd4, 0x4a, 0xf6, 0xa8 } };
|
||||
|
||||
cairo_user_data_key_t gKeyD3D10Texture;
|
||||
|
||||
|
@ -84,8 +83,36 @@ LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget)
|
|||
{
|
||||
}
|
||||
|
||||
struct DeviceAttachments
|
||||
{
|
||||
nsRefPtr<ID3D10Effect> mEffect;
|
||||
nsRefPtr<ID3D10InputLayout> mInputLayout;
|
||||
nsRefPtr<ID3D10Buffer> mVertexBuffer;
|
||||
nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
|
||||
};
|
||||
|
||||
LayerManagerD3D10::~LayerManagerD3D10()
|
||||
{
|
||||
if (mDevice) {
|
||||
int referenceCount = 0;
|
||||
UINT size = sizeof(referenceCount);
|
||||
HRESULT hr = mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
|
||||
NS_ASSERTION(SUCCEEDED(hr), "Reference count not found on device.");
|
||||
referenceCount--;
|
||||
mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
|
||||
|
||||
if (!referenceCount) {
|
||||
DeviceAttachments *attachments;
|
||||
size = sizeof(attachments);
|
||||
mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments);
|
||||
// No LayerManagers left for this device. Clear out interfaces stored which
|
||||
// hold a reference to the device.
|
||||
mDevice->SetPrivateData(sDeviceAttachments, 0, NULL);
|
||||
|
||||
delete attachments;
|
||||
}
|
||||
}
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
|
@ -129,8 +156,19 @@ LayerManagerD3D10::Initialize()
|
|||
mNv3DVUtils->SetDeviceInfo(devUnknown);
|
||||
}
|
||||
|
||||
UINT size = sizeof(ID3D10Effect*);
|
||||
if (FAILED(mDevice->GetPrivateData(sEffect, &size, mEffect.StartAssignment()))) {
|
||||
int referenceCount = 0;
|
||||
UINT size = sizeof(referenceCount);
|
||||
// If this isn't there yet it'll fail, count will remain 0, which is correct.
|
||||
mDevice->GetPrivateData(sLayerManagerCount, &size, &referenceCount);
|
||||
referenceCount++;
|
||||
mDevice->SetPrivateData(sLayerManagerCount, sizeof(referenceCount), &referenceCount);
|
||||
|
||||
DeviceAttachments *attachments;
|
||||
size = sizeof(DeviceAttachments*);
|
||||
if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
|
||||
attachments = new DeviceAttachments;
|
||||
mDevice->SetPrivateData(sDeviceAttachments, sizeof(attachments), &attachments);
|
||||
|
||||
D3D10CreateEffectFromMemoryFunc createEffect = (D3D10CreateEffectFromMemoryFunc)
|
||||
GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory");
|
||||
|
||||
|
@ -149,11 +187,8 @@ LayerManagerD3D10::Initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sEffect, mEffect);
|
||||
}
|
||||
|
||||
size = sizeof(ID3D10InputLayout*);
|
||||
if (FAILED(mDevice->GetPrivateData(sInputLayout, &size, mInputLayout.StartAssignment()))) {
|
||||
attachments->mEffect = mEffect;
|
||||
|
||||
D3D10_INPUT_ELEMENT_DESC layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
|
@ -172,11 +207,8 @@ LayerManagerD3D10::Initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sInputLayout, mInputLayout);
|
||||
}
|
||||
|
||||
size = sizeof(ID3D10Buffer*);
|
||||
if (FAILED(mDevice->GetPrivateData(sVertexBuffer, &size, mVertexBuffer.StartAssignment()))) {
|
||||
attachments->mInputLayout = mInputLayout;
|
||||
|
||||
Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
|
||||
CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
@ -188,7 +220,11 @@ LayerManagerD3D10::Initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sVertexBuffer, mVertexBuffer);
|
||||
attachments->mVertexBuffer = mVertexBuffer;
|
||||
} else {
|
||||
mEffect = attachments->mEffect;
|
||||
mVertexBuffer = attachments->mVertexBuffer;
|
||||
mInputLayout = attachments->mInputLayout;
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIDevice> dxgiDevice;
|
||||
|
@ -333,6 +369,13 @@ LayerManagerD3D10::CreateCanvasLayer()
|
|||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ReadbackLayer>
|
||||
LayerManagerD3D10::CreateReadbackLayer()
|
||||
{
|
||||
nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageContainer>
|
||||
LayerManagerD3D10::CreateImageContainer()
|
||||
{
|
||||
|
@ -382,6 +425,13 @@ LayerManagerD3D10::CreateOptimalSurface(const gfxIntSize &aSize,
|
|||
return surface.forget();
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10*
|
||||
LayerManagerD3D10::readbackManager()
|
||||
{
|
||||
EnsureReadbackManager();
|
||||
return mReadbackManager;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetViewport(const nsIntSize &aViewport)
|
||||
{
|
||||
|
@ -495,6 +545,32 @@ LayerManagerD3D10::VerifyBufferSize()
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::EnsureReadbackManager()
|
||||
{
|
||||
if (mReadbackManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceAttachments *attachments;
|
||||
UINT size = sizeof(DeviceAttachments*);
|
||||
if (FAILED(mDevice->GetPrivateData(sDeviceAttachments, &size, &attachments))) {
|
||||
// Strange! This shouldn't happen ... return a readback manager for this
|
||||
// layer manager only.
|
||||
mReadbackManager = new ReadbackManagerD3D10();
|
||||
gfx::LogFailure(NS_LITERAL_CSTRING("Couldn't get device attachments for device."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (attachments->mReadbackManager) {
|
||||
mReadbackManager = attachments->mReadbackManager;
|
||||
return;
|
||||
}
|
||||
|
||||
mReadbackManager = new ReadbackManagerD3D10();
|
||||
attachments->mReadbackManager = mReadbackManager;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::Render()
|
||||
{
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "gfxContext.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "ReadbackManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -123,6 +125,8 @@ public:
|
|||
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
|
||||
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
|
||||
|
||||
virtual already_AddRefed<ImageContainer> CreateImageContainer();
|
||||
|
||||
virtual already_AddRefed<gfxASurface>
|
||||
|
@ -142,6 +146,8 @@ public:
|
|||
|
||||
ID3D10Effect *effect() const { return mEffect; }
|
||||
|
||||
ReadbackManagerD3D10 *readbackManager();
|
||||
|
||||
void SetViewport(const nsIntSize &aViewport);
|
||||
const nsIntSize &GetViewport() { return mViewport; }
|
||||
|
||||
|
@ -156,6 +162,7 @@ private:
|
|||
void SetupPipeline();
|
||||
void UpdateRenderTarget();
|
||||
void VerifyBufferSize();
|
||||
void EnsureReadbackManager();
|
||||
|
||||
void Render();
|
||||
|
||||
|
@ -164,6 +171,7 @@ private:
|
|||
nsRefPtr<ID3D10Effect> mEffect;
|
||||
nsRefPtr<ID3D10InputLayout> mInputLayout;
|
||||
nsRefPtr<ID3D10Buffer> mVertexBuffer;
|
||||
nsRefPtr<ReadbackManagerD3D10> mReadbackManager;
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> mRTView;
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* 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 GFX_READBACKLAYERD3D10_H
|
||||
#define GFX_READBACKLAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class THEBES_API ReadbackLayerD3D10 :
|
||||
public ReadbackLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ReadbackLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ReadbackLayer(aManager, NULL),
|
||||
LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer() {}
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_READBACKLAYERD3D10_H */
|
|
@ -0,0 +1,250 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* 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 "ReadbackManagerD3D10.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// Structure that contains the information required to execute a readback task,
|
||||
// the only member accessed off the main thread here is mReadbackTexture. Since
|
||||
// mLayer may be released only on the main thread this object should always be
|
||||
// destroyed on the main thread!
|
||||
struct ReadbackTask {
|
||||
// The texture that we copied the contents of the thebeslayer to.
|
||||
nsRefPtr<ID3D10Texture2D> mReadbackTexture;
|
||||
// This exists purely to keep the ReadbackLayer alive for the lifetime of
|
||||
// mUpdate. Note that this addref and release should occur -solely- on the
|
||||
// main thread.
|
||||
nsRefPtr<ReadbackLayer> mLayer;
|
||||
ReadbackProcessor::Update mUpdate;
|
||||
// The origin in ThebesLayer coordinates of mReadbackTexture.
|
||||
gfxPoint mOrigin;
|
||||
// mLayer->GetBackgroundOffset() when the task is created. We have
|
||||
// to save this in the ReadbackTask because it might change before
|
||||
// the update is delivered to the readback sink.
|
||||
nsIntPoint mBackgroundOffset;
|
||||
};
|
||||
|
||||
// This class is created and dispatched from the Readback thread but it must be
|
||||
// destroyed by the main thread.
|
||||
class ReadbackResultWriter : public nsIRunnable
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
public:
|
||||
ReadbackResultWriter(ReadbackTask *aTask) : mTask(aTask) {}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
ReadbackProcessor::Update *update = &mTask->mUpdate;
|
||||
|
||||
if (!update->mLayer->GetSink()) {
|
||||
// This can happen when a plugin is destroyed.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIntPoint offset = mTask->mBackgroundOffset;
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
mTask->mReadbackTexture->GetDesc(&desc);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
// We know this map will immediately succeed, as we've already mapped this
|
||||
// copied data on our task thread.
|
||||
HRESULT hr = mTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// If this fails we're never going to get our ThebesLayer content.
|
||||
update->mLayer->GetSink()->SetUnknown(update->mSequenceCounter);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> sourceSurface =
|
||||
new gfxImageSurface((unsigned char*)mappedTex.pData,
|
||||
gfxIntSize(desc.Width, desc.Height),
|
||||
mappedTex.RowPitch,
|
||||
gfxASurface::ImageFormatRGB24);
|
||||
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update->mLayer->GetSink()->BeginUpdate(update->mUpdateRect + offset,
|
||||
update->mSequenceCounter);
|
||||
|
||||
if (ctx) {
|
||||
ctx->Translate(gfxPoint(offset.x, offset.y));
|
||||
ctx->SetSource(sourceSurface, gfxPoint(mTask->mOrigin.x,
|
||||
mTask->mOrigin.y));
|
||||
ctx->Paint();
|
||||
|
||||
update->mLayer->GetSink()->EndUpdate(ctx, update->mUpdateRect + offset);
|
||||
}
|
||||
|
||||
mTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<ReadbackTask> mTask;
|
||||
};
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(ReadbackResultWriter, nsIRunnable)
|
||||
|
||||
DWORD WINAPI StartTaskThread(void *aManager)
|
||||
{
|
||||
static_cast<ReadbackManagerD3D10*>(aManager)->ProcessTasks();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10::ReadbackManagerD3D10()
|
||||
: mRefCnt(0)
|
||||
{
|
||||
::InitializeCriticalSection(&mTaskMutex);
|
||||
mShutdownEvent = ::CreateEventA(NULL, FALSE, FALSE, "ReadbackShutdownEvent");
|
||||
mTaskSemaphore = ::CreateSemaphoreA(NULL, 0, 1000000, "ReadbackTaskSemaphore");
|
||||
mTaskThread = ::CreateThread(NULL, 0, StartTaskThread, this, 0, 0);
|
||||
}
|
||||
|
||||
ReadbackManagerD3D10::~ReadbackManagerD3D10()
|
||||
{
|
||||
::SetEvent(mShutdownEvent);
|
||||
|
||||
// This shouldn't take longer than 5 seconds, if it does we're going to choose
|
||||
// to leak the thread and its synchronisation in favor of crashing or freezing
|
||||
DWORD result = ::WaitForSingleObject(mTaskThread, 5000);
|
||||
if (result != WAIT_TIMEOUT) {
|
||||
::DeleteCriticalSection(&mTaskMutex);
|
||||
::CloseHandle(mShutdownEvent);
|
||||
::CloseHandle(mTaskSemaphore);
|
||||
::CloseHandle(mTaskThread);
|
||||
} else {
|
||||
NS_WARNING("ReadbackManager: Task thread did not shutdown in 5 seconds. Leaking.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D10::PostTask(ID3D10Texture2D *aTexture, void *aUpdate, const gfxPoint &aOrigin)
|
||||
{
|
||||
ReadbackTask *task = new ReadbackTask;
|
||||
task->mReadbackTexture = aTexture;
|
||||
task->mUpdate = *static_cast<ReadbackProcessor::Update*>(aUpdate);
|
||||
task->mOrigin = aOrigin;
|
||||
task->mLayer = task->mUpdate.mLayer;
|
||||
task->mBackgroundOffset = task->mLayer->GetBackgroundLayerOffset();
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
mPendingReadbackTasks.AppendElement(task);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
::ReleaseSemaphore(mTaskSemaphore, 1, NULL);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ReadbackManagerD3D10::QueryInterface(REFIID riid, void **ppvObject)
|
||||
{
|
||||
if (!ppvObject) {
|
||||
return E_POINTER;
|
||||
}
|
||||
|
||||
if (riid == IID_IUnknown) {
|
||||
*ppvObject = this;
|
||||
} else {
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ReadbackManagerD3D10::AddRef()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"ReadbackManagerD3D10 should only be refcounted on main thread.");
|
||||
return ++mRefCnt;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ReadbackManagerD3D10::Release()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"ReadbackManagerD3D10 should only be refcounted on main thread.");
|
||||
ULONG newRefCnt = --mRefCnt;
|
||||
if (!newRefCnt) {
|
||||
mRefCnt++;
|
||||
delete this;
|
||||
}
|
||||
return newRefCnt;
|
||||
}
|
||||
|
||||
void
|
||||
ReadbackManagerD3D10::ProcessTasks()
|
||||
{
|
||||
HANDLE handles[] = { mTaskSemaphore, mShutdownEvent };
|
||||
|
||||
while (true) {
|
||||
DWORD result = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
if (result != WAIT_OBJECT_0) {
|
||||
return;
|
||||
}
|
||||
|
||||
::EnterCriticalSection(&mTaskMutex);
|
||||
ReadbackTask *nextReadbackTask = mPendingReadbackTasks[0].forget();
|
||||
mPendingReadbackTasks.RemoveElementAt(0);
|
||||
::LeaveCriticalSection(&mTaskMutex);
|
||||
|
||||
// We want to block here until the texture contents are available, the
|
||||
// easiest thing is to simply map and unmap.
|
||||
D3D10_MAPPED_TEXTURE2D mappedTex;
|
||||
nextReadbackTask->mReadbackTexture->Map(0, D3D10_MAP_READ, 0, &mappedTex);
|
||||
nextReadbackTask->mReadbackTexture->Unmap(0);
|
||||
|
||||
// We can only send the update to the sink on the main thread, so post an
|
||||
// event there to do so. Ownership of the task is passed from
|
||||
// mPendingReadbackTasks to ReadbackResultWriter here.
|
||||
nsCOMPtr<nsIThread> thread = do_GetMainThread();
|
||||
thread->Dispatch(new ReadbackResultWriter(nextReadbackTask),
|
||||
nsIEventTarget::DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Bas Schouten <bschouten@mozilla.com>
|
||||
*
|
||||
* 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 GFX_READBACKMANAGERD3D10_H
|
||||
#define GFX_READBACKMANAGERD3D10_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d10_1.h>
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "gfxPoint.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
DWORD WINAPI StartTaskThread(void *aManager);
|
||||
|
||||
struct ReadbackTask;
|
||||
|
||||
class ReadbackManagerD3D10 : public IUnknown
|
||||
{
|
||||
public:
|
||||
ReadbackManagerD3D10();
|
||||
~ReadbackManagerD3D10();
|
||||
|
||||
/**
|
||||
* Tell the readback manager to post a readback task.
|
||||
*
|
||||
* @param aTexture D3D10_USAGE_STAGING texture that will contain the data that
|
||||
* was readback.
|
||||
* @param aUpdate ReadbackProcessor::Update object. This is a void pointer
|
||||
* since we cannot forward declare a nested class, and do not
|
||||
* export ReadbackProcessor.h
|
||||
* @param aOrigin Origin of the aTexture surface in the ThebesLayer
|
||||
* coordinate system.
|
||||
*/
|
||||
void PostTask(ID3D10Texture2D *aTexture, void *aUpdate, const gfxPoint &aOrigin);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
|
||||
void **ppvObject);
|
||||
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
virtual ULONG STDMETHODCALLTYPE Release(void);
|
||||
|
||||
private:
|
||||
friend DWORD WINAPI StartTaskThread(void *aManager);
|
||||
|
||||
void ProcessTasks();
|
||||
|
||||
// The invariant maintained by |mTaskSemaphore| is that the readback thread
|
||||
// will awaken from WaitForMultipleObjects() at least once per readback
|
||||
// task enqueued by the main thread. Since the readback thread processes
|
||||
// exactly one task per wakeup (with one exception), no tasks are lost. The
|
||||
// exception is when the readback thread is shut down, which orphans the
|
||||
// remaining tasks, on purpose.
|
||||
HANDLE mTaskSemaphore;
|
||||
// Event signaled when the task thread should shutdown
|
||||
HANDLE mShutdownEvent;
|
||||
// Handle to the task thread
|
||||
HANDLE mTaskThread;
|
||||
|
||||
// FiFo list of readback tasks that are to be executed. Access is synchronized
|
||||
// by mTaskMutex.
|
||||
CRITICAL_SECTION mTaskMutex;
|
||||
nsTArray<nsAutoPtr<ReadbackTask>> mPendingReadbackTasks;
|
||||
|
||||
ULONG mRefCnt;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GFX_READBACKMANAGERD3D10_H */
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include "gfxTeeSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "ReadbackLayer.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -168,7 +170,7 @@ ThebesLayerD3D10::RenderLayer()
|
|||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::Validate()
|
||||
ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback)
|
||||
{
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
|
@ -191,6 +193,12 @@ ThebesLayerD3D10::Validate()
|
|||
mTextureOnWhite = nsnull;
|
||||
}
|
||||
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
nsIntRegion readbackRegion;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
if (mTexture) {
|
||||
|
@ -264,6 +272,23 @@ ThebesLayerD3D10::Validate()
|
|||
|
||||
DrawRegion(region, mode);
|
||||
|
||||
if (readbackUpdates.Length() > 0) {
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
visibleRect.width, visibleRect.height,
|
||||
1, 1, 0, D3D10_USAGE_STAGING,
|
||||
D3D10_CPU_ACCESS_READ);
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> readbackTexture;
|
||||
device()->CreateTexture2D(&desc, NULL, getter_AddRefs(readbackTexture));
|
||||
device()->CopyResource(readbackTexture, mTexture);
|
||||
|
||||
for (int i = 0; i < readbackUpdates.Length(); i++) {
|
||||
mD3DManager->readbackManager()->PostTask(readbackTexture,
|
||||
&readbackUpdates[i],
|
||||
gfxPoint(visibleRect.x, visibleRect.y));
|
||||
}
|
||||
}
|
||||
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,13 +51,15 @@ public:
|
|||
ThebesLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
virtual ~ThebesLayerD3D10();
|
||||
|
||||
void Validate(ReadbackProcessor *aReadback);
|
||||
|
||||
/* ThebesLayer implementation */
|
||||
void InvalidateRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer();
|
||||
virtual void Validate();
|
||||
virtual void Validate() { Validate(nsnull); }
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
private:
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef GFX_CANVASLAYEROGL_H
|
||||
#define GFX_CANVASLAYEROGL_H
|
||||
#ifndef GFX_CANVASLAYERD3D9_H
|
||||
#define GFX_CANVASLAYERD3D9_H
|
||||
|
||||
#include "LayerManagerD3D9.h"
|
||||
#include "GLContext.h"
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
#include "ContainerLayerD3D9.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsRect.h"
|
||||
#include "ThebesLayerD3D9.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -71,6 +73,7 @@ ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
|
|||
mLastChild = aChild;
|
||||
}
|
||||
NS_ADDREF(aChild);
|
||||
DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
for (Layer *child = GetFirstChild();
|
||||
|
@ -86,6 +89,7 @@ ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
|
|||
}
|
||||
aChild->SetPrevSibling(child);
|
||||
NS_ADDREF(aChild);
|
||||
DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +109,7 @@ ContainerLayerD3D9::RemoveChild(Layer *aChild)
|
|||
aChild->SetNextSibling(nsnull);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
aChild->SetParent(nsnull);
|
||||
DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
@ -122,6 +127,7 @@ ContainerLayerD3D9::RemoveChild(Layer *aChild)
|
|||
child->SetNextSibling(nsnull);
|
||||
child->SetPrevSibling(nsnull);
|
||||
child->SetParent(nsnull);
|
||||
DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
@ -175,6 +181,9 @@ ContainerLayerD3D9::RenderLayer()
|
|||
|
||||
device()->GetScissorRect(&containerClipRect);
|
||||
|
||||
ReadbackProcessor readback;
|
||||
readback.BuildUpdates(this);
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
PRBool useIntermediate = UseIntermediateSurface();
|
||||
|
||||
|
@ -315,7 +324,11 @@ ContainerLayerD3D9::RenderLayer()
|
|||
device()->SetScissorRect(&r);
|
||||
}
|
||||
|
||||
layerToRender->RenderLayer();
|
||||
if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) {
|
||||
static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback);
|
||||
} else {
|
||||
layerToRender->RenderLayer();
|
||||
}
|
||||
|
||||
if (clipRect && !useIntermediate) {
|
||||
// In this situation we've set a new scissor rect and we will continue
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "ImageLayerD3D9.h"
|
||||
#include "ColorLayerD3D9.h"
|
||||
#include "CanvasLayerD3D9.h"
|
||||
#include "ReadbackLayerD3D9.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "nsIGfxInfo.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
@ -228,6 +229,13 @@ LayerManagerD3D9::CreateCanvasLayer()
|
|||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ReadbackLayer>
|
||||
LayerManagerD3D9::CreateReadbackLayer()
|
||||
{
|
||||
nsRefPtr<ReadbackLayer> layer = new ReadbackLayerD3D9(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageContainer>
|
||||
LayerManagerD3D9::CreateImageContainer()
|
||||
{
|
||||
|
|
|
@ -149,6 +149,8 @@ public:
|
|||
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
|
||||
|
||||
virtual already_AddRefed<ReadbackLayer> CreateReadbackLayer();
|
||||
|
||||
virtual already_AddRefed<ImageContainer> CreateImageContainer();
|
||||
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* ***** 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 Corporation code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert O'Callahan <rocallahan@mozilla.com>
|
||||
*
|
||||
* 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 GFX_READBACKLAYERD3D9_H
|
||||
#define GFX_READBACKLAYERD3D9_H
|
||||
|
||||
#include "LayerManagerD3D9.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class THEBES_API ReadbackLayerD3D9 :
|
||||
public ReadbackLayer,
|
||||
public LayerD3D9
|
||||
{
|
||||
public:
|
||||
ReadbackLayerD3D9(LayerManagerD3D9 *aManager)
|
||||
: ReadbackLayer(aManager, NULL),
|
||||
LayerD3D9(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D9*>(this);
|
||||
}
|
||||
|
||||
virtual Layer* GetLayer() { return this; }
|
||||
virtual void RenderLayer() {}
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_READBACKLAYERD3D9_H */
|
|
@ -41,6 +41,7 @@
|
|||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxTeeSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -201,7 +202,7 @@ ThebesLayerD3D9::RenderVisibleRegion()
|
|||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::RenderLayer()
|
||||
ThebesLayerD3D9::RenderThebesLayer(ReadbackProcessor* aReadback)
|
||||
{
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
|
@ -219,22 +220,30 @@ ThebesLayerD3D9::RenderLayer()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!mValidRegion.IsEqual(mVisibleRegion)) {
|
||||
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
||||
nsIntRegion readbackRegion;
|
||||
if (aReadback && UsedForReadback()) {
|
||||
aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion);
|
||||
}
|
||||
|
||||
// Because updates to D3D9 ThebesLayers are rendered with the CPU, we don't
|
||||
// have to do readback from D3D9 surfaces. Instead we make sure that any area
|
||||
// needed for readback is included in the drawRegion we ask layout to render.
|
||||
// Then the readback areas we need can be copied out of the temporary
|
||||
// destinationSurface in DrawRegion.
|
||||
nsIntRegion drawRegion;
|
||||
drawRegion.Sub(mVisibleRegion, mValidRegion);
|
||||
drawRegion.Or(drawRegion, readbackRegion);
|
||||
// NS_ASSERTION(mVisibleRegion.Contains(region), "Bad readback region!");
|
||||
|
||||
if (!drawRegion.IsEmpty()) {
|
||||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
if (!cbInfo.Callback) {
|
||||
NS_ERROR("D3D9 should never need to update ThebesLayers in an empty transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
/* We use the bounds of the visible region because we draw the bounds of
|
||||
* this region when we draw this entire texture. We have to make sure that
|
||||
* the areas that aren't filled with content get their background drawn.
|
||||
* This is an issue for opaque surfaces, which otherwise won't get their
|
||||
* background painted.
|
||||
*/
|
||||
nsIntRegion region;
|
||||
region.Sub(mVisibleRegion, mValidRegion);
|
||||
DrawRegion(region, mode);
|
||||
DrawRegion(drawRegion, mode, readbackUpdates);
|
||||
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
|
@ -407,7 +416,8 @@ FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
|
|||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
|
||||
ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
const nsTArray<ReadbackProcessor::Update>& aReadbackUpdates)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
@ -480,6 +490,22 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
|
|||
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
|
||||
for (PRUint32 i = 0; i < aReadbackUpdates.Length(); ++i) {
|
||||
NS_ASSERTION(aMode == SURFACE_OPAQUE,
|
||||
"Transparent surfaces should not be used for readback");
|
||||
const ReadbackProcessor::Update& update = aReadbackUpdates[i];
|
||||
nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
|
||||
nsRefPtr<gfxContext> ctx =
|
||||
update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
|
||||
update.mSequenceCounter);
|
||||
if (ctx) {
|
||||
ctx->Translate(gfxPoint(offset.x, offset.y));
|
||||
ctx->SetSource(destinationSurface, gfxPoint(bounds.x, bounds.y));
|
||||
ctx->Paint();
|
||||
update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoTArray<IDirect3DTexture9*,2> srcTextures;
|
||||
nsAutoTArray<IDirect3DTexture9*,2> destTextures;
|
||||
switch (aMode)
|
||||
|
|
|
@ -41,10 +41,13 @@
|
|||
#include "Layers.h"
|
||||
#include "LayerManagerD3D9.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "ReadbackProcessor.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ReadbackProcessor;
|
||||
|
||||
class ThebesLayerD3D9 : public ThebesLayer,
|
||||
public LayerD3D9
|
||||
{
|
||||
|
@ -58,10 +61,12 @@ public:
|
|||
/* LayerD3D9 implementation */
|
||||
Layer* GetLayer();
|
||||
virtual PRBool IsEmpty();
|
||||
virtual void RenderLayer();
|
||||
virtual void RenderLayer() { RenderThebesLayer(nsnull); }
|
||||
virtual void CleanResources();
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
void RenderThebesLayer(ReadbackProcessor* aReadback);
|
||||
|
||||
private:
|
||||
/*
|
||||
* D3D9 texture
|
||||
|
@ -96,7 +101,8 @@ private:
|
|||
void RenderVisibleRegion();
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode);
|
||||
void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode,
|
||||
const nsTArray<ReadbackProcessor::Update>& aReadbackUpdates);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
|
||||
|
|
|
@ -57,6 +57,7 @@ ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter)
|
|||
aContainer->mLastChild = aChild;
|
||||
}
|
||||
NS_ADDREF(aChild);
|
||||
aContainer->DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
for (Layer *child = aContainer->GetFirstChild();
|
||||
|
@ -72,6 +73,7 @@ ContainerInsertAfter(Container* aContainer, Layer* aChild, Layer* aAfter)
|
|||
}
|
||||
aChild->SetPrevSibling(child);
|
||||
NS_ADDREF(aChild);
|
||||
aContainer->DidInsertChild(aChild);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -92,6 +94,7 @@ ContainerRemoveChild(Container* aContainer, Layer* aChild)
|
|||
aChild->SetNextSibling(nsnull);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
aChild->SetParent(nsnull);
|
||||
aContainer->DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
@ -109,6 +112,7 @@ ContainerRemoveChild(Container* aContainer, Layer* aChild)
|
|||
child->SetNextSibling(nsnull);
|
||||
child->SetPrevSibling(nsnull);
|
||||
child->SetParent(nsnull);
|
||||
aContainer->DidRemoveChild(aChild);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "gfxContext.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class THEBES_API gfxAlphaRecovery {
|
||||
public:
|
||||
|
@ -51,6 +52,16 @@ public:
|
|||
gfxFloat r, g, b;
|
||||
};
|
||||
|
||||
/**
|
||||
* Some SIMD fast-paths only can be taken if the relative
|
||||
* byte-alignment of images' pointers and strides meets certain
|
||||
* criteria. Aligning image pointers and strides by
|
||||
* |GoodAlignmentLog2()| below will ensure that fast-paths aren't
|
||||
* skipped because of misalignment. Fast-paths may still be taken
|
||||
* even if GoodAlignmentLog2() is not met, in some conditions.
|
||||
*/
|
||||
static PRUint32 GoodAlignmentLog2() { return 4; /* for SSE2 */ }
|
||||
|
||||
/* Given two surfaces of equal size with the same rendering, one onto a
|
||||
* black background and the other onto white, recovers alpha values from
|
||||
* the difference and sets the alpha values on the black surface.
|
||||
|
@ -62,12 +73,30 @@ public:
|
|||
Analysis *analysis = nsnull);
|
||||
|
||||
#ifdef MOZILLA_MAY_SUPPORT_SSE2
|
||||
/* This does the save as the previous function, but uses SSE2
|
||||
/* This does the same as the previous function, but uses SSE2
|
||||
* optimizations. Usually this should not be called directly. Be sure to
|
||||
* check mozilla::supports_sse2() before calling this function.
|
||||
*/
|
||||
static PRBool RecoverAlphaSSE2 (gfxImageSurface *blackSurface,
|
||||
const gfxImageSurface *whiteSurface);
|
||||
|
||||
/**
|
||||
* A common use-case for alpha recovery is to paint into a
|
||||
* temporary "white image", then paint onto a subrect of the
|
||||
* surface, the "black image", into which alpha-recovered pixels
|
||||
* are eventually to be written. This function returns a rect
|
||||
* aligned so that recovering alpha for that rect will hit SIMD
|
||||
* fast-paths, if possible. It's not always possible to align
|
||||
* |aRect| so that fast-paths will be taken.
|
||||
*
|
||||
* The returned rect is always a superset of |aRect|.
|
||||
*/
|
||||
static nsIntRect AlignRectForSubimageRecovery(const nsIntRect& aRect,
|
||||
gfxImageSurface* aSurface);
|
||||
#else
|
||||
static nsIntRect AlignRectForSubimageRecovery(const nsIntRect& aRect,
|
||||
gfxImageSurface*)
|
||||
{ return aRect; }
|
||||
#endif
|
||||
|
||||
/** from cairo-xlib-utils.c, modified */
|
||||
|
|
|
@ -160,3 +160,99 @@ gfxAlphaRecovery::RecoverAlphaSSE2(gfxImageSurface* blackSurf,
|
|||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
ByteAlignment(PRInt32 aAlignToLog2, PRInt32 aX, PRInt32 aY=0, PRInt32 aStride=1)
|
||||
{
|
||||
return (aX + aStride * aY) & ((1 << aAlignToLog2) - 1);
|
||||
}
|
||||
|
||||
/*static*/ nsIntRect
|
||||
gfxAlphaRecovery::AlignRectForSubimageRecovery(const nsIntRect& aRect,
|
||||
gfxImageSurface* aSurface)
|
||||
{
|
||||
NS_ASSERTION(gfxASurface::ImageFormatARGB32 == aSurface->Format(),
|
||||
"Thebes grew support for non-ARGB32 COLOR_ALPHA?");
|
||||
static const PRInt32 kByteAlignLog2 = GoodAlignmentLog2();
|
||||
static const PRInt32 bpp = 4;
|
||||
static const PRInt32 pixPerAlign = (1 << kByteAlignLog2) / bpp;
|
||||
//
|
||||
// We're going to create a subimage of the surface with size
|
||||
// <sw,sh> for alpha recovery, and want a SIMD fast-path. The
|
||||
// rect <x,y, w,h> /needs/ to be redrawn, but it might not be
|
||||
// properly aligned for SIMD. So we want to find a rect <x',y',
|
||||
// w',h'> that's a superset of what needs to be redrawn but is
|
||||
// properly aligned. Proper alignment is
|
||||
//
|
||||
// BPP * (x' + y' * sw) \cong 0 (mod ALIGN)
|
||||
// BPP * w' \cong BPP * sw (mod ALIGN)
|
||||
//
|
||||
// (We assume the pixel at surface <0,0> is already ALIGN'd.)
|
||||
// That rect (obviously) has to fit within the surface bounds, and
|
||||
// we should also minimize the extra pixels redrawn only for
|
||||
// alignment's sake. So we also want
|
||||
//
|
||||
// minimize <x',y', w',h'>
|
||||
// 0 <= x' <= x
|
||||
// 0 <= y' <= y
|
||||
// w <= w' <= sw
|
||||
// h <= h' <= sh
|
||||
//
|
||||
// This is a messy integer non-linear programming problem, except
|
||||
// ... we can assume that ALIGN/BPP is a very small constant. So,
|
||||
// brute force is viable. The algorithm below will find a
|
||||
// solution if one exists, but isn't guaranteed to find the
|
||||
// minimum solution. (For SSE2, ALIGN/BPP = 4, so it'll do at
|
||||
// most 64 iterations below). In what's likely the common case,
|
||||
// an already-aligned rectangle, it only needs 1 iteration.
|
||||
//
|
||||
// Is this alignment worth doing? Recovering alpha will take work
|
||||
// proportional to w*h (assuming alpha recovery computation isn't
|
||||
// memory bound). This analysis can lead to O(w+h) extra work
|
||||
// (with small constants). In exchange, we expect to shave off a
|
||||
// ALIGN/BPP constant by using SIMD-ized alpha recovery. So as
|
||||
// w*h diverges from w+h, the win factor approaches ALIGN/BPP. We
|
||||
// only really care about the w*h >> w+h case anyway; others
|
||||
// should be fast enough even with the overhead. (Unless the cost
|
||||
// of repainting the expanded rect is high, but in that case
|
||||
// SIMD-ized alpha recovery won't make a difference so this code
|
||||
// shouldn't be called.)
|
||||
//
|
||||
gfxIntSize surfaceSize = aSurface->GetSize();
|
||||
const PRInt32 stride = bpp * surfaceSize.width;
|
||||
if (stride != aSurface->Stride()) {
|
||||
NS_WARNING("Unexpected stride, falling back on slow alpha recovery");
|
||||
return aRect;
|
||||
}
|
||||
|
||||
const PRInt32 x = aRect.x, y = aRect.y, w = aRect.width, h = aRect.height;
|
||||
const PRInt32 sw = surfaceSize.width, sh = surfaceSize.height;
|
||||
const PRInt32 strideAlign = ByteAlignment(kByteAlignLog2, stride);
|
||||
|
||||
PRInt32 dx, dy, dw;
|
||||
// The outer two loops search for an aligned top-left pixel
|
||||
for (dy = 0; (dy < pixPerAlign) && (y - dy >= 0) && (h + dy <= sh); ++dy) {
|
||||
for (dx = 0; (dx < pixPerAlign) && (x - dx >= 0); ++dx) {
|
||||
if (0 != ByteAlignment(kByteAlignLog2,
|
||||
bpp * (x - dx), y - dy, stride)) {
|
||||
continue;
|
||||
}
|
||||
// The inner searches for an aligned stride
|
||||
for (dw = 0; (dw < pixPerAlign) && (w + dw + dx <= sw); ++dw) {
|
||||
if (strideAlign == ByteAlignment(kByteAlignLog2,
|
||||
bpp * (w + dw + dx))) {
|
||||
goto FOUND_SOLUTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find a solution.
|
||||
return aRect;
|
||||
|
||||
FOUND_SOLUTION:
|
||||
nsIntRect solution = nsIntRect(x - dx, y - dy, w + dw + dx, h + dy);
|
||||
NS_ABORT_IF_FALSE(nsIntRect(0,0, sw,sh).Contains(solution),
|
||||
"'Solution' extends outside surface bounds!");
|
||||
return solution;
|
||||
}
|
||||
|
|
|
@ -243,6 +243,10 @@ struct THEBES_API gfxRGBA {
|
|||
{
|
||||
return r == other.r && g == other.g && b == other.b && a == other.a;
|
||||
}
|
||||
bool operator!=(const gfxRGBA& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this color value as a packed 32-bit integer. This reconstructs
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "prmem.h"
|
||||
|
||||
#include "gfxAlphaRecovery.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
#include "cairo.h"
|
||||
|
@ -96,6 +97,24 @@ gfxImageSurface::InitWithData(unsigned char *aData, const gfxIntSize& aSize,
|
|||
Init(surface);
|
||||
}
|
||||
|
||||
static void*
|
||||
TryAllocAlignedBytes(size_t aSize)
|
||||
{
|
||||
// Use fallible allocators here
|
||||
#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_JEMALLOC_POSIX_MEMALIGN)
|
||||
void* ptr;
|
||||
// Try to align for fast alpha recovery. This should only help
|
||||
// cairo too, can't hurt.
|
||||
return moz_posix_memalign(&ptr,
|
||||
1 << gfxAlphaRecovery::GoodAlignmentLog2(),
|
||||
aSize) ?
|
||||
nsnull : ptr;
|
||||
#else
|
||||
// Oh well, hope that luck is with us in the allocator
|
||||
return moz_malloc(aSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
gfxImageSurface::gfxImageSurface(const gfxIntSize& size, gfxImageFormat format) :
|
||||
mSize(size), mOwnsData(PR_FALSE), mData(nsnull), mFormat(format)
|
||||
{
|
||||
|
@ -107,8 +126,9 @@ gfxImageSurface::gfxImageSurface(const gfxIntSize& size, gfxImageFormat format)
|
|||
// if we have a zero-sized surface, just leave mData nsnull
|
||||
if (mSize.height * mStride > 0) {
|
||||
|
||||
// Use the fallible allocator here
|
||||
mData = (unsigned char *) moz_malloc(mSize.height * mStride);
|
||||
// This can fail to allocate memory aligned as we requested,
|
||||
// or it can fail to allocate any memory at all.
|
||||
mData = (unsigned char *) TryAllocAlignedBytes(mSize.height * mStride);
|
||||
if (!mData)
|
||||
return;
|
||||
memset(mData, 0, mSize.height * mStride);
|
||||
|
|
|
@ -60,6 +60,13 @@ struct THEBES_API gfxIntSize {
|
|||
int operator!=(const gfxIntSize& s) const {
|
||||
return ((width != s.width) || (height != s.height));
|
||||
}
|
||||
bool operator<(const gfxIntSize& s) const {
|
||||
return (operator<=(s) &&
|
||||
(width < s.width || height < s.height));
|
||||
}
|
||||
bool operator<=(const gfxIntSize& s) const {
|
||||
return (width <= s.width) && (height <= s.height);
|
||||
}
|
||||
gfxIntSize operator+(const gfxIntSize& s) const {
|
||||
return gfxIntSize(width + s.width, height + s.height);
|
||||
}
|
||||
|
|
|
@ -323,11 +323,18 @@ mozJSSubScriptLoader::LoadSubScript (const PRUnichar * aURL
|
|||
tmp.Append(uriStr);
|
||||
|
||||
uriStr = tmp;
|
||||
}
|
||||
|
||||
rv = NS_OpenURI(getter_AddRefs(instream), uri, serv,
|
||||
nsnull, nsnull, nsIRequest::LOAD_NORMAL,
|
||||
getter_AddRefs(chan));
|
||||
}
|
||||
|
||||
// Instead of calling NS_OpenURI, we create the channel ourselves and call
|
||||
// SetContentType, to avoid expensive MIME type lookups (bug 632490).
|
||||
rv = NS_NewChannel(getter_AddRefs(chan), uri, serv,
|
||||
nsnull, nsnull, nsIRequest::LOAD_NORMAL);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
chan->SetContentType(NS_LITERAL_CSTRING("application/javascript"));
|
||||
rv = chan->Open(getter_AddRefs(instream));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
errmsg = JS_NewStringCopyZ (cx, LOAD_ERROR_NOSTREAM);
|
||||
|
|
|
@ -78,6 +78,7 @@ enum Type {
|
|||
TYPE_PAGE_CONTENT,
|
||||
TYPE_PAGE_SEQUENCE,
|
||||
TYPE_PLUGIN,
|
||||
TYPE_PLUGIN_READBACK,
|
||||
TYPE_PRINT_PREVIEW_BACKGROUND,
|
||||
TYPE_PRINT_PLUGIN,
|
||||
TYPE_REMOTE,
|
||||
|
|
|
@ -375,7 +375,7 @@ nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
|
|||
r.And(*aVisibleRegion, GetBounds(aBuilder));
|
||||
PRBool notUsed;
|
||||
return ComputeVisibilityForSublist(aBuilder, aVisibleRegion,
|
||||
r.GetBounds(), notUsed);
|
||||
r.GetBounds(), r.GetBounds(), notUsed);
|
||||
}
|
||||
|
||||
static nsRegion
|
||||
|
@ -397,6 +397,7 @@ PRBool
|
|||
nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aListVisibleBounds,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
#ifdef DEBUG
|
||||
nsRegion r;
|
||||
|
@ -429,7 +430,7 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
|||
item->mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
PRBool containsRootContentDocBG = PR_FALSE;
|
||||
if (item->ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion,
|
||||
containsRootContentDocBG)) {
|
||||
if (containsRootContentDocBG) {
|
||||
aContainsRootContentDocBG = PR_TRUE;
|
||||
|
@ -744,8 +745,11 @@ PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
itemVisible.And(*aVisibleRegion, bounds);
|
||||
mVisibleRect = itemVisible.GetBounds();
|
||||
|
||||
// When we recompute visibility within layers we don't need to
|
||||
// expand the visible region for content behind plugins (the plugin
|
||||
// is not in the layer).
|
||||
PRBool notUsed;
|
||||
if (!ComputeVisibility(aBuilder, aVisibleRegion, notUsed))
|
||||
if (!ComputeVisibility(aBuilder, aVisibleRegion, nsRect(), notUsed))
|
||||
return PR_FALSE;
|
||||
|
||||
PRBool forceTransparentBackground;
|
||||
|
@ -763,9 +767,11 @@ void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplaySolidColor::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
PRBool retval = nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
if (retval && IsRootContentDocBackground()) {
|
||||
aContainsRootContentDocBG = PR_TRUE;
|
||||
|
@ -923,9 +929,11 @@ nsDisplayBackground::HitTest(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -1198,8 +1206,10 @@ nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -1243,8 +1253,10 @@ nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -1342,8 +1354,10 @@ nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
|
|||
PRBool
|
||||
nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -1388,8 +1402,10 @@ nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -1429,9 +1445,11 @@ nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) {
|
|||
PRBool
|
||||
nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
return mList.ComputeVisibilityForSublist(aBuilder, aVisibleRegion,
|
||||
mVisibleRect,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
}
|
||||
|
||||
|
@ -1618,6 +1636,7 @@ nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
PRBool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
// Our children are translucent so we should not allow them to subtract
|
||||
// area from aVisibleRegion. We do need to find out what is visible under
|
||||
|
@ -1630,9 +1649,11 @@ PRBool nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
// do not pass up the aContainsRootContentDocBG value because anything under
|
||||
// us is not opaque
|
||||
PRBool notUsed;
|
||||
nsRect allowExpansion;
|
||||
allowExpansion.IntersectRect(bounds, aAllowVisibleRegionExpansion);
|
||||
return
|
||||
nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren,
|
||||
notUsed);
|
||||
allowExpansion, notUsed);
|
||||
}
|
||||
|
||||
PRBool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
|
||||
|
@ -1708,6 +1729,7 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
|
@ -1722,14 +1744,17 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
nsRect boundedRect;
|
||||
boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));
|
||||
nsRect allowExpansion;
|
||||
allowExpansion.IntersectRect(allowExpansion, boundedRect);
|
||||
PRBool visible = mList.ComputeVisibilityForSublist(
|
||||
aBuilder, &childVisibleRegion, boundedRect, aContainsRootContentDocBG);
|
||||
aBuilder, &childVisibleRegion, boundedRect, allowExpansion, aContainsRootContentDocBG);
|
||||
mVisibleRect = boundedRect;
|
||||
|
||||
return visible;
|
||||
|
||||
} else {
|
||||
return nsDisplayOwnLayer::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
}
|
||||
}
|
||||
|
@ -1780,13 +1805,17 @@ void nsDisplayClip::Paint(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
PRBool nsDisplayClip::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
nsRegion clipped;
|
||||
clipped.And(*aVisibleRegion, mClip);
|
||||
|
||||
nsRegion finalClipped(clipped);
|
||||
nsRect allowExpansion;
|
||||
allowExpansion.IntersectRect(mClip, aAllowVisibleRegionExpansion);
|
||||
PRBool anyVisible =
|
||||
nsDisplayWrapList::ComputeVisibility(aBuilder, &finalClipped,
|
||||
allowExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
|
||||
nsRegion removed;
|
||||
|
@ -1880,13 +1909,14 @@ nsDisplayClipRoundedRect::WrapWithClone(nsDisplayListBuilder* aBuilder,
|
|||
PRBool nsDisplayClipRoundedRect::ComputeVisibility(
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
nsRegion clipped;
|
||||
clipped.And(*aVisibleRegion, mClip);
|
||||
|
||||
PRBool notUsed;
|
||||
return nsDisplayWrapList::ComputeVisibility(aBuilder, &clipped, notUsed);
|
||||
return nsDisplayWrapList::ComputeVisibility(aBuilder, &clipped, nsRect(), notUsed);
|
||||
// FIXME: Remove a *conservative* opaque region from aVisibleRegion
|
||||
// (like in nsDisplayClip::ComputeVisibility).
|
||||
}
|
||||
|
@ -1949,6 +1979,7 @@ void nsDisplayZoom::Paint(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
PRBool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
||||
nsRegion *aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
// Convert the passed in visible region to our appunits.
|
||||
|
@ -1958,9 +1989,12 @@ PRBool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
|||
|
||||
nsRect transformedVisibleRect =
|
||||
mVisibleRect.ConvertAppUnitsRoundOut(mParentAPD, mAPD);
|
||||
nsRect allowExpansion =
|
||||
aAllowVisibleRegionExpansion.ConvertAppUnitsRoundIn(mParentAPD, mAPD);
|
||||
PRBool retval =
|
||||
mList.ComputeVisibilityForSublist(aBuilder, &visibleRegion,
|
||||
transformedVisibleRect,
|
||||
allowExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
|
||||
nsRegion removed;
|
||||
|
@ -2158,6 +2192,7 @@ nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
PRBool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
||||
nsRegion *aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
/* As we do this, we need to be sure to
|
||||
|
@ -2440,6 +2475,7 @@ void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
PRBool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG) {
|
||||
nsPoint offset = aBuilder->ToReferenceFrame(mEffectsFrame);
|
||||
nsRect dirtyRect =
|
||||
|
@ -2453,7 +2489,7 @@ PRBool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
|||
nsRect r;
|
||||
r.IntersectRect(dirtyRect, mList.GetBounds(aBuilder));
|
||||
PRBool notUsed;
|
||||
mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r, notUsed);
|
||||
mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r, nsRect(), notUsed);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -705,13 +705,17 @@ public:
|
|||
* this item to the intersection of *aVisibleRegion and this item's bounds.
|
||||
* We rely on that, so this should only be called by
|
||||
* nsDisplayList::ComputeVisibility or nsDisplayItem::RecomputeVisibility.
|
||||
*
|
||||
* aAllowVisibleRegionExpansion is a rect where we are allowed to
|
||||
* expand the visible region and is only used for making sure the
|
||||
* background behind a plugin is visible.
|
||||
*
|
||||
* @return PR_TRUE if the item is visible, PR_FALSE if no part of the item
|
||||
* is visible. aContainsRootContentDocBG is set to true if this item contains
|
||||
* the background for the root content document.
|
||||
*/
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{ return !mVisibleRect.IsEmpty(); }
|
||||
|
||||
|
@ -993,6 +997,7 @@ public:
|
|||
PRBool ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aListVisibleBounds,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
/**
|
||||
|
@ -1399,6 +1404,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER)
|
||||
|
||||
|
@ -1457,6 +1463,7 @@ public:
|
|||
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
PRBool IsRootContentDocBackground() {
|
||||
|
@ -1487,6 +1494,7 @@ public:
|
|||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
PRBool* aForceTransparentSurface = nsnull);
|
||||
|
@ -1526,6 +1534,7 @@ public:
|
|||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
NS_DISPLAY_DECL_NAME("BoxShadowOuter", TYPE_BOX_SHADOW_OUTER)
|
||||
|
||||
|
@ -1551,6 +1560,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER)
|
||||
|
||||
|
@ -1577,6 +1587,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE)
|
||||
};
|
||||
|
@ -1639,6 +1650,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
|
||||
NS_WARNING("This list should already have been flattened!!!");
|
||||
|
@ -1724,6 +1736,7 @@ public:
|
|||
LayerManager* aManager);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
|
||||
NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
|
||||
|
@ -1791,6 +1804,7 @@ public:
|
|||
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
private:
|
||||
|
@ -1822,6 +1836,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
|
||||
NS_DISPLAY_DECL_NAME("Clip", TYPE_CLIP)
|
||||
|
@ -1864,6 +1879,7 @@ public:
|
|||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
|
||||
NS_DISPLAY_DECL_NAME("ClipRoundedRect", TYPE_CLIP_ROUNDED_RECT)
|
||||
|
@ -1905,6 +1921,7 @@ public:
|
|||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
NS_DISPLAY_DECL_NAME("Zoom", TYPE_ZOOM)
|
||||
|
||||
|
@ -1940,6 +1957,7 @@ public:
|
|||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
|
||||
NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS)
|
||||
|
@ -2004,6 +2022,7 @@ public:
|
|||
LayerManager* aManager);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
||||
nsRegion *aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
virtual PRBool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
|
||||
|
||||
|
|
|
@ -173,10 +173,12 @@ public:
|
|||
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
PRBool retval = NS_GET_A(mExtraBackgroundColor) > 0 ||
|
||||
nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
if (retval && mFrame->PresContext()->IsRootContentDocument()) {
|
||||
aContainsRootContentDocBG = PR_TRUE;
|
||||
|
|
|
@ -163,6 +163,7 @@ enum { XKeyPress = KeyPress };
|
|||
#include "gfxImageSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "Layers.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
// accessibility support
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -237,6 +238,8 @@ static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
|
|||
#define MAC_CARBON_PLUGINS
|
||||
#endif
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::plugins;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
// special class for handeling DOM context menu events because for
|
||||
|
@ -464,6 +467,13 @@ public:
|
|||
// Return true if we set image with valid surface
|
||||
PRBool SetCurrentImage(ImageContainer* aContainer);
|
||||
|
||||
// Methods to update the background image we send to async plugins.
|
||||
// The eventual target of these operations is PluginInstanceParent,
|
||||
// but it takes several hops to get there.
|
||||
void SetBackgroundUnknown();
|
||||
already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect);
|
||||
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
|
||||
|
||||
PRBool UseLayers()
|
||||
{
|
||||
PRBool useAsyncRendering;
|
||||
|
@ -474,6 +484,7 @@ public:
|
|||
mPluginWindow->type == NPWindowTypeDrawable));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
// return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
|
||||
PRBool IsUpToDate()
|
||||
|
@ -484,6 +495,13 @@ private:
|
|||
mPluginWindow->height);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIPluginInstance_MOZILLA_2_0_BRANCH>
|
||||
GetInstance()
|
||||
{
|
||||
nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = do_QueryInterface(mInstance);
|
||||
return inst.forget();
|
||||
}
|
||||
|
||||
void FixUpURLS(const nsString &name, nsAString &value);
|
||||
|
||||
nsPluginNativeWindow *mPluginWindow;
|
||||
|
@ -606,6 +624,53 @@ private:
|
|||
PRPackedBool mWaitingForPaint;
|
||||
};
|
||||
|
||||
class PluginBackgroundSink : public ReadbackSink {
|
||||
public:
|
||||
PluginBackgroundSink(nsObjectFrame* aFrame, PRUint64 aStartSequenceNumber)
|
||||
: mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
|
||||
~PluginBackgroundSink()
|
||||
{
|
||||
if (mFrame) {
|
||||
mFrame->mBackgroundSink = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetUnknown(PRUint64 aSequenceNumber)
|
||||
{
|
||||
if (!AcceptUpdate(aSequenceNumber))
|
||||
return;
|
||||
mFrame->mInstanceOwner->SetBackgroundUnknown();
|
||||
}
|
||||
|
||||
virtual already_AddRefed<gfxContext>
|
||||
BeginUpdate(const nsIntRect& aRect, PRUint64 aSequenceNumber)
|
||||
{
|
||||
if (!AcceptUpdate(aSequenceNumber))
|
||||
return nsnull;
|
||||
return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
|
||||
}
|
||||
|
||||
virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
|
||||
{
|
||||
return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
|
||||
}
|
||||
|
||||
void Destroy() { mFrame = nsnull; }
|
||||
|
||||
protected:
|
||||
PRBool AcceptUpdate(PRUint64 aSequenceNumber) {
|
||||
if (aSequenceNumber > mLastSequenceNumber && mFrame &&
|
||||
mFrame->mInstanceOwner) {
|
||||
mLastSequenceNumber = aSequenceNumber;
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint64 mLastSequenceNumber;
|
||||
nsObjectFrame* mFrame;
|
||||
};
|
||||
|
||||
// Mac specific code to fix up port position and clip
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
|
@ -651,7 +716,6 @@ NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -689,6 +753,10 @@ nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
if (mBackgroundSink) {
|
||||
mBackgroundSink->Destroy();
|
||||
}
|
||||
|
||||
nsObjectFrameSuper::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
|
@ -1253,19 +1321,48 @@ nsObjectFrame::PaintPrintPlugin(nsIFrame* aFrame, nsIRenderingContext* aCtx,
|
|||
static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
nsRect r = mFrame->GetContentRect() - mFrame->GetPosition() +
|
||||
ToReferenceFrame();
|
||||
if (aBuilder->IsForPluginGeometry()) {
|
||||
// Return the geometry we want, not the geometry we have (which is based
|
||||
// on the surface the plugin last gave us)
|
||||
return r;
|
||||
class nsDisplayPluginReadback : public nsDisplayItem {
|
||||
public:
|
||||
nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
: nsDisplayItem(aBuilder, aFrame)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayPluginReadback);
|
||||
}
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayPluginReadback() {
|
||||
MOZ_COUNT_DTOR(nsDisplayPluginReadback);
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this);
|
||||
}
|
||||
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
if (mozilla::LAYER_ACTIVE == f->GetLayerState(aBuilder, nsnull)) {
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return LAYER_ACTIVE;
|
||||
}
|
||||
};
|
||||
|
||||
static nsRect
|
||||
GetDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
|
||||
{
|
||||
nsRect r = aFrame->GetContentRect() - aFrame->GetPosition() +
|
||||
aItem->ToReferenceFrame();
|
||||
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(aFrame);
|
||||
if (LAYER_ACTIVE == f->GetLayerState(aBuilder)) {
|
||||
ImageContainer* c = f->GetImageContainer();
|
||||
if (c) {
|
||||
gfxIntSize size = c->GetCurrentSize();
|
||||
|
@ -1279,6 +1376,38 @@ nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
|||
return r;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return GetDisplayItemBounds(aBuilder, this, mFrame);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG))
|
||||
return PR_FALSE;
|
||||
|
||||
nsRect expand;
|
||||
expand.IntersectRect(aAllowVisibleRegionExpansion, GetBounds(aBuilder));
|
||||
// *Add* our bounds to the visible region so that stuff underneath us is
|
||||
// likely to be made visible, so we can use it for a background! This is
|
||||
// a bit crazy since we normally only subtract from the visible region.
|
||||
aVisibleRegion->Or(*aVisibleRegion, expand);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return GetDisplayItemBounds(aBuilder, this, mFrame);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx)
|
||||
|
@ -1290,10 +1419,12 @@ nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
|
|||
PRBool
|
||||
nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder));
|
||||
return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
|
||||
aAllowVisibleRegionExpansion,
|
||||
aContainsRootContentDocBG);
|
||||
}
|
||||
|
||||
|
@ -1456,10 +1587,12 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists)
|
||||
{
|
||||
AddStateBits(NS_OBJECT_NEEDS_SET_IMAGE);
|
||||
|
||||
// XXX why are we painting collapsed object frames?
|
||||
if (!IsVisibleOrCollapsedForPainting(aBuilder))
|
||||
return NS_OK;
|
||||
|
||||
|
||||
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -1504,6 +1637,12 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
|
||||
nsDisplayItem::TYPE_PRINT_PLUGIN));
|
||||
} else {
|
||||
if (aBuilder->IsPaintingToWindow() && GetLayerState(aBuilder) == LAYER_ACTIVE) {
|
||||
rv = replacedContent.AppendNewToTop(new (aBuilder)
|
||||
nsDisplayPluginReadback(aBuilder, this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = replacedContent.AppendNewToTop(new (aBuilder)
|
||||
nsDisplayPlugin(aBuilder, this));
|
||||
}
|
||||
|
@ -1807,14 +1946,44 @@ nsPluginInstanceOwner::SetCurrentImage(ImageContainer* aContainer)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
mozilla::LayerState
|
||||
nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
void
|
||||
nsPluginInstanceOwner::SetBackgroundUnknown()
|
||||
{
|
||||
if (!mInstanceOwner || !mInstanceOwner->UseLayers())
|
||||
return mozilla::LAYER_NONE;
|
||||
nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
|
||||
if (inst) {
|
||||
inst->SetBackgroundUnknown();
|
||||
}
|
||||
}
|
||||
|
||||
return mozilla::LAYER_ACTIVE;
|
||||
already_AddRefed<gfxContext>
|
||||
nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
|
||||
{
|
||||
nsIntRect rect = aRect;
|
||||
nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
|
||||
nsRefPtr<gfxContext> ctx;
|
||||
if (inst &&
|
||||
NS_SUCCEEDED(inst->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) {
|
||||
return ctx.forget();
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext,
|
||||
const nsIntRect& aRect)
|
||||
{
|
||||
nsIntRect rect = aRect;
|
||||
nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
|
||||
if (inst) {
|
||||
inst->EndUpdateBackground(aContext, &rect);
|
||||
}
|
||||
}
|
||||
|
||||
LayerState
|
||||
nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return mInstanceOwner && mInstanceOwner->UseLayers() ?
|
||||
LAYER_ACTIVE : LAYER_NONE;
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
|
@ -1833,6 +2002,18 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
if (window->width <= 0 || window->height <= 0)
|
||||
return nsnull;
|
||||
|
||||
// Create image
|
||||
nsRefPtr<ImageContainer> container = GetImageContainer(aManager);
|
||||
if (!container)
|
||||
return nsnull;
|
||||
if (GetStateBits() & NS_OBJECT_NEEDS_SET_IMAGE) {
|
||||
RemoveStateBits(NS_OBJECT_NEEDS_SET_IMAGE);
|
||||
if (!mInstanceOwner->SetCurrentImage(container)) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
gfxIntSize size = container->GetCurrentSize();
|
||||
|
||||
nsRect area = GetContentRect() + aBuilder->ToReferenceFrame(GetParent());
|
||||
gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
|
||||
// to provide crisper and faster drawing.
|
||||
|
@ -1840,41 +2021,55 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
nsRefPtr<Layer> layer =
|
||||
(aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
|
||||
|
||||
if (!layer) {
|
||||
mInstanceOwner->NotifyPaintWaiter(aBuilder);
|
||||
// Initialize ImageLayer
|
||||
layer = aManager->CreateImageLayer();
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
|
||||
if (!layer) {
|
||||
mInstanceOwner->NotifyPaintWaiter(aBuilder);
|
||||
// Initialize ImageLayer
|
||||
layer = aManager->CreateImageLayer();
|
||||
if (!layer)
|
||||
return nsnull;
|
||||
}
|
||||
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
|
||||
|
||||
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
|
||||
imglayer->SetContainer(container);
|
||||
imglayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
|
||||
|
||||
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
|
||||
} else {
|
||||
NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
|
||||
"Unknown item type");
|
||||
if (!layer) {
|
||||
layer = aManager->CreateReadbackLayer();
|
||||
if (!layer)
|
||||
return nsnull;
|
||||
}
|
||||
NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
|
||||
|
||||
ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
|
||||
if (readback->GetSize() != nsIntSize(size.width, size.height)) {
|
||||
// This will destroy any old background sink and notify us that the
|
||||
// background is now unknown
|
||||
readback->SetSink(nsnull);
|
||||
NS_ASSERTION(!mBackgroundSink, "Should have been cleared");
|
||||
|
||||
readback->SetSize(nsIntSize(size.width, size.height));
|
||||
|
||||
mBackgroundSink =
|
||||
new PluginBackgroundSink(this,
|
||||
readback->AllocateSequenceNumber());
|
||||
readback->SetSink(mBackgroundSink);
|
||||
// The layer has taken ownership of our sink. When either the sink dies
|
||||
// or the frame dies, the connection from the surviving object is nulled out.
|
||||
}
|
||||
}
|
||||
|
||||
if (!layer)
|
||||
return nsnull;
|
||||
|
||||
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "ObjectFrame works only with ImageLayer");
|
||||
// Create image
|
||||
nsRefPtr<ImageContainer> container = GetImageContainer(aManager);
|
||||
if (!container)
|
||||
return nsnull;
|
||||
|
||||
if (!mInstanceOwner->SetCurrentImage(container)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
|
||||
imglayer->SetContainer(container);
|
||||
imglayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
|
||||
|
||||
layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
|
||||
|
||||
// Set a transform on the layer to draw the plugin in the right place
|
||||
gfxMatrix transform;
|
||||
// Center plugin if layer size != frame rect
|
||||
r.pos.x += (r.Width() - container->GetCurrentSize().width) / 2;
|
||||
r.pos.y += (r.Height() - container->GetCurrentSize().height) / 2;
|
||||
transform.Translate(r.pos);
|
||||
|
||||
layer->SetTransform(gfx3DMatrix::From2D(transform));
|
||||
nsRefPtr<Layer> result = layer.forget();
|
||||
return result.forget();
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2039,7 +2234,7 @@ nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
|
|||
// double pass render. If this plugin isn't oop, the register window message
|
||||
// will be ignored.
|
||||
NPEvent pluginEvent;
|
||||
pluginEvent.event = mozilla::plugins::DoublePassRenderingEvent();
|
||||
pluginEvent.event = DoublePassRenderingEvent();
|
||||
pluginEvent.wParam = 0;
|
||||
pluginEvent.lParam = 0;
|
||||
if (pluginEvent.event)
|
||||
|
|
|
@ -62,9 +62,12 @@ class nsIPluginInstance;
|
|||
class nsPresContext;
|
||||
class nsDisplayPlugin;
|
||||
class nsIDOMElement;
|
||||
class PluginBackgroundSink;
|
||||
|
||||
#define nsObjectFrameSuper nsFrame
|
||||
|
||||
#define NS_OBJECT_NEEDS_SET_IMAGE NS_FRAME_STATE_BIT(31)
|
||||
|
||||
class nsObjectFrame : public nsObjectFrameSuper,
|
||||
public nsIObjectFrame,
|
||||
public nsIReflowCallback {
|
||||
|
@ -176,12 +179,15 @@ public:
|
|||
virtual PRBool ReflowFinished();
|
||||
virtual void ReflowCallbackCanceled();
|
||||
|
||||
/**
|
||||
* Builds either an ImageLayer or a ReadbackLayer, depending on the type
|
||||
* of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively).
|
||||
*/
|
||||
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
nsDisplayItem* aItem);
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager);
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
ImageContainer* GetImageContainer(LayerManager* aManager = nsnull);
|
||||
|
||||
|
@ -272,6 +278,7 @@ protected:
|
|||
|
||||
friend class nsPluginInstanceOwner;
|
||||
friend class nsDisplayPlugin;
|
||||
friend class PluginBackgroundSink;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -289,6 +296,11 @@ private:
|
|||
nsIView* mInnerView;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
nsIntRect mWindowlessRect;
|
||||
/**
|
||||
* This is owned by the ReadbackLayer for this nsObjectFrame. It is
|
||||
* automatically cleared if the PluginBackgroundSink is destroyed.
|
||||
*/
|
||||
PluginBackgroundSink* mBackgroundSink;
|
||||
|
||||
// For assertions that make it easier to determine if a crash is due
|
||||
// to the underlying problem described in bug 136927, and to prevent
|
||||
|
@ -322,6 +334,7 @@ public:
|
|||
nsIRenderingContext* aCtx);
|
||||
virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion,
|
||||
PRBool& aContainsRootContentDocBG);
|
||||
|
||||
NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN)
|
||||
|
@ -345,7 +358,7 @@ public:
|
|||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder, aManager);
|
||||
return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -1558,7 +1558,7 @@ asserts(0-1) == 582146-1.html about:blank
|
|||
== 584699-1.html 584699-1-ref.html
|
||||
== 585598-2.xhtml 585598-2-ref.xhtml
|
||||
== 586400-1.html 586400-1-ref.html
|
||||
== 586683-1.html 586683-1-ref.html
|
||||
fails-if(cocoaWidget) == 586683-1.html 586683-1-ref.html
|
||||
== 589615-1a.xhtml 589615-1-ref.html
|
||||
== 589615-1b.html 589615-1-ref.html
|
||||
== 589672-1.html 589672-1-ref.html
|
||||
|
|
|
@ -571,6 +571,7 @@ function ReadManifest(aURL)
|
|||
cond = true;
|
||||
} else if (item == "needs-focus") {
|
||||
needs_focus = true;
|
||||
cond = false;
|
||||
} else if ((m = item.match(/^asserts\((\d+)(-\d+)?\)$/))) {
|
||||
cond = false;
|
||||
minAsserts = Number(m[1]);
|
||||
|
|
|
@ -48,6 +48,8 @@ interface nsIOutputStream;
|
|||
struct JSContext;
|
||||
struct JSObject;
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
struct nsIntRect;
|
||||
|
||||
#define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
|
||||
%}
|
||||
|
@ -55,6 +57,8 @@ class gfxASurface;
|
|||
[ptr] native JSContextPtr(JSContext);
|
||||
[ptr] native JSObjectPtr(JSObject);
|
||||
[ptr] native gfxASurfacePtr(gfxASurface);
|
||||
[ptr] native gfxContextPtr(gfxContext);
|
||||
[ptr] native nsIntRectPtr(nsIntRect);
|
||||
|
||||
[uuid(84994340-E120-4051-824F-D4EE8AEF1A3E)]
|
||||
interface nsIPluginInstance : nsISupports
|
||||
|
@ -247,3 +251,18 @@ interface nsIPluginInstance : nsISupports
|
|||
*/
|
||||
PRBool useAsyncPainting();
|
||||
};
|
||||
|
||||
|
||||
// XXX kill me after branching
|
||||
[noscript, uuid(324f3c02-4fbd-430b-8afa-db083d3867fc)]
|
||||
interface nsIPluginInstance_MOZILLA_2_0_BRANCH : nsIPluginInstance
|
||||
{
|
||||
/**
|
||||
* This is the second leg in the trip to PluginInstanceParent. It
|
||||
* approximately follows the ReadbackSink API.
|
||||
*/
|
||||
|
||||
void setBackgroundUnknown();
|
||||
void beginUpdateBackground(in nsIntRectPtr rect, out gfxContextPtr ctx);
|
||||
void endUpdateBackground(in gfxContextPtr ctx, in nsIntRectPtr rect);
|
||||
};
|
||||
|
|
|
@ -255,4 +255,32 @@ PluginPRLibrary::GetSurface(NPP instance, gfxASurface** aSurface)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginPRLibrary::SetBackgroundUnknown(NPP instance)
|
||||
{
|
||||
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
||||
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
||||
NS_ERROR("Unexpected use of async APIs for in-process plugin.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginPRLibrary::BeginUpdateBackground(NPP instance,
|
||||
const nsIntRect&, gfxContext** aCtx)
|
||||
{
|
||||
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
||||
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
||||
NS_ERROR("Unexpected use of async APIs for in-process plugin.");
|
||||
*aCtx = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginPRLibrary::EndUpdateBackground(NPP instance,
|
||||
gfxContext*, const nsIntRect&)
|
||||
{
|
||||
NS_RUNTIMEABORT("This should never be called");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -142,6 +142,14 @@ public:
|
|||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
|
||||
virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface);
|
||||
NS_OVERRIDE virtual bool UseAsyncPainting() { return false; }
|
||||
NS_OVERRIDE
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance);
|
||||
NS_OVERRIDE
|
||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
||||
const nsIntRect&, gfxContext** aCtx);
|
||||
NS_OVERRIDE
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
gfxContext* aCtx, const nsIntRect&);
|
||||
|
||||
private:
|
||||
NP_InitializeFunc mNP_Initialize;
|
||||
|
|
|
@ -59,13 +59,13 @@
|
|||
#include "nsJSNPRuntime.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::plugins::parent;
|
||||
using mozilla::TimeStamp;
|
||||
|
||||
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
|
||||
static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsNPAPIPluginInstance, nsIPluginInstance)
|
||||
NS_IMPL_ISUPPORTS2(nsNPAPIPluginInstance, nsIPluginInstance, nsIPluginInstance_MOZILLA_2_0_BRANCH)
|
||||
|
||||
nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
|
||||
:
|
||||
|
@ -809,18 +809,32 @@ nsNPAPIPluginInstance::IsWindowless(PRBool* isWindowless)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class NS_STACK_CLASS AutoPluginLibraryCall
|
||||
{
|
||||
public:
|
||||
AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
|
||||
: mThis(aThis), mGuard(aThis), mLibrary(nsnull)
|
||||
{
|
||||
nsNPAPIPlugin* plugin = mThis->GetPlugin();
|
||||
if (plugin)
|
||||
mLibrary = plugin->GetLibrary();
|
||||
}
|
||||
operator bool() { return !!mLibrary; }
|
||||
PluginLibrary* operator->() { return mLibrary; }
|
||||
|
||||
private:
|
||||
nsNPAPIPluginInstance* mThis;
|
||||
PluginDestructionGuard mGuard;
|
||||
PluginLibrary* mLibrary;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
|
||||
{
|
||||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
if (!mPlugin)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -833,12 +847,7 @@ nsNPAPIPluginInstance::GetSurface(gfxASurface** aSurface)
|
|||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
if (!mPlugin)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -861,12 +870,7 @@ nsNPAPIPluginInstance::UseAsyncPainting(PRBool* aIsAsync)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
if (!mPlugin)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -874,6 +878,47 @@ nsNPAPIPluginInstance::UseAsyncPainting(PRBool* aIsAsync)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::SetBackgroundUnknown()
|
||||
{
|
||||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return library->SetBackgroundUnknown(&mNPP);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
|
||||
gfxContext** aContext)
|
||||
{
|
||||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return library->BeginUpdateBackground(&mNPP, *aRect, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
|
||||
nsIntRect* aRect)
|
||||
{
|
||||
if (RUNNING != mRunning)
|
||||
return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return library->EndUpdateBackground(&mNPP, aContext, *aRect);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginInstance::IsTransparent(PRBool* isTransparent)
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
void (*callback)(NPP npp, uint32_t timerID);
|
||||
};
|
||||
|
||||
class nsNPAPIPluginInstance : public nsIPluginInstance
|
||||
class nsNPAPIPluginInstance : public nsIPluginInstance_MOZILLA_2_0_BRANCH
|
||||
{
|
||||
private:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
@ -75,6 +75,7 @@ private:
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGININSTANCE
|
||||
NS_DECL_NSIPLUGININSTANCE_MOZILLA_2_0_BRANCH
|
||||
|
||||
nsNPAPIPlugin* GetPlugin();
|
||||
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<style type="text/css">
|
||||
#one {
|
||||
position:absolute;
|
||||
left:0px; top:0px;
|
||||
z-index:4;
|
||||
}
|
||||
#two {
|
||||
position:absolute;
|
||||
top:100px; left:100px;
|
||||
background-color:rgb(0,0,0,0);
|
||||
z-index:3;
|
||||
}
|
||||
#three {
|
||||
position:absolute;
|
||||
left:100px; top:100px;
|
||||
width:200px; height:200px;
|
||||
background-color: rgb(255,0,0);
|
||||
opacity:0.6;
|
||||
z-index:2;
|
||||
}
|
||||
#four {
|
||||
position:absolute;
|
||||
top:100px; left:100px;
|
||||
z-index:1;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var plugin, div, canvas;
|
||||
function start() {
|
||||
plugin = document.getElementById("four");
|
||||
div = document.getElementById("three");
|
||||
canvas = document.getElementById("two");
|
||||
paintCanvas();
|
||||
|
||||
mozRequestAnimationFrame(moveSomething);
|
||||
}
|
||||
|
||||
function paintCanvas() {
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = "rgba(255,0,0, 0.6)";
|
||||
ctx.fillRect(0,0, 200,200);
|
||||
}
|
||||
|
||||
var i = 0, numLoops = 20;
|
||||
var pluginIn = true, divIn = true, canvasIn = true;
|
||||
function moveSomething() {
|
||||
var didSomething = (0 === (i % 2)) ? moveSomethingOut() : moveSomethingIn();
|
||||
if (!didSomething && ++i >= numLoops) {
|
||||
return finish();
|
||||
}
|
||||
|
||||
mozRequestAnimationFrame(moveSomething);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
function moveSomethingOut() {
|
||||
if (pluginIn) {
|
||||
plugin.style.left = "400px";
|
||||
pluginIn = false;
|
||||
} else if (divIn) {
|
||||
div.style.left = "400px";
|
||||
divIn = false;
|
||||
} else if (canvasIn) {
|
||||
canvas.style.left = "400px";
|
||||
canvasIn = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function moveSomethingIn() {
|
||||
if (!pluginIn) {
|
||||
plugin.style.left = "100px";
|
||||
pluginIn = true;
|
||||
} else if (!divIn) {
|
||||
div.style.left = "100px";
|
||||
divIn = true;
|
||||
} else if (!canvasIn) {
|
||||
canvas.style.left = "100px";
|
||||
canvasIn = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function reset() {
|
||||
|
||||
}
|
||||
</script>
|
||||
</style>
|
||||
</head>
|
||||
<body onload="start();">
|
||||
<embed id="four" type="application/x-test" width="200" height="200"
|
||||
drawmode="solid" color="FFFF0000"></embed>
|
||||
<div id="three"></div>
|
||||
<canvas id="two" width="200" height="200"></canvas>
|
||||
<embed id="one" type="application/x-test" width="400" height="400"
|
||||
drawmode="solid" color="9900FF00"></embed>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -9,3 +9,4 @@ load 570884.html
|
|||
# Plugin arch is going to change anyway with OOP content so skipping
|
||||
# this test for now is OK.
|
||||
skip-if(browserIsRemote||!haveTestPlugin||http.platform!="X11"||!testPluginIsOOP()) load 598862.html
|
||||
load 626602-1.html
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
<script type="text/javascript">
|
||||
var NUM_STEPS = 1;
|
||||
</script>
|
||||
<script type="text/javascript" src="plugin-background.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<embed id="plugin" type="application/x-test" width="199" height="199"
|
||||
drawmode="solid" color="330000FF"></embed>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
<script type="text/javascript">
|
||||
var NUM_STEPS = 10;
|
||||
</script>
|
||||
<script type="text/javascript" src="plugin-background.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<embed id="plugin" type="application/x-test" width="199" height="199"
|
||||
drawmode="solid" color="330000FF"></embed>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
<script type="text/javascript">
|
||||
var NUM_STEPS = 2;
|
||||
</script>
|
||||
<script type="text/javascript" src="plugin-background.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<embed id="plugin" type="application/x-test" width="199" height="199"
|
||||
drawmode="solid" color="330000FF"></embed>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
<script type="text/javascript">
|
||||
var NUM_STEPS = 5;
|
||||
</script>
|
||||
<script type="text/javascript" src="plugin-background.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<embed id="plugin" type="application/x-test" width="199" height="199"
|
||||
drawmode="solid" color="330000FF"></embed>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<div id="plugin"></div>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,58 @@
|
|||
div {
|
||||
position: absolute;
|
||||
}
|
||||
#bad {
|
||||
left:220px; top:0px;
|
||||
z-index: 0;
|
||||
}
|
||||
#good {
|
||||
left:0px; top:0px;
|
||||
width:220px; height:220px;
|
||||
background-color: rgba(0,255,0, 0.6);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#topbar {
|
||||
left:0px; top:0px;
|
||||
width:220px; height:20px;
|
||||
background-color: rgb(0,0,0);
|
||||
z-index: 2;
|
||||
}
|
||||
#topbar {
|
||||
left:0px; top:0px;
|
||||
width:220px; height:20px;
|
||||
background-color: rgb(0,0,0);
|
||||
z-index: 2;
|
||||
}
|
||||
#leftbar {
|
||||
left:0px; top:0px;
|
||||
width:20px; height:220px;
|
||||
background-color: rgb(0,0,0);
|
||||
z-index: 2;
|
||||
}
|
||||
#rightbar {
|
||||
left:200px; top:0px;
|
||||
width:20px; height:220px;
|
||||
background-color: rgb(0,0,0);
|
||||
z-index: 2;
|
||||
}
|
||||
#bottombar {
|
||||
left:0px; top:200px;
|
||||
width:220px; height:20px;
|
||||
background-color: rgb(0,0,0);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
div#plugin {
|
||||
position: absolute;
|
||||
left:1px; top:1px;
|
||||
width:199px; height:199px;
|
||||
background-color: rgba(0,0,255, 0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
embed#plugin {
|
||||
position: absolute;
|
||||
left:1px; top:1px;
|
||||
z-index: 1;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="plugin-background.css"></link>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bad">Test some plugin stuff.</div>
|
||||
<div id="good"></div>
|
||||
|
||||
<embed id="plugin" type="application/x-test" width="199" height="199"
|
||||
drawmode="solid" color="330000FF"></embed>
|
||||
|
||||
<div id="topbar"></div>
|
||||
<div id="leftbar"></div>
|
||||
<div id="rightbar"></div>
|
||||
<div id="bottombar"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,75 @@
|
|||
// The including script sets this for us
|
||||
//var NUM_STEPS;
|
||||
|
||||
var plugin;
|
||||
var left = 1, top = 1, width = 199, height = 199;
|
||||
function movePluginTo(x, y, w, h) {
|
||||
left = x; top = y; width = w; height = h;
|
||||
plugin.width = w;
|
||||
plugin.height = h;
|
||||
plugin.style.left = left + "px";
|
||||
plugin.style.top = top + "px";
|
||||
}
|
||||
function deltaInBounds(dx,dy, dw,dh) {
|
||||
var l = dx + left;
|
||||
var r = l + width + dw;
|
||||
var t = dy + top;
|
||||
var b = t + height + dh;
|
||||
return (0 <= l && l <= 20 &&
|
||||
0 <= t && t <= 20 &&
|
||||
200 <= r && r <= 220 &&
|
||||
200 <= b && b <= 220);
|
||||
}
|
||||
|
||||
var initialFrame;
|
||||
function start() {
|
||||
window.removeEventListener("MozReftestInvalidate", start, false);
|
||||
|
||||
window.addEventListener("MozAfterPaint", step, false);
|
||||
window.addEventListener("MozPaintWaitFinished", step, false);
|
||||
|
||||
initialFrame = window.mozPaintCount;
|
||||
plugin = document.getElementById("plugin");
|
||||
|
||||
movePluginTo(0,0, 200,200);
|
||||
}
|
||||
|
||||
var steps = 0;
|
||||
var which = "move"; // or "grow"
|
||||
var dx = 1, dy = 1, dw = 1, dh = 1;
|
||||
function step() {
|
||||
if (++steps >= NUM_STEPS) {
|
||||
window.removeEventListener("MozAfterPaint", step, false);
|
||||
window.removeEventListener("MozPaintWaitFinished", step, false);
|
||||
return finish();
|
||||
}
|
||||
|
||||
var didSomething = false;
|
||||
if (which == "grow") {
|
||||
if (deltaInBounds(0,0, dw,dh)) {
|
||||
movePluginTo(left,top, width+dw, height+dh);
|
||||
didSomething = true;
|
||||
} else {
|
||||
dw = -dw; dh = -dh;
|
||||
}
|
||||
} else {
|
||||
// "move"
|
||||
if (deltaInBounds(dx,dy, 0,0)) {
|
||||
movePluginTo(left+dx,top+dy, width, height);
|
||||
didSomething = true;
|
||||
} else {
|
||||
dx = -dx; dy = -dy;
|
||||
}
|
||||
}
|
||||
which = (which == "grow") ? "move" : "grow";
|
||||
|
||||
if (!didSomething) {
|
||||
step();
|
||||
}
|
||||
}
|
||||
|
||||
function finish() {
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
window.addEventListener("MozReftestInvalidate", start, false);
|
|
@ -0,0 +1,49 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
#one {
|
||||
position:absolute;
|
||||
left:0px; top:0px;
|
||||
z-index:4;
|
||||
}
|
||||
#two {
|
||||
position:absolute;
|
||||
top:100px; left:100px;
|
||||
background-color:rgb(0,0,0,0);
|
||||
z-index:3;
|
||||
}
|
||||
#three {
|
||||
position:absolute;
|
||||
left:100px; top:100px;
|
||||
width:200px; height:200px;
|
||||
background-color: rgb(255,0,0);
|
||||
opacity:0.6;
|
||||
z-index:2;
|
||||
}
|
||||
#four {
|
||||
position:absolute;
|
||||
top:100px; left:100px;
|
||||
z-index:1;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function paintCanvas() {
|
||||
var canvas = document.getElementById("two");
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = "rgba(255,0,0, 0.6)";
|
||||
ctx.fillRect(0,0, 200,200);
|
||||
}
|
||||
</script>
|
||||
</style>
|
||||
</head>
|
||||
<body onload="paintCanvas();">
|
||||
<embed id="four" type="application/x-test" width="200" height="200"
|
||||
drawmode="solid" color="FFFF0000"></embed>
|
||||
<div id="three"></div>
|
||||
<canvas id="two" width="200" height="200"></canvas>
|
||||
<embed id="one" type="application/x-test" width="400" height="400"
|
||||
drawmode="solid" color="9900FF00"></embed>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
#one {
|
||||
position:absolute;
|
||||
left:0px; top:0px;
|
||||
z-index:1;
|
||||
}
|
||||
#two {
|
||||
position:absolute;
|
||||
top:100px; left:100px;
|
||||
// Set these using the canvas API
|
||||
// width:200px; height:200px;
|
||||
// background-color: rgb(255,0,0);
|
||||
z-index:0;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function paintCanvas() {
|
||||
var canvas = document.getElementById("two");
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.fillStyle = "rgb(255,0,0)";
|
||||
ctx.fillRect(0,0, 200,200);
|
||||
}
|
||||
</script>
|
||||
</style>
|
||||
</head>
|
||||
<body onload="paintCanvas();">
|
||||
<canvas width="200" height="200" id="two"></canvas>
|
||||
<embed id="one" type="application/x-test" width="400" height="400" drawmode="solid" color="9900FF00"></embed>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
#one {
|
||||
position:absolute;
|
||||
left:0px; top:0px;
|
||||
z-index:1;
|
||||
}
|
||||
#two {
|
||||
position:absolute;
|
||||
top:0px; left:0px;
|
||||
width:200px; height:200px;
|
||||
z-index:0;
|
||||
background-color: rgb(255,0,0);
|
||||
-moz-transform-origin: 0 0;
|
||||
-moz-transform: translate(100px,100px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="two"></div>
|
||||
<embed id="one" type="application/x-test" width="400" height="400" drawmode="solid" color="9900FF00"></embed>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -9,3 +9,11 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) =
|
|||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-3.html border-padding-3-ref.html # bug 629430
|
||||
random-if(cocoaWidget||d2d) fails-if(!haveTestPlugin) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html
|
||||
fails-if(!haveTestPlugin) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html
|
||||
fails-if(!haveTestPlugin) == plugin-background.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-1-step.html plugin-background-ref.html
|
||||
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-background-2-step.html plugin-background-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-background-5-step.html plugin-background-ref.html
|
||||
fails-if(!haveTestPlugin) == plugin-background-10-step.html plugin-background-ref.html
|
||||
|
|
|
@ -381,13 +381,17 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
|||
if (expose.x < clip.left || expose.y < clip.top ||
|
||||
expose.x + expose.width > clip.right ||
|
||||
expose.y + expose.height > clip.bottom) {
|
||||
g_warning("expose rectangle not in clip rectangle");
|
||||
g_warning("expose rectangle (x=%d,y=%d,w=%d,h=%d) not in clip rectangle (l=%d,t=%d,r=%d,b=%d)",
|
||||
expose.x, expose.y, expose.width, expose.height,
|
||||
clip.left, clip.top, clip.right, clip.bottom);
|
||||
return 0;
|
||||
}
|
||||
if (expose.x < window.x || expose.y < window.y ||
|
||||
expose.x + expose.width > window.x + int32_t(window.width) ||
|
||||
expose.y + expose.height > window.y + int32_t(window.height)) {
|
||||
g_warning("expose rectangle not in plugin rectangle");
|
||||
g_warning("expose rectangle (x=%d,y=%d,w=%d,h=%d) not in plugin rectangle (x=%d,y=%d,w=%d,h=%d)",
|
||||
expose.x, expose.y, expose.width, expose.height,
|
||||
window.x, window.y, window.width, window.height);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ SDK_XPIDLSRCS = \
|
|||
nsIUploadChannel.idl \
|
||||
nsIUnicharStreamListener.idl \
|
||||
nsITraceableChannel.idl \
|
||||
nsIX509Cert.idl \
|
||||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
|
@ -143,6 +144,8 @@ XPIDLSRCS = \
|
|||
nsIRedirectResultListener.idl \
|
||||
mozIThirdPartyUtil.idl \
|
||||
nsISerializationHelper.idl \
|
||||
nsISSLStatus.idl \
|
||||
nsISSLStatusProvider.idl \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_IPC
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
* Jim Mathies <jmathies@mozilla.com>
|
||||
* Guillermo Robla Vicario <groblavicario@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -52,6 +53,9 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsIHttpAuthenticableChannel.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIX509Cert.h"
|
||||
#include "nsISSLStatus.h"
|
||||
#include "nsISSLStatusProvider.h"
|
||||
|
||||
static const char kAllowProxies[] = "network.automatic-ntlm-auth.allow-proxies";
|
||||
static const char kTrustedURIs[] = "network.automatic-ntlm-auth.trusted-uris";
|
||||
|
@ -235,6 +239,9 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
|||
LOG(("nsHttpNTLMAuth::ChallengeReceived [ss=%p cs=%p]\n",
|
||||
*sessionState, *continuationState));
|
||||
|
||||
// Use the native NTLM if available
|
||||
mUseNative = PR_TRUE;
|
||||
|
||||
// NOTE: we don't define any session state, but we do use the pointer.
|
||||
|
||||
*identityInvalid = PR_FALSE;
|
||||
|
@ -298,6 +305,8 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
|||
// see bug 520607 for details.
|
||||
LOG(("Trying to fall back on internal ntlm auth.\n"));
|
||||
module = do_CreateInstance(NS_AUTH_MODULE_CONTRACTID_PREFIX "ntlm");
|
||||
|
||||
mUseNative = PR_FALSE;
|
||||
|
||||
// Prompt user for domain, username, and password.
|
||||
*identityInvalid = PR_TRUE;
|
||||
|
@ -366,8 +375,65 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// This update enables updated Windows machines (Win7 or patched previous
|
||||
// versions) and Linux machines running Samba (updated for Channel
|
||||
// Binding), to perform Channel Binding when authenticating using NTLMv2
|
||||
// and an outer secure channel.
|
||||
//
|
||||
// Currently only implemented for Windows, linux support will be landing in
|
||||
// a separate patch, update this #ifdef accordingly then.
|
||||
#if defined (XP_WIN) /* || defined (LINUX) */
|
||||
PRBool isHttps;
|
||||
rv = uri->SchemeIs("https", &isHttps);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// When the url starts with https, we should retrieve the server
|
||||
// certificate and compute the CBT, but only when we are using
|
||||
// the native NTLM implementation and not the internal one.
|
||||
if (isHttps && mUseNative) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(authChannel, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISupports> security;
|
||||
rv = channel->GetSecurityInfo(getter_AddRefs(security));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISSLStatusProvider>
|
||||
statusProvider(do_QueryInterface(security));
|
||||
NS_ENSURE_TRUE(statusProvider, NS_ERROR_FAILURE);
|
||||
|
||||
rv = statusProvider->GetSSLStatus(getter_AddRefs(security));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsISSLStatus> status(do_QueryInterface(security));
|
||||
NS_ENSURE_TRUE(status, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIX509Cert> cert;
|
||||
rv = status->GetServerCert(getter_AddRefs(cert));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
PRUint32 length;
|
||||
PRUint8* certArray;
|
||||
cert->GetRawDER(&length, &certArray);
|
||||
|
||||
// If there is a server certificate, we pass it along the
|
||||
// first time we call GetNextToken().
|
||||
inBufLen = length;
|
||||
inBuf = certArray;
|
||||
} else {
|
||||
// If there is no server certificate, we don't pass anything.
|
||||
inBufLen = 0;
|
||||
inBuf = nsnull;
|
||||
}
|
||||
#else // Extended protection update is just for Linux and Windows machines.
|
||||
inBufLen = 0;
|
||||
inBuf = nsnull;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
// decode challenge; skip past "NTLM " to the start of the base64
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@netscape.com>
|
||||
* Guillermo Robla Vicario <groblavicario@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -48,6 +49,11 @@ public:
|
|||
|
||||
nsHttpNTLMAuth() {}
|
||||
virtual ~nsHttpNTLMAuth() {}
|
||||
|
||||
private:
|
||||
// This flag indicates whether we are using the native NTLM implementation
|
||||
// or the internal one.
|
||||
PRBool mUseNative;
|
||||
};
|
||||
|
||||
#endif // !nsHttpNTLMAuth_h__
|
||||
|
|
|
@ -687,6 +687,9 @@ nsHttpTransaction::LocateHttpStart(char *buf, PRUint32 len,
|
|||
|
||||
static const char HTTPHeader[] = "HTTP/1.";
|
||||
static const PRInt32 HTTPHeaderLen = sizeof(HTTPHeader) - 1;
|
||||
|
||||
if (aAllowPartialMatch && (len < HTTPHeaderLen))
|
||||
return (PL_strncasecmp(buf, HTTPHeader, len) == 0) ? buf : nsnull;
|
||||
|
||||
// mLineBuf can contain partial match from previous search
|
||||
if (!mLineBuf.IsEmpty()) {
|
||||
|
@ -714,13 +717,9 @@ nsHttpTransaction::LocateHttpStart(char *buf, PRUint32 len,
|
|||
if (PL_strncasecmp(buf, HTTPHeader, PR_MIN(len, HTTPHeaderLen)) == 0) {
|
||||
if (len < HTTPHeaderLen) {
|
||||
// partial HTTPHeader sequence found
|
||||
if (aAllowPartialMatch) {
|
||||
return buf;
|
||||
} else {
|
||||
// save partial match to mLineBuf
|
||||
mLineBuf.Assign(buf, len);
|
||||
return 0;
|
||||
}
|
||||
// save partial match to mLineBuf
|
||||
mLineBuf.Assign(buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// whole HTTPHeader sequence found
|
||||
|
@ -828,7 +827,7 @@ nsHttpTransaction::ParseHead(char *buf,
|
|||
if (!mConnection || !mConnection->LastTransactionExpectedNoContent()) {
|
||||
// tolerate only minor junk before the status line
|
||||
mHttpResponseMatched = PR_TRUE;
|
||||
char *p = LocateHttpStart(buf, PR_MIN(count, 8), PR_TRUE);
|
||||
char *p = LocateHttpStart(buf, PR_MIN(count, 11), PR_TRUE);
|
||||
if (!p) {
|
||||
// Treat any 0.9 style response of a put as a failure.
|
||||
if (mRequestHead->Method() == nsHttp::Put)
|
||||
|
|
|
@ -50,7 +50,6 @@ SDK_XPIDLSRCS = \
|
|||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsISSLStatusProvider.idl \
|
||||
nsIBufEntropyCollector.idl \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ SDK_XPIDLSRCS = \
|
|||
nsIASN1Sequence.idl \
|
||||
nsICertificateDialogs.idl \
|
||||
nsICRLInfo.idl \
|
||||
nsIX509Cert.idl \
|
||||
nsIX509CertDB.idl \
|
||||
nsIX509CertValidity.idl \
|
||||
$(NULL)
|
||||
|
@ -80,7 +79,6 @@ XPIDLSRCS = \
|
|||
nsIGenKeypairInfoDlg.idl \
|
||||
nsITokenDialogs.idl \
|
||||
nsITokenPasswordDialogs.idl \
|
||||
nsISSLStatus.idl \
|
||||
nsIKeygenThread.idl \
|
||||
nsICMSSecureMessage.idl \
|
||||
nsIUserCertPicker.idl \
|
||||
|
|
|
@ -2696,20 +2696,9 @@ HUD_SERVICE.prototype =
|
|||
}
|
||||
}
|
||||
|
||||
// Need to detect that the console component has been paved over. Do this by
|
||||
// checking whether its global object is equal to that of an object
|
||||
// returned by our native ConsoleAPI nsIDOMGlobalPropertyInitializer.
|
||||
// Need to detect that the console component has been paved over.
|
||||
let consoleObject = unwrap(aContentWindow).console;
|
||||
let consoleGlobal = Cu.getGlobalForObject(consoleObject);
|
||||
|
||||
let nativeConsoleObj = Cc["@mozilla.org/console-api;1"].
|
||||
createInstance(Ci.nsIDOMGlobalPropertyInitializer).
|
||||
init(aContentWindow);
|
||||
let nativeConsoleGlobal = Cu.getGlobalForObject(nativeConsoleObj);
|
||||
|
||||
// Need a "===" comparison because backstagepass objects have strange
|
||||
// behavior with ==
|
||||
if (consoleGlobal !== nativeConsoleGlobal)
|
||||
if (!("__mozillaConsole__" in consoleObject))
|
||||
this.logWarningAboutReplacedAPI(hudId);
|
||||
|
||||
// register the controller to handle "select all" properly
|
||||
|
|
|
@ -49,7 +49,7 @@ var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
|
|||
.getService(Components.interfaces.nsIIOService);
|
||||
|
||||
function createInstallTrigger(window) {
|
||||
return {
|
||||
let chromeObject = {
|
||||
window: window,
|
||||
|
||||
__exposedProps__: {
|
||||
|
@ -61,9 +61,7 @@ function createInstallTrigger(window) {
|
|||
updateEnabled: "r",
|
||||
install: "r",
|
||||
installChrome: "r",
|
||||
startSoftwareUpdate: "r",
|
||||
toString: "r",
|
||||
toSource: "r", // XXX workaround for bug 582100
|
||||
startSoftwareUpdate: "r"
|
||||
},
|
||||
|
||||
// == Public interface ==
|
||||
|
@ -188,6 +186,26 @@ function createInstallTrigger(window) {
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
let sandbox = Cu.Sandbox(window);
|
||||
let obj = Cu.evalInSandbox(
|
||||
"(function (x) {\
|
||||
var bind = Function.bind;\
|
||||
return {\
|
||||
enabled: bind.call(x.enabled, x),\
|
||||
updateEnabled: bind.call(x.updateEnabled, x),\
|
||||
install: bind.call(x.install, x),\
|
||||
installChrome: bind.call(x.installChrome, x),\
|
||||
startSoftwareUpdate: bind.call(x.startSoftwareUpdate, x)\
|
||||
};\
|
||||
})", sandbox)(chromeObject);
|
||||
|
||||
obj.SKIN = chromeObject.SKIN;
|
||||
obj.LOCALE = chromeObject.LOCALE;
|
||||
obj.CONTENT = chromeObject.CONTENT;
|
||||
obj.PACKAGE = chromeObject.PACKAGE;
|
||||
|
||||
return obj;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,6 +46,11 @@
|
|||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
// Compatibility macro for <libnotify-0.7
|
||||
#ifndef NOTIFY_CHECK_VERSION
|
||||
#define NOTIFY_CHECK_VERSION(x,y,z) 0
|
||||
#endif
|
||||
|
||||
static PRBool gHasActions = PR_FALSE;
|
||||
|
||||
static void notify_action_cb(NotifyNotification *notification,
|
||||
|
@ -218,7 +223,13 @@ nsAlertsIconListener::ShowAlert(GdkPixbuf* aPixbuf)
|
|||
{
|
||||
mNotification = notify_notification_new(mAlertTitle.get(),
|
||||
mAlertText.get(),
|
||||
NULL, NULL);
|
||||
NULL
|
||||
// >=libnotify-0.7.0 has no support for attaching to widgets
|
||||
#if !NOTIFY_CHECK_VERSION(0,7,0)
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
if (!mNotification)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче