1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/layers/RemoteTextureMap.h"
12 #include "CompositableHost.h"
13 #include "mozilla/ipc/ProtocolUtils.h"
14 #include "mozilla/gfx/gfxVars.h"
15 #include "mozilla/layers/AsyncImagePipelineManager.h"
16 #include "mozilla/layers/BufferTexture.h"
17 #include "mozilla/layers/CompositorThread.h"
18 #include "mozilla/layers/ImageDataSerializer.h"
19 #include "mozilla/layers/RemoteTextureHostWrapper.h"
20 #include "mozilla/layers/TextureClientSharedSurface.h"
21 #include "mozilla/layers/WebRenderTextureHost.h"
22 #include "mozilla/StaticPrefs_gfx.h"
23 #include "mozilla/StaticPrefs_webgl.h"
24 #include "mozilla/webgpu/ExternalTexture.h"
25 #include "mozilla/webrender/RenderThread.h"
26 #include "SharedSurface.h"
28 namespace mozilla::layers
{
30 RemoteTextureRecycleBin::RemoteTextureRecycleBin(bool aIsShared
)
31 : mIsShared(aIsShared
) {}
33 RemoteTextureRecycleBin::~RemoteTextureRecycleBin() = default;
35 RemoteTextureOwnerClient::RemoteTextureOwnerClient(
36 const base::ProcessId aForPid
)
39 RemoteTextureOwnerClient::~RemoteTextureOwnerClient() = default;
41 bool RemoteTextureOwnerClient::IsRegistered(
42 const RemoteTextureOwnerId aOwnerId
) {
43 auto it
= mOwnerIds
.find(aOwnerId
);
44 if (it
== mOwnerIds
.end()) {
50 void RemoteTextureOwnerClient::RegisterTextureOwner(
51 const RemoteTextureOwnerId aOwnerId
, bool aSharedRecycling
) {
52 MOZ_ASSERT(mOwnerIds
.find(aOwnerId
) == mOwnerIds
.end());
53 mOwnerIds
.emplace(aOwnerId
);
54 RefPtr
<RemoteTextureRecycleBin
> recycleBin
;
55 if (aSharedRecycling
) {
56 if (!mSharedRecycleBin
) {
57 mSharedRecycleBin
= new RemoteTextureRecycleBin(true);
59 recycleBin
= mSharedRecycleBin
;
61 RemoteTextureMap::Get()->RegisterTextureOwner(aOwnerId
, mForPid
, recycleBin
);
64 void RemoteTextureOwnerClient::UnregisterTextureOwner(
65 const RemoteTextureOwnerId aOwnerId
) {
66 auto it
= mOwnerIds
.find(aOwnerId
);
67 if (it
== mOwnerIds
.end()) {
71 RemoteTextureMap::Get()->UnregisterTextureOwner(aOwnerId
, mForPid
);
74 void RemoteTextureOwnerClient::UnregisterAllTextureOwners() {
75 if (mOwnerIds
.empty()) {
78 RemoteTextureMap::Get()->UnregisterTextureOwners(mOwnerIds
, mForPid
);
80 mSharedRecycleBin
= nullptr;
83 bool RemoteTextureOwnerClient::WaitForTxn(const RemoteTextureOwnerId aOwnerId
,
84 RemoteTextureTxnType aTxnType
,
85 RemoteTextureTxnId aTxnId
) {
86 auto it
= mOwnerIds
.find(aOwnerId
);
87 if (it
== mOwnerIds
.end() || !aTxnType
|| !aTxnId
) {
90 return RemoteTextureMap::Get()->WaitForTxn(aOwnerId
, mForPid
, aTxnType
,
94 void RemoteTextureOwnerClient::ClearRecycledTextures() {
95 RemoteTextureMap::Get()->ClearRecycledTextures(mOwnerIds
, mForPid
,
99 void RemoteTextureOwnerClient::NotifyContextLost(
100 const RemoteTextureOwnerIdSet
* aOwnerIds
) {
102 for (const auto& id
: *aOwnerIds
) {
103 if (mOwnerIds
.find(id
) == mOwnerIds
.end()) {
104 MOZ_ASSERT_UNREACHABLE("owner id not registered by client");
109 aOwnerIds
= &mOwnerIds
;
111 if (aOwnerIds
->empty()) {
114 RemoteTextureMap::Get()->NotifyContextLost(*aOwnerIds
, mForPid
);
117 void RemoteTextureOwnerClient::NotifyContextRestored(
118 const RemoteTextureOwnerIdSet
* aOwnerIds
) {
120 for (const auto& id
: *aOwnerIds
) {
121 if (mOwnerIds
.find(id
) == mOwnerIds
.end()) {
122 MOZ_ASSERT_UNREACHABLE("owner id not registered by client");
127 aOwnerIds
= &mOwnerIds
;
129 if (aOwnerIds
->empty()) {
132 RemoteTextureMap::Get()->NotifyContextRestored(*aOwnerIds
, mForPid
);
135 void RemoteTextureOwnerClient::PushTexture(
136 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
137 UniquePtr
<TextureData
>&& aTextureData
) {
138 MOZ_ASSERT(IsRegistered(aOwnerId
));
140 RefPtr
<TextureHost
> textureHost
= RemoteTextureMap::CreateRemoteTexture(
141 aTextureData
.get(), TextureFlags::DEFAULT
);
143 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
147 RemoteTextureMap::Get()->PushTexture(aTextureId
, aOwnerId
, mForPid
,
148 std::move(aTextureData
), textureHost
,
149 /* aResourceWrapper */ nullptr);
152 void RemoteTextureOwnerClient::PushTexture(
153 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
154 const std::shared_ptr
<gl::SharedSurface
>& aSharedSurface
,
155 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
156 const SurfaceDescriptor
& aDesc
) {
157 MOZ_ASSERT(IsRegistered(aOwnerId
));
159 UniquePtr
<TextureData
> textureData
=
160 MakeUnique
<SharedSurfaceTextureData
>(aDesc
, aFormat
, aSize
);
161 RefPtr
<TextureHost
> textureHost
= RemoteTextureMap::CreateRemoteTexture(
162 textureData
.get(), TextureFlags::DEFAULT
);
164 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
168 RemoteTextureMap::Get()->PushTexture(
169 aTextureId
, aOwnerId
, mForPid
, std::move(textureData
), textureHost
,
170 SharedResourceWrapper::SharedSurface(aSharedSurface
));
173 void RemoteTextureOwnerClient::PushTexture(
174 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
175 const std::shared_ptr
<webgpu::ExternalTexture
>& aExternalTexture
,
176 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
177 const SurfaceDescriptor
& aDesc
) {
178 MOZ_ASSERT(IsRegistered(aOwnerId
));
180 UniquePtr
<TextureData
> textureData
=
181 MakeUnique
<SharedSurfaceTextureData
>(aDesc
, aFormat
, aSize
);
182 RefPtr
<TextureHost
> textureHost
= RemoteTextureMap::CreateRemoteTexture(
183 textureData
.get(), TextureFlags::DEFAULT
);
185 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
189 RemoteTextureMap::Get()->PushTexture(
190 aTextureId
, aOwnerId
, mForPid
, std::move(textureData
), textureHost
,
191 SharedResourceWrapper::ExternalTexture(aExternalTexture
));
194 void RemoteTextureOwnerClient::PushDummyTexture(
195 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
) {
196 MOZ_ASSERT(IsRegistered(aOwnerId
));
198 auto flags
= TextureFlags::DEALLOCATE_CLIENT
| TextureFlags::REMOTE_TEXTURE
|
199 TextureFlags::DUMMY_TEXTURE
;
200 auto* rawData
= BufferTextureData::Create(
201 gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8A8
, gfx::BackendType::SKIA
,
202 LayersBackend::LAYERS_WR
, flags
, ALLOC_DEFAULT
, nullptr);
204 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
208 auto textureData
= UniquePtr
<TextureData
>(rawData
);
210 RefPtr
<TextureHost
> textureHost
= RemoteTextureMap::CreateRemoteTexture(
211 textureData
.get(), TextureFlags::DUMMY_TEXTURE
);
213 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
217 RemoteTextureMap::Get()->PushTexture(aTextureId
, aOwnerId
, mForPid
,
218 std::move(textureData
), textureHost
,
219 /* aResourceWrapper */ nullptr);
222 void RemoteTextureOwnerClient::GetLatestBufferSnapshot(
223 const RemoteTextureOwnerId aOwnerId
, const mozilla::ipc::Shmem
& aDestShmem
,
224 const gfx::IntSize
& aSize
) {
225 MOZ_ASSERT(IsRegistered(aOwnerId
));
226 RemoteTextureMap::Get()->GetLatestBufferSnapshot(aOwnerId
, mForPid
,
230 UniquePtr
<TextureData
> RemoteTextureOwnerClient::GetRecycledTextureData(
231 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
232 TextureType aTextureType
, RemoteTextureOwnerId aOwnerId
) {
233 return RemoteTextureMap::Get()->GetRecycledTextureData(
234 aOwnerId
, mForPid
, mSharedRecycleBin
, aSize
, aFormat
, aTextureType
);
237 UniquePtr
<TextureData
>
238 RemoteTextureOwnerClient::CreateOrRecycleBufferTextureData(
239 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
240 RemoteTextureOwnerId aOwnerId
) {
242 GetRecycledTextureData(aSize
, aFormat
, TextureType::Unknown
, aOwnerId
);
247 auto flags
= TextureFlags::DEALLOCATE_CLIENT
| TextureFlags::REMOTE_TEXTURE
;
248 auto* data
= BufferTextureData::Create(aSize
, aFormat
, gfx::BackendType::SKIA
,
249 LayersBackend::LAYERS_WR
, flags
,
250 ALLOC_DEFAULT
, nullptr);
251 return UniquePtr
<TextureData
>(data
);
254 std::shared_ptr
<gl::SharedSurface
>
255 RemoteTextureOwnerClient::GetRecycledSharedSurface(
256 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
257 SurfaceDescriptor::Type aType
, RemoteTextureOwnerId aOwnerId
) {
258 UniquePtr
<SharedResourceWrapper
> wrapper
=
259 RemoteTextureMap::Get()->RemoteTextureMap::GetRecycledSharedTexture(
260 aOwnerId
, mForPid
, mSharedRecycleBin
, aSize
, aFormat
, aType
);
264 MOZ_ASSERT(wrapper
->mSharedSurface
);
265 return wrapper
->mSharedSurface
;
268 std::shared_ptr
<webgpu::ExternalTexture
>
269 RemoteTextureOwnerClient::GetRecycledExternalTexture(
270 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
271 SurfaceDescriptor::Type aType
, RemoteTextureOwnerId aOwnerId
) {
272 UniquePtr
<SharedResourceWrapper
> wrapper
=
273 RemoteTextureMap::Get()->RemoteTextureMap::GetRecycledSharedTexture(
274 aOwnerId
, mForPid
, mSharedRecycleBin
, aSize
, aFormat
, aType
);
278 MOZ_ASSERT(wrapper
->mExternalTexture
);
279 return wrapper
->mExternalTexture
;
282 StaticAutoPtr
<RemoteTextureMap
> RemoteTextureMap::sInstance
;
285 void RemoteTextureMap::Init() {
286 MOZ_ASSERT(!sInstance
);
287 sInstance
= new RemoteTextureMap();
291 void RemoteTextureMap::Shutdown() {
297 RemoteTextureMap::RemoteTextureMap() : mMonitor("RemoteTextureMap::mMonitor") {}
299 RemoteTextureMap::~RemoteTextureMap() = default;
301 bool RemoteTextureMap::RecycleTexture(
302 const RefPtr
<RemoteTextureRecycleBin
>& aRecycleBin
,
303 TextureDataHolder
& aHolder
, bool aExpireOldTextures
) {
304 if (!aHolder
.mTextureData
||
305 (aHolder
.mTextureHost
&&
306 aHolder
.mTextureHost
->GetFlags() & TextureFlags::DUMMY_TEXTURE
)) {
310 // Expire old textures so they don't sit in the list forever if unused.
311 constexpr size_t kSharedTextureLimit
= 21;
312 constexpr size_t kTextureLimit
= 7;
313 while (aRecycleBin
->mRecycledTextures
.size() >=
314 (aRecycleBin
->mIsShared
? kSharedTextureLimit
: kTextureLimit
)) {
315 if (!aExpireOldTextures
) {
316 // There are too many textures, and we can't expire any to make room.
319 aRecycleBin
->mRecycledTextures
.pop_front();
322 TextureData::Info info
;
323 aHolder
.mTextureData
->FillInfo(info
);
324 RemoteTextureRecycleBin::RecycledTextureHolder recycled
{info
.size
,
326 if (aHolder
.mResourceWrapper
) {
327 // Don't attempt to recycle non-recyclable shared surfaces
328 if (aHolder
.mResourceWrapper
->mSharedSurface
&&
329 !aHolder
.mResourceWrapper
->mSharedSurface
->mDesc
.canRecycle
) {
333 // Recycle shared texture
334 SurfaceDescriptor desc
;
335 if (!aHolder
.mTextureData
->Serialize(desc
)) {
338 recycled
.mType
= desc
.type();
339 recycled
.mResourceWrapper
= std::move(aHolder
.mResourceWrapper
);
341 // Recycle texture data
342 recycled
.mTextureData
= std::move(aHolder
.mTextureData
);
344 if (!StaticPrefs::gfx_remote_texture_recycle_disabled()) {
345 aRecycleBin
->mRecycledTextures
.push_back(std::move(recycled
));
351 void RemoteTextureMap::PushTexture(
352 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
353 const base::ProcessId aForPid
, UniquePtr
<TextureData
>&& aTextureData
,
354 RefPtr
<TextureHost
>& aTextureHost
,
355 UniquePtr
<SharedResourceWrapper
>&& aResourceWrapper
) {
356 MOZ_RELEASE_ASSERT(aTextureHost
);
358 std::vector
<RefPtr
<TextureHost
>>
359 releasingTextures
; // Release outside the monitor
360 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>
361 renderingReadyCallbacks
; // Call outside the monitor
363 MonitorAutoLock
lock(mMonitor
);
365 auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
);
367 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
371 if (owner
->mIsContextLost
&&
372 !(aTextureHost
->GetFlags() & TextureFlags::DUMMY_TEXTURE
)) {
373 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
374 gfxCriticalNoteOnce
<< "Texture pushed during context lost";
377 auto textureData
= MakeUnique
<TextureDataHolder
>(
378 aTextureId
, aTextureHost
, std::move(aTextureData
),
379 std::move(aResourceWrapper
));
381 MOZ_ASSERT(owner
->mLatestPushedTextureId
< aTextureId
);
382 if (owner
->mLatestPushedTextureId
< aTextureId
) {
383 owner
->mLatestPushedTextureId
= aTextureId
;
385 MOZ_ASSERT(owner
->mLatestUsingTextureId
< aTextureId
);
387 owner
->mWaitingTextureDataHolders
.push_back(std::move(textureData
));
390 GetRenderingReadyCallbacks(lock
, owner
, aTextureId
,
391 renderingReadyCallbacks
);
392 // Update mRemoteTextureHost.
393 // This happens when PushTexture() with RemoteTextureId is called after
394 // GetRemoteTexture() with the RemoteTextureId.
395 const auto key
= std::pair(aForPid
, aTextureId
);
396 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
397 if (it
!= mRemoteTextureHostWrapperHolders
.end()) {
398 MOZ_ASSERT(!it
->second
->mRemoteTextureHost
);
399 it
->second
->mRemoteTextureHost
= aTextureHost
;
405 // Release owner->mReleasingRenderedTextureHosts before checking
406 // NumCompositableRefs()
407 if (!owner
->mReleasingRenderedTextureHosts
.empty()) {
409 owner
->mReleasingRenderedTextureHosts
.begin(),
410 owner
->mReleasingRenderedTextureHosts
.end(),
411 std::back_inserter(releasingTextures
),
412 [](CompositableTextureHostRef
& aRef
) { return aRef
.get(); });
413 owner
->mReleasingRenderedTextureHosts
.clear();
416 // Drop obsoleted remote textures.
417 while (!owner
->mUsingTextureDataHolders
.empty()) {
418 auto& front
= owner
->mUsingTextureDataHolders
.front();
419 // If mLatestRenderedTextureHost is last compositable ref of remote
420 // texture's TextureHost, its RemoteTextureHostWrapper is already
421 // unregistered. It happens when pushed remote textures that follow are
422 // not rendered since last mLatestRenderedTextureHost update. In this
423 // case, remove the TextureHost from mUsingTextureDataHolders. It is for
424 // unblocking remote texture recyclieng.
425 if (front
->mTextureHost
&&
426 front
->mTextureHost
->NumCompositableRefs() == 1 &&
427 front
->mTextureHost
== owner
->mLatestRenderedTextureHost
) {
428 owner
->mUsingTextureDataHolders
.pop_front();
431 // When compositable ref of TextureHost becomes 0, the TextureHost is not
432 // used by WebRender anymore.
433 if (front
->mTextureHost
&&
434 front
->mTextureHost
->NumCompositableRefs() == 0) {
435 owner
->mReleasingTextureDataHolders
.push_back(std::move(front
));
436 owner
->mUsingTextureDataHolders
.pop_front();
437 } else if (front
->mTextureHost
&&
438 front
->mTextureHost
->NumCompositableRefs() >= 0) {
439 // Remote texture is still in use by WebRender.
442 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
443 owner
->mUsingTextureDataHolders
.pop_front();
446 while (!owner
->mReleasingTextureDataHolders
.empty()) {
447 RecycleTexture(owner
->mRecycleBin
,
448 *owner
->mReleasingTextureDataHolders
.front(), true);
449 owner
->mReleasingTextureDataHolders
.pop_front();
453 const auto info
= RemoteTextureInfo(aTextureId
, aOwnerId
, aForPid
);
454 for (auto& callback
: renderingReadyCallbacks
) {
459 bool RemoteTextureMap::RemoveTexture(const RemoteTextureId aTextureId
,
460 const RemoteTextureOwnerId aOwnerId
,
461 const base::ProcessId aForPid
) {
462 MonitorAutoLock
lock(mMonitor
);
464 auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
);
469 for (auto it
= owner
->mWaitingTextureDataHolders
.begin();
470 it
!= owner
->mWaitingTextureDataHolders
.end(); it
++) {
472 if (data
->mTextureId
== aTextureId
) {
473 if (mRemoteTextureHostWrapperHolders
.find(std::pair(
474 aForPid
, aTextureId
)) != mRemoteTextureHostWrapperHolders
.end()) {
477 if (!RecycleTexture(owner
->mRecycleBin
, *data
, false)) {
478 owner
->mReleasingTextureDataHolders
.push_back(std::move(data
));
480 owner
->mWaitingTextureDataHolders
.erase(it
);
488 void RemoteTextureMap::GetLatestBufferSnapshot(
489 const RemoteTextureOwnerId aOwnerId
, const base::ProcessId aForPid
,
490 const mozilla::ipc::Shmem
& aDestShmem
, const gfx::IntSize
& aSize
) {
491 // The compositable ref of remote texture should be updated in mMonitor lock.
492 CompositableTextureHostRef textureHostRef
;
493 RefPtr
<TextureHost
> releasingTexture
; // Release outside the monitor
494 std::shared_ptr
<webgpu::ExternalTexture
> externalTexture
;
496 MonitorAutoLock
lock(mMonitor
);
498 auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
);
500 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
504 // Get latest TextureHost of remote Texture.
505 if (owner
->mWaitingTextureDataHolders
.empty() &&
506 owner
->mUsingTextureDataHolders
.empty()) {
509 const auto* holder
= !owner
->mWaitingTextureDataHolders
.empty()
510 ? owner
->mWaitingTextureDataHolders
.back().get()
511 : owner
->mUsingTextureDataHolders
.back().get();
512 TextureHost
* textureHost
= holder
->mTextureHost
;
514 if (textureHost
->GetSize() != aSize
) {
515 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
518 if (textureHost
->GetFormat() != gfx::SurfaceFormat::R8G8B8A8
&&
519 textureHost
->GetFormat() != gfx::SurfaceFormat::B8G8R8A8
) {
520 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
523 if (holder
->mResourceWrapper
&&
524 holder
->mResourceWrapper
->mExternalTexture
) {
525 // Increment compositable ref to prevent that TextureDataHolder is removed
527 textureHostRef
= textureHost
;
528 externalTexture
= holder
->mResourceWrapper
->mExternalTexture
;
529 } else if (textureHost
->AsBufferTextureHost()) {
530 // Increment compositable ref to prevent that TextureDataHolder is removed
532 textureHostRef
= textureHost
;
534 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
539 if (!textureHostRef
) {
543 if (externalTexture
) {
544 externalTexture
->GetSnapshot(aDestShmem
, aSize
);
545 } else if (auto* bufferTextureHost
= textureHostRef
->AsBufferTextureHost()) {
546 uint32_t stride
= ImageDataSerializer::ComputeRGBStride(
547 bufferTextureHost
->GetFormat(), aSize
.width
);
548 uint32_t bufferSize
= stride
* aSize
.height
;
549 uint8_t* dst
= aDestShmem
.get
<uint8_t>();
550 uint8_t* src
= bufferTextureHost
->GetBuffer();
552 MOZ_ASSERT(bufferSize
<= aDestShmem
.Size
<uint8_t>());
553 memcpy(dst
, src
, bufferSize
);
557 MonitorAutoLock
lock(mMonitor
);
558 // Release compositable ref in mMonitor lock, but release RefPtr outside the
560 releasingTexture
= textureHostRef
;
561 textureHostRef
= nullptr;
565 void RemoteTextureMap::RegisterTextureOwner(
566 const RemoteTextureOwnerId aOwnerId
, const base::ProcessId aForPid
,
567 const RefPtr
<RemoteTextureRecycleBin
>& aRecycleBin
) {
568 MonitorAutoLock
lock(mMonitor
);
570 const auto key
= std::pair(aForPid
, aOwnerId
);
571 auto it
= mTextureOwners
.find(key
);
572 if (it
!= mTextureOwners
.end()) {
573 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
576 auto owner
= MakeUnique
<TextureOwner
>();
578 owner
->mRecycleBin
= aRecycleBin
;
580 owner
->mRecycleBin
= new RemoteTextureRecycleBin(false);
583 auto itWaiting
= mWaitingTextureOwners
.find(key
);
584 if (itWaiting
!= mWaitingTextureOwners
.end()) {
585 owner
->mRenderingReadyCallbackHolders
.swap(
586 itWaiting
->second
->mRenderingReadyCallbackHolders
);
587 mWaitingTextureOwners
.erase(itWaiting
);
590 mTextureOwners
.emplace(key
, std::move(owner
));
593 void RemoteTextureMap::KeepTextureDataAliveForTextureHostIfNecessary(
594 const MonitorAutoLock
& aProofOfLock
, RemoteTextureMap::TextureOwner
* aOwner
,
595 std::deque
<UniquePtr
<TextureDataHolder
>>& aHolders
) {
596 for (auto& holder
: aHolders
) {
597 // If remote texture of TextureHost still exist, keep
598 // SharedResourceWrapper/TextureData alive while the TextureHost is alive.
599 if (holder
->mTextureHost
&&
600 holder
->mTextureHost
->NumCompositableRefs() > 0) {
601 RefPtr
<nsISerialEventTarget
> eventTarget
= GetCurrentSerialEventTarget();
602 RefPtr
<Runnable
> runnable
= NS_NewRunnableFunction(
603 "RemoteTextureMap::UnregisterTextureOwner::Runnable",
604 [data
= std::move(holder
->mTextureData
),
605 wrapper
= std::move(holder
->mResourceWrapper
)]() {});
607 auto destroyedCallback
= [eventTarget
= std::move(eventTarget
),
608 runnable
= std::move(runnable
)]() mutable {
609 eventTarget
->Dispatch(runnable
.forget());
612 holder
->mTextureHost
->SetDestroyedCallback(destroyedCallback
);
614 RecycleTexture(aOwner
->mRecycleBin
, *holder
, true);
619 UniquePtr
<RemoteTextureMap::TextureOwner
>
620 RemoteTextureMap::UnregisterTextureOwner(
621 MonitorAutoLock
& aProofOfLock
, const RemoteTextureOwnerId aOwnerId
,
622 const base::ProcessId aForPid
,
623 std::vector
<RefPtr
<TextureHost
>>& aReleasingTextures
,
624 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>&
625 aRenderingReadyCallbacks
) {
626 const auto key
= std::pair(aForPid
, aOwnerId
);
627 auto it
= mTextureOwners
.find(key
);
628 if (it
== mTextureOwners
.end()) {
629 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
633 auto* owner
= it
->second
.get();
634 // If waiting for a last use, and it hasn't arrived yet, then defer
636 if (owner
->mWaitForTxn
) {
637 owner
->mDeferUnregister
= GetCurrentSerialEventTarget();
638 // If another thread is waiting on this owner to produce textures,
639 // it must be notified that owner is going away.
640 if (!owner
->mLatestTextureHost
&&
641 owner
->mWaitingTextureDataHolders
.empty()) {
642 aProofOfLock
.Notify();
647 if (owner
->mLatestTextureHost
) {
648 // Release CompositableRef in mMonitor
649 aReleasingTextures
.emplace_back(owner
->mLatestTextureHost
);
650 owner
->mLatestTextureHost
= nullptr;
653 // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could
654 // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts in
655 // mUsingTextureDataHolders alive. They need to be cleared before
656 // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses
657 // NumCompositableRefs().
658 if (!owner
->mReleasingRenderedTextureHosts
.empty()) {
659 std::transform(owner
->mReleasingRenderedTextureHosts
.begin(),
660 owner
->mReleasingRenderedTextureHosts
.end(),
661 std::back_inserter(aReleasingTextures
),
662 [](CompositableTextureHostRef
& aRef
) { return aRef
.get(); });
663 owner
->mReleasingRenderedTextureHosts
.clear();
665 if (owner
->mLatestRenderedTextureHost
) {
666 owner
->mLatestRenderedTextureHost
= nullptr;
669 GetAllRenderingReadyCallbacks(aProofOfLock
, owner
, aRenderingReadyCallbacks
);
671 KeepTextureDataAliveForTextureHostIfNecessary(
672 aProofOfLock
, owner
, owner
->mWaitingTextureDataHolders
);
674 KeepTextureDataAliveForTextureHostIfNecessary(
675 aProofOfLock
, owner
, owner
->mUsingTextureDataHolders
);
677 KeepTextureDataAliveForTextureHostIfNecessary(
678 aProofOfLock
, owner
, owner
->mReleasingTextureDataHolders
);
680 UniquePtr
<TextureOwner
> releasingOwner
= std::move(it
->second
);
681 mTextureOwners
.erase(it
);
682 return releasingOwner
;
685 void RemoteTextureMap::UnregisterTextureOwner(
686 const RemoteTextureOwnerId aOwnerId
, const base::ProcessId aForPid
) {
687 UniquePtr
<TextureOwner
> releasingOwner
; // Release outside the monitor
688 std::vector
<RefPtr
<TextureHost
>>
689 releasingTextures
; // Release outside the monitor
690 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>
691 renderingReadyCallbacks
; // Call outside the monitor
693 MonitorAutoLock
lock(mMonitor
);
695 releasingOwner
= UnregisterTextureOwner(
696 lock
, aOwnerId
, aForPid
, releasingTextures
, renderingReadyCallbacks
);
697 if (!releasingOwner
) {
705 RemoteTextureInfo(RemoteTextureId
{0}, RemoteTextureOwnerId
{0}, 0);
706 for (auto& callback
: renderingReadyCallbacks
) {
711 void RemoteTextureMap::UnregisterTextureOwners(
712 const RemoteTextureOwnerIdSet
& aOwnerIds
, const base::ProcessId aForPid
) {
713 std::vector
<UniquePtr
<TextureOwner
>>
714 releasingOwners
; // Release outside the monitor
715 std::vector
<RefPtr
<TextureHost
>>
716 releasingTextures
; // Release outside the monitor
717 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>
718 renderingReadyCallbacks
; // Call outside the monitor
720 MonitorAutoLock
lock(mMonitor
);
722 for (const auto& id
: aOwnerIds
) {
723 if (auto releasingOwner
= UnregisterTextureOwner(
724 lock
, id
, aForPid
, releasingTextures
, renderingReadyCallbacks
)) {
725 releasingOwners
.push_back(std::move(releasingOwner
));
729 if (releasingOwners
.empty()) {
737 RemoteTextureInfo(RemoteTextureId
{0}, RemoteTextureOwnerId
{0}, 0);
738 for (auto& callback
: renderingReadyCallbacks
) {
743 already_AddRefed
<RemoteTextureTxnScheduler
>
744 RemoteTextureMap::RegisterTxnScheduler(base::ProcessId aForPid
,
745 RemoteTextureTxnType aType
) {
746 MonitorAutoLock
lock(mMonitor
);
748 const auto key
= std::pair(aForPid
, aType
);
749 auto it
= mTxnSchedulers
.find(key
);
750 if (it
!= mTxnSchedulers
.end()) {
751 return do_AddRef(it
->second
);
754 RefPtr
<RemoteTextureTxnScheduler
> scheduler(
755 new RemoteTextureTxnScheduler(aForPid
, aType
));
756 mTxnSchedulers
.emplace(key
, scheduler
.get());
757 return scheduler
.forget();
760 void RemoteTextureMap::UnregisterTxnScheduler(base::ProcessId aForPid
,
761 RemoteTextureTxnType aType
) {
762 MonitorAutoLock
lock(mMonitor
);
764 const auto key
= std::pair(aForPid
, aType
);
765 auto it
= mTxnSchedulers
.find(key
);
766 if (it
== mTxnSchedulers
.end()) {
767 MOZ_ASSERT_UNREACHABLE("Remote texture txn scheduler does not exist.");
770 mTxnSchedulers
.erase(it
);
773 already_AddRefed
<RemoteTextureTxnScheduler
> RemoteTextureTxnScheduler::Create(
774 mozilla::ipc::IProtocol
* aProtocol
) {
775 if (auto* instance
= RemoteTextureMap::Get()) {
776 if (auto* toplevel
= aProtocol
->ToplevelProtocol()) {
777 auto pid
= toplevel
->OtherPidMaybeInvalid();
778 if (pid
!= base::kInvalidProcessId
) {
779 return instance
->RegisterTxnScheduler(pid
, toplevel
->GetProtocolId());
786 RemoteTextureTxnScheduler::~RemoteTextureTxnScheduler() {
787 NotifyTxn(std::numeric_limits
<RemoteTextureTxnId
>::max());
788 RemoteTextureMap::Get()->UnregisterTxnScheduler(mForPid
, mType
);
791 void RemoteTextureTxnScheduler::NotifyTxn(RemoteTextureTxnId aTxnId
) {
792 MonitorAutoLock
lock(RemoteTextureMap::Get()->mMonitor
);
796 for (; !mWaits
.empty(); mWaits
.pop_front()) {
797 auto& wait
= mWaits
.front();
798 if (wait
.mTxnId
> aTxnId
) {
801 RemoteTextureMap::Get()->NotifyTxn(lock
, wait
.mOwnerId
, mForPid
);
805 bool RemoteTextureTxnScheduler::WaitForTxn(const MonitorAutoLock
& aProofOfLock
,
806 RemoteTextureOwnerId aOwnerId
,
807 RemoteTextureTxnId aTxnId
) {
808 if (aTxnId
<= mLastTxnId
) {
811 mWaits
.insert(std::upper_bound(mWaits
.begin(), mWaits
.end(), aTxnId
),
812 Wait
{aOwnerId
, aTxnId
});
816 void RemoteTextureMap::ClearRecycledTextures(
817 const RemoteTextureOwnerIdSet
& aOwnerIds
, const base::ProcessId aForPid
,
818 const RefPtr
<RemoteTextureRecycleBin
>& aRecycleBin
) {
819 std::list
<RemoteTextureRecycleBin::RecycledTextureHolder
>
820 releasingTextures
; // Release outside the monitor
822 MonitorAutoLock
lock(mMonitor
);
825 releasingTextures
.splice(releasingTextures
.end(),
826 aRecycleBin
->mRecycledTextures
);
829 for (const auto& id
: aOwnerIds
) {
830 const auto key
= std::pair(aForPid
, id
);
831 auto it
= mTextureOwners
.find(key
);
832 if (it
== mTextureOwners
.end()) {
833 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
836 auto& owner
= it
->second
;
838 releasingTextures
.splice(releasingTextures
.end(),
839 owner
->mRecycleBin
->mRecycledTextures
);
844 void RemoteTextureMap::NotifyContextLost(
845 const RemoteTextureOwnerIdSet
& aOwnerIds
, const base::ProcessId aForPid
) {
846 MonitorAutoLock
lock(mMonitor
);
848 bool changed
= false;
849 for (const auto& id
: aOwnerIds
) {
850 const auto key
= std::pair(aForPid
, id
);
851 auto it
= mTextureOwners
.find(key
);
852 if (it
== mTextureOwners
.end()) {
853 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
856 auto& owner
= it
->second
;
857 if (!owner
->mIsContextLost
) {
858 owner
->mIsContextLost
= true;
868 void RemoteTextureMap::NotifyContextRestored(
869 const RemoteTextureOwnerIdSet
& aOwnerIds
, const base::ProcessId aForPid
) {
870 MonitorAutoLock
lock(mMonitor
);
872 bool changed
= false;
873 for (const auto& id
: aOwnerIds
) {
874 const auto key
= std::pair(aForPid
, id
);
875 auto it
= mTextureOwners
.find(key
);
876 if (it
== mTextureOwners
.end()) {
877 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
880 auto& owner
= it
->second
;
881 if (owner
->mIsContextLost
) {
882 owner
->mIsContextLost
= false;
893 RefPtr
<TextureHost
> RemoteTextureMap::CreateRemoteTexture(
894 TextureData
* aTextureData
, TextureFlags aTextureFlags
) {
895 SurfaceDescriptor desc
;
896 DebugOnly
<bool> ret
= aTextureData
->Serialize(desc
);
898 TextureFlags flags
= aTextureFlags
| TextureFlags::REMOTE_TEXTURE
|
899 TextureFlags::DEALLOCATE_CLIENT
;
901 Maybe
<wr::ExternalImageId
> externalImageId
= Nothing();
902 RefPtr
<TextureHost
> textureHost
=
903 TextureHost::Create(desc
, null_t(), nullptr, LayersBackend::LAYERS_WR
,
904 flags
, externalImageId
);
905 MOZ_ASSERT(textureHost
);
907 gfxCriticalNoteOnce
<< "Failed to create remote texture";
911 textureHost
->EnsureRenderTexture(Nothing());
916 void RemoteTextureMap::UpdateTexture(const MonitorAutoLock
& aProofOfLock
,
917 RemoteTextureMap::TextureOwner
* aOwner
,
918 const RemoteTextureId aTextureId
) {
919 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
921 MOZ_ASSERT(aTextureId
>= aOwner
->mLatestUsingTextureId
);
923 if (aTextureId
== aOwner
->mLatestUsingTextureId
) {
924 // No need to update texture.
928 // Move remote textures to mUsingTextureDataHolders.
929 while (!aOwner
->mWaitingTextureDataHolders
.empty()) {
930 auto& front
= aOwner
->mWaitingTextureDataHolders
.front();
931 if (aTextureId
< front
->mTextureId
) {
934 MOZ_RELEASE_ASSERT(front
->mTextureHost
);
935 aOwner
->mLatestTextureHost
= front
->mTextureHost
;
936 aOwner
->mLatestUsingTextureId
= front
->mTextureId
;
938 UniquePtr
<TextureDataHolder
> holder
= std::move(front
);
939 aOwner
->mWaitingTextureDataHolders
.pop_front();
940 // If there are textures not being used by the compositor that will be
941 // obsoleted by this new texture, then queue them for removal later on
942 // the creating thread.
943 while (!aOwner
->mUsingTextureDataHolders
.empty()) {
944 auto& back
= aOwner
->mUsingTextureDataHolders
.back();
945 if (back
->mTextureHost
&&
946 back
->mTextureHost
->NumCompositableRefs() == 0) {
947 if (!RecycleTexture(aOwner
->mRecycleBin
, *back
, false)) {
948 aOwner
->mReleasingTextureDataHolders
.push_back(std::move(back
));
950 aOwner
->mUsingTextureDataHolders
.pop_back();
955 aOwner
->mUsingTextureDataHolders
.push_back(std::move(holder
));
959 void RemoteTextureMap::GetRenderingReadyCallbacks(
960 const MonitorAutoLock
& aProofOfLock
, RemoteTextureMap::TextureOwner
* aOwner
,
961 const RemoteTextureId aTextureId
,
962 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>& aFunctions
) {
965 while (!aOwner
->mRenderingReadyCallbackHolders
.empty()) {
966 auto& front
= aOwner
->mRenderingReadyCallbackHolders
.front();
967 if (aTextureId
< front
->mTextureId
) {
970 if (front
->mCallback
) {
971 aFunctions
.push_back(std::move(front
->mCallback
));
973 aOwner
->mRenderingReadyCallbackHolders
.pop_front();
977 void RemoteTextureMap::GetAllRenderingReadyCallbacks(
978 const MonitorAutoLock
& aProofOfLock
, RemoteTextureMap::TextureOwner
* aOwner
,
979 std::vector
<std::function
<void(const RemoteTextureInfo
&)>>& aFunctions
) {
980 GetRenderingReadyCallbacks(aProofOfLock
, aOwner
, RemoteTextureId::Max(),
982 MOZ_ASSERT(aOwner
->mRenderingReadyCallbackHolders
.empty());
985 bool RemoteTextureMap::WaitForRemoteTextureOwner(
986 RemoteTextureHostWrapper
* aTextureHostWrapper
) {
987 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
988 MOZ_ASSERT(aTextureHostWrapper
);
990 const auto& ownerId
= aTextureHostWrapper
->mOwnerId
;
991 const auto& forPid
= aTextureHostWrapper
->mForPid
;
993 MonitorAutoLock
lock(mMonitor
);
995 auto* owner
= GetTextureOwner(lock
, ownerId
, forPid
);
996 // If there is no texture owner yet, then we might need to wait for one to
997 // be created, if allowed. If so, we must also wait for an initial texture
998 // host to be created so we can use it.
999 if (!owner
|| (!owner
->mLatestTextureHost
&&
1000 owner
->mWaitingTextureDataHolders
.empty())) {
1001 const TimeDuration timeout
= TimeDuration::FromMilliseconds(10000);
1002 while (!owner
|| (!owner
->mLatestTextureHost
&&
1003 owner
->mWaitingTextureDataHolders
.empty())) {
1004 if (owner
&& (owner
->mIsContextLost
|| owner
->mDeferUnregister
)) {
1005 // If the context was lost, no further updates are expected.
1008 CVStatus status
= mMonitor
.Wait(timeout
);
1009 if (status
== CVStatus::Timeout
) {
1012 owner
= GetTextureOwner(lock
, ownerId
, forPid
);
1018 void RemoteTextureMap::GetRemoteTexture(
1019 RemoteTextureHostWrapper
* aTextureHostWrapper
) {
1020 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1021 MOZ_ASSERT(aTextureHostWrapper
);
1023 if (aTextureHostWrapper
->IsReadyForRendering()) {
1027 const auto& textureId
= aTextureHostWrapper
->mTextureId
;
1028 const auto& ownerId
= aTextureHostWrapper
->mOwnerId
;
1029 const auto& forPid
= aTextureHostWrapper
->mForPid
;
1030 const auto& size
= aTextureHostWrapper
->mSize
;
1032 RefPtr
<TextureHost
> textureHost
;
1034 MonitorAutoLock
lock(mMonitor
);
1036 auto* owner
= GetTextureOwner(lock
, ownerId
, forPid
);
1041 UpdateTexture(lock
, owner
, textureId
);
1043 if (owner
->mLatestTextureHost
&&
1044 (owner
->mLatestTextureHost
->GetFlags() & TextureFlags::DUMMY_TEXTURE
)) {
1045 // Remote texture allocation was failed.
1049 if (textureId
== owner
->mLatestUsingTextureId
) {
1050 MOZ_ASSERT(owner
->mLatestTextureHost
);
1051 MOZ_ASSERT(owner
->mLatestTextureHost
->GetSize() == size
);
1052 if (owner
->mLatestTextureHost
->GetSize() != size
) {
1053 gfxCriticalNoteOnce
<< "unexpected remote texture size: "
1054 << owner
->mLatestTextureHost
->GetSize()
1055 << " expected: " << size
;
1057 textureHost
= owner
->mLatestTextureHost
;
1060 // Update mRemoteTextureHost
1061 if (textureId
== owner
->mLatestUsingTextureId
) {
1062 const auto key
= std::pair(forPid
, textureId
);
1063 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1064 if (it
!= mRemoteTextureHostWrapperHolders
.end() &&
1065 !it
->second
->mRemoteTextureHost
) {
1066 it
->second
->mRemoteTextureHost
= owner
->mLatestTextureHost
;
1068 MOZ_ASSERT(it
->second
->mRemoteTextureHost
== owner
->mLatestTextureHost
);
1073 aTextureHostWrapper
->SetRemoteTextureHost(lock
, textureHost
);
1074 aTextureHostWrapper
->ApplyTextureFlagsToRemoteTexture();
1079 void RemoteTextureMap::NotifyTxn(const MonitorAutoLock
& aProofOfLock
,
1080 const RemoteTextureOwnerId aOwnerId
,
1081 const base::ProcessId aForPid
) {
1082 if (auto* owner
= GetTextureOwner(aProofOfLock
, aOwnerId
, aForPid
)) {
1083 if (!owner
->mWaitForTxn
) {
1084 MOZ_ASSERT_UNREACHABLE("Expected texture owner to wait for txn.");
1087 owner
->mWaitForTxn
= false;
1088 if (!owner
->mDeferUnregister
) {
1089 // If unregistering was not deferred, then don't try to force
1090 // unregistering yet.
1093 owner
->mDeferUnregister
->Dispatch(NS_NewRunnableFunction(
1094 "RemoteTextureMap::SetLastRemoteTextureUse::Runnable",
1095 [aOwnerId
, aForPid
]() {
1096 RemoteTextureMap::Get()->UnregisterTextureOwner(aOwnerId
, aForPid
);
1101 bool RemoteTextureMap::WaitForTxn(const RemoteTextureOwnerId aOwnerId
,
1102 const base::ProcessId aForPid
,
1103 RemoteTextureTxnType aTxnType
,
1104 RemoteTextureTxnId aTxnId
) {
1105 MonitorAutoLock
lock(mMonitor
);
1106 if (auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
)) {
1107 if (owner
->mDeferUnregister
) {
1108 MOZ_ASSERT_UNREACHABLE(
1109 "Texture owner must wait for txn before unregistering.");
1112 if (owner
->mWaitForTxn
) {
1113 MOZ_ASSERT_UNREACHABLE("Texture owner already waiting for txn.");
1116 const auto key
= std::pair(aForPid
, aTxnType
);
1117 auto it
= mTxnSchedulers
.find(key
);
1118 if (it
== mTxnSchedulers
.end()) {
1119 // During shutdown, different toplevel protocols may go away in
1120 // disadvantageous orders, causing us to sometimes be processing
1121 // waits even though the source of transactions upon which the
1122 // wait depends shut down. This is generally harmless to ignore,
1123 // as it means no further transactions will be generated of that
1124 // type and all such transactions have been processed before it
1126 NS_WARNING("Could not find scheduler for txn type.");
1129 if (it
->second
->WaitForTxn(lock
, aOwnerId
, aTxnId
)) {
1130 owner
->mWaitForTxn
= true;
1137 void RemoteTextureMap::ReleaseRemoteTextureHost(
1138 RemoteTextureHostWrapper
* aTextureHostWrapper
) {
1139 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1140 MOZ_ASSERT(aTextureHostWrapper
);
1142 RefPtr
<TextureHost
> releasingTexture
; // Release outside the mutex
1144 MonitorAutoLock
lock(mMonitor
);
1145 releasingTexture
= aTextureHostWrapper
->GetRemoteTextureHost(lock
);
1146 aTextureHostWrapper
->ClearRemoteTextureHost(lock
);
1150 RefPtr
<TextureHost
> RemoteTextureMap::GetOrCreateRemoteTextureHostWrapper(
1151 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
1152 const base::ProcessId aForPid
, const gfx::IntSize
& aSize
,
1153 const TextureFlags aFlags
) {
1154 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1155 MonitorAutoLock
lock(mMonitor
);
1157 const auto key
= std::pair(aForPid
, aTextureId
);
1158 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1159 if (it
!= mRemoteTextureHostWrapperHolders
.end()) {
1160 return it
->second
->mRemoteTextureHostWrapper
;
1163 auto wrapper
= RemoteTextureHostWrapper::Create(aTextureId
, aOwnerId
, aForPid
,
1165 auto wrapperHolder
= MakeUnique
<RemoteTextureHostWrapperHolder
>(wrapper
);
1167 mRemoteTextureHostWrapperHolders
.emplace(key
, std::move(wrapperHolder
));
1172 void RemoteTextureMap::UnregisterRemoteTextureHostWrapper(
1173 const RemoteTextureId aTextureId
, const RemoteTextureOwnerId aOwnerId
,
1174 const base::ProcessId aForPid
) {
1175 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1177 std::vector
<RefPtr
<TextureHost
>>
1178 releasingTextures
; // Release outside the monitor
1180 MonitorAutoLock
lock(mMonitor
);
1182 const auto key
= std::pair(aForPid
, aTextureId
);
1183 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1184 if (it
== mRemoteTextureHostWrapperHolders
.end()) {
1185 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1188 releasingTextures
.emplace_back(it
->second
->mRemoteTextureHostWrapper
);
1189 if (it
->second
->mRemoteTextureHost
) {
1190 releasingTextures
.emplace_back(it
->second
->mRemoteTextureHost
);
1193 mRemoteTextureHostWrapperHolders
.erase(it
);
1198 bool RemoteTextureMap::CheckRemoteTextureReady(
1199 const RemoteTextureInfo
& aInfo
,
1200 std::function
<void(const RemoteTextureInfo
&)>&& aCallback
) {
1201 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1203 MonitorAutoLock
lock(mMonitor
);
1205 auto* owner
= GetTextureOwner(lock
, aInfo
.mOwnerId
, aInfo
.mForPid
);
1206 if (aInfo
.mWaitForRemoteTextureOwner
&& !owner
) {
1207 // Remote texture owner is not registered yet. Waiting for remote texture
1210 const auto key
= std::pair(aInfo
.mForPid
, aInfo
.mOwnerId
);
1211 if (!mWaitingTextureOwners
[key
]) {
1212 auto waitingOwner
= MakeUnique
<WaitingTextureOwner
>();
1213 mWaitingTextureOwners
[key
] = std::move(waitingOwner
);
1216 MOZ_ASSERT(mWaitingTextureOwners
[key
]);
1218 WaitingTextureOwner
* waitingOwner
= mWaitingTextureOwners
[key
].get();
1220 auto callbackHolder
= MakeUnique
<RenderingReadyCallbackHolder
>(
1221 aInfo
.mTextureId
, std::move(aCallback
));
1222 waitingOwner
->mRenderingReadyCallbackHolders
.push_back(
1223 std::move(callbackHolder
));
1228 if (!owner
|| owner
->mIsContextLost
) {
1229 // Owner is already removed or context lost. No need to wait texture ready.
1233 const auto key
= std::pair(aInfo
.mForPid
, aInfo
.mTextureId
);
1234 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1235 if (it
== mRemoteTextureHostWrapperHolders
.end()) {
1236 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1237 gfxCriticalNoteOnce
<< "Remote texture does not exist id:"
1238 << uint64_t(aInfo
.mTextureId
);
1242 if (owner
->mLatestPushedTextureId
>= aInfo
.mTextureId
) {
1246 auto callbackHolder
= MakeUnique
<RenderingReadyCallbackHolder
>(
1247 aInfo
.mTextureId
, std::move(aCallback
));
1248 owner
->mRenderingReadyCallbackHolders
.push_back(std::move(callbackHolder
));
1253 bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo
& aInfo
) {
1254 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1256 MonitorAutoLock
lock(mMonitor
);
1258 auto* owner
= GetTextureOwner(lock
, aInfo
.mOwnerId
, aInfo
.mForPid
);
1259 if (aInfo
.mWaitForRemoteTextureOwner
&&
1260 (!owner
|| (!owner
->mLatestTextureHost
&&
1261 owner
->mWaitingTextureDataHolders
.empty()))) {
1262 const TimeDuration timeout
= TimeDuration::FromMilliseconds(10000);
1263 while (!owner
|| (!owner
->mLatestTextureHost
&&
1264 owner
->mWaitingTextureDataHolders
.empty())) {
1265 if (owner
&& (owner
->mIsContextLost
|| owner
->mDeferUnregister
)) {
1266 // If the context was lost, no further updates are expected.
1269 CVStatus status
= mMonitor
.Wait(timeout
);
1270 if (status
== CVStatus::Timeout
) {
1273 owner
= GetTextureOwner(lock
, aInfo
.mOwnerId
, aInfo
.mForPid
);
1277 if (!owner
|| owner
->mIsContextLost
) {
1278 // Owner is already removed or context lost.
1282 const auto key
= std::pair(aInfo
.mForPid
, aInfo
.mTextureId
);
1283 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1284 if (it
== mRemoteTextureHostWrapperHolders
.end()) {
1285 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1286 gfxCriticalNoteOnce
<< "Remote texture does not exist id:"
1287 << uint64_t(aInfo
.mTextureId
);
1291 const TimeDuration timeout
= TimeDuration::FromMilliseconds(1000);
1293 while (owner
->mLatestPushedTextureId
< aInfo
.mTextureId
) {
1294 CVStatus status
= mMonitor
.Wait(timeout
);
1295 if (status
== CVStatus::Timeout
) {
1296 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1297 gfxCriticalNoteOnce
<< "Remote texture wait time out id:"
1298 << uint64_t(aInfo
.mTextureId
);
1302 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1303 if (it
== mRemoteTextureHostWrapperHolders
.end()) {
1304 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1308 auto* owner
= GetTextureOwner(lock
, aInfo
.mOwnerId
, aInfo
.mForPid
);
1309 // When owner is alreay unregistered, remote texture will not be pushed.
1310 if (!owner
|| owner
->mIsContextLost
) {
1311 // This could happen with IPC abnormal shutdown
1319 void RemoteTextureMap::SuppressRemoteTextureReadyCheck(
1320 const RemoteTextureInfo
& aInfo
) {
1321 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1322 MonitorAutoLock
lock(mMonitor
);
1324 // Clear if WaitingTextureOwner exists.
1326 mWaitingTextureOwners
.find(std::pair(aInfo
.mForPid
, aInfo
.mOwnerId
));
1327 if (itWaiting
!= mWaitingTextureOwners
.end()) {
1328 mWaitingTextureOwners
.erase(itWaiting
);
1331 const auto key
= std::pair(aInfo
.mForPid
, aInfo
.mTextureId
);
1332 auto it
= mRemoteTextureHostWrapperHolders
.find(key
);
1333 if (it
== mRemoteTextureHostWrapperHolders
.end()) {
1334 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
1337 it
->second
->mReadyCheckSuppressed
= true;
1340 UniquePtr
<TextureData
> RemoteTextureMap::GetRecycledTextureData(
1341 const RemoteTextureOwnerId aOwnerId
, const base::ProcessId aForPid
,
1342 const RefPtr
<RemoteTextureRecycleBin
>& aRecycleBin
,
1343 const gfx::IntSize
& aSize
, gfx::SurfaceFormat aFormat
,
1344 TextureType aTextureType
) {
1345 MonitorAutoLock
lock(mMonitor
);
1347 RefPtr
<RemoteTextureRecycleBin
> bin
;
1348 if (aOwnerId
.IsValid()) {
1349 if (auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
)) {
1350 bin
= owner
->mRecycleBin
;
1359 for (auto it
= bin
->mRecycledTextures
.begin();
1360 it
!= bin
->mRecycledTextures
.end(); it
++) {
1362 if (holder
.mTextureData
&&
1363 holder
.mTextureData
->GetTextureType() == aTextureType
&&
1364 holder
.mSize
== aSize
&& holder
.mFormat
== aFormat
) {
1365 UniquePtr
<TextureData
> texture
= std::move(holder
.mTextureData
);
1366 bin
->mRecycledTextures
.erase(it
);
1374 UniquePtr
<SharedResourceWrapper
> RemoteTextureMap::GetRecycledSharedTexture(
1375 const RemoteTextureOwnerId aOwnerId
, const base::ProcessId aForPid
,
1376 const RefPtr
<RemoteTextureRecycleBin
>& aRecycleBin
,
1377 const gfx::IntSize
& aSize
, const gfx::SurfaceFormat aFormat
,
1378 SurfaceDescriptor::Type aType
) {
1379 MonitorAutoLock
lock(mMonitor
);
1381 RefPtr
<RemoteTextureRecycleBin
> bin
;
1382 if (aOwnerId
.IsValid()) {
1383 if (auto* owner
= GetTextureOwner(lock
, aOwnerId
, aForPid
)) {
1384 bin
= owner
->mRecycleBin
;
1393 for (auto it
= bin
->mRecycledTextures
.begin();
1394 it
!= bin
->mRecycledTextures
.end(); it
++) {
1396 if (holder
.mType
== aType
&& holder
.mSize
== aSize
&&
1397 holder
.mFormat
== aFormat
) {
1398 UniquePtr
<SharedResourceWrapper
> wrapper
=
1399 std::move(holder
.mResourceWrapper
);
1400 bin
->mRecycledTextures
.erase(it
);
1408 RemoteTextureMap::TextureOwner
* RemoteTextureMap::GetTextureOwner(
1409 const MonitorAutoLock
& aProofOfLock
, const RemoteTextureOwnerId aOwnerId
,
1410 const base::ProcessId aForPid
) {
1411 const auto key
= std::pair(aForPid
, aOwnerId
);
1412 auto it
= mTextureOwners
.find(key
);
1413 if (it
== mTextureOwners
.end()) {
1416 return it
->second
.get();
1419 RemoteTextureMap::TextureDataHolder::TextureDataHolder(
1420 const RemoteTextureId aTextureId
, RefPtr
<TextureHost
> aTextureHost
,
1421 UniquePtr
<TextureData
>&& aTextureData
,
1422 UniquePtr
<SharedResourceWrapper
>&& aResourceWrapper
)
1423 : mTextureId(aTextureId
),
1424 mTextureHost(aTextureHost
),
1425 mTextureData(std::move(aTextureData
)),
1426 mResourceWrapper(std::move(aResourceWrapper
)) {}
1428 RemoteTextureMap::RenderingReadyCallbackHolder::RenderingReadyCallbackHolder(
1429 const RemoteTextureId aTextureId
,
1430 std::function
<void(const RemoteTextureInfo
&)>&& aCallback
)
1431 : mTextureId(aTextureId
), mCallback(aCallback
) {}
1433 RemoteTextureMap::RemoteTextureHostWrapperHolder::
1434 RemoteTextureHostWrapperHolder(
1435 RefPtr
<TextureHost
> aRemoteTextureHostWrapper
)
1436 : mRemoteTextureHostWrapper(aRemoteTextureHostWrapper
) {}
1438 } // namespace mozilla::layers