|  | // 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 <memory> | 
|  | #include "gpu/GLES2/gl2extchromium.h" | 
|  | #include "platform/graphics/gpu/Extensions3DUtil.h" | 
|  | #include "platform/wtf/PtrUtil.h" | 
|  | #include "public/platform/Platform.h" | 
|  | #include "public/platform/WebGraphicsContext3DProvider.h" | 
|  | #include "third_party/khronos/GLES2/gl2.h" | 
|  |  | 
|  | namespace blink { | 
|  |  | 
|  | std::unique_ptr<SharedContextRateLimiter> SharedContextRateLimiter::Create( | 
|  | unsigned max_pending_ticks) { | 
|  | return WTF::WrapUnique(new SharedContextRateLimiter(max_pending_ticks)); | 
|  | } | 
|  |  | 
|  | 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::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 
|  | if (gl && gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { | 
|  | std::unique_ptr<Extensions3DUtil> extensions_util = | 
|  | Extensions3DUtil::Create(gl); | 
|  | // TODO(junov): when the GLES 3.0 command buffer is ready, we could use | 
|  | // fenceSync instead. | 
|  | can_use_sync_queries_ = | 
|  | extensions_util->SupportsExtension("GL_CHROMIUM_sync_query"); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SharedContextRateLimiter::Tick() { | 
|  | if (!context_provider_) | 
|  | return; | 
|  |  | 
|  | gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 
|  | if (!gl || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR) | 
|  | return; | 
|  |  | 
|  | queries_.push_back(0); | 
|  | if (can_use_sync_queries_) { | 
|  | gl->GenQueriesEXT(1, &queries_.back()); | 
|  | gl->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, queries_.back()); | 
|  | gl->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); | 
|  | } | 
|  | if (queries_.size() > max_pending_ticks_) { | 
|  | if (can_use_sync_queries_) { | 
|  | GLuint result; | 
|  | gl->GetQueryObjectuivEXT(queries_.front(), GL_QUERY_RESULT_EXT, &result); | 
|  | gl->DeleteQueriesEXT(1, &queries_.front()); | 
|  | queries_.pop_front(); | 
|  | } else { | 
|  | gl->Finish(); | 
|  | Reset(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void SharedContextRateLimiter::Reset() { | 
|  | if (!context_provider_) | 
|  | return; | 
|  |  | 
|  | gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | 
|  | if (can_use_sync_queries_ && gl && | 
|  | gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { | 
|  | while (queries_.size() > 0) { | 
|  | gl->DeleteQueriesEXT(1, &queries_.front()); | 
|  | queries_.pop_front(); | 
|  | } | 
|  | } else { | 
|  | queries_.clear(); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace blink |