1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 4; -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "GLScreenBuffer.h"
8 #include "CompositorTypes.h"
10 #include "gfx2DGlue.h"
11 #include "MozFramebuffer.h"
12 #include "SharedSurface.h"
13 #include "mozilla/gfx/BuildConstants.h"
15 namespace mozilla::gl
{
20 UniquePtr
<SwapChainPresenter
> SwapChain::Acquire(
21 const gfx::IntSize
& size
, const gfx::ColorSpace2 colorSpace
) {
24 std::shared_ptr
<SharedSurface
> surf
;
27 const auto& existingDesc
= mPool
.front()->mDesc
;
28 auto newDesc
= existingDesc
;
30 newDesc
.colorSpace
= colorSpace
;
31 if (newDesc
!= existingDesc
|| !mPool
.front()->IsValid()) {
36 // When pooling is disabled, recycling of SharedSurfaces is managed by the
37 // owner of the SwapChain by calling StoreRecycledSurface().
38 if (!mPool
.empty() && (!mPoolLimit
|| mPool
.size() >= mPoolLimit
)) {
43 auto uniquePtrSurf
= mFactory
->CreateShared(size
, colorSpace
);
44 if (!uniquePtrSurf
) return nullptr;
45 surf
.reset(uniquePtrSurf
.release());
49 while (mPool
.size() > mPoolLimit
) {
54 auto ret
= MakeUnique
<SwapChainPresenter
>(*this);
55 const auto old
= ret
->SwapBackBuffer(surf
);
56 MOZ_ALWAYS_TRUE(!old
);
60 void SwapChain::ClearPool() {
62 mPrevFrontBuffer
= nullptr;
65 bool SwapChain::StoreRecycledSurface(
66 const std::shared_ptr
<SharedSurface
>& surf
) {
68 // Don't allow external recycled surfaces if SwapChain is managing own pool.
69 MOZ_ASSERT(!mPoolLimit
);
70 if (mPoolLimit
> 0 || !mFactory
||
71 NS_WARN_IF(surf
->mDesc
.gl
!= mFactory
->mDesc
.gl
)) {
72 // Ensure we don't accidentally store an expired shared surface or from a
82 SwapChainPresenter::SwapChainPresenter(SwapChain
& swapChain
)
83 : mSwapChain(&swapChain
) {
84 MOZ_RELEASE_ASSERT(mSwapChain
->mPresenter
== nullptr);
85 mSwapChain
->mPresenter
= this;
88 SwapChainPresenter::~SwapChainPresenter() {
89 if (!mSwapChain
) return;
90 MOZ_RELEASE_ASSERT(mSwapChain
->mPresenter
== this);
91 mSwapChain
->mPresenter
= nullptr;
93 auto newFront
= SwapBackBuffer(nullptr);
95 mSwapChain
->mPrevFrontBuffer
= mSwapChain
->mFrontBuffer
;
96 mSwapChain
->mFrontBuffer
= newFront
;
100 std::shared_ptr
<SharedSurface
> SwapChainPresenter::SwapBackBuffer(
101 std::shared_ptr
<SharedSurface
> back
) {
103 mBackBuffer
->UnlockProd();
104 mBackBuffer
->ProducerRelease();
105 mBackBuffer
->Commit();
107 auto old
= mBackBuffer
;
110 mBackBuffer
->WaitForBufferOwnership();
111 mBackBuffer
->ProducerAcquire();
112 mBackBuffer
->LockProd();
117 GLuint
SwapChainPresenter::Fb() const {
118 if (!mBackBuffer
) return 0;
119 const auto& fb
= mBackBuffer
->mFb
;
127 SwapChain::SwapChain()
128 : // We need to apply pooling on Android because of the AndroidSurface slow
129 // destructor bugs. They cause a noticeable performance hit. See bug
131 mPoolLimit(kIsAndroid
? 4 : 0) {}
133 SwapChain::~SwapChain() {
135 // Out of order destruction, but ok.
136 (void)mPresenter
->SwapBackBuffer(nullptr);
137 mPresenter
->mSwapChain
= nullptr;
138 mPresenter
= nullptr;
140 if (mDestroyedCallback
) {
141 mDestroyedCallback();
145 } // namespace mozilla::gl