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::GPU_DATA_BUFFER)) {
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::COMPOSER_CLIENT_TARGET
345 | BufferUsage::CPU_READ_MASK));
346 }
347
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)348 Error3 allocateCb(const uint32_t usage,
349 const uint32_t width, const uint32_t height,
350 const PixelFormat format,
351 const EmulatorFrameworkFormat emulatorFrameworkFormat,
352 const int glFormat, const int glType,
353 const size_t bufferSize,
354 const int32_t bytesPerPixel,
355 const int32_t stride,
356 cb_handle_30_t** cb) {
357 const HostConnectionSession conn = getHostConnectionSession();
358 ExtendedRCEncoderContext *const rcEnc = conn.getRcEncoder();
359 CRASH_IF(!rcEnc, "conn.getRcEncoder() failed");
360
361 GoldfishAddressSpaceHostMemoryAllocator host_memory_allocator(
362 rcEnc->featureInfo_const()->hasSharedSlotsHostMemoryAllocator);
363 if (!host_memory_allocator.is_opened()) {
364 RETURN_ERROR(Error3::NO_RESOURCES);
365 }
366
367 GoldfishAddressSpaceBlock bufferBits;
368 if (host_memory_allocator.hostMalloc(&bufferBits, bufferSize)) {
369 RETURN_ERROR(Error3::NO_RESOURCES);
370 }
371
372 uint32_t hostHandle = 0;
373 QEMU_PIPE_HANDLE hostHandleRefCountFd = QEMU_PIPE_INVALID_HANDLE;
374 if (needHostCb(usage, format)) {
375 hostHandleRefCountFd = qemu_pipe_open("refcount");
376 if (!qemu_pipe_valid(hostHandleRefCountFd)) {
377 RETURN_ERROR(Error3::NO_RESOURCES);
378 }
379
380 const GLenum allocFormat =
381 (PixelFormat::RGBX_8888 == format) ? GL_RGB : glFormat;
382
383 hostHandle = rcEnc->rcCreateColorBufferDMA(
384 rcEnc,
385 width, height,
386 allocFormat, static_cast<int>(emulatorFrameworkFormat));
387
388 if (!hostHandle) {
389 qemu_pipe_close(hostHandleRefCountFd);
390 RETURN_ERROR(Error3::NO_RESOURCES);
391 }
392
393 if (qemu_pipe_write(hostHandleRefCountFd,
394 &hostHandle,
395 sizeof(hostHandle)) != sizeof(hostHandle)) {
396 rcEnc->rcCloseColorBuffer(rcEnc, hostHandle);
397 qemu_pipe_close(hostHandleRefCountFd);
398 RETURN_ERROR(Error3::NO_RESOURCES);
399 }
400 }
401
402 std::unique_ptr<cb_handle_30_t> handle =
403 std::make_unique<cb_handle_30_t>(
404 host_memory_allocator.release(),
405 hostHandleRefCountFd,
406 hostHandle,
407 usage,
408 width,
409 height,
410 static_cast<int>(format),
411 glFormat,
412 glType,
413 bufferSize,
414 bufferBits.guestPtr(),
415 bufferBits.size(),
416 bufferBits.offset(),
417 bytesPerPixel,
418 stride);
419
420 bufferBits.release();
421 *cb = handle.release();
422 RETURN(Error3::NONE);
423 }
424
freeCb(std::unique_ptr<cb_handle_30_t> cb)425 void freeCb(std::unique_ptr<cb_handle_30_t> cb) {
426 // no need to undo .hostMalloc: the kernel will take care of it once the
427 // last bufferFd (duped) is closed.
428
429 if (qemu_pipe_valid(cb->hostHandleRefCountFd)) {
430 qemu_pipe_close(cb->hostHandleRefCountFd);
431 }
432 GoldfishAddressSpaceBlock::memoryUnmap(cb->getBufferPtr(), cb->mmapedSize);
433 GoldfishAddressSpaceHostMemoryAllocator::closeHandle(cb->bufferFd);
434 }
435
getHostConnectionSession() const436 HostConnectionSession getHostConnectionSession() const {
437 return HostConnectionSession(m_hostConn.get());
438 }
439
440 std::unique_ptr<HostConnection> m_hostConn;
441 };
442
main(int,char **)443 int main(int, char**) {
444 using ::android::sp;
445
446 ::android::hardware::configureRpcThreadpool(4, true /* callerWillJoin */);
447
448 sp<IAllocator3> allocator(new GoldfishAllocator());
449 if (allocator->registerAsService() != ::android::NO_ERROR) {
450 ALOGE("failed to register graphics IAllocator@3.0 service");
451 return -EINVAL;
452 }
453
454 ALOGI("graphics IAllocator@3.0 service is initialized");
455 ::android::hardware::joinRpcThreadpool();
456
457 ALOGI("graphics IAllocator@3.0 service is terminating");
458 return 0;
459 }
460