Bug 1849470 - Update in-tree zlib to version 1.3. r=aosmond
[gecko.git] / gfx / layers / RemoteTextureMap.cpp
blobf1448efcfc4e35d52b359f843530a9dae04886c2
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"
9 #include <vector>
11 #include "CompositableHost.h"
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/layers/AsyncImagePipelineManager.h"
14 #include "mozilla/layers/BufferTexture.h"
15 #include "mozilla/layers/CompositorThread.h"
16 #include "mozilla/layers/ImageDataSerializer.h"
17 #include "mozilla/layers/RemoteTextureHostWrapper.h"
18 #include "mozilla/layers/WebRenderTextureHost.h"
19 #include "mozilla/StaticPrefs_webgl.h"
20 #include "mozilla/webrender/RenderThread.h"
21 #include "SharedSurface.h"
23 namespace mozilla::layers {
25 RemoteTextureOwnerClient::RemoteTextureOwnerClient(
26 const base::ProcessId aForPid)
27 : mForPid(aForPid) {}
29 RemoteTextureOwnerClient::~RemoteTextureOwnerClient() = default;
31 bool RemoteTextureOwnerClient::IsRegistered(
32 const RemoteTextureOwnerId aOwnerId) {
33 auto it = mOwnerIds.find(aOwnerId);
34 if (it == mOwnerIds.end()) {
35 return false;
37 return true;
40 void RemoteTextureOwnerClient::RegisterTextureOwner(
41 const RemoteTextureOwnerId aOwnerId, bool aIsSyncMode) {
42 MOZ_ASSERT(mOwnerIds.find(aOwnerId) == mOwnerIds.end());
43 mOwnerIds.emplace(aOwnerId);
44 RemoteTextureMap::Get()->RegisterTextureOwner(aOwnerId, mForPid, aIsSyncMode);
47 void RemoteTextureOwnerClient::UnregisterTextureOwner(
48 const RemoteTextureOwnerId aOwnerId) {
49 auto it = mOwnerIds.find(aOwnerId);
50 if (it == mOwnerIds.end()) {
51 return;
53 mOwnerIds.erase(it);
54 RemoteTextureMap::Get()->UnregisterTextureOwner(aOwnerId, mForPid);
57 void RemoteTextureOwnerClient::UnregisterAllTextureOwners() {
58 if (mOwnerIds.empty()) {
59 return;
61 RemoteTextureMap::Get()->UnregisterTextureOwners(mOwnerIds, mForPid);
62 mOwnerIds.clear();
65 void RemoteTextureOwnerClient::NotifyContextLost() {
66 if (mOwnerIds.empty()) {
67 return;
69 RemoteTextureMap::Get()->NotifyContextLost(mOwnerIds, mForPid);
72 void RemoteTextureOwnerClient::PushTexture(
73 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
74 UniquePtr<TextureData>&& aTextureData,
75 const std::shared_ptr<gl::SharedSurface>& aSharedSurface) {
76 MOZ_ASSERT(IsRegistered(aOwnerId));
78 RefPtr<TextureHost> textureHost = RemoteTextureMap::CreateRemoteTexture(
79 aTextureData.get(), TextureFlags::DEFAULT);
80 if (!textureHost) {
81 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
82 return;
85 RemoteTextureMap::Get()->PushTexture(aTextureId, aOwnerId, mForPid,
86 std::move(aTextureData), textureHost,
87 aSharedSurface);
90 void RemoteTextureOwnerClient::PushDummyTexture(
91 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId) {
92 MOZ_ASSERT(IsRegistered(aOwnerId));
94 auto flags = TextureFlags::DEALLOCATE_CLIENT | TextureFlags::REMOTE_TEXTURE |
95 TextureFlags::DUMMY_TEXTURE;
96 auto* rawData = BufferTextureData::Create(
97 gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8A8, gfx::BackendType::SKIA,
98 LayersBackend::LAYERS_WR, flags, ALLOC_DEFAULT, nullptr);
99 if (!rawData) {
100 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
101 return;
104 auto textureData = UniquePtr<TextureData>(rawData);
106 RefPtr<TextureHost> textureHost = RemoteTextureMap::CreateRemoteTexture(
107 textureData.get(), TextureFlags::DUMMY_TEXTURE);
108 if (!textureHost) {
109 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
110 return;
113 RemoteTextureMap::Get()->PushTexture(aTextureId, aOwnerId, mForPid,
114 std::move(textureData), textureHost,
115 /* aSharedSurface */ nullptr);
118 void RemoteTextureOwnerClient::GetLatestBufferSnapshot(
119 const RemoteTextureOwnerId aOwnerId, const mozilla::ipc::Shmem& aDestShmem,
120 const gfx::IntSize& aSize) {
121 MOZ_ASSERT(IsRegistered(aOwnerId));
122 RemoteTextureMap::Get()->GetLatestBufferSnapshot(aOwnerId, mForPid,
123 aDestShmem, aSize);
126 UniquePtr<TextureData>
127 RemoteTextureOwnerClient::CreateOrRecycleBufferTextureData(
128 const RemoteTextureOwnerId aOwnerId, gfx::IntSize aSize,
129 gfx::SurfaceFormat aFormat) {
130 auto texture = RemoteTextureMap::Get()->GetRecycledBufferTextureData(
131 aOwnerId, mForPid, aSize, aFormat);
132 if (texture) {
133 return texture;
136 auto flags = TextureFlags::DEALLOCATE_CLIENT | TextureFlags::REMOTE_TEXTURE;
137 auto* data = BufferTextureData::Create(aSize, aFormat, gfx::BackendType::SKIA,
138 LayersBackend::LAYERS_WR, flags,
139 ALLOC_DEFAULT, nullptr);
140 return UniquePtr<TextureData>(data);
143 std::shared_ptr<gl::SharedSurface>
144 RemoteTextureOwnerClient::GetRecycledSharedSurface(
145 const RemoteTextureOwnerId aOwnerId) {
146 return RemoteTextureMap::Get()->RemoteTextureMap::GetRecycledSharedSurface(
147 aOwnerId, mForPid);
150 StaticAutoPtr<RemoteTextureMap> RemoteTextureMap::sInstance;
152 /* static */
153 void RemoteTextureMap::Init() {
154 MOZ_ASSERT(!sInstance);
155 sInstance = new RemoteTextureMap();
158 /* static */
159 void RemoteTextureMap::Shutdown() {
160 if (sInstance) {
161 sInstance = nullptr;
165 RemoteTextureMap::RemoteTextureMap() : mMonitor("D3D11TextureMap::mMonitor") {}
167 RemoteTextureMap::~RemoteTextureMap() = default;
169 void RemoteTextureMap::PushTexture(
170 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
171 const base::ProcessId aForPid, UniquePtr<TextureData>&& aTextureData,
172 RefPtr<TextureHost>& aTextureHost,
173 const std::shared_ptr<gl::SharedSurface>& aSharedSurface) {
174 MOZ_RELEASE_ASSERT(aTextureHost);
176 std::vector<std::function<void(const RemoteTextureInfo&)>>
177 renderingReadyCallbacks; // Call outside the monitor
179 MonitorAutoLock lock(mMonitor);
181 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
182 if (!owner) {
183 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
184 return;
187 if (owner->mIsContextLost &&
188 !(aTextureHost->GetFlags() & TextureFlags::DUMMY_TEXTURE)) {
189 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
190 gfxCriticalNoteOnce << "Texture pushed during context lost";
193 const auto key = std::pair(aForPid, aOwnerId);
194 auto it = mRemoteTexturePushListeners.find(key);
195 // Notify a new texture if callback is requested
196 if (it != mRemoteTexturePushListeners.end()) {
197 RefPtr<CompositableHost> compositableHost = it->second;
198 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
199 "RemoteTextureMap::PushTexture::Runnable",
200 [compositableHost, aTextureId, aOwnerId, aForPid]() {
201 compositableHost->NotifyPushTexture(aTextureId, aOwnerId, aForPid);
203 CompositorThread()->Dispatch(runnable.forget());
206 auto textureData = MakeUnique<TextureDataHolder>(
207 aTextureId, aTextureHost, std::move(aTextureData), aSharedSurface);
209 MOZ_ASSERT(owner->mLatestTextureId < aTextureId);
211 owner->mWaitingTextureDataHolders.push_back(std::move(textureData));
213 if (!owner->mIsSyncMode) {
214 renderingReadyCallbacks =
215 GetRenderingReadyCallbacks(lock, owner, aTextureId);
216 // Update mAsyncRemoteTextureHost for async mode.
217 // This happens when PushTexture() with RemoteTextureId is called after
218 // GetRemoteTextureForDisplayList() with the RemoteTextureId.
219 const auto key = std::pair(aForPid, aTextureId);
220 auto it = mRemoteTextureHostWrapperHolders.find(key);
221 if (it != mRemoteTextureHostWrapperHolders.end()) {
222 MOZ_ASSERT(!it->second->mAsyncRemoteTextureHost);
223 it->second->mAsyncRemoteTextureHost = aTextureHost;
227 mMonitor.Notify();
229 // Release owner->mReleasingRenderedTextureHosts before checking
230 // NumCompositableRefs()
231 if (!owner->mReleasingRenderedTextureHosts.empty()) {
232 owner->mReleasingRenderedTextureHosts.clear();
235 // Drop obsoleted remote textures.
236 while (!owner->mUsingTextureDataHolders.empty()) {
237 auto& front = owner->mUsingTextureDataHolders.front();
238 // When compositable ref of TextureHost becomes 0, the TextureHost is not
239 // used by WebRender anymore.
240 if (front->mTextureHost &&
241 front->mTextureHost->NumCompositableRefs() == 0) {
242 // Recycle gl::SharedSurface
243 if (front->mSharedSurface) {
244 owner->mRecycledSharedSurfaces.push(front->mSharedSurface);
245 front->mSharedSurface = nullptr;
247 // Recycle BufferTextureData
248 if (!(front->mTextureHost->GetFlags() & TextureFlags::DUMMY_TEXTURE) &&
249 (front->mTextureData &&
250 front->mTextureData->AsBufferTextureData())) {
251 owner->mRecycledTextures.push(std::move(front->mTextureData));
253 owner->mUsingTextureDataHolders.pop_front();
254 } else if (front->mTextureHost &&
255 front->mTextureHost->NumCompositableRefs() >= 0) {
256 // Remote texture is still in use by WebRender.
257 break;
258 } else {
259 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
260 owner->mUsingTextureDataHolders.pop_front();
265 const auto info = RemoteTextureInfo(aTextureId, aOwnerId, aForPid);
266 for (auto& callback : renderingReadyCallbacks) {
267 callback(info);
271 void RemoteTextureMap::GetLatestBufferSnapshot(
272 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
273 const mozilla::ipc::Shmem& aDestShmem, const gfx::IntSize& aSize) {
274 // The compositable ref of remote texture should be updated in mMonitor lock.
275 CompositableTextureHostRef textureHostRef;
276 RefPtr<TextureHost> releasingTexture; // Release outside the monitor
278 MonitorAutoLock lock(mMonitor);
280 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
281 if (!owner) {
282 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
283 return;
286 // Get latest TextureHost of remote Texture.
287 if (owner->mWaitingTextureDataHolders.empty() &&
288 !owner->mLatestTextureHost) {
289 return;
291 TextureHost* textureHost =
292 !owner->mWaitingTextureDataHolders.empty()
293 ? owner->mWaitingTextureDataHolders.back()->mTextureHost
294 : owner->mLatestTextureHost;
295 if (!textureHost->AsBufferTextureHost()) {
296 // Only BufferTextureHost is supported for now.
297 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
298 return;
300 if (textureHost->GetSize() != aSize) {
301 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
302 return;
304 if (textureHost->GetFormat() != gfx::SurfaceFormat::R8G8B8A8 &&
305 textureHost->GetFormat() != gfx::SurfaceFormat::B8G8R8A8) {
306 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
307 return;
309 // Increment compositable ref to prevent that TextureHost is removed during
310 // memcpy.
311 textureHostRef = textureHost;
314 if (!textureHostRef) {
315 return;
318 auto* bufferTextureHost = textureHostRef->AsBufferTextureHost();
319 if (bufferTextureHost) {
320 uint32_t stride = ImageDataSerializer::ComputeRGBStride(
321 bufferTextureHost->GetFormat(), aSize.width);
322 uint32_t bufferSize = stride * aSize.height;
323 uint8_t* dst = aDestShmem.get<uint8_t>();
324 uint8_t* src = bufferTextureHost->GetBuffer();
326 MOZ_ASSERT(bufferSize <= aDestShmem.Size<uint8_t>());
327 memcpy(dst, src, bufferSize);
331 MonitorAutoLock lock(mMonitor);
332 // Release compositable ref in mMonitor lock, but release RefPtr outside the
333 // monitor
334 releasingTexture = textureHostRef;
335 textureHostRef = nullptr;
339 void RemoteTextureMap::RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
340 const base::ProcessId aForPid,
341 bool aIsSyncMode) {
342 MonitorAutoLock lock(mMonitor);
344 const auto key = std::pair(aForPid, aOwnerId);
345 auto it = mTextureOwners.find(key);
346 if (it != mTextureOwners.end()) {
347 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
348 return;
350 auto owner = MakeUnique<TextureOwner>();
351 owner->mIsSyncMode = aIsSyncMode;
353 mTextureOwners.emplace(key, std::move(owner));
356 void RemoteTextureMap::KeepTextureDataAliveForTextureHostIfNecessary(
357 const MonitorAutoLock& aProofOfLock,
358 std::deque<UniquePtr<TextureDataHolder>>& aHolders) {
359 for (auto& holder : aHolders) {
360 // If remote texture of TextureHost still exist, keep
361 // gl::SharedSurface/TextureData alive while the TextureHost is alive.
362 if (holder->mTextureHost &&
363 holder->mTextureHost->NumCompositableRefs() >= 0) {
364 RefPtr<nsISerialEventTarget> eventTarget =
365 MessageLoop::current()->SerialEventTarget();
366 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
367 "RemoteTextureMap::UnregisterTextureOwner::Runnable",
368 [data = std::move(holder->mTextureData),
369 surface = std::move(holder->mSharedSurface)]() {});
371 auto destroyedCallback = [eventTarget = std::move(eventTarget),
372 runnable = std::move(runnable)]() mutable {
373 eventTarget->Dispatch(runnable.forget());
376 holder->mTextureHost->SetDestroyedCallback(destroyedCallback);
381 void RemoteTextureMap::UnregisterTextureOwner(
382 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid) {
383 UniquePtr<TextureOwner> releasingOwner; // Release outside the monitor
384 RefPtr<TextureHost> releasingTexture; // Release outside the monitor
385 std::vector<std::function<void(const RemoteTextureInfo&)>>
386 renderingReadyCallbacks; // Call outside the monitor
388 MonitorAutoLock lock(mMonitor);
390 const auto key = std::pair(aForPid, aOwnerId);
391 auto it = mTextureOwners.find(key);
392 if (it == mTextureOwners.end()) {
393 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
394 return;
397 if (it->second->mLatestTextureHost) {
398 // Release CompositableRef in mMonitor
399 releasingTexture = it->second->mLatestTextureHost;
400 it->second->mLatestTextureHost = nullptr;
403 // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could
404 // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts in
405 // mUsingTextureDataHolders alive. They need to be cleared before
406 // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses
407 // NumCompositableRefs().
408 if (!it->second->mReleasingRenderedTextureHosts.empty()) {
409 it->second->mReleasingRenderedTextureHosts.clear();
411 if (it->second->mLatestRenderedTextureHost) {
412 it->second->mLatestRenderedTextureHost = nullptr;
415 renderingReadyCallbacks =
416 GetAllRenderingReadyCallbacks(lock, it->second.get());
418 KeepTextureDataAliveForTextureHostIfNecessary(
419 lock, it->second->mWaitingTextureDataHolders);
421 KeepTextureDataAliveForTextureHostIfNecessary(
422 lock, it->second->mUsingTextureDataHolders);
424 releasingOwner = std::move(it->second);
425 mTextureOwners.erase(it);
427 mMonitor.Notify();
430 const auto info =
431 RemoteTextureInfo(RemoteTextureId{0}, RemoteTextureOwnerId{0}, 0);
432 for (auto& callback : renderingReadyCallbacks) {
433 callback(info);
437 void RemoteTextureMap::UnregisterTextureOwners(
438 const std::unordered_set<RemoteTextureOwnerId,
439 RemoteTextureOwnerId::HashFn>& aOwnerIds,
440 const base::ProcessId aForPid) {
441 std::vector<UniquePtr<TextureOwner>>
442 releasingOwners; // Release outside the monitor
443 std::vector<RefPtr<TextureHost>>
444 releasingTextures; // Release outside the monitor
445 std::vector<std::function<void(const RemoteTextureInfo&)>>
446 renderingReadyCallbacks; // Call outside the monitor
448 MonitorAutoLock lock(mMonitor);
450 for (auto id : aOwnerIds) {
451 const auto key = std::pair(aForPid, id);
452 auto it = mTextureOwners.find(key);
453 if (it == mTextureOwners.end()) {
454 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
455 continue;
458 if (it->second->mLatestTextureHost) {
459 // Release CompositableRef in mMonitor
460 releasingTextures.emplace_back(it->second->mLatestTextureHost);
461 it->second->mLatestTextureHost = nullptr;
464 // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could
465 // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts
466 // in mUsingTextureDataHolders alive. They need to be cleared before
467 // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses
468 // NumCompositableRefs().
469 if (!it->second->mReleasingRenderedTextureHosts.empty()) {
470 it->second->mReleasingRenderedTextureHosts.clear();
472 if (it->second->mLatestRenderedTextureHost) {
473 it->second->mLatestRenderedTextureHost = nullptr;
476 renderingReadyCallbacks =
477 GetAllRenderingReadyCallbacks(lock, it->second.get());
479 KeepTextureDataAliveForTextureHostIfNecessary(
480 lock, it->second->mWaitingTextureDataHolders);
482 KeepTextureDataAliveForTextureHostIfNecessary(
483 lock, it->second->mUsingTextureDataHolders);
485 releasingOwners.push_back(std::move(it->second));
486 mTextureOwners.erase(it);
489 mMonitor.Notify();
492 const auto info =
493 RemoteTextureInfo(RemoteTextureId{0}, RemoteTextureOwnerId{0}, 0);
494 for (auto& callback : renderingReadyCallbacks) {
495 callback(info);
499 void RemoteTextureMap::NotifyContextLost(
500 const std::unordered_set<RemoteTextureOwnerId,
501 RemoteTextureOwnerId::HashFn>& aOwnerIds,
502 const base::ProcessId aForPid) {
503 MonitorAutoLock lock(mMonitor);
505 for (auto id : aOwnerIds) {
506 const auto key = std::pair(aForPid, id);
507 auto it = mTextureOwners.find(key);
508 if (it == mTextureOwners.end()) {
509 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
510 continue;
512 it->second->mIsContextLost = true;
514 mMonitor.Notify();
517 /* static */
518 RefPtr<TextureHost> RemoteTextureMap::CreateRemoteTexture(
519 TextureData* aTextureData, TextureFlags aTextureFlags) {
520 SurfaceDescriptor desc;
521 DebugOnly<bool> ret = aTextureData->Serialize(desc);
522 MOZ_ASSERT(ret);
523 TextureFlags flags = aTextureFlags | TextureFlags::REMOTE_TEXTURE |
524 TextureFlags::DEALLOCATE_CLIENT;
526 Maybe<wr::ExternalImageId> externalImageId = Nothing();
527 RefPtr<TextureHost> textureHost =
528 TextureHost::Create(desc, null_t(), nullptr, LayersBackend::LAYERS_WR,
529 flags, externalImageId);
530 MOZ_ASSERT(textureHost);
531 if (!textureHost) {
532 gfxCriticalNoteOnce << "Failed to create remote texture";
533 return nullptr;
536 textureHost->EnsureRenderTexture(Nothing());
538 return textureHost;
541 void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
542 RemoteTextureMap::TextureOwner* aOwner,
543 const RemoteTextureId aTextureId) {
544 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
545 MOZ_ASSERT(aOwner);
546 MOZ_ASSERT(aTextureId >= aOwner->mLatestTextureId);
548 if (aTextureId == aOwner->mLatestTextureId) {
549 // No need to update texture.
550 return;
553 // Move remote textures to mUsingTextureDataHolders.
554 while (!aOwner->mWaitingTextureDataHolders.empty()) {
555 auto& front = aOwner->mWaitingTextureDataHolders.front();
556 if (aTextureId < front->mTextureId) {
557 break;
559 MOZ_RELEASE_ASSERT(front->mTextureHost);
560 aOwner->mLatestTextureHost = front->mTextureHost;
561 aOwner->mLatestTextureId = front->mTextureId;
563 UniquePtr<TextureDataHolder> holder = std::move(front);
564 aOwner->mWaitingTextureDataHolders.pop_front();
565 aOwner->mUsingTextureDataHolders.push_back(std::move(holder));
569 std::vector<std::function<void(const RemoteTextureInfo&)>>
570 RemoteTextureMap::GetRenderingReadyCallbacks(
571 const MonitorAutoLock& aProofOfLock, RemoteTextureMap::TextureOwner* aOwner,
572 const RemoteTextureId aTextureId) {
573 MOZ_ASSERT(aOwner);
575 std::vector<std::function<void(const RemoteTextureInfo&)>> functions;
577 while (!aOwner->mRenderingReadyCallbackHolders.empty()) {
578 auto& front = aOwner->mRenderingReadyCallbackHolders.front();
579 if (aTextureId < front->mTextureId) {
580 break;
582 if (front->mCallback) {
583 functions.push_back(std::move(front->mCallback));
585 aOwner->mRenderingReadyCallbackHolders.pop_front();
588 return functions;
591 std::vector<std::function<void(const RemoteTextureInfo&)>>
592 RemoteTextureMap::GetAllRenderingReadyCallbacks(
593 const MonitorAutoLock& aProofOfLock,
594 RemoteTextureMap::TextureOwner* aOwner) {
595 auto functions =
596 GetRenderingReadyCallbacks(aProofOfLock, aOwner, RemoteTextureId::Max());
597 MOZ_ASSERT(aOwner->mRenderingReadyCallbackHolders.empty());
599 return functions;
602 bool RemoteTextureMap::GetRemoteTextureForDisplayList(
603 RemoteTextureHostWrapper* aTextureHostWrapper,
604 std::function<void(const RemoteTextureInfo&)>&& aReadyCallback) {
605 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
606 MOZ_ASSERT(aTextureHostWrapper);
608 if (aTextureHostWrapper->IsReadyForRendering()) {
609 return false;
612 const auto& textureId = aTextureHostWrapper->mTextureId;
613 const auto& ownerId = aTextureHostWrapper->mOwnerId;
614 const auto& forPid = aTextureHostWrapper->mForPid;
615 const auto& size = aTextureHostWrapper->mSize;
617 RefPtr<TextureHost> textureHost;
619 MonitorAutoLock lock(mMonitor);
621 auto* owner = GetTextureOwner(lock, ownerId, forPid);
622 if (!owner) {
623 return false;
626 UpdateTexture(lock, owner, textureId);
628 if (owner->mLatestTextureHost &&
629 (owner->mLatestTextureHost->GetFlags() & TextureFlags::DUMMY_TEXTURE)) {
630 // Remote texture allocation was failed.
631 return false;
634 bool syncMode = owner->mIsSyncMode || bool(aReadyCallback);
636 if (syncMode) {
637 // remote texture sync ipc
638 if (textureId == owner->mLatestTextureId) {
639 MOZ_ASSERT(owner->mLatestTextureHost);
640 MOZ_ASSERT(owner->mLatestTextureHost->GetSize() == size);
641 if (owner->mLatestTextureHost->GetSize() != size) {
642 gfxCriticalNoteOnce << "unexpected remote texture size: "
643 << owner->mLatestTextureHost->GetSize()
644 << " expected: " << size;
646 textureHost = owner->mLatestTextureHost;
647 } else {
648 if (aReadyCallback) {
649 auto callbackHolder = MakeUnique<RenderingReadyCallbackHolder>(
650 textureId, std::move(aReadyCallback));
651 owner->mRenderingReadyCallbackHolders.push_back(
652 std::move(callbackHolder));
653 return true;
654 } else {
655 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
658 } else {
659 // remote texture async ipc
660 if (owner->mLatestTextureHost) {
661 if (owner->mLatestTextureHost->GetSize() == size) {
662 textureHost = owner->mLatestTextureHost;
663 } else {
664 gfxCriticalNoteOnce << "unexpected remote texture size: "
665 << owner->mLatestTextureHost->GetSize()
666 << " expected: " << size;
667 if (!owner->mIsContextLost) {
668 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
671 } else {
672 gfxCriticalNoteOnce << "remote texture does not exist";
673 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
676 // Update mAsyncRemoteTextureHost for async mode
677 if (textureId == owner->mLatestTextureId) {
678 const auto key = std::pair(forPid, textureId);
679 auto it = mRemoteTextureHostWrapperHolders.find(key);
680 if (it != mRemoteTextureHostWrapperHolders.end() &&
681 !it->second->mAsyncRemoteTextureHost) {
682 it->second->mAsyncRemoteTextureHost = owner->mLatestTextureHost;
683 } else {
684 MOZ_ASSERT(it->second->mAsyncRemoteTextureHost ==
685 owner->mLatestTextureHost);
690 if (textureHost) {
691 aTextureHostWrapper->SetRemoteTextureHostForDisplayList(lock, textureHost,
692 syncMode);
693 aTextureHostWrapper->ApplyTextureFlagsToRemoteTexture();
697 return false;
700 wr::MaybeExternalImageId RemoteTextureMap::GetExternalImageIdOfRemoteTexture(
701 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
702 const base::ProcessId aForPid) {
703 MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
704 MonitorAutoLock lock(mMonitor);
706 const auto key = std::pair(aForPid, aTextureId);
707 auto it = mRemoteTextureHostWrapperHolders.find(key);
708 if (it == mRemoteTextureHostWrapperHolders.end()) {
709 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
710 return Nothing();
713 TextureHost* remoteTexture = it->second->mAsyncRemoteTextureHost;
715 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
716 if (!owner) {
717 if (!remoteTexture) {
718 // This could happen with IPC abnormal shutdown
719 return Nothing();
721 return remoteTexture->GetMaybeExternalImageId();
724 if (remoteTexture &&
725 remoteTexture->GetFlags() & TextureFlags::DUMMY_TEXTURE) {
726 // Remote texture allocation was failed.
727 return Nothing();
729 MOZ_ASSERT(!(remoteTexture &&
730 remoteTexture->GetFlags() & TextureFlags::DUMMY_TEXTURE));
732 MOZ_ASSERT(owner);
734 if (!remoteTexture) {
735 // Use mLatestRenderedTextureHost for rendering. Remote texture of
736 // aTextureId does not exist.
737 remoteTexture = owner->mLatestRenderedTextureHost;
738 if (!it->second->mReadyCheckSuppressed && !owner->mIsContextLost) {
739 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
740 gfxCriticalNoteOnce << "remote texture for rendering does not exist id:"
741 << uint64_t(aTextureId);
743 } else {
744 // Update mLatestRenderedTextureHost
745 if (owner->mLatestRenderedTextureHost) {
746 owner->mReleasingRenderedTextureHosts.push_back(
747 owner->mLatestRenderedTextureHost);
748 owner->mLatestRenderedTextureHost = nullptr;
750 owner->mLatestRenderedTextureHost = remoteTexture;
753 if (!remoteTexture) {
754 return Nothing();
757 return remoteTexture->GetMaybeExternalImageId();
760 void RemoteTextureMap::ReleaseRemoteTextureHostForDisplayList(
761 RemoteTextureHostWrapper* aTextureHostWrapper) {
762 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
763 MOZ_ASSERT(aTextureHostWrapper);
765 RefPtr<TextureHost> releasingTexture; // Release outside the mutex
767 MonitorAutoLock lock(mMonitor);
768 releasingTexture =
769 aTextureHostWrapper->GetRemoteTextureHostForDisplayList(lock);
770 aTextureHostWrapper->ClearRemoteTextureHostForDisplayList(lock);
774 RefPtr<TextureHost> RemoteTextureMap::GetOrCreateRemoteTextureHostWrapper(
775 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
776 const base::ProcessId aForPid, const gfx::IntSize aSize,
777 const TextureFlags aFlags) {
778 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
779 MonitorAutoLock lock(mMonitor);
781 const auto key = std::pair(aForPid, aTextureId);
782 auto it = mRemoteTextureHostWrapperHolders.find(key);
783 if (it != mRemoteTextureHostWrapperHolders.end()) {
784 return it->second->mRemoteTextureHostWrapper;
787 auto wrapper = RemoteTextureHostWrapper::Create(aTextureId, aOwnerId, aForPid,
788 aSize, aFlags);
789 auto wrapperHolder = MakeUnique<RemoteTextureHostWrapperHolder>(wrapper);
791 mRemoteTextureHostWrapperHolders.emplace(key, std::move(wrapperHolder));
793 return wrapper;
796 void RemoteTextureMap::UnregisterRemoteTextureHostWrapper(
797 const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
798 const base::ProcessId aForPid) {
799 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
801 std::vector<RefPtr<TextureHost>>
802 releasingTextures; // Release outside the monitor
804 MonitorAutoLock lock(mMonitor);
806 const auto key = std::pair(aForPid, aTextureId);
807 auto it = mRemoteTextureHostWrapperHolders.find(key);
808 if (it == mRemoteTextureHostWrapperHolders.end()) {
809 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
810 return;
812 releasingTextures.emplace_back(it->second->mRemoteTextureHostWrapper);
813 if (it->second->mAsyncRemoteTextureHost) {
814 releasingTextures.emplace_back(it->second->mAsyncRemoteTextureHost);
817 mRemoteTextureHostWrapperHolders.erase(it);
818 mMonitor.Notify();
822 void RemoteTextureMap::RegisterRemoteTexturePushListener(
823 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
824 CompositableHost* aListener) {
825 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
827 RefPtr<CompositableHost>
828 releasingCompositableHost; // Release outside the monitor
830 MonitorAutoLock lock(mMonitor);
832 const auto key = std::pair(aForPid, aOwnerId);
833 auto it = mRemoteTexturePushListeners.find(key);
834 // Remove obsoleted CompositableHost.
835 if (it != mRemoteTexturePushListeners.end()) {
836 releasingCompositableHost = std::move(it->second);
837 mRemoteTexturePushListeners.erase(it);
839 mRemoteTexturePushListeners.emplace(key, aListener);
841 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
842 if (!owner) {
843 return;
845 if (owner->mWaitingTextureDataHolders.empty() &&
846 !owner->mLatestTextureHost) {
847 return;
850 // Get latest RemoteTextureId.
851 auto textureId = !owner->mWaitingTextureDataHolders.empty()
852 ? owner->mWaitingTextureDataHolders.back()->mTextureId
853 : owner->mLatestTextureId;
855 // Notify the RemoteTextureId to callback
856 RefPtr<CompositableHost> compositableHost = aListener;
857 RefPtr<Runnable> runnable = NS_NewRunnableFunction(
858 "RemoteTextureMap::RegisterRemoteTexturePushListener::Runnable",
859 [compositableHost, textureId, aOwnerId, aForPid]() {
860 compositableHost->NotifyPushTexture(textureId, aOwnerId, aForPid);
862 CompositorThread()->Dispatch(runnable.forget());
866 void RemoteTextureMap::UnregisterRemoteTexturePushListener(
867 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
868 CompositableHost* aListener) {
869 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
871 RefPtr<CompositableHost>
872 releasingCompositableHost; // Release outside the monitor
874 MonitorAutoLock lock(mMonitor);
876 const auto key = std::pair(aForPid, aOwnerId);
877 auto it = mRemoteTexturePushListeners.find(key);
878 if (it == mRemoteTexturePushListeners.end()) {
879 return;
881 if (aListener != it->second) {
882 // aListener was alredy obsoleted.
883 return;
885 releasingCompositableHost = std::move(it->second);
886 mRemoteTexturePushListeners.erase(it);
890 bool RemoteTextureMap::CheckRemoteTextureReady(
891 const RemoteTextureInfo& aInfo,
892 std::function<void(const RemoteTextureInfo&)>&& aCallback) {
893 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
895 MonitorAutoLock lock(mMonitor);
897 auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
898 if (!owner || owner->mIsContextLost) {
899 // Owner is already removed or context lost.
900 return false;
903 const auto key = std::pair(aInfo.mForPid, aInfo.mTextureId);
904 auto it = mRemoteTextureHostWrapperHolders.find(key);
905 if (it == mRemoteTextureHostWrapperHolders.end()) {
906 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
907 gfxCriticalNoteOnce << "Remote texture does not exist id:"
908 << uint64_t(aInfo.mTextureId);
909 return true;
912 if (it->second->mAsyncRemoteTextureHost) {
913 return true;
915 MOZ_ASSERT(!it->second->mAsyncRemoteTextureHost);
917 // Check if RemoteTextureId is as expected.
918 if (!owner->mRenderingReadyCallbackHolders.empty()) {
919 auto& front = owner->mRenderingReadyCallbackHolders.front();
920 MOZ_RELEASE_ASSERT(aInfo.mTextureId >= front->mTextureId);
923 auto callbackHolder = MakeUnique<RenderingReadyCallbackHolder>(
924 aInfo.mTextureId, std::move(aCallback));
925 owner->mRenderingReadyCallbackHolders.push_back(std::move(callbackHolder));
927 return false;
930 bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) {
931 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
933 MonitorAutoLock lock(mMonitor);
935 auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
936 if (!owner || owner->mIsContextLost) {
937 // Owner is already removed or context lost.
938 return false;
941 const auto key = std::pair(aInfo.mForPid, aInfo.mTextureId);
942 auto it = mRemoteTextureHostWrapperHolders.find(key);
943 if (it == mRemoteTextureHostWrapperHolders.end()) {
944 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
945 gfxCriticalNoteOnce << "Remote texture does not exist id:"
946 << uint64_t(aInfo.mTextureId);
947 return false;
950 const TimeDuration timeout = TimeDuration::FromMilliseconds(1000);
951 TextureHost* remoteTexture = it->second->mAsyncRemoteTextureHost;
953 while (!remoteTexture) {
954 CVStatus status = mMonitor.Wait(timeout);
955 if (status == CVStatus::Timeout) {
956 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
957 gfxCriticalNoteOnce << "Remote texture wait time out id:"
958 << uint64_t(aInfo.mTextureId);
959 return false;
962 auto it = mRemoteTextureHostWrapperHolders.find(key);
963 if (it == mRemoteTextureHostWrapperHolders.end()) {
964 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
965 return false;
968 remoteTexture = it->second->mAsyncRemoteTextureHost;
969 if (!remoteTexture) {
970 auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid);
971 // When owner is alreay unregistered, remote texture will not be pushed.
972 if (!owner || owner->mIsContextLost) {
973 // This could happen with IPC abnormal shutdown
974 return false;
979 return true;
982 void RemoteTextureMap::SuppressRemoteTextureReadyCheck(
983 const RemoteTextureId aTextureId, const base::ProcessId aForPid) {
984 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
985 MonitorAutoLock lock(mMonitor);
987 const auto key = std::pair(aForPid, aTextureId);
988 auto it = mRemoteTextureHostWrapperHolders.find(key);
989 if (it == mRemoteTextureHostWrapperHolders.end()) {
990 MOZ_ASSERT_UNREACHABLE("unexpected to be called");
991 return;
993 it->second->mReadyCheckSuppressed = true;
996 UniquePtr<TextureData> RemoteTextureMap::GetRecycledBufferTextureData(
997 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
998 gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
999 std::stack<UniquePtr<TextureData>>
1000 releasingTextures; // Release outside the monitor
1001 UniquePtr<TextureData> texture;
1003 MonitorAutoLock lock(mMonitor);
1005 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
1006 if (!owner) {
1007 return nullptr;
1010 if (owner->mRecycledTextures.empty()) {
1011 return nullptr;
1014 if (!owner->mRecycledTextures.empty()) {
1015 auto& top = owner->mRecycledTextures.top();
1016 auto* bufferTexture = top->AsBufferTextureData();
1018 if (bufferTexture && bufferTexture->GetSize() == aSize &&
1019 bufferTexture->GetFormat() == aFormat) {
1020 texture = std::move(top);
1021 owner->mRecycledTextures.pop();
1022 } else {
1023 // If size or format are different, release all textures.
1024 owner->mRecycledTextures.swap(releasingTextures);
1028 return texture;
1031 std::shared_ptr<gl::SharedSurface> RemoteTextureMap::GetRecycledSharedSurface(
1032 const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid) {
1033 std::shared_ptr<gl::SharedSurface> sharedSurface;
1035 MonitorAutoLock lock(mMonitor);
1037 auto* owner = GetTextureOwner(lock, aOwnerId, aForPid);
1038 if (!owner) {
1039 return nullptr;
1042 if (owner->mRecycledSharedSurfaces.empty()) {
1043 return nullptr;
1046 if (!owner->mRecycledSharedSurfaces.empty()) {
1047 sharedSurface = owner->mRecycledSharedSurfaces.front();
1048 owner->mRecycledSharedSurfaces.pop();
1051 return sharedSurface;
1054 RemoteTextureMap::TextureOwner* RemoteTextureMap::GetTextureOwner(
1055 const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
1056 const base::ProcessId aForPid) {
1057 const auto key = std::pair(aForPid, aOwnerId);
1058 auto it = mTextureOwners.find(key);
1059 if (it == mTextureOwners.end()) {
1060 return nullptr;
1062 return it->second.get();
1065 RemoteTextureMap::TextureDataHolder::TextureDataHolder(
1066 const RemoteTextureId aTextureId, RefPtr<TextureHost> aTextureHost,
1067 UniquePtr<TextureData>&& aTextureData,
1068 const std::shared_ptr<gl::SharedSurface>& aSharedSurface)
1069 : mTextureId(aTextureId),
1070 mTextureHost(aTextureHost),
1071 mTextureData(std::move(aTextureData)),
1072 mSharedSurface(aSharedSurface) {}
1074 RemoteTextureMap::RenderingReadyCallbackHolder::RenderingReadyCallbackHolder(
1075 const RemoteTextureId aTextureId,
1076 std::function<void(const RemoteTextureInfo&)>&& aCallback)
1077 : mTextureId(aTextureId), mCallback(aCallback) {}
1079 RemoteTextureMap::RemoteTextureHostWrapperHolder::
1080 RemoteTextureHostWrapperHolder(
1081 RefPtr<TextureHost> aRemoteTextureHostWrapper)
1082 : mRemoteTextureHostWrapper(aRemoteTextureHostWrapper) {}
1084 } // namespace mozilla::layers