blob: 6e173b553f2bc8c12608a96f1fb746d898314cdd [file] [log] [blame]
// Copyright 2015 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 "ui/ozone/platform/drm/gpu/drm_thread.h"
#include <utility>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
#include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_buffer.h"
#include "ui/ozone/platform/drm/gpu/gbm_device.h"
#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
#include "ui/ozone/platform/drm/gpu/proxy_helpers.h"
#include "ui/ozone/platform/drm/gpu/screen_manager.h"
#include "ui/ozone/public/ozone_switches.h"
namespace ui {
namespace {
class GbmBufferGenerator : public ScanoutBufferGenerator {
public:
GbmBufferGenerator() {}
~GbmBufferGenerator() override {}
// ScanoutBufferGenerator:
scoped_refptr<ScanoutBuffer> Create(const scoped_refptr<DrmDevice>& drm,
gfx::BufferFormat format,
const gfx::Size& size) override {
scoped_refptr<GbmDevice> gbm(static_cast<GbmDevice*>(drm.get()));
return GbmBuffer::CreateBuffer(gbm, format, size,
gfx::BufferUsage::SCANOUT);
}
protected:
DISALLOW_COPY_AND_ASSIGN(GbmBufferGenerator);
};
class GbmDeviceGenerator : public DrmDeviceGenerator {
public:
GbmDeviceGenerator(bool use_atomic) : use_atomic_(use_atomic) {}
~GbmDeviceGenerator() override {}
// DrmDeviceGenerator:
scoped_refptr<DrmDevice> CreateDevice(const base::FilePath& path,
base::File file,
bool is_primary_device) override {
scoped_refptr<DrmDevice> drm =
new GbmDevice(path, std::move(file), is_primary_device);
if (drm->Initialize(use_atomic_))
return drm;
return nullptr;
}
private:
bool use_atomic_;
DISALLOW_COPY_AND_ASSIGN(GbmDeviceGenerator);
};
} // namespace
DrmThread::DrmThread() : base::Thread("DrmThread") {}
DrmThread::~DrmThread() {
Stop();
}
void DrmThread::Start() {
base::Thread::Options thread_options;
thread_options.message_loop_type = base::MessageLoop::TYPE_IO;
thread_options.priority = base::ThreadPriority::DISPLAY;
if (!StartWithOptions(thread_options))
LOG(FATAL) << "Failed to create DRM thread";
}
void DrmThread::Init() {
bool use_atomic = false;
#if defined(USE_DRM_ATOMIC)
use_atomic = true;
#endif
device_manager_.reset(new DrmDeviceManager(
base::WrapUnique(new GbmDeviceGenerator(use_atomic))));
buffer_generator_.reset(new GbmBufferGenerator());
screen_manager_.reset(new ScreenManager(buffer_generator_.get()));
display_manager_.reset(
new DrmGpuDisplayManager(screen_manager_.get(), device_manager_.get()));
}
void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
scoped_refptr<GbmBuffer>* buffer) {
scoped_refptr<GbmDevice> gbm =
static_cast<GbmDevice*>(device_manager_->GetDrmDevice(widget).get());
DCHECK(gbm);
*buffer = GbmBuffer::CreateBuffer(gbm, format, size, usage);
}
void DrmThread::CreateBufferFromFds(const gfx::Size& size,
gfx::BufferFormat format,
std::vector<base::ScopedFD>&& fds,
std::vector<int> strides,
std::vector<int> offsets,
scoped_refptr<GbmBuffer>* buffer) {
scoped_refptr<GbmDevice> gbm =
static_cast<GbmDevice*>(device_manager_->GetPrimaryDrmDevice().get());
DCHECK(gbm);
*buffer = GbmBuffer::CreateBufferFromFds(gbm, format, size, std::move(fds),
strides, offsets);
}
void DrmThread::GetScanoutFormats(
gfx::AcceleratedWidget widget,
std::vector<gfx::BufferFormat>* scanout_formats) {
display_manager_->GetScanoutFormats(widget, scanout_formats);
}
void DrmThread::SchedulePageFlip(gfx::AcceleratedWidget widget,
const std::vector<OverlayPlane>& planes,
const SwapCompletionCallback& callback) {
DrmWindow* window = screen_manager_->GetWindow(widget);
if (window)
window->SchedulePageFlip(planes, callback);
else
callback.Run(gfx::SwapResult::SWAP_ACK);
}
void DrmThread::GetVSyncParameters(
gfx::AcceleratedWidget widget,
const gfx::VSyncProvider::UpdateVSyncCallback& callback) {
DrmWindow* window = screen_manager_->GetWindow(widget);
// No need to call the callback if there isn't a window since the vsync
// provider doesn't require the callback to be called if there isn't a vsync
// data source.
if (window)
window->GetVSyncParameters(callback);
}
void DrmThread::CreateWindow(gfx::AcceleratedWidget widget) {
std::unique_ptr<DrmWindow> window(
new DrmWindow(widget, device_manager_.get(), screen_manager_.get()));
window->Initialize(buffer_generator_.get());
screen_manager_->AddWindow(widget, std::move(window));
}
void DrmThread::DestroyWindow(gfx::AcceleratedWidget widget) {
std::unique_ptr<DrmWindow> window = screen_manager_->RemoveWindow(widget);
window->Shutdown();
}
void DrmThread::SetWindowBounds(gfx::AcceleratedWidget widget,
const gfx::Rect& bounds) {
screen_manager_->GetWindow(widget)->SetBounds(bounds);
}
void DrmThread::SetCursor(gfx::AcceleratedWidget widget,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location,
int frame_delay_ms) {
screen_manager_->GetWindow(widget)
->SetCursor(bitmaps, location, frame_delay_ms);
}
void DrmThread::MoveCursor(gfx::AcceleratedWidget widget,
const gfx::Point& location) {
screen_manager_->GetWindow(widget)->MoveCursor(location);
}
void DrmThread::CheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
const std::vector<OverlayCheck_Params>& overlays,
const base::Callback<void(gfx::AcceleratedWidget,
const std::vector<OverlayCheck_Params>&)>&
callback) {
callback.Run(widget,
screen_manager_->GetWindow(widget)->TestPageFlip(overlays));
}
void DrmThread::RefreshNativeDisplays(
const base::Callback<void(const std::vector<DisplaySnapshot_Params>&)>&
callback) {
callback.Run(display_manager_->GetDisplays());
}
void DrmThread::ConfigureNativeDisplay(
int64_t id,
const DisplayMode_Params& mode,
const gfx::Point& origin,
const base::Callback<void(int64_t, bool)>& callback) {
callback.Run(id, display_manager_->ConfigureDisplay(id, mode, origin));
}
void DrmThread::DisableNativeDisplay(
int64_t id,
const base::Callback<void(int64_t, bool)>& callback) {
callback.Run(id, display_manager_->DisableDisplay(id));
}
void DrmThread::TakeDisplayControl(const base::Callback<void(bool)>& callback) {
callback.Run(display_manager_->TakeDisplayControl());
}
void DrmThread::RelinquishDisplayControl(
const base::Callback<void(bool)>& callback) {
display_manager_->RelinquishDisplayControl();
callback.Run(true);
}
void DrmThread::AddGraphicsDevice(const base::FilePath& path,
const base::FileDescriptor& fd) {
device_manager_->AddDrmDevice(path, fd);
}
void DrmThread::RemoveGraphicsDevice(const base::FilePath& path) {
device_manager_->RemoveDrmDevice(path);
}
void DrmThread::GetHDCPState(
int64_t display_id,
const base::Callback<void(int64_t, bool, HDCPState)>& callback) {
HDCPState state = HDCP_STATE_UNDESIRED;
bool success = display_manager_->GetHDCPState(display_id, &state);
callback.Run(display_id, success, state);
}
void DrmThread::SetHDCPState(
int64_t display_id,
HDCPState state,
const base::Callback<void(int64_t, bool)>& callback) {
callback.Run(display_id, display_manager_->SetHDCPState(display_id, state));
}
void DrmThread::SetColorCorrection(
int64_t display_id,
const std::vector<GammaRampRGBEntry>& degamma_lut,
const std::vector<GammaRampRGBEntry>& gamma_lut,
const std::vector<float>& correction_matrix) {
display_manager_->SetColorCorrection(display_id, degamma_lut, gamma_lut,
correction_matrix);
}
} // namespace ui