GLScreenBuffer.cpp (3746B)
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/. */ 5 6 #include "GLScreenBuffer.h" 7 8 #include "CompositorTypes.h" 9 #include "GLContext.h" 10 #include "gfx2DGlue.h" 11 #include "MozFramebuffer.h" 12 #include "SharedSurface.h" 13 #include "mozilla/gfx/BuildConstants.h" 14 15 namespace mozilla::gl { 16 17 // - 18 // SwapChainPresenter 19 20 UniquePtr<SwapChainPresenter> SwapChain::Acquire( 21 const gfx::IntSize& size, const gfx::ColorSpace2 colorSpace) { 22 MOZ_ASSERT(mFactory); 23 24 std::shared_ptr<SharedSurface> surf; 25 if (!mPool.empty()) { 26 // Try reuse 27 const auto& existingDesc = mPool.front()->mDesc; 28 auto newDesc = existingDesc; 29 newDesc.size = size; 30 newDesc.colorSpace = colorSpace; 31 if (newDesc != existingDesc || !mPool.front()->IsValid()) { 32 mPool = {}; 33 } 34 } 35 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)) { 39 surf = mPool.front(); 40 mPool.pop(); 41 } 42 if (!surf) { 43 auto uniquePtrSurf = mFactory->CreateShared(size, colorSpace); 44 if (!uniquePtrSurf) return nullptr; 45 surf.reset(uniquePtrSurf.release()); 46 } 47 if (mPoolLimit > 0) { 48 mPool.push(surf); 49 while (mPool.size() > mPoolLimit) { 50 mPool.pop(); 51 } 52 } 53 54 auto ret = MakeUnique<SwapChainPresenter>(*this); 55 const auto old = ret->SwapBackBuffer(surf); 56 MOZ_ALWAYS_TRUE(!old); 57 return ret; 58 } 59 60 void SwapChain::ClearPool() { 61 mPool = {}; 62 mPrevFrontBuffer = nullptr; 63 } 64 65 bool SwapChain::StoreRecycledSurface( 66 const std::shared_ptr<SharedSurface>& surf) { 67 MOZ_ASSERT(mFactory); 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 73 // different context. 74 return false; 75 } 76 mPool.push(surf); 77 return true; 78 } 79 80 // - 81 82 SwapChainPresenter::SwapChainPresenter(SwapChain& swapChain) 83 : mSwapChain(&swapChain) { 84 MOZ_RELEASE_ASSERT(mSwapChain->mPresenter == nullptr); 85 mSwapChain->mPresenter = this; 86 } 87 88 SwapChainPresenter::~SwapChainPresenter() { 89 if (!mSwapChain) return; 90 MOZ_RELEASE_ASSERT(mSwapChain->mPresenter == this); 91 mSwapChain->mPresenter = nullptr; 92 93 auto newFront = SwapBackBuffer(nullptr); 94 if (newFront) { 95 mSwapChain->mPrevFrontBuffer = mSwapChain->mFrontBuffer; 96 mSwapChain->mFrontBuffer = newFront; 97 } 98 } 99 100 std::shared_ptr<SharedSurface> SwapChainPresenter::SwapBackBuffer( 101 std::shared_ptr<SharedSurface> back) { 102 if (mBackBuffer) { 103 mBackBuffer->EndWrite(); 104 } 105 auto old = mBackBuffer; 106 mBackBuffer = back; 107 if (mBackBuffer) { 108 mBackBuffer->BeginWrite(); 109 } 110 return old; 111 } 112 113 GLuint SwapChainPresenter::Fb() const { 114 if (!mBackBuffer) return 0; 115 const auto& fb = mBackBuffer->mFb; 116 if (!fb) return 0; 117 return fb->mFB; 118 } 119 120 // - 121 // SwapChain 122 123 SwapChain::SwapChain() 124 : // We need to apply pooling on Android because of the AndroidSurface slow 125 // destructor bugs. They cause a noticeable performance hit. See bug 126 // #1646073. 127 mPoolLimit(kIsAndroid ? 4 : 0) {} 128 129 SwapChain::~SwapChain() { 130 if (mPresenter) { 131 // Out of order destruction, but ok. 132 (void)mPresenter->SwapBackBuffer(nullptr); 133 mPresenter->mSwapChain = nullptr; 134 mPresenter = nullptr; 135 } 136 if (mDestroyedCallback) { 137 mDestroyedCallback(); 138 } 139 } 140 141 } // namespace mozilla::gl