blob: 1103bc665d94bd2f44dc0c503048876378caa923 [file] [log] [blame]
// Copyright 2017 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.
#ifndef CHROME_BROWSER_ANDROID_VR_MAILBOX_TO_SURFACE_BRIDGE_H_
#define CHROME_BROWSER_ANDROID_VR_MAILBOX_TO_SURFACE_BRIDGE_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.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 gl {
class SurfaceTexture;
} // namespace gl
namespace gfx {
class GpuMemoryBuffer;
}
namespace gpu {
class ContextSupport;
struct Mailbox;
struct MailboxHolder;
struct SyncToken;
namespace gles2 {
class GLES2Interface;
}
} // namespace gpu
namespace viz {
class ContextProvider;
}
namespace vr {
class MailboxToSurfaceBridge {
public:
MailboxToSurfaceBridge();
virtual ~MailboxToSurfaceBridge();
// Returns true if the GPU process connection is established and ready to use.
// Equivalent to waiting for on_initialized to be called.
virtual bool IsConnected();
// Checks if a workaround from "gpu/config/gpu_driver_bug_workaround_type.h"
// is active. Requires initialization to be complete.
bool IsGpuWorkaroundEnabled(int32_t workaround);
void CreateSurface(gl::SurfaceTexture*);
// This class can be used in a couple ways using these sequences:
//
// To use entirely on the GL thread:
// Call CreateAndBindContextProvider(callback) from your thread.
// When the callback is invoked, the object is ready for GL calls
// such as CreateMailboxTexture().
//
// To create on one thread and use GL on another:
// Call CreateUnboundContextProvider(callback) and then make sure
// to call BindContextProviderToCurrentThread() from your GL
// thread afterwards before making an GL-related calls.
// Asynchronously create the context using the surface provided by an earlier
// CreateSurface call, or an offscreen context if that wasn't called. Also
// binds the context provider to the thread used for constructing the
// MailboxToSurfaceBridge object, and calls the callback on the constructor
// thread. Use this if constructing the object on the intended GL thread.
void CreateAndBindContextProvider(base::OnceClosure callback);
// Variant of above, use this if the MailboxToSurfaceBridge constructor
// wasn't run on the GL thread. The provided callback is run on the
// constructor thread. After that, you can pass the MailboxToSurfaceBridge
// to another thread. You must call BindContextProviderToCurrentThread()
// on the target GL thread before using any GL methods.
// The GL methods check that they are called on this thread, so there
// will be a DCHECK error if they are not used consistently.
virtual void CreateUnboundContextProvider(base::OnceClosure callback);
// Client must call this on the target (GL) thread after
// CreateUnboundContextProvider. It's called automatically when using
// CreateAndBindContextProvider.
virtual void BindContextProviderToCurrentThread();
// All other public methods below must be called on the GL thread
// (except when marked otherwise).
void ResizeSurface(int width, int height);
// Returns true if swapped successfully. This can fail if the GL
// context isn't ready for use yet, in that case the caller
// won't get a new frame on the SurfaceTexture.
bool CopyMailboxToSurfaceAndSwap(const gpu::MailboxHolder& mailbox);
void GenSyncToken(gpu::SyncToken* out_sync_token);
void WaitSyncToken(const gpu::SyncToken& sync_token);
// Copies a GpuFence from the local context to the GPU process,
// and issues a server wait for it.
void WaitForClientGpuFence(gfx::GpuFence*);
// Creates a GpuFence in the GPU process after the supplied sync_token
// completes, and copies it for use in the local context. This is
// asynchronous, the callback receives the GpuFence once it's available.
void CreateGpuFence(
const gpu::SyncToken& sync_token,
base::OnceCallback<void(std::unique_ptr<gfx::GpuFence>)> callback);
// Creates a texture and binds it to a newly created mailbox. Returns its
// mailbox and texture ID in the command buffer context. (Don't use that
// in the local GL context, it's not valid there.)
virtual uint32_t CreateMailboxTexture(gpu::Mailbox* mailbox);
// Creates a GLImage from the |buffer| and binds it to the supplied texture_id
// in the GPU process. Returns the image ID in the command buffer context.
// Does not take ownership of |buffer| or retain any references to it.
uint32_t BindSharedBufferImage(gfx::GpuMemoryBuffer* buffer,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
uint32_t texture_id);
void UnbindSharedBuffer(uint32_t image_id, uint32_t texture_id);
private:
void CreateContextProviderInternal();
void OnContextAvailableOnUiThread(
scoped_refptr<viz::ContextProvider> provider);
void InitializeRenderer();
void DestroyContext();
void DrawQuad(unsigned int textureHandle);
scoped_refptr<viz::ContextProvider> context_provider_;
std::unique_ptr<gl::ScopedJavaSurface> surface_;
gpu::gles2::GLES2Interface* gl_ = nullptr;
gpu::ContextSupport* context_support_ = nullptr;
int surface_handle_ = gpu::kNullSurfaceHandle;
// TODO(https://crbug.com/836524): shouldn't have both of these closures
// in the same class like this.
base::OnceClosure on_context_bound_;
base::OnceClosure on_context_provider_ready_;
// Saved state for a pending resize, the dimensions are only
// valid if needs_resize_ is true.
bool needs_resize_ = false;
int resize_width_;
int resize_height_;
// A swap ID which is passed to GL swap. Incremented each call.
uint64_t swap_id_ = 0;
// A task runner for the thread the object was created on.
scoped_refptr<base::SingleThreadTaskRunner> constructor_thread_task_runner_;
// Must be last.
base::WeakPtrFactory<MailboxToSurfaceBridge> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(MailboxToSurfaceBridge);
};
} // namespace vr
#endif // CHROME_BROWSER_ANDROID_VR_MAILBOX_TO_SURFACE_BRIDGE_H_