mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1092360 - Avoid redundant framebuffer switches. r=jrmuizel
This commit is contained in:
parent
10872ba23d
commit
8d0678b3a9
@ -17,6 +17,18 @@ class Matrix4x4;
|
||||
|
||||
namespace layers {
|
||||
|
||||
Compositor::Compositor(PCompositorParent* aParent)
|
||||
: mCompositorID(0)
|
||||
, mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
|
||||
, mParent(aParent)
|
||||
, mScreenRotation(ROTATION_0)
|
||||
{
|
||||
}
|
||||
|
||||
Compositor::~Compositor()
|
||||
{
|
||||
}
|
||||
|
||||
/* static */ LayersBackend Compositor::sBackend = LayersBackend::LAYERS_NONE;
|
||||
/* static */ LayersBackend
|
||||
Compositor::GetBackend()
|
||||
|
@ -182,18 +182,12 @@ enum SurfaceInitMode
|
||||
class Compositor
|
||||
{
|
||||
protected:
|
||||
virtual ~Compositor() {}
|
||||
virtual ~Compositor();
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(Compositor)
|
||||
|
||||
explicit Compositor(PCompositorParent* aParent = nullptr)
|
||||
: mCompositorID(0)
|
||||
, mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
|
||||
, mParent(aParent)
|
||||
, mScreenRotation(ROTATION_0)
|
||||
{
|
||||
}
|
||||
explicit Compositor(PCompositorParent* aParent = nullptr);
|
||||
|
||||
virtual TemporaryRef<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
|
||||
virtual bool Initialize() = 0;
|
||||
@ -478,6 +472,12 @@ public:
|
||||
mScreenRotation = aRotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to set the composition target (the screen or an offscreen target)
|
||||
* after we've ran the prepare phase. This must be called after BeginFrame.
|
||||
*/
|
||||
virtual void SetFinalDestinationTarget() = 0;
|
||||
|
||||
protected:
|
||||
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
|
||||
const gfx::Rect& aVisibleRect,
|
||||
@ -510,6 +510,7 @@ protected:
|
||||
|
||||
RefPtr<gfx::DrawTarget> mTarget;
|
||||
nsIntRect mTargetBounds;
|
||||
RefPtr<CompositingRenderTarget> mFinalDestinationTarget;
|
||||
|
||||
private:
|
||||
static LayersBackend sBackend;
|
||||
|
@ -85,13 +85,16 @@ void BasicCompositor::Destroy()
|
||||
TemporaryRef<CompositingRenderTarget>
|
||||
BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit)
|
||||
{
|
||||
MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
|
||||
MOZ_ASSERT(aRect.width != 0 && aRect.height != 0,
|
||||
"Trying to create a render target of invalid size");
|
||||
|
||||
if (aRect.width * aRect.height == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target = mDrawTarget->CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
RefPtr<DrawTarget> target =
|
||||
static_cast<BasicCompositingRenderTarget*>(mFinalDestinationTarget.get())->mDrawTarget->
|
||||
CreateSimilarDrawTarget(aRect.Size(), SurfaceFormat::B8G8R8A8);
|
||||
|
||||
if (!target) {
|
||||
return nullptr;
|
||||
@ -440,7 +443,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
}
|
||||
return;
|
||||
}
|
||||
SetRenderTarget(target);
|
||||
mFinalDestinationTarget = target;
|
||||
|
||||
// We only allocate a surface sized to the invalidated region, so we need to
|
||||
// translate future coordinates.
|
||||
@ -454,9 +457,9 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
}
|
||||
|
||||
if (aClipRectIn) {
|
||||
mRenderTarget->mDrawTarget->PushClipRect(*aClipRectIn);
|
||||
mDrawTarget->PushClipRect(*aClipRectIn);
|
||||
} else {
|
||||
mRenderTarget->mDrawTarget->PushClipRect(rect);
|
||||
mDrawTarget->PushClipRect(rect);
|
||||
if (aClipRectOut) {
|
||||
*aClipRectOut = rect;
|
||||
}
|
||||
@ -503,6 +506,7 @@ BasicCompositor::EndFrame()
|
||||
|
||||
mDrawTarget = nullptr;
|
||||
mRenderTarget = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
@ -512,6 +516,7 @@ BasicCompositor::AbortFrame()
|
||||
mRenderTarget->mDrawTarget->PopClip();
|
||||
mDrawTarget = nullptr;
|
||||
mRenderTarget = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -121,6 +121,10 @@ public:
|
||||
|
||||
gfx::DrawTarget *GetDrawTarget() { return mDrawTarget; }
|
||||
|
||||
virtual void SetFinalDestinationTarget() MOZ_OVERRIDE {
|
||||
MOZ_ASSERT(mFinalDestinationTarget);
|
||||
SetRenderTarget(mFinalDestinationTarget);
|
||||
}
|
||||
private:
|
||||
|
||||
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE { return mWidgetSize; }
|
||||
|
@ -138,6 +138,8 @@ ContainerPrepare(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const RenderTargetIntRect& aClipRect)
|
||||
{
|
||||
Compositor* compositor = aManager->GetCompositor();
|
||||
|
||||
aContainer->mPrepared = MakeUnique<PreparedData>();
|
||||
aContainer->mPrepared->mNeedsSurfaceCopy = false;
|
||||
|
||||
@ -184,7 +186,12 @@ ContainerPrepare(ContainerT* aContainer,
|
||||
// If we don't need a copy we can render to the intermediate now to avoid
|
||||
// unecessary render target switching. This brings a big perf boost on mobile gpus.
|
||||
RefPtr<CompositingRenderTarget> surface = CreateTemporaryTarget(aContainer, aManager);
|
||||
RenderIntermediate(aContainer, aManager, RenderTargetPixel::ToUntyped(aClipRect), surface);
|
||||
|
||||
if (surface) {
|
||||
compositor->SetRenderTarget(surface);
|
||||
RenderLayers(aContainer, aManager, aClipRect);
|
||||
}
|
||||
|
||||
aContainer->mPrepared->mTmpTarget = surface;
|
||||
} else {
|
||||
aContainer->mPrepared->mNeedsSurfaceCopy = true;
|
||||
@ -304,40 +311,26 @@ CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
|
||||
return compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
|
||||
}
|
||||
|
||||
template<class ContainerT> void
|
||||
RenderIntermediate(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const nsIntRect& aClipRect,
|
||||
RefPtr<CompositingRenderTarget> surface)
|
||||
{
|
||||
Compositor* compositor = aManager->GetCompositor();
|
||||
RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
|
||||
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
compositor->SetRenderTarget(surface);
|
||||
// pre-render all of the layers into our temporary
|
||||
RenderLayers(aContainer, aManager, RenderTargetPixel::FromUntyped(aClipRect));
|
||||
// Unbind the current surface and rebind the previous one.
|
||||
compositor->SetRenderTarget(previousTarget);
|
||||
}
|
||||
|
||||
template<class ContainerT> void
|
||||
ContainerRender(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const nsIntRect& aClipRect)
|
||||
{
|
||||
Compositor* compositor = aManager->GetCompositor();
|
||||
|
||||
MOZ_ASSERT(aContainer->mPrepared);
|
||||
if (aContainer->UseIntermediateSurface()) {
|
||||
RefPtr<CompositingRenderTarget> surface;
|
||||
|
||||
if (aContainer->mPrepared->mNeedsSurfaceCopy) {
|
||||
RefPtr<CompositingRenderTarget> previousTarget = compositor->GetCurrentRenderTarget();
|
||||
// we needed to copy the background so we waited until now to render the intermediate
|
||||
surface = CreateTemporaryTargetAndCopyFromBackground(aContainer, aManager);
|
||||
RenderIntermediate(aContainer, aManager,
|
||||
aClipRect, surface);
|
||||
compositor->SetRenderTarget(surface);
|
||||
if (surface) {
|
||||
RenderLayers(aContainer, aManager, RenderTargetPixel::FromUntyped(aClipRect));
|
||||
}
|
||||
compositor->SetRenderTarget(previousTarget);
|
||||
} else {
|
||||
surface = aContainer->mPrepared->mTmpTarget;
|
||||
}
|
||||
@ -352,7 +345,7 @@ ContainerRender(ContainerT* aContainer,
|
||||
nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
RefPtr<gfx::DataSourceSurface> surf = surface->Dump(aManager->GetCompositor());
|
||||
RefPtr<gfx::DataSourceSurface> surf = surface->Dump(compositor);
|
||||
if (surf) {
|
||||
WriteSnapshotToDumpFile(aContainer, surf);
|
||||
}
|
||||
|
@ -37,11 +37,6 @@ class ContainerLayerComposite : public ContainerLayer,
|
||||
LayerManagerComposite* aManager,
|
||||
const RenderTargetIntRect& aClipRect);
|
||||
template<class ContainerT>
|
||||
friend void RenderIntermediate(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const nsIntRect& aClipRect,
|
||||
RefPtr<CompositingRenderTarget> surface);
|
||||
template<class ContainerT>
|
||||
friend RefPtr<CompositingRenderTarget>
|
||||
CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
@ -112,11 +107,6 @@ class RefLayerComposite : public RefLayer,
|
||||
LayerManagerComposite* aManager,
|
||||
const nsIntRect& aClipRect);
|
||||
template<class ContainerT>
|
||||
friend void RenderIntermediate(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const nsIntRect& aClipRect,
|
||||
RefPtr<CompositingRenderTarget> surface);
|
||||
template<class ContainerT>
|
||||
friend RefPtr<CompositingRenderTarget>
|
||||
CreateTemporaryTargetAndCopyFromBackground(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
|
@ -704,10 +704,16 @@ LayerManagerComposite::Render()
|
||||
}
|
||||
|
||||
if (actualBounds.IsEmpty()) {
|
||||
mCompositor->SetFinalDestinationTarget();
|
||||
mCompositor->GetWidget()->PostRender(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare our intermediate surface to minimize render target switches.
|
||||
RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
|
||||
|
||||
mCompositor->SetFinalDestinationTarget();
|
||||
|
||||
// Allow widget to render a custom background.
|
||||
mCompositor->GetWidget()->DrawWindowUnderlay(this, nsIntRect(actualBounds.x,
|
||||
actualBounds.y,
|
||||
@ -722,7 +728,6 @@ LayerManagerComposite::Render()
|
||||
}
|
||||
|
||||
// Render our layers.
|
||||
RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
|
||||
RootLayer()->RenderLayer(clipRect);
|
||||
|
||||
if (!mRegionToClear.IsEmpty()) {
|
||||
|
@ -869,7 +869,7 @@ CompositorD3D11::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
mContext->OMSetBlendState(mAttachments->mPremulBlendState, sBlendFactor, 0xFFFFFFFF);
|
||||
mContext->RSSetState(mAttachments->mRasterizerState);
|
||||
|
||||
SetRenderTarget(mDefaultRT);
|
||||
mFinalDestinationTarget = mDefaultRT;
|
||||
}
|
||||
|
||||
void
|
||||
@ -888,6 +888,7 @@ CompositorD3D11::EndFrame()
|
||||
}
|
||||
|
||||
mCurrentRT = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -142,6 +142,10 @@ public:
|
||||
|
||||
ID3D11DeviceContext* GetDC() { return mContext; }
|
||||
|
||||
virtual void SetFinalDestinationTarget() MOZ_OVERRIDE {
|
||||
MOZ_ASSERT(mFinalDestinationTarget);
|
||||
SetRenderTarget(mFinalDestinationTarget);
|
||||
}
|
||||
private:
|
||||
enum Severity {
|
||||
Recoverable,
|
||||
|
@ -592,7 +592,7 @@ CompositorD3D9::Ready()
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mCurrentRT && !mDefaultRT,
|
||||
NS_ASSERTION(!mCurrentRT && !mFinalDestinationTarget,
|
||||
"Shouldn't have any render targets around, they must be released before our device");
|
||||
mSwapChain = nullptr;
|
||||
|
||||
@ -645,10 +645,9 @@ CompositorD3D9::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
device()->SetScissorRect(&r);
|
||||
|
||||
nsRefPtr<IDirect3DSurface9> backBuffer = mSwapChain->GetBackBuffer();
|
||||
mDefaultRT = new CompositingRenderTargetD3D9(backBuffer,
|
||||
INIT_MODE_CLEAR,
|
||||
IntRect(0, 0, mSize.width, mSize.height));
|
||||
SetRenderTarget(mDefaultRT);
|
||||
mFinalDestinationTarget = new CompositingRenderTargetD3D9(backBuffer,
|
||||
INIT_MODE_CLEAR,
|
||||
IntRect(0, 0, mSize.width, mSize.height));
|
||||
}
|
||||
|
||||
void
|
||||
@ -669,7 +668,7 @@ CompositorD3D9::EndFrame()
|
||||
}
|
||||
|
||||
mCurrentRT = nullptr;
|
||||
mDefaultRT = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -120,6 +120,11 @@ public:
|
||||
|
||||
virtual TemporaryRef<DataTextureSource>
|
||||
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) MOZ_OVERRIDE;
|
||||
|
||||
virtual void SetFinalDestinationTarget() MOZ_OVERRIDE {
|
||||
MOZ_ASSERT(mFinalDestinationTarget);
|
||||
SetRenderTarget(mFinalDestinationTarget);
|
||||
}
|
||||
private:
|
||||
// ensure mSize is up to date with respect to mWidget
|
||||
void EnsureSize();
|
||||
@ -164,7 +169,6 @@ private:
|
||||
/* Widget associated with this layer manager */
|
||||
nsIWidget *mWidget;
|
||||
|
||||
RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
|
||||
RefPtr<CompositingRenderTargetD3D9> mCurrentRT;
|
||||
|
||||
nsIntSize mSize;
|
||||
|
@ -448,6 +448,21 @@ CompositorOGL::PrepareViewport(const gfx::IntSize& aSize)
|
||||
mProjMatrix = matrix3d;
|
||||
}
|
||||
|
||||
void
|
||||
CompositorOGL::SetFinalDestinationTarget() {
|
||||
MOZ_ASSERT(mFinalDestinationTarget);
|
||||
SetRenderTarget(mFinalDestinationTarget);
|
||||
|
||||
// If the Android compositor is being used, this clear will be done in
|
||||
// DrawWindowUnderlay. Make sure the bits used here match up with those used
|
||||
// in mobile/android/base/gfx/LayerRenderer.java
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TemporaryRef<CompositingRenderTarget>
|
||||
CompositorOGL::CreateRenderTarget(const IntRect &aRect, SurfaceInitMode aInit)
|
||||
{
|
||||
@ -608,15 +623,10 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
TexturePoolOGL::Fill(gl());
|
||||
#endif
|
||||
|
||||
mCurrentRenderTarget =
|
||||
mFinalDestinationTarget =
|
||||
CompositingRenderTargetOGL::RenderTargetForWindow(this,
|
||||
IntSize(width, height));
|
||||
mCurrentRenderTarget->BindRenderTarget();
|
||||
|
||||
mContextStateTracker.PushOGLSection(gl(), "Frame");
|
||||
#ifdef DEBUG
|
||||
mWindowRenderTarget = mCurrentRenderTarget;
|
||||
#endif
|
||||
|
||||
// Default blend function implements "OVER"
|
||||
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
|
||||
@ -628,14 +638,6 @@ CompositorOGL::BeginFrame(const nsIntRegion& aInvalidRegion,
|
||||
if (aClipRectOut && !aClipRectIn) {
|
||||
aClipRectOut->SetRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
// If the Android compositor is being used, this clear will be done in
|
||||
// DrawWindowUnderlay. Make sure the bits used here match up with those used
|
||||
// in mobile/android/base/gfx/LayerRenderer.java
|
||||
#ifndef MOZ_WIDGET_ANDROID
|
||||
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -1175,7 +1177,8 @@ CompositorOGL::EndFrame()
|
||||
PROFILER_LABEL("CompositorOGL", "EndFrame",
|
||||
js::ProfileEntry::Category::GRAPHICS);
|
||||
|
||||
MOZ_ASSERT(mCurrentRenderTarget == mWindowRenderTarget, "Rendering target not properly restored");
|
||||
MOZ_ASSERT(mCurrentRenderTarget == mFinalDestinationTarget,
|
||||
"Rendering target not properly restored");
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (gfxUtils::sDumpPainting) {
|
||||
@ -1204,6 +1207,7 @@ CompositorOGL::EndFrame()
|
||||
}
|
||||
|
||||
mCurrentRenderTarget = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
|
||||
if (mTexturePool) {
|
||||
mTexturePool->EndFrame();
|
||||
@ -1296,6 +1300,7 @@ CompositorOGL::AbortFrame()
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
mFrameInProgress = false;
|
||||
mCurrentRenderTarget = nullptr;
|
||||
mFinalDestinationTarget = nullptr;
|
||||
|
||||
if (mTexturePool) {
|
||||
mTexturePool->EndFrame();
|
||||
|
@ -272,6 +272,8 @@ public:
|
||||
const gfx::Matrix4x4& GetProjMatrix() const {
|
||||
return mProjMatrix;
|
||||
}
|
||||
|
||||
virtual void SetFinalDestinationTarget() MOZ_OVERRIDE;
|
||||
private:
|
||||
virtual gfx::IntSize GetWidgetSize() const MOZ_OVERRIDE
|
||||
{
|
||||
@ -297,9 +299,6 @@ private:
|
||||
|
||||
/** Currently bound render target */
|
||||
RefPtr<CompositingRenderTargetOGL> mCurrentRenderTarget;
|
||||
#ifdef DEBUG
|
||||
CompositingRenderTargetOGL* mWindowRenderTarget;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* VBO that has some basics in it for a textured quad, including vertex
|
||||
|
Loading…
Reference in New Issue
Block a user