blob: 9f8a49d10dd0e70b3693cfc9e04aa7c7e5a42071 [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_overlay_validator.h"
#include <drm_fourcc.h>
#include <memory>
#include <utility>
#include "base/files/platform_file.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/common/linux/gbm_buffer.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
namespace ui {
namespace {
scoped_refptr<DrmFramebuffer> GetBufferForPageFlipTest(
const scoped_refptr<DrmDevice>& drm_device,
const gfx::Size& size,
uint32_t format,
std::vector<scoped_refptr<DrmFramebuffer>>* reusable_buffers) {
// Check if we can re-use existing buffers.
for (const auto& buffer : *reusable_buffers) {
if (buffer->framebuffer_pixel_format() == format &&
buffer->size() == size) {
return buffer;
}
}
// TODO(dcastagna): use the right modifiers.
std::unique_ptr<GbmBuffer> buffer =
drm_device->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT);
if (!buffer)
return nullptr;
scoped_refptr<DrmFramebuffer> drm_framebuffer =
DrmFramebuffer::AddFramebuffer(drm_device, buffer.get());
if (!drm_framebuffer)
return nullptr;
reusable_buffers->push_back(drm_framebuffer);
return drm_framebuffer;
}
} // namespace
DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) : window_(window) {}
DrmOverlayValidator::~DrmOverlayValidator() {}
std::vector<OverlayCheckReturn_Params> DrmOverlayValidator::TestPageFlip(
const std::vector<OverlayCheck_Params>& params,
const DrmOverlayPlaneList& last_used_planes) {
std::vector<OverlayCheckReturn_Params> returns(params.size());
HardwareDisplayController* controller = window_->GetController();
if (!controller) {
// The controller is not yet installed.
for (auto& param : returns)
param.status = OVERLAY_STATUS_NOT;
return returns;
}
DrmOverlayPlaneList test_list;
std::vector<scoped_refptr<DrmFramebuffer>> reusable_buffers;
scoped_refptr<DrmDevice> drm = controller->GetDrmDevice();
for (const auto& plane : last_used_planes)
reusable_buffers.push_back(plane.buffer);
for (size_t i = 0; i < params.size(); ++i) {
if (!params[i].is_overlay_candidate) {
returns[i].status = OVERLAY_STATUS_NOT;
continue;
}
scoped_refptr<DrmFramebuffer> buffer = GetBufferForPageFlipTest(
drm, params[i].buffer_size,
params[i].is_opaque
? GetFourCCFormatForOpaqueFramebuffer(params[i].format)
: GetFourCCFormatFromBufferFormat(params[i].format),
&reusable_buffers);
DrmOverlayPlane plane(buffer, params[i].plane_z_order, params[i].transform,
params[i].display_rect, params[i].crop_rect,
/* enable_blend */ true, /* gpu_fence */ nullptr);
test_list.push_back(std::move(plane));
if (buffer && controller->TestPageFlip(test_list)) {
returns[i].status = OVERLAY_STATUS_ABLE;
} else {
// If test failed here, platform cannot support this configuration
// with current combination of layers. This is usually the case when this
// plane has requested post processing capability which needs additional
// hardware resources and they might be already in use by other planes.
// For example this plane has requested scaling capabilities and all
// available scalars are already in use by other planes.
returns[i].status = OVERLAY_STATUS_NOT;
test_list.pop_back();
}
}
return returns;
}
} // namespace ui