Commit 64d0d296 authored by Julien Isorce's avatar Julien Isorce Committed by Commit Bot

Add GetPlaneSurface to ui::GbmBuffer

There is currently a GetSurface() api but it only gives
access to the plane 0.

This new api GetPlaneSurface allows to get access to any
planes to support YUV formats.

Bug: 1043007
Test: ./out/ozone_build/ozone_unittests
Change-Id: I4116affcf168cdaeebf3b405234aa3e5f55cc30f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2032060Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Reviewed-by: default avatarMaksim Sisov <msisov@igalia.com>
Commit-Queue: Julien Isorce <julien.isorce@chromium.org>
Cr-Commit-Position: refs/heads/master@{#740986}
parent 09c111fe
...@@ -36,6 +36,7 @@ class GbmBuffer { ...@@ -36,6 +36,7 @@ class GbmBuffer {
virtual size_t GetPlaneSize(size_t plane) const = 0; virtual size_t GetPlaneSize(size_t plane) const = 0;
virtual uint32_t GetHandle() const = 0; virtual uint32_t GetHandle() const = 0;
virtual gfx::NativePixmapHandle ExportHandle() const = 0; virtual gfx::NativePixmapHandle ExportHandle() const = 0;
virtual sk_sp<SkSurface> GetPlaneSurface(size_t plane) = 0;
virtual sk_sp<SkSurface> GetSurface() = 0; virtual sk_sp<SkSurface> GetSurface() = 0;
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define GBM_MAX_PLANES 4 #define GBM_MAX_PLANES 4
#define GBM_BO_USE_TEXTURING 0 #define GBM_BO_USE_TEXTURING 0
#define GBM_BO_USE_CAMERA_READ 0
#define GBM_BO_USE_CAMERA_WRITE 0 #define GBM_BO_USE_CAMERA_WRITE 0
#define GBM_BO_USE_HW_VIDEO_DECODER 0 #define GBM_BO_USE_HW_VIDEO_DECODER 0
#define GBM_BO_USE_HW_VIDEO_ENCODER 0 #define GBM_BO_USE_HW_VIDEO_ENCODER 0
......
...@@ -33,6 +33,7 @@ class GbmDevice { ...@@ -33,6 +33,7 @@ class GbmDevice {
uint32_t format, uint32_t format,
const gfx::Size& size, const gfx::Size& size,
gfx::NativePixmapHandle handle) = 0; gfx::NativePixmapHandle handle) = 0;
virtual bool IsFormatAndUsageSupported(uint32_t format, uint32_t flags) = 0;
}; };
} // namespace ui } // namespace ui
......
...@@ -151,10 +151,13 @@ class Buffer final : public ui::GbmBuffer { ...@@ -151,10 +151,13 @@ class Buffer final : public ui::GbmBuffer {
format_modifier_(modifier), format_modifier_(modifier),
flags_(flags), flags_(flags),
size_(size), size_(size),
handle_(std::move(handle)) {} handle_(std::move(handle)),
mapped_planes_(handle_.planes.size()) {}
~Buffer() override { ~Buffer() override {
DCHECK(!mmap_data_); for (const auto& mapped_plane : mapped_planes_) {
DCHECK(!mapped_plane.mapped_data);
}
gbm_bo_destroy(bo_); gbm_bo_destroy(bo_);
} }
...@@ -203,38 +206,86 @@ class Buffer final : public ui::GbmBuffer { ...@@ -203,38 +206,86 @@ class Buffer final : public ui::GbmBuffer {
return CloneHandleForIPC(handle_); return CloneHandleForIPC(handle_);
} }
sk_sp<SkSurface> GetSurface() override { sk_sp<SkSurface> GetPlaneSurface(size_t plane) override {
CHECK(HaveGbmMap()); CHECK(HaveGbmMap());
DCHECK(!mmap_data_); DCHECK_LT(plane, handle_.planes.size());
uint32_t stride; DCHECK(!mapped_planes_[plane].mapped_data);
void* addr;
addr = const int plane_count = GetPlaneCount(bo_);
uint32_t stride = 0;
mapped_planes_.resize(plane_count);
void* mmap_data = nullptr;
void* addr =
#if defined(MINIGBM) #if defined(MINIGBM)
gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_), gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_),
GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data_, 0); GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data, plane);
#else #else
gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_), gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_),
GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data_); GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data);
addr = static_cast<uint8_t*>(addr) + GetPlaneOffset(plane);
#endif #endif
if (!addr) if (!addr)
return nullptr; return nullptr;
SkImageInfo info = mapped_planes_[plane].addr = addr;
SkImageInfo::MakeN32Premul(size_.width(), size_.height()); mapped_planes_[plane].mapped_data = mmap_data;
return SkSurface::MakeRasterDirectReleaseProc(info, addr, stride,
&Buffer::UnmapGbmBo, this); SkImageInfo info;
switch (GetBufferFormat()) {
case gfx::BufferFormat::RGBX_8888:
case gfx::BufferFormat::RGBA_8888:
case gfx::BufferFormat::BGRX_8888:
case gfx::BufferFormat::BGRA_8888:
info = SkImageInfo::MakeN32Premul(size_.width(), size_.height());
break;
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
info = SkImageInfo::Make({size_.width(), size_.height()},
kGray_8_SkColorType, kOpaque_SkAlphaType);
break;
default:
NOTREACHED();
break;
}
// TODO(crbug.com/1043007): Let SkSurface own the pixels by using
// sk_sp<SkPixelRef> so no need the call back UnmapGbmBo, neither
// mapped_planes_.
sk_sp<SkSurface> sk_surface = SkSurface::MakeRasterDirectReleaseProc(
info, addr, stride, &Buffer::UnmapGbmBo, this);
if (!sk_surface) {
UnmapGbmBo(addr, this);
return nullptr;
}
return sk_surface;
} }
sk_sp<SkSurface> GetSurface() override { return GetPlaneSurface(0); }
private: private:
static void UnmapGbmBo(void* pixels, void* context) { static void UnmapGbmBo(void* pixels, void* context) {
CHECK(HaveGbmMap()); CHECK(HaveGbmMap());
Buffer* buffer = static_cast<Buffer*>(context); Buffer* buffer = static_cast<Buffer*>(context);
gbm_bo_unmap(buffer->bo_, buffer->mmap_data_);
buffer->mmap_data_ = nullptr; // Find matching plane.
void* mmap_data = nullptr;
for (auto& mapped_plane : buffer->mapped_planes_) {
if (mapped_plane.addr == pixels) {
mmap_data = mapped_plane.mapped_data;
mapped_plane = {};
break;
}
}
CHECK(mmap_data);
gbm_bo_unmap(buffer->bo_, mmap_data);
} }
gbm_bo* const bo_; gbm_bo* const bo_;
void* mmap_data_ = nullptr;
const uint32_t format_; const uint32_t format_;
const uint64_t format_modifier_; const uint64_t format_modifier_;
...@@ -244,6 +295,12 @@ class Buffer final : public ui::GbmBuffer { ...@@ -244,6 +295,12 @@ class Buffer final : public ui::GbmBuffer {
const gfx::NativePixmapHandle handle_; const gfx::NativePixmapHandle handle_;
struct MappedPlane {
void* addr = nullptr;
void* mapped_data = nullptr;
};
std::vector<MappedPlane> mapped_planes_;
DISALLOW_COPY_AND_ASSIGN(Buffer); DISALLOW_COPY_AND_ASSIGN(Buffer);
}; };
...@@ -342,23 +399,24 @@ class Device final : public ui::GbmDevice { ...@@ -342,23 +399,24 @@ class Device final : public ui::GbmDevice {
gbm_flags &= ~GBM_BO_USE_SCANOUT; gbm_flags &= ~GBM_BO_USE_SCANOUT;
struct gbm_bo* bo = nullptr; struct gbm_bo* bo = nullptr;
if (!gbm_device_is_format_supported(device_, format, gbm_flags)) { if (!IsFormatAndUsageSupported(format, gbm_flags)) {
LOG(ERROR) << "gbm format not supported: " << format; LOG(ERROR) << "gbm format not supported: " << format;
return nullptr; return nullptr;
} }
struct gbm_import_fd_modifier_data fd_data; struct gbm_import_fd_modifier_data fd_data;
fd_data.width = size.width(); fd_data.width = base::checked_cast<uint32_t>(size.width());
fd_data.height = size.height(); fd_data.height = base::checked_cast<uint32_t>(size.height());
fd_data.format = format; fd_data.format = format;
fd_data.num_fds = handle.planes.size(); fd_data.num_fds = base::checked_cast<uint32_t>(handle.planes.size());
fd_data.modifier = handle.modifier; fd_data.modifier = handle.modifier;
DCHECK_LE(handle.planes.size(), 3u); DCHECK_LE(handle.planes.size(), 3u);
for (size_t i = 0; i < handle.planes.size(); ++i) { for (size_t i = 0; i < handle.planes.size(); ++i) {
fd_data.fds[i] = handle.planes[i < handle.planes.size() ? i : 0].fd.get(); fd_data.fds[i] = base::checked_cast<int>(
fd_data.strides[i] = handle.planes[i].stride; handle.planes[i < handle.planes.size() ? i : 0].fd.get());
fd_data.offsets[i] = handle.planes[i].offset; fd_data.strides[i] = base::checked_cast<int>(handle.planes[i].stride);
fd_data.offsets[i] = base::checked_cast<int>(handle.planes[i].offset);
} }
// The fd passed to gbm_bo_import is not ref-counted and need to be // The fd passed to gbm_bo_import is not ref-counted and need to be
...@@ -373,6 +431,10 @@ class Device final : public ui::GbmDevice { ...@@ -373,6 +431,10 @@ class Device final : public ui::GbmDevice {
size, std::move(handle)); size, std::move(handle));
} }
bool IsFormatAndUsageSupported(uint32_t format, uint32_t flags) override {
return gbm_device_is_format_supported(device_, format, flags);
}
private: private:
gbm_device* const device_; gbm_device* const device_;
......
...@@ -70,8 +70,14 @@ class MockGbmBuffer final : public ui::GbmBuffer { ...@@ -70,8 +70,14 @@ class MockGbmBuffer final : public ui::GbmBuffer {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return gfx::NativePixmapHandle(); return gfx::NativePixmapHandle();
} }
sk_sp<SkSurface> GetPlaneSurface(size_t plane) override {
sk_sp<SkSurface> GetSurface() override { return nullptr; } NOTIMPLEMENTED();
return nullptr;
}
sk_sp<SkSurface> GetSurface() override {
NOTIMPLEMENTED();
return nullptr;
}
private: private:
uint32_t format_ = 0; uint32_t format_ = 0;
...@@ -163,4 +169,9 @@ std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferFromHandle( ...@@ -163,4 +169,9 @@ std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferFromHandle(
return nullptr; return nullptr;
} }
bool MockGbmDevice::IsFormatAndUsageSupported(uint32_t format, uint32_t flags) {
NOTREACHED();
return false;
}
} // namespace ui } // namespace ui
...@@ -30,6 +30,7 @@ class MockGbmDevice : public GbmDevice { ...@@ -30,6 +30,7 @@ class MockGbmDevice : public GbmDevice {
uint32_t format, uint32_t format,
const gfx::Size& size, const gfx::Size& size,
gfx::NativePixmapHandle handle) override; gfx::NativePixmapHandle handle) override;
bool IsFormatAndUsageSupported(uint32_t format, uint32_t flags) override;
private: private:
uint32_t next_handle_ = 0; uint32_t next_handle_ = 0;
......
...@@ -399,6 +399,12 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer( ...@@ -399,6 +399,12 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
return DrmOverlayPlane::Error(); return DrmOverlayPlane::Error();
} }
if (buffer->GetNumPlanes() > 1) {
NOTREACHED() << "Expected only one plane but got "
<< buffer->GetNumPlanes();
return DrmOverlayPlane::Error();
}
sk_sp<SkSurface> surface = buffer->GetSurface(); sk_sp<SkSurface> surface = buffer->GetSurface();
if (!surface) { if (!surface) {
VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer."; VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer.";
......
...@@ -51,6 +51,7 @@ class FakeGbmBuffer : public GbmBuffer { ...@@ -51,6 +51,7 @@ class FakeGbmBuffer : public GbmBuffer {
gfx::NativePixmapHandle ExportHandle() const override { gfx::NativePixmapHandle ExportHandle() const override {
return gfx::NativePixmapHandle(); return gfx::NativePixmapHandle();
} }
sk_sp<SkSurface> GetPlaneSurface(size_t plane) override { return nullptr; }
sk_sp<SkSurface> GetSurface() override { return nullptr; } sk_sp<SkSurface> GetSurface() override { return nullptr; }
private: private:
...@@ -81,6 +82,9 @@ class FakeGbmDevice : public GbmDevice { ...@@ -81,6 +82,9 @@ class FakeGbmDevice : public GbmDevice {
gfx::NativePixmapHandle handle) override { gfx::NativePixmapHandle handle) override {
return nullptr; return nullptr;
} }
bool IsFormatAndUsageSupported(uint32_t format, uint32_t flags) override {
return false;
}
private: private:
DISALLOW_COPY_AND_ASSIGN(FakeGbmDevice); DISALLOW_COPY_AND_ASSIGN(FakeGbmDevice);
......
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