1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h"
6 
7 #include <vulkan/vulkan.h>
8 
9 #include <utility>
10 
11 #include "base/bind.h"
12 #include "base/memory/ptr_util.h"
13 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
14 #include "ui/gfx/buffer_format_util.h"
15 #include "ui/gfx/client_native_pixmap_factory.h"
16 #include "ui/gfx/native_pixmap.h"
17 
18 #if defined(USE_OZONE)
19 #include "ui/base/ui_base_features.h"
20 #include "ui/ozone/public/ozone_platform.h"
21 #include "ui/ozone/public/surface_factory_ozone.h"
22 #endif
23 
24 namespace gpu {
25 namespace {
26 
FreeNativePixmapForTesting(scoped_refptr<gfx::NativePixmap> native_pixmap)27 void FreeNativePixmapForTesting(
28     scoped_refptr<gfx::NativePixmap> native_pixmap) {
29   // Nothing to do here. |native_pixmap| will be freed when this function
30   // returns and reference count drops to 0.
31 }
32 
33 }  // namespace
34 
GpuMemoryBufferImplNativePixmap(gfx::GpuMemoryBufferId id,const gfx::Size & size,gfx::BufferFormat format,DestructionCallback callback,std::unique_ptr<gfx::ClientNativePixmap> pixmap,gfx::NativePixmapHandle handle)35 GpuMemoryBufferImplNativePixmap::GpuMemoryBufferImplNativePixmap(
36     gfx::GpuMemoryBufferId id,
37     const gfx::Size& size,
38     gfx::BufferFormat format,
39     DestructionCallback callback,
40     std::unique_ptr<gfx::ClientNativePixmap> pixmap,
41     gfx::NativePixmapHandle handle)
42     : GpuMemoryBufferImpl(id, size, format, std::move(callback)),
43       pixmap_(std::move(pixmap)),
44       handle_(std::move(handle)) {}
45 
46 GpuMemoryBufferImplNativePixmap::~GpuMemoryBufferImplNativePixmap() = default;
47 
48 // static
49 std::unique_ptr<GpuMemoryBufferImplNativePixmap>
CreateFromHandle(gfx::ClientNativePixmapFactory * client_native_pixmap_factory,gfx::GpuMemoryBufferHandle handle,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,DestructionCallback callback)50 GpuMemoryBufferImplNativePixmap::CreateFromHandle(
51     gfx::ClientNativePixmapFactory* client_native_pixmap_factory,
52     gfx::GpuMemoryBufferHandle handle,
53     const gfx::Size& size,
54     gfx::BufferFormat format,
55     gfx::BufferUsage usage,
56     DestructionCallback callback) {
57   std::unique_ptr<gfx::ClientNativePixmap> native_pixmap =
58       client_native_pixmap_factory->ImportFromHandle(
59           CloneHandleForIPC(handle.native_pixmap_handle), size, format, usage);
60   if (!native_pixmap)
61     return nullptr;
62 
63   return base::WrapUnique(new GpuMemoryBufferImplNativePixmap(
64       handle.id, size, format, std::move(callback), std::move(native_pixmap),
65       std::move(handle.native_pixmap_handle)));
66 }
67 
68 // static
AllocateForTesting(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,gfx::GpuMemoryBufferHandle * handle)69 base::OnceClosure GpuMemoryBufferImplNativePixmap::AllocateForTesting(
70     const gfx::Size& size,
71     gfx::BufferFormat format,
72     gfx::BufferUsage usage,
73     gfx::GpuMemoryBufferHandle* handle) {
74   scoped_refptr<gfx::NativePixmap> pixmap;
75 #if defined(USE_OZONE)
76   if (features::IsUsingOzonePlatform()) {
77     pixmap = ui::OzonePlatform::GetInstance()
78                  ->GetSurfaceFactoryOzone()
79                  ->CreateNativePixmap(gfx::kNullAcceleratedWidget,
80                                       VK_NULL_HANDLE, size, format, usage);
81     handle->native_pixmap_handle = pixmap->ExportHandle();
82   } else
83 #endif
84   {
85     // TODO(j.isorce): use gbm_bo_create / gbm_bo_get_fd from system libgbm.
86     NOTIMPLEMENTED();
87   }
88   handle->type = gfx::NATIVE_PIXMAP;
89   return base::BindOnce(&FreeNativePixmapForTesting, pixmap);
90 }
91 
Map()92 bool GpuMemoryBufferImplNativePixmap::Map() {
93   DCHECK(!mapped_);
94   DCHECK_EQ(gfx::NumberOfPlanesForLinearBufferFormat(GetFormat()),
95             handle_.planes.size());
96   mapped_ = pixmap_->Map();
97   return mapped_;
98 }
99 
memory(size_t plane)100 void* GpuMemoryBufferImplNativePixmap::memory(size_t plane) {
101   DCHECK(mapped_);
102   return pixmap_->GetMemoryAddress(plane);
103 }
104 
Unmap()105 void GpuMemoryBufferImplNativePixmap::Unmap() {
106   DCHECK(mapped_);
107   pixmap_->Unmap();
108   mapped_ = false;
109 }
110 
stride(size_t plane) const111 int GpuMemoryBufferImplNativePixmap::stride(size_t plane) const {
112   // The caller is responsible for ensuring that |plane| is within bounds.
113   CHECK_LT(plane, handle_.planes.size());
114 
115   // |handle_|.planes[plane].stride is a uint32_t. For usages for which we
116   // create a ClientNativePixmapDmaBuf,
117   // ClientNativePixmapDmaBuf::ImportFromDmabuf() ensures that the stride fits
118   // on an int, so this checked_cast shouldn't fail. For usages for which we
119   // create a ClientNativePixmapOpaque, we don't validate the stride, but the
120   // expectation is that either a) the stride() method won't be called, or b)
121   // the stride() method is called on the GPU process and
122   // |handle_|.planes[plane].stride is also set on the GPU process so there's no
123   // need to validate it. Refer to http://crbug.com/1093644#c1 for a more
124   // detailed discussion.
125   return base::checked_cast<int>(handle_.planes[plane].stride);
126 }
127 
GetType() const128 gfx::GpuMemoryBufferType GpuMemoryBufferImplNativePixmap::GetType() const {
129   return gfx::NATIVE_PIXMAP;
130 }
131 
CloneHandle() const132 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplNativePixmap::CloneHandle()
133     const {
134   gfx::GpuMemoryBufferHandle handle;
135   handle.type = gfx::NATIVE_PIXMAP;
136   handle.id = id_;
137   handle.native_pixmap_handle = gfx::CloneHandleForIPC(handle_);
138   return handle;
139 }
140 
141 }  // namespace gpu
142