Skip to content

Commit

Permalink
Citizen OSR GPU fixes
Browse files Browse the repository at this point in the history
Mainly, adding support for GPU VSync-based frame source, supporting non-NTHANDLE, and some changes for M91 parity.
  • Loading branch information
blattersturm committed Aug 31, 2022
1 parent 85592ea commit 90a2efc
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 9 deletions.
43 changes: 36 additions & 7 deletions libcef/browser/osr/gl_output_surface_external.cc
Expand Up @@ -19,6 +19,7 @@
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/swap_result.h"
#include "ui/gl/gl_utils.h"
#include "ui/gl/vsync_thread_win.h"

#if defined (OS_WIN) && !defined(ARCH_CPU_ARM_FAMILY)
#include "ui/gl/gl_image_dxgi.h"
Expand Down Expand Up @@ -138,13 +139,20 @@ GLOutputSurfaceExternal::GLOutputSurfaceExternal(
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
mojo::Remote<viz::mojom::ExternalRendererUpdater> external_renderer_updater)
: GLOutputSurface(context_provider, gpu::kNullSurfaceHandle),
vsync_thread_(gl::VSyncThreadWin::GetInstance()),
gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
external_renderer_updater_(std::move(external_renderer_updater)) {
external_renderer_updater_(std::move(external_renderer_updater)),
task_runner_(base::ThreadTaskRunnerHandle::Get()) {
capabilities_.uses_default_gl_framebuffer = false;
capabilities_.supports_gpu_vsync = true;
}

GLOutputSurfaceExternal::~GLOutputSurfaceExternal() {
DiscardBackbuffer();

if (gpu_vsync_callback_) {
vsync_thread_->RemoveObserver(this);
}
}

void GLOutputSurfaceExternal::EnsureBackbuffer() {
Expand All @@ -169,6 +177,20 @@ void GLOutputSurfaceExternal::EnsureBackbuffer() {
}
}

void GLOutputSurfaceExternal::OnVSync(base::TimeTicks timebase,
base::TimeDelta interval) {
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&GLOutputSurfaceExternal::HandleVSyncOnMainThread,
weak_ptr_factory_.GetWeakPtr(), timebase, interval));
}

void GLOutputSurfaceExternal::HandleVSyncOnMainThread(base::TimeTicks timebase,
base::TimeDelta interval) {
if (gpu_vsync_callback_)
gpu_vsync_callback_.Run(timebase, interval);
}

void GLOutputSurfaceExternal::DiscardBackbuffer() {
current_surface_.reset();

Expand Down Expand Up @@ -228,6 +250,11 @@ void GLOutputSurfaceExternal::OnSyncWaitComplete(
if (new_texture)
handle = current_surface_->GetHandle();

auto now = base::TimeTicks::Now();
client()->DidReceiveSwapBuffersAck({.swap_start = now, .swap_end = now}, gfx::GpuFenceHandle());
client()->DidReceivePresentationFeedback(gfx::PresentationFeedback(
now, /*base::Milliseconds(16)*/base::TimeDelta(), /*flags=*/0));

if (current_surface_) {
external_renderer_updater_->OnAfterFlip(
std::move(handle), new_texture, gfx::Rect(size_),
Expand All @@ -240,15 +267,17 @@ void GLOutputSurfaceExternal::OnSyncWaitComplete(
}
}

void GLOutputSurfaceExternal::SetGpuVSyncCallback(GpuVSyncCallback callback) {
if (!gpu_vsync_callback_) {
vsync_thread_->AddObserver(this);
}

gpu_vsync_callback_ = std::move(callback);
}

void GLOutputSurfaceExternal::OnAfterSwap(
std::vector<ui::LatencyInfo> latency_info) {
latency_tracker()->OnGpuSwapBuffersCompleted(latency_info);
// Swap timings are not available since for offscreen there is no Swap, just a
// SignalSyncToken. We use base::TimeTicks::Now() as an overestimate.
auto now = base::TimeTicks::Now();
client()->DidReceiveSwapBuffersAck({.swap_start = now}, gfx::GpuFenceHandle());
client()->DidReceivePresentationFeedback(gfx::PresentationFeedback(
now, base::Milliseconds(16), /*flags=*/0));

if (needs_swap_size_notifications())
client()->DidSwapWithSize(size_);
Expand Down
16 changes: 15 additions & 1 deletion libcef/browser/osr/gl_output_surface_external.h
Expand Up @@ -15,12 +15,18 @@
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "ui/gfx/color_space.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/vsync_observer.h"

namespace gl {
class VSyncThreadWin;
}

namespace viz {

class ExternalImageData;

class VIZ_SERVICE_EXPORT GLOutputSurfaceExternal : public GLOutputSurface {
class VIZ_SERVICE_EXPORT GLOutputSurfaceExternal : public GLOutputSurface, public gl::VSyncObserver {
public:
explicit GLOutputSurfaceExternal(
scoped_refptr<VizProcessContextProvider> context_provider,
Expand All @@ -34,8 +40,12 @@ class VIZ_SERVICE_EXPORT GLOutputSurfaceExternal : public GLOutputSurface {
void BindFramebuffer() override;
void Reshape(const ReshapeParams& params) override;
void SwapBuffers(OutputSurfaceFrame frame) override;
void SetGpuVSyncCallback(GpuVSyncCallback callback) override;

void OnVSync(base::TimeTicks timebase, base::TimeDelta interval) override;

private:
void HandleVSyncOnMainThread(base::TimeTicks timebase, base::TimeDelta interval);
void OnSyncWaitComplete(std::vector<ui::LatencyInfo> latency_info);
void OnAfterSwap(std::vector<ui::LatencyInfo> latency_info);
void BindTexture();
Expand All @@ -44,6 +54,9 @@ class VIZ_SERVICE_EXPORT GLOutputSurfaceExternal : public GLOutputSurface {

ExternalImageData* CreateSurface();

const raw_ptr<gl::VSyncThreadWin> vsync_thread_;

GpuVSyncCallback gpu_vsync_callback_;
std::unique_ptr<ExternalImageData> current_surface_;
bool new_texture = false;

Expand All @@ -56,6 +69,7 @@ class VIZ_SERVICE_EXPORT GLOutputSurfaceExternal : public GLOutputSurface {
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;

mojo::Remote<viz::mojom::ExternalRendererUpdater> external_renderer_updater_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;

GLOutputSurfaceExternal(const GLOutputSurfaceExternal&);
void operator=(const GLOutputSurfaceExternal&);
Expand Down
2 changes: 1 addition & 1 deletion libcef/browser/osr/host_display_client_osr.cc
Expand Up @@ -61,7 +61,7 @@ void CefExternalRendererUpdaterOSR::OnAfterFlip(
#if defined (OS_WIN) && !defined(ARCH_CPU_ARM_FAMILY)
HANDLE nthandle = nullptr;
if (new_texture)
nthandle = handle.dxgi_handle.Get();
nthandle = HANDLE(handle.dxgi_handle);
view_->OnAcceleratedPaint2(damage_rect, nthandle, new_texture);
#elif defined(OS_MAC)
view_->OnAcceleratedPaint2(damage_rect,
Expand Down
4 changes: 4 additions & 0 deletions libcef/browser/osr/render_widget_host_view_osr.cc
Expand Up @@ -924,6 +924,7 @@ void CefRenderWidgetHostViewOSR::OnFrameComplete(
DCHECK_EQ(begin_frame_source_.source_id(), ack.frame_id.source_id);
DCHECK_EQ(begin_frame_number_, ack.frame_id.sequence_number);
begin_frame_pending_ = false;
had_frame_ = true;
}

void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation(
Expand Down Expand Up @@ -958,6 +959,9 @@ void CefRenderWidgetHostViewOSR::OnRenderFrameMetadataChangedAfterActivation(

std::unique_ptr<viz::HostDisplayClient>
CefRenderWidgetHostViewOSR::CreateHostDisplayClient() {
if (had_frame_) {
begin_frame_pending_ = false;
}
host_display_client_ =
new CefHostDisplayClientOSR(this, gfx::kNullAcceleratedWidget, use_proxy_output_);
host_display_client_->SetActive(true);
Expand Down
1 change: 1 addition & 0 deletions libcef/browser/osr/render_widget_host_view_osr.h
Expand Up @@ -366,6 +366,7 @@ class CefRenderWidgetHostViewOSR
viz::StubBeginFrameSource begin_frame_source_;
uint64_t begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
bool begin_frame_pending_ = false;
bool had_frame_ = false;

bool sync_frame_rate_ = false;
bool external_begin_frame_enabled_ = false;
Expand Down

0 comments on commit 90a2efc

Please sign in to comment.