Commit 56c883db authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

GLX: implement GLSurface PresentationCallback

This CL implements GLSurface PresentationCallback for GLX. It uses
OpenGL GpuTimer to query the |timestamp| for GPU finishes renderering
the back buffer, and use the closest VSync after the |timestamp| to
run presentation callback.

Bug: 776877
Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: I87f40022555b988e9cbe5cd628979c15f6043f0d
Reviewed-on: https://chromium-review.googlesource.com/809704Reviewed-by: default avatardanakj <danakj@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523646}
parent 5822c72b
......@@ -216,4 +216,14 @@ void SoftwareOutputDeviceMac::GetVSyncParameters(
update_vsync_callback_ = callback;
}
bool SoftwareOutputDeviceMac::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase,
base::TimeDelta* interval) {
return false;
}
bool SoftwareOutputDeviceMac::SupportGetVSyncParametersIfAvailable() {
return false;
}
} // namespace viz
......@@ -38,6 +38,9 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
// gfx::VSyncProvider implementation.
void GetVSyncParameters(
const gfx::VSyncProvider::UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
// Testing methods.
SkRegion LastCopyRegionForTesting() const {
......
......@@ -31,6 +31,13 @@ class FakeVSyncProvider : public gfx::VSyncProvider {
call_count_++;
}
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override {
return false;
}
bool SupportGetVSyncParametersIfAvailable() override { return false; }
int call_count() const { return call_count_; }
void set_timebase(base::TimeTicks timebase) { timebase_ = timebase; }
......
......@@ -663,6 +663,16 @@ void GpuVSyncProviderWin::GetVSyncParameters(
// thread.
}
bool GpuVSyncProviderWin::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase,
base::TimeDelta* interval) {
return false;
}
bool GpuVSyncProviderWin::SupportGetVSyncParametersIfAvailable() {
return false;
}
void GpuVSyncProviderWin::OnVSync(base::TimeTicks timestamp,
base::TimeDelta interval) {
DCHECK(vsync_worker_->BelongsToWorkerThread());
......
......@@ -31,6 +31,9 @@ class GPU_EXPORT GpuVSyncProviderWin : public gfx::VSyncProvider {
// This class ignores this method and updates VSync directly via a
// worker thread IPC call.
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
private:
void OnVSync(base::TimeTicks timestamp, base::TimeDelta interval);
......
......@@ -11,4 +11,16 @@ void FixedVSyncProvider::GetVSyncParameters(
callback.Run(timebase_, interval_);
}
bool FixedVSyncProvider::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase,
base::TimeDelta* interval) {
*timebase = timebase_;
*interval = interval_;
return true;
}
bool FixedVSyncProvider::SupportGetVSyncParametersIfAvailable() {
return true;
}
} // namespace gfx
......@@ -26,6 +26,14 @@ class GFX_EXPORT VSyncProvider {
// no data source). We provide the strong guarantee that the callback will
// not be called once the instance of this class is destroyed.
virtual void GetVSyncParameters(const UpdateVSyncCallback& callback) = 0;
// Similar to GetVSyncParameters(). It returns true, if the data is available.
// Otherwise false is returned.
virtual bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) = 0;
// Returns true, if GetVSyncParametersIfAvailable is supported.
virtual bool SupportGetVSyncParametersIfAvailable() = 0;
};
// Provides a constant timebase and interval.
......@@ -38,6 +46,9 @@ class GFX_EXPORT FixedVSyncProvider : public VSyncProvider {
~FixedVSyncProvider() override {}
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
private:
base::TimeTicks timebase_;
......
This diff is collapsed.
......@@ -11,13 +11,16 @@
#include <string>
#include "base/compiler_specific.h"
#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/vsync_provider.h"
#include "ui/gfx/x/x11_types.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gpu_timing.h"
namespace gl {
......@@ -76,6 +79,7 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
gfx::SwapResult SwapBuffers(const PresentationCallback& callback) override;
gfx::Size GetSize() override;
void* GetHandle() override;
bool SupportsPresentationCallback() override;
bool SupportsPostSubBuffer() override;
void* GetConfig() override;
GLSurfaceFormat GetFormat() override;
......@@ -85,6 +89,7 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
int width,
int height,
const PresentationCallback& callback) override;
bool OnMakeCurrent(GLContext* context) override;
gfx::VSyncProvider* GetVSyncProvider() override;
VisualID GetVisualID() const { return visual_id_; }
......@@ -103,10 +108,23 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
bool CanHandleEvent(XEvent* xevent);
gfx::AcceleratedWidget window() const { return window_; }
private:
// The handle for the drawable to make current or swap.
GLXDrawable GetDrawableHandle() const;
void PreSwapBuffers(const PresentationCallback& callback);
void PostSwapBuffers();
// Check |pending_frames_| and run presentation callbacks.
void CheckPendingFrames();
// Callback used by PostDelayedTask for running CheckPendingFrames().
void CheckPendingFramesCallback();
void UpdateVSyncCallback(const base::TimeTicks timebase,
const base::TimeDelta interval);
// Window passed in at creation. Always valid.
gfx::AcceleratedWidget parent_window_;
......@@ -122,6 +140,26 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
std::unique_ptr<gfx::VSyncProvider> vsync_provider_;
scoped_refptr<GLContext> gl_context_;
scoped_refptr<GPUTimingClient> gpu_timing_client_;
struct Frame {
Frame(Frame&& other);
Frame(std::unique_ptr<GPUTimer>&& timer,
const PresentationCallback& callback);
~Frame();
Frame& operator=(Frame&& other);
std::unique_ptr<GPUTimer> timer;
PresentationCallback callback;
};
base::circular_deque<Frame> pending_frames_;
base::TimeTicks vsync_timebase_;
base::TimeDelta vsync_interval_;
bool waiting_for_vsync_parameters_;
base::WeakPtrFactory<NativeViewGLSurfaceGLX> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceGLX);
};
......
......@@ -136,7 +136,7 @@ class GL_EXPORT GPUTimingClient
// CheckAndResetTimerErrors has to be called before reading timestamps
// from GPUTimers instances and after making sure all the timers
// were available.
// If the returned value is false, all the previous timers should be
// If the returned value is true, all the previous timers should be
// discarded.
bool CheckAndResetTimerErrors();
......
......@@ -38,6 +38,15 @@ SyncControlVSyncProvider::~SyncControlVSyncProvider() {}
void SyncControlVSyncProvider::GetVSyncParameters(
const UpdateVSyncCallback& callback) {
base::TimeTicks timebase;
base::TimeDelta interval;
if (GetVSyncParametersIfAvailable(&timebase, &interval))
callback.Run(timebase, interval);
}
bool SyncControlVSyncProvider::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase_out,
base::TimeDelta* interval_out) {
TRACE_EVENT0("gpu", "SyncControlVSyncProvider::GetVSyncParameters");
#if defined(OS_LINUX)
// The actual clock used for the system time returned by glXGetSyncValuesOML
......@@ -51,7 +60,7 @@ void SyncControlVSyncProvider::GetVSyncParameters(
int64_t media_stream_counter;
int64_t swap_buffer_counter;
if (!GetSyncValues(&system_time, &media_stream_counter, &swap_buffer_counter))
return;
return false;
// Both Intel and Mali drivers will return TRUE for GetSyncValues
// but a value of 0 for MSC if they cannot access the CRTC data structure
......@@ -61,7 +70,7 @@ void SyncControlVSyncProvider::GetVSyncParameters(
if (invalid_msc_) {
LOG_IF(ERROR, !prev_invalid_msc) << "glXGetSyncValuesOML "
"should not return TRUE with a media stream counter of 0.";
return;
return false;
}
struct timespec real_time;
......@@ -90,7 +99,7 @@ void SyncControlVSyncProvider::GetVSyncParameters(
// Return if |system_time| is more than 1 frames in the future.
int64_t interval_in_microseconds = last_good_interval_.InMicroseconds();
if (system_time > monotonic_time_in_microseconds + interval_in_microseconds)
return;
return false;
// If |system_time| is slightly in the future, adjust it to the previous
// frame and use the last frame counter to prevent issues in the callback.
......@@ -100,7 +109,7 @@ void SyncControlVSyncProvider::GetVSyncParameters(
}
if (monotonic_time_in_microseconds - system_time >
base::Time::kMicrosecondsPerSecond)
return;
return false;
const base::TimeTicks timebase =
base::TimeTicks() + base::TimeDelta::FromMicroseconds(system_time);
......@@ -154,8 +163,20 @@ void SyncControlVSyncProvider::GetVSyncParameters(
last_timebase_ = timebase;
last_media_stream_counter_ = media_stream_counter;
callback.Run(timebase, last_good_interval_);
*timebase_out = timebase;
*interval_out = last_good_interval_;
return true;
#else
return false;
#endif // defined(OS_LINUX)
}
bool SyncControlVSyncProvider::SupportGetVSyncParametersIfAvailable() {
#if defined(OS_LINUX)
return true;
#else
return false;
#endif
}
} // namespace gl
......@@ -21,6 +21,9 @@ class SyncControlVSyncProvider : public gfx::VSyncProvider {
~SyncControlVSyncProvider() override;
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
static constexpr bool IsSupported() {
#if defined(OS_LINUX)
......
......@@ -30,6 +30,15 @@ void VSyncProviderWin::InitializeOneOff() {
}
void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
base::TimeTicks timebase;
base::TimeDelta interval;
if (GetVSyncParametersIfAvailable(&timebase, &interval))
callback.Run(timebase, interval);
}
bool VSyncProviderWin::GetVSyncParametersIfAvailable(
base::TimeTicks* out_timebase,
base::TimeDelta* out_interval) {
TRACE_EVENT0("gpu", "WinVSyncProvider::GetVSyncParameters");
base::TimeTicks timebase;
......@@ -105,9 +114,16 @@ void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
}
}
if (!interval.is_zero()) {
callback.Run(timebase, interval);
}
if (interval.is_zero())
return false;
*out_timebase = timebase;
*out_interval = interval;
return true;
}
bool VSyncProviderWin::SupportGetVSyncParametersIfAvailable() {
return true;
}
} // namespace gl
......@@ -20,6 +20,9 @@ class GL_EXPORT VSyncProviderWin : public gfx::VSyncProvider {
// gfx::VSyncProvider overrides;
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
private:
gfx::AcceleratedWidget window_;
......
......@@ -17,4 +17,14 @@ void DrmVSyncProvider::GetVSyncParameters(const UpdateVSyncCallback& callback) {
window_->GetVSyncParameters(callback);
}
bool DrmVSyncProvider::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase,
base::TimeDelta* interval) {
return false;
}
bool DrmVSyncProvider::SupportGetVSyncParametersIfAvailable() {
return false;
}
} // namespace ui
......@@ -19,6 +19,9 @@ class DrmVSyncProvider : public gfx::VSyncProvider {
~DrmVSyncProvider() override;
void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
base::TimeDelta* interval) override;
bool SupportGetVSyncParametersIfAvailable() override;
private:
DrmWindowProxy* window_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment