--- a/gfx/layers/TextureSourceProvider.cpp
+++ b/gfx/layers/TextureSourceProvider.cpp
@@ -15,37 +15,41 @@ namespace layers {
TextureSourceProvider::~TextureSourceProvider()
{
ReadUnlockTextures();
}
void
TextureSourceProvider::ReadUnlockTextures()
{
+#ifdef XP_DARWIN
nsClassHashtable<nsUint32HashKey, nsTArray<uint64_t>> texturesIdsToUnlockByPid;
for (auto& texture : mUnlockAfterComposition) {
auto bufferTexture = texture->AsBufferTextureHost();
if (bufferTexture && bufferTexture->IsDirectMap()) {
texture->ReadUnlock();
auto actor = texture->GetIPDLActor();
if (actor) {
base::ProcessId pid = actor->OtherPid();
nsTArray<uint64_t>* textureIds = texturesIdsToUnlockByPid.LookupOrAdd(pid);
textureIds->AppendElement(TextureHost::GetTextureSerial(actor));
}
} else {
texture->ReadUnlock();
}
}
- mUnlockAfterComposition.Clear();
-#ifdef XP_DARWIN
for (auto it = texturesIdsToUnlockByPid.ConstIter(); !it.Done(); it.Next()) {
TextureSync::SetTexturesUnlocked(it.Key(), *it.UserData());
}
+#else
+ for (auto& texture : mUnlockAfterComposition) {
+ texture->ReadUnlock();
+ }
#endif
+ mUnlockAfterComposition.Clear();
}
void
TextureSourceProvider::UnlockAfterComposition(TextureHost* aTexture)
{
mUnlockAfterComposition.AppendElement(aTexture);
}
--- a/gfx/layers/TextureSync.cpp
+++ b/gfx/layers/TextureSync.cpp
@@ -56,37 +56,44 @@ GetLockedTextureIdsForProcess(pid_t pid)
if (gProcessTextureIds.find(pid) == gProcessTextureIds.end()) {
gProcessTextureIds[pid] = std::unordered_set<uint64_t>();
}
return &gProcessTextureIds.at(pid);
}
bool
-WaitForTextureIdsToUnlock(pid_t pid, uint64_t* textureIds, uint32_t textureIdsLength)
+WaitForTextureIdsToUnlock(pid_t pid, const Span<const uint64_t>& textureIds)
{
{
StaticMonitorAutoLock lock(gTextureLockMonitor);
std::unordered_set<uint64_t>* freedTextureIds = GetLockedTextureIdsForProcess(pid);
+ TimeStamp start = TimeStamp::Now();
while (true) {
bool allCleared = true;
- for (uint32_t i = 0; i < textureIdsLength; ++i) {
- if (freedTextureIds->find(textureIds[i]) != freedTextureIds->end()) {
+ for (uint64_t textureId : textureIds) {
+ if (freedTextureIds->find(textureId) != freedTextureIds->end()) {
allCleared = false;
}
}
if (allCleared) {
return true;
}
if (lock.Wait(TimeDuration::FromMilliseconds(kTextureLockTimeout)) == CVStatus::Timeout) {
return false;
}
+
+ // In case the monitor gets signaled multiple times, each less than kTextureLockTimeout.
+ // This ensures that the total time we wait is < 2 * kTextureLockTimeout
+ if ((TimeStamp::Now() - start).ToMilliseconds() > (double)kTextureLockTimeout) {
+ return false;
+ }
}
}
}
void
CheckTexturesForUnlock()
{
for (auto& textureSourceProvider : gTextureSourceProviders) {
@@ -105,17 +112,17 @@ TextureSync::DispatchCheckTexturesForUnl
void
TextureSync::HandleWaitForTexturesMessage(MachReceiveMessage* rmsg, ipc::MemoryPorts* ports)
{
WaitForTexturesRequest* req = reinterpret_cast<WaitForTexturesRequest*>(rmsg->GetData());
uint64_t* textureIds = (uint64_t*)(req + 1);
uint32_t textureIdsLength = (rmsg->GetDataLength() - sizeof(WaitForTexturesRequest)) / sizeof(uint64_t);
- bool success = WaitForTextureIdsToUnlock(req->pid, textureIds, textureIdsLength);
+ bool success = WaitForTextureIdsToUnlock(req->pid, MakeSpan<uint64_t>(textureIds, textureIdsLength));
if (!success) {
LOG_ERROR("Waiting for textures to unlock failed.\n");
}
MachSendMessage msg(ipc::kReturnWaitForTexturesMsg);
WaitForTexturesReply replydata;
replydata.success = success;
@@ -124,20 +131,18 @@ TextureSync::HandleWaitForTexturesMessag
if (KERN_SUCCESS != err) {
LOG_ERROR("SendMessage failed 0x%x %s\n", err, mach_error_string(err));
}
}
void
TextureSync::RegisterTextureSourceProvider(TextureSourceProvider* textureSourceProvider)
{
- RefPtr<TextureSourceProvider> ref(textureSourceProvider);
- MOZ_RELEASE_ASSERT(!gTextureSourceProviders.Contains(ref));
-
- gTextureSourceProviders.AppendElement(ref.forget());
+ MOZ_RELEASE_ASSERT(!gTextureSourceProviders.Contains(textureSourceProvider));
+ gTextureSourceProviders.AppendElement(textureSourceProvider);
}
void
TextureSync::SetTexturesLocked(pid_t pid, const nsTArray<uint64_t>& textureIds)
{
StaticMonitorAutoLock mal(gTextureLockMonitor);
std::unordered_set<uint64_t>* lockedTextureIds = GetLockedTextureIdsForProcess(pid);
for (uint64_t textureId : textureIds) {
@@ -196,21 +201,17 @@ TextureSync::UpdateTextureLocks(base::Pr
smsg.SetData(&aProcessId, sizeof(aProcessId));
ipc::SharedMemoryBasic::SendMachMessage(aProcessId, smsg, NULL);
}
bool
TextureSync::WaitForTextures(base::ProcessId aProcessId, const nsTArray<uint64_t>& textureIds)
{
if (aProcessId == getpid()) {
- UniquePtr<uint64_t[]> reqTextureIds = MakeUnique<uint64_t[]>(textureIds.Length());
- for (uint32_t i = 0; i < textureIds.Length(); ++i) {
- reqTextureIds[i] = textureIds[i];
- }
- bool success = WaitForTextureIdsToUnlock(aProcessId, reqTextureIds.get(), textureIds.Length());
+ bool success = WaitForTextureIdsToUnlock(aProcessId, MakeSpan<uint64_t>(textureIds));
if (!success) {
LOG_ERROR("Failed waiting for textures to unlock.\n");
}
return success;
}
MachSendMessage smsg(ipc::kWaitForTexturesMsg);
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -312,16 +312,21 @@ ClientLayerManager::BeginTransaction()
return BeginTransactionWithTarget(nullptr);
}
bool
ClientLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags)
{
+ // This just causes the compositor to check whether the GPU is done with its
+ // textures or not and unlock them if it is. This helps us avoid the case
+ // where we take a long time painting asynchronously, turn IPC back on at
+ // the end of that, and then have to wait for the compositor to to get into
+ // TiledLayerBufferComposite::UseTiles before getting a response.
if (mForwarder) {
mForwarder->UpdateTextureLocks();
}
// Wait for any previous async paints to complete before starting to paint again.
// Do this outside the profiler and telemetry block so this doesn't count as time
// spent rasterizing.
{