blob: bc2178e8e9ddc35a9fc619948a1f3fbc4785de0d [file] [log] [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h"
#include <memory>
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
#include "third_party/khronos/GLES2/gl2.h"
namespace blink {
SharedContextRateLimiter::SharedContextRateLimiter(unsigned max_pending_ticks)
: max_pending_ticks_(max_pending_ticks), can_use_sync_queries_(false) {
context_provider_ =
Platform::Current()->CreateSharedOffscreenGraphicsContext3DProvider();
if (!context_provider_)
return;
gpu::raster::RasterInterface* raster_interface =
context_provider_->RasterInterface();
if (raster_interface &&
raster_interface->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
const auto& gpu_capabilities = context_provider_->GetCapabilities();
// TODO(junov): when the GLES 3.0 command buffer is ready, we could use
// fenceSync instead.
can_use_sync_queries_ = gpu_capabilities.sync_query;
}
}
void SharedContextRateLimiter::Tick() {
TRACE_EVENT0("blink", "SharedContextRateLimiter::Tick");
if (!context_provider_)
return;
gpu::raster::RasterInterface* raster_interface =
context_provider_->RasterInterface();
if (!raster_interface ||
raster_interface->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
return;
queries_.push_back(0);
if (can_use_sync_queries_) {
raster_interface->GenQueriesEXT(1, &queries_.back());
raster_interface->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM,
queries_.back());
raster_interface->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
}
if (queries_.size() > max_pending_ticks_) {
if (can_use_sync_queries_) {
TRACE_EVENT0("blink",
"GPU backpressure via GL_COMMANDS_COMPLETED_CHROMIUM");
GLuint result;
raster_interface->GetQueryObjectuivEXT(queries_.front(),
GL_QUERY_RESULT_EXT, &result);
raster_interface->DeleteQueriesEXT(1, &queries_.front());
queries_.pop_front();
} else {
TRACE_EVENT0("blink", "GPU backpressure via RasterInterface::Finish");
raster_interface->Finish();
Reset();
}
}
}
void SharedContextRateLimiter::Reset() {
if (!context_provider_)
return;
gpu::raster::RasterInterface* raster_interface =
context_provider_->RasterInterface();
if (can_use_sync_queries_ && raster_interface &&
raster_interface->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
while (!queries_.empty()) {
raster_interface->DeleteQueriesEXT(1, &queries_.front());
queries_.pop_front();
}
} else {
queries_.clear();
}
}
} // namespace blink