blob: 30a7b157eca209fa155366a9fde8f0b8f2200e82 [file] [log] [blame] [edit]
// 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 "config.h"
#include "modules/webgl/EXTDisjointTimerQuery.h"
#include "bindings/modules/v8/WebGLAny.h"
#include "modules/webgl/WebGLRenderingContextBase.h"
#include "modules/webgl/WebGLTimerQueryEXT.h"
namespace blink {
EXTDisjointTimerQuery::~EXTDisjointTimerQuery()
{
}
WebGLExtensionName EXTDisjointTimerQuery::name() const
{
return EXTDisjointTimerQueryName;
}
EXTDisjointTimerQuery* EXTDisjointTimerQuery::create(WebGLRenderingContextBase* context)
{
EXTDisjointTimerQuery* o = new EXTDisjointTimerQuery(context);
return o;
}
bool EXTDisjointTimerQuery::supported(WebGLRenderingContextBase* context)
{
return context->extensionsUtil()->supportsExtension("GL_EXT_disjoint_timer_query");
}
const char* EXTDisjointTimerQuery::extensionName()
{
return "EXT_disjoint_timer_query";
}
WebGLTimerQueryEXT* EXTDisjointTimerQuery::createQueryEXT()
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return nullptr;
WebGLTimerQueryEXT* o = WebGLTimerQueryEXT::create(scoped.context());
scoped.context()->addContextObject(o);
return o;
}
void EXTDisjointTimerQuery::deleteQueryEXT(WebGLTimerQueryEXT* query)
{
WebGLExtensionScopedContext scoped(this);
if (!query || scoped.isLost())
return;
query->deleteObject(scoped.context()->webContext());
if (query == m_currentElapsedQuery)
m_currentElapsedQuery.clear();
}
GLboolean EXTDisjointTimerQuery::isQueryEXT(WebGLTimerQueryEXT* query)
{
WebGLExtensionScopedContext scoped(this);
if (!query || scoped.isLost() || query->isDeleted() || !query->validate(0, scoped.context())) {
return false;
}
return scoped.context()->webContext()->isQueryEXT(query->object());
}
void EXTDisjointTimerQuery::beginQueryEXT(GLenum target, WebGLTimerQueryEXT* query)
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return;
if (!query || query->isDeleted() || !query->validate(0, scoped.context())) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
if (target != GL_TIME_ELAPSED_EXT) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_ENUM);
return;
}
if (m_currentElapsedQuery.get()) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
if (query->hasTarget() && query->target() != target) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
scoped.context()->webContext()->beginQueryEXT(target, query->object());
query->setTarget(target);
m_currentElapsedQuery = query;
}
void EXTDisjointTimerQuery::endQueryEXT(GLenum target)
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return;
if (target != GL_TIME_ELAPSED_EXT) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_ENUM);
return;
}
if (!m_currentElapsedQuery) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
scoped.context()->webContext()->endQueryEXT(target);
m_currentElapsedQuery.clear();
}
void EXTDisjointTimerQuery::queryCounterEXT(WebGLTimerQueryEXT* query, GLenum target)
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return;
if (!query || query->isDeleted() || !query->validate(0, scoped.context())) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
if (target != GL_TIMESTAMP_EXT) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_ENUM);
return;
}
if (query->hasTarget() && query->target() != target) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return;
}
scoped.context()->webContext()->queryCounterEXT(query->object(), target);
query->setTarget(target);
}
ScriptValue EXTDisjointTimerQuery::getQueryEXT(ScriptState* scriptState, GLenum target, GLenum pname)
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return ScriptValue::createNull(scriptState);
if (target == GL_TIMESTAMP_EXT || target == GL_TIME_ELAPSED_EXT) {
switch (pname) {
case GL_CURRENT_QUERY_EXT:
if (GL_TIME_ELAPSED_EXT == target && m_currentElapsedQuery.get())
return WebGLAny(scriptState, m_currentElapsedQuery.get());
return ScriptValue::createNull(scriptState);
case GL_QUERY_COUNTER_BITS_EXT: {
GLint value = 0;
scoped.context()->webContext()->getQueryivEXT(target, pname, &value);
return WebGLAny(scriptState, value);
}
default:
break;
}
}
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_ENUM);
return ScriptValue::createNull(scriptState);
}
ScriptValue EXTDisjointTimerQuery::getQueryObjectEXT(ScriptState* scriptState, WebGLTimerQueryEXT* query, GLenum pname)
{
WebGLExtensionScopedContext scoped(this);
if (scoped.isLost())
return ScriptValue::createNull(scriptState);
if (!query || query->isDeleted() || !query->validate(0, scoped.context())) {
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_OPERATION);
return ScriptValue::createNull(scriptState);
}
// TODO(kbr): Per the spec, figure out a way to only update this value once
// the current frame has completed rendering.
switch (pname) {
case GL_QUERY_RESULT_EXT: {
GLuint64 result = 0;
scoped.context()->webContext()->getQueryObjectui64vEXT(query->object(), pname, &result);
return WebGLAny(scriptState, result);
}
case GL_QUERY_RESULT_AVAILABLE_EXT: {
GLuint available = 0;
scoped.context()->webContext()->getQueryObjectuivEXT(query->object(), pname, &available);
return WebGLAny(scriptState, !!available);
}
default:
scoped.context()->webContext()->synthesizeGLError(GL_INVALID_ENUM);
break;
}
return ScriptValue::createNull(scriptState);
}
DEFINE_TRACE(EXTDisjointTimerQuery)
{
visitor->trace(m_currentElapsedQuery);
WebGLExtension::trace(visitor);
}
EXTDisjointTimerQuery::EXTDisjointTimerQuery(WebGLRenderingContextBase* context)
: WebGLExtension(context)
{
context->extensionsUtil()->ensureExtensionEnabled("GL_EXT_disjoint_timer_query");
}
} // namespace blink