blob: 0fc1996dba52ab16ea00e68e10bfbbd984df7fcc [file] [log] [blame]
// Copyright 2015 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 "platform/graphics/gpu/SharedContextRateLimiter.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "platform/graphics/gpu/Extensions3DUtil.h"
#include "public/platform/Platform.h"
#include "public/platform/WebGraphicsContext3D.h"
#include "public/platform/WebGraphicsContext3DProvider.h"
#ifndef GL_COMMANDS_COMPLETED_CHROMIUM
#define GL_COMMANDS_COMPLETED_CHROMIUM 0x84F7
#endif
namespace blink {
PassOwnPtr<SharedContextRateLimiter> SharedContextRateLimiter::create(unsigned maxPendingTicks)
{
return adoptPtr(new SharedContextRateLimiter(maxPendingTicks));
}
SharedContextRateLimiter::SharedContextRateLimiter(unsigned maxPendingTicks)
: m_maxPendingTicks(maxPendingTicks)
, m_canUseSyncQueries(false)
{
m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
if (!m_contextProvider)
return;
gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
OwnPtr<Extensions3DUtil> extensionsUtil = Extensions3DUtil::create(m_contextProvider->context3d(), gl);
// TODO(junov): when the GLES 3.0 command buffer is ready, we could use fenceSync instead
m_canUseSyncQueries = extensionsUtil->supportsExtension("GL_CHROMIUM_sync_query");
}
}
void SharedContextRateLimiter::tick()
{
if (!m_contextProvider)
return;
gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
if (!gl || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR)
return;
WebGraphicsContext3D* context = m_contextProvider->context3d();
m_queries.append(m_canUseSyncQueries ? context->createQueryEXT() : 0);
if (m_canUseSyncQueries) {
context->beginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, m_queries.last());
context->endQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
}
if (m_queries.size() > m_maxPendingTicks) {
if (m_canUseSyncQueries) {
WGC3Duint result;
context->getQueryObjectuivEXT(m_queries.first(), GL_QUERY_RESULT_EXT, &result);
context->deleteQueryEXT(m_queries.first());
m_queries.removeFirst();
} else {
context->finish();
reset();
}
}
}
void SharedContextRateLimiter::reset()
{
if (!m_contextProvider)
return;
gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
WebGraphicsContext3D* context = m_contextProvider->context3d();
while (m_queries.size() > 0) {
context->deleteQueryEXT(m_queries.first());
m_queries.removeFirst();
}
} else {
m_queries.clear();
}
}
} // namespace blink