mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 780330: Avoid mapping/unmapping buffers when we don't use them. r=mattwoodrow sr=roc
This commit is contained in:
parent
c1c917ac7e
commit
a67f684009
@ -3,11 +3,14 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "ThebesLayerBuffer.h"
|
||||
#include "Layers.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "ipc/AutoOpenSurface.h"
|
||||
#include "nsDeviceContext.h"
|
||||
#include "sampler.h"
|
||||
|
||||
@ -57,7 +60,7 @@ ThebesLayerBuffer::DrawBufferQuadrant(gfxContext* aTarget,
|
||||
true);
|
||||
|
||||
gfxPoint quadrantTranslation(quadrantRect.x, quadrantRect.y);
|
||||
nsRefPtr<gfxPattern> pattern = new gfxPattern(mBuffer);
|
||||
nsRefPtr<gfxPattern> pattern = new gfxPattern(EnsureBuffer());
|
||||
|
||||
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
gfxPattern::GraphicsFilter filter = gfxPattern::FILTER_NEAREST;
|
||||
@ -113,7 +116,7 @@ ThebesLayerBuffer::DrawBufferWithRotation(gfxContext* aTarget, float aOpacity,
|
||||
already_AddRefed<gfxContext>
|
||||
ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
|
||||
{
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(mBuffer);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(EnsureBuffer());
|
||||
|
||||
// Figure out which quadrant to draw in
|
||||
int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x;
|
||||
@ -127,6 +130,35 @@ ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds)
|
||||
return ctx.forget();
|
||||
}
|
||||
|
||||
gfxASurface::gfxContentType
|
||||
ThebesLayerBuffer::BufferContentType()
|
||||
{
|
||||
return mBuffer ? mBuffer->GetContentType() : mBufferProvider->ContentType();
|
||||
}
|
||||
|
||||
bool
|
||||
ThebesLayerBuffer::BufferSizeOkFor(const nsIntSize& aSize)
|
||||
{
|
||||
return (aSize == mBufferRect.Size() ||
|
||||
(SizedToVisibleBounds != mBufferSizePolicy &&
|
||||
aSize < mBufferRect.Size()));
|
||||
}
|
||||
|
||||
gfxASurface*
|
||||
ThebesLayerBuffer::EnsureBuffer()
|
||||
{
|
||||
if (!mBuffer && mBufferProvider) {
|
||||
mBuffer = mBufferProvider->Get();
|
||||
}
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
bool
|
||||
ThebesLayerBuffer::HaveBuffer()
|
||||
{
|
||||
return mBuffer || mBufferProvider;
|
||||
}
|
||||
|
||||
static void
|
||||
WrapRotationAxis(int32_t* aRotationPoint, int32_t aSize)
|
||||
{
|
||||
@ -156,7 +188,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
|
||||
while (true) {
|
||||
contentType = aContentType;
|
||||
neededRegion = aLayer->GetVisibleRegion();
|
||||
canReuseBuffer = mBuffer && BufferSizeOkFor(neededRegion.GetBounds().Size());
|
||||
canReuseBuffer = HaveBuffer() && BufferSizeOkFor(neededRegion.GetBounds().Size());
|
||||
|
||||
if (canReuseBuffer) {
|
||||
if (mBufferRect.Contains(neededRegion.GetBounds())) {
|
||||
@ -184,7 +216,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
|
||||
neededRegion = destBufferRect;
|
||||
}
|
||||
|
||||
if (mBuffer && contentType != mBuffer->GetContentType()) {
|
||||
if (HaveBuffer() && contentType != BufferContentType()) {
|
||||
// We're effectively clearing the valid region, so we need to draw
|
||||
// the entire needed region now.
|
||||
result.mRegionToInvalidate = aLayer->GetValidRegion();
|
||||
@ -231,7 +263,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
|
||||
if (mBufferRotation == nsIntPoint(0,0)) {
|
||||
nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
|
||||
nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
|
||||
mBuffer->MovePixels(srcRect, dest);
|
||||
EnsureBuffer()->MovePixels(srcRect, dest);
|
||||
result.mDidSelfCopy = true;
|
||||
// Don't set destBuffer; we special-case self-copies, and
|
||||
// just did the necessary work above.
|
||||
@ -269,7 +301,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType,
|
||||
bool isClear = mBuffer == nullptr;
|
||||
|
||||
if (destBuffer) {
|
||||
if (mBuffer) {
|
||||
if (HaveBuffer()) {
|
||||
// Copy the bits
|
||||
nsRefPtr<gfxContext> tmpCtx = new gfxContext(destBuffer);
|
||||
nsIntPoint offset = -destBufferRect.TopLeft();
|
||||
|
@ -13,6 +13,7 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class AutoOpenSurface;
|
||||
class ThebesLayer;
|
||||
|
||||
/**
|
||||
@ -50,7 +51,8 @@ public:
|
||||
};
|
||||
|
||||
ThebesLayerBuffer(BufferSizePolicy aBufferSizePolicy)
|
||||
: mBufferRotation(0,0)
|
||||
: mBufferProvider(nullptr)
|
||||
, mBufferRotation(0,0)
|
||||
, mBufferSizePolicy(aBufferSizePolicy)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ThebesLayerBuffer);
|
||||
@ -67,6 +69,7 @@ public:
|
||||
void Clear()
|
||||
{
|
||||
mBuffer = nullptr;
|
||||
mBufferProvider = nullptr;
|
||||
mBufferRect.SetEmpty();
|
||||
}
|
||||
|
||||
@ -172,13 +175,22 @@ protected:
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the buffer only. This is intended to be used with the
|
||||
* shadow-layer Open/CloseDescriptor interface, to ensure we don't
|
||||
* accidentally touch a buffer when it's not mapped.
|
||||
* Set the buffer provider only. This is used with surfaces that
|
||||
* require explicit map/unmap, which |aProvider| is used to do on
|
||||
* demand in this code.
|
||||
*
|
||||
* It's the caller's responsibility to ensure |aProvider| is valid
|
||||
* for the duration of operations it requests of this
|
||||
* ThebesLayerBuffer. It's also the caller's responsibility to
|
||||
* unset the provider when inactive, by calling
|
||||
* SetBufferProvider(nullptr).
|
||||
*/
|
||||
void SetBuffer(gfxASurface* aBuffer)
|
||||
void SetBufferProvider(AutoOpenSurface* aProvider)
|
||||
{
|
||||
mBuffer = aBuffer;
|
||||
mBufferProvider = aProvider;
|
||||
if (!mBufferProvider) {
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,14 +201,31 @@ protected:
|
||||
GetContextForQuadrantUpdate(const nsIntRect& aBounds);
|
||||
|
||||
private:
|
||||
bool BufferSizeOkFor(const nsIntSize& aSize)
|
||||
{
|
||||
return (aSize == mBufferRect.Size() ||
|
||||
(SizedToVisibleBounds != mBufferSizePolicy &&
|
||||
aSize < mBufferRect.Size()));
|
||||
}
|
||||
// Buffer helpers. Don't use mBuffer directly; instead use one of
|
||||
// these helpers.
|
||||
|
||||
/**
|
||||
* Return the buffer's content type. Requires a valid buffer or
|
||||
* buffer provider.
|
||||
*/
|
||||
gfxASurface::gfxContentType BufferContentType();
|
||||
bool BufferSizeOkFor(const nsIntSize& aSize);
|
||||
/**
|
||||
* If the buffer hasn't been mapped, map it and return it.
|
||||
*/
|
||||
gfxASurface* EnsureBuffer();
|
||||
/**
|
||||
* True if we have a buffer where we can get it (but not necessarily
|
||||
* mapped currently).
|
||||
*/
|
||||
bool HaveBuffer();
|
||||
|
||||
nsRefPtr<gfxASurface> mBuffer;
|
||||
/**
|
||||
* This member is only set transiently. It's used to map mBuffer
|
||||
* when we're using surfaces that require explicit map/unmap.
|
||||
*/
|
||||
AutoOpenSurface* mBufferProvider;
|
||||
/** The area of the ThebesLayer that is covered by the buffer as a whole */
|
||||
nsIntRect mBufferRect;
|
||||
/**
|
||||
|
@ -64,7 +64,7 @@ public:
|
||||
* When BasicThebesLayerBuffer is used with layers that hold
|
||||
* SurfaceDescriptor, this buffer only has a valid gfxASurface in
|
||||
* the scope of an AutoOpenSurface for that SurfaceDescriptor. That
|
||||
* is, it's sort of a "virtual buffer" that's only mapped an
|
||||
* is, it's sort of a "virtual buffer" that's only mapped and
|
||||
* unmapped within the scope of AutoOpenSurface. None of the
|
||||
* underlying buffer attributes (rect, rotation) are affected by
|
||||
* mapping/unmapping.
|
||||
@ -72,13 +72,13 @@ public:
|
||||
* These helpers just exist to provide more descriptive names of the
|
||||
* map/unmap process.
|
||||
*/
|
||||
void MapBuffer(gfxASurface* aBuffer)
|
||||
void ProvideBuffer(AutoOpenSurface* aProvider)
|
||||
{
|
||||
SetBuffer(aBuffer);
|
||||
SetBufferProvider(aProvider);
|
||||
}
|
||||
void UnmapBuffer()
|
||||
void RevokeBuffer()
|
||||
{
|
||||
SetBuffer(nullptr);
|
||||
SetBufferProvider(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -248,13 +248,13 @@ struct NS_STACK_CLASS AutoBufferTracker {
|
||||
mLayer->mBufferTracker = this;
|
||||
if (IsSurfaceDescriptorValid(mLayer->mBackBuffer)) {
|
||||
mInitialBuffer.construct(OPEN_READ_WRITE, mLayer->mBackBuffer);
|
||||
mLayer->mBuffer.MapBuffer(mInitialBuffer.ref().Get());
|
||||
mLayer->mBuffer.ProvideBuffer(&mInitialBuffer.ref());
|
||||
}
|
||||
}
|
||||
|
||||
~AutoBufferTracker() {
|
||||
mLayer->mBufferTracker = nullptr;
|
||||
mLayer->mBuffer.UnmapBuffer();
|
||||
mLayer->mBuffer.RevokeBuffer();
|
||||
// mInitialBuffer and mNewBuffer will clean up after themselves if
|
||||
// they were constructed.
|
||||
}
|
||||
@ -597,11 +597,11 @@ BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
|
||||
}
|
||||
|
||||
AutoOpenSurface autoFrontBuffer(OPEN_READ_ONLY, mFrontBufferDescriptor);
|
||||
mFrontBuffer.MapBuffer(autoFrontBuffer.Get());
|
||||
mFrontBuffer.ProvideBuffer(&autoFrontBuffer);
|
||||
|
||||
mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
|
||||
|
||||
mFrontBuffer.UnmapBuffer();
|
||||
mFrontBuffer.RevokeBuffer();
|
||||
}
|
||||
|
||||
already_AddRefed<ThebesLayer>
|
||||
|
Loading…
Reference in New Issue
Block a user