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"
14 namespace mozilla::gl
{
19 // We need to apply pooling on Android because of the AndroidSurface slow
20 // destructor bugs. They cause a noticeable performance hit. See bug
22 static constexpr size_t kPoolSize
=
23 #if defined(MOZ_WIDGET_ANDROID)
29 UniquePtr
<SwapChainPresenter
> SwapChain::Acquire(
30 const gfx::IntSize
& size
, const gfx::ColorSpace2 colorSpace
) {
33 std::shared_ptr
<SharedSurface
> surf
;
36 const auto& existingDesc
= mPool
.front()->mDesc
;
37 auto newDesc
= existingDesc
;
39 newDesc
.colorSpace
= colorSpace
;
40 if (newDesc
!= existingDesc
|| !mPool
.front()->IsValid()) {
45 // When mDestroyedCallback exists, recycling of SharedSurfaces is managed by
46 // the owner of the SwapChain by calling StoreRecycledSurface().
47 const auto poolSize
= mDestroyedCallback
? 0 : kPoolSize
;
49 if (!mPool
.empty() && (!poolSize
|| mPool
.size() == poolSize
)) {
54 auto uniquePtrSurf
= mFactory
->CreateShared(size
, colorSpace
);
55 if (!uniquePtrSurf
) return nullptr;
56 surf
.reset(uniquePtrSurf
.release());
59 while (mPool
.size() > poolSize
) {
63 auto ret
= MakeUnique
<SwapChainPresenter
>(*this);
64 const auto old
= ret
->SwapBackBuffer(surf
);
65 MOZ_ALWAYS_TRUE(!old
);
69 void SwapChain::ClearPool() {
71 mPrevFrontBuffer
= nullptr;
74 bool SwapChain::StoreRecycledSurface(
75 const std::shared_ptr
<SharedSurface
>& surf
) {
77 if (!mFactory
|| NS_WARN_IF(surf
->mDesc
.gl
!= mFactory
->mDesc
.gl
)) {
78 // Ensure we don't accidentally store an expired shared surface or from a
88 SwapChainPresenter::SwapChainPresenter(SwapChain
& swapChain
)
89 : mSwapChain(&swapChain
) {
90 MOZ_RELEASE_ASSERT(mSwapChain
->mPresenter
== nullptr);
91 mSwapChain
->mPresenter
= this;
94 SwapChainPresenter::~SwapChainPresenter() {
95 if (!mSwapChain
) return;
96 MOZ_RELEASE_ASSERT(mSwapChain
->mPresenter
== this);
97 mSwapChain
->mPresenter
= nullptr;
99 auto newFront
= SwapBackBuffer(nullptr);
101 mSwapChain
->mPrevFrontBuffer
= mSwapChain
->mFrontBuffer
;
102 mSwapChain
->mFrontBuffer
= newFront
;
106 std::shared_ptr
<SharedSurface
> SwapChainPresenter::SwapBackBuffer(
107 std::shared_ptr
<SharedSurface
> back
) {
109 mBackBuffer
->UnlockProd();
110 mBackBuffer
->ProducerRelease();
111 mBackBuffer
->Commit();
113 auto old
= mBackBuffer
;
116 mBackBuffer
->WaitForBufferOwnership();
117 mBackBuffer
->ProducerAcquire();
118 mBackBuffer
->LockProd();
123 GLuint
SwapChainPresenter::Fb() const {
124 if (!mBackBuffer
) return 0;
125 const auto& fb
= mBackBuffer
->mFb
;
133 SwapChain::SwapChain() = default;
135 SwapChain::~SwapChain() {
137 // Out of order destruction, but ok.
138 (void)mPresenter
->SwapBackBuffer(nullptr);
139 mPresenter
->mSwapChain
= nullptr;
140 mPresenter
= nullptr;
142 if (mDestroyedCallback
) {
143 mDestroyedCallback();
147 } // namespace mozilla::gl