Commit cd5d9e03 authored by Michael Spang's avatar Michael Spang Committed by Commit Bot

ozone: drm: Allow creating vulkan-renderable scanout buffers

Use vkCreateDmaBufImageINTEL until VK_EXT_image_drm_format_modifier is
available. We can't import buffers created with modifiers using this
method, so work around this for by adding a new flag to buffer creation.

Bug: 851997
Test: ozone_demo --enable-vulkan on vulkan-enabled eve

Change-Id: If91c678d7ee4ce52c610f55f9c7a2dbd561a4158
Reviewed-on: https://chromium-review.googlesource.com/1104866
Commit-Queue: Michael Spang <spang@chromium.org>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570233}
parent 9c97e58e
......@@ -119,6 +119,7 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
uint32_t client_flags,
scoped_refptr<GbmBuffer>* buffer) {
scoped_refptr<GbmDevice> gbm =
static_cast<GbmDevice*>(device_manager_->GetDrmDevice(widget).get());
......@@ -169,7 +170,8 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
// buffer in that case.
bool retry_without_scanout = usage != gfx::BufferUsage::SCANOUT;
do {
if (modifiers.size() > 0 && !(flags & GBM_BO_USE_LINEAR))
if (modifiers.size() > 0 && !(flags & GBM_BO_USE_LINEAR) &&
!(client_flags & GbmBuffer::kFlagNoModifiers))
*buffer = GbmBuffer::CreateBufferWithModifiers(gbm, fourcc_format, size,
flags, modifiers);
else
......
......@@ -70,6 +70,7 @@ class DrmThread : public base::Thread,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
uint32_t flags,
scoped_refptr<GbmBuffer>* buffer);
void CreateBufferFromFds(gfx::AcceleratedWidget widget,
const gfx::Size& size,
......
......@@ -36,7 +36,8 @@ scoped_refptr<GbmBuffer> DrmThreadProxy::CreateBuffer(
gfx::AcceleratedWidget widget,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage) {
gfx::BufferUsage usage,
uint32_t flags) {
DCHECK(drm_thread_.task_runner())
<< "no task runner! in DrmThreadProxy::CreateBuffer";
scoped_refptr<GbmBuffer> buffer;
......@@ -44,7 +45,7 @@ scoped_refptr<GbmBuffer> DrmThreadProxy::CreateBuffer(
PostSyncTask(
drm_thread_.task_runner(),
base::BindOnce(&DrmThread::CreateBuffer, base::Unretained(&drm_thread_),
widget, size, format, usage, &buffer));
widget, size, format, usage, flags, &buffer));
return buffer;
}
......
......@@ -35,7 +35,8 @@ class DrmThreadProxy {
scoped_refptr<GbmBuffer> CreateBuffer(gfx::AcceleratedWidget widget,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage);
gfx::BufferUsage usage,
uint32_t flags);
scoped_refptr<GbmBuffer> CreateBufferFromFds(
gfx::AcceleratedWidget widget,
......
......@@ -23,6 +23,8 @@ class GbmSurfaceFactory;
class GbmBuffer : public ScanoutBuffer {
public:
static constexpr uint32_t kFlagNoModifiers = 1U << 0;
static scoped_refptr<GbmBuffer> CreateBuffer(
const scoped_refptr<GbmDevice>& gbm,
uint32_t format,
......
......@@ -29,7 +29,11 @@
#include "ui/ozone/public/surface_ozone_canvas.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.h"
#if defined(OS_CHROMEOS)
#include <vulkan/vulkan_intel.h>
#endif
#endif
namespace ui {
......@@ -135,6 +139,60 @@ std::unique_ptr<gpu::VulkanImplementation>
GbmSurfaceFactory::CreateVulkanImplementation() {
return std::make_unique<ui::VulkanImplementationGbm>();
}
scoped_refptr<gfx::NativePixmap> GbmSurfaceFactory::CreateNativePixmapForVulkan(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
const gpu::VulkanFunctionPointers* vulkan_function_pointers,
VkDevice vk_device,
VkDeviceMemory* vk_device_memory,
VkImage* vk_image) {
#if defined(OS_CHROMEOS)
scoped_refptr<GbmBuffer> buffer = drm_thread_proxy_->CreateBuffer(
widget, size, format, usage, GbmBuffer::kFlagNoModifiers);
if (!buffer.get())
return nullptr;
PFN_vkCreateDmaBufImageINTEL create_dma_buf_image_intel =
reinterpret_cast<PFN_vkCreateDmaBufImageINTEL>(
vulkan_function_pointers->vkGetDeviceProcAddr(
vk_device, "vkCreateDmaBufImageINTEL"));
if (!create_dma_buf_image_intel) {
LOG(ERROR) << "Scanout buffers can only be imported into vulkan when "
"vkCreateDmaBufImageINTEL is available.";
return nullptr;
}
DCHECK(buffer->AreFdsValid());
DCHECK_EQ(buffer->GetFdCount(), 1U);
base::ScopedFD vk_image_fd(dup(buffer->GetFd(0)));
DCHECK(vk_image_fd.is_valid());
VkDmaBufImageCreateInfo dma_buf_image_create_info = {
.sType = static_cast<VkStructureType>(
VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL),
.fd = vk_image_fd.release(),
.format = VK_FORMAT_B8G8R8A8_SRGB,
.extent = (VkExtent3D){size.width(), size.height(), 1},
.strideInBytes = buffer->GetStride(0),
};
VkResult result =
create_dma_buf_image_intel(vk_device, &dma_buf_image_create_info, nullptr,
vk_device_memory, vk_image);
if (result != VK_SUCCESS) {
LOG(ERROR) << "Failed to create a Vulkan image from a dmabuf.";
return nullptr;
}
return base::MakeRefCounted<GbmPixmap>(this, buffer);
#else
return nullptr;
#endif
}
#endif
std::unique_ptr<OverlaySurface> GbmSurfaceFactory::CreateOverlaySurface(
......@@ -162,8 +220,8 @@ scoped_refptr<gfx::NativePixmap> GbmSurfaceFactory::CreateNativePixmap(
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage) {
scoped_refptr<GbmBuffer> buffer =
drm_thread_proxy_->CreateBuffer(widget, size, format, usage);
scoped_refptr<GbmBuffer> buffer = drm_thread_proxy_->CreateBuffer(
widget, size, format, usage, 0 /* flags */);
if (!buffer.get())
return nullptr;
......
......@@ -41,6 +41,15 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation()
override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmapForVulkan(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
const gpu::VulkanFunctionPointers* vulkan_function_pointers,
VkDevice vk_device,
VkDeviceMemory* vk_device_memory,
VkImage* vk_image) override;
#endif
std::unique_ptr<OverlaySurface> CreateOverlaySurface(
......
......@@ -36,6 +36,20 @@ std::unique_ptr<gpu::VulkanImplementation>
SurfaceFactoryOzone::CreateVulkanImplementation() {
return nullptr;
}
scoped_refptr<gfx::NativePixmap>
SurfaceFactoryOzone::CreateNativePixmapForVulkan(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
const gpu::VulkanFunctionPointers* vulkan_function_pointers,
VkDevice vk_device,
VkDeviceMemory* vk_device_memory,
VkImage* vk_image) {
NOTIMPLEMENTED();
return nullptr;
}
#endif
std::unique_ptr<OverlaySurface> SurfaceFactoryOzone::CreateOverlaySurface(
......
......@@ -32,6 +32,10 @@ namespace gfx {
class NativePixmap;
}
namespace gpu {
struct VulkanFunctionPointers;
}
namespace ui {
class SurfaceOzoneCanvas;
......@@ -80,6 +84,19 @@ class OZONE_BASE_EXPORT SurfaceFactoryOzone {
// creating surfaces that swap to a platform window.
virtual std::unique_ptr<gpu::VulkanImplementation>
CreateVulkanImplementation();
// Creates a scanout NativePixmap that can be rendered using Vulkan.
// TODO(spang): Remove this once VK_EXT_image_drm_format_modifier is
// available.
virtual scoped_refptr<gfx::NativePixmap> CreateNativePixmapForVulkan(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
const gpu::VulkanFunctionPointers* vulkan_function_pointers,
VkDevice vk_device,
VkDeviceMemory* vk_device_memory,
VkImage* vk_image);
#endif
// Creates an overlay surface for a platform window.
......
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