blob: bfee6e5f92bbc0d02f8bee9e324f487ae6442f00 [file] [log] [blame]
// Copyright 2014 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 "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h"
#include <vulkan/vulkan.h>
#include <utility>
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/client_native_pixmap_factory.h"
#include "ui/gfx/native_pixmap.h"
#if defined(USE_OZONE)
#include "ui/base/ui_base_features.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/surface_factory_ozone.h"
#endif
namespace gpu {
namespace {
void FreeNativePixmapForTesting(
scoped_refptr<gfx::NativePixmap> native_pixmap) {
// Nothing to do here. |native_pixmap| will be freed when this function
// returns and reference count drops to 0.
}
} // namespace
GpuMemoryBufferImplNativePixmap::GpuMemoryBufferImplNativePixmap(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
gfx::BufferFormat format,
DestructionCallback callback,
std::unique_ptr<gfx::ClientNativePixmap> pixmap,
gfx::NativePixmapHandle handle)
: GpuMemoryBufferImpl(id, size, format, std::move(callback)),
pixmap_(std::move(pixmap)),
handle_(std::move(handle)) {}
GpuMemoryBufferImplNativePixmap::~GpuMemoryBufferImplNativePixmap() = default;
// static
std::unique_ptr<GpuMemoryBufferImplNativePixmap>
GpuMemoryBufferImplNativePixmap::CreateFromHandle(
gfx::ClientNativePixmapFactory* client_native_pixmap_factory,
gfx::GpuMemoryBufferHandle handle,
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
DestructionCallback callback) {
std::unique_ptr<gfx::ClientNativePixmap> native_pixmap =
client_native_pixmap_factory->ImportFromHandle(
CloneHandleForIPC(handle.native_pixmap_handle), size, format, usage);
if (!native_pixmap)
return nullptr;
return base::WrapUnique(new GpuMemoryBufferImplNativePixmap(
handle.id, size, format, std::move(callback), std::move(native_pixmap),
std::move(handle.native_pixmap_handle)));
}
// static
base::OnceClosure GpuMemoryBufferImplNativePixmap::AllocateForTesting(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage,
gfx::GpuMemoryBufferHandle* handle) {
scoped_refptr<gfx::NativePixmap> pixmap;
#if defined(USE_OZONE)
if (features::IsUsingOzonePlatform()) {
pixmap = ui::OzonePlatform::GetInstance()
->GetSurfaceFactoryOzone()
->CreateNativePixmap(gfx::kNullAcceleratedWidget,
VK_NULL_HANDLE, size, format, usage);
handle->native_pixmap_handle = pixmap->ExportHandle();
} else
#endif
{
// TODO(j.isorce): use gbm_bo_create / gbm_bo_get_fd from system libgbm.
NOTIMPLEMENTED();
}
handle->type = gfx::NATIVE_PIXMAP;
return base::BindOnce(&FreeNativePixmapForTesting, pixmap);
}
bool GpuMemoryBufferImplNativePixmap::Map() {
DCHECK(!mapped_);
DCHECK_EQ(gfx::NumberOfPlanesForLinearBufferFormat(GetFormat()),
handle_.planes.size());
mapped_ = pixmap_->Map();
return mapped_;
}
void* GpuMemoryBufferImplNativePixmap::memory(size_t plane) {
DCHECK(mapped_);
return pixmap_->GetMemoryAddress(plane);
}
void GpuMemoryBufferImplNativePixmap::Unmap() {
DCHECK(mapped_);
pixmap_->Unmap();
mapped_ = false;
}
int GpuMemoryBufferImplNativePixmap::stride(size_t plane) const {
// The caller is responsible for ensuring that |plane| is within bounds.
CHECK_LT(plane, handle_.planes.size());
// |handle_|.planes[plane].stride is a uint32_t. For usages for which we
// create a ClientNativePixmapDmaBuf,
// ClientNativePixmapDmaBuf::ImportFromDmabuf() ensures that the stride fits
// on an int, so this checked_cast shouldn't fail. For usages for which we
// create a ClientNativePixmapOpaque, we don't validate the stride, but the
// expectation is that either a) the stride() method won't be called, or b)
// the stride() method is called on the GPU process and
// |handle_|.planes[plane].stride is also set on the GPU process so there's no
// need to validate it. Refer to http://crbug.com/1093644#c1 for a more
// detailed discussion.
return base::checked_cast<int>(handle_.planes[plane].stride);
}
gfx::GpuMemoryBufferType GpuMemoryBufferImplNativePixmap::GetType() const {
return gfx::NATIVE_PIXMAP;
}
gfx::GpuMemoryBufferHandle GpuMemoryBufferImplNativePixmap::CloneHandle()
const {
gfx::GpuMemoryBufferHandle handle;
handle.type = gfx::NATIVE_PIXMAP;
handle.id = id_;
handle.native_pixmap_handle = gfx::CloneHandleForIPC(handle_);
return handle;
}
} // namespace gpu