1 // Copyright 2017 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_android_hardware_buffer.h"
6 
7 #include <utility>
8 
9 #include "base/android/android_hardware_buffer_compat.h"
10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
15 #include "ui/gfx/android/android_surface_control_compat.h"
16 #include "ui/gfx/geometry/size.h"
17 
18 namespace gpu {
19 
20 namespace {
21 
GetBufferDescription(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage)22 AHardwareBuffer_Desc GetBufferDescription(const gfx::Size& size,
23                                           gfx::BufferFormat format,
24                                           gfx::BufferUsage usage) {
25   // On create, all elements must be initialized, including setting the
26   // "reserved for future use" (rfu) fields to zero.
27   AHardwareBuffer_Desc desc = {};
28   desc.width = size.width();
29   desc.height = size.height();
30   desc.layers = 1;  // number of images
31 
32   switch (format) {
33     case gfx::BufferFormat::RGBA_8888:
34       desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
35       break;
36     case gfx::BufferFormat::RGBX_8888:
37       desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM;
38       break;
39     case gfx::BufferFormat::BGR_565:
40       desc.format = AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM;
41       break;
42     case gfx::BufferFormat::RGBA_F16:
43       desc.format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT;
44       break;
45     case gfx::BufferFormat::RGBA_1010102:
46       desc.format = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
47       break;
48     default:
49       NOTREACHED();
50   }
51 
52   switch (usage) {
53     case gfx::BufferUsage::GPU_READ:
54     case gfx::BufferUsage::SCANOUT:
55       desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
56                    AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
57       if (usage == gfx::BufferUsage::SCANOUT)
58         desc.usage |= gfx::SurfaceControl::RequiredUsage();
59       break;
60     default:
61       NOTREACHED();
62   }
63   return desc;
64 }
65 
66 }  // namespace
67 
68 GpuMemoryBufferImplAndroidHardwareBuffer::
GpuMemoryBufferImplAndroidHardwareBuffer(gfx::GpuMemoryBufferId id,const gfx::Size & size,gfx::BufferFormat format,DestructionCallback callback,base::android::ScopedHardwareBufferHandle handle)69     GpuMemoryBufferImplAndroidHardwareBuffer(
70         gfx::GpuMemoryBufferId id,
71         const gfx::Size& size,
72         gfx::BufferFormat format,
73         DestructionCallback callback,
74         base::android::ScopedHardwareBufferHandle handle)
75     : GpuMemoryBufferImpl(id, size, format, std::move(callback)),
76       hardware_buffer_handle_(std::move(handle)) {}
77 
78 GpuMemoryBufferImplAndroidHardwareBuffer::
~GpuMemoryBufferImplAndroidHardwareBuffer()79     ~GpuMemoryBufferImplAndroidHardwareBuffer() {}
80 
81 // static
82 std::unique_ptr<GpuMemoryBufferImplAndroidHardwareBuffer>
Create(gfx::GpuMemoryBufferId id,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,DestructionCallback callback)83 GpuMemoryBufferImplAndroidHardwareBuffer::Create(gfx::GpuMemoryBufferId id,
84                                                  const gfx::Size& size,
85                                                  gfx::BufferFormat format,
86                                                  gfx::BufferUsage usage,
87                                                  DestructionCallback callback) {
88   DCHECK(base::AndroidHardwareBufferCompat::IsSupportAvailable());
89 
90   AHardwareBuffer* buffer = nullptr;
91   AHardwareBuffer_Desc desc = GetBufferDescription(size, format, usage);
92   base::AndroidHardwareBufferCompat::GetInstance().Allocate(&desc, &buffer);
93   if (!buffer) {
94     LOG(ERROR) << "Failed to allocate AHardwareBuffer";
95     return nullptr;
96   }
97 
98   return base::WrapUnique(new GpuMemoryBufferImplAndroidHardwareBuffer(
99       id, size, format, std::move(callback),
100       base::android::ScopedHardwareBufferHandle::Adopt(buffer)));
101 }
102 
103 // static
104 std::unique_ptr<GpuMemoryBufferImplAndroidHardwareBuffer>
CreateFromHandle(gfx::GpuMemoryBufferHandle handle,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,DestructionCallback callback)105 GpuMemoryBufferImplAndroidHardwareBuffer::CreateFromHandle(
106     gfx::GpuMemoryBufferHandle handle,
107     const gfx::Size& size,
108     gfx::BufferFormat format,
109     gfx::BufferUsage usage,
110     DestructionCallback callback) {
111   DCHECK(handle.android_hardware_buffer.is_valid());
112   return base::WrapUnique(new GpuMemoryBufferImplAndroidHardwareBuffer(
113       handle.id, size, format, std::move(callback),
114       std::move(handle.android_hardware_buffer)));
115 }
116 
Map()117 bool GpuMemoryBufferImplAndroidHardwareBuffer::Map() {
118   return false;
119 }
120 
memory(size_t plane)121 void* GpuMemoryBufferImplAndroidHardwareBuffer::memory(size_t plane) {
122   return nullptr;
123 }
124 
Unmap()125 void GpuMemoryBufferImplAndroidHardwareBuffer::Unmap() {}
126 
stride(size_t plane) const127 int GpuMemoryBufferImplAndroidHardwareBuffer::stride(size_t plane) const {
128   return 0;
129 }
130 
GetType() const131 gfx::GpuMemoryBufferType GpuMemoryBufferImplAndroidHardwareBuffer::GetType()
132     const {
133   return gfx::ANDROID_HARDWARE_BUFFER;
134 }
135 
136 gfx::GpuMemoryBufferHandle
CloneHandle() const137 GpuMemoryBufferImplAndroidHardwareBuffer::CloneHandle() const {
138   gfx::GpuMemoryBufferHandle handle;
139   handle.type = gfx::ANDROID_HARDWARE_BUFFER;
140   handle.id = id_;
141   handle.android_hardware_buffer = hardware_buffer_handle_.Clone();
142   return handle;
143 }
144 
145 // static
AllocateForTesting(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,gfx::GpuMemoryBufferHandle * handle)146 base::OnceClosure GpuMemoryBufferImplAndroidHardwareBuffer::AllocateForTesting(
147     const gfx::Size& size,
148     gfx::BufferFormat format,
149     gfx::BufferUsage usage,
150     gfx::GpuMemoryBufferHandle* handle) {
151   gfx::GpuMemoryBufferId kBufferId(1);
152   handle->type = gfx::ANDROID_HARDWARE_BUFFER;
153   handle->id = kBufferId;
154   AHardwareBuffer* buffer = nullptr;
155   AHardwareBuffer_Desc desc = GetBufferDescription(size, format, usage);
156   base::AndroidHardwareBufferCompat::GetInstance().Allocate(&desc, &buffer);
157   DCHECK(buffer);
158   handle->android_hardware_buffer =
159       base::android::ScopedHardwareBufferHandle::Adopt(buffer);
160   return base::DoNothing();
161 }
162 
163 }  // namespace gpu
164