1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
18 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
19 #include <hidl/LegacySupport.h>
20 #include <qemu_pipe_bp.h>
21
22 #include "glUtils.h"
23 #include "cb_handle_30.h"
24 #include "host_connection_session.h"
25 #include "types.h"
26 #include "debug.h"
27
28 const int kOMX_COLOR_FormatYUV420Planar = 19;
29
30 using ::android::hardware::hidl_handle;
31 using ::android::hardware::hidl_vec;
32 using ::android::hardware::hidl_bitfield;
33 using ::android::hardware::Return;
34 using ::android::hardware::Void;
35
36 using ::android::hardware::graphics::common::V1_2::PixelFormat;
37 using ::android::hardware::graphics::common::V1_0::BufferUsage;
38
39 namespace AllocatorV3 = ::android::hardware::graphics::allocator::V3_0;
40 namespace MapperV3 = ::android::hardware::graphics::mapper::V3_0;
41
42 using IAllocator3 = AllocatorV3::IAllocator;
43 using IMapper3 = MapperV3::IMapper;
44 using Error3 = MapperV3::Error;
45 using BufferDescriptorInfo = IMapper3::BufferDescriptorInfo;
46
47 class GoldfishAllocator : public IAllocator3 {
48 public:
GoldfishAllocator()49 GoldfishAllocator() : m_hostConn(HostConnection::createUnique()) {}
50
dumpDebugInfo(dumpDebugInfo_cb hidl_cb)51 Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) {
52 hidl_cb("GoldfishAllocator::dumpDebugInfo is not implemented");
53 return {};
54 }
55
allocate(const hidl_vec<uint32_t> & rawDescriptor,uint32_t count,allocate_cb hidl_cb)56 Return<void> allocate(const hidl_vec<uint32_t>& rawDescriptor,
57 uint32_t count,
58 allocate_cb hidl_cb) {
59 uint32_t stride = 0;
60 std::vector<cb_handle_30_t*> cbs;
61 cbs.reserve(count);
62
63 const Error3 e = allocateImpl(rawDescriptor, count, &stride, &cbs);
64 if (e == Error3::NONE) {
65 hidl_vec<hidl_handle> handles(cbs.cbegin(), cbs.cend());
66 hidl_cb(Error3::NONE, stride, handles);
67 } else {
68 hidl_cb(e, 0, {});
69 }
70
71 for (cb_handle_30_t* cb : cbs) {
72 freeCb(std::unique_ptr<cb_handle_30_t>(cb));
73 }
74
75 return {};
76 }
77
78 private:
79 // this function should be in sync with GoldfishMapper::isSupportedImpl
allocateImpl(const hidl_vec<uint32_t> & rawDescriptor,uint32_t count,uint32_t * pStride,std::vector<cb_handle_30_t * > * cbs)80 Error3 allocateImpl(const hidl_vec<uint32_t>& rawDescriptor,
81 uint32_t count,
82 uint32_t* pStride,
83 std::vector<cb_handle_30_t*>* cbs) {
84 BufferDescriptorInfo descriptor;
85 if (!decodeBufferDescriptorInfo(rawDescriptor, &descriptor)) {
86 RETURN_ERROR(Error3::BAD_DESCRIPTOR);
87 }
88
89 if (!descriptor.width) { RETURN_ERROR(Error3::UNSUPPORTED); }
90 if (!descriptor.height) { RETURN_ERROR(Error3::UNSUPPORTED); }
91 if (descriptor.layerCount != 1) { RETURN_ERROR(Error3::UNSUPPORTED); }
92
93 const uint32_t usage = descriptor.usage;
94 const bool usageSwWrite = usage & BufferUsage::CPU_WRITE_MASK;
95 const bool usageSwRead = usage & BufferUsage::CPU_READ_MASK;
96 const bool usageHwCamWrite = usage & BufferUsage::CAMERA_OUTPUT;
97 const bool usageHwCamRead = usage & BufferUsage::CAMERA_INPUT;
98
99 int bpp = 1;
100 int glFormat = 0;
101 int glType = 0;
102 int align = 1;
103 bool yuv_format = false;
104 EmulatorFrameworkFormat emulatorFrameworkFormat =
105 EmulatorFrameworkFormat::GL_COMPATIBLE;
106
107 PixelFormat format;
108 Error3 e = getBufferFormat(descriptor.format, usage, &format);
109 if (e != Error3::NONE) {
110 ALOGE("%s:%d Unsupported format: frameworkFormat=%d, usage=%x",
111 __func__, __LINE__, descriptor.format, usage);
112 return e;
113 }
114
115 switch (format) {
116 case PixelFormat::RGBA_8888:
117 case PixelFormat::RGBX_8888:
118 case PixelFormat::BGRA_8888:
119 bpp = 4;
120 glFormat = GL_RGBA;
121 glType = GL_UNSIGNED_BYTE;
122 break;
123
124 case PixelFormat::RGB_888:
125 if (usage & (BufferUsage::GPU_TEXTURE |
126 BufferUsage::GPU_RENDER_TARGET |
127 BufferUsage::COMPOSER_OVERLAY |
128 BufferUsage::COMPOSER_CLIENT_TARGET)) {
129 RETURN_ERROR(Error3::UNSUPPORTED);
130 } else {
131 bpp = 3;
132 glFormat = GL_RGB;
133 glType = GL_UNSIGNED_BYTE;
134 }
135 break;
136
137 case PixelFormat::RGB_565:
138 bpp = 2;
139 glFormat = GL_RGB565;
140 glType = GL_UNSIGNED_SHORT_5_6_5;
141 break;
142
143 case PixelFormat::RGBA_FP16:
144 bpp = 8;
145 glFormat = GL_RGBA16F;
146 glType = GL_HALF_FLOAT;
147 break;
148
149 case PixelFormat::RGBA_1010102:
150 bpp = 4;
151 glFormat = GL_RGB10_A2;
152 glType = GL_UNSIGNED_INT_2_10_10_10_REV;
153 break;
154
155 case PixelFormat::RAW16:
156 case PixelFormat::Y16:
157 bpp = 2;
158 align = 16 * bpp;
159 if (!((usageSwRead || usageHwCamRead) && (usageSwWrite || usageHwCamWrite))) {
160 // Raw sensor data or Y16 only goes between camera and CPU
161 RETURN_ERROR(Error3::UNSUPPORTED);
162 }
163 // Not expecting to actually create any GL surfaces for this
164 glFormat = GL_LUMINANCE;
165 glType = GL_UNSIGNED_SHORT;
166 break;
167
168 case PixelFormat::BLOB:
169 if (!usageSwRead) {
170 // Blob data cannot be used by HW other than camera emulator
171 // But there is a CTS test trying to have access to it
172 // BUG: https://buganizer.corp.google.com/issues/37719518
173 RETURN_ERROR(Error3::UNSUPPORTED);
174 }
175 // Not expecting to actually create any GL surfaces for this
176 glFormat = GL_LUMINANCE;
177 glType = GL_UNSIGNED_BYTE;
178 break;
179
180 case PixelFormat::YCRCB_420_SP:
181 yuv_format = true;
182 // Not expecting to actually create any GL surfaces for this
183 break;
184
185 case PixelFormat::YV12:
186 align = 16;
187 yuv_format = true;
188 // We are going to use RGB8888 on the host for Vulkan
189 glFormat = GL_RGBA;
190 glType = GL_UNSIGNED_BYTE;
191 emulatorFrameworkFormat = EmulatorFrameworkFormat::YV12;
192 break;
193
194 case PixelFormat::YCBCR_420_888:
195 yuv_format = true;
196 // We are going to use RGBA 8888 on the host
197 glFormat = GL_RGBA;
198 glType = GL_UNSIGNED_BYTE;
199 emulatorFrameworkFormat = EmulatorFrameworkFormat::YUV_420_888;
200 break;
201
202 default:
203 if (static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format) ==
204 android::hardware::graphics::common::V1_1::PixelFormat::YCBCR_P010) {
205 yuv_format = true;
206 glFormat = GL_RGBA;
207 glType = GL_UNSIGNED_BYTE;
208 bpp = 2;
209 break;
210 }
211
212 ALOGE("%s:%d Unsupported format: format=%d, frameworkFormat=%d, usage=%x",
213 __func__, __LINE__, format, descriptor.format, usage);
214 RETURN_ERROR(Error3::UNSUPPORTED);
215 }
216
217 const size_t align1 = align - 1;
218 const uint32_t width = descriptor.width;
219 const uint32_t height = descriptor.height;
220 uint32_t stride;
221 size_t bufferSize;
222
223 if (yuv_format) {
224 const size_t yStride = (width * bpp + align1) & ~align1;
225 const size_t uvStride = (yStride / 2 + align1) & ~align1;
226 const size_t uvHeight = height / 2;
227 bufferSize = yStride * height + 2 * (uvHeight * uvStride);
228 stride = yStride / bpp;
229 } else {
230 const size_t bpr = (width * bpp + align1) & ~align1;
231 bufferSize = bpr * height;
232 stride = bpr / bpp;
233 }
234
235 *pStride = stride;
236
237 return allocateImpl2(usage,
238 width, height,
239 format, emulatorFrameworkFormat,
240 glFormat, glType,
241 bufferSize,
242 bpp, stride,
243 count, cbs);
244 }
245
allocateImpl2(const uint32_t usage,const uint32_t width,const uint32_t height,const PixelFormat format,const EmulatorFrameworkFormat emulatorFrameworkFormat,const int glFormat,const int glType,const size_t bufferSize,const uint32_t bytesPerPixel,const uint32_t stride,const uint32_t count,std::vector<cb_handle_30_t * > * cbs)246 Error3 allocateImpl2(const uint32_t usage,
247 const uint32_t width, const uint32_t height,
248 const PixelFormat format,
249 const EmulatorFrameworkFormat emulatorFrameworkFormat,
250 const int glFormat, const int glType,
251 const size_t bufferSize,
252 const uint32_t bytesPerPixel,
253 const uint32_t stride,
254 const uint32_t count,
255 std::vector<cb_handle_30_t*>* cbs) {
256 for (uint32_t i = 0; i < count; ++i) {
257 cb_handle_30_t* cb;
258 Error3 e = allocateCb(usage,
259 width, height,
260 format, emulatorFrameworkFormat,
261 glFormat, glType,
262 bufferSize,
263 bytesPerPixel, stride,
264 &cb);
265 if (e == Error3::NONE) {
266 cbs->push_back(cb);
267 } else {
268 return e;
269 }
270 }
271
272 RETURN(Error3::NONE);
273 }
274
275 // see GoldfishMapper::encodeBufferDescriptorInfo
decodeBufferDescriptorInfo(const hidl_vec<uint32_t> & raw,BufferDescriptorInfo * d)276 static bool decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& raw,
277 BufferDescriptorInfo* d) {
278 if (raw.size() == 5) {
279 d->width = raw[0];
280 d->height = raw[1];
281 d->layerCount = raw[2];
282 d->format = static_cast<PixelFormat>(raw[3]);
283 d->usage = raw[4];
284
285 RETURN(true);
286 } else {
287 RETURN_ERROR(false);
288 }
289 }
290
getBufferFormat(const PixelFormat frameworkFormat,const uint32_t usage,PixelFormat * format)291 static Error3 getBufferFormat(const PixelFormat frameworkFormat,
292 const uint32_t usage,
293 PixelFormat* format) {
294 if (frameworkFormat == PixelFormat::IMPLEMENTATION_DEFINED) {
295 if (usage & BufferUsage::CAMERA_OUTPUT) {
296 if (usage & BufferUsage::GPU_TEXTURE) {
297 // Camera-to-display is RGBA
298 *format = PixelFormat::RGBA_8888;
299 RETURN(Error3::NONE);
300 } else if (usage & BufferUsage::VIDEO_ENCODER) {
301 // Camera-to-encoder is NV21
302 *format = PixelFormat::YCRCB_420_SP;
303 RETURN(Error3::NONE);
304 } else {
305 // b/189957071
306 *format = PixelFormat::YCBCR_420_888;
307 RETURN(Error3::NONE);
308 }
309 }
310 RETURN_ERROR(Error3::UNSUPPORTED);
311 } else if (static_cast<int>(frameworkFormat) == kOMX_COLOR_FormatYUV420Planar &&
312 (usage & BufferUsage::VIDEO_DECODER)) {
313 ALOGW("gralloc_alloc: Requested OMX_COLOR_FormatYUV420Planar, given "
314 "YCbCr_420_888, taking experimental path. "
315 "usage=%x", usage);
316 *format = PixelFormat::YCBCR_420_888;
317 RETURN(Error3::NONE);
318 } else {
319 *format = frameworkFormat;
320 RETURN(Error3::NONE);
321 }
322 }
323
needHostCb(const uint32_t usage,const PixelFormat format)324 static bool needHostCb(const uint32_t usage, const PixelFormat format) {
325 if (static_cast<android::hardware::graphics::common::V1_1::PixelFormat>(format) ==
326 android::hardware::graphics::common::V1_1::PixelFormat::YCBCR_P010) {
327 return false;
328 }
329
330 // b/186585177
331 if ((usage & (BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK)) &&
332 (0 == (usage & ~(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK)))) {
333 return false;
334 }
335
336 return ((usage & BufferUsage::GPU_DATA_BUFFER)
337 || (format != PixelFormat::BLOB &&
338 format != PixelFormat::RAW16 &&
339 format != PixelFormat::Y16))
340 && (usage & (BufferUsage::GPU_TEXTURE
341 | BufferUsage::GPU_RENDER_TARGET
342 | BufferUsage::COMPOSER_OVERLAY
343 | BufferUsage::VIDEO_ENCODER
344 | BufferUsage::VIDEO_DECODER
345 | BufferUsage::COMPOSER_CLIENT_TARGET
346 | BufferUsage::CPU_READ_MASK));
347 }
348
allocateCb(const uint32_t usage,const uint32_t width,const uint32_t height,const PixelFormat format,const EmulatorFrameworkFormat emulatorFrameworkFormat,const int glFormat,const int glType,const size_t bufferSize,const int32_t bytesPerPixel,const int32_t stride,cb_handle_30_t ** cb)349 Error3 allocateCb(const uint32_t usage,
350 const uint32_t width, const uint32_t height,
351 const PixelFormat format,
352 const EmulatorFrameworkFormat emulatorFrameworkFormat,
353 const int glFormat, const int glType,
354 const size_t bufferSize,
355 const int32_t bytesPerPixel,
356 const int32_t stride,
357 cb_handle_30_t** cb) {
358 const HostConnectionSession conn = getHostConnectionSession();
359 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
360 CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
361
362 GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
363 rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
364 if (!host_memory_allocator.is_opened()) {
365 RETURN_ERROR(Error3::NO_RESOURCES);
366 }
367
368 GoldfishAddressSpaceBlock bufferBits;
369 if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) {
370 RETURN_ERROR(Error3::NO_RESOURCES);
371 }
372
373 uint32_t hostHandle = 0;
374 QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
375 if (needHostCb(usage, format)) {
376 hostHandleRefCountFd = qemu_pipe_open("refcount");
377 if (!qemu_pipe_valid(hostHandleRefCountFd)) {
378 RETURN_ERROR(Error3::NO_RESOURCES);
379 }
380
381 const GLenum allocFormat =
382 (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
383
384 hostHandle = rcEnc->rcCreateColorBufferDMA(
385 rcEnc,
386 width, height,
387 allocFormat, static_cast<int>(emulatorFrameworkFormat));
388
389 if (!hostHandle) {
390 qemu_pipe_close(hostHandleRefCountFd);
391 RETURN_ERROR(Error3::NO_RESOURCES);
392 }
393
394 if (qemu_pipe_write(hostHandleRefCountFd,
395 &hostHandle,
396 sizeof(hostHandle)) != sizeof(hostHandle)) {
397 rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
398 qemu_pipe_close(hostHandleRefCountFd);
399 RETURN_ERROR(Error3::NO_RESOURCES);
400 }
401 }
402
403 std::unique_ptr<cb_handle_30_t> handle =
404 std::make_unique<cb_handle_30_t>(
405 host_memory_allocator.release(),
406 hostHandleRefCountFd,
407 hostHandle,
408 usage,
409 width,
410 height,
411 static_cast<int>(format),
412 glFormat,
413 glType,
414 bufferSize,
415 bufferBits.guestPtr(),
416 bufferBits.size(),
417 bufferBits.offset(),
418 bytesPerPixel,
419 stride);
420
421 bufferBits.release();
422 *cb = handle.release();
423 RETURN(Error3::NONE);
424 }
425
freeCb(std::unique_ptr<cb_handle_30_t> cb)426 void freeCb(std::unique_ptr<cb_handle_30_t> cb) {
427 // no need to undo .hostMalloc: the kernel will take care of it once the
428 // last bufferFd (duped) is closed.
429
430 if (qemu_pipe_valid(cb->hostHandleRefCountFd)) {
431 qemu_pipe_close(cb->hostHandleRefCountFd);
432 }
433 GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
434 GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
435 }
436
getHostConnectionSession() const437 HostConnectionSession getHostConnectionSession() const {
438 return HostConnectionSession(m_hostConn.get());
439 }
440
441 std::unique_ptr<HostConnection> m_hostConn;
442 };
443
main(int,char **)444 int main(int, char**) {
445 using ::android::sp;
446
447 ::android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
448
449 sp<IAllocator3> allocator(new GoldfishAllocator());
450 if (allocator->registerAsService() != ::android::NO_ERROR) {
451 ALOGE("failed to register graphics IAllocator@3.0 service");
452 return -EINVAL;
453 }
454
455 ALOGI("graphics IAllocator@3.0 service is initialized");
456 ::android::hardware::joinRpcThreadpool();
457
458 ALOGI("graphics IAllocator@3.0 service is terminating");
459 return 0;
460 }
461