зеркало из https://github.com/mozilla/pjs.git
Bug 626602, part 9: When possible, copy from a background to an opaque surface and have transparent plugins draw directly on the copied background, instead of doing alpha recovery or hoping plugins give us alpha values. r=bsmedberg,karlt sr=roc
This commit is contained in:
Родитель
589b7d181b
Коммит
3ae8df01ae
|
@ -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 ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
include protocol PPluginBackgroundDestroyer;
|
||||||
include protocol PPluginModule;
|
include protocol PPluginModule;
|
||||||
include protocol PPluginScriptableObject;
|
include protocol PPluginScriptableObject;
|
||||||
include protocol PBrowserStream;
|
include protocol PBrowserStream;
|
||||||
|
@ -57,6 +58,7 @@ using mozilla::gfxSurfaceType;
|
||||||
using gfxIntSize;
|
using gfxIntSize;
|
||||||
using mozilla::null_t;
|
using mozilla::null_t;
|
||||||
using mozilla::plugins::WindowsSharedMemoryHandle;
|
using mozilla::plugins::WindowsSharedMemoryHandle;
|
||||||
|
using nsIntRect;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace plugins {
|
namespace plugins {
|
||||||
|
@ -83,6 +85,7 @@ rpc protocol PPluginInstance
|
||||||
{
|
{
|
||||||
manager PPluginModule;
|
manager PPluginModule;
|
||||||
|
|
||||||
|
manages PPluginBackgroundDestroyer;
|
||||||
manages PPluginScriptableObject;
|
manages PPluginScriptableObject;
|
||||||
manages PBrowserStream;
|
manages PBrowserStream;
|
||||||
manages PPluginStream;
|
manages PPluginStream;
|
||||||
|
@ -126,6 +129,13 @@ child:
|
||||||
// with type equals to surfaceType
|
// with type equals to surfaceType
|
||||||
async AsyncSetWindow(gfxSurfaceType surfaceType, NPRemoteWindow window);
|
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()
|
rpc NPP_Destroy()
|
||||||
returns (NPError rv);
|
returns (NPError rv);
|
||||||
|
|
||||||
|
@ -236,6 +246,8 @@ parent:
|
||||||
child:
|
child:
|
||||||
rpc SetPluginFocus();
|
rpc SetPluginFocus();
|
||||||
rpc UpdateWindow();
|
rpc UpdateWindow();
|
||||||
|
|
||||||
|
async PPluginBackgroundDestroyer();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace plugins
|
} // 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 ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "PluginBackgroundDestroyer.h"
|
||||||
#include "PluginInstanceChild.h"
|
#include "PluginInstanceChild.h"
|
||||||
#include "PluginModuleChild.h"
|
#include "PluginModuleChild.h"
|
||||||
#include "BrowserStreamChild.h"
|
#include "BrowserStreamChild.h"
|
||||||
|
@ -167,7 +168,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface)
|
||||||
#endif // OS_WIN
|
#endif // OS_WIN
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
InitPopupMenuHook();
|
InitPopupMenuHook();
|
||||||
HookSystemParametersInfo();
|
|
||||||
#endif // OS_WIN
|
#endif // OS_WIN
|
||||||
#ifdef MOZ_X11
|
#ifdef MOZ_X11
|
||||||
// Maemo flash can render plugin with any provided rectangle and not require this quirk.
|
// Maemo flash can render plugin with any provided rectangle and not require this quirk.
|
||||||
|
@ -925,6 +925,11 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (mPluginIface->setwindow)
|
||||||
(void) mPluginIface->setwindow(&mData, &mWindow);
|
(void) mPluginIface->setwindow(&mData, &mWindow);
|
||||||
|
|
||||||
|
@ -1245,47 +1250,6 @@ PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
|
||||||
return res;
|
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 */
|
/* set window long ptr hook for flash */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2306,6 +2270,10 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||||
const NPRemoteWindow& aWindow,
|
const NPRemoteWindow& aWindow,
|
||||||
bool aIsAsync)
|
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();
|
AssertPluginThread();
|
||||||
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
|
NS_ASSERTION(!aWindow.window, "Remote window should be null.");
|
||||||
NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!");
|
NS_ASSERTION(!mPendingPluginCall, "Can't do SetWindow during plugin call!");
|
||||||
|
@ -2318,11 +2286,8 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||||
}
|
}
|
||||||
|
|
||||||
mWindow.window = NULL;
|
mWindow.window = NULL;
|
||||||
if (mWindow.width != aWindow.width || mWindow.height != aWindow.height) {
|
if (mWindow.width != aWindow.width || mWindow.height != aWindow.height ||
|
||||||
ClearCurrentSurface();
|
mWindow.clipRect.top != aWindow.clipRect.top ||
|
||||||
mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
|
|
||||||
}
|
|
||||||
if (mWindow.clipRect.top != aWindow.clipRect.top ||
|
|
||||||
mWindow.clipRect.left != aWindow.clipRect.left ||
|
mWindow.clipRect.left != aWindow.clipRect.left ||
|
||||||
mWindow.clipRect.bottom != aWindow.clipRect.bottom ||
|
mWindow.clipRect.bottom != aWindow.clipRect.bottom ||
|
||||||
mWindow.clipRect.right != aWindow.clipRect.right)
|
mWindow.clipRect.right != aWindow.clipRect.right)
|
||||||
|
@ -2363,12 +2328,16 @@ GfxFromNsRect(const nsIntRect& aRect)
|
||||||
bool
|
bool
|
||||||
PluginInstanceChild::CreateOptSurface(void)
|
PluginInstanceChild::CreateOptSurface(void)
|
||||||
{
|
{
|
||||||
|
NS_ABORT_IF_FALSE(mSurfaceType != gfxASurface::SurfaceTypeMax,
|
||||||
|
"Need a valid surface type here");
|
||||||
NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
|
NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
|
||||||
|
|
||||||
nsRefPtr<gfxASurface> retsurf;
|
nsRefPtr<gfxASurface> retsurf;
|
||||||
|
// Use an opaque surface unless we're transparent and *don't* have
|
||||||
|
// a background to source from.
|
||||||
gfxASurface::gfxImageFormat format =
|
gfxASurface::gfxImageFormat format =
|
||||||
mIsTransparent ? gfxASurface::ImageFormatARGB32 :
|
(mIsTransparent && !mBackground) ? gfxASurface::ImageFormatARGB32 :
|
||||||
gfxASurface::ImageFormatRGB24;
|
gfxASurface::ImageFormatRGB24;
|
||||||
|
|
||||||
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
#if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
|
||||||
// On Maemo 5, we must send the Visibility event to activate the plugin
|
// On Maemo 5, we must send the Visibility event to activate the plugin
|
||||||
|
@ -2406,10 +2375,12 @@ PluginInstanceChild::CreateOptSurface(void)
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (mSurfaceType == gfxASurface::SurfaceTypeWin32 ||
|
if (mSurfaceType == gfxASurface::SurfaceTypeWin32 ||
|
||||||
mSurfaceType == gfxASurface::SurfaceTypeD2D) {
|
mSurfaceType == gfxASurface::SurfaceTypeD2D) {
|
||||||
|
bool willHaveTransparentPixels = mIsTransparent && !mBackground;
|
||||||
|
|
||||||
SharedDIBSurface* s = new SharedDIBSurface();
|
SharedDIBSurface* s = new SharedDIBSurface();
|
||||||
if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
|
if (!s->Create(reinterpret_cast<HDC>(mWindow.window),
|
||||||
mWindow.width, mWindow.height, mIsTransparent))
|
mWindow.width, mWindow.height,
|
||||||
|
willHaveTransparentPixels))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mCurrentSurface = s;
|
mCurrentSurface = s;
|
||||||
|
@ -2490,6 +2461,8 @@ PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined(XP_WIN)
|
||||||
|
mDoAlphaExtraction = mIsTransparent && !mBackground;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2498,12 +2471,38 @@ PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
||||||
bool
|
bool
|
||||||
PluginInstanceChild::EnsureCurrentBuffer(void)
|
PluginInstanceChild::EnsureCurrentBuffer(void)
|
||||||
{
|
{
|
||||||
if (mCurrentSurface) {
|
nsIntRect toInvalidate(0, 0, 0, 0);
|
||||||
return true;
|
gfxIntSize winSize = gfxIntSize(mWindow.width, mWindow.height);
|
||||||
|
|
||||||
|
if (mBackground && mBackground->GetSize() != winSize) {
|
||||||
|
// It would be nice to keep the old background here, but doing
|
||||||
|
// so can lead to cases in which we permanently keep the old
|
||||||
|
// background size.
|
||||||
|
mBackground = nsnull;
|
||||||
|
toInvalidate.UnionRect(toInvalidate,
|
||||||
|
nsIntRect(0, 0, winSize.width, winSize.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mWindow.width || !mWindow.height) {
|
if (mCurrentSurface) {
|
||||||
return false;
|
gfxIntSize surfSize = mCurrentSurface->GetSize();
|
||||||
|
if (winSize != surfSize ||
|
||||||
|
(mBackground && !CanPaintOnBackground()) ||
|
||||||
|
(mBackground &&
|
||||||
|
gfxASurface::CONTENT_COLOR != mCurrentSurface->GetContentType()) ||
|
||||||
|
(!mBackground && mIsTransparent &&
|
||||||
|
gfxASurface::CONTENT_COLOR == mCurrentSurface->GetContentType())) {
|
||||||
|
// Don't try to use an old, invalid DC.
|
||||||
|
mWindow.window = nsnull;
|
||||||
|
ClearCurrentSurface();
|
||||||
|
toInvalidate.UnionRect(toInvalidate,
|
||||||
|
nsIntRect(0, 0, winSize.width, winSize.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
|
||||||
|
|
||||||
|
if (mCurrentSurface) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CreateOptSurface()) {
|
if (!CreateOptSurface()) {
|
||||||
|
@ -2548,7 +2547,7 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
||||||
mWindow.window = nsnull;
|
mWindow.window = nsnull;
|
||||||
mWsInfo.depth = gfxUtils::ImageFormatToDepth(img->Format());
|
mWsInfo.depth = gfxUtils::ImageFormatToDepth(img->Format());
|
||||||
mWsInfo.colormap = 0;
|
mWsInfo.colormap = 0;
|
||||||
needWindowUpdate = PR_TRUE;
|
needWindowUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // MAEMO
|
#endif // MAEMO
|
||||||
|
@ -2614,6 +2613,11 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
if (mPluginIface->setwindow) {
|
||||||
mPluginIface->setwindow(&mData, &mWindow);
|
mPluginIface->setwindow(&mData, &mWindow);
|
||||||
}
|
}
|
||||||
|
@ -2623,12 +2627,6 @@ void
|
||||||
PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||||
gfxASurface* aSurface)
|
gfxASurface* aSurface)
|
||||||
{
|
{
|
||||||
bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
|
|
||||||
if (temporarilyMakeVisible) {
|
|
||||||
mWindow.clipRect.right = mWindow.width;
|
|
||||||
mWindow.clipRect.bottom = mWindow.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateWindowAttributes();
|
UpdateWindowAttributes();
|
||||||
|
|
||||||
#ifdef MOZ_X11
|
#ifdef MOZ_X11
|
||||||
|
@ -2717,14 +2715,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||||
#else
|
#else
|
||||||
NS_RUNTIMEABORT("Surface type not implemented.");
|
NS_RUNTIMEABORT("Surface type not implemented.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (temporarilyMakeVisible) {
|
|
||||||
mWindow.clipRect.right = mWindow.clipRect.bottom = 0;
|
|
||||||
|
|
||||||
if (mPluginIface->setwindow) {
|
|
||||||
mPluginIface->setwindow(&mData, &mWindow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2754,7 +2744,7 @@ PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mIsTransparent) {
|
if (aColor.a > 0.0) {
|
||||||
// Clear surface content for transparent rendering
|
// Clear surface content for transparent rendering
|
||||||
nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface);
|
nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface);
|
||||||
ctx->SetColor(aColor);
|
ctx->SetColor(aColor);
|
||||||
|
@ -2811,6 +2801,9 @@ PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||||
|
|
||||||
// We always use a temporary "white image"
|
// We always use a temporary "white image"
|
||||||
whiteImage = new gfxImageSurface(targetSize, gfxASurface::ImageFormatRGB24);
|
whiteImage = new gfxImageSurface(targetSize, gfxASurface::ImageFormatRGB24);
|
||||||
|
if (whiteImage->CairoStatus()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// On windows, we need an HDC and so can't paint directly to
|
// On windows, we need an HDC and so can't paint directly to
|
||||||
|
@ -2877,43 +2870,109 @@ PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PluginInstanceChild::CanPaintOnBackground()
|
||||||
|
{
|
||||||
|
return (mBackground &&
|
||||||
|
mCurrentSurface &&
|
||||||
|
mCurrentSurface->GetSize() == mBackground->GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PluginInstanceChild::ShowPluginFrame()
|
PluginInstanceChild::ShowPluginFrame()
|
||||||
{
|
{
|
||||||
if (mPendingPluginCall) {
|
// mLayersRendering can be false if we somehow get here without
|
||||||
|
// receiving AsyncSetWindow() first. mPendingPluginCall is our
|
||||||
|
// re-entrancy guard; we can't paint while nested inside another
|
||||||
|
// paint.
|
||||||
|
if (!mLayersRendering || mPendingPluginCall) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoRestore<bool> pending(mPendingPluginCall);
|
AutoRestore<bool> pending(mPendingPluginCall);
|
||||||
mPendingPluginCall = true;
|
mPendingPluginCall = true;
|
||||||
|
|
||||||
|
bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
|
||||||
|
if (temporarilyMakeVisible && mWindow.width && mWindow.height) {
|
||||||
|
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.
|
||||||
|
ClearCurrentSurface();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!EnsureCurrentBuffer()) {
|
if (!EnsureCurrentBuffer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make expose rect not bigger than clip rect
|
NS_ASSERTION(mWindow.width == (mWindow.clipRect.right - mWindow.clipRect.left) &&
|
||||||
mAccumulatedInvalidRect.IntersectRect(mAccumulatedInvalidRect,
|
mWindow.height == (mWindow.clipRect.bottom - mWindow.clipRect.top),
|
||||||
nsIntRect(mWindow.clipRect.left, mWindow.clipRect.top,
|
"Clip rect should be same size as window when using layers");
|
||||||
mWindow.clipRect.right - mWindow.clipRect.left,
|
|
||||||
mWindow.clipRect.bottom - mWindow.clipRect.top));
|
|
||||||
|
|
||||||
// Clear accRect here to be able to pass
|
// Clear accRect here to be able to pass
|
||||||
// test_invalidate_during_plugin_paint test
|
// test_invalidate_during_plugin_paint test
|
||||||
nsIntRect rect = mAccumulatedInvalidRect;
|
nsIntRect rect = mAccumulatedInvalidRect;
|
||||||
mAccumulatedInvalidRect.Empty();
|
mAccumulatedInvalidRect.Empty();
|
||||||
|
|
||||||
|
// Fix up old invalidations that might have been made when our
|
||||||
|
// surface was a different size
|
||||||
|
gfxIntSize surfaceSize = mCurrentSurface->GetSize();
|
||||||
|
rect.IntersectRect(rect,
|
||||||
|
nsIntRect(0, 0, surfaceSize.width, surfaceSize.height));
|
||||||
|
|
||||||
if (!ReadbackDifferenceRect(rect)) {
|
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);
|
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> on surface <w=%d,h=%d>",
|
||||||
|
this, haveTransparentPixels ? " with alpha" : "",
|
||||||
|
rect.x, rect.y, rect.width, rect.height,
|
||||||
|
mCurrentSurface->GetSize().width, mCurrentSurface->GetSize().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);
|
PaintRectWithAlphaExtraction(rect, mCurrentSurface);
|
||||||
} else {
|
} else {
|
||||||
|
PLUGIN_LOG_DEBUG((" (onto opaque surface)"));
|
||||||
PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0));
|
PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0));
|
||||||
}
|
}
|
||||||
mHasPainted = true;
|
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,
|
NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
|
||||||
(uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
|
(uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
|
||||||
SurfaceDescriptor currSurf;
|
SurfaceDescriptor currSurf;
|
||||||
|
@ -2937,7 +2996,7 @@ PluginInstanceChild::ShowPluginFrame()
|
||||||
mCurrentSurfaceActor =
|
mCurrentSurfaceActor =
|
||||||
SendPPluginSurfaceConstructor(handle,
|
SendPPluginSurfaceConstructor(handle,
|
||||||
mCurrentSurface->GetSize(),
|
mCurrentSurface->GetSize(),
|
||||||
mIsTransparent);
|
haveTransparentPixels);
|
||||||
}
|
}
|
||||||
currSurf = mCurrentSurfaceActor;
|
currSurf = mCurrentSurfaceActor;
|
||||||
s->Flush();
|
s->Flush();
|
||||||
|
@ -2981,9 +3040,17 @@ PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect& rect)
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (mCurrentSurface->GetContentType() != mBackSurface->GetContentType())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (mSurfaceDifferenceRect.IsEmpty())
|
if (mSurfaceDifferenceRect.IsEmpty())
|
||||||
return true;
|
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
|
// Read back previous content
|
||||||
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||||
|
@ -3009,7 +3076,7 @@ PluginInstanceChild::InvalidateRectDelayed(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentInvalidateTask = nsnull;
|
mCurrentInvalidateTask = nsnull;
|
||||||
if (mAccumulatedInvalidRect.IsEmpty() || (mHasPainted && !IsVisible())) {
|
if (mAccumulatedInvalidRect.IsEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3021,7 +3088,7 @@ PluginInstanceChild::InvalidateRectDelayed(void)
|
||||||
void
|
void
|
||||||
PluginInstanceChild::AsyncShowPluginFrame(void)
|
PluginInstanceChild::AsyncShowPluginFrame(void)
|
||||||
{
|
{
|
||||||
if (mCurrentInvalidateTask || (mHasPainted && !IsVisible())) {
|
if (mCurrentInvalidateTask) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3057,9 +3124,111 @@ PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
|
||||||
AsyncShowPluginFrame();
|
AsyncShowPluginFrame();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If we were going to use layers rendering but it's not set up
|
||||||
|
// yet, and the plugin happens to call this first, we'll forward
|
||||||
|
// the invalidation to the browser. It's unclear whether
|
||||||
|
// non-layers plugins need this rect forwarded when their window
|
||||||
|
// width or height is 0, which it would be for layers plugins
|
||||||
|
// before their first SetWindow().
|
||||||
SendNPN_InvalidateRect(*aInvalidRect);
|
SendNPN_InvalidateRect(*aInvalidRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground,
|
||||||
|
const nsIntRect& aRect)
|
||||||
|
{
|
||||||
|
NS_ABORT_IF_FALSE(mIsTransparent, "Only transparent plugins use backgrounds");
|
||||||
|
|
||||||
|
if (!mBackground) {
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxIntSize bgSize = mBackground->GetSize();
|
||||||
|
mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect,
|
||||||
|
nsIntRect(0, 0, bgSize.width, bgSize.height));
|
||||||
|
AsyncShowPluginFrame();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX refactor me
|
||||||
|
mAccumulatedInvalidRect.UnionRect(aRect, mAccumulatedInvalidRect);
|
||||||
|
|
||||||
|
// The browser is limping along with a stale copy of our pixels.
|
||||||
|
// Try to repaint ASAP. This will ClearCurrentBackground() if we
|
||||||
|
// needed it.
|
||||||
|
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);
|
||||||
|
|
||||||
|
// NB: we don't have to XSync here because only ShowPluginFrame()
|
||||||
|
// uses mBackground, and it always XSyncs after finishing.
|
||||||
|
mBackground = nsnull;
|
||||||
|
AsyncShowPluginFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PPluginBackgroundDestroyerChild::Send__delete__(aActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PluginInstanceChild::DeallocPPluginBackgroundDestroyer(
|
||||||
|
PPluginBackgroundDestroyerChild* aActor)
|
||||||
|
{
|
||||||
|
delete aActor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat,
|
PluginInstanceChild::ScheduleTimer(uint32_t interval, bool repeat,
|
||||||
TimerFunc func)
|
TimerFunc func)
|
||||||
|
@ -3149,7 +3318,8 @@ PluginInstanceChild::SwapSurfaces()
|
||||||
// Outdated back surface... not usable anymore due to changed plugin size.
|
// Outdated back surface... not usable anymore due to changed plugin size.
|
||||||
// Dropping obsolete surface
|
// Dropping obsolete surface
|
||||||
if (mCurrentSurface && mBackSurface &&
|
if (mCurrentSurface && mBackSurface &&
|
||||||
mCurrentSurface->GetSize() != mBackSurface->GetSize()) {
|
(mCurrentSurface->GetSize() != mBackSurface->GetSize() ||
|
||||||
|
mCurrentSurface->GetContentType() != mBackSurface->GetContentType())) {
|
||||||
mCurrentSurface = nsnull;
|
mCurrentSurface = nsnull;
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
if (mCurrentSurfaceActor) {
|
if (mCurrentSurfaceActor) {
|
||||||
|
|
|
@ -240,6 +240,22 @@ private:
|
||||||
InternalGetNPObjectForValue(NPNVariable aValue,
|
InternalGetNPObjectForValue(NPNVariable aValue,
|
||||||
NPObject** aObject);
|
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)
|
#if defined(OS_WIN)
|
||||||
static bool RegisterWindowClass();
|
static bool RegisterWindowClass();
|
||||||
bool CreatePluginWindow();
|
bool CreatePluginWindow();
|
||||||
|
@ -294,7 +310,6 @@ private:
|
||||||
int nIndex,
|
int nIndex,
|
||||||
LONG newLong);
|
LONG newLong);
|
||||||
#endif
|
#endif
|
||||||
void HookSystemParametersInfo();
|
|
||||||
|
|
||||||
class FlashThrottleAsyncMsg : public ChildAsyncCall
|
class FlashThrottleAsyncMsg : public ChildAsyncCall
|
||||||
{
|
{
|
||||||
|
@ -411,6 +426,8 @@ private:
|
||||||
const NPCocoaEvent *mCurrentEvent;
|
const NPCocoaEvent *mCurrentEvent;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool CanPaintOnBackground();
|
||||||
|
|
||||||
bool IsVisible() {
|
bool IsVisible() {
|
||||||
return mWindow.clipRect.top != 0 ||
|
return mWindow.clipRect.top != 0 ||
|
||||||
mWindow.clipRect.left != 0 ||
|
mWindow.clipRect.left != 0 ||
|
||||||
|
@ -492,6 +509,13 @@ private:
|
||||||
// surface which is on ParentProcess side
|
// surface which is on ParentProcess side
|
||||||
nsRefPtr<gfxASurface> mBackSurface;
|
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
|
#ifdef XP_WIN
|
||||||
// These actors mirror mCurrentSurface/mBackSurface
|
// These actors mirror mCurrentSurface/mBackSurface
|
||||||
PPluginSurfaceChild* mCurrentSurfaceActor;
|
PPluginSurfaceChild* mCurrentSurfaceActor;
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "PluginInstanceParent.h"
|
#include "PluginInstanceParent.h"
|
||||||
|
|
||||||
#include "BrowserStreamParent.h"
|
#include "BrowserStreamParent.h"
|
||||||
|
#include "PluginBackgroundDestroyer.h"
|
||||||
#include "PluginModuleParent.h"
|
#include "PluginModuleParent.h"
|
||||||
#include "PluginStreamParent.h"
|
#include "PluginStreamParent.h"
|
||||||
#include "StreamNotifyParent.h"
|
#include "StreamNotifyParent.h"
|
||||||
|
@ -498,6 +499,12 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
||||||
const SurfaceDescriptor& newSurface,
|
const SurfaceDescriptor& newSurface,
|
||||||
SurfaceDescriptor* prevSurface)
|
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;
|
nsRefPtr<gfxASurface> surface;
|
||||||
if (newSurface.type() == SurfaceDescriptor::TShmem) {
|
if (newSurface.type() == SurfaceDescriptor::TShmem) {
|
||||||
if (!newSurface.get_Shmem().IsReadable()) {
|
if (!newSurface.get_Shmem().IsReadable()) {
|
||||||
|
@ -529,6 +536,11 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
||||||
#ifdef MOZ_X11
|
#ifdef MOZ_X11
|
||||||
if (mFrontSurface &&
|
if (mFrontSurface &&
|
||||||
mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib)
|
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);
|
XSync(DefaultXDisplay(), False);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -540,6 +552,9 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
||||||
mFrontSurface = surface;
|
mFrontSurface = surface;
|
||||||
RecvNPN_InvalidateRect(updatedRect);
|
RecvNPN_InvalidateRect(updatedRect);
|
||||||
|
|
||||||
|
PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)",
|
||||||
|
mFrontSurface.get()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +642,164 @@ PluginInstanceParent::IsRemoteDrawingCoreAnimation(PRBool *aDrawing)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
PluginInstanceParent::SetBackgroundUnknown()
|
||||||
|
{
|
||||||
|
PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this));
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#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(BackgroundDescriptor(), aRect);
|
||||||
|
|
||||||
|
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
|
NPError
|
||||||
PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
||||||
{
|
{
|
||||||
|
|
|
@ -282,13 +282,27 @@ public:
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
|
nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
|
||||||
#endif
|
#endif
|
||||||
nsresult SetBackgroundUnknown() { return NS_OK; }
|
nsresult SetBackgroundUnknown();
|
||||||
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
||||||
gfxContext** aCtx) { return NS_OK; }
|
gfxContext** aCtx);
|
||||||
nsresult EndUpdateBackground(gfxContext* aCtx,
|
nsresult EndUpdateBackground(gfxContext* aCtx,
|
||||||
const nsIntRect& aRect) { return NS_OK; }
|
const nsIntRect& aRect);
|
||||||
|
|
||||||
private:
|
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
|
// Quirks mode support for various plugin mime types
|
||||||
enum PluginQuirks {
|
enum PluginQuirks {
|
||||||
// OSX: Don't use the refresh timer for plug-ins
|
// OSX: Don't use the refresh timer for plug-ins
|
||||||
|
@ -345,6 +359,16 @@ private:
|
||||||
|
|
||||||
// ObjectFrame layer wrapper
|
// ObjectFrame layer wrapper
|
||||||
nsRefPtr<gfxASurface> mFrontSurface;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1876,7 +1876,6 @@ PluginModuleChild::InitQuirksModes(const nsCString& aMimeType)
|
||||||
mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
|
mQuirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
|
||||||
mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
|
mQuirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
|
||||||
mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
|
mQuirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
|
||||||
mQuirks |= QUIRK_FLASH_MASK_CLEARTYPE_SETTINGS;
|
|
||||||
mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
|
mQuirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -246,12 +246,9 @@ public:
|
||||||
// results so mouse input works when flash is displaying it's settings
|
// results so mouse input works when flash is displaying it's settings
|
||||||
// window.
|
// window.
|
||||||
QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5,
|
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,
|
|
||||||
// Win: Addresses a flash bug with mouse capture and full screen
|
// Win: Addresses a flash bug with mouse capture and full screen
|
||||||
// windows.
|
// windows.
|
||||||
QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 7,
|
QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
int GetQuirks() { return mQuirks; }
|
int GetQuirks() { return mQuirks; }
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
# ***** END LICENSE BLOCK *****
|
# ***** END LICENSE BLOCK *****
|
||||||
|
|
||||||
IPDLSRCS = \
|
IPDLSRCS = \
|
||||||
|
PPluginBackgroundDestroyer.ipdl \
|
||||||
PPluginModule.ipdl \
|
PPluginModule.ipdl \
|
||||||
PPluginIdentifier.ipdl \
|
PPluginIdentifier.ipdl \
|
||||||
PPluginInstance.ipdl \
|
PPluginInstance.ipdl \
|
||||||
|
|
|
@ -381,13 +381,17 @@ pluginHandleEvent(InstanceData* instanceData, void* event)
|
||||||
if (expose.x < clip.left || expose.y < clip.top ||
|
if (expose.x < clip.left || expose.y < clip.top ||
|
||||||
expose.x + expose.width > clip.right ||
|
expose.x + expose.width > clip.right ||
|
||||||
expose.y + expose.height > clip.bottom) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (expose.x < window.x || expose.y < window.y ||
|
if (expose.x < window.x || expose.y < window.y ||
|
||||||
expose.x + expose.width > window.x + int32_t(window.width) ||
|
expose.x + expose.width > window.x + int32_t(window.width) ||
|
||||||
expose.y + expose.height > window.y + int32_t(window.height)) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче