chromium/components/webxr/mailbox_to_surface_bridge_impl.h

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_WEBXR_MAILBOX_TO_SURFACE_BRIDGE_IMPL_H_
#define COMPONENTS_WEBXR_MAILBOX_TO_SURFACE_BRIDGE_IMPL_H_

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/single_thread_task_runner.h"
#include "device/vr/android/mailbox_to_surface_bridge.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gl/android/scoped_java_surface.h"

namespace gpu {
class ContextSupport;

namespace gles2 {
class GLES2Interface;
}
}  // namespace gpu

namespace viz {
class ContextProvider;
}

namespace webxr {

class MailboxToSurfaceBridgeImpl : public device::MailboxToSurfaceBridge {
 public:
  // It's OK to create an object instance and pass it to a different thread,
  // i.e. to enable dependency injection for a unit test, but all methods on it
  // must be called consistently on a single GL thread. This is verified by
  // DCHECKs.
  MailboxToSurfaceBridgeImpl();

  MailboxToSurfaceBridgeImpl(const MailboxToSurfaceBridgeImpl&) = delete;
  MailboxToSurfaceBridgeImpl& operator=(const MailboxToSurfaceBridgeImpl&) =
      delete;

  ~MailboxToSurfaceBridgeImpl() override;

  bool IsConnected() override;

  bool IsGpuWorkaroundEnabled(int32_t workaround) override;

  void CreateSurface(gl::SurfaceTexture*) override;

  void CreateAndBindContextProvider(base::OnceClosure callback) override;

  // All other public methods below must be called on the GL thread
  // (except when marked otherwise).

  void ResizeSurface(int width, int height) override;

  bool CopyMailboxToSurfaceAndSwap(const gpu::MailboxHolder& mailbox,
                                   const gfx::Transform& uv_transform) override;

  void GenSyncToken(gpu::SyncToken* out_sync_token) override;

  void WaitSyncToken(const gpu::SyncToken& sync_token) override;

  void WaitForClientGpuFence(gfx::GpuFence&) override;

  void CreateGpuFence(const gpu::SyncToken& sync_token,
                      base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)>
                          callback) override;

  scoped_refptr<gpu::ClientSharedImage> CreateSharedImage(
      gfx::GpuMemoryBufferHandle buffer_handle,
      gfx::BufferFormat buffer_format,
      const gfx::Size& size,
      const gfx::ColorSpace& color_space,
      gpu::SharedImageUsageSet usage,
      gpu::SyncToken& sync_token) override;

  void DestroySharedImage(
      const gpu::SyncToken& sync_token,
      scoped_refptr<gpu::ClientSharedImage> shared_image) override;

 private:
  void BindContextProviderToCurrentThread();
  void OnContextAvailableOnUiThread(
      scoped_refptr<viz::ContextProvider> provider);
  void InitializeRenderer();
  void DestroyContext();
  void DrawQuad(unsigned int textureHandle, const gfx::Transform& uv_transform);

  scoped_refptr<viz::ContextProvider> context_provider_;
  raw_ptr<gpu::gles2::GLES2Interface> gl_ = nullptr;
  raw_ptr<gpu::ContextSupport> context_support_ = nullptr;
  int surface_handle_ = gpu::kNullSurfaceHandle;
  // TODO(crbug.com/41385307): shouldn't have both of these closures
  // in the same class like this.
  base::OnceClosure on_context_bound_;

  // Only initialized if we have Surface (i.e surface_handle_ is not null).
  int surface_width_ = 0;
  int surface_height_ = 0;

  // If true, surface width/height is the intended size that should be applied
  // to the surface once it's ready for use.
  bool needs_resize_ = false;

  // A swap ID which is passed to GL swap. Incremented each call.
  uint64_t swap_id_ = 0;

  // Uniform handle for the UV transform used by DrawQuad.
  uint32_t uniform_uv_transform_handle_ = 0;

  // A task runner for the GL thread
  scoped_refptr<base::SingleThreadTaskRunner> gl_thread_task_runner_;

  // Must be last.
  base::WeakPtrFactory<MailboxToSurfaceBridgeImpl> weak_ptr_factory_{this};
};

class MailboxToSurfaceBridgeFactoryImpl
    : public device::MailboxToSurfaceBridgeFactory {
 public:
  std::unique_ptr<device::MailboxToSurfaceBridge> Create() const override;
};

}  // namespace webxr

#endif  // COMPONENTS_WEBXR_MAILBOX_TO_SURFACE_BRIDGE_IMPL_H_