зеркало из https://github.com/mozilla/gecko-dev.git
Bug 626602. Part 3: Hook up ReadbackLayers in nsObjectFrame. r=cjones
This commit is contained in:
Родитель
1619ca83d2
Коммит
ac0601703a
|
@ -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,
|
||||
|
|
|
@ -164,6 +164,7 @@ enum { XKeyPress = KeyPress };
|
|||
#include "gfxImageSurface.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "Layers.h"
|
||||
#include "ReadbackLayer.h"
|
||||
|
||||
// accessibility support
|
||||
#ifdef ACCESSIBILITY
|
||||
|
@ -238,6 +239,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
|
||||
|
@ -467,6 +470,11 @@ 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
|
||||
void SetBackgroundUnknown() {}
|
||||
already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect) { return nsnull; }
|
||||
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect) {}
|
||||
|
||||
PRBool UseAsyncRendering()
|
||||
{
|
||||
PRBool useAsyncRendering;
|
||||
|
@ -624,6 +632,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
|
||||
|
||||
|
@ -669,7 +724,6 @@ NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -707,6 +761,10 @@ nsObjectFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
|||
mWidget->Destroy();
|
||||
}
|
||||
|
||||
if (mBackgroundSink) {
|
||||
mBackgroundSink->Destroy();
|
||||
}
|
||||
|
||||
nsObjectFrameSuper::DestroyFrom(aDestructRoot);
|
||||
}
|
||||
|
||||
|
@ -1277,20 +1335,56 @@ 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,
|
||||
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);
|
||||
}
|
||||
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return LAYER_ACTIVE;
|
||||
}
|
||||
};
|
||||
|
||||
static nsRect
|
||||
GetDesiredDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
|
||||
{
|
||||
nsRect r = aFrame->GetContentRect() - aFrame->GetPosition() +
|
||||
aItem->ToReferenceFrame();
|
||||
return r;
|
||||
}
|
||||
|
||||
static nsRect
|
||||
GetDrawnDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
|
||||
{
|
||||
nsRect r = aFrame->GetContentRect() - aFrame->GetPosition() +
|
||||
aItem->ToReferenceFrame();
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
if (mozilla::LAYER_ACTIVE == f->GetLayerState(aBuilder, nsnull)) {
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(aFrame);
|
||||
if (LAYER_ACTIVE == f->GetLayerState(aBuilder, nsnull)) {
|
||||
ImageContainer* c = f->GetImageContainer();
|
||||
if (c) {
|
||||
gfxIntSize size = c->GetCurrentSize();
|
||||
|
@ -1305,6 +1399,40 @@ nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
|||
return r;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return GetDesiredDisplayItemBounds(aBuilder, this, mFrame);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
nsRegion* aVisibleRegion,
|
||||
PRBool& aContainsRootContentDocBG)
|
||||
{
|
||||
if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, aContainsRootContentDocBG))
|
||||
return PR_FALSE;
|
||||
// *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, GetBounds(aBuilder));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
// We use display lists to notify plugins of visibility. But we
|
||||
// also need to return the "real" visible bounds, possibly those of
|
||||
// our Image, when actually painting. Usually those will be the
|
||||
// same, but for the plugin to paint initially, something needs to
|
||||
// notify it that it's visible. So return whichever the appropriate
|
||||
// rect here.
|
||||
return aBuilder->IsForPluginGeometry() ?
|
||||
GetDesiredDisplayItemBounds(aBuilder, this, mFrame) :
|
||||
GetDrawnDisplayItemBounds(aBuilder, this, mFrame);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsIRenderingContext* aCtx)
|
||||
|
@ -1455,6 +1583,18 @@ PRBool
|
|||
nsObjectFrame::IsOpaque() const
|
||||
{
|
||||
#if defined(XP_MACOSX)
|
||||
// ???
|
||||
return PR_FALSE;
|
||||
#else
|
||||
return !IsTransparentMode();
|
||||
#endif
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsObjectFrame::IsTransparentMode() const
|
||||
{
|
||||
#if defined(XP_MACOSX)
|
||||
// ???
|
||||
return PR_FALSE;
|
||||
#else
|
||||
if (!mInstanceOwner)
|
||||
|
@ -1463,7 +1603,7 @@ nsObjectFrame::IsOpaque() const
|
|||
NPWindow *window;
|
||||
mInstanceOwner->GetWindow(window);
|
||||
if (window->type != NPWindowTypeDrawable)
|
||||
return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPluginInstance> pi;
|
||||
|
@ -1473,7 +1613,7 @@ nsObjectFrame::IsOpaque() const
|
|||
|
||||
PRBool transparent = PR_FALSE;
|
||||
pi->IsTransparent(&transparent);
|
||||
return !transparent;
|
||||
return transparent;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1482,10 +1622,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);
|
||||
|
||||
|
@ -1530,6 +1672,14 @@ nsObjectFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
|
||||
nsDisplayItem::TYPE_PRINT_PLUGIN));
|
||||
} else {
|
||||
if (aBuilder->IsPaintingToWindow() &&
|
||||
GetLayerState(aBuilder, nsnull) == LAYER_ACTIVE &&
|
||||
IsTransparentMode()) {
|
||||
rv = replacedContent.AppendNewToTop(new (aBuilder)
|
||||
nsDisplayPluginReadback(aBuilder, this));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = replacedContent.AppendNewToTop(new (aBuilder)
|
||||
nsDisplayPlugin(aBuilder, this));
|
||||
}
|
||||
|
@ -1831,7 +1981,8 @@ nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
|
|||
return mozilla::LAYER_NONE;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
|
||||
if (aManager &&
|
||||
aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
|
||||
mInstanceOwner->GetEventModel() == NPEventModelCocoa &&
|
||||
mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics &&
|
||||
mInstanceOwner->IsRemoteDrawingCoreAnimation())
|
||||
|
@ -1862,6 +2013,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.
|
||||
|
@ -1869,49 +2032,66 @@ nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
nsRefPtr<Layer> layer =
|
||||
(aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
|
||||
|
||||
if (!layer) {
|
||||
if (mInstanceOwner->UseAsyncRendering()) {
|
||||
if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
|
||||
if (!layer) {
|
||||
mInstanceOwner->NotifyPaintWaiter(aBuilder);
|
||||
// Initialize ImageLayer
|
||||
layer = aManager->CreateImageLayer();
|
||||
if (!layer)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Initialize ImageLayer
|
||||
layer = aManager->CreateImageLayer();
|
||||
}
|
||||
|
||||
if (!layer)
|
||||
return nsnull;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Until we get async plugins on mac we need to manually trigger the DrawRect event
|
||||
mInstanceOwner->DoCocoaEventDrawRect(r, nsnull);
|
||||
// Until we get async plugins on mac we need to manually trigger the DrawRect event
|
||||
mInstanceOwner->DoCocoaEventDrawRect(r, nsnull);
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "ObjectFrame works only with ImageLayer");
|
||||
// Create image
|
||||
nsRefPtr<ImageContainer> container = GetImageContainer(aManager);
|
||||
if (!container)
|
||||
return nsnull;
|
||||
NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
|
||||
|
||||
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);
|
||||
} else {
|
||||
NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
|
||||
"Unknown item type");
|
||||
NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
|
||||
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
r.pos.x += (r.Width() - size.width) / 2;
|
||||
r.pos.y += (r.Height() - size.height) / 2;
|
||||
transform.Translate(r.pos);
|
||||
|
||||
layer->SetTransform(gfx3DMatrix::From2D(transform));
|
||||
nsRefPtr<Layer> result = layer.forget();
|
||||
return result.forget();
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2076,7 +2256,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)
|
||||
|
|
|
@ -63,9 +63,12 @@ class nsPresContext;
|
|||
class nsDisplayPlugin;
|
||||
class nsIDOMElement;
|
||||
class nsIOSurface;
|
||||
class PluginBackgroundSink;
|
||||
|
||||
#define nsObjectFrameSuper nsFrame
|
||||
|
||||
#define NS_OBJECT_NEEDS_SET_IMAGE NS_FRAME_STATE_BIT(31)
|
||||
|
||||
class nsObjectFrame : public nsObjectFrameSuper,
|
||||
public nsIObjectFrame,
|
||||
public nsIReflowCallback {
|
||||
|
@ -177,6 +180,10 @@ 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);
|
||||
|
@ -230,6 +237,7 @@ protected:
|
|||
PRBool IsHidden(PRBool aCheckVisibilityStyle = PR_TRUE) const;
|
||||
|
||||
PRBool IsOpaque() const;
|
||||
PRBool IsTransparentMode() const;
|
||||
|
||||
void NotifyContentObjectWrapper();
|
||||
|
||||
|
@ -273,6 +281,7 @@ protected:
|
|||
|
||||
friend class nsPluginInstanceOwner;
|
||||
friend class nsDisplayPlugin;
|
||||
friend class PluginBackgroundSink;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -290,6 +299,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
|
||||
|
@ -348,7 +362,8 @@ public:
|
|||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager)
|
||||
{
|
||||
return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder, aManager);
|
||||
return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder,
|
||||
aManager);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Загрузка…
Ссылка в новой задаче