blob: 9ea3659a25ab815cc4a7b12d910a58ea37f0ed49 [file] [log] [blame]
// Copyright 2018 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/gfx/linux/test/mock_gbm_device.h"
#include <xf86drm.h>
#include <memory>
#include <utility>
#include "base/check_op.h"
#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/numerics/safe_math.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/linux/gbm_buffer.h"
namespace ui {
namespace {
base::ScopedFD MakeFD() {
base::FilePath temp_path;
if (!base::CreateTemporaryFile(&temp_path))
return {};
auto file =
base::File(temp_path, base::File::FLAG_READ | base::File::FLAG_WRITE |
base::File::FLAG_CREATE_ALWAYS);
return base::ScopedFD(file.TakePlatformFile());
}
class MockGbmBuffer final : public ui::GbmBuffer {
public:
MockGbmBuffer(uint32_t format,
uint32_t flags,
uint64_t modifier,
const gfx::Size& size,
std::vector<gfx::NativePixmapPlane> planes,
std::vector<uint32_t> handles)
: format_(format),
format_modifier_(modifier),
flags_(flags),
size_(size),
planes_(std::move(planes)),
handles_(std::move(handles)) {}
MockGbmBuffer(const MockGbmBuffer&) = delete;
MockGbmBuffer& operator=(const MockGbmBuffer&) = delete;
~MockGbmBuffer() override = default;
uint32_t GetFormat() const override { return format_; }
uint64_t GetFormatModifier() const override { return format_modifier_; }
uint32_t GetFlags() const override { return flags_; }
gfx::Size GetSize() const override { return size_; }
gfx::BufferFormat GetBufferFormat() const override {
return ui::GetBufferFormatFromFourCCFormat(format_);
}
bool AreFdsValid() const override {
if (planes_.empty())
return false;
for (const auto& plane : planes_) {
if (!plane.fd.is_valid())
return false;
}
return true;
}
size_t GetNumPlanes() const override { return planes_.size(); }
int GetPlaneFd(size_t plane) const override {
return planes_[plane].fd.get();
}
uint32_t GetPlaneStride(size_t plane) const override {
DCHECK_LT(plane, planes_.size());
return planes_[plane].stride;
}
size_t GetPlaneOffset(size_t plane) const override {
DCHECK_LT(plane, planes_.size());
return planes_[plane].offset;
}
size_t GetPlaneSize(size_t plane) const override {
DCHECK_LT(plane, planes_.size());
return static_cast<size_t>(planes_[plane].size);
}
uint32_t GetPlaneHandle(size_t plane) const override {
DCHECK_LT(plane, planes_.size());
return handles_[plane];
}
uint32_t GetHandle() const override { return GetPlaneHandle(0); }
gfx::NativePixmapHandle ExportHandle() const override {
NOTIMPLEMENTED();
return gfx::NativePixmapHandle();
}
sk_sp<SkSurface> GetSurface() override { return nullptr; }
private:
uint32_t format_ = 0;
uint64_t format_modifier_ = 0;
uint32_t flags_ = 0;
gfx::Size size_;
std::vector<gfx::NativePixmapPlane> planes_;
std::vector<uint32_t> handles_;
};
} // namespace
MockGbmDevice::MockGbmDevice() = default;
MockGbmDevice::~MockGbmDevice() = default;
void MockGbmDevice::set_allocation_failure(bool should_fail_allocations) {
should_fail_allocations_ = should_fail_allocations;
}
std::vector<uint64_t> MockGbmDevice::GetSupportedModifiers() const {
return supported_modifiers_;
}
std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBuffer(uint32_t format,
const gfx::Size& size,
uint32_t flags) {
if (should_fail_allocations_)
return nullptr;
return CreateBufferWithModifiers(format, size, flags, {});
}
std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferWithModifiers(
uint32_t format,
const gfx::Size& size,
uint32_t flags,
const std::vector<uint64_t>& modifiers) {
if (should_fail_allocations_)
return nullptr;
uint32_t bytes_per_pixel;
switch (format) {
case DRM_FORMAT_XRGB8888:
case DRM_FORMAT_ARGB8888:
case DRM_FORMAT_ARGB2101010:
case DRM_FORMAT_ABGR2101010:
bytes_per_pixel = 4;
break;
case DRM_FORMAT_NV12:
bytes_per_pixel = 2;
break;
default:
NOTREACHED() << "Unsupported format: " << format;
return nullptr;
}
uint64_t format_modifier =
modifiers.empty() ? DRM_FORMAT_MOD_NONE : modifiers.back();
if (!base::Contains(supported_modifiers_, format_modifier)) {
PLOG(ERROR) << "Unsupported format modifier: " << std::hex
<< format_modifier;
return nullptr;
}
uint32_t width = base::checked_cast<uint32_t>(size.width());
uint32_t height = base::checked_cast<uint32_t>(size.height());
uint32_t plane_stride = base::CheckMul(bytes_per_pixel, width).ValueOrDie();
uint32_t plane_size = base::CheckMul(plane_stride, height).ValueOrDie();
uint32_t plane_offset = 0;
std::vector<gfx::NativePixmapPlane> planes;
planes.emplace_back(plane_stride, plane_offset, plane_size, MakeFD());
std::vector<uint32_t> handles;
handles.push_back(next_handle_++);
return std::make_unique<MockGbmBuffer>(format, flags, format_modifier, size,
std::move(planes), std::move(handles));
}
std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferFromHandle(
uint32_t format,
const gfx::Size& size,
gfx::NativePixmapHandle handle) {
NOTREACHED();
return nullptr;
}
} // namespace ui