blob: 00cf3de04d7ca49c53d3602cc3df6635c4cbd693 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gpu_fence_manager.h"
#include <memory>
#include "base/bind.h"
#include "base/logging.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gl/gl_fence.h"
namespace gpu {
namespace gles2 {
GpuFenceManager::GpuFenceEntry::GpuFenceEntry() = default;
GpuFenceManager::GpuFenceEntry::~GpuFenceEntry() = default;
GpuFenceManager::GpuFenceManager() = default;
GpuFenceManager::~GpuFenceManager() {
DCHECK(gpu_fence_entries_.empty());
}
bool GpuFenceManager::CreateGpuFence(uint32_t client_id) {
// This must be a new entry.
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it != gpu_fence_entries_.end())
return false;
auto entry = std::make_unique<GpuFenceEntry>();
entry->gl_fence_ = gl::GLFence::CreateForGpuFence();
if (!entry->gl_fence_)
return false;
std::pair<GpuFenceEntryMap::iterator, bool> result =
gpu_fence_entries_.emplace(client_id, std::move(entry));
DCHECK(result.second);
return true;
}
bool GpuFenceManager::CreateGpuFenceFromHandle(
uint32_t client_id,
const gfx::GpuFenceHandle& handle) {
// The handle must be valid. The fallback kEmpty type cannot be duplicated.
if (handle.is_null())
return false;
// This must be a new entry.
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it != gpu_fence_entries_.end())
return false;
gfx::GpuFence gpu_fence(handle);
auto entry = std::make_unique<GpuFenceEntry>();
entry->gl_fence_ = gl::GLFence::CreateFromGpuFence(gpu_fence);
if (!entry->gl_fence_)
return false;
std::pair<GpuFenceEntryMap::iterator, bool> result =
gpu_fence_entries_.emplace(client_id, std::move(entry));
DCHECK(result.second);
return true;
}
bool GpuFenceManager::IsValidGpuFence(uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
return it != gpu_fence_entries_.end();
}
std::unique_ptr<gfx::GpuFence> GpuFenceManager::GetGpuFence(
uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it == gpu_fence_entries_.end())
return nullptr;
GpuFenceEntry* entry = it->second.get();
DCHECK(entry->gl_fence_);
return entry->gl_fence_->GetGpuFence();
}
bool GpuFenceManager::GpuFenceServerWait(uint32_t client_id) {
GpuFenceEntryMap::iterator it = gpu_fence_entries_.find(client_id);
if (it == gpu_fence_entries_.end())
return false;
GpuFenceEntry* entry = it->second.get();
DCHECK(entry->gl_fence_);
entry->gl_fence_->ServerWait();
return true;
}
bool GpuFenceManager::RemoveGpuFence(uint32_t client_id) {
return gpu_fence_entries_.erase(client_id) == 1u;
}
void GpuFenceManager::Destroy(bool have_context) {
if (!have_context) {
// Invalidate fences on context loss. This is a no-op for EGL fences, but
// other platforms may want this.
for (auto& it : gpu_fence_entries_) {
it.second.get()->gl_fence_->Invalidate();
}
}
gpu_fence_entries_.clear();
}
} // namespace gles2
} // namespace gpu