Commit 631cb004 authored by Mark Yacoub's avatar Mark Yacoub Committed by Chromium LUCI CQ

Fallback to Linear Modifiers if Preferred Modifiers fail.

Test-Modeset with preferred modifiers.
If it the test passes, save the preferred modifiers to use for full modeset.
If it fails, try testing with linear modifiers for every controller.
Use empty modifiers list if the platform doesn't support preferred modifiers list.

This enables us to launch Intel Rendering Buffer Compression.
http://go/cros-intelrbc

BUG=979736,1082882

TEST: RBC enabled on (4K eDP with 4K external) and (4K eDP and 2 external monitors), zork, and nautilus
Change-Id: I7698d2cc9f13e5293eb0f6579dee775314988037
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2567263Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Commit-Queue: Mark Yacoub <markyacoub@google.com>
Cr-Commit-Position: refs/heads/master@{#834389}
parent 9790b36c
......@@ -46,7 +46,7 @@ scoped_refptr<DrmFramebuffer> GetBufferForPageFlipTest(
// flip commits.
std::vector<uint64_t> modifiers =
is_0th_plane
? drm_window->GetController()->GetFormatModifiers(fourcc_format)
? drm_window->GetController()->GetSupportedModifiers(fourcc_format)
: std::vector<uint64_t>();
// Check if we can re-use existing buffers.
......@@ -86,7 +86,7 @@ scoped_refptr<DrmFramebuffer> GetBufferForPageFlipTest(
DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) : window_(window) {}
DrmOverlayValidator::~DrmOverlayValidator() {}
DrmOverlayValidator::~DrmOverlayValidator() = default;
OverlayStatusList DrmOverlayValidator::TestPageFlip(
const OverlaySurfaceCandidateList& params,
......
......@@ -142,7 +142,7 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
std::vector<uint64_t> modifiers;
if (window && window->GetController() && !(flags & GBM_BO_USE_LINEAR) &&
!(client_flags & GbmPixmap::kFlagNoModifiers)) {
modifiers = window->GetController()->GetFormatModifiers(fourcc_format);
modifiers = window->GetController()->GetSupportedModifiers(fourcc_format);
}
CreateBufferWithGbmFlags(drm, fourcc_format, size, framebuffer_size, flags,
......
......@@ -31,11 +31,9 @@ DrmWindow::DrmWindow(gfx::AcceleratedWidget widget,
ScreenManager* screen_manager)
: widget_(widget),
device_manager_(device_manager),
screen_manager_(screen_manager) {
}
screen_manager_(screen_manager) {}
DrmWindow::~DrmWindow() {
}
DrmWindow::~DrmWindow() = default;
void DrmWindow::Initialize() {
TRACE_EVENT1("drm", "DrmWindow::Initialize", "widget", widget_);
......@@ -97,7 +95,10 @@ void DrmWindow::SchedulePageFlip(
if (controller_) {
const DrmDevice* drm = controller_->GetDrmDevice().get();
for (const auto& plane : planes) {
if (plane.buffer && plane.buffer->drm_device() != drm) {
if (plane.buffer &&
(plane.buffer->drm_device() != drm ||
controller_->IsModifierBad(plane.buffer->framebuffer_pixel_format(),
plane.buffer->format_modifier()))) {
// Although |force_buffer_reallocation_| is set to true during window
// bounds update, this may still be needed because of in-flight buffers.
force_buffer_reallocation_ = true;
......
......@@ -19,6 +19,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
......@@ -200,17 +201,16 @@ bool HardwareDisplayController::ScheduleOrTestPageFlip(
}
std::vector<uint64_t> HardwareDisplayController::GetFormatModifiers(
uint32_t format) const {
std::vector<uint64_t> modifiers;
uint32_t fourcc_format) const {
if (crtc_controllers_.empty())
return modifiers;
return std::vector<uint64_t>();
modifiers = crtc_controllers_[0]->GetFormatModifiers(format);
std::vector<uint64_t> modifiers =
crtc_controllers_[0]->GetFormatModifiers(fourcc_format);
for (size_t i = 1; i < crtc_controllers_.size(); ++i) {
std::vector<uint64_t> other =
crtc_controllers_[i]->GetFormatModifiers(format);
crtc_controllers_[i]->GetFormatModifiers(fourcc_format);
std::vector<uint64_t> intersection;
std::set_intersection(modifiers.begin(), modifiers.end(), other.begin(),
......@@ -221,11 +221,27 @@ std::vector<uint64_t> HardwareDisplayController::GetFormatModifiers(
return modifiers;
}
std::vector<uint64_t>
HardwareDisplayController::GetFormatModifiersForModesetting(
std::vector<uint64_t> HardwareDisplayController::GetSupportedModifiers(
uint32_t fourcc_format) const {
const auto& modifiers = GetFormatModifiers(fourcc_format);
if (preferred_format_modifier_.empty())
return std::vector<uint64_t>();
auto it = preferred_format_modifier_.find(fourcc_format);
if (it != preferred_format_modifier_.end()) {
return std::vector<uint64_t>{it->second};
}
return GetFormatModifiers(fourcc_format);
}
std::vector<uint64_t>
HardwareDisplayController::GetFormatModifiersForTestModeset(
uint32_t fourcc_format) {
// If we're about to test, clear the current preferred modifier.
preferred_format_modifier_.clear();
std::vector<uint64_t> filtered_modifiers;
const auto& modifiers = GetFormatModifiers(fourcc_format);
for (auto modifier : modifiers) {
// AFBC for modeset buffers doesn't work correctly, as we can't fill it with
// a valid AFBC buffer. For now, don't use AFBC for modeset buffers.
......@@ -238,6 +254,31 @@ HardwareDisplayController::GetFormatModifiersForModesetting(
return filtered_modifiers;
}
void HardwareDisplayController::UpdatePreferredModiferForFormat(
gfx::BufferFormat buffer_format,
uint64_t modifier) {
uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(buffer_format);
base::InsertOrAssign(preferred_format_modifier_, fourcc_format, modifier);
uint32_t opaque_fourcc_format =
GetFourCCFormatForOpaqueFramebuffer(buffer_format);
base::InsertOrAssign(preferred_format_modifier_, opaque_fourcc_format,
modifier);
}
bool HardwareDisplayController::IsModifierBad(uint32_t pixel_format,
uint64_t modifier) const {
if (preferred_format_modifier_.empty())
return false;
// If we don't have a format saved, we can't tell if it's bad.
auto it = preferred_format_modifier_.find(pixel_format);
if (it == preferred_format_modifier_.end())
return false;
return it->second != modifier;
}
void HardwareDisplayController::MoveCursor(const gfx::Point& location) {
cursor_location_ = location;
UpdateCursorLocation();
......
......@@ -14,9 +14,11 @@
#include <vector>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
......@@ -128,17 +130,21 @@ class HardwareDisplayController {
// doesn't change any state.
bool TestPageFlip(const DrmOverlayPlaneList& plane_list);
// Return the supported modifiers for |fourcc_format| for this
// controller.
std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format) const;
// Return the supported modifiers for |fourcc_format| for this controller.
std::vector<uint64_t> GetSupportedModifiers(uint32_t fourcc_format) const;
// Return the supported modifiers for |fourcc_format| for this
// controller to be used for modeset buffers. Currently, this only exists
// because we can't provide valid AFBC buffers during modeset.
// See https://crbug.com/852675
// TODO: Remove this.
std::vector<uint64_t> GetFormatModifiersForModesetting(
uint32_t fourcc_format) const;
std::vector<uint64_t> GetFormatModifiersForTestModeset(
uint32_t fourcc_format);
void UpdatePreferredModiferForFormat(gfx::BufferFormat buffer_format,
uint64_t modifier);
bool IsModifierBad(uint32_t pixel_format, uint64_t modifier) const;
// Moves the hardware cursor to |location|.
void MoveCursor(const gfx::Point& location);
......@@ -189,6 +195,8 @@ class HardwareDisplayController {
void ResetCursor();
void DisableCursor();
std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format) const;
HardwareDisplayPlaneList owned_hardware_planes_;
// Stores the CRTC configuration. This is used to identify monitors and
......@@ -207,6 +215,11 @@ class HardwareDisplayController {
int cursor_frontbuffer_ = 0;
DrmDumbBuffer* current_cursor_ = nullptr;
// Maps each fourcc_format to its preferred modifier which was generated
// through modeset-test and updated in UpdatePreferredModifierForFormat().
base::flat_map<uint32_t /*fourcc_format*/, uint64_t /*preferred_modifier*/>
preferred_format_modifier_;
base::WeakPtrFactory<HardwareDisplayController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
......
......@@ -37,7 +37,7 @@ namespace {
bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
HardwareDisplayController* controller,
SkSurface* surface,
uint32_t fourcc_format) {
const std::vector<uint64_t>& modifiers) {
DCHECK(!controller->crtc_controllers().empty());
CrtcController* first_crtc = controller->crtc_controllers()[0].get();
ScopedDrmCrtcPtr saved_crtc(drm->GetCrtc(first_crtc->crtc()));
......@@ -46,7 +46,6 @@ bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
return false;
}
const auto& modifiers = controller->GetFormatModifiers(fourcc_format);
for (const uint64_t modifier : modifiers) {
// A value of 0 means DRM_FORMAT_MOD_NONE. If the CRTC has any other
// modifier (tiling, compression, etc.) we can't read the fb and assume it's
......@@ -94,13 +93,6 @@ CrtcController* GetCrtcController(HardwareDisplayController* controller,
return nullptr;
}
std::vector<uint64_t> GetModifiersForPrimaryFormat(
HardwareDisplayController* controller) {
gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format);
return controller->GetFormatModifiersForModesetting(fourcc_format);
}
bool AreAllStatusesTrue(base::flat_map<int64_t, bool>& display_statuses) {
auto it = find_if(display_statuses.begin(), display_statuses.end(),
[](const auto status) { return status.second == false; });
......@@ -259,21 +251,73 @@ base::flat_map<int64_t, bool> ScreenManager::ConfigureDisplayControllers(
base::flat_map<int64_t, bool> ScreenManager::TestAndModeset(
const ControllerConfigsList& controllers_params) {
if (!TestModeset(controllers_params)) {
TRACE_EVENT0("drm", "ScreenManager::TestAndModeset");
if (TestAndSetPreferredModifiers(controllers_params) ||
TestAndSetLinearModifier(controllers_params)) {
return Modeset(controllers_params);
}
// If we fail to test even with the base modifier, report a failure.
base::flat_map<int64_t, bool> statuses;
for (const auto& params : controllers_params)
statuses.insert(std::make_pair(params.display_id, false));
return statuses;
}
bool ScreenManager::TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params) {
TRACE_EVENT1("drm", "ScreenManager::TestAndSetPreferredModifiers",
"display_count", controllers_params.size());
CrtcPreferredModifierMap crtcs_preferred_modifier;
CommitRequest commit_request;
auto drm = controllers_params[0].drm;
for (const auto& params : controllers_params) {
auto it = FindDisplayController(params.drm, params.crtc);
DCHECK(controllers_.end() != it);
HardwareDisplayController* controller = it->get();
if (params.mode) {
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetFormatModifiersForTestModeset(fourcc_format);
DrmOverlayPlane primary_plane = GetModesetBuffer(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
modifiers);
if (!primary_plane.buffer) {
return false;
}
return Modeset(controllers_params);
crtcs_preferred_modifier[params.crtc] = std::make_pair(
modifiers.empty(), primary_plane.buffer->format_modifier());
GetModesetControllerProps(&commit_request, controller, params.origin,
*params.mode, primary_plane);
} else {
controller->GetDisableProps(&commit_request);
}
}
if (!drm->plane_manager()->Commit(
std::move(commit_request),
DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET)) {
return false;
}
SetPreferredModifiers(controllers_params, crtcs_preferred_modifier);
return true;
}
bool ScreenManager::TestModeset(
bool ScreenManager::TestAndSetLinearModifier(
const ControllerConfigsList& controllers_params) {
TRACE_EVENT1("drm", "ScreenManager::TestModeset", "display_count",
controllers_params.size());
TRACE_EVENT1("drm", "ScreenManager::TestAndSetLinearModifier",
"display_count", controllers_params.size());
CrtcPreferredModifierMap crtcs_preferred_modifier;
CommitRequest commit_request;
auto drm = controllers_params[0].drm;
......@@ -282,10 +326,23 @@ bool ScreenManager::TestModeset(
DCHECK(controllers_.end() != it);
HardwareDisplayController* controller = it->get();
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetFormatModifiersForTestModeset(fourcc_format);
// Test with an empty list if no preferred modifiers are advertised.
// Platforms might not support gbm_bo_create_with_modifiers(). If the
// platform doesn't expose modifiers, do not attempt to explicitly request
// LINEAR otherwise we might CHECK() when trying to allocate buffers.
if (!modifiers.empty())
modifiers = std::vector<uint64_t>{DRM_FORMAT_MOD_LINEAR};
crtcs_preferred_modifier[params.crtc] =
std::make_pair(modifiers.empty(), DRM_FORMAT_MOD_LINEAR);
if (params.mode) {
DrmOverlayPlane primary_plane = GetModesetBuffer(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
GetModifiersForPrimaryFormat(controller));
modifiers);
if (!primary_plane.buffer)
return false;
......@@ -296,9 +353,36 @@ bool ScreenManager::TestModeset(
}
}
return drm->plane_manager()->Commit(
if (!drm->plane_manager()->Commit(
std::move(commit_request),
DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET);
DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET)) {
return false;
}
SetPreferredModifiers(controllers_params, crtcs_preferred_modifier);
return true;
}
void ScreenManager::SetPreferredModifiers(
const ControllerConfigsList& controllers_params,
const CrtcPreferredModifierMap& crtcs_preferred_modifier) {
for (const auto& params : controllers_params) {
if (params.mode) {
bool was_modifiers_list_empty =
crtcs_preferred_modifier.at(params.crtc).first;
// No preferred modifiers should be saved as some platforms might not have
// bo_create_with_modifiers implemented, this will send the preferred
// modifiers list as an empty list.
if (!was_modifiers_list_empty) {
uint64_t picked_modifier =
crtcs_preferred_modifier.at(params.crtc).second;
auto it = FindDisplayController(params.drm, params.crtc);
DCHECK(*it);
it->get()->UpdatePreferredModiferForFormat(
display::DisplaySnapshot::PrimaryFormat(), picked_modifier);
}
}
}
}
base::flat_map<int64_t, bool> ScreenManager::Modeset(
......@@ -316,9 +400,14 @@ base::flat_map<int64_t, bool> ScreenManager::Modeset(
DCHECK(controllers_.end() != it);
HardwareDisplayController* controller = it->get();
uint32_t fourcc_format = GetFourCCFormatForOpaqueFramebuffer(
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetSupportedModifiers(fourcc_format);
DrmOverlayPlane primary_plane = GetModesetBuffer(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
GetModifiersForPrimaryFormat(controller));
modifiers);
if (primary_plane.buffer) {
SetDisplayControllerForEnableAndGetProps(
&commit_request, params.drm, params.crtc, params.connector,
......@@ -552,10 +641,14 @@ void ScreenManager::UpdateControllerToWindowMapping() {
// otherwise the controller may be waiting for a page flip while the window
// tries to schedule another buffer.
if (should_enable) {
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
display::DisplaySnapshot::PrimaryFormat());
std::vector<uint64_t> modifiers =
controller->GetSupportedModifiers(fourcc_format);
DrmOverlayPlane primary_plane = GetModesetBuffer(
controller,
gfx::Rect(controller->origin(), controller->GetModeSize()),
GetModifiersForPrimaryFormat(controller));
modifiers);
DCHECK(primary_plane.buffer);
CommitRequest commit_request;
......@@ -606,8 +699,7 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
sk_sp<SkSurface> surface = buffer->GetSurface();
if (!surface) {
VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer.";
} else if (!FillModesetBuffer(drm, controller, surface.get(),
buffer->GetFormat())) {
} else if (!FillModesetBuffer(drm, controller, surface.get(), modifiers)) {
// If we fail to fill the modeset buffer, clear it black to avoid displaying
// an uninitialized framebuffer.
surface->getCanvas()->clear(SK_ColorBLACK);
......
......@@ -98,6 +98,9 @@ class ScreenManager {
std::vector<std::unique_ptr<HardwareDisplayController>>;
using WidgetToWindowMap =
std::unordered_map<gfx::AcceleratedWidget, std::unique_ptr<DrmWindow>>;
using CrtcPreferredModifierMap = base::flat_map<
uint32_t /*crtc_is*/,
std::pair<bool /*modifiers_list.empty()*/, uint64_t /*picked_modifier*/>>;
// Returns an iterator into |controllers_| for the controller identified by
// (|crtc|, |connector|).
......@@ -108,7 +111,15 @@ class ScreenManager {
base::flat_map<int64_t, bool> TestAndModeset(
const ControllerConfigsList& controllers_params);
bool TestModeset(const ControllerConfigsList& controllers_params);
bool TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params);
bool TestAndSetLinearModifier(
const ControllerConfigsList& controllers_params);
// Setting the Preferred modifiers that passed from one of the Modeset Test
// functions. The preferred modifiers are used in Modeset.
void SetPreferredModifiers(
const ControllerConfigsList& controllers_params,
const CrtcPreferredModifierMap& crtcs_preferred_modifier);
base::flat_map<int64_t, bool> Modeset(
const ControllerConfigsList& controllers_params);
......
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