mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 564991. Part 34: Make sure that ThebesLayerBuffers are always allocated as similar surfaces to the widget surface, whenever possible. r=cjones
This commit is contained in:
parent
cc0c10fa76
commit
e98a518e3c
@ -209,6 +209,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
|
||||
#include "nsHTMLMediaElement.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
const char kLoadAsData[] = "loadAsData";
|
||||
|
||||
@ -6128,7 +6129,7 @@ nsContentUtils::PlatformToDOMLineBreaks(nsString &aString)
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::layers::LayerManager>
|
||||
already_AddRefed<LayerManager>
|
||||
nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc)
|
||||
{
|
||||
nsIDocument* doc = aDoc;
|
||||
@ -6163,14 +6164,13 @@ nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc)
|
||||
nsIWidget* widget =
|
||||
nsLayoutUtils::GetDisplayRootFrame(rootFrame)->GetNearestWidget();
|
||||
if (widget) {
|
||||
nsRefPtr<mozilla::layers::LayerManager> manager = widget->GetLayerManager();
|
||||
nsRefPtr<LayerManager> manager = widget->GetLayerManager();
|
||||
return manager.forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<mozilla::layers::LayerManager> manager =
|
||||
new mozilla::layers::BasicLayerManager(nsnull);
|
||||
nsRefPtr<LayerManager> manager = new BasicLayerManager();
|
||||
return manager.forget();
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "ThebesLayerBuffer.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
|
||||
@ -323,8 +324,22 @@ BasicThebesLayer::Paint(gfxContext* aContext,
|
||||
}
|
||||
|
||||
{
|
||||
nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer();
|
||||
if (!referenceSurface) {
|
||||
gfxContext* defaultTarget = BasicManager()->GetDefaultTarget();
|
||||
if (defaultTarget) {
|
||||
referenceSurface = defaultTarget->CurrentSurface();
|
||||
} else {
|
||||
nsIWidget* widget = BasicManager()->GetRetainerWidget();
|
||||
if (widget) {
|
||||
referenceSurface = widget->GetThebesSurface();
|
||||
} else {
|
||||
referenceSurface = aContext->CurrentSurface();
|
||||
}
|
||||
}
|
||||
}
|
||||
ThebesLayerBuffer::PaintState state =
|
||||
mBuffer.BeginPaint(this, aContext, flags);
|
||||
mBuffer.BeginPaint(this, referenceSurface, flags);
|
||||
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
||||
|
||||
if (state.mContext) {
|
||||
@ -697,13 +712,23 @@ MayHaveOverlappingOrTransparentLayers(Layer* aLayer,
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager(gfxContext* aContext) :
|
||||
mDefaultTarget(aContext)
|
||||
BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
|
||||
mWidget(aWidget)
|
||||
#ifdef DEBUG
|
||||
, mPhase(PHASE_NONE)
|
||||
#endif
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE),
|
||||
mRetain(PR_FALSE)
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicLayerManager);
|
||||
NS_ASSERTION(aWidget, "Must provide a widget");
|
||||
}
|
||||
|
||||
BasicLayerManager::BasicLayerManager() :
|
||||
mWidget(nsnull)
|
||||
#ifdef DEBUG
|
||||
, mPhase(PHASE_NONE)
|
||||
#endif
|
||||
, mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
|
||||
{
|
||||
MOZ_COUNT_CTOR(BasicLayerManager);
|
||||
}
|
||||
@ -724,14 +749,6 @@ BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
|
||||
mDoubleBuffering = aDoubleBuffering;
|
||||
}
|
||||
|
||||
void
|
||||
BasicLayerManager::SetRetain(PRBool aRetain)
|
||||
{
|
||||
NS_ASSERTION(!InTransaction(),
|
||||
"Must set retained mode outside transaction");
|
||||
mRetain = aRetain;
|
||||
}
|
||||
|
||||
void
|
||||
BasicLayerManager::BeginTransaction()
|
||||
{
|
||||
|
@ -45,11 +45,11 @@
|
||||
#include "nsAutoRef.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BasicThebesLayer;
|
||||
|
||||
/**
|
||||
* This is a cairo/Thebes-only, main-thread-only implementation of layers.
|
||||
*
|
||||
@ -61,19 +61,29 @@ class BasicThebesLayer;
|
||||
class THEBES_API BasicLayerManager : public LayerManager {
|
||||
public:
|
||||
/**
|
||||
* Construct a BasicLayerManager which will render to aContext when
|
||||
* BeginTransaction is called. This can be null, in which case
|
||||
* transactions started with BeginTransaction will not do any painting.
|
||||
* Construct a BasicLayerManager which will have no default
|
||||
* target context. SetDefaultTarget or BeginTransactionWithTarget
|
||||
* must be called for any rendering to happen. ThebesLayers will not
|
||||
* be retained.
|
||||
*/
|
||||
BasicLayerManager(gfxContext* aContext);
|
||||
virtual ~BasicLayerManager();
|
||||
|
||||
BasicLayerManager();
|
||||
/**
|
||||
* When aRetain is true, we will try to retain the visible contents of
|
||||
* ThebesLayers as cairo surfaces. This can only be called outside a
|
||||
* transaction. By default, layer contents are not retained.
|
||||
* Construct a BasicLayerManager which will have no default
|
||||
* target context. SetDefaultTarget or BeginTransactionWithTarget
|
||||
* must be called for any rendering to happen. ThebesLayers will be
|
||||
* retained; that is, we will try to retain the visible contents of
|
||||
* ThebesLayers as cairo surfaces. We create ThebesLayer buffers by
|
||||
* creating similar surfaces to the default target context, or to
|
||||
* aWidget's GetThebesSurface if there is no default target context, or
|
||||
* to the passed-in context if there is no widget and no default
|
||||
* target context.
|
||||
*
|
||||
* This does not keep a strong reference to the widget, so the caller
|
||||
* must ensure that the widget outlives the layer manager or call
|
||||
* ClearWidget before the widget dies.
|
||||
*/
|
||||
void SetRetain(PRBool aRetain);
|
||||
BasicLayerManager(nsIWidget* aWidget);
|
||||
virtual ~BasicLayerManager();
|
||||
|
||||
/**
|
||||
* Set the default target context that will be used when BeginTransaction
|
||||
@ -91,6 +101,10 @@ public:
|
||||
BUFFER_BUFFERED
|
||||
};
|
||||
void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
|
||||
gfxContext* GetDefaultTarget() { return mDefaultTarget; }
|
||||
|
||||
nsIWidget* GetRetainerWidget() { return mWidget; }
|
||||
void ClearRetainerWidget() { mWidget = nsnull; }
|
||||
|
||||
virtual void BeginTransaction();
|
||||
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
|
||||
@ -113,7 +127,7 @@ public:
|
||||
PRBool InTransaction() { return mPhase != PHASE_NONE; }
|
||||
#endif
|
||||
gfxContext* GetTarget() { return mTarget; }
|
||||
PRBool IsRetained() { return mRetain; }
|
||||
PRBool IsRetained() { return mWidget != nsnull; }
|
||||
|
||||
private:
|
||||
// Paints aLayer to mTarget.
|
||||
@ -128,6 +142,9 @@ private:
|
||||
void PopGroupWithCachedSurface(gfxContext *aTarget,
|
||||
const gfxPoint& aSavedOffset);
|
||||
|
||||
// Widget whose surface should be used as the basis for ThebesLayer
|
||||
// buffers.
|
||||
nsIWidget* mWidget;
|
||||
// The default context for BeginTransaction.
|
||||
nsRefPtr<gfxContext> mDefaultTarget;
|
||||
// The context to draw into.
|
||||
@ -143,7 +160,6 @@ private:
|
||||
|
||||
BufferMode mDoubleBuffering;
|
||||
PRPackedBool mUsingDefaultTarget;
|
||||
PRPackedBool mRetain;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -132,14 +132,14 @@ CreateBuffer(gfxASurface* aTargetSurface, gfxASurface::gfxContentType aType,
|
||||
}
|
||||
|
||||
ThebesLayerBuffer::PaintState
|
||||
ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, gfxContext* aTarget,
|
||||
ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer,
|
||||
gfxASurface* aReferenceSurface,
|
||||
PRUint32 aFlags)
|
||||
{
|
||||
PaintState result;
|
||||
|
||||
gfxASurface::gfxContentType desiredContentType = gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
nsRefPtr<gfxASurface> targetSurface = aTarget->CurrentSurface();
|
||||
if (targetSurface->AreSimilarSurfacesSensitiveToContentType()) {
|
||||
if (aReferenceSurface->AreSimilarSurfacesSensitiveToContentType()) {
|
||||
if (aFlags & OPAQUE_CONTENT) {
|
||||
desiredContentType = gfxASurface::CONTENT_COLOR;
|
||||
}
|
||||
@ -192,7 +192,8 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, gfxContext* aTarget,
|
||||
// We can't do a real self-copy because the buffer is rotated.
|
||||
// So allocate a new buffer for the destination.
|
||||
destBufferRect = visibleBounds;
|
||||
destBuffer = CreateBuffer(targetSurface, desiredContentType, destBufferRect.Size());
|
||||
destBuffer = CreateBuffer(aReferenceSurface, desiredContentType,
|
||||
destBufferRect.Size());
|
||||
if (!destBuffer)
|
||||
return result;
|
||||
}
|
||||
@ -210,7 +211,8 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, gfxContext* aTarget,
|
||||
} else {
|
||||
// The buffer's not big enough, so allocate a new one
|
||||
destBufferRect = visibleBounds;
|
||||
destBuffer = CreateBuffer(targetSurface, desiredContentType, destBufferRect.Size());
|
||||
destBuffer = CreateBuffer(aReferenceSurface, desiredContentType,
|
||||
destBufferRect.Size());
|
||||
if (!destBuffer)
|
||||
return result;
|
||||
}
|
||||
|
@ -107,14 +107,16 @@ public:
|
||||
OPAQUE_CONTENT = 0x01
|
||||
};
|
||||
/**
|
||||
* Start a drawing operation. Ths returns a PaintState describing what
|
||||
* Start a drawing operation. This returns a PaintState describing what
|
||||
* needs to be drawn to bring the buffer up to date in the visible region.
|
||||
* This queries aLayer to get the currently valid and visible regions.
|
||||
* The returned mContext may be null if mRegionToDraw is empty.
|
||||
* Otherwise it must not be null.
|
||||
* mRegionToInvalidate will contain mRegionToDraw.
|
||||
* @param aReferenceSurface if we need to create a buffer, we'll create
|
||||
* a surface that's similar to aReferenceSurface
|
||||
*/
|
||||
PaintState BeginPaint(ThebesLayer* aLayer, gfxContext* aTarget,
|
||||
PaintState BeginPaint(ThebesLayer* aLayer, gfxASurface* aReferenceSurface,
|
||||
PRUint32 aFlags);
|
||||
/**
|
||||
* Complete the drawing operation. The region to draw must have been drawn
|
||||
@ -122,6 +124,13 @@ public:
|
||||
*/
|
||||
void DrawTo(ThebesLayer* aLayer, PRUint32 aFlags, gfxContext* aTarget, float aOpacity);
|
||||
|
||||
/**
|
||||
* Get the underlying buffer, if any. This is useful because we can pass
|
||||
* in the buffer as the default "reference surface" if there is one.
|
||||
* Don't use it for anything else!
|
||||
*/
|
||||
gfxASurface* GetBuffer() { return mBuffer; }
|
||||
|
||||
protected:
|
||||
enum XSide {
|
||||
LEFT, RIGHT
|
||||
|
@ -44,11 +44,11 @@
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(HWND wnd) :
|
||||
gfxWindowsSurface::gfxWindowsSurface(HWND wnd, PRUint32 flags) :
|
||||
mOwnsDC(PR_TRUE), mForPrinting(PR_FALSE), mWnd(wnd)
|
||||
{
|
||||
mDC = ::GetDC(mWnd);
|
||||
Init(cairo_win32_surface_create(mDC));
|
||||
InitWithDC(flags);
|
||||
}
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(HDC dc, PRUint32 flags) :
|
||||
@ -63,11 +63,7 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, PRUint32 flags) :
|
||||
mForPrinting = PR_TRUE;
|
||||
} else
|
||||
#endif
|
||||
if (flags & FLAG_IS_TRANSPARENT) {
|
||||
Init(cairo_win32_surface_create_with_alpha(mDC));
|
||||
} else {
|
||||
Init(cairo_win32_surface_create(mDC));
|
||||
}
|
||||
InitWithDC(flags);
|
||||
}
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& size, gfxImageFormat imageFormat) :
|
||||
@ -110,7 +106,6 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, const gfxIntSize& size, gfxImageFor
|
||||
mDC = nsnull;
|
||||
}
|
||||
|
||||
|
||||
gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
|
||||
mOwnsDC(PR_FALSE), mForPrinting(PR_FALSE), mWnd(nsnull)
|
||||
{
|
||||
@ -125,6 +120,16 @@ gfxWindowsSurface::gfxWindowsSurface(cairo_surface_t *csurf) :
|
||||
Init(csurf, PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
gfxWindowsSurface::InitWithDC(PRUint32 flags)
|
||||
{
|
||||
if (flags & FLAG_IS_TRANSPARENT) {
|
||||
Init(cairo_win32_surface_create_with_alpha(mDC));
|
||||
} else {
|
||||
Init(cairo_win32_surface_create(mDC));
|
||||
}
|
||||
}
|
||||
|
||||
gfxWindowsSurface::~gfxWindowsSurface()
|
||||
{
|
||||
if (mOwnsDC) {
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
FLAG_IS_TRANSPARENT = (1 << 2),
|
||||
};
|
||||
|
||||
gfxWindowsSurface(HWND wnd);
|
||||
gfxWindowsSurface(HWND wnd, PRUint32 flags = 0);
|
||||
gfxWindowsSurface(HDC dc, PRUint32 flags = 0);
|
||||
|
||||
// Create a DIB surface
|
||||
@ -67,6 +67,8 @@ public:
|
||||
|
||||
gfxWindowsSurface(cairo_surface_t *csurf);
|
||||
|
||||
void InitWithDC(PRUint32 flags);
|
||||
|
||||
virtual ~gfxWindowsSurface();
|
||||
|
||||
HDC GetDC() { return mDC; }
|
||||
|
@ -968,7 +968,7 @@ FrameLayerBuilder::AddThebesDisplayItem(ThebesLayer* aLayer,
|
||||
// manager now so that if we need to modify the retained layer
|
||||
// tree during this process, those modifications will happen
|
||||
// during the construction phase for the retained layer tree.
|
||||
tempManager = new BasicLayerManager(nsnull);
|
||||
tempManager = new BasicLayerManager();
|
||||
tempManager->BeginTransaction();
|
||||
nsRefPtr<Layer> layer = aItem->BuildLayer(aBuilder, tempManager);
|
||||
if (!layer) {
|
||||
|
@ -371,7 +371,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||
NS_WARNING("Nowhere to paint into");
|
||||
return;
|
||||
}
|
||||
layerManager = new BasicLayerManager(nsnull);
|
||||
layerManager = new BasicLayerManager();
|
||||
if (!layerManager)
|
||||
return;
|
||||
}
|
||||
|
@ -3260,7 +3260,11 @@ gfxASurface *nsWindow::GetThebesSurface()
|
||||
return (new gfxD2DSurface(mWnd, content));
|
||||
} else {
|
||||
#endif
|
||||
return (new gfxWindowsSurface(mWnd));
|
||||
PRUint32 flags = gfxWindowsSurface::FLAG_TAKE_DC;
|
||||
if (mTransparencyMode != eTransparencyOpaque) {
|
||||
flags |= gfxWindowsSurface::FLAG_IS_TRANSPARENT;
|
||||
}
|
||||
return (new gfxWindowsSurface(mWnd, flags));
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
}
|
||||
#endif
|
||||
|
@ -129,6 +129,11 @@ nsBaseWidget::nsBaseWidget()
|
||||
//-------------------------------------------------------------------------
|
||||
nsBaseWidget::~nsBaseWidget()
|
||||
{
|
||||
if (mLayerManager &&
|
||||
mLayerManager->GetBackendType() == LayerManager::LAYERS_BASIC) {
|
||||
static_cast<BasicLayerManager*>(mLayerManager.get())->ClearRetainerWidget();
|
||||
}
|
||||
|
||||
#ifdef NOISY_WIDGET_LEAKS
|
||||
gNumWidgets--;
|
||||
printf("WIDGETS- = %d\n", gNumWidgets);
|
||||
@ -727,9 +732,7 @@ LayerManager* nsBaseWidget::GetLayerManager()
|
||||
}
|
||||
}
|
||||
if (!mLayerManager) {
|
||||
nsRefPtr<BasicLayerManager> basicManager = new BasicLayerManager(nsnull);
|
||||
basicManager->SetRetain(PR_TRUE);
|
||||
mLayerManager = basicManager.forget();
|
||||
mLayerManager = new BasicLayerManager(this);
|
||||
}
|
||||
}
|
||||
return mLayerManager;
|
||||
|
Loading…
Reference in New Issue
Block a user