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