| Index: content/common/gpu/pass_through_image_transport_surface.cc
|
| diff --git a/content/common/gpu/pass_through_image_transport_surface.cc b/content/common/gpu/pass_through_image_transport_surface.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3d0d1c8a350e1e36bb3e139b2dc688f9b7fdfdce
|
| --- /dev/null
|
| +++ b/content/common/gpu/pass_through_image_transport_surface.cc
|
| @@ -0,0 +1,175 @@
|
| +// Copyright 2016 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 "content/common/gpu/pass_through_image_transport_surface.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/command_line.h"
|
| +#include "build/build_config.h"
|
| +#include "content/common/gpu/gpu_command_buffer_stub.h"
|
| +#include "ui/gfx/vsync_provider.h"
|
| +#include "ui/gl/gl_context.h"
|
| +#include "ui/gl/gl_switches.h"
|
| +
|
| +namespace content {
|
| +
|
| +PassThroughImageTransportSurface::PassThroughImageTransportSurface(
|
| + GpuChannelManager* /* manager */,
|
| + GpuCommandBufferStub* stub,
|
| + gfx::GLSurface* surface)
|
| + : GLSurfaceAdapter(surface),
|
| + stub_(stub->AsWeakPtr()),
|
| + did_set_swap_interval_(false),
|
| + weak_ptr_factory_(this) {}
|
| +
|
| +bool PassThroughImageTransportSurface::Initialize(
|
| + gfx::GLSurface::Format format) {
|
| + // The surface is assumed to have already been initialized.
|
| + if (!stub_.get() || !stub_->decoder())
|
| + return false;
|
| + stub_->SetLatencyInfoCallback(
|
| + base::Bind(&PassThroughImageTransportSurface::SetLatencyInfo,
|
| + base::Unretained(this)));
|
| + return true;
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::Destroy() {
|
| + GLSurfaceAdapter::Destroy();
|
| +}
|
| +
|
| +gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| + gfx::SwapResult result = gfx::GLSurfaceAdapter::SwapBuffers();
|
| + FinishSwapBuffers(std::move(latency_info), result);
|
| + return result;
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::SwapBuffersAsync(
|
| + const GLSurface::SwapCompletionCallback& callback) {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| +
|
| + // We use WeakPtr here to avoid manual management of life time of an instance
|
| + // of this class. Callback will not be called once the instance of this class
|
| + // is destroyed. However, this also means that the callback can be run on
|
| + // the calling thread only.
|
| + gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
|
| + &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
|
| +}
|
| +
|
| +gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x,
|
| + int y,
|
| + int width,
|
| + int height) {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| + gfx::SwapResult result =
|
| + gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
|
| + FinishSwapBuffers(std::move(latency_info), result);
|
| + return result;
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::PostSubBufferAsync(
|
| + int x,
|
| + int y,
|
| + int width,
|
| + int height,
|
| + const GLSurface::SwapCompletionCallback& callback) {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| + gfx::GLSurfaceAdapter::PostSubBufferAsync(
|
| + x, y, width, height,
|
| + base::Bind(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info),
|
| + callback));
|
| +}
|
| +
|
| +gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| + gfx::SwapResult result = gfx::GLSurfaceAdapter::CommitOverlayPlanes();
|
| + FinishSwapBuffers(std::move(latency_info), result);
|
| + return result;
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::CommitOverlayPlanesAsync(
|
| + const GLSurface::SwapCompletionCallback& callback) {
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
|
| + gfx::GLSurfaceAdapter::CommitOverlayPlanesAsync(base::Bind(
|
| + &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
|
| +}
|
| +
|
| +bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
|
| + if (!did_set_swap_interval_) {
|
| + if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kDisableGpuVsync))
|
| + context->ForceSwapIntervalZero(true);
|
| + else
|
| + context->SetSwapInterval(1);
|
| + did_set_swap_interval_ = true;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {
|
| + if (stub_.get()) {
|
| + stub_->SetLatencyInfoCallback(
|
| + base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
|
| + }
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::SetLatencyInfo(
|
| + const std::vector<ui::LatencyInfo>& latency_info) {
|
| + latency_info_.insert(latency_info_.end(), latency_info.begin(),
|
| + latency_info.end());
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
|
| + gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
|
| + if (vsync_provider) {
|
| + vsync_provider->GetVSyncParameters(base::Bind(
|
| + &GpuCommandBufferStub::SendUpdateVSyncParameters, stub_->AsWeakPtr()));
|
| + }
|
| +}
|
| +
|
| +scoped_ptr<std::vector<ui::LatencyInfo>>
|
| +PassThroughImageTransportSurface::StartSwapBuffers() {
|
| + // GetVsyncValues before SwapBuffers to work around Mali driver bug:
|
| + // crbug.com/223558.
|
| + SendVSyncUpdateIfAvailable();
|
| +
|
| + base::TimeTicks swap_time = base::TimeTicks::Now();
|
| + for (auto& latency : latency_info_) {
|
| + latency.AddLatencyNumberWithTimestamp(
|
| + ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
|
| + }
|
| +
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info(
|
| + new std::vector<ui::LatencyInfo>());
|
| + latency_info->swap(latency_info_);
|
| +
|
| + return latency_info;
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::FinishSwapBuffers(
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
|
| + gfx::SwapResult result) {
|
| + base::TimeTicks swap_ack_time = base::TimeTicks::Now();
|
| + for (auto& latency : *latency_info) {
|
| + latency.AddLatencyNumberWithTimestamp(
|
| + ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
|
| + swap_ack_time, 1);
|
| + }
|
| +
|
| + stub_->SendSwapBuffersCompleted(*latency_info, result);
|
| +}
|
| +
|
| +void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
|
| + scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
|
| + GLSurface::SwapCompletionCallback callback,
|
| + gfx::SwapResult result) {
|
| + FinishSwapBuffers(std::move(latency_info), result);
|
| + callback.Run(result);
|
| +}
|
| +
|
| +} // namespace content
|
|
|