summaryrefslogtreecommitdiffstats
path: root/third_party/WebKit/Source/platform/graphics/gpu/SharedContextRateLimiter.cpp
blob: fa3cf4fd02ec2bebbf660693b94d47d92d496d7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 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(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;

    m_queries.append(0);
    if (m_canUseSyncQueries)
        gl->GenQueriesEXT(1, &m_queries.last());
    if (m_canUseSyncQueries) {
        gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, m_queries.last());
        gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
    }
    if (m_queries.size() > m_maxPendingTicks) {
        if (m_canUseSyncQueries) {
            WGC3Duint result;
            gl->GetQueryObjectuivEXT(m_queries.first(), GL_QUERY_RESULT_EXT, &result);
            gl->DeleteQueriesEXT(1, &m_queries.first());
            m_queries.removeFirst();
        } else {
            gl->Finish();
            reset();
        }
    }
}

void SharedContextRateLimiter::reset()
{
    if (!m_contextProvider)
        return;

    gpu::gles2::GLES2Interface* gl = m_contextProvider->contextGL();
    if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
        while (m_queries.size() > 0) {
            gl->DeleteQueriesEXT(1, &m_queries.first());
            m_queries.removeFirst();
        }
    } else {
        m_queries.clear();
    }
}

} // namespace blink