Bug 829747 - Update WebGL canvases asynchronously r=jgilbert,bgirard

This commit is contained in:
James Willcox 2013-03-18 13:34:43 -04:00
Родитель a60b979b8e
Коммит 3d05feef6e
12 изменённых файлов: 137 добавлений и 40 удалений

Просмотреть файл

@ -2879,7 +2879,7 @@ GLContext::CreateScreenBufferImpl(const gfxIntSize& size, const SurfaceCaps& cap
if (!newScreen)
return false;
if (!newScreen->PublishFrame(size)) {
if (!newScreen->Resize(size)) {
delete newScreen;
return false;
}
@ -2901,7 +2901,7 @@ GLContext::ResizeScreenBuffer(const gfxIntSize& size)
if (!IsOffscreenSizeAllowed(size))
return false;
return mScreen->PublishFrame(size);
return mScreen->Resize(size);
}

Просмотреть файл

@ -325,27 +325,12 @@ GLScreenBuffer::Morph(SurfaceFactory_GL* newFactory, SurfaceStreamType streamTyp
mStream = newStream;
}
bool
GLScreenBuffer::Swap(const gfxIntSize& size)
void
GLScreenBuffer::Attach(SharedSurface* surface, const gfxIntSize& size)
{
ScopedBindFramebuffer autoFB(mGL);
SharedSurface* nextSurf = mStream->SwapProducer(mFactory, size);
if (!nextSurf) {
SurfaceFactory_GL* basicFactory =
new SurfaceFactory_Basic(mGL, mFactory->Caps());
nextSurf = mStream->SwapProducer(basicFactory, size);
if (!nextSurf) {
delete basicFactory;
return false;
}
// Swap out the apparently defective old factory.
delete mFactory;
mFactory = basicFactory;
}
SharedSurface_GL* surf = SharedSurface_GL::Cast(nextSurf);
SharedSurface_GL* surf = SharedSurface_GL::Cast(surface);
if (mRead && SharedSurf())
SharedSurf()->UnlockProd();
@ -376,6 +361,27 @@ GLScreenBuffer::Swap(const gfxIntSize& size)
if (!PreserveBuffer()) {
// DiscardFramebuffer here could help perf on some mobile platforms.
}
}
bool
GLScreenBuffer::Swap(const gfxIntSize& size)
{
SharedSurface* nextSurf = mStream->SwapProducer(mFactory, size);
if (!nextSurf) {
SurfaceFactory_GL* basicFactory =
new SurfaceFactory_Basic(mGL, mFactory->Caps());
nextSurf = mStream->SwapProducer(basicFactory, size);
if (!nextSurf) {
delete basicFactory;
return false;
}
// Swap out the apparently defective old factory.
delete mFactory;
mFactory = basicFactory;
}
Attach(nextSurf, size);
return true;
}
@ -389,6 +395,16 @@ GLScreenBuffer::PublishFrame(const gfxIntSize& size)
return good;
}
bool
GLScreenBuffer::Resize(const gfxIntSize& size)
{
SharedSurface* surface = mStream->Resize(mFactory, size);
if (!surface)
return false;
Attach(surface, size);
return true;
}
DrawBuffer*
GLScreenBuffer::CreateDraw(const gfxIntSize& size)

Просмотреть файл

@ -265,9 +265,13 @@ protected:
public:
bool PublishFrame(const gfxIntSize& size);
bool Resize(const gfxIntSize& size);
void Readback(SharedSurface_GL* src, gfxImageSurface* dest);
protected:
void Attach(SharedSurface* surface, const gfxIntSize& size);
DrawBuffer* CreateDraw(const gfxIntSize& size);
ReadBuffer* CreateRead(SharedSurface_GL* surf);

Просмотреть файл

@ -8,6 +8,7 @@
#include "gfxPoint.h"
#include "SharedSurface.h"
#include "SurfaceFactory.h"
#include "sampler.h"
namespace mozilla {
namespace gfx {
@ -20,7 +21,7 @@ SurfaceStream::ChooseGLStreamType(SurfaceStream::OMTC omtc,
if (preserveBuffer)
return SurfaceStreamType::TripleBuffer_Copy;
else
return SurfaceStreamType::TripleBuffer;
return SurfaceStreamType::TripleBuffer_Async;
} else {
if (preserveBuffer)
return SurfaceStreamType::SingleBuffer;
@ -37,6 +38,8 @@ SurfaceStream::CreateForType(SurfaceStreamType type, SurfaceStream* prevStream)
return new SurfaceStream_SingleBuffer(prevStream);
case SurfaceStreamType::TripleBuffer_Copy:
return new SurfaceStream_TripleBuffer_Copy(prevStream);
case SurfaceStreamType::TripleBuffer_Async:
return new SurfaceStream_TripleBuffer_Async(prevStream);
case SurfaceStreamType::TripleBuffer:
return new SurfaceStream_TripleBuffer(prevStream);
default:
@ -158,7 +161,18 @@ SurfaceStream::SwapConsumer()
return ret;
}
SharedSurface*
SurfaceStream::Resize(SurfaceFactory* factory, const gfxIntSize& size)
{
MonitorAutoLock lock(mMonitor);
if (mProducer) {
Scrap(mProducer);
}
New(factory, size, mProducer);
return mProducer;
}
SurfaceStream_SingleBuffer::SurfaceStream_SingleBuffer(SurfaceStream* prevStream)
: SurfaceStream(SurfaceStreamType::SingleBuffer, prevStream)
@ -200,7 +214,7 @@ SharedSurface*
SurfaceStream_SingleBuffer::SwapProducer(SurfaceFactory* factory,
const gfxIntSize& size)
{
MutexAutoLock lock(mMutex);
MonitorAutoLock lock(mMonitor);
if (mConsumer) {
Recycle(factory, mConsumer);
}
@ -238,7 +252,7 @@ SurfaceStream_SingleBuffer::SwapProducer(SurfaceFactory* factory,
SharedSurface*
SurfaceStream_SingleBuffer::SwapConsumer_NoWait()
{
MutexAutoLock lock(mMutex);
MonitorAutoLock lock(mMonitor);
// Use Cons, if present.
// Otherwise, just use Prod directly.
@ -293,7 +307,7 @@ SharedSurface*
SurfaceStream_TripleBuffer_Copy::SwapProducer(SurfaceFactory* factory,
const gfxIntSize& size)
{
MutexAutoLock lock(mMutex);
MonitorAutoLock lock(mMonitor);
RecycleScraps(factory);
if (mProducer) {
@ -323,10 +337,11 @@ SurfaceStream_TripleBuffer_Copy::SwapProducer(SurfaceFactory* factory,
return mProducer;
}
SharedSurface*
SurfaceStream_TripleBuffer_Copy::SwapConsumer_NoWait()
{
MutexAutoLock lock(mMutex);
MonitorAutoLock lock(mMonitor);
if (mStaging) {
Scrap(mConsumer);
@ -380,13 +395,18 @@ SharedSurface*
SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory,
const gfxIntSize& size)
{
MutexAutoLock lock(mMutex);
SAMPLE_LABEL("SurfaceStream_TripleBuffer", "SwapProducer");
MonitorAutoLock lock(mMonitor);
if (mProducer) {
RecycleScraps(factory);
if (mStaging)
Recycle(factory, mStaging);
// If WaitForCompositor succeeds, mStaging has moved to mConsumer.
// If it failed, we might have to scrap it.
if (mStaging && !WaitForCompositor())
Scrap(mStaging);
MOZ_ASSERT(!mStaging);
Move(mProducer, mStaging);
mStaging->Fence();
}
@ -400,14 +420,36 @@ SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory,
SharedSurface*
SurfaceStream_TripleBuffer::SwapConsumer_NoWait()
{
MutexAutoLock lock(mMutex);
MonitorAutoLock lock(mMonitor);
if (mStaging) {
Scrap(mConsumer);
Move(mStaging, mConsumer);
mMonitor.NotifyAll();
}
return mConsumer;
}
SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream)
: SurfaceStream_TripleBuffer(prevStream)
{
}
SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
{
}
bool
SurfaceStream_TripleBuffer_Async::WaitForCompositor()
{
SAMPLE_LABEL("SurfaceStream_TripleBuffer_Async", "WaitForCompositor");
// We are assumed to be locked
while (mStaging)
mMonitor.Wait();
return true;
}
} /* namespace gfx */
} /* namespace mozilla */

Просмотреть файл

@ -8,7 +8,7 @@
#include <stack>
#include <set>
#include "mozilla/Mutex.h"
#include "mozilla/Monitor.h"
#include "mozilla/Attributes.h"
#include "gfxPoint.h"
#include "SurfaceTypes.h"
@ -48,7 +48,7 @@ protected:
SharedSurface* mProducer;
std::set<SharedSurface*> mSurfaces;
std::stack<SharedSurface*> mScraps;
mutable Mutex mMutex;
mutable Monitor mMonitor;
bool mIsAlive;
// |previous| can be null, indicating this is the first one.
@ -56,7 +56,7 @@ protected:
SurfaceStream(SurfaceStreamType type, SurfaceStream* prevStream)
: mType(type)
, mProducer(nullptr)
, mMutex("SurfaceStream mutex")
, mMonitor("SurfaceStream monitor")
, mIsAlive(true)
{
MOZ_ASSERT(!prevStream || mType != prevStream->mType,
@ -107,6 +107,8 @@ public:
virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
const gfxIntSize& size) = 0;
virtual SharedSurface* Resize(SurfaceFactory* factory, const gfxIntSize& size);
protected:
// SwapCons will return the same surface more than once,
// if nothing new has been published.
@ -169,6 +171,9 @@ protected:
SharedSurface* mStaging;
SharedSurface* mConsumer;
// Returns true if we were able to wait, false if not
virtual bool WaitForCompositor() { return false; }
public:
SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
virtual ~SurfaceStream_TripleBuffer();
@ -182,6 +187,17 @@ public:
virtual void SurrenderSurfaces(SharedSurface*& producer, SharedSurface*& consumer);
};
class SurfaceStream_TripleBuffer_Async
: public SurfaceStream_TripleBuffer
{
protected:
virtual bool WaitForCompositor();
public:
SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream);
virtual ~SurfaceStream_TripleBuffer_Async();
};
} /* namespace gfx */
} /* namespace mozilla */

Просмотреть файл

@ -78,6 +78,7 @@ MOZ_END_ENUM_CLASS(SharedSurfaceType)
MOZ_BEGIN_ENUM_CLASS(SurfaceStreamType, uint8_t)
SingleBuffer,
TripleBuffer_Copy,
TripleBuffer_Async,
TripleBuffer,
Max
MOZ_END_ENUM_CLASS(SurfaceStreamType)

Просмотреть файл

@ -12,6 +12,7 @@
#include "SurfaceStream.h"
#include "SharedSurfaceGL.h"
#include "SharedSurfaceEGL.h"
#include "sampler.h"
#include "BasicLayersImpl.h"
#include "nsXULAppAPI.h"
@ -411,6 +412,7 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData)
void
BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
{
SAMPLE_LABEL("BasicShadowableCanvasLayer", "Paint");
if (!HasShadow()) {
BasicCanvasLayer::Paint(aContext, aMaskLayer);
return;
@ -436,7 +438,7 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
// Call Painted() to reset our dirty 'bit'.
Painted();
FireDidTransactionCallback();
BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
BasicManager()->PaintedCanvasNoSwap(BasicManager()->Hold(this),
mNeedsYFlip,
mBackBuffer);
// Move SharedTextureHandle ownership to ShadowLayer

Просмотреть файл

@ -523,7 +523,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
SAMPLE_LABEL("BasicLayerManager", "EndTranscationInternal");
SAMPLE_LABEL("BasicLayerManager", "EndTransactionInternal");
#ifdef MOZ_LAYERS_HAVE_LOG
MOZ_LAYERS_LOG((" ----- (beginning paint)"));
Log();
@ -871,6 +871,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
void* aCallbackData,
ReadbackProcessor* aReadback)
{
SAMPLE_LABEL("BasicLayerManager", "PaintLayer");
PaintContext paintContext(aTarget, aLayer, aCallback, aCallbackData, aReadback);
// Don't attempt to paint layers with a singular transform, cairo will

Просмотреть файл

@ -297,6 +297,16 @@ ShadowLayerForwarder::PaintedCanvas(ShadowableLayer* aCanvas,
aNeedYFlip));
}
void
ShadowLayerForwarder::PaintedCanvasNoSwap(ShadowableLayer* aCanvas,
bool aNeedYFlip,
const SurfaceDescriptor& aNewFrontSurface)
{
mTxn->AddNoSwapPaint(OpPaintCanvas(NULL, Shadow(aCanvas),
aNewFrontSurface,
aNeedYFlip));
}
bool
ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies)
{

Просмотреть файл

@ -219,6 +219,9 @@ public:
void PaintedCanvas(ShadowableLayer* aCanvas,
bool aNeedYFlip,
const SurfaceDescriptor& aNewFrontSurface);
void PaintedCanvasNoSwap(ShadowableLayer* aCanvas,
bool aNeedYFlip,
const SurfaceDescriptor& aNewFrontSurface);
/**
* End the current transaction and forward it to ShadowLayerManager.

Просмотреть файл

@ -422,11 +422,14 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
RenderTraceInvalidateStart(canvas, "FF00FF", canvas->GetVisibleRegion().GetBounds());
canvas->SetAllocator(this);
CanvasSurface newBack;
CanvasSurface newBack = CanvasSurface(null_t());
canvas->Swap(op.newFrontBuffer(), op.needYFlip(), &newBack);
canvas->Updated();
if (newBack.type() != CanvasSurface::Tnull_t) {
replyv.push_back(OpBufferSwap(shadow, NULL,
newBack));
}
RenderTraceInvalidateEnd(canvas, "FF00FF");
break;

Просмотреть файл

@ -444,7 +444,6 @@ ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
SurfaceStreamHandle handle = (SurfaceStreamHandle)nullptr;
mFrontBufferDescriptor = SurfaceStreamDescriptor(handle, false);
}
*aNewBack = mFrontBufferDescriptor;
mFrontBufferDescriptor = aNewFront;
mNeedsYFlip = needYFlip;
} else {