Commit de566f6b authored by Pawel Osciak's avatar Pawel Osciak Committed by Commit Bot

Add support for protected gpu memory buffers and a secure mode to ArcVDA.

A protected gpu memory buffer is a buffer that can be referred to
by a GpuMemoryBufferHandle, which does not provide access to the buffer's
contents. Such handle can be shared with and received from clients that
should not have access to the buffer's contents. When such handle is
passed to the ProtectedGpuMemoryBufferManager service by its privileged
client, it can be translated into another GpuMemoryBufferHandle, which
allows access to the buffer.

Also, implement a ProtectedMemoryManager to provide an allocation and
lookup service for such buffers for gbm.

Finally, add secure mode API to the ArcVideoAccelerator stack and integrate
it with the above, to provide a secure codec mode implementation.

TEST=E2E video playback tests
BUG=b:27174405,b:62575861,b:27204780

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: I80259db35463f7ed0cc3acc28bf767e55e46c8b8
Reviewed-on: https://chromium-review.googlesource.com/689818Reviewed-by: default avatarKuang-che Wu <kcwu@chromium.org>
Reviewed-by: default avatarOwen Lin <owenlin@chromium.org>
Reviewed-by: default avatarHidehiko Abe <hidehiko@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarDavid Reveman <reveman@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarJorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Queue: Pawel Osciak <posciak@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512797}
parent 0152131a
......@@ -4,12 +4,12 @@
"service_manager:connector": {
"provides": {
"browser": [
"arc::mojom::ProtectedBufferManager",
"arc::mojom::VideoDecodeAccelerator",
"arc::mojom::VideoDecodeClient",
"arc::mojom::VideoEncodeAccelerator",
"arc::mojom::VideoEncodeClient",
"chrome::mojom::ResourceUsageReporter",
"media::mojom::ProtectedBufferManager",
"profiling::mojom::ProfilingClient"
]
}
......
......@@ -149,7 +149,7 @@ void ArcOemCryptoBridge::ConnectToDaemon(
mojom::OemCryptoServiceRequest request) {
// Get the Mojo interface from the GPU for dealing with secure buffers and
// pass that to the daemon as well in our Connect call.
media::mojom::ProtectedBufferManagerPtr gpu_buffer_manager;
mojom::ProtectedBufferManagerPtr gpu_buffer_manager;
content::BindInterfaceInGpuProcess(mojo::MakeRequest(&gpu_buffer_manager));
oemcrypto_host_daemon_ptr_->Connect(std::move(request),
std::move(gpu_buffer_manager));
......
......@@ -27,6 +27,10 @@ static_library("gpu") {
"gpu_arc_video_decode_accelerator.h",
"gpu_arc_video_encode_accelerator.cc",
"gpu_arc_video_encode_accelerator.h",
"protected_buffer_manager.cc",
"protected_buffer_manager.h",
"protected_buffer_manager_proxy.cc",
"protected_buffer_manager_proxy.h",
]
}
}
......@@ -72,6 +72,8 @@ class ArcVideoDecodeAccelerator {
struct Config {
size_t num_input_buffers = 0;
uint32_t input_pixel_format = 0;
// If true, only buffers created via AllocateProtectedBuffer() may be used.
bool secure_mode = false;
// TODO(owenlin): Add output_pixel_format. For now only the native pixel
// format of each VDA on Chromium is supported.
};
......@@ -111,10 +113,27 @@ class ArcVideoDecodeAccelerator {
// returns SUCCESS iff initialization is successful.
virtual Result Initialize(const Config& config, Client* client) = 0;
// Allocates a new protected buffer on accelerator side for the given |port|
// and |index|, the contents of which will be inaccessible to the client.
// The protected buffer will remain valid for at least as long as the resource
// backing the passed |handle_fd| is not released (i.e. there is at least one
// reference on the file backing |handle_fd|.
//
// Usable only if the accelerator has been initialized to run in secure mode.
// Allocation for input will create a protected buffer of at least |size|;
// for output, |size| is ignored, and the currently configured output format
// is used instead to determine the required buffer size and format.
virtual bool AllocateProtectedBuffer(PortType port,
uint32_t index,
base::ScopedFD handle_fd,
size_t size) = 0;
// Assigns a shared memory to be used for the accelerator at the specified
// port and index. A buffer must be successfully bound before it can be passed
// to the accelerator via UseBuffer(). Already bound buffers may be reused
// multiple times without additional bindings.
// Not allowed in secure_mode, where protected buffers have to be allocated
// instead.
virtual void BindSharedMemory(PortType port,
uint32_t index,
base::ScopedFD ashmem_fd,
......@@ -125,6 +144,8 @@ class ArcVideoDecodeAccelerator {
// port and index. A buffer must be successfully bound before it can be
// passed to the accelerator via UseBuffer(). Already bound buffers may be
// reused multiple times without additional bindings.
// Not allowed in secure_mode, where protected buffers have to be allocated
// instead.
virtual void BindDmabuf(
PortType port,
uint32_t index,
......@@ -134,6 +155,8 @@ class ArcVideoDecodeAccelerator {
// Passes a buffer to the accelerator. For input buffer, the accelerator
// will process it. For output buffer, the accelerator will output content
// to it.
// In secure mode, |port| and |index| must correspond to a protected buffer
// allocated using AllocateProtectedBuffer().
virtual void UseBuffer(PortType port,
uint32_t index,
const BufferMetadata& metadata) = 0;
......
......@@ -19,6 +19,9 @@
namespace chromeos {
namespace arc {
class ProtectedBufferManager;
class ProtectedBufferHandle;
// This class is executed in the GPU process. It takes decoding requests from
// ARC via IPC channels and translates and sends those requests to an
// implementation of media::VideoDecodeAccelerator. It also returns the decoded
......@@ -28,8 +31,9 @@ class ChromeArcVideoDecodeAccelerator
public media::VideoDecodeAccelerator::Client,
public base::SupportsWeakPtr<ChromeArcVideoDecodeAccelerator> {
public:
explicit ChromeArcVideoDecodeAccelerator(
const gpu::GpuPreferences& gpu_preferences);
ChromeArcVideoDecodeAccelerator(
const gpu::GpuPreferences& gpu_preferences,
ProtectedBufferManager* protected_buffer_manager);
~ChromeArcVideoDecodeAccelerator() override;
// Implementation of the ArcVideoDecodeAccelerator interface.
......@@ -37,6 +41,10 @@ class ChromeArcVideoDecodeAccelerator
const Config& config,
ArcVideoDecodeAccelerator::Client* client) override;
void SetNumberOfOutputBuffers(size_t number) override;
bool AllocateProtectedBuffer(PortType port,
uint32_t index,
base::ScopedFD handle_fd,
size_t size) override;
void BindSharedMemory(PortType port,
uint32_t index,
base::ScopedFD ashmem_fd,
......@@ -80,28 +88,34 @@ class ChromeArcVideoDecodeAccelerator
// The information about the shared memory used as an input buffer.
struct InputBufferInfo {
// The file handle to access the buffer. It is owned by this class and
// should be closed after use.
base::ScopedFD handle;
// SharedMemoryHandle for this buffer to be passed to accelerator.
// In non-secure mode, received via BindSharedMemory from the client,
// in secure mode, a handle for the SharedMemory in protected_shmem.
base::SharedMemoryHandle shm_handle;
// The offset of the payload to the beginning of the shared memory.
off_t offset = 0;
// Used only in secure mode; handle to the protected buffer backing
// this input buffer.
std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle;
// The size of the payload in bytes.
size_t length = 0;
// Offset to the payload from the beginning of the shared memory buffer.
off_t offset = 0;
InputBufferInfo();
InputBufferInfo(InputBufferInfo&& other);
~InputBufferInfo();
};
// The information about the dmabuf used as an output buffer.
// The information about the native pixmap used as an output buffer.
struct OutputBufferInfo {
base::ScopedFD handle;
std::vector<::arc::VideoFramePlane> planes;
// GpuMemoryBufferHandle for this buffer to be passed to accelerator.
// In non-secure mode, received via BindDmabuf from the client,
// in secure mode, a handle to the NativePixmap in protected_pixmap.
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle;
// Used only in secure mode; handle to the protected buffer backing
// this output buffer.
std::unique_ptr<ProtectedBufferHandle> protected_buffer_handle;
OutputBufferInfo();
OutputBufferInfo(OutputBufferInfo&& other);
~OutputBufferInfo();
};
......@@ -155,12 +169,12 @@ class ChromeArcVideoDecodeAccelerator
std::list<InputRecord> input_records_;
// The details of the shared memory of each input buffers.
std::vector<InputBufferInfo> input_buffer_info_;
std::vector<std::unique_ptr<InputBufferInfo>> input_buffer_info_;
// To keep those output buffers which have been bound by bindDmabuf() but
// haven't been passed to VDA yet. Will call VDA::ImportBufferForPicture()
// when those buffers are used for the first time.
std::vector<OutputBufferInfo> buffers_pending_import_;
std::vector<std::unique_ptr<OutputBufferInfo>> buffers_pending_import_;
THREAD_CHECKER(thread_checker_);
size_t output_buffer_size_;
......@@ -168,7 +182,10 @@ class ChromeArcVideoDecodeAccelerator
// The minimal number of requested output buffers.
uint32_t requested_num_of_output_buffers_;
bool secure_mode_ = false;
gpu::GpuPreferences gpu_preferences_;
ProtectedBufferManager* protected_buffer_manager_;
DISALLOW_COPY_AND_ASSIGN(ChromeArcVideoDecodeAccelerator);
};
......
......@@ -22,8 +22,14 @@
#if defined(OS_CHROMEOS)
#include "chrome/gpu/gpu_arc_video_decode_accelerator.h"
#include "chrome/gpu/gpu_arc_video_encode_accelerator.h"
#include "chrome/gpu/protected_buffer_manager.h"
#include "chrome/gpu/protected_buffer_manager_proxy.h"
#include "content/public/common/service_manager_connection.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#if defined(USE_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#endif
#endif
namespace {
......@@ -46,6 +52,10 @@ ChromeContentGpuClient::ChromeContentGpuClient()
metrics::CallStackProfileParams::MAY_SHUFFLE))) {
if (StackSamplingConfiguration::Get()->IsProfilerEnabledForCurrentProcess())
stack_sampling_profiler_.Start();
#if defined(OS_CHROMEOS)
protected_buffer_manager_.reset(new chromeos::arc::ProtectedBufferManager());
#endif
}
ChromeContentGpuClient::~ChromeContentGpuClient() {}
......@@ -61,6 +71,10 @@ void ChromeContentGpuClient::InitializeRegistry(
base::Bind(&ChromeContentGpuClient::CreateArcVideoEncodeAccelerator,
base::Unretained(this)),
base::ThreadTaskRunnerHandle::Get());
registry->AddInterface(
base::Bind(&ChromeContentGpuClient::CreateProtectedBufferManager,
base::Unretained(this)),
base::ThreadTaskRunnerHandle::Get());
#endif
}
......@@ -68,6 +82,13 @@ void ChromeContentGpuClient::GpuServiceInitialized(
const gpu::GpuPreferences& gpu_preferences) {
#if defined(OS_CHROMEOS)
gpu_preferences_ = gpu_preferences;
#if defined(USE_OZONE)
ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->SetGetProtectedNativePixmapDelegate(base::Bind(
&chromeos::arc::ProtectedBufferManager::GetProtectedNativePixmapFor,
base::Unretained(protected_buffer_manager_.get())));
#endif
#endif
metrics::mojom::CallStackProfileCollectorPtr browser_interface;
......@@ -78,12 +99,11 @@ void ChromeContentGpuClient::GpuServiceInitialized(
}
#if defined(OS_CHROMEOS)
void ChromeContentGpuClient::CreateArcVideoDecodeAccelerator(
::arc::mojom::VideoDecodeAcceleratorRequest request) {
mojo::MakeStrongBinding(
base::MakeUnique<chromeos::arc::GpuArcVideoDecodeAccelerator>(
gpu_preferences_),
gpu_preferences_, protected_buffer_manager_.get()),
std::move(request));
}
......@@ -94,4 +114,12 @@ void ChromeContentGpuClient::CreateArcVideoEncodeAccelerator(
gpu_preferences_),
std::move(request));
}
void ChromeContentGpuClient::CreateProtectedBufferManager(
::arc::mojom::ProtectedBufferManagerRequest request) {
mojo::MakeStrongBinding(
base::MakeUnique<chromeos::arc::GpuArcProtectedBufferManagerProxy>(
protected_buffer_manager_.get()),
std::move(request));
}
#endif
......@@ -12,10 +12,16 @@
#include "content/public/gpu/content_gpu_client.h"
#if defined(OS_CHROMEOS)
#include "components/arc/common/protected_buffer_manager.mojom.h"
#include "components/arc/common/video_decode_accelerator.mojom.h"
#include "components/arc/common/video_encode_accelerator.mojom.h"
#include "gpu/command_buffer/service/gpu_preferences.h"
namespace chromeos {
namespace arc {
class ProtectedBufferManager;
} // namespace arc
} // namespace chromeos
#endif
class ChromeContentGpuClient : public content::ContentGpuClient {
......@@ -35,6 +41,9 @@ class ChromeContentGpuClient : public content::ContentGpuClient {
void CreateArcVideoEncodeAccelerator(
::arc::mojom::VideoEncodeAcceleratorRequest request);
void CreateProtectedBufferManager(
::arc::mojom::ProtectedBufferManagerRequest request);
#endif
// Used to profile process startup.
......@@ -42,6 +51,8 @@ class ChromeContentGpuClient : public content::ContentGpuClient {
#if defined(OS_CHROMEOS)
gpu::GpuPreferences gpu_preferences_;
std::unique_ptr<chromeos::arc::ProtectedBufferManager>
protected_buffer_manager_;
#endif
DISALLOW_COPY_AND_ASSIGN(ChromeContentGpuClient);
......
......@@ -98,6 +98,7 @@ struct TypeConverter<chromeos::arc::ArcVideoDecodeAccelerator::Config,
chromeos::arc::ArcVideoDecodeAccelerator::Config result;
result.num_input_buffers = input->num_input_buffers;
result.input_pixel_format = input->input_pixel_format;
result.secure_mode = input->secure_mode;
return result;
}
};
......@@ -108,9 +109,12 @@ namespace chromeos {
namespace arc {
GpuArcVideoDecodeAccelerator::GpuArcVideoDecodeAccelerator(
const gpu::GpuPreferences& gpu_preferences)
const gpu::GpuPreferences& gpu_preferences,
ProtectedBufferManager* protected_buffer_manager)
: gpu_preferences_(gpu_preferences),
accelerator_(new ChromeArcVideoDecodeAccelerator(gpu_preferences_)) {}
accelerator_(std::make_unique<ChromeArcVideoDecodeAccelerator>(
gpu_preferences_,
protected_buffer_manager)) {}
GpuArcVideoDecodeAccelerator::~GpuArcVideoDecodeAccelerator() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
......@@ -166,7 +170,9 @@ void GpuArcVideoDecodeAccelerator::Initialize(
LOG(ERROR) << "only decoder is supported";
std::move(callback).Run(
::arc::mojom::VideoDecodeAccelerator::Result::INVALID_ARGUMENT);
return;
}
client_ = std::move(client);
ArcVideoDecodeAccelerator::Result result = accelerator_->Initialize(
config.To<ArcVideoDecodeAccelerator::Config>(), this);
......@@ -197,6 +203,26 @@ base::ScopedFD GpuArcVideoDecodeAccelerator::UnwrapFdFromMojoHandle(
return base::ScopedFD(platform_file);
}
void GpuArcVideoDecodeAccelerator::AllocateProtectedBuffer(
::arc::mojom::PortType port,
uint32_t index,
mojo::ScopedHandle handle,
uint64_t size,
AllocateProtectedBufferCallback callback) {
DVLOG(2) << "port=" << port << ", index=" << index << ", size=" << size;
base::ScopedFD fd = UnwrapFdFromMojoHandle(std::move(handle));
if (!fd.is_valid()) {
std::move(callback).Run(false);
return;
}
bool result = accelerator_->AllocateProtectedBuffer(
static_cast<PortType>(port), index, std::move(fd), size);
std::move(callback).Run(result);
}
void GpuArcVideoDecodeAccelerator::BindSharedMemory(
::arc::mojom::PortType port,
uint32_t index,
......
......@@ -19,6 +19,8 @@
namespace chromeos {
namespace arc {
class ProtectedBufferManager;
// GpuArcVideoDecodeAccelerator manages life-cycle and IPC message translation
// for ArcVideoDecodeAccelerator.
//
......@@ -28,8 +30,9 @@ class GpuArcVideoDecodeAccelerator
: public ::arc::mojom::VideoDecodeAccelerator,
public ArcVideoDecodeAccelerator::Client {
public:
explicit GpuArcVideoDecodeAccelerator(
const gpu::GpuPreferences& gpu_preferences);
GpuArcVideoDecodeAccelerator(
const gpu::GpuPreferences& gpu_preferences,
ProtectedBufferManager* protected_buffer_manager);
~GpuArcVideoDecodeAccelerator() override;
private:
......@@ -46,6 +49,14 @@ class GpuArcVideoDecodeAccelerator
void Initialize(::arc::mojom::VideoDecodeAcceleratorConfigPtr config,
::arc::mojom::VideoDecodeClientPtr client,
InitializeCallback callback) override;
void AllocateProtectedBuffer(
::arc::mojom::PortType port,
uint32_t index,
mojo::ScopedHandle handle,
uint64_t size,
AllocateProtectedBufferCallback callback) override;
void BindSharedMemory(::arc::mojom::PortType port,
uint32_t index,
mojo::ScopedHandle ashmem_handle,
......
This diff is collapsed.
// 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_GPU_PROTECTED_BUFFER_MANAGER_H_
#define CHROME_GPU_PROTECTED_BUFFER_MANAGER_H_
#include <map>
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/native_pixmap.h"
namespace chromeos {
namespace arc {
// A ProtectedBufferHandle is returned to the owning client that requested
// the underlying ProtectedBuffer to be allocated.
//
// A ProtectedBuffer is a buffer that can be referred to via a handle (a dummy
// handle), which does not provide access to the actual contents of the buffer.
//
// The client should release this handle once the buffer is no longer needed.
// Releasing triggers destruction of the ProtectedBuffer instance stored in
// the ProtectedBufferManager, via the destruction callback passed to the
// ProtectedBufferHandle's constructor.
class ProtectedBufferHandle {
public:
// ProtectedBufferHandle takes ownership of the passed |shm_handle|.
ProtectedBufferHandle(base::OnceClosure destruction_cb,
const base::SharedMemoryHandle& shm_handle);
// ProtectedBufferHandle takes ownership of the passed |native_pixmap_handle|.
ProtectedBufferHandle(base::OnceClosure destruction_cb,
const gfx::NativePixmapHandle& native_pixmap_handle);
// Closes the underlying handle.
~ProtectedBufferHandle();
// Return a non-owned SharedMemoryHandle or NativePixmapHandle for this
// ProtectedBufferHandle, or an invalid/null handle if not applicable for the
// underlying type.
base::SharedMemoryHandle shm_handle() const;
gfx::NativePixmapHandle native_pixmap_handle() const;
private:
// The underlying, owning handles to the protected buffer.
// Only one of the handles is valid for each instance of this class.
// Closed on destruction of this ProtectedBufferHandle.
base::SharedMemoryHandle shm_handle_;
gfx::NativePixmapHandle native_pixmap_handle_;
base::OnceClosure destruction_cb_;
};
class ProtectedBufferManager {
public:
ProtectedBufferManager();
~ProtectedBufferManager();
// Allocate a ProtectedSharedMemory buffer of |size| bytes, to be referred to
// via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
// it.
// Destroying the ProtectedBufferHandle will result in permanently
// disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
// not free the underlying protected memory, which will remain valid as long
// as any SharedMemoryHandles to it are still in use.
// Return nullptr on failure.
std::unique_ptr<ProtectedBufferHandle> AllocateProtectedSharedMemory(
base::ScopedFD dummy_fd,
size_t size);
// Allocate a ProtectedNativePixmap of |format| and |size|, to be referred to
// via |dummy_fd| as the dummy handle, returning a ProtectedBufferHandle to
// it.
// Destroying the ProtectedBufferHandle will result in permanently
// disassociating the |dummy_fd| with the underlying ProtectedBuffer, but may
// not free the underlying protected memory, which will remain valid as long
// as any NativePixmapHandles to it are still in use.
// Return nullptr on failure.
std::unique_ptr<ProtectedBufferHandle> AllocateProtectedNativePixmap(
base::ScopedFD dummy_fd,
gfx::BufferFormat format,
const gfx::Size& size);
// Return a duplicated SharedMemoryHandle associated with the |dummy_fd|,
// if one exists, or an invalid handle otherwise.
// The client is responsible for closing the handle after use.
base::SharedMemoryHandle GetProtectedSharedMemoryHandleFor(
base::ScopedFD dummy_fd);
// Return a duplicated NativePixmapHandle associated with the |dummy_fd|,
// if one exists, or an empty handle otherwise.
// The client is responsible for closing the handle after use.
gfx::NativePixmapHandle GetProtectedNativePixmapHandleFor(
base::ScopedFD dummy_fd);
// Return a protected NativePixmap for a dummy |handle|, if one exists, or
// nullptr otherwise. On success, the |handle| is closed.
scoped_refptr<gfx::NativePixmap> GetProtectedNativePixmapFor(
const gfx::NativePixmapHandle& handle);
private:
// Used internally to maintain the association between the dummy handle and
// the underlying buffer.
class ProtectedBuffer;
class ProtectedSharedMemory;
class ProtectedNativePixmap;
// Imports the |dummy_fd| as a NativePixmap. This returns a unique |id|,
// which is guaranteed to be the same for all future imports of any fd
// referring to the buffer to which |dummy_fd| refers to, regardless of
// whether it is the same fd as the original one, or not, for the lifetime
// of the buffer.
//
// This allows us to have an unambiguous mapping from any fd referring to
// the same memory buffer to the same unique id.
//
// Returns nullptr on failure, in which case the returned id is not valid.
scoped_refptr<gfx::NativePixmap> ImportDummyFd(base::ScopedFD dummy_fd,
uint32_t* id) const;
// Removes an entry for given |id| from buffer_map_, to be called when the
// last reference to the buffer is dropped.
void RemoveEntry(uint32_t id);
// A map of unique ids to the ProtectedBuffers associated with them.
using ProtectedBufferMap =
std::map<uint32_t, std::unique_ptr<ProtectedBuffer>>;
ProtectedBufferMap buffer_map_;
base::Lock buffer_map_lock_;
base::WeakPtr<ProtectedBufferManager> weak_this_;
base::WeakPtrFactory<ProtectedBufferManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ProtectedBufferManager);
};
} // namespace arc
} // namespace chromeos
#endif // CHROME_GPU_PROTECTED_BUFFER_MANAGER_H_
// 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.
#include "chrome/gpu/protected_buffer_manager_proxy.h"
#include "chrome/gpu/protected_buffer_manager.h"
#include "mojo/public/cpp/system/platform_handle.h"
#define VLOGF(level) VLOG(level) << __func__ << "(): "
namespace chromeos {
namespace arc {
GpuArcProtectedBufferManagerProxy::GpuArcProtectedBufferManagerProxy(
chromeos::arc::ProtectedBufferManager* protected_buffer_manager)
: protected_buffer_manager_(protected_buffer_manager) {
DCHECK(protected_buffer_manager_);
}
base::ScopedFD GpuArcProtectedBufferManagerProxy::UnwrapFdFromMojoHandle(
mojo::ScopedHandle handle) {
base::PlatformFile platform_file;
MojoResult mojo_result =
mojo::UnwrapPlatformFile(std::move(handle), &platform_file);
if (mojo_result != MOJO_RESULT_OK) {
VLOGF(1) << "UnwrapPlatformFile failed: " << mojo_result;
return base::ScopedFD();
}
return base::ScopedFD(platform_file);
}
mojo::ScopedHandle GpuArcProtectedBufferManagerProxy::WrapFdInMojoHandle(
base::ScopedFD fd) {
return mojo::WrapPlatformFile(fd.release());
}
void GpuArcProtectedBufferManagerProxy::GetProtectedSharedMemoryFromHandle(
mojo::ScopedHandle dummy_handle,
GetProtectedSharedMemoryFromHandleCallback callback) {
base::ScopedFD unwrapped_fd = UnwrapFdFromMojoHandle(std::move(dummy_handle));
base::ScopedFD shmem_fd(
protected_buffer_manager_
->GetProtectedSharedMemoryHandleFor(std::move(unwrapped_fd))
.Release());
std::move(callback).Run(WrapFdInMojoHandle(std::move(shmem_fd)));
}
} // namespace arc
} // namespace chromeos
// 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_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_
#define CHROME_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_
#include "components/arc/common/protected_buffer_manager.mojom.h"
namespace chromeos {
namespace arc {
class ProtectedBufferManager;
// Manages mojo IPC translation for chromeos::arc::ProtectedBufferManager.
class GpuArcProtectedBufferManagerProxy
: public ::arc::mojom::ProtectedBufferManager {
public:
explicit GpuArcProtectedBufferManagerProxy(
chromeos::arc::ProtectedBufferManager* protected_buffer_manager);
// arc::mojom::ProtectedBufferManager implementation.
void GetProtectedSharedMemoryFromHandle(
mojo::ScopedHandle dummy_handle,
GetProtectedSharedMemoryFromHandleCallback callback) override;
private:
base::ScopedFD UnwrapFdFromMojoHandle(mojo::ScopedHandle handle);
mojo::ScopedHandle WrapFdInMojoHandle(base::ScopedFD fd);
chromeos::arc::ProtectedBufferManager* protected_buffer_manager_;
DISALLOW_COPY_AND_ASSIGN(GpuArcProtectedBufferManagerProxy);
};
} // namespace arc
} // namespace chromeos
#endif // CHROME_GPU_PROTECTED_BUFFER_MANAGER_PROXY_H_
......@@ -21,5 +21,5 @@ import "protected_buffer_manager.mojom";
// Next Method ID: 1
interface OemCryptoHostDaemon {
Connect@0(arc.mojom.OemCryptoService& oemcryptor,
media.mojom.ProtectedBufferManager protected_buffer_manager);
arc.mojom.ProtectedBufferManager protected_buffer_manager);
};
......@@ -5,7 +5,7 @@
// The original version of this file lives in the Chromium repository at:
// src/components/arc/common/protected_buffer_manager.mojom
module media.mojom;
module arc.mojom;
// This interface is exposed by the GPU process for translating dummy handles
// for secure buffers into a usable shared memory handle. The output of a
......
......@@ -40,6 +40,7 @@ struct VideoFormat {
uint32 crop_height;
};
// Next MinVersion: 2
struct VideoDecodeAcceleratorConfig {
// Deprecated. This config struct is used for decoder only.
enum DeviceTypeDeprecated {
......@@ -51,11 +52,12 @@ struct VideoDecodeAcceleratorConfig {
DeviceTypeDeprecated device_type_deprecated;
uint32 num_input_buffers;
uint32 input_pixel_format;
[MinVersion=1] bool secure_mode;
};
// Next MinVersion: 4
// Next MinVersion: 5
// Deprecated method IDs: 2, 7
// Next method ID: 10
// Next method ID: 11
interface VideoDecodeAccelerator {
enum Result {
SUCCESS = 0,
......@@ -70,6 +72,10 @@ interface VideoDecodeAccelerator {
Initialize@8(VideoDecodeAcceleratorConfig config,
VideoDecodeClient client) => (Result result);
[MinVersion=4]
AllocateProtectedBuffer@10(PortType port, uint32 index, handle handle_fd,
uint64 size) => (bool result);
BindSharedMemory@1(PortType port, uint32 index, handle ashmem_fd,
uint32 offset, uint32 length);
......
......@@ -132,6 +132,8 @@ component("gpu") {
"fake_jpeg_decode_accelerator.h",
"fake_video_decode_accelerator.cc",
"fake_video_decode_accelerator.h",
"format_utils.cc",
"format_utils.h",
"gles2_decoder_helper.cc",
"gles2_decoder_helper.h",
"gpu_video_accelerator_util.cc",
......
// 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.
#include "media/gpu/format_utils.h"
#include "base/logging.h"
namespace media {
VideoPixelFormat GfxBufferFormatToVideoPixelFormat(gfx::BufferFormat format) {
switch (format) {
case gfx::BufferFormat::BGRX_8888:
return PIXEL_FORMAT_XRGB;
case gfx::BufferFormat::BGRA_8888:
return PIXEL_FORMAT_ARGB;
case gfx::BufferFormat::YVU_420:
return PIXEL_FORMAT_YV12;
case gfx::BufferFormat::YUV_420_BIPLANAR:
return PIXEL_FORMAT_NV12;
default:
LOG(FATAL) << "Add more cases as needed";
return PIXEL_FORMAT_UNKNOWN;
}
}
gfx::BufferFormat VideoPixelFormatToGfxBufferFormat(
VideoPixelFormat pixel_format) {
switch (pixel_format) {
case PIXEL_FORMAT_ARGB:
return gfx::BufferFormat::BGRA_8888;
case PIXEL_FORMAT_XRGB:
return gfx::BufferFormat::BGRX_8888;
case PIXEL_FORMAT_YV12:
return gfx::BufferFormat::YVU_420;
case PIXEL_FORMAT_NV12:
return gfx::BufferFormat::YUV_420_BIPLANAR;
default:
LOG(FATAL) << "Add more cases as needed";
return gfx::BufferFormat::BGRX_8888;
}
}
} // namespace media
// 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 MEDIA_GPU_FORMAT_UTILS_H_
#define MEDIA_GPU_FORMAT_UTILS_H_
#include "media/base/video_types.h"
#include "ui/gfx/buffer_types.h"
namespace media {
VideoPixelFormat GfxBufferFormatToVideoPixelFormat(gfx::BufferFormat format);
gfx::BufferFormat VideoPixelFormatToGfxBufferFormat(
VideoPixelFormat pixel_format);
} // namespace media
#endif // MEDIA_GPU_FORMAT_UTILS_H_
......@@ -23,6 +23,7 @@
#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/bind_to_current_loop.h"
#include "media/gpu/accelerated_video_decoder.h"
#include "media/gpu/format_utils.h"
#include "media/gpu/h264_decoder.h"
#include "media/gpu/vaapi_picture.h"
#include "media/gpu/vp8_decoder.h"
......@@ -706,24 +707,6 @@ void VaapiVideoDecodeAccelerator::InitiateSurfaceSetChange(size_t num_pics,
TryFinishSurfaceSetChange();
}
static VideoPixelFormat BufferFormatToVideoPixelFormat(
gfx::BufferFormat format) {
switch (format) {
case gfx::BufferFormat::BGRX_8888:
return PIXEL_FORMAT_XRGB;
case gfx::BufferFormat::BGRA_8888:
return PIXEL_FORMAT_ARGB;
case gfx::BufferFormat::YVU_420:
return PIXEL_FORMAT_YV12;
default:
LOG(FATAL) << "Add more cases as needed";
return PIXEL_FORMAT_UNKNOWN;
}
}
void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
DCHECK(task_runner_->BelongsToCurrentThread());
......@@ -763,7 +746,7 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
VLOGF(2) << "Requesting " << requested_num_pics_
<< " pictures of size: " << requested_pic_size_.ToString();
VideoPixelFormat format = BufferFormatToVideoPixelFormat(output_format_);
VideoPixelFormat format = GfxBufferFormatToVideoPixelFormat(output_format_);
task_runner_->PostTask(
FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_,
requested_num_pics_, format, 1, requested_pic_size_,
......
......@@ -61,6 +61,7 @@
#include "media/base/test_data_util.h"
#include "media/gpu/fake_video_decode_accelerator.h"
#include "media/gpu/features.h"
#include "media/gpu/format_utils.h"
#include "media/gpu/gpu_video_decode_accelerator_factory.h"
#include "media/gpu/rendering_helper.h"
#include "media/gpu/video_accelerator_unittest_helpers.h"
......@@ -340,23 +341,6 @@ scoped_refptr<TextureRef> TextureRef::Create(
return base::WrapRefCounted(new TextureRef(texture_id, no_longer_needed_cb));
}
#if defined(OS_CHROMEOS)
gfx::BufferFormat VideoPixelFormatToGfxBufferFormat(
VideoPixelFormat pixel_format) {
switch (pixel_format) {
case VideoPixelFormat::PIXEL_FORMAT_ARGB:
return gfx::BufferFormat::BGRA_8888;
case VideoPixelFormat::PIXEL_FORMAT_XRGB:
return gfx::BufferFormat::BGRX_8888;
case VideoPixelFormat::PIXEL_FORMAT_NV12:
return gfx::BufferFormat::YUV_420_BIPLANAR;
default:
LOG_ASSERT(false) << "Unknown VideoPixelFormat";
return gfx::BufferFormat::BGRX_8888;
}
}
#endif
// static
scoped_refptr<TextureRef> TextureRef::CreatePreallocated(
uint32_t texture_id,
......
......@@ -34,6 +34,14 @@ class NativePixmap : public base::RefCountedThreadSafe<NativePixmap> {
virtual gfx::BufferFormat GetBufferFormat() const = 0;
virtual gfx::Size GetBufferSize() const = 0;
// Return an id that is guaranteed to be unique and equal for all instances
// of this NativePixmap backed by the same buffer, for the duration of its
// lifetime. If such id cannot be generated, 0 (an invalid id) is returned.
//
// TODO(posciak): crbug.com/771863, remove this once a different mechanism
// for protected shared memory buffers is implemented.
virtual uint32_t GetUniqueId() const = 0;
// Sets the overlay plane to switch to at the next page flip.
// |widget| specifies the screen to display this overlay plane on.
// |plane_z_order| specifies the stacking order of the plane relative to the
......
......@@ -63,6 +63,7 @@ class CastPixmap : public gfx::NativePixmap {
return gfx::BufferFormat::BGRA_8888;
}
gfx::Size GetBufferSize() const override { return gfx::Size(); }
uint32_t GetUniqueId() const override { return 0; }
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int plane_z_order,
......
......@@ -261,11 +261,11 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds(
// Try to use scanout if supported.
int gbm_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
bool try_scanout =
gbm_device_is_format_supported(gbm->device(), format, gbm_flags);
if (!gbm_device_is_format_supported(gbm->device(), format, gbm_flags))
gbm_flags &= ~GBM_BO_USE_SCANOUT;
gbm_bo* bo = nullptr;
if (try_scanout) {
if (gbm_device_is_format_supported(gbm->device(), format, gbm_flags)) {
struct gbm_import_fd_planar_data fd_data;
fd_data.width = size.width();
fd_data.height = size.height();
......@@ -287,8 +287,6 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds(
LOG(ERROR) << "nullptr returned from gbm_bo_import";
return nullptr;
}
} else {
gbm_flags &= ~GBM_BO_USE_SCANOUT;
}
scoped_refptr<GbmBuffer> buffer(new GbmBuffer(gbm, bo, format, gbm_flags, 0,
......@@ -365,6 +363,10 @@ gfx::Size GbmPixmap::GetBufferSize() const {
return buffer_->GetSize();
}
uint32_t GbmPixmap::GetUniqueId() const {
return buffer_->GetHandle();
}
bool GbmPixmap::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int plane_z_order,
gfx::OverlayTransform plane_transform,
......
......@@ -119,6 +119,7 @@ class GbmPixmap : public gfx::NativePixmap {
uint64_t GetDmaBufModifier(size_t plane) const override;
gfx::BufferFormat GetBufferFormat() const override;
gfx::Size GetBufferSize() const override;
uint32_t GetUniqueId() const override;
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int plane_z_order,
gfx::OverlayTransform plane_transform,
......
......@@ -160,7 +160,7 @@ scoped_refptr<gfx::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
}
scoped_refptr<gfx::NativePixmap>
GbmSurfaceFactory::CreateNativePixmapFromHandle(
GbmSurfaceFactory::CreateNativePixmapFromHandleInternal(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
......@@ -176,7 +176,6 @@ GbmSurfaceFactory::CreateNativePixmapFromHandle(
}
std::vector<gfx::NativePixmapPlane> planes;
for (const auto& plane : handle.planes) {
planes.push_back(plane);
}
......@@ -185,7 +184,44 @@ GbmSurfaceFactory::CreateNativePixmapFromHandle(
widget, size, format, std::move(scoped_fds), planes);
if (!buffer)
return nullptr;
return base::MakeRefCounted<GbmPixmap>(this, buffer);
}
scoped_refptr<gfx::NativePixmap>
GbmSurfaceFactory::CreateNativePixmapFromHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) {
// Query the external service (if available), whether it recognizes this
// NativePixmapHandle, and whether it can provide a corresponding NativePixmap
// backing it. If so, the handle is consumed. Otherwise, the handle remains
// valid and can be further importer by standard means.
if (!get_protected_native_pixmap_callback_.is_null()) {
auto protected_pixmap = get_protected_native_pixmap_callback_.Run(handle);
if (protected_pixmap)
return protected_pixmap;
}
return CreateNativePixmapFromHandleInternal(widget, size, format, handle);
}
scoped_refptr<gfx::NativePixmap>
GbmSurfaceFactory::CreateNativePixmapForProtectedBufferHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) {
// Create a new NativePixmap without querying the external service for any
// existing mappings.
return CreateNativePixmapFromHandleInternal(widget, size, format, handle);
}
void GbmSurfaceFactory::SetGetProtectedNativePixmapDelegate(
const GetProtectedNativePixmapCallback&
get_protected_native_pixmap_callback) {
get_protected_native_pixmap_callback_ = get_protected_native_pixmap_callback;
}
} // namespace ui
......@@ -50,8 +50,22 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) override;
void SetGetProtectedNativePixmapDelegate(
const GetProtectedNativePixmapCallback&
get_protected_native_pixmap_callback) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmapForProtectedBufferHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) override;
private:
scoped_refptr<gfx::NativePixmap> CreateNativePixmapFromHandleInternal(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle);
std::unique_ptr<GLOzone> egl_implementation_;
std::unique_ptr<GLOzone> osmesa_implementation_;
......@@ -61,6 +75,8 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
std::map<gfx::AcceleratedWidget, GbmSurfaceless*> widget_to_surface_map_;
GetProtectedNativePixmapCallback get_protected_native_pixmap_callback_;
DISALLOW_COPY_AND_ASSIGN(GbmSurfaceFactory);
};
......
......@@ -83,6 +83,7 @@ class TestPixmap : public gfx::NativePixmap {
uint64_t GetDmaBufModifier(size_t plane) const override { return 0; }
gfx::BufferFormat GetBufferFormat() const override { return format_; }
gfx::Size GetBufferSize() const override { return gfx::Size(); }
uint32_t GetUniqueId() const override { return 0; }
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int plane_z_order,
gfx::OverlayTransform plane_transform,
......
......@@ -52,4 +52,17 @@ SurfaceFactoryOzone::CreateNativePixmapFromHandle(
return nullptr;
}
scoped_refptr<gfx::NativePixmap>
SurfaceFactoryOzone::CreateNativePixmapForProtectedBufferHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle) {
return nullptr;
}
void SurfaceFactoryOzone::SetGetProtectedNativePixmapDelegate(
const GetProtectedNativePixmapCallback&
get_protected_native_pixmap_callback) {}
} // namespace ui
......@@ -99,6 +99,38 @@ class OZONE_BASE_EXPORT SurfaceFactoryOzone {
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle);
// A temporary solution that allows protected NativePixmap management to be
// handled outside the Ozone platform (crbug.com/771863).
// The current implementation uses dummy NativePixmaps as transparent handles
// to separate NativePixmaps with actual contents. This method takes
// a NativePixmapHandle to such a dummy pixmap, and creates a NativePixmap
// instance for it.
virtual scoped_refptr<gfx::NativePixmap>
CreateNativePixmapForProtectedBufferHandle(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
const gfx::NativePixmapHandle& handle);
// This callback can be used by implementations of this interface to query
// for a NativePixmap for the given NativePixmapHandle, instead of importing
// it via standard means. This happens if an external service is maintaining
// a separate mapping of NativePixmapHandles to NativePixmaps.
// If this callback returns non-nullptr, the returned NativePixmap should
// be used instead of the NativePixmap that would have been produced by the
// standard, implementation-specific NativePixmapHandle import mechanism.
using GetProtectedNativePixmapCallback =
base::Callback<scoped_refptr<gfx::NativePixmap>(
const gfx::NativePixmapHandle&)>;
// Called by an external service to set the GetProtectedNativePixmapCallback,
// to be used by the implementation when importing NativePixmapHandles.
// TODO(posciak): crbug.com/778555, move this to platform-specific
// implementation(s) and make protected pixmap handling transparent to the
// clients of this interface, removing the need for this callback.
virtual void SetGetProtectedNativePixmapDelegate(
const GetProtectedNativePixmapCallback&
get_protected_native_pixmap_callback);
protected:
SurfaceFactoryOzone();
virtual ~SurfaceFactoryOzone();
......
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