зеркало из https://github.com/mozilla/gecko-dev.git
Bug 556487 - Plugin Child/Parent async implementation. r=roc a=blocking2.0
This commit is contained in:
Родитель
def2c978ef
Коммит
b48ea2580b
|
@ -43,6 +43,14 @@
|
|||
#include "PluginStreamChild.h"
|
||||
#include "StreamNotifyChild.h"
|
||||
#include "PluginProcessChild.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxContext.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
#include "gfxSharedImageSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "gfxAlphaRecovery.h"
|
||||
|
||||
#include "mozilla/ipc/SyncChannel.h"
|
||||
|
||||
|
@ -90,6 +98,13 @@ const int kFlashWMUSERMessageThrottleDelayMs = 5;
|
|||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#endif // defined(XP_MACOSX)
|
||||
|
||||
template<>
|
||||
struct RunnableMethodTraits<PluginInstanceChild>
|
||||
{
|
||||
static void RetainCallee(PluginInstanceChild* obj) { }
|
||||
static void ReleaseCallee(PluginInstanceChild* obj) { }
|
||||
};
|
||||
|
||||
PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
||||
const nsCString& aMimeType)
|
||||
: mPluginIface(aPluginIface)
|
||||
|
@ -111,6 +126,18 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
|||
, mShContext(nsnull)
|
||||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mCurrentEvent(nsnull)
|
||||
#endif
|
||||
, mLayersRendering(PR_FALSE)
|
||||
, mAccumulatedInvalidRect(0,0,0,0)
|
||||
, mIsTransparent(PR_FALSE)
|
||||
, mSurfaceType(gfxASurface::SurfaceTypeMax)
|
||||
, mPendingForcePaint(PR_FALSE)
|
||||
, mCurrentInvalidateTask(nsnull)
|
||||
, mPendingPluginCall(PR_FALSE)
|
||||
, mDoAlphaExtraction(PR_FALSE)
|
||||
, mSurfaceDifferenceRect(0,0,0,0)
|
||||
#ifdef MOZ_X11
|
||||
, mFlash10Quirks(PR_FALSE)
|
||||
#endif
|
||||
{
|
||||
memset(&mWindow, 0, sizeof(mWindow));
|
||||
|
@ -128,6 +155,15 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
|||
#if defined(OS_WIN)
|
||||
InitPopupMenuHook();
|
||||
#endif // OS_WIN
|
||||
#ifdef MOZ_X11
|
||||
const char *description = NULL;
|
||||
mPluginIface->getvalue(GetNPP(), NPPVpluginDescriptionString,
|
||||
&description);
|
||||
if (description) {
|
||||
NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
|
||||
mFlash10Quirks = StringBeginsWith(nsDependentCString(description), flash10Head);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PluginInstanceChild::~PluginInstanceChild()
|
||||
|
@ -401,9 +437,9 @@ PluginInstanceChild::NPN_SetValue(NPPVariable aVar, void* aValue)
|
|||
|
||||
case NPPVpluginTransparentBool: {
|
||||
NPError rv;
|
||||
bool transparent = (NPBool) (intptr_t) aValue;
|
||||
mIsTransparent = (NPBool) (intptr_t) aValue;
|
||||
|
||||
if (!CallNPN_SetValue_NPPVpluginTransparent(transparent, &rv))
|
||||
if (!CallNPN_SetValue_NPPVpluginTransparent(mIsTransparent, &rv))
|
||||
return NPERR_GENERIC_ERROR;
|
||||
|
||||
return rv;
|
||||
|
@ -814,6 +850,8 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
|||
&mWsInfo.visual, &mWsInfo.depth))
|
||||
return false;
|
||||
|
||||
mLayersRendering = PR_FALSE;
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
if (gtk_check_version(2,18,7) != NULL) { // older
|
||||
if (aWindow.type == NPWindowTypeWindow) {
|
||||
|
@ -1941,16 +1979,457 @@ PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
|
|||
bool
|
||||
PluginInstanceChild::RecvPaintFinished(void)
|
||||
{
|
||||
return false;
|
||||
if (mPendingForcePaint) {
|
||||
nsIntRect r(0, 0, mWindow.width, mWindow.height);
|
||||
mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect);
|
||||
mPendingForcePaint = PR_FALSE;
|
||||
}
|
||||
if (!mAccumulatedInvalidRect.IsEmpty()) {
|
||||
AsyncShowPluginFrame();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
const NPRemoteWindow& aWindow)
|
||||
{
|
||||
AssertPluginThread();
|
||||
|
||||
mWindow.window = reinterpret_cast<void*>(aWindow.window);
|
||||
if (mWindow.width != aWindow.width || mWindow.height != aWindow.height) {
|
||||
mCurrentSurface = nsnull;
|
||||
mHelperSurface = nsnull;
|
||||
mPendingForcePaint = PR_TRUE;
|
||||
}
|
||||
mWindow.x = aWindow.x;
|
||||
mWindow.y = aWindow.y;
|
||||
mWindow.width = aWindow.width;
|
||||
mWindow.height = aWindow.height;
|
||||
mWindow.clipRect = aWindow.clipRect;
|
||||
mWindow.type = aWindow.type;
|
||||
|
||||
mLayersRendering = PR_TRUE;
|
||||
mSurfaceType = aSurfaceType;
|
||||
UpdateWindowAttributes(PR_TRUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline gfxRect
|
||||
GfxFromNsRect(const nsIntRect& aRect)
|
||||
{
|
||||
return gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
|
||||
}
|
||||
|
||||
PRBool
|
||||
PluginInstanceChild::CreateOptSurface(void)
|
||||
{
|
||||
nsRefPtr<gfxASurface> retsurf;
|
||||
gfxASurface::gfxImageFormat format =
|
||||
mIsTransparent ? gfxASurface::ImageFormatARGB32 :
|
||||
gfxASurface::ImageFormatRGB24;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
Display* dpy = mWsInfo.display;
|
||||
Screen* screen = DefaultScreenOfDisplay(dpy);
|
||||
if (format == gfxASurface::ImageFormatRGB24 &&
|
||||
DefaultDepth(dpy, DefaultScreen(dpy)) == 16) {
|
||||
format = gfxASurface::ImageFormatRGB16_565;
|
||||
}
|
||||
|
||||
if (mSurfaceType == gfxASurface::SurfaceTypeXlib) {
|
||||
XRenderPictFormat* xfmt = gfxXlibSurface::FindRenderFormat(dpy, format);
|
||||
if (!xfmt) {
|
||||
NS_ERROR("Need X falback surface, but FindRenderFormat failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
mCurrentSurface =
|
||||
gfxXlibSurface::Create(screen, xfmt,
|
||||
gfxIntSize(mWindow.width,
|
||||
mWindow.height));
|
||||
return mCurrentSurface != nsnull;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make common shmem implementation working for any platform
|
||||
mCurrentSurface = new gfxSharedImageSurface();
|
||||
if (NS_FAILED(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->
|
||||
Init(this, gfxIntSize(mWindow.width, mWindow.height), format))) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
|
||||
{
|
||||
if (!mCurrentSurface) {
|
||||
NS_ERROR("Cannot create helper surface without mCurrentSurface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_PLATFORM_MAEMO
|
||||
// On maemo plugins support non-default visual rendering
|
||||
PRBool supportNonDefaultVisual = PR_TRUE;
|
||||
#else
|
||||
PRBool supportNonDefaultVisual = PR_FALSE;
|
||||
#endif
|
||||
#ifdef MOZ_X11
|
||||
Screen* screen = DefaultScreenOfDisplay(mWsInfo.display);
|
||||
Visual* defaultVisual = DefaultVisualOfScreen(screen);
|
||||
Visual* visual = nsnull;
|
||||
Colormap colormap = 0;
|
||||
mDoAlphaExtraction = PR_FALSE;
|
||||
PRBool createHelperSurface = PR_FALSE;
|
||||
|
||||
if (mCurrentSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
static_cast<gfxXlibSurface*>(mCurrentSurface.get())->
|
||||
GetColormapAndVisual(&colormap, &visual);
|
||||
// Create helper surface if layer surface visual not same as default
|
||||
// and we don't support non-default visual rendering
|
||||
if (!visual || (defaultVisual != visual && !supportNonDefaultVisual)) {
|
||||
createHelperSurface = PR_TRUE;
|
||||
visual = defaultVisual;
|
||||
mDoAlphaExtraction = mIsTransparent;
|
||||
}
|
||||
} else if (mCurrentSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
// For image layer surface we should always create helper surface
|
||||
createHelperSurface = PR_TRUE;
|
||||
// Check if we can create helper surface with non-default visual
|
||||
visual = gfxXlibSurface::FindVisual(screen,
|
||||
static_cast<gfxImageSurface*>(mCurrentSurface.get())->Format());
|
||||
if (visual && defaultVisual != visual && !supportNonDefaultVisual) {
|
||||
visual = defaultVisual;
|
||||
mDoAlphaExtraction = mIsTransparent;
|
||||
}
|
||||
}
|
||||
|
||||
if (createHelperSurface) {
|
||||
if (!visual) {
|
||||
NS_ERROR("Need X falback surface, but visual failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
mHelperSurface =
|
||||
gfxXlibSurface::Create(screen, visual,
|
||||
mCurrentSurface->GetSize());
|
||||
if (!mHelperSurface) {
|
||||
NS_WARNING("Fail to create create helper surface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
PluginInstanceChild::EnsureCurrentBuffer(void)
|
||||
{
|
||||
if (mCurrentSurface) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (!mWindow.width || !mWindow.height) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!CreateOptSurface()) {
|
||||
NS_ERROR("Cannot create optimized surface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!MaybeCreatePlatformHelperSurface()) {
|
||||
NS_ERROR("Cannot create helper surface");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::UpdateWindowAttributes(PRBool aForceSetWindow)
|
||||
{
|
||||
nsRefPtr<gfxASurface> curSurface = mHelperSurface ? mHelperSurface : mCurrentSurface;
|
||||
PRBool needWindowUpdate = aForceSetWindow;
|
||||
#ifdef MOZ_X11
|
||||
Visual* visual = nsnull;
|
||||
Colormap colormap = 0;
|
||||
if (curSurface && curSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
static_cast<gfxXlibSurface*>(curSurface.get())->
|
||||
GetColormapAndVisual(&colormap, &visual);
|
||||
if (visual != mWsInfo.visual || colormap != mWsInfo.colormap) {
|
||||
mWsInfo.visual = visual;
|
||||
mWsInfo.colormap = colormap;
|
||||
needWindowUpdate = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!needWindowUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The clip rect is relative to drawable top-left.
|
||||
nsIntRect clipRect;
|
||||
mWindow.x = mWindow.y = 0;
|
||||
clipRect.SetRect(mWindow.x, mWindow.y, mWindow.width, mWindow.height);
|
||||
// Don't ask the plugin to draw outside the drawable.
|
||||
// This also ensures that the unsigned clip rectangle offsets won't be -ve.
|
||||
|
||||
NPRect newClipRect;
|
||||
newClipRect.left = clipRect.x;
|
||||
newClipRect.top = clipRect.y;
|
||||
newClipRect.right = clipRect.XMost();
|
||||
newClipRect.bottom = clipRect.YMost();
|
||||
mWindow.clipRect = newClipRect;
|
||||
|
||||
if (mPluginIface->setwindow) {
|
||||
mPluginIface->setwindow(&mData, &mWindow);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface)
|
||||
{
|
||||
UpdateWindowAttributes();
|
||||
#ifdef MOZ_X11
|
||||
NS_ASSERTION(aSurface->GetType() == gfxASurface::SurfaceTypeXlib,
|
||||
"Non supported platform surface type");
|
||||
|
||||
mPendingPluginCall = PR_TRUE;
|
||||
NPEvent pluginEvent;
|
||||
XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose;
|
||||
exposeEvent.type = GraphicsExpose;
|
||||
exposeEvent.display = mWsInfo.display;
|
||||
exposeEvent.drawable = static_cast<gfxXlibSurface*>(aSurface)->XDrawable();
|
||||
exposeEvent.x = aRect.x;
|
||||
exposeEvent.y = aRect.y;
|
||||
exposeEvent.width = aRect.width;
|
||||
exposeEvent.height = aRect.height;
|
||||
exposeEvent.count = 0;
|
||||
// information not set:
|
||||
exposeEvent.serial = 0;
|
||||
exposeEvent.send_event = False;
|
||||
exposeEvent.major_code = 0;
|
||||
exposeEvent.minor_code = 0;
|
||||
mPluginIface->event(&mData, reinterpret_cast<void*>(&exposeEvent));
|
||||
mPendingPluginCall = PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::PaintRectToSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface,
|
||||
const gfxRGBA& aColor)
|
||||
{
|
||||
// Render using temporary X surface, with copy to image surface
|
||||
nsIntRect plPaintRect(aRect);
|
||||
nsRefPtr<gfxASurface> renderSurface = aSurface;
|
||||
#ifdef MOZ_X11
|
||||
if (mIsTransparent && mFlash10Quirks) {
|
||||
// Work around a bug in Flash up to 10.1 d51 at least, where expose event
|
||||
// top left coordinates within the plugin-rect and not at the drawable
|
||||
// origin are misinterpreted. (We can move the top left coordinate
|
||||
// provided it is within the clipRect.), see bug 574583
|
||||
plPaintRect.SetRect(0, 0, aRect.XMost(), aRect.YMost());
|
||||
}
|
||||
if (renderSurface->GetType() != gfxASurface::SurfaceTypeXlib) {
|
||||
// On X11 we can paint to non Xlib surface only with HelperSurface
|
||||
renderSurface = mHelperSurface;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mIsTransparent) {
|
||||
// Clear surface content for transparent rendering
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(renderSurface);
|
||||
ctx->SetColor(aColor);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->Rectangle(GfxFromNsRect(plPaintRect));
|
||||
ctx->Fill();
|
||||
}
|
||||
|
||||
PaintRectToPlatformSurface(plPaintRect, renderSurface);
|
||||
|
||||
if (renderSurface != aSurface) {
|
||||
// Copy helper surface content to target
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
||||
ctx->SetSource(renderSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->Rectangle(GfxFromNsRect(aRect));
|
||||
ctx->Fill();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface)
|
||||
{
|
||||
// Paint onto black image
|
||||
PRBool needImageSurface = PR_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 = PR_FALSE;
|
||||
blackImage = surface->GetSubimage(GfxFromNsRect(aRect));
|
||||
}
|
||||
}
|
||||
// otherwise create new helper surface
|
||||
if (needImageSurface) {
|
||||
blackImage = new gfxImageSurface(clipSize, gfxASurface::ImageFormatARGB32);
|
||||
}
|
||||
|
||||
// Paint to black image
|
||||
blackImage->SetDeviceOffset(deviceOffset);
|
||||
PaintRectToSurface(aRect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
|
||||
|
||||
// Paint onto white image
|
||||
nsRefPtr<gfxImageSurface> whiteImage =
|
||||
new gfxImageSurface(clipSize, gfxASurface::ImageFormatRGB24);
|
||||
|
||||
whiteImage->SetDeviceOffset(deviceOffset);
|
||||
PaintRectToSurface(aRect, 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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (needImageSurface) {
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(blackImage);
|
||||
ctx->Rectangle(GfxFromNsRect(aRect));
|
||||
ctx->Fill();
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
PluginInstanceChild::ShowPluginFrame()
|
||||
{
|
||||
if (mPendingPluginCall) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (!EnsureCurrentBuffer()) {
|
||||
return PR_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));
|
||||
|
||||
// Cleare accRect here to be able to pass test_invalidate_during_plugin_paint test
|
||||
nsIntRect rect = mAccumulatedInvalidRect;
|
||||
mAccumulatedInvalidRect.Empty();
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// We can read safetly from XSurface, because PluginHost is not able to modify that surface
|
||||
if (mBackSurface && mBackSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
if (!mSurfaceDifferenceRect.IsEmpty()) {
|
||||
// Read back previous content
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mCurrentSurface);
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(mBackSurface);
|
||||
// Subtract from mSurfaceDifferenceRect area which is overlapping with rect
|
||||
nsIntRegion result;
|
||||
result.Sub(mSurfaceDifferenceRect, nsIntRegion(rect));
|
||||
nsIntRegionRectIterator iter(result);
|
||||
const nsIntRect* r;
|
||||
while ((r = iter.Next()) != nsnull) {
|
||||
ctx->Rectangle(GfxFromNsRect(*r));
|
||||
}
|
||||
ctx->Fill();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Just repaint whole plugin, because we cannot read back from Shmem which is owned by another process
|
||||
rect.SetRect(0, 0, mWindow.width, mWindow.height);
|
||||
}
|
||||
|
||||
if (mDoAlphaExtraction) {
|
||||
PaintRectWithAlphaExtraction(rect, mCurrentSurface);
|
||||
} else {
|
||||
PaintRectToSurface(rect, mCurrentSurface, gfxRGBA(0.0, 0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
NPRect r = { rect.y, rect.x, rect.YMost(), rect.XMost() };
|
||||
SurfaceDescriptor currSurf;
|
||||
SurfaceDescriptor outSurf = null_t();
|
||||
#ifdef MOZ_X11
|
||||
if (mCurrentSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mCurrentSurface.get());
|
||||
currSurf = SurfaceDescriptorX11(xsurf->XDrawable(), xsurf->XRenderFormat()->id,
|
||||
mCurrentSurface->GetSize());
|
||||
// Need to sync all pending x-paint requests
|
||||
// before giving drawable to another process
|
||||
XSync(mWsInfo.display, False);
|
||||
} else
|
||||
#endif
|
||||
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface)) {
|
||||
currSurf = static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem();
|
||||
} else {
|
||||
NS_RUNTIMEABORT("Surface type is not remotable");
|
||||
return PR_FALSE;
|
||||
}
|
||||
if (!SendShow(r, currSurf, &outSurf)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> tmp = mCurrentSurface;
|
||||
mCurrentSurface = mBackSurface;
|
||||
mBackSurface = tmp;
|
||||
// Outdated back surface... not usable anymore due to changed plugin size.
|
||||
// Dropping obsolete surface
|
||||
if (mCurrentSurface && mBackSurface &&
|
||||
mCurrentSurface->GetSize() != mBackSurface->GetSize()) {
|
||||
mCurrentSurface = nsnull;
|
||||
}
|
||||
mSurfaceDifferenceRect = rect;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::InvalidateRectDelayed(void)
|
||||
{
|
||||
if (!mCurrentInvalidateTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCurrentInvalidateTask = nsnull;
|
||||
if (mAccumulatedInvalidRect.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ShowPluginFrame()) {
|
||||
AsyncShowPluginFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::AsyncShowPluginFrame(void)
|
||||
{
|
||||
if (mCurrentInvalidateTask) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCurrentInvalidateTask =
|
||||
NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed);
|
||||
MessageLoop::current()->PostTask(FROM_HERE, mCurrentInvalidateTask);
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
|
||||
{
|
||||
|
@ -1967,6 +2446,17 @@ PluginInstanceChild::InvalidateRect(NPRect* aInvalidRect)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (mLayersRendering) {
|
||||
nsIntRect r(aInvalidRect->left, aInvalidRect->top,
|
||||
aInvalidRect->right - aInvalidRect->left,
|
||||
aInvalidRect->bottom - aInvalidRect->top);
|
||||
|
||||
mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect);
|
||||
// If we are able to paint and invalidate sent, then reset
|
||||
// accumulated rectangle
|
||||
AsyncShowPluginFrame();
|
||||
return;
|
||||
}
|
||||
SendNPN_InvalidateRect(*aInvalidRect);
|
||||
}
|
||||
|
||||
|
@ -2044,6 +2534,19 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
AssertPluginThread();
|
||||
|
||||
if (mBackSurface) {
|
||||
// Get last surface back, and drop it
|
||||
SurfaceDescriptor temp = null_t();
|
||||
NPRect r = { 0, 0, 1, 1 };
|
||||
SendShow(r, temp, &temp);
|
||||
}
|
||||
if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface))
|
||||
DeallocShmem(static_cast<gfxSharedImageSurface*>(mCurrentSurface.get())->GetShmem());
|
||||
if (gfxSharedImageSurface::IsSharedImage(mBackSurface))
|
||||
DeallocShmem(static_cast<gfxSharedImageSurface*>(mBackSurface.get())->GetShmem());
|
||||
mCurrentSurface = nsnull;
|
||||
mBackSurface = nsnull;
|
||||
|
||||
nsTArray<PBrowserStreamChild*> streams;
|
||||
ManagedPBrowserStreamChild(streams);
|
||||
|
||||
|
@ -2065,6 +2568,10 @@ PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
|
|||
}
|
||||
|
||||
mTimers.Clear();
|
||||
if (mCurrentInvalidateTask) {
|
||||
mCurrentInvalidateTask->Cancel();
|
||||
mCurrentInvalidateTask = nsnull;
|
||||
}
|
||||
|
||||
PluginModuleChild::current()->NPP_Destroy(this);
|
||||
mData.ndata = 0;
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "nsRect.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "mozilla/PaintTracker.h"
|
||||
#include "gfxASurface.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -378,6 +379,102 @@ public:
|
|||
private:
|
||||
const NPCocoaEvent *mCurrentEvent;
|
||||
#endif
|
||||
|
||||
// ShowPluginFrame - in general does four things:
|
||||
// 1) Create mCurrentSurface optimized for rendering to parent process
|
||||
// 2) Updated mCurrentSurface to be a complete copy of mBackSurface
|
||||
// 3) Draw the invalidated plugin area into mCurrentSurface
|
||||
// 4) Send it to parent process.
|
||||
PRBool ShowPluginFrame(void);
|
||||
|
||||
// Post ShowPluginFrame task
|
||||
void AsyncShowPluginFrame(void);
|
||||
|
||||
// In the PaintRect functions, aSurface is the size of the full plugin window. Each PaintRect function
|
||||
// renders into the subrectangle aRect of aSurface (possibly more if we're working around a Flash bug).
|
||||
|
||||
// Paint plugin content rectangle to surface with bg color filling
|
||||
void PaintRectToSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface,
|
||||
const gfxRGBA& aColor);
|
||||
|
||||
// Render plugin content to surface using
|
||||
// white/black image alpha extraction algorithm
|
||||
void PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface);
|
||||
|
||||
// Call plugin NPAPI function to render plugin content to surface
|
||||
// @param - aSurface - should be compatible with current platform plugin rendering
|
||||
// @return - FALSE if plugin not painted to surface
|
||||
void PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface);
|
||||
|
||||
// Update NPWindow platform attributes and call plugin "setwindow"
|
||||
// @param - aForceSetWindow - call setwindow even if platform attributes are the same
|
||||
void UpdateWindowAttributes(PRBool aForceSetWindow = PR_FALSE);
|
||||
|
||||
// Create optimized mCurrentSurface for parent process rendering
|
||||
// @return FALSE if optimized surface not created
|
||||
PRBool CreateOptSurface(void);
|
||||
|
||||
// Create mHelperSurface if mCurrentSurface non compatible with plugins
|
||||
// @return TRUE if helper surface created successfully, or not needed
|
||||
PRBool MaybeCreatePlatformHelperSurface(void);
|
||||
|
||||
// Make sure that we have surface for rendering
|
||||
PRBool EnsureCurrentBuffer(void);
|
||||
|
||||
// Helper function for delayed InvalidateRect call
|
||||
// non null mCurrentInvalidateTask will call this function
|
||||
void InvalidateRectDelayed(void);
|
||||
|
||||
// Set as true when SetupLayer called
|
||||
// and go with different path in InvalidateRect function
|
||||
PRPackedBool mLayersRendering;
|
||||
// Current surface available for rendering
|
||||
nsRefPtr<gfxASurface> mCurrentSurface;
|
||||
// Back surface, just keeping reference to
|
||||
// surface which is on ParentProcess side
|
||||
nsRefPtr<gfxASurface> mBackSurface;
|
||||
// Accumulated invalidate rect, while back buffer is not accessible
|
||||
nsIntRect mAccumulatedInvalidRect;
|
||||
// Plugin only call SetTransparent
|
||||
// and does not remember their transparent state
|
||||
// and p->getvalue return always false
|
||||
PRPackedBool mIsTransparent;
|
||||
// Surface type optimized of parent process
|
||||
gfxSurfaceType mSurfaceType;
|
||||
|
||||
// set TRUE if plugin surface dropped in asyncSetWindow
|
||||
// if TRUE then initiate full repaint in RecvPaintFinished
|
||||
PRPackedBool mPendingForcePaint;
|
||||
|
||||
// Keep InvalidateRect task pointer to be able Cancel it on Destroy
|
||||
CancelableTask *mCurrentInvalidateTask;
|
||||
|
||||
// True while plugin-child in plugin call
|
||||
// Use to prevent plugin paint re-enter
|
||||
PRPackedBool mPendingPluginCall;
|
||||
|
||||
// On some platforms, plugins may not support rendering to a surface with
|
||||
// alpha, or not support rendering to an image surface.
|
||||
// In those cases we need to draw to a temporary platform surface; we cache
|
||||
// that surface here.
|
||||
nsRefPtr<gfxASurface> mHelperSurface;
|
||||
|
||||
// true when plugin does not support painting to ARGB32 surface
|
||||
// this is false for maemo platform, and false if plugin
|
||||
// supports NPPVpluginTransparentAlphaBool (which is not part of NPAPI yet)
|
||||
PRPackedBool mDoAlphaExtraction;
|
||||
|
||||
// Cached rectangle rendered to previous surface(mBackSurface)
|
||||
// Used for reading back to current surface and syncing data
|
||||
nsIntRect mSurfaceDifferenceRect;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Used with windowless flash plugin only, see bug 574583
|
||||
PRPackedBool mFlash10Quirks;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
|
|
@ -46,6 +46,16 @@
|
|||
#include "npfunctions.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "gfxASurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
#ifdef MOZ_X11
|
||||
#include "gfxXlibSurface.h"
|
||||
#endif
|
||||
#include "gfxContext.h"
|
||||
#include "gfxColor.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <windowsx.h>
|
||||
|
@ -88,6 +98,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
|
|||
, mDrawingModel(NPDrawingModelCoreGraphics)
|
||||
, mIOSurface(nsnull)
|
||||
#endif
|
||||
, mSentPaintNotification(PR_FALSE)
|
||||
{
|
||||
InitQuirksModes(aMimeType);
|
||||
}
|
||||
|
@ -465,26 +476,96 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect,
|
|||
const SurfaceDescriptor& newSurface,
|
||||
SurfaceDescriptor* prevSurface)
|
||||
{
|
||||
*prevSurface = null_t();
|
||||
return false;
|
||||
nsRefPtr<gfxASurface> surface;
|
||||
if (newSurface.type() == SurfaceDescriptor::TShmem) {
|
||||
if (!newSurface.get_Shmem().IsReadable()) {
|
||||
NS_WARNING("back surface not readable");
|
||||
return false;
|
||||
}
|
||||
surface = new gfxSharedImageSurface(newSurface.get_Shmem());
|
||||
}
|
||||
#ifdef MOZ_X11
|
||||
else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) {
|
||||
SurfaceDescriptorX11 xdesc = newSurface.get_SurfaceDescriptorX11();
|
||||
XRenderPictFormat pf;
|
||||
pf.id = xdesc.xrenderPictID();
|
||||
XRenderPictFormat *incFormat =
|
||||
XRenderFindFormat(DefaultXDisplay(), PictFormatID, &pf, 0);
|
||||
surface =
|
||||
new gfxXlibSurface(DefaultScreenOfDisplay(DefaultXDisplay()),
|
||||
xdesc.XID(), incFormat, xdesc.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
mSentPaintNotification = PR_FALSE;
|
||||
if (mFrontSurface) {
|
||||
#ifdef MOZ_X11
|
||||
if (mFrontSurface->GetType() == gfxASurface::SurfaceTypeXlib) {
|
||||
gfxXlibSurface *xsurf = static_cast<gfxXlibSurface*>(mFrontSurface.get());
|
||||
*prevSurface =
|
||||
SurfaceDescriptorX11(xsurf->XDrawable(), xsurf->XRenderFormat()->id,
|
||||
mFrontSurface->GetSize());
|
||||
} else
|
||||
#endif
|
||||
if (gfxSharedImageSurface::IsSharedImage(mFrontSurface)) {
|
||||
*prevSurface = static_cast<gfxSharedImageSurface*>(mFrontSurface.get())->GetShmem();
|
||||
} else {
|
||||
*prevSurface = null_t();
|
||||
}
|
||||
} else {
|
||||
*prevSurface = null_t();
|
||||
}
|
||||
mFrontSurface = surface;
|
||||
RecvNPN_InvalidateRect(updatedRect);
|
||||
#ifdef MOZ_X11
|
||||
// Sync prevSurface before sending to child
|
||||
if (prevSurface->type() == SurfaceDescriptor::TSurfaceDescriptorX11) {
|
||||
XSync(DefaultXDisplay(), False);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
NPRemoteWindow window;
|
||||
mWindowType = aWindow->type;
|
||||
window.window = reinterpret_cast<unsigned long>(aWindow->window);
|
||||
window.x = aWindow->x;
|
||||
window.y = aWindow->y;
|
||||
window.width = aWindow->width;
|
||||
window.height = aWindow->height;
|
||||
window.clipRect = aWindow->clipRect;
|
||||
window.type = aWindow->type;
|
||||
mSentPaintNotification = PR_FALSE;
|
||||
if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
|
||||
window))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::NotifyPainted(void)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
bool rv = true;
|
||||
if (!mSentPaintNotification) {
|
||||
rv = SendPaintFinished();
|
||||
mSentPaintNotification = rv;
|
||||
}
|
||||
return rv ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PluginInstanceParent::GetSurface(gfxASurface** aSurface)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (mFrontSurface) {
|
||||
NS_ADDREF(*aSurface = mFrontSurface);
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NPError
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsRect.h"
|
||||
#include "gfxASurface.h"
|
||||
#ifdef MOZ_X11
|
||||
class gfxXlibSurface;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
@ -314,6 +318,12 @@ private:
|
|||
int16_t mDrawingModel;
|
||||
nsIOSurface *mIOSurface;
|
||||
#endif // definied(OS_MACOSX)
|
||||
|
||||
// ObjectFrame layer wrapper
|
||||
nsRefPtr<gfxASurface> mFrontSurface;
|
||||
|
||||
// Don't spam plugin process with extra paint notifications
|
||||
PRPackedBool mSentPaintNotification;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -90,6 +90,11 @@ PluginProcessChild::Init()
|
|||
# error Sorry
|
||||
#endif
|
||||
|
||||
if (NS_FAILED(nsRegion::InitStatic())) {
|
||||
NS_ERROR("Could not initialize nsRegion");
|
||||
return false;
|
||||
}
|
||||
|
||||
mPlugin.Init(pluginFilename, ParentHandle(),
|
||||
IOThreadChild::message_loop(),
|
||||
IOThreadChild::channel());
|
||||
|
@ -103,6 +108,7 @@ PluginProcessChild::CleanUp()
|
|||
#ifdef XP_WIN
|
||||
::OleUninitialize();
|
||||
#endif
|
||||
nsRegion::ShutdownStatic();
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
Загрузка…
Ссылка в новой задаче